Skip to content

Commit 08a7352

Browse files
committed
mi: Add security send & security receive commands
Add functions for the Security Send & Security Receive Admin Channel commands, and a small example in mi-mctp. Includes a fix for specifying the security_send data, Reported-by: Hao Jiang <[email protected]> Signed-off-by: Jeremy Kerr <[email protected]>
1 parent de534bc commit 08a7352

4 files changed

Lines changed: 206 additions & 0 deletions

File tree

examples/mi-mctp.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,106 @@ int do_admin_raw(nvme_mi_ep_t ep, int argc, char **argv)
415415
return 0;
416416
}
417417

418+
static struct {
419+
uint8_t id;
420+
const char *name;
421+
} sec_protos[] = {
422+
{ 0x00, "Security protocol information" },
423+
{ 0xea, "NVMe" },
424+
{ 0xec, "JEDEC Universal Flash Storage" },
425+
{ 0xed, "SDCard TrustedFlash Security" },
426+
{ 0xee, "IEEE 1667" },
427+
{ 0xef, "ATA Device Server Password Security" },
428+
};
429+
430+
static const char *sec_proto_description(uint8_t id)
431+
{
432+
unsigned int i;
433+
434+
for (i = 0; i < ARRAY_SIZE(sec_protos); i++) {
435+
if (sec_protos[i].id == id)
436+
return sec_protos[i].name;
437+
}
438+
439+
if (id >= 0xf0)
440+
return "Vendor specific";
441+
442+
return "unknown";
443+
}
444+
445+
int do_security_info(nvme_mi_ep_t ep, int argc, char **argv)
446+
{
447+
struct nvme_security_receive_args args = { 0 };
448+
nvme_mi_ctrl_t ctrl;
449+
int i, rc, n_proto;
450+
unsigned long tmp;
451+
uint16_t ctrl_id;
452+
struct {
453+
uint8_t rsvd[6];
454+
uint16_t len;
455+
uint8_t protocols[256];
456+
} proto_info;
457+
458+
if (argc != 2) {
459+
fprintf(stderr, "no controller ID specified\n");
460+
return -1;
461+
}
462+
463+
tmp = atoi(argv[1]);
464+
if (tmp < 0 || tmp > 0xffff) {
465+
fprintf(stderr, "invalid controller ID\n");
466+
return -1;
467+
}
468+
469+
ctrl_id = tmp & 0xffff;
470+
471+
ctrl = nvme_mi_init_ctrl(ep, ctrl_id);
472+
if (!ctrl) {
473+
warn("can't create controller");
474+
return -1;
475+
}
476+
477+
/* protocol 0x00, spsp 0x0000: retrieve supported protocols */
478+
args.args_size = sizeof(args);
479+
args.data = &proto_info;
480+
args.data_len = sizeof(proto_info);
481+
482+
rc = nvme_mi_admin_security_recv(ctrl, &args);
483+
if (rc) {
484+
warnx("can't perform Security Receive command: rc %d", rc);
485+
return -1;
486+
}
487+
488+
if (args.data_len < 6) {
489+
warnx("Short response in security receive command (%d bytes)",
490+
args.data_len);
491+
return -1;
492+
}
493+
494+
n_proto = be16_to_cpu(proto_info.len);
495+
if (args.data_len < 6 + n_proto) {
496+
warnx("Short response in security receive command (%d bytes), "
497+
"for %d protocols", args.data_len, n_proto);
498+
return -1;
499+
}
500+
501+
printf("Supported protocols:\n");
502+
for (i = 0; i < n_proto; i++) {
503+
uint8_t id = proto_info.protocols[i];
504+
printf(" 0x%02x: %s\n", id, sec_proto_description(id));
505+
}
506+
507+
return 0;
508+
}
509+
510+
418511
enum action {
419512
ACTION_INFO,
420513
ACTION_CONTROLLERS,
421514
ACTION_IDENTIFY,
422515
ACTION_GET_LOG_PAGE,
423516
ACTION_ADMIN_RAW,
517+
ACTION_SECURITY_INFO,
424518
};
425519

426520
int main(int argc, char **argv)
@@ -441,6 +535,7 @@ int main(int argc, char **argv)
441535
" identify <controller-id> [--partial]\n"
442536
" get-log-page <controller-id> [<log-id>]\n"
443537
" admin <controller-id> <opcode> [<cdw10>, <cdw11>, ...]\n"
538+
" security-info <controller-id>\n"
444539
);
445540
return EXIT_FAILURE;
446541
}
@@ -467,6 +562,8 @@ int main(int argc, char **argv)
467562
action = ACTION_GET_LOG_PAGE;
468563
} else if (!strcmp(action_str, "admin")) {
469564
action = ACTION_ADMIN_RAW;
565+
} else if (!strcmp(action_str, "security-info")) {
566+
action = ACTION_SECURITY_INFO;
470567
} else {
471568
fprintf(stderr, "invalid action '%s'\n", action_str);
472569
return EXIT_FAILURE;
@@ -497,6 +594,9 @@ int main(int argc, char **argv)
497594
case ACTION_ADMIN_RAW:
498595
rc = do_admin_raw(ep, argc, argv);
499596
break;
597+
case ACTION_SECURITY_INFO:
598+
rc = do_security_info(ep, argc, argv);
599+
break;
500600
}
501601

502602
nvme_mi_close(ep);

src/libnvme-mi.map

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ LIBNVME_MI_1_1 {
1313
nvme_mi_admin_identify_partial;
1414
nvme_mi_admin_get_log_page;
1515
nvme_mi_admin_xfer;
16+
nvme_mi_admin_security_send;
17+
nvme_mi_admin_security_recv;
1618
nvme_mi_open_mctp;
1719
local:
1820
*;

src/nvme/mi.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,104 @@ int nvme_mi_admin_get_log_page(nvme_mi_ctrl_t ctrl,
345345
return rc;
346346
}
347347

348+
int nvme_mi_admin_security_send(nvme_mi_ctrl_t ctrl,
349+
struct nvme_security_send_args *args)
350+
{
351+
352+
struct nvme_mi_admin_resp_hdr resp_hdr;
353+
struct nvme_mi_admin_req_hdr req_hdr;
354+
struct nvme_mi_resp resp;
355+
struct nvme_mi_req req;
356+
int rc;
357+
358+
if (args->args_size < sizeof(*args))
359+
return -EINVAL;
360+
361+
if (args->data_len > 4096)
362+
return -EINVAL;
363+
364+
nvme_mi_admin_init_req(&req, &req_hdr, ctrl->id,
365+
nvme_admin_security_send);
366+
367+
req_hdr.cdw10 = cpu_to_le32(args->secp << 24 |
368+
args->spsp0 << 16 |
369+
args->spsp1 << 8 |
370+
args->nssf);
371+
372+
req_hdr.cdw11 = cpu_to_le32(args->data_len & 0xffffffff);
373+
374+
req_hdr.flags = 0x1;
375+
req_hdr.dlen = cpu_to_le32(args->data_len & 0xffffffff);
376+
req.data = args->data;
377+
req.data_len = args->data_len;
378+
379+
nvme_mi_calc_req_mic(&req);
380+
381+
nvme_mi_admin_init_resp(&resp, &resp_hdr);
382+
383+
rc = nvme_mi_submit(ctrl->ep, &req, &resp);
384+
if (rc)
385+
return rc;
386+
387+
if (resp_hdr.status)
388+
return resp_hdr.status;
389+
390+
if (args->result)
391+
*args->result = le32_to_cpu(resp_hdr.cdw0);
392+
393+
return 0;
394+
}
395+
396+
int nvme_mi_admin_security_recv(nvme_mi_ctrl_t ctrl,
397+
struct nvme_security_receive_args *args)
398+
{
399+
400+
struct nvme_mi_admin_resp_hdr resp_hdr;
401+
struct nvme_mi_admin_req_hdr req_hdr;
402+
struct nvme_mi_resp resp;
403+
struct nvme_mi_req req;
404+
int rc;
405+
406+
if (args->args_size < sizeof(*args))
407+
return -EINVAL;
408+
409+
if (args->data_len > 4096)
410+
return -EINVAL;
411+
412+
nvme_mi_admin_init_req(&req, &req_hdr, ctrl->id,
413+
nvme_admin_security_recv);
414+
415+
req_hdr.cdw10 = cpu_to_le32(args->secp << 24 |
416+
args->spsp0 << 16 |
417+
args->spsp1 << 8 |
418+
args->nssf);
419+
420+
req_hdr.cdw11 = cpu_to_le32(args->data_len & 0xffffffff);
421+
422+
req_hdr.flags = 0x1;
423+
req_hdr.dlen = cpu_to_le32(args->data_len & 0xffffffff);
424+
425+
nvme_mi_calc_req_mic(&req);
426+
427+
nvme_mi_admin_init_resp(&resp, &resp_hdr);
428+
resp.data = args->data;
429+
resp.data_len = args->data_len;
430+
431+
rc = nvme_mi_submit(ctrl->ep, &req, &resp);
432+
if (rc)
433+
return rc;
434+
435+
if (resp_hdr.status)
436+
return resp_hdr.status;
437+
438+
if (args->result)
439+
*args->result = resp_hdr.cdw0;
440+
441+
args->data_len = resp.data_len;
442+
443+
return 0;
444+
}
445+
348446
static int nvme_mi_read_data(nvme_mi_ep_t ep, __u32 cdw0,
349447
void *data, size_t *data_len)
350448
{

src/nvme/mi.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,5 +206,11 @@ static inline int nvme_mi_admin_identify_ctrl_list(nvme_mi_ctrl_t ctrl,
206206
int nvme_mi_admin_get_log_page(nvme_mi_ctrl_t ctrl,
207207
struct nvme_get_log_args *args);
208208

209+
int nvme_mi_admin_security_send(nvme_mi_ctrl_t ctrl,
210+
struct nvme_security_send_args *args);
211+
212+
int nvme_mi_admin_security_recv(nvme_mi_ctrl_t ctrl,
213+
struct nvme_security_receive_args *args);
214+
209215

210216
#endif /* _LIBNVME_MI_MI_H */

0 commit comments

Comments
 (0)