Skip to content

Commit 718f5c9

Browse files
committed
linux: use EVP_PKEY_CTX_add1_hkdf_info only once in compat function
OpenSSL prior to 3.3.1 had an issue with EVP_PKEY_CTX_add1_hkdf_info() where it acted like a 'set1' function instead of an 'add1' as documented. Work around that by building the entire info vector outside of the OpenSSL API and only calling this function once. This is the same workaround used in commit eff0ffe ("linux: fix HKDF TLS key derivation back to OpenSSL 3.0.8"). Signed-off-by: Daniel Wagner <[email protected]>
1 parent acd30ba commit 718f5c9

1 file changed

Lines changed: 57 additions & 33 deletions

File tree

src/nvme/linux.c

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -814,9 +814,11 @@ static int derive_retained_key_compat(int hmac, const char *hostnqn,
814814
size_t key_len)
815815
{
816816
_cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL;
817-
uint16_t length = key_len & 0xFFFF;
817+
_cleanup_free_ uint8_t *hkdf_info = NULL;
818818
const EVP_MD *md;
819819
size_t hmac_len;
820+
char *pos;
821+
int ret;
820822

821823
if (hmac == NVME_HMAC_ALG_NONE) {
822824
memcpy(retained, configured, key_len);
@@ -847,23 +849,28 @@ static int derive_retained_key_compat(int hmac, const char *hostnqn,
847849
errno = ENOKEY;
848850
return -1;
849851
}
850-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
851-
(const unsigned char *)&length, 2) <= 0) {
852-
errno = ENOKEY;
853-
return -1;
854-
}
855-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
856-
(const unsigned char *)"tls13 ", 6) <= 0) {
857-
errno = ENOKEY;
852+
853+
/* +1 byte so that the snprintf terminating null can not overflow */
854+
hkdf_info = malloc(HKDF_INFO_MAX_LEN + 1);
855+
if (!hkdf_info) {
856+
errno = ENOMEM;
858857
return -1;
859858
}
860-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
861-
(const unsigned char *)"HostNQN", 7) <= 0) {
859+
860+
pos = (char *)hkdf_info;
861+
*(uint16_t *)pos = cpu_to_le16(key_len);
862+
pos += sizeof(uint16_t);
863+
864+
ret = snprintf(pos, HKDF_INFO_LABEL_MAX + 1,
865+
"tls13 HostNQN%s", hostnqn);
866+
if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX) {
862867
errno = ENOKEY;
863868
return -1;
864869
}
865-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
866-
(const unsigned char *)hostnqn, strlen(hostnqn)) <= 0) {
870+
pos += ret;
871+
872+
if (EVP_PKEY_CTX_add1_hkdf_info(ctx, hkdf_info,
873+
(pos - (char *)hkdf_info)) <= 0) {
867874
errno = ENOKEY;
868875
return -1;
869876
}
@@ -1002,9 +1009,11 @@ static int derive_tls_key_compat(int version, unsigned char cipher,
10021009
unsigned char *psk, size_t key_len)
10031010
{
10041011
_cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL;
1005-
uint16_t length = key_len & 0xFFFF;
1012+
_cleanup_free_ uint8_t *hkdf_info = NULL;
10061013
const EVP_MD *md;
10071014
size_t hmac_len;
1015+
char *pos;
1016+
int ret;
10081017

10091018
md = select_hmac(cipher, &hmac_len);
10101019
if (!md || !hmac_len) {
@@ -1030,35 +1039,50 @@ static int derive_tls_key_compat(int version, unsigned char cipher,
10301039
errno = ENOKEY;
10311040
return -1;
10321041
}
1033-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
1034-
(const unsigned char *)&length, 2) <= 0) {
1035-
errno = ENOKEY;
1036-
return -1;
1037-
}
1038-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
1039-
(const unsigned char *)"tls13 ", 6) <= 0) {
1040-
errno = ENOKEY;
1042+
1043+
/* +1 byte so that the snprintf terminating null can not overflow */
1044+
hkdf_info = malloc(HKDF_INFO_MAX_LEN + 1);
1045+
if (!hkdf_info) {
1046+
errno = ENOMEM;
10411047
return -1;
10421048
}
1043-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
1044-
(const unsigned char *)"nvme-tls-psk", 12) <= 0) {
1049+
1050+
pos = (char *)hkdf_info;
1051+
*(uint16_t *)pos = cpu_to_le16(key_len);
1052+
pos += sizeof(uint16_t);
1053+
1054+
ret = snprintf(pos, HKDF_INFO_LABEL_MAX + 1, "tls13 nvme-tls-psk");
1055+
if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX) {
10451056
errno = ENOKEY;
10461057
return -1;
10471058
}
1048-
if (version == 1) {
1049-
char hash_str[5];
1059+
pos += ret;
10501060

1051-
sprintf(hash_str, "%02d ", cipher);
1052-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
1053-
(const unsigned char *)hash_str,
1054-
strlen(hash_str)) <= 0) {
1061+
switch (version) {
1062+
case 0:
1063+
ret = snprintf(pos, HKDF_INFO_CONTEXT_MAX + 1, "%s", context);
1064+
if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX) {
10551065
errno = ENOKEY;
10561066
return -1;
10571067
}
1068+
pos += ret;
1069+
break;
1070+
case 1:
1071+
ret = snprintf(pos, HKDF_INFO_CONTEXT_MAX + 1, "%02d %s",
1072+
cipher, context);
1073+
if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX) {
1074+
errno = ENOKEY;
1075+
return -1;
1076+
}
1077+
pos += ret;
1078+
break;
1079+
default:
1080+
errno = ENOKEY;
1081+
return -1;
10581082
}
1059-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
1060-
(const unsigned char *)context,
1061-
strlen(context)) <= 0) {
1083+
1084+
if (EVP_PKEY_CTX_add1_hkdf_info(ctx, hkdf_info,
1085+
(pos - (char *)hkdf_info)) <= 0) {
10621086
errno = ENOKEY;
10631087
return -1;
10641088
}

0 commit comments

Comments
 (0)