@@ -686,45 +686,10 @@ static DEFINE_CLEANUP_FUNC(
686
686
cleanup_evp_pkey_ctx , EVP_PKEY_CTX * , EVP_PKEY_CTX_free )
687
687
#define _cleanup_evp_pkey_ctx_ __cleanup__(cleanup_evp_pkey_ctx)
688
688
689
- /*
690
- * hkdf_info_printf()
691
- *
692
- * Helper function to append variable length label and context to an HkdfLabel
693
- *
694
- * RFC 8446 (TLS 1.3) Section 7.1 defines the HKDF-Expand-Label function as a
695
- * specialization of the HKDF-Expand function (RFC 5869), where the info
696
- * parameter is structured as an HkdfLabel.
697
- *
698
- * An HkdfLabel structure includes two variable length vectors (label and
699
- * context) which must be preceded by their content length as per RFC 8446
700
- * Section 3.4 (and not NUL terminated as per Section 7.1). Additionally,
701
- * HkdfLabel.label must begin with "tls13 "
702
- *
703
- * Returns the number of bytes appended to the HKDF info buffer, or -1 on an
704
- * error.
705
- */
706
- __attribute__((format (printf , 2 , 3 )))
707
- static int hkdf_info_printf (EVP_PKEY_CTX * ctx , char * fmt , ...)
708
- {
709
- _cleanup_free_ char * str ;
710
- uint8_t len ;
711
- int ret ;
712
- va_list myargs ;
713
-
714
- va_start (myargs , fmt );
715
- ret = vasprintf (& str , fmt , myargs );
716
- va_end (myargs );
717
- if (ret < 0 )
718
- return ret ;
719
- if (ret > 255 )
720
- return -1 ;
721
- 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 );
727
- }
689
+ /* NVMe is using the TLS 1.3 HkdfLabel structure */
690
+ #define HKDF_INFO_MAX_LEN 514
691
+ #define HKDF_INFO_LABEL_MAX 256
692
+ #define HKDF_INFO_CONTEXT_MAX 256
728
693
729
694
/*
730
695
* derive_retained_key()
@@ -760,9 +725,19 @@ static int derive_retained_key(int hmac, const char *hostnqn,
760
725
size_t key_len )
761
726
{
762
727
_cleanup_evp_pkey_ctx_ EVP_PKEY_CTX * ctx = NULL ;
763
- uint16_t length = htons (key_len & 0xFFFF );
728
+ _cleanup_free_ uint8_t * hkdf_info = NULL ;
729
+ char * hkdf_label ;
764
730
const EVP_MD * md ;
765
731
size_t hmac_len ;
732
+ char * pos ;
733
+ int ret ;
734
+
735
+ /* +1 byte so that the snprintf terminating null can not overflow */
736
+ hkdf_info = malloc (HKDF_INFO_MAX_LEN + 1 );
737
+ if (!hkdf_info ) {
738
+ errno = ENOMEM ;
739
+ return -1 ;
740
+ }
766
741
767
742
if (hmac == NVME_HMAC_ALG_NONE ) {
768
743
memcpy (retained , configured , key_len );
@@ -793,16 +768,34 @@ static int derive_retained_key(int hmac, const char *hostnqn,
793
768
errno = ENOKEY ;
794
769
return -1 ;
795
770
}
796
- if (EVP_PKEY_CTX_add1_hkdf_info (ctx ,
797
- (const unsigned char * )& length , 2 ) <= 0 ) {
771
+
772
+ if (key_len > USHRT_MAX ) {
773
+ errno = EINVAL ;
774
+ return -1 ;
775
+ }
776
+ pos = (char * )hkdf_info ;
777
+ * (uint16_t * )pos = htons (key_len & 0xFFFF );
778
+ pos += sizeof (uint16_t );
779
+
780
+ hkdf_label = "tls13 HostNQN" ;
781
+ ret = snprintf (pos , HKDF_INFO_LABEL_MAX + 1 , "%c%s" ,
782
+ (int )strlen (hkdf_label ), hkdf_label );
783
+ if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX ) {
798
784
errno = ENOKEY ;
799
785
return -1 ;
800
786
}
801
- if (hkdf_info_printf (ctx , "tls13 HostNQN" ) <= 0 ) {
787
+ pos += ret ;
788
+
789
+ ret = snprintf (pos , HKDF_INFO_CONTEXT_MAX + 1 , "%c%s" ,
790
+ (int )strlen (hostnqn ), hostnqn );
791
+ if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX ) {
802
792
errno = ENOKEY ;
803
793
return -1 ;
804
794
}
805
- if (hkdf_info_printf (ctx , "%s" , hostnqn ) <= 0 ) {
795
+ pos += ret ;
796
+
797
+ if (EVP_PKEY_CTX_add1_hkdf_info (ctx , hkdf_info ,
798
+ (pos - (char * )hkdf_info )) <= 0 ) {
806
799
errno = ENOKEY ;
807
800
return -1 ;
808
801
}
@@ -911,9 +904,19 @@ static int derive_tls_key(int version, unsigned char cipher,
911
904
unsigned char * psk , size_t key_len )
912
905
{
913
906
_cleanup_evp_pkey_ctx_ EVP_PKEY_CTX * ctx = NULL ;
914
- uint16_t length = htons (key_len & 0xFFFF );
907
+ _cleanup_free_ uint8_t * hkdf_info = NULL ;
908
+ char * hkdf_label ;
915
909
const EVP_MD * md ;
916
910
size_t hmac_len ;
911
+ char * pos ;
912
+ int ret ;
913
+
914
+ /* +1 byte so that the snprintf terminating null can not overflow */
915
+ hkdf_info = malloc (HKDF_INFO_MAX_LEN + 1 );
916
+ if (!hkdf_info ) {
917
+ errno = ENOMEM ;
918
+ return -1 ;
919
+ }
917
920
918
921
md = select_hmac (cipher , & hmac_len );
919
922
if (!md || !hmac_len ) {
@@ -939,33 +942,53 @@ static int derive_tls_key(int version, unsigned char cipher,
939
942
errno = ENOKEY ;
940
943
return -1 ;
941
944
}
942
- if ( EVP_PKEY_CTX_add1_hkdf_info ( ctx ,
943
- ( const unsigned char * ) & length , 2 ) <= 0 ) {
944
- errno = ENOKEY ;
945
+
946
+ if ( key_len > USHRT_MAX ) {
947
+ errno = EINVAL ;
945
948
return -1 ;
946
949
}
947
- if (hkdf_info_printf (ctx , "tls13 nvme-tls-psk" ) <= 0 ) {
950
+ pos = (char * )hkdf_info ;
951
+ * (uint16_t * )pos = htons (key_len & 0xFFFF );
952
+ pos += sizeof (uint16_t );
953
+
954
+ hkdf_label = "tls13 nvme-tls-psk" ;
955
+ ret = snprintf (pos , HKDF_INFO_LABEL_MAX + 1 , "%c%s" ,
956
+ (int )strlen (hkdf_label ), hkdf_label );
957
+ if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX ) {
948
958
errno = ENOKEY ;
949
959
return -1 ;
950
960
}
961
+ pos += ret ;
962
+
951
963
switch (version ) {
952
964
case 0 :
953
- if (hkdf_info_printf (ctx , "%s" , context ) <= 0 ) {
965
+ ret = snprintf (pos , HKDF_INFO_CONTEXT_MAX + 1 , "%c%s" ,
966
+ (int )strlen (context ), context );
967
+ if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX ) {
954
968
errno = ENOKEY ;
955
969
return -1 ;
956
970
}
971
+ pos += ret ;
957
972
break ;
958
973
case 1 :
959
- if (hkdf_info_printf (ctx , "%02d %s" , cipher , context ) <= 0 ) {
974
+ ret = snprintf (pos , HKDF_INFO_CONTEXT_MAX + 1 , "%c%02d %s" ,
975
+ (int )strlen (context ) + 3 , cipher , context );
976
+ if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX ) {
960
977
errno = ENOKEY ;
961
978
return -1 ;
962
979
}
980
+ pos += ret ;
963
981
break ;
964
982
default :
965
983
errno = ENOKEY ;
966
984
return -1 ;
967
985
}
968
986
987
+ if (EVP_PKEY_CTX_add1_hkdf_info (ctx , hkdf_info ,
988
+ (pos - (char * )hkdf_info )) <= 0 ) {
989
+ errno = ENOKEY ;
990
+ return -1 ;
991
+ }
969
992
if (EVP_PKEY_derive (ctx , psk , & key_len ) <= 0 ) {
970
993
errno = ENOKEY ;
971
994
return -1 ;
0 commit comments