From: Hannes Reinecke Date: Wed, 21 Feb 2024 06:57:16 +0000 (+0100) Subject: linux: add nvme_export_tls_key() X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=acf2e4485d615e88a7877f204d856c6c46869fb7;p=users%2Fsagi%2Flibnvme.git linux: add nvme_export_tls_key() 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 --- diff --git a/src/libnvme.map b/src/libnvme.map index 2576425a..2591bc64 100644 --- a/src/libnvme.map +++ b/src/libnvme.map @@ -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; diff --git a/src/nvme/linux.c b/src/nvme/linux.c index 6155cc26..f69856c3 100644 --- a/src/nvme/linux.c +++ b/src/nvme/linux.c @@ -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; +} diff --git a/src/nvme/linux.h b/src/nvme/linux.h index 454ae0da..1cb583e5 100644 --- a/src/nvme/linux.h +++ b/src/nvme/linux.h @@ -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