Skip to content

Commit 6787e18

Browse files
committed
linux: create raw secret from pin secret
Allow the secret input to be a just a pin. This is for testing purposes not recommended use in production systems. Signed-off-by: Daniel Wagner <[email protected]>
1 parent f9eb4ce commit 6787e18

1 file changed

Lines changed: 81 additions & 23 deletions

File tree

libnvme/src/nvme/linux.c

Lines changed: 81 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -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 */
216224
static 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

753801
static 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

Comments
 (0)