2121#include <openssl/engine.h>
2222#include <openssl/evp.h>
2323#include <openssl/hmac.h>
24+ #include <openssl/kdf.h>
2425
2526#ifdef CONFIG_OPENSSL_3
2627#include <openssl/core_names.h>
@@ -474,7 +475,143 @@ int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac,
474475 memcpy (key , secret , key_len );
475476 return 0 ;
476477}
477- #endif /* !CONFIG_OPENSSL */
478+
479+ static int derive_nvme_keys (const char * hostnqn , const char * identity ,
480+ int hmac , unsigned char * configured ,
481+ unsigned char * psk , int key_len )
482+ {
483+ errno = EOPNOTSUPP ;
484+ return -1 ;
485+ }
486+ #else /* CONFIG_OPENSSL */
487+ static int derive_retained_key (const EVP_MD * md , const char * hostnqn ,
488+ unsigned char * generated ,
489+ unsigned char * retained ,
490+ size_t key_len )
491+ {
492+ EVP_PKEY_CTX * ctx ;
493+ int ret ;
494+
495+ ctx = EVP_PKEY_CTX_new_id (EVP_PKEY_HKDF , NULL );
496+ if (!ctx ) {
497+ errno = ENOMEM ;
498+ return -1 ;
499+ }
500+
501+ if (EVP_PKEY_derive_init (ctx ) <= 0 ) {
502+ ret = - ENOMEM ;
503+ goto out_free_ctx ;
504+ }
505+ ret = - ENOKEY ;
506+ if (EVP_PKEY_CTX_set_hkdf_md (ctx , md ) <= 0 )
507+ goto out_free_ctx ;
508+ if (EVP_PKEY_CTX_set1_hkdf_key (ctx , generated , key_len ) <= 0 )
509+ goto out_free_ctx ;
510+ if (EVP_PKEY_CTX_add1_hkdf_info (ctx ,
511+ (const unsigned char * )"tls13 " , 6 ) <= 0 )
512+ goto out_free_ctx ;
513+ if (EVP_PKEY_CTX_add1_hkdf_info (ctx ,
514+ (const unsigned char * )"HostNQN" , 7 ) <= 0 )
515+ goto out_free_ctx ;
516+ if (EVP_PKEY_CTX_add1_hkdf_info (ctx ,
517+ (const unsigned char * )hostnqn , strlen (hostnqn )) <= 0 )
518+ goto out_free_ctx ;
519+
520+ if (EVP_PKEY_derive (ctx , retained , & key_len ) > 0 )
521+ ret = key_len ;
522+
523+ out_free_ctx :
524+ if (ret < 0 ) {
525+ errno = - ret ;
526+ ret = -1 ;
527+ }
528+ EVP_PKEY_CTX_free (ctx );
529+ return ret ;
530+ }
531+
532+ static int derive_tls_key (const EVP_MD * md , const char * identity ,
533+ unsigned char * retained ,
534+ unsigned char * psk , size_t key_len )
535+ {
536+ EVP_PKEY_CTX * ctx ;
537+ int ret ;
538+
539+ ctx = EVP_PKEY_CTX_new_id (EVP_PKEY_HKDF , NULL );
540+ if (!ctx ) {
541+ errno = ENOMEM ;
542+ return -1 ;
543+ }
544+
545+ if (EVP_PKEY_derive_init (ctx ) <= 0 ) {
546+ ret = - ENOMEM ;
547+ goto out_free_ctx ;
548+ }
549+ ret = - ENOKEY ;
550+ if (EVP_PKEY_CTX_set_hkdf_md (ctx , md ) <= 0 )
551+ goto out_free_ctx ;
552+ if (EVP_PKEY_CTX_set1_hkdf_key (ctx , retained , key_len ) <= 0 )
553+ goto out_free_ctx ;
554+ if (EVP_PKEY_CTX_add1_hkdf_info (ctx ,
555+ (const unsigned char * )"tls13 " , 6 ) <= 0 )
556+ goto out_free_ctx ;
557+ if (EVP_PKEY_CTX_add1_hkdf_info (ctx ,
558+ (const unsigned char * )"nvme-tls-psk" , 12 ) <= 0 )
559+ goto out_free_ctx ;
560+ if (EVP_PKEY_CTX_add1_hkdf_info (ctx ,
561+ (const unsigned char * )identity ,
562+ strlen (identity )) <= 0 )
563+ goto out_free_ctx ;
564+
565+ if (EVP_PKEY_derive (ctx , psk , & key_len ) > 0 )
566+ ret = key_len ;
567+
568+ out_free_ctx :
569+ EVP_PKEY_CTX_free (ctx );
570+ if (ret < 0 ) {
571+ errno = - ret ;
572+ ret = -1 ;
573+ }
574+
575+ return ret ;
576+ }
577+
578+ static int derive_nvme_keys (const char * hostnqn , const char * identity ,
579+ int hmac , unsigned char * configured ,
580+ unsigned char * psk , int key_len )
581+ {
582+ const EVP_MD * md ;
583+ unsigned char * retained ;
584+ int ret = -1 ;
585+
586+ if (!hostnqn || !identity ) {
587+ errno = EINVAL ;
588+ return -1 ;
589+ }
590+
591+ switch (hmac ) {
592+ case 1 :
593+ md = EVP_sha256 ();
594+ break ;
595+ case 2 :
596+ md = EVP_sha384 ();
597+ break ;
598+ default :
599+ errno = EINVAL ;
600+ return -1 ;
601+ }
602+
603+ retained = malloc (key_len );
604+ if (!retained ) {
605+ errno = ENOMEM ;
606+ return -1 ;
607+ }
608+ ret = derive_retained_key (md , hostnqn , configured , retained , key_len );
609+ if (ret > 0 )
610+ ret = derive_tls_key (md , identity , retained , psk , key_len );
611+ free (retained );
612+ return ret ;
613+ }
614+ #endif /* CONFIG_OPENSSL */
478615
479616#ifdef CONFIG_OPENSSL_1
480617int nvme_gen_dhchap_key (char * hostnqn , enum nvme_hmac_alg hmac ,
@@ -653,6 +790,56 @@ long nvme_lookup_keyring(const char *keyring)
653790 return 0 ;
654791 return keyring_id ;
655792}
793+
794+ long nvme_insert_tls_key (const char * keyring , const char * key_type ,
795+ const char * hostnqn , const char * subsysnqn , int hmac ,
796+ unsigned char * configured_key , int key_len )
797+ {
798+ key_serial_t keyring_id , key = 0 ;
799+ char * identity ;
800+ unsigned char * psk ;
801+ int ret = -1 ;
802+
803+ keyring_id = nvme_lookup_keyring (keyring );
804+ if (keyring_id < 0 )
805+ return -1 ;
806+
807+ identity = malloc (strlen (hostnqn ) + strlen (subsysnqn ) + 12 );
808+ if (!identity ) {
809+ errno = ENOMEM ;
810+ return -1 ;
811+ }
812+
813+ sprintf (identity , "NVMe0R%02d %s %s" , hmac , hostnqn , subsysnqn );
814+
815+ psk = malloc (key_len );
816+ if (!psk ) {
817+ errno = ENOMEM ;
818+ goto out_free_identity ;
819+ }
820+ memset (psk , 0 , key_len );
821+ ret = derive_nvme_keys (hostnqn , identity , hmac ,
822+ configured_key , psk , key_len );
823+ if (ret != key_len )
824+ goto out_free_psk ;
825+
826+ key = keyctl_search (keyring_id , key_type , identity , 0 );
827+ if (key > 0 ) {
828+ if (keyctl_update (key , psk , key_len ) < 0 )
829+ key = 0 ;
830+ } else {
831+ key = add_key (key_type , identity ,
832+ psk , key_len , keyring_id );
833+ if (key < 0 )
834+ key = 0 ;
835+ }
836+ out_free_psk :
837+ free (psk );
838+ out_free_identity :
839+ free (identity );
840+ return key ;
841+ }
842+
656843#else
657844long nvme_lookup_keyring (const char * keyring )
658845{
@@ -661,4 +848,11 @@ long nvme_lookup_keyring(const char *keyring)
661848 errno = ENOTSUP ;
662849 return 0 ;
663850}
851+
852+ long nvme_insert_tls_key (const char * keyring , const char * key_type ,
853+ const char * hostnqn , const char * subsysnqn , int hmac ,
854+ unsigned char * configured_key , int key_len )
855+ {
856+ return derive_nvme_keys (NULL , NULL , 0 , NULL , NULL , 0 );
857+ }
664858#endif
0 commit comments