]> www.infradead.org Git - users/sagi/libnvme.git/commitdiff
linux: add nvme_export_tls_key()
authorHannes Reinecke <hare@suse.de>
Wed, 21 Feb 2024 06:57:16 +0000 (07:57 +0100)
committerDaniel Wagner <wagi@monom.org>
Thu, 7 Mar 2024 13:49:46 +0000 (14:49 +0100)
Add a function to export a TLS key in the PSK interchange format
as defined in the NVMe TCP transport specification.

Signed-off-by: Hannes Reinecke <hare@suse.de>
src/libnvme.map
src/nvme/linux.c
src/nvme/linux.h

index 2576425ab5b2048577e8fd102b09e98495842ee2..2591bc648205fc5c460f6e43de45491e5b6f516a 100644 (file)
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 LIBNVME_1.9 {
        global:
+               nvme_export_tls_key;
                nvme_get_logging_level;
                nvme_read_key;
                nvme_submit_passthru;
index 6155cc2676a2a8725aae1e939af093eb3d16e73e..f69856c39287ea0380b2bf888eda12e952672d3d 100644 (file)
@@ -43,6 +43,7 @@
 #include "log.h"
 #include "private.h"
 #include "base64.h"
+#include "crc32.h"
 
 static int __nvme_open(const char *name)
 {
@@ -1351,3 +1352,42 @@ long nvme_insert_tls_key(const char *keyring, const char *key_type,
                                             hostnqn, subsysnqn, 0, hmac,
                                             configured_key, key_len);
 }
+
+char *nvme_export_tls_key(const unsigned char *key_data, int key_len)
+{
+       unsigned char raw_secret[52];
+       char *encoded_key;
+       unsigned int raw_len, encoded_len, len;
+       unsigned long crc = crc32(0L, NULL, 0);
+
+       if (key_len == 32) {
+               raw_len = 32;
+       } else if (key_len == 48) {
+               raw_len = 48;
+       } else {
+               errno = EINVAL;
+               return NULL;
+       }
+
+       memcpy(raw_secret, key_data, raw_len);
+       crc = crc32(crc, raw_secret, raw_len);
+       raw_secret[raw_len++] = crc & 0xff;
+       raw_secret[raw_len++] = (crc >> 8) & 0xff;
+       raw_secret[raw_len++] = (crc >> 16) & 0xff;
+       raw_secret[raw_len++] = (crc >> 24) & 0xff;
+
+       encoded_len = (raw_len * 2) + 20;
+       encoded_key = malloc(encoded_len);
+       if (!encoded_key) {
+               errno = ENOMEM;
+               return NULL;
+       }
+       memset(encoded_key, 0, encoded_len);
+       len = sprintf(encoded_key, "NVMeTLSkey-1:%02x:",
+                     key_len == 32 ? 1 : 2);
+       len += base64_encode(raw_secret, raw_len, encoded_key + len);
+       encoded_key[len++] = ':';
+       encoded_key[len++] = '\0';
+
+       return encoded_key;
+}
index 454ae0daac479751acd46b78d34321f78d5f13e1..1cb583e55d15512529999e524efe1cadad867838 100644 (file)
@@ -370,6 +370,20 @@ char *nvme_generate_tls_key_identity(const char *hostnqn, const char *subsysnqn,
                                     int version, int hmac,
                                     unsigned char *configured_key, int key_len);
 
+/**
+ * nvme_export_tls_key() - Export a TLS key
+ * @key_data:  Raw data of the key
+ * @key_len:   Length of @key_data
+ *
+ * Returns @key_data in the PSK Interchange format as defined in section
+ * 3.6.1.5 of the NVMe TCP Transport specification.
+ *
+ * Return: The string containing the TLS identity or NULL with errno set
+ * on error. It is the responsibility of the caller to free the returned
+ * string.
+ */
+char *nvme_export_tls_key(const unsigned char *key_data, int key_len);
+
 /**
  * nvme_submit_passthru - Low level ioctl wrapper for passthru commands
  * @fd:                File descriptor of the nvme device