@@ -1000,11 +1000,62 @@ static ssize_t getrandom_bytes(void *buf, size_t buflen)
10001000 return result ;
10011001}
10021002
1003+ #ifdef CONFIG_OPENSSL
1004+ static ssize_t getswordfish (struct nvme_global_ctx * ctx ,
1005+ const char * seed , void * buf , size_t buflen )
1006+ {
1007+ unsigned char hash [EVP_MAX_MD_SIZE ];
1008+ unsigned int hash_len ;
1009+ size_t copied = 0 ;
1010+ unsigned int counter = 0 ;
1011+
1012+ EVP_MD_CTX * md_ctx = EVP_MD_CTX_new ();
1013+ if (!md_ctx )
1014+ return - ENOMEM ;
1015+
1016+ while (copied < buflen ) {
1017+ if (EVP_DigestInit_ex (md_ctx , EVP_sha256 (), NULL ) != 1 )
1018+ goto err ;
1019+
1020+ EVP_DigestUpdate (md_ctx , seed , strlen (seed ));
1021+ EVP_DigestUpdate (md_ctx , & counter , sizeof (counter ));
1022+
1023+ if (EVP_DigestFinal_ex (md_ctx , hash , & hash_len ) != 1 )
1024+ goto err ;
1025+
1026+ size_t to_copy = buflen - copied ;
1027+ if (to_copy > hash_len )
1028+ to_copy = hash_len ;
1029+
1030+ memcpy ((unsigned char * )buf + copied , hash , to_copy );
1031+ copied += to_copy ;
1032+ counter ++ ;
1033+ }
1034+
1035+ EVP_MD_CTX_free (md_ctx );
1036+ return buflen ;
1037+
1038+ err :
1039+ EVP_MD_CTX_free (md_ctx );
1040+ return - EIO ;
1041+ }
1042+ #else /* !CONFIG_OPENSSL */
1043+ static ssize_t getswordfish (struct nvme_global_ctx * ctx ,
1044+ const char * seed , void * buf , size_t buflen )
1045+ {
1046+ nvme_msg (ctx , LOG_ERR , "NVMe TLS is not supported; "
1047+ "recompile with OpenSSL support.\n" );
1048+ return - ENOTSUP ;
1049+ }
1050+
1051+ #endif /* !CONFIG_OPENSSL */
1052+
10031053__public int nvme_create_raw_secret (struct nvme_global_ctx * ctx ,
10041054 const char * secret , size_t key_len , unsigned char * * raw_secret )
10051055{
10061056 _cleanup_free_ unsigned char * buf = NULL ;
1007- int err ;
1057+ int secret_len = 0 , i , err ;
1058+ unsigned int c ;
10081059
10091060 if (key_len != 32 && key_len != 48 && key_len != 64 ) {
10101061 nvme_msg (ctx , LOG_ERR , "Invalid key length %ld" , key_len );
@@ -1020,33 +1071,42 @@ __public int nvme_create_raw_secret(struct nvme_global_ctx *ctx,
10201071 if (err < 0 )
10211072 return err ;
10221073
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 ) {
1074+ goto out ;
1075+ }
1076+
1077+ if (strlen (secret ) < 4 ) {
1078+ nvme_msg (ctx , LOG_ERR , "Input secret too short\n" );
1079+ return - EINVAL ;
1080+ }
1081+
1082+ if (!strncmp (secret , "pin:" , 4 )) {
1083+ err = getswordfish (ctx , & secret [4 ], buf , key_len );
1084+ if (err < 0 )
1085+ return err ;
1086+
1087+ goto out ;
1088+ }
1089+
1090+ for (i = 0 ; i < strlen (secret ); i += 2 ) {
1091+ if (sscanf (& secret [i ], "%02x" , & c ) != 1 ) {
10441092 nvme_msg (ctx , LOG_ERR ,
1045- "Invalid key length (%d bytes) " , secret_len );
1093+ "Invalid secret '%s' " , secret );
10461094 return - EINVAL ;
10471095 }
1096+ if (i >= key_len * 2 ) {
1097+ nvme_msg (ctx , LOG_ERR ,
1098+ "Skipping excess secret bytes\n" );
1099+ break ;
1100+ }
1101+ buf [secret_len ++ ] = (unsigned char )c ;
1102+ }
1103+ if (secret_len != key_len ) {
1104+ nvme_msg (ctx , LOG_ERR ,
1105+ "Invalid key length (%d bytes)\n" , secret_len );
1106+ return - EINVAL ;
10481107 }
10491108
1109+ out :
10501110 * raw_secret = buf ;
10511111 buf = NULL ;
10521112 return 0 ;
0 commit comments