Skip to content

Commit c79d956

Browse files
cleechhreinecke
authored andcommitted
libnvme: TLS PSK derivation fixes
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 <[email protected]>
1 parent a3995d2 commit c79d956

1 file changed

Lines changed: 57 additions & 29 deletions

File tree

src/nvme/linux.c

Lines changed: 57 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,46 @@ static DEFINE_CLEANUP_FUNC(
665665
cleanup_evp_pkey_ctx, EVP_PKEY_CTX *, EVP_PKEY_CTX_free)
666666
#define _cleanup_evp_pkey_ctx_ __cleanup__(cleanup_evp_pkey_ctx)
667667

668+
/*
669+
* hkdf_info_printf()
670+
*
671+
* Helper function to append variable length label and context to an HkdfLabel
672+
*
673+
* RFC 8446 (TLS 1.3) Section 7.1 defines the HKDF-Expand-Label function as a
674+
* specialization of the HKDF-Expand function (RFC 5869), where the info
675+
* parameter is structured as an HkdfLabel.
676+
*
677+
* An HkdfLabel structure includes two variable length vectors (label and
678+
* context) which must be preceded by their content length as per RFC 8446
679+
* Section 3.4 (and not NUL terminated as per Section 7.1). Additionally,
680+
* HkdfLabel.label must begin with "tls13 "
681+
*
682+
* Returns the number of bytes appended to the HKDF info buffer, or -1 on an
683+
* error.
684+
*/
685+
__attribute__((format(printf, 2, 3)))
686+
static int hkdf_info_printf(EVP_PKEY_CTX *ctx, char *fmt, ...)
687+
{
688+
_cleanup_free_ char *str;
689+
uint8_t len;
690+
int ret;
691+
692+
va_list myargs;
693+
va_start(myargs, fmt);
694+
ret = vasprintf(&str, fmt, myargs);
695+
va_end(myargs);
696+
if (ret < 0)
697+
return ret;
698+
if (ret > 255)
699+
return -1;
700+
len = ret;
701+
if (EVP_PKEY_CTX_add1_hkdf_info(ctx, (unsigned char *)&len, 1) <= 0)
702+
return -1;
703+
if (EVP_PKEY_CTX_add1_hkdf_info(ctx, (unsigned char *)str, len) <= 0)
704+
return -1;
705+
return (ret + 1);
706+
}
707+
668708
/*
669709
* derive_retained_key()
670710
*
@@ -699,7 +739,7 @@ static int derive_retained_key(int hmac, const char *hostnqn,
699739
size_t key_len)
700740
{
701741
_cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL;
702-
uint16_t length = key_len & 0xFFFF;
742+
uint16_t length = htons(key_len & 0xFFFF);
703743
const EVP_MD *md;
704744
size_t hmac_len;
705745

@@ -737,18 +777,11 @@ static int derive_retained_key(int hmac, const char *hostnqn,
737777
errno = ENOKEY;
738778
return -1;
739779
}
740-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
741-
(const unsigned char *)"tls13 ", 6) <= 0) {
742-
errno = ENOKEY;
743-
return -1;
744-
}
745-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
746-
(const unsigned char *)"HostNQN", 7) <= 0) {
780+
if (hkdf_info_printf(ctx, "tls13 HostNQN") <= 0) {
747781
errno = ENOKEY;
748782
return -1;
749783
}
750-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
751-
(const unsigned char *)hostnqn, strlen(hostnqn)) <= 0) {
784+
if (hkdf_info_printf(ctx, "%s", hostnqn) <= 0) {
752785
errno = ENOKEY;
753786
return -1;
754787
}
@@ -783,12 +816,13 @@ static int derive_retained_key(int hmac, const char *hostnqn,
783816
*
784817
* and the value '0' is invalid here.
785818
*/
819+
786820
static int derive_tls_key(int version, unsigned char cipher,
787821
const char *context, unsigned char *retained,
788822
unsigned char *psk, size_t key_len)
789823
{
790824
_cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL;
791-
uint16_t length = key_len & 0xFFFF;
825+
uint16_t length = htons(key_len & 0xFFFF);
792826
const EVP_MD *md;
793827
size_t hmac_len;
794828

@@ -821,30 +855,24 @@ static int derive_tls_key(int version, unsigned char cipher,
821855
errno = ENOKEY;
822856
return -1;
823857
}
824-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
825-
(const unsigned char *)"tls13 ", 6) <= 0) {
826-
errno = ENOKEY;
827-
return -1;
828-
}
829-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
830-
(const unsigned char *)"nvme-tls-psk", 12) <= 0) {
858+
if (hkdf_info_printf(ctx, "tls13 nvme-tls-psk") <= 0) {
831859
errno = ENOKEY;
832860
return -1;
833861
}
834-
if (version == 1) {
835-
char hash_str[5];
836-
837-
sprintf(hash_str, "%02d ", cipher);
838-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
839-
(const unsigned char *)hash_str,
840-
strlen(hash_str)) <= 0) {
862+
switch (version) {
863+
case 0:
864+
if (hkdf_info_printf(ctx, "%s", context) <= 0) {
841865
errno = ENOKEY;
842866
return -1;
843867
}
844-
}
845-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
846-
(const unsigned char *)context,
847-
strlen(context)) <= 0) {
868+
break;
869+
case 1:
870+
if (hkdf_info_printf(ctx, "%02d %s", cipher, context) <= 0) {
871+
errno = ENOKEY;
872+
return -1;
873+
}
874+
break;
875+
default:
848876
errno = ENOKEY;
849877
return -1;
850878
}

0 commit comments

Comments
 (0)