Skip to content

Commit 0b686f5

Browse files
committed
Merge branch 'derived_tls_fix'
2 parents e9dae79 + 29ebb78 commit 0b686f5

1 file changed

Lines changed: 154 additions & 71 deletions

File tree

src/nvme/linux.c

Lines changed: 154 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ static int derive_psk_digest(const char *hostnqn, const char *subsysnqn,
564564
return -1;
565565
}
566566

567-
static int derive_tls_key(int version, int cipher, const char *context,
567+
static int derive_tls_key(int version, int cipher, const char *digest, int digest_length_in_bytes,
568568
unsigned char *retained,
569569
unsigned char *psk, size_t key_len)
570570
{
@@ -714,6 +714,137 @@ static int derive_retained_key(int hmac, const char *hostnqn,
714714
return key_len;
715715
}
716716

717+
/*
718+
*
719+
* HKDF_Extract_Expand_Label(): This function performs the following operations
720+
* PRK=HKDF-Extract(0, Secret) followed by
721+
* HKDF-Expand-Label(PRK, Label, Ctx, HashLengh) to generate a new secret
722+
*
723+
* HKDF-Expand-Label: Reference: https://datatracker.ietf.org/doc/html/rfc8446#page-102
724+
* HKDF-Extract & HKDF-Expand : Reference: https://www.rfc-editor.org/rfc/rfc5869.txt
725+
*
726+
* HKDF-Expand-Label(Secret, Label, Context, Length) =
727+
* HKDF-Expand(Secret, HkdfLabel, Length)
728+
*
729+
* Where HkdfLabel is specified as:
730+
*
731+
* struct {
732+
* uint16 length = Length;
733+
* opaque label<7..255> = "tls13 " + Label;
734+
* opaque context<0..255> = Context;
735+
* } HkdfLabel;
736+
*
737+
* Derive-Secret(Secret, Label, Messages) =
738+
* HKDF-Expand-Label(Secret, Label,
739+
* Transcript-Hash(Messages), Hash.length)
740+
*
741+
*
742+
* [cipher] : HMAC algorithm type [256/384]
743+
* [Secret] : Input to HKDF-Extract(0, Secret)
744+
* [label] : Label to be added to base label ("tls13 ") to produce the HkdfLabel:'opaque label'
745+
* [label_length] : Length of the Label
746+
* [context] : Context to produce to produce the HkdfLabel:'opaque context'
747+
* [context_length] : Context length to produce to produce the HkdfLabel:'opaque context'
748+
* [new_seret] : Pointer to the NewSecret generated by HKDF-Expand-Label(...)
749+
* [derived_secret_length] : Length parameter for HKDF-Expand(Secret, HkdfLabel, Length)
750+
*
751+
*/
752+
int HKDF_Extract_Expand_Label(unsigned char cipher,
753+
const unsigned char *secret,
754+
const char *label, uint8_t label_length,
755+
const char *context, uint8_t context_length,
756+
unsigned char *derived_secret, uint8_t derived_secret_length)
757+
{
758+
_cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL;
759+
size_t key_len = derived_secret_length;
760+
761+
const EVP_MD *md;
762+
size_t hmac_len;
763+
764+
md = select_hmac(cipher, &hmac_len);
765+
if (!md || !hmac_len || ((uint16_t)hmac_len != derived_secret_length)) {
766+
767+
768+
errno = EINVAL;
769+
return -1;
770+
}
771+
772+
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
773+
if (!ctx) {
774+
errno = ENOMEM;
775+
return -1;
776+
}
777+
778+
if (EVP_PKEY_derive_init(ctx) <= 0) {
779+
errno = ENOMEM;
780+
return -1;
781+
}
782+
if (EVP_PKEY_CTX_set_hkdf_md(ctx, md) <= 0) {
783+
errno = ENOKEY;
784+
return -1;
785+
}
786+
if (EVP_PKEY_CTX_set1_hkdf_key(ctx, secret, key_len) <= 0) {
787+
errno = ENOKEY;
788+
return -1;
789+
}
790+
////////////////////////////////////////////////////////////////////////////////////////
791+
// HkdfLabel: Part 1/3
792+
// uint16 length = Length;
793+
// The 'Length' needs to be represented based on the network byte-order based on
794+
// the TLS specification
795+
////////////////////////////////////////////////////////////////////////////////////////
796+
uint16_t hkdf_expand_label_length = (((uint16_t)hmac_len & 0xFF) << 8) | ((uint16_t)hmac_len >> 8);
797+
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
798+
(const unsigned char *)&hkdf_expand_label_length, 2) <= 0) {
799+
errno = ENOKEY;
800+
return -1;
801+
}
802+
803+
////////////////////////////////////////////////////////////////////////////////////////
804+
// HkdfLabel: Part 2/3
805+
// opaque label<7..255> = "tls13 " + Label;
806+
////////////////////////////////////////////////////////////////////////////////////////
807+
const char *tls_13_label = "tls13 ";
808+
uint8_t f_label_length = strlen(tls_13_label) + label_length;
809+
// add label length: since label is opaque
810+
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,(const unsigned char *)&f_label_length, 1) <= 0) {
811+
errno = ENOKEY;
812+
return -1;
813+
}
814+
815+
if (EVP_PKEY_CTX_add1_hkdf_info(ctx, (const unsigned char *)"tls13 ", 6) <= 0) {
816+
errno = ENOKEY;
817+
return -1;
818+
}
819+
820+
if (EVP_PKEY_CTX_add1_hkdf_info(ctx, (const unsigned char *)label, label_length) <= 0) {
821+
errno = ENOKEY;
822+
return -1;
823+
}
824+
825+
////////////////////////////////////////////////////////////////////////////////////////
826+
// HkdfLabel: Part 3/3
827+
// opaque context<0..255> = Context
828+
////////////////////////////////////////////////////////////////////////////////////////
829+
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,(const unsigned char *)&context_length, 1) <= 0) {
830+
errno = ENOKEY;
831+
return -1;
832+
}
833+
834+
if (EVP_PKEY_CTX_add1_hkdf_info(ctx, (const unsigned char *)context, context_length)<= 0) {
835+
errno = ENOKEY;
836+
return -1;
837+
}
838+
839+
// Generate Key now
840+
if (EVP_PKEY_derive(ctx, derived_secret, &key_len) <= 0) {
841+
errno = ENOKEY;
842+
return -1;
843+
}
844+
845+
return key_len;
846+
}
847+
717848
/*
718849
* derive_tls_key()
719850
*
@@ -737,77 +868,29 @@ static int derive_retained_key(int hmac, const char *hostnqn,
737868
* and the value '0' is invalid here.
738869
*/
739870
static int derive_tls_key(int version, unsigned char cipher,
740-
const char *context, unsigned char *retained,
871+
const char *psk_digest, uint8_t psk_digest_buffer_length, unsigned char *retained,
741872
unsigned char *psk, size_t key_len)
742873
{
743-
_cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL;
744-
uint16_t length = key_len & 0xFFFF;
745-
const EVP_MD *md;
746-
size_t hmac_len;
747-
748-
md = select_hmac(cipher, &hmac_len);
749-
if (!md || !hmac_len) {
750-
errno = EINVAL;
751-
return -1;
752-
}
753-
754-
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
755-
if (!ctx) {
756-
errno = ENOMEM;
757-
return -1;
758-
}
759-
760-
if (EVP_PKEY_derive_init(ctx) <= 0) {
761-
errno = ENOMEM;
762-
return -1;
763-
}
764-
if (EVP_PKEY_CTX_set_hkdf_md(ctx, md) <= 0) {
765-
errno = ENOKEY;
766-
return -1;
767-
}
768-
if (EVP_PKEY_CTX_set1_hkdf_key(ctx, retained, key_len) <= 0) {
769-
errno = ENOKEY;
770-
return -1;
771-
}
772-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
773-
(const unsigned char *)&length, 2) <= 0) {
774-
errno = ENOKEY;
775-
return -1;
776-
}
777-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
778-
(const unsigned char *)"tls13 ", 6) <= 0) {
779-
errno = ENOKEY;
780-
return -1;
781-
}
782-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
783-
(const unsigned char *)"nvme-tls-psk", 12) <= 0) {
784-
errno = ENOKEY;
785-
return -1;
786-
}
787-
if (version == 1) {
788-
char hash_str[5];
789-
790-
sprintf(hash_str, "%02d ", cipher);
791-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
792-
(const unsigned char *)hash_str,
793-
strlen(hash_str)) <= 0) {
794-
errno = ENOKEY;
795-
return -1;
796-
}
797-
}
798-
if (EVP_PKEY_CTX_add1_hkdf_info(ctx,
799-
(const unsigned char *)context,
800-
strlen(context)) <= 0) {
801-
errno = ENOKEY;
802-
return -1;
803-
}
804-
805-
if (EVP_PKEY_derive(ctx, psk, &key_len) <= 0) {
806-
errno = ENOKEY;
807-
return -1;
808-
}
809-
810-
return key_len;
874+
// Reference: https://nvmexpress.org/wp-content/uploads/NVM-Express-TCP-Transport-Specification-Revision-1.1-2024.08.05-Ratified.pdf
875+
//
876+
// 1. PRK = HKDF-Extract(0, Input PSK); and
877+
// 2. TLS PSK = HKDF-Expand-Label(PRK, “nvme-tls-psk”, Context, L),
878+
//
879+
// Context = “<hash> <PSK digest>” :
880+
char context[64+3]; // Max hash size length (64) + 3
881+
uint8_t context_length = psk_digest_buffer_length;
882+
if (version == 1) {
883+
sprintf(&context[0], "%02d ", cipher);
884+
memcpy(&context[3], psk_digest, psk_digest_buffer_length);
885+
context_length += 3;
886+
}
887+
else
888+
{
889+
memcpy(&context[0], psk_digest, psk_digest_buffer_length);
890+
}
891+
892+
return HKDF_Extract_Expand_Label(cipher, &retained[0], "nvme-tls-psk", strlen("nvme-tls-psk"),
893+
context, context_length, psk, key_len);
811894
}
812895

813896
static DEFINE_CLEANUP_FUNC(
@@ -1073,7 +1156,7 @@ static int derive_nvme_keys(const char *hostnqn, const char *subsysnqn,
10731156
digest, identity);
10741157
if (ret < 0)
10751158
return ret;
1076-
return derive_tls_key(version, cipher, context, retained,
1159+
return derive_tls_key(version, cipher, context, strlen(context), retained,
10771160
psk, key_len);
10781161
}
10791162

0 commit comments

Comments
 (0)