@@ -212,6 +212,14 @@ static int derive_tls_key_compat(struct nvme_global_ctx *ctx,
212212 "recompile with OpenSSL support.\n" );
213213 return - ENOTSUP ;
214214}
215+
216+ static ssize_t getswordfish (struct nvme_global_ctx * ctx ,
217+ const char * seed , void * buf , size_t buflen )
218+ {
219+ nvme_msg (ctx , LOG_ERR , "NVMe TLS is not supported; "
220+ "recompile with OpenSSL support.\n" );
221+ return - ENOTSUP ;
222+ }
215223#else /* CONFIG_OPENSSL */
216224static unsigned char default_hmac (size_t key_len )
217225{
@@ -748,6 +756,46 @@ static int derive_psk_digest(struct nvme_global_ctx *ctx,
748756
749757 return strlen (digest );
750758}
759+
760+ static ssize_t getswordfish (struct nvme_global_ctx * ctx ,
761+ const char * seed , void * buf , size_t buflen )
762+ {
763+ unsigned char hash [EVP_MAX_MD_SIZE ];
764+ unsigned int hash_len ;
765+ size_t copied = 0 ;
766+ unsigned int counter = 0 ;
767+
768+ EVP_MD_CTX * md_ctx = EVP_MD_CTX_new ();
769+ if (!md_ctx )
770+ return - ENOMEM ;
771+
772+ while (copied < buflen ) {
773+ if (EVP_DigestInit_ex (md_ctx , EVP_sha256 (), NULL ) != 1 )
774+ goto err ;
775+
776+ EVP_DigestUpdate (md_ctx , seed , strlen (seed ));
777+ EVP_DigestUpdate (md_ctx , & counter , sizeof (counter ));
778+
779+ if (EVP_DigestFinal_ex (md_ctx , hash , & hash_len ) != 1 )
780+ goto err ;
781+
782+ size_t to_copy = buflen - copied ;
783+ if (to_copy > hash_len )
784+ to_copy = hash_len ;
785+
786+ memcpy ((unsigned char * )buf + copied , hash , to_copy );
787+ copied += to_copy ;
788+ counter ++ ;
789+ }
790+
791+ EVP_MD_CTX_free (md_ctx );
792+ return buflen ;
793+
794+ err :
795+ EVP_MD_CTX_free (md_ctx );
796+ return - EIO ;
797+ }
798+
751799#endif /* !CONFIG_OPENSSL */
752800
753801static int gen_tls_identity (const char * hostnqn , const char * subsysnqn ,
@@ -1004,7 +1052,8 @@ __public int nvme_create_raw_secret(struct nvme_global_ctx *ctx,
10041052 const char * secret , size_t key_len , unsigned char * * raw_secret )
10051053{
10061054 _cleanup_free_ unsigned char * buf = NULL ;
1007- int err ;
1055+ int secret_len = 0 , i , err ;
1056+ unsigned int c ;
10081057
10091058 if (key_len != 32 && key_len != 48 && key_len != 64 ) {
10101059 nvme_msg (ctx , LOG_ERR , "Invalid key length %ld" , key_len );
@@ -1020,33 +1069,42 @@ __public int nvme_create_raw_secret(struct nvme_global_ctx *ctx,
10201069 if (err < 0 )
10211070 return err ;
10221071
1023- * raw_secret = buf ;
1024- buf = NULL ;
1025- return 0 ;
1026- } else {
1027- int secret_len = 0 , i ;
1028- unsigned int c ;
1029-
1030- for (i = 0 ; i < strlen (secret ); i += 2 ) {
1031- if (sscanf (& secret [i ], "%02x" , & c ) != 1 ) {
1032- nvme_msg (ctx , LOG_ERR ,
1033- "Invalid secret '%s'" , secret );
1034- return - EINVAL ;
1035- }
1036- if (i >= key_len * 2 ) {
1037- nvme_msg (ctx , LOG_ERR ,
1038- "Skipping excess secret bytes\n" );
1039- break ;
1040- }
1041- buf [secret_len ++ ] = (unsigned char )c ;
1042- }
1043- if (secret_len != key_len ) {
1072+ goto out ;
1073+ }
1074+
1075+ if (strlen (secret ) < 4 ) {
1076+ nvme_msg (ctx , LOG_ERR , "Input secret too short\n" );
1077+ return - EINVAL ;
1078+ }
1079+
1080+ if (!strncmp (secret , "pin:" , 4 )) {
1081+ err = getswordfish (ctx , & secret [4 ], buf , key_len );
1082+ if (err < 0 )
1083+ return err ;
1084+
1085+ goto out ;
1086+ }
1087+
1088+ for (i = 0 ; i < strlen (secret ); i += 2 ) {
1089+ if (sscanf (& secret [i ], "%02x" , & c ) != 1 ) {
10441090 nvme_msg (ctx , LOG_ERR ,
1045- "Invalid key length (%d bytes) " , secret_len );
1091+ "Invalid secret '%s' " , secret );
10461092 return - EINVAL ;
10471093 }
1094+ if (i >= key_len * 2 ) {
1095+ nvme_msg (ctx , LOG_ERR ,
1096+ "Skipping excess secret bytes\n" );
1097+ break ;
1098+ }
1099+ buf [secret_len ++ ] = (unsigned char )c ;
1100+ }
1101+ if (secret_len != key_len ) {
1102+ nvme_msg (ctx , LOG_ERR ,
1103+ "Invalid key length (%d bytes)\n" , secret_len );
1104+ return - EINVAL ;
10481105 }
10491106
1107+ out :
10501108 * raw_secret = buf ;
10511109 buf = NULL ;
10521110 return 0 ;
0 commit comments