Skip to content

Commit f9eb4ce

Browse files
committed
linux: add nvme_create_raw_secret
Move helper function to create the raw secret from the input string to the library. This allows to use a common function to consistently create the raw secret in nvme-cli and libnvme. Signed-off-by: Daniel Wagner <[email protected]>
1 parent 3f53169 commit f9eb4ce

4 files changed

Lines changed: 100 additions & 74 deletions

File tree

libnvme/src/libnvme.ld

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ LIBNVME_3 {
66
nvme_close;
77
nvme_create_ctrl;
88
nvme_create_global_ctx;
9+
nvme_create_raw_secret;
910
nvme_ctrl_first_ns;
1011
nvme_ctrl_first_path;
1112
nvme_ctrl_get_config;

libnvme/src/nvme/linux.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919

2020
#include <sys/ioctl.h>
2121
#include <sys/param.h>
22+
#if HAVE_SYS_RANDOM
23+
#include <sys/random.h>
24+
#endif
2225
#include <sys/stat.h>
2326

2427
#ifndef _GNU_SOURCE
@@ -979,6 +982,76 @@ __public int nvme_set_keyring(struct nvme_global_ctx *ctx, long key_id)
979982
return 0;
980983
}
981984

985+
static ssize_t getrandom_bytes(void *buf, size_t buflen)
986+
{
987+
ssize_t result;
988+
#if HAVE_SYS_RANDOM
989+
result = getrandom(buf, buflen, GRND_NONBLOCK);
990+
#else
991+
_cleanup_fd_ int fd = -1;
992+
993+
fd = open("/dev/urandom", O_RDONLY);
994+
if (fd < 0)
995+
return -errno;
996+
result = read(fd, buf, buflen);
997+
#endif
998+
if (result < 0)
999+
return -errno;
1000+
return result;
1001+
}
1002+
1003+
__public int nvme_create_raw_secret(struct nvme_global_ctx *ctx,
1004+
const char *secret, size_t key_len, unsigned char **raw_secret)
1005+
{
1006+
_cleanup_free_ unsigned char *buf = NULL;
1007+
int err;
1008+
1009+
if (key_len != 32 && key_len != 48 && key_len != 64) {
1010+
nvme_msg(ctx, LOG_ERR, "Invalid key length %ld", key_len);
1011+
return -EINVAL;
1012+
}
1013+
1014+
buf = malloc(key_len);
1015+
if (!buf)
1016+
return -ENOMEM;
1017+
1018+
if (!secret) {
1019+
err = getrandom_bytes(buf, key_len);
1020+
if (err < 0)
1021+
return err;
1022+
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) {
1044+
nvme_msg(ctx, LOG_ERR,
1045+
"Invalid key length (%d bytes)", secret_len);
1046+
return -EINVAL;
1047+
}
1048+
}
1049+
1050+
*raw_secret = buf;
1051+
buf = NULL;
1052+
return 0;
1053+
}
1054+
9821055
__public int nvme_read_key(struct nvme_global_ctx *ctx, long keyring_id,
9831056
long key_id, int *len, unsigned char **key)
9841057
{

libnvme/src/nvme/linux.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,24 @@ int nvme_lookup_key(struct nvme_global_ctx *ctx, const char *type,
103103
*/
104104
int nvme_set_keyring(struct nvme_global_ctx *ctx, long keyring_id);
105105

106+
/**
107+
* nvme_create_raw_secret - Generate a raw secret buffer from input data
108+
* @ctx: struct nvme_global_ctx object
109+
* @secret: Input secret data
110+
* @key_len: The length of the raw_secret in bytes
111+
* @raw_secret: Return buffer with the generated raw secret
112+
*
113+
* Transforms the provided @secret into a raw secret buffer suitable for
114+
* use with NVMe key management operations.
115+
*
116+
* The generated raw secret can subsequently be passed to nvme_read_key()
117+
* or nvme_update_key().
118+
*
119+
* Return: 0 on success, or a negative error code on failure.
120+
*/
121+
int nvme_create_raw_secret(struct nvme_global_ctx *ctx,
122+
const char *secret, size_t key_len, unsigned char **raw_secret);
123+
106124
/**
107125
* nvme_read_key() - Read key raw data
108126
* @ctx: struct nvme_global_ctx object

nvme.c

Lines changed: 8 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,6 @@
4646
#include <sys/stat.h>
4747
#include <sys/types.h>
4848

49-
#if HAVE_SYS_RANDOM
50-
#include <sys/random.h>
51-
#endif
5249

5350
#include <libnvme.h>
5451

@@ -311,24 +308,6 @@ static OPT_VALS(feature_name) = {
311308
VAL_END()
312309
};
313310

314-
static ssize_t getrandom_bytes(void *buf, size_t buflen)
315-
{
316-
ssize_t result;
317-
#if HAVE_SYS_RANDOM
318-
result = getrandom(buf, buflen, GRND_NONBLOCK);
319-
#else
320-
_cleanup_fd_ int fd = -1;
321-
322-
fd = open("/dev/urandom", O_RDONLY);
323-
if (fd < 0)
324-
return -errno;
325-
result = read(fd, buf, buflen);
326-
#endif
327-
if (result < 0)
328-
return -errno;
329-
return result;
330-
}
331-
332311
static int check_arg_dev(int argc, char **argv)
333312
{
334313
if (optind >= argc) {
@@ -9554,7 +9533,6 @@ static int show_hostnqn_cmd(int argc, char **argv, struct command *acmd, struct
95549533
return 0;
95559534
}
95569535

9557-
95589536
static int gen_dhchap_key(int argc, char **argv, struct command *acmd, struct plugin *plugin)
95599537
{
95609538
const char *desc =
@@ -9641,32 +9619,9 @@ static int gen_dhchap_key(int argc, char **argv, struct command *acmd, struct pl
96419619
cfg.key_len = 32;
96429620
}
96439621

9644-
if (cfg.key_len != 32 && cfg.key_len != 48 && cfg.key_len != 64) {
9645-
nvme_show_error("Invalid key length %u", cfg.key_len);
9646-
return -EINVAL;
9647-
}
9648-
raw_secret = malloc(cfg.key_len);
9649-
if (!raw_secret)
9650-
return -ENOMEM;
9651-
if (!cfg.secret) {
9652-
if (getrandom_bytes(raw_secret, cfg.key_len) < 0)
9653-
return -errno;
9654-
} else {
9655-
int secret_len = 0, i;
9656-
unsigned int c;
9657-
9658-
for (i = 0; i < strlen(cfg.secret); i += 2) {
9659-
if (sscanf(&cfg.secret[i], "%02x", &c) != 1) {
9660-
nvme_show_error("Invalid secret '%s'", cfg.secret);
9661-
return -EINVAL;
9662-
}
9663-
raw_secret[secret_len++] = (unsigned char)c;
9664-
}
9665-
if (secret_len != cfg.key_len) {
9666-
nvme_show_error("Invalid key length (%d bytes)", secret_len);
9667-
return -EINVAL;
9668-
}
9669-
}
9622+
err = nvme_create_raw_secret(ctx, cfg.secret, cfg.key_len, &raw_secret);
9623+
if (err)
9624+
return err;
96709625

96719626
if (!cfg.nqn) {
96729627
cfg.nqn = hnqn = nvme_read_hostnqn();
@@ -9854,6 +9809,7 @@ static int append_keyfile(struct nvme_global_ctx *ctx, const char *keyring,
98549809
return err;
98559810
}
98569811

9812+
98579813
static int gen_tls_key(int argc, char **argv, struct command *acmd, struct plugin *plugin)
98589814
{
98599815
const char *desc = "Generate a TLS key in NVMe PSK Interchange format.";
@@ -9943,38 +9899,16 @@ static int gen_tls_key(int argc, char **argv, struct command *acmd, struct plugi
99439899
if (cfg.hmac == 2)
99449900
key_len = 48;
99459901

9902+
99469903
ctx = nvme_create_global_ctx(stderr, log_level);
99479904
if (!ctx) {
99489905
nvme_show_error("Failed to create global context");
99499906
return -ENOMEM;
99509907
}
99519908

9952-
raw_secret = malloc(key_len + 4);
9953-
if (!raw_secret)
9954-
return -ENOMEM;
9955-
if (!cfg.secret) {
9956-
if (getrandom_bytes(raw_secret, key_len) < 0)
9957-
return -errno;
9958-
} else {
9959-
int secret_len = 0, i;
9960-
unsigned int c;
9961-
9962-
for (i = 0; i < strlen(cfg.secret); i += 2) {
9963-
if (sscanf(&cfg.secret[i], "%02x", &c) != 1) {
9964-
nvme_show_error("Invalid secret '%s'", cfg.secret);
9965-
return -EINVAL;
9966-
}
9967-
if (i >= key_len * 2) {
9968-
fprintf(stderr, "Skipping excess secret bytes\n");
9969-
break;
9970-
}
9971-
raw_secret[secret_len++] = (unsigned char)c;
9972-
}
9973-
if (secret_len != key_len) {
9974-
nvme_show_error("Invalid key length (%d bytes)", secret_len);
9975-
return -EINVAL;
9976-
}
9977-
}
9909+
err = nvme_create_raw_secret(ctx, cfg.secret, key_len, &raw_secret);
9910+
if (err)
9911+
return err;
99789912

99799913
err = nvme_export_tls_key(ctx, raw_secret, key_len, &encoded_key);
99809914
if (err) {

0 commit comments

Comments
 (0)