Skip to content

Commit ff4af0c

Browse files
committed
linux: fix HKDF TLS key derivation back to OpenSSL 3.0.8
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. Signed-off-by: Chris Leech <[email protected]>
1 parent 32560ea commit ff4af0c

1 file changed

Lines changed: 80 additions & 68 deletions

File tree

src/nvme/linux.c

Lines changed: 80 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -703,13 +703,13 @@ static DEFINE_CLEANUP_FUNC(
703703
* Returns the number of bytes appended to the HKDF info buffer, or -1 on an
704704
* error.
705705
*/
706-
__attribute__((format(printf, 2, 3)))
707-
static int hkdf_info_printf(EVP_PKEY_CTX *ctx, char *fmt, ...)
706+
__attribute__((format(printf, 3, 4)))
707+
static int hkdf_info_printf(uint8_t *info, size_t *pos, char *fmt, ...)
708708
{
709-
_cleanup_free_ char *str;
709+
_cleanup_free_ char *str = NULL;
710+
va_list myargs;
710711
uint8_t len;
711712
int ret;
712-
va_list myargs;
713713

714714
va_start(myargs, fmt);
715715
ret = vasprintf(&str, fmt, myargs);
@@ -719,11 +719,11 @@ static int hkdf_info_printf(EVP_PKEY_CTX *ctx, char *fmt, ...)
719719
if (ret > 255)
720720
return -1;
721721
len = ret;
722-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx, (unsigned char *)&len, 1) <= 0)
723-
return -1;
724-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx, (unsigned char *)str, len) <= 0)
725-
return -1;
726-
return (ret + 1);
722+
info[*pos] = len;
723+
*pos += 1;
724+
memcpy(&info[*pos], str, len);
725+
*pos += len;
726+
return (len + 1);
727727
}
728728

