All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chris Leech <cleech@redhat.com>
To: linux-nvme@lists.infradead.org
Cc: Hannes Reinecke <hare@suse.de>, Daniel Wagner <dwagner@suse.de>,
	Prashanth Nayak <prashanth.nayak@netapp.com>,
	John Meneghini <jmeneghi@redhat.com>
Subject: [PATCH 1/1] libnvme: TLS PSK derivation fixes
Date: Sun, 20 Jul 2025 19:17:18 -0700	[thread overview]
Message-ID: <20250721021718.1159879-2-cleech@redhat.com> (raw)
In-Reply-To: <20250721021718.1159879-1-cleech@redhat.com>

There are issues with the Retained and TLS PSK derivations due to the
implementation not adhering to the RFC 8446 definition of the
HKDF-Expand-Label function.

  1) The 16-bit HkdfLabel.length value must be converted to network byte
     order.

  2) The variable length HkdfLabel.label and HkdfLabel.context vectors
     must be prefixed with a length byte.

Signed-off-by: Chris Leech <cleech@redhat.com>
---
 src/nvme/linux.c | 86 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 57 insertions(+), 29 deletions(-)

diff --git a/src/nvme/linux.c b/src/nvme/linux.c
index ae4aa526..674b20b5 100644
--- a/src/nvme/linux.c
+++ b/src/nvme/linux.c
@@ -618,6 +618,46 @@ static DEFINE_CLEANUP_FUNC(
 	cleanup_evp_pkey_ctx, EVP_PKEY_CTX *, EVP_PKEY_CTX_free)
 #define _cleanup_evp_pkey_ctx_ __cleanup__(cleanup_evp_pkey_ctx)
 
+/*
+ * hkdf_info_printf()
+ *
+ * Helper function to append variable length label and context to an HkdfLabel
+ *
+ * RFC 8446 (TLS 1.3) Section 7.1 defines the HKDF-Expand-Label function as a
+ * specialization of the HKDF-Expand function (RFC 5869), where the info
+ * parameter is structured as an HkdfLabel.
+ *
+ * An HkdfLabel structure includes two variable length vectors (label and
+ * context) which must be preceded by their content length as per RFC 8446
+ * Section 3.4 (and not NUL terminated as per Section 7.1). Additionally,
+ * HkdfLabel.label must begin with "tls13 "
+ *
+ * Returns the number of bytes appended to the HKDF info buffer, or -1 on an
+ * error.
+ */
+__attribute__((format(printf, 2, 3)))
+static int hkdf_info_printf(EVP_PKEY_CTX *ctx, char *fmt, ...)
+{
+	_cleanup_free_ char *str;
+	uint8_t len;
+	int ret;
+
+	va_list myargs;
+	va_start(myargs, fmt);
+	ret = vasprintf(&str, fmt, myargs);
+	va_end(myargs);
+	if (ret < 0)
+		return ret;
+	if (ret > 255)
+		return -1;
+	len = ret;
+	if (EVP_PKEY_CTX_add1_hkdf_info(ctx, (unsigned char *)&len, 1) <= 0)
+		return -1;
+	if (EVP_PKEY_CTX_add1_hkdf_info(ctx, (unsigned char *)str, len) <= 0)
+		return -1;
+	return (ret + 1);
+}
+
 /*
  * derive_retained_key()
  *
@@ -652,7 +692,7 @@ static int derive_retained_key(int hmac, const char *hostnqn,
 			       size_t key_len)
 {
 	_cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL;
-	uint16_t length = key_len & 0xFFFF;
+	uint16_t length = htons(key_len & 0xFFFF);
 	const EVP_MD *md;
 	size_t hmac_len;
 
@@ -690,18 +730,11 @@ static int derive_retained_key(int hmac, const char *hostnqn,
 		errno = ENOKEY;
 		return -1;
 	}
-	if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
-			(const unsigned char *)"tls13 ", 6) <= 0) {
-		errno = ENOKEY;
-		return -1;
-	}
-	if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
-			(const unsigned char *)"HostNQN", 7) <= 0) {
+	if (hkdf_info_printf(ctx, "tls13 HostNQN") <= 0) {
 		errno = ENOKEY;
 		return -1;
 	}
-	if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
-			(const unsigned char *)hostnqn, strlen(hostnqn)) <= 0) {
+	if (hkdf_info_printf(ctx, "%s", hostnqn) <= 0) {
 		errno = ENOKEY;
 		return -1;
 	}
@@ -736,12 +769,13 @@ static int derive_retained_key(int hmac, const char *hostnqn,
  *
  * and the value '0' is invalid here.
  */
+
 static int derive_tls_key(int version, unsigned char cipher,
 			  const char *context, unsigned char *retained,
 			  unsigned char *psk, size_t key_len)
 {
 	_cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL;
-	uint16_t length = key_len & 0xFFFF;
+	uint16_t length = htons(key_len & 0xFFFF);
 	const EVP_MD *md;
 	size_t hmac_len;
 
@@ -774,30 +808,24 @@ static int derive_tls_key(int version, unsigned char cipher,
 		errno = ENOKEY;
 		return -1;
 	}
-	if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
-			(const unsigned char *)"tls13 ", 6) <= 0) {
-		errno = ENOKEY;
-		return -1;
-	}
-	if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
-			(const unsigned char *)"nvme-tls-psk", 12) <= 0) {
+	if (hkdf_info_printf(ctx, "tls13 nvme-tls-psk") <= 0) {
 		errno = ENOKEY;
 		return -1;
 	}
-	if (version == 1) {
-		char hash_str[5];
-
-		sprintf(hash_str, "%02d ", cipher);
-		if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
-				(const unsigned char *)hash_str,
-				strlen(hash_str)) <= 0) {
+	switch (version) {
+	case 0:
+		if (hkdf_info_printf(ctx, "%s", context) <= 0) {
 			errno = ENOKEY;
 			return -1;
 		}
-	}
-	if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
-			(const unsigned char *)context,
-			strlen(context)) <= 0) {
+		break;
+	case 1:
+		if (hkdf_info_printf(ctx, "%02d %s", cipher, context) <= 0) {
+			errno = ENOKEY;
+			return -1;
+		}
+		break;
+	default:
 		errno = ENOKEY;
 		return -1;
 	}
-- 
2.50.1



  reply	other threads:[~2025-07-21  2:19 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-21  2:17 [PATCH 0/1] NVMe/TLS connection issues to SPDK Chris Leech
2025-07-21  2:17 ` Chris Leech [this message]
2025-07-21  6:36   ` [PATCH 1/1] libnvme: TLS PSK derivation fixes Hannes Reinecke
2025-07-21 15:31     ` Chris Leech
2025-07-25  9:36       ` Hannes Reinecke
2025-07-25 18:08         ` Chris Leech
2025-07-28  7:12           ` Hannes Reinecke
2025-08-08 16:18             ` John Meneghini
2025-08-12  4:33             ` Chris Leech
2025-08-18  9:42               ` Hannes Reinecke
2025-08-20  8:10               ` Daniel Wagner
2025-08-20  8:22                 ` Hannes Reinecke
2025-08-26 14:09                   ` John Meneghini
2025-07-21  7:11 ` [PATCH 0/1] NVMe/TLS connection issues to SPDK Hannes Reinecke
2025-07-21 15:44   ` Chris Leech
2025-07-22  6:27     ` Hannes Reinecke
2025-07-24 14:35       ` Daniel Wagner
2025-07-24 15:07         ` Chris Leech
2025-07-24 15:37           ` Daniel Wagner
2025-08-12 22:05 ` Chris Leech
2025-08-12 22:11 ` [RFC PATCH 1/2] crypto: hkdf: add hkdf_expand_label() Chris Leech
2025-08-18  9:44   ` Hannes Reinecke

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250721021718.1159879-2-cleech@redhat.com \
    --to=cleech@redhat.com \
    --cc=dwagner@suse.de \
    --cc=hare@suse.de \
    --cc=jmeneghi@redhat.com \
    --cc=linux-nvme@lists.infradead.org \
    --cc=prashanth.nayak@netapp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.