3939#include "tree.h"
4040#include "log.h"
4141#include "private.h"
42+ #include "base64.h"
4243
4344static int __nvme_open (const char * name )
4445{
@@ -554,11 +555,17 @@ static int derive_retained_key(int hmac, const char *hostnqn,
554555}
555556
556557static int gen_tls_identity (const char * hostnqn , const char * subsysnqn ,
557- int hmac , char * identity ,
558+ int version , int hmac , char * identity ,
558559 unsigned char * retained , size_t key_len )
559560{
561+ if (version != 0 ) {
562+ nvme_msg (NULL , LOG_ERR , "NVMe TLS 2.0 is not supported; "
563+ "recompile with OpenSSL support.\n" );
564+ errno = NOTSUP ;
565+ return -1 ;
566+ }
560567 sprintf (identity , "NVMe0R%02d %s %s" ,
561- version , hmac , hostnqn , subsysnqn );
568+ hmac , hostnqn , subsysnqn );
562569 return strlen (identity );
563570}
564571
@@ -780,12 +787,90 @@ int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac,
780787}
781788
782789static int gen_tls_identity (const char * hostnqn , const char * subsysnqn ,
783- int hmac , char * identity ,
790+ int version , int hmac , char * identity ,
784791 unsigned char * retained , size_t key_len )
785792{
786- sprintf (identity , "NVMe0R%02d %s %s" ,
787- hmac , hostnqn , subsysnqn );
788- return strlen (identity );
793+ static const char hmac_seed [] = "NVMe-over-Fabrics" ;
794+ size_t hmac_len ;
795+ const EVP_MD * md = select_hmac (hmac , & hmac_len );
796+ HMAC_CTX * hmac_ctx ;
797+ unsigned char * psk_ctx ;
798+ char * enc_ctx ;
799+ size_t len = -1 ;
800+
801+ if (version == 0 ) {
802+ sprintf (identity , "NVMe%01dR%02d %s %s" ,
803+ version , hmac , hostnqn , subsysnqn );
804+ return strlen (identity );
805+ }
806+ if (version > 1 ) {
807+ errno = EINVAL ;
808+ return -1 ;
809+ }
810+
811+ hmac_ctx = HMAC_CTX_new ();
812+ if (!hmac_ctx ) {
813+ errno = ENOMEM ;
814+ return -1 ;
815+ }
816+ if (!md ) {
817+ errno = EINVAL ;
818+ goto out_free_hmac ;
819+ }
820+
821+ psk_ctx = malloc (key_len );
822+ if (!psk_ctx ) {
823+ errno = ENOMEM ;
824+ goto out_free_hmac ;
825+ }
826+ if (!HMAC_Init_ex (hmac_ctx , retained , key_len , md , NULL )) {
827+ errno = ENOMEM ;
828+ goto out_free_psk ;
829+ }
830+ if (!HMAC_Update (hmac_ctx , (unsigned char * )hostnqn ,
831+ strlen (hostnqn ))) {
832+ errno = ENOKEY ;
833+ goto out_free_psk ;
834+ }
835+ if (!HMAC_Update (hmac_ctx , (unsigned char * )" " , 1 )) {
836+ errno = ENOKEY ;
837+ goto out_free_psk ;
838+ }
839+ if (!HMAC_Update (hmac_ctx , (unsigned char * )subsysnqn ,
840+ strlen (subsysnqn ))) {
841+ errno = ENOKEY ;
842+ goto out_free_psk ;
843+ }
844+ if (!HMAC_Update (hmac_ctx , (unsigned char * )" " , 1 )) {
845+ errno = ENOKEY ;
846+ goto out_free_psk ;
847+ }
848+ if (!HMAC_Update (hmac_ctx , (unsigned char * )hmac_seed ,
849+ strlen (hmac_seed ))) {
850+ errno = ENOKEY ;
851+ goto out_free_psk ;
852+ }
853+ if (!HMAC_Final (hmac_ctx , psk_ctx , (unsigned int * )& key_len )) {
854+ errno = ENOKEY ;
855+ goto out_free_psk ;
856+ }
857+ enc_ctx = malloc (key_len * 2 );
858+ memset (enc_ctx , 0 , key_len * 2 );
859+ len = base64_encode (psk_ctx , key_len , enc_ctx );
860+ if (len < 0 ) {
861+ errno = ENOKEY ;
862+ goto out_free_enc ;
863+ }
864+ sprintf (identity , "NVMe%01dR%02d %s %s %s" ,
865+ version , hmac , hostnqn , subsysnqn , enc_ctx );
866+ len = strlen (identity );
867+ out_free_enc :
868+ free (enc_ctx );
869+ out_free_psk :
870+ free (psk_ctx );
871+ out_free_hmac :
872+ HMAC_CTX_free (hmac_ctx );
873+ return len ;
789874}
790875#endif /* !CONFIG_OPENSSL_1 */
791876
@@ -883,18 +968,133 @@ int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac,
883968}
884969
885970static int gen_tls_identity (const char * hostnqn , const char * subsysnqn ,
886- int hmac , char * identity ,
971+ int version , int hmac , char * identity ,
887972 unsigned char * retained , size_t key_len )
888973{
889- sprintf (identity , "NVMe0R%02d %s %s" ,
890- version , hmac , hostnqn , subsysnqn );
891- return strlen (identity );
974+ static const char hmac_seed [] = "NVMe-over-Fabrics" ;
975+ size_t hmac_len ;
976+ OSSL_PARAM params [2 ], * p = params ;
977+ OSSL_LIB_CTX * lib_ctx ;
978+ EVP_MAC_CTX * mac_ctx = NULL ;
979+ EVP_MAC * mac = NULL ;
980+ char * progq = NULL ;
981+ char * digest = NULL ;
982+ unsigned char * psk_ctx ;
983+ char * enc_ctx ;
984+ size_t len = -1 ;
985+
986+ if (version == 0 ) {
987+ sprintf (identity , "NVMe%01dR%02d %s %s" ,
988+ version , hmac , hostnqn , subsysnqn );
989+ return strlen (identity );
990+ }
991+ if (version > 1 ) {
992+ errno = EINVAL ;
993+ return -1 ;
994+ }
995+
996+ lib_ctx = OSSL_LIB_CTX_new ();
997+ if (!lib_ctx ) {
998+ errno = ENOMEM ;
999+ return -1 ;
1000+ }
1001+ mac = EVP_MAC_fetch (lib_ctx , OSSL_MAC_NAME_HMAC , progq );
1002+ if (!mac ) {
1003+ errno = ENOMEM ;
1004+ goto out_free_ossl ;
1005+ }
1006+
1007+ mac_ctx = EVP_MAC_CTX_new (mac );
1008+ if (!mac_ctx ) {
1009+ errno = ENOMEM ;
1010+ goto out_free_mac ;
1011+ }
1012+ switch (hmac ) {
1013+ case NVME_HMAC_ALG_SHA2_256 :
1014+ digest = OSSL_DIGEST_NAME_SHA2_256 ;
1015+ break ;
1016+ case NVME_HMAC_ALG_SHA2_384 :
1017+ digest = OSSL_DIGEST_NAME_SHA2_384 ;
1018+ break ;
1019+ default :
1020+ errno = EINVAL ;
1021+ break ;
1022+ }
1023+ if (!digest )
1024+ goto out_free_ctx ;
1025+ * p ++ = OSSL_PARAM_construct_utf8_string (OSSL_MAC_PARAM_DIGEST ,
1026+ digest , 0 );
1027+ * p = OSSL_PARAM_construct_end ();
1028+
1029+ psk_ctx = malloc (key_len );
1030+ if (!psk_ctx ) {
1031+ errno = ENOMEM ;
1032+ goto out_free_ctx ;
1033+ }
1034+
1035+ if (!EVP_MAC_init (mac_ctx , retained , key_len , params )) {
1036+ errno = ENOKEY ;
1037+ goto out_free_psk ;
1038+ }
1039+ if (!EVP_MAC_update (mac_ctx , (unsigned char * )hostnqn ,
1040+ strlen (hostnqn ))) {
1041+ errno = ENOKEY ;
1042+ goto out_free_psk ;
1043+ }
1044+ if (!EVP_MAC_update (mac_ctx , (unsigned char * )" " , 1 )) {
1045+ errno = ENOKEY ;
1046+ goto out_free_psk ;
1047+ }
1048+ if (!EVP_MAC_update (mac_ctx , (unsigned char * )subsysnqn ,
1049+ strlen (subsysnqn ))) {
1050+ errno = ENOKEY ;
1051+ goto out_free_psk ;
1052+ }
1053+ if (!EVP_MAC_update (mac_ctx , (unsigned char * )" " , 1 )) {
1054+ errno = ENOKEY ;
1055+ goto out_free_psk ;
1056+ }
1057+ if (!EVP_MAC_update (mac_ctx , (unsigned char * )hmac_seed ,
1058+ strlen (hmac_seed ))) {
1059+ errno = ENOKEY ;
1060+ goto out_free_psk ;
1061+ }
1062+ if (!EVP_MAC_final (mac_ctx , psk_ctx , & hmac_len , key_len )) {
1063+ errno = ENOKEY ;
1064+ goto out_free_psk ;
1065+ }
1066+ if (hmac_len > key_len ) {
1067+ errno = EMSGSIZE ;
1068+ goto out_free_psk ;
1069+ }
1070+ enc_ctx = malloc (hmac_len * 2 );
1071+ memset (enc_ctx , 0 , hmac_len * 2 );
1072+ len = base64_encode (psk_ctx , hmac_len , enc_ctx );
1073+ if (len < 0 ) {
1074+ errno = ENOKEY ;
1075+ goto out_free_enc ;
1076+ }
1077+ sprintf (identity , "NVMe%01dR%02d %s %s %s" ,
1078+ version , hmac , hostnqn , subsysnqn , enc_ctx );
1079+ len = strlen (identity );
1080+ out_free_enc :
1081+ free (enc_ctx );
1082+ out_free_psk :
1083+ free (psk_ctx );
1084+ out_free_ctx :
1085+ EVP_MAC_CTX_free (mac_ctx );
1086+ out_free_mac :
1087+ EVP_MAC_free (mac );
1088+ out_free_ossl :
1089+ OSSL_LIB_CTX_free (lib_ctx );
1090+
1091+ return len ;
8921092}
8931093#endif /* !CONFIG_OPENSSL_3 */
8941094
8951095#ifdef CONFIG_KEYUTILS
8961096static int derive_nvme_keys (const char * hostnqn , const char * subsysnqn ,
897- char * identity ,
1097+ char * identity , int version ,
8981098 int hmac , unsigned char * configured ,
8991099 unsigned char * psk , int key_len )
9001100{
@@ -914,7 +1114,7 @@ static int derive_nvme_keys(const char *hostnqn, const char *subsysnqn,
9141114 ret = derive_retained_key (hmac , hostnqn , configured , retained , key_len );
9151115 if (ret < 0 )
9161116 goto out ;
917- ret = gen_tls_identity (hostnqn , subsysnqn , hmac ,
1117+ ret = gen_tls_identity (hostnqn , subsysnqn , version , hmac ,
9181118 identity , retained , key_len );
9191119 if (ret < 0 )
9201120 goto out ;
@@ -924,6 +1124,23 @@ static int derive_nvme_keys(const char *hostnqn, const char *subsysnqn,
9241124 return ret ;
9251125}
9261126
1127+ static size_t nvme_identity_len (int hmac , int version , const char * hostnqn ,
1128+ const char * subsysnqn )
1129+ {
1130+ size_t len ;
1131+
1132+ len = strlen (hostnqn ) + strlen (subsysnqn ) + 12 ;
1133+ if (version == 1 ) {
1134+ len += 66 ;
1135+ if (hmac == NVME_HMAC_ALG_SHA2_384 )
1136+ len += 32 ;
1137+ } else if (version > 1 ) {
1138+ errno = EINVAL ;
1139+ return -1 ;
1140+ }
1141+ return len ;
1142+ }
1143+
9271144long nvme_lookup_keyring (const char * keyring )
9281145{
9291146 key_serial_t keyring_id ;
@@ -963,9 +1180,10 @@ int nvme_set_keyring(long key_id)
9631180 return 0 ;
9641181}
9651182
966- long nvme_insert_tls_key (const char * keyring , const char * key_type ,
967- const char * hostnqn , const char * subsysnqn , int hmac ,
968- unsigned char * configured_key , int key_len )
1183+ long nvme_insert_tls_key_versioned (const char * keyring , const char * key_type ,
1184+ const char * hostnqn , const char * subsysnqn ,
1185+ int version , int hmac ,
1186+ unsigned char * configured_key , int key_len )
9691187{
9701188 key_serial_t keyring_id , key = 0 ;
9711189 char * identity ;
@@ -977,7 +1195,10 @@ long nvme_insert_tls_key(const char *keyring, const char *key_type,
9771195 if (keyring_id == 0 )
9781196 return -1 ;
9791197
980- identity_len = strlen (hostnqn ) + strlen (subsysnqn ) + 12 ;
1198+ identity_len = nvme_identity_len (hmac , version , hostnqn , subsysnqn );
1199+ if (identity_len < 0 )
1200+ return -1 ;
1201+
9811202 identity = malloc (identity_len );
9821203 if (!identity ) {
9831204 errno = ENOMEM ;
@@ -990,7 +1211,7 @@ long nvme_insert_tls_key(const char *keyring, const char *key_type,
9901211 goto out_free_identity ;
9911212 }
9921213 memset (psk , 0 , key_len );
993- ret = derive_nvme_keys (hostnqn , subsysnqn , identity , hmac ,
1214+ ret = derive_nvme_keys (hostnqn , subsysnqn , identity , version , hmac ,
9941215 configured_key , psk , key_len );
9951216 if (ret != key_len )
9961217 goto out_free_psk ;
@@ -1045,13 +1266,23 @@ int nvme_set_keyring(long key_id)
10451266 return -1 ;
10461267}
10471268
1048- long nvme_insert_tls_key (const char * keyring , const char * key_type ,
1049- const char * hostnqn , const char * subsysnqn , int hmac ,
1050- unsigned char * configured_key , int key_len )
1269+ long nvme_insert_tls_key_versioned (const char * keyring , const char * key_type ,
1270+ const char * hostnqn , const char * subsysnqn ,
1271+ int version , int hmac ,
1272+ unsigned char * configured_key , int key_len )
10511273{
10521274 nvme_msg (NULL , LOG_ERR , "key operations not supported; "
10531275 "recompile with keyutils support.\n" );
10541276 errno = ENOTSUP ;
10551277 return -1 ;
10561278}
10571279#endif
1280+
1281+ long nvme_insert_tls_key (const char * keyring , const char * key_type ,
1282+ const char * hostnqn , const char * subsysnqn , int hmac ,
1283+ unsigned char * configured_key , int key_len )
1284+ {
1285+ return nvme_insert_tls_key_versioned (keyring , key_type ,
1286+ hostnqn , subsysnqn , 0 , hmac ,
1287+ configured_key , key_len );
1288+ }
0 commit comments