729729
/*
@@ -760,9 +760,17 @@ static int derive_retained_key(int hmac, const char *hostnqn,
760760
size_t key_len)
761761
{
762762
_cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL;
763+
_cleanup_free_ uint8_t *hkdf_info = NULL;
763764
uint16_t length = htons(key_len & 0xFFFF);
764765
const EVP_MD *md;
765766
size_t hmac_len;
767+
size_t pos;
768+
769+
hkdf_info = malloc(2 + 1 + strlen("tls13 HostNQN") + 256);
770+
if (!hkdf_info) {
771+
errno = ENOMEM;
772+
return -1;
773+
}
766774

767775
if (hmac == NVME_HMAC_ALG_NONE) {
768776
memcpy(retained, configured, key_len);
@@ -793,20 +801,20 @@ static int derive_retained_key(int hmac, const char *hostnqn,
793801
errno = ENOKEY;
794802
return -1;
795803
}
796-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
797-
(const unsigned char *)&length, 2) <= 0) {
804+
*(uint16_t *)&hkdf_info[0] = length;
805+
pos = sizeof(uint16_t);
806+
if (hkdf_info_printf(hkdf_info, &pos, "tls13 HostNQN") <= 0) {
798807
errno = ENOKEY;
799808
return -1;
800809
}
801-
if (hkdf_info_printf(ctx, "tls13 HostNQN") <= 0) {
810+
if (hkdf_info_printf(hkdf_info, &pos, "%s", hostnqn) <= 0) {
802811
errno = ENOKEY;
803812
return -1;
804813
}
805-
if (hkdf_info_printf(ctx, "%s", hostnqn) <= 0) {
814+
if(EVP_PKEY_CTX_add1_hkdf_info(ctx, hkdf_info, pos) <= 0) {
806815
errno = ENOKEY;
807816
return -1;
808817
}
809-
810818
if (EVP_PKEY_derive(ctx, retained, &key_len) <= 0) {
811819
errno = ENOKEY;
812820
return -1;
@@ -821,9 +829,17 @@ static int derive_retained_key_compat(int hmac, const char *hostnqn,
821829
size_t key_len)
822830
{
823831
_cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL;
832+
_cleanup_free_ uint8_t *hkdf_info = NULL;
824833
uint16_t length = key_len & 0xFFFF;
825834
const EVP_MD *md;
826835
size_t hmac_len;
836+
size_t pos;
837+
838+
hkdf_info = malloc(2 + strlen("tls13 HostNQN") + 255);
839+
if (!hkdf_info) {
840+
errno = ENOMEM;
841+
return -1;
842+
}
827843

828844
if (hmac == NVME_HMAC_ALG_NONE) {
829845
memcpy(retained, configured, key_len);
@@ -854,23 +870,17 @@ static int derive_retained_key_compat(int hmac, const char *hostnqn,
854870
errno = ENOKEY;
855871
return -1;
856872
}
857-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
858-
(const unsigned char *)&length, 2) <= 0) {
859-
errno = ENOKEY;
860-
return -1;
861-
}
862-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
863-
(const unsigned char *)"tls13 ", 6) <= 0) {
864-
errno = ENOKEY;
865-
return -1;
866-
}
867-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
868-
(const unsigned char *)"HostNQN", 7) <= 0) {
869-
errno = ENOKEY;
870-
return -1;
871-
}
872-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
873-
(const unsigned char *)hostnqn, strlen(hostnqn)) <= 0) {
873+
874+
*(uint16_t *)&hkdf_info[0] = length;
875+
pos = sizeof(uint16_t);
876+
memcpy(&hkdf_info[pos], "tls13 ", 6);
877+
pos += 6;
878+
memcpy(&hkdf_info[pos], "HostNQN", 7);
879+
pos += 7;
880+
memcpy(&hkdf_info[pos], hostnqn, strlen(hostnqn));
881+
pos += strlen(hostnqn);
882+
883+
if (EVP_PKEY_CTX_add1_hkdf_info(ctx, hkdf_info, pos) <= 0) {
874884
errno = ENOKEY;
875885
return -1;
876886
}
@@ -911,9 +921,17 @@ static int derive_tls_key(int version, unsigned char cipher,
911921
unsigned char *psk, size_t key_len)
912922
{
913923
_cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL;
924+
_cleanup_free_ uint8_t *hkdf_info = NULL;
914925
uint16_t length = htons(key_len & 0xFFFF);
915926
const EVP_MD *md;
916927
size_t hmac_len;
928+
size_t pos;
929+
930+
hkdf_info = malloc(2 + 1 + strlen("tls13 nvme-tls-psk") + 256);
931+
if (!hkdf_info) {
932+
errno = ENOMEM;
933+
return -1;
934+
}
917935

918936
md = select_hmac(cipher, &hmac_len);
919937
if (!md || !hmac_len) {
@@ -939,24 +957,21 @@ static int derive_tls_key(int version, unsigned char cipher,
939957
errno = ENOKEY;
940958
return -1;
941959
}
942-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
943-
(const unsigned char *)&length, 2) <= 0) {
944-
errno = ENOKEY;
945-
return -1;
946-
}
947-
if (hkdf_info_printf(ctx, "tls13 nvme-tls-psk") <= 0) {
960+
*(uint16_t *)&hkdf_info[0] = length;
961+
pos = sizeof(uint16_t);
962+
if (hkdf_info_printf(hkdf_info, &pos, "tls13 nvme-tls-psk") <= 0) {
948963
errno = ENOKEY;
949964
return -1;
950965
}
951966
switch (version) {
952967
case 0:
953-
if (hkdf_info_printf(ctx, "%s", context) <= 0) {
968+
if (hkdf_info_printf(hkdf_info, &pos, "%s", context) <= 0) {
954969
errno = ENOKEY;
955970
return -1;
956971
}
957972
break;
958973
case 1:
959-
if (hkdf_info_printf(ctx, "%02d %s", cipher, context) <= 0) {
974+
if (hkdf_info_printf(hkdf_info, &pos, "%02d %s", cipher, context) <= 0) {
960975
errno = ENOKEY;
961976
return -1;
962977
}
@@ -965,7 +980,10 @@ static int derive_tls_key(int version, unsigned char cipher,
965980
errno = ENOKEY;
966981
return -1;
967982
}
968-
983+
if(EVP_PKEY_CTX_add1_hkdf_info(ctx, hkdf_info, pos) <= 0) {
984+
errno = ENOKEY;
985+
return -1;
986+
}
969987
if (EVP_PKEY_derive(ctx, psk, &key_len) <= 0) {
970988
errno = ENOKEY;
971989
return -1;
@@ -979,9 +997,17 @@ static int derive_tls_key_compat(int version, unsigned char cipher,
979997
unsigned char *psk, size_t key_len)
980998
{
981999
_cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL;
1000+
_cleanup_free_ uint8_t *hkdf_info = NULL;
9821001
uint16_t length = key_len & 0xFFFF;
9831002
const EVP_MD *md;
9841003
size_t hmac_len;
1004+
size_t pos;
1005+
1006+
hkdf_info = malloc(2 + strlen("tls13 nvme-tls-psk") + 255);
1007+
if (!hkdf_info) {
1008+
errno = ENOMEM;
1009+
return -1;
1010+
}
9851011

9861012
md = select_hmac(cipher, &hmac_len);
9871013
if (!md || !hmac_len) {
@@ -1007,39 +1033,25 @@ static int derive_tls_key_compat(int version, unsigned char cipher,
10071033
errno = ENOKEY;
10081034
return -1;
10091035
}
1010-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
1011-
(const unsigned char *)&length, 2) <= 0) {
1012-
errno = ENOKEY;
1013-
return -1;
1014-
}
1015-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
1016-
(const unsigned char *)"tls13 ", 6) <= 0) {
1017-
errno = ENOKEY;
1018-
return -1;
1019-
}
1020-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
1021-
(const unsigned char *)"nvme-tls-psk", 12) <= 0) {
1022-
errno = ENOKEY;
1023-
return -1;
1024-
}
1025-
if (version == 1) {
1026-
char hash_str[5];
10271036

1028-
sprintf(hash_str, "%02d ", cipher);
1029-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
1030-
(const unsigned char *)hash_str,
1031-
strlen(hash_str)) <= 0) {
1032-
errno = ENOKEY;
1033-
return -1;
1034-
}
1037+
*(uint16_t *)&hkdf_info[0] = length;
1038+
pos = sizeof(uint16_t);
1039+
memcpy(&hkdf_info[pos], "tls13 ", 6);
1040+
pos += 6;
1041+
memcpy(&hkdf_info[pos], "nvme-tls-psk", 12);
1042+
pos += 12;
1043+
1044+
if (version == 1) {
1045+
sprintf((char *)&hkdf_info[pos], "%02d ", cipher);
1046+
pos += 3;
10351047
}
1036-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
1037-
(const unsigned char *)context,
1038-
strlen(context)) <= 0) {
1048+
memcpy(&hkdf_info[pos], context, strlen(context));
1049+
pos += strlen(context);
1050+
1051+
if(EVP_PKEY_CTX_add1_hkdf_info(ctx, hkdf_info, pos) <= 0) {
10391052
errno = ENOKEY;
10401053
return -1;
10411054
}
1042-
10431055
if (EVP_PKEY_derive(ctx, psk, &key_len) <= 0) {
10441056
errno = ENOKEY;
10451057
return -1;

0 commit comments

Comments
 (0)