@@ -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 */
739870static 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
813896static 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