From: Keith Busch Date: Mon, 1 Dec 2014 19:00:22 +0000 (-0700) Subject: NVMe: Add security send/receive support X-Git-Tag: v0.1~91 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=daf2d99135a642165ce319341b5ad4718e69e9bc;p=users%2Fsagi%2Fnvme-cli.git NVMe: Add security send/receive support Signed-off-by: Keith Busch --- diff --git a/Documentation/nvme-format.txt b/Documentation/nvme-format.txt index db6baa07..64658854 100644 --- a/Documentation/nvme-format.txt +++ b/Documentation/nvme-format.txt @@ -55,6 +55,19 @@ OPTIONS the secureerase operation. The erase applies to all user data, regardless of location (e.g., within an exposed LBA, within a cache, within deallocated LBAs, etc). Defaults to 0. ++ +[] +|================= +|Value|Definition +|0|No secure erase operation requested +|1|User Data Erase: All user data shall be erased, contents of the user +data after the erase is indeterminate (e.g., the user data may be zero +filled, one filled, etc). The controller may perform a cryptographic +erase when a User Data Erase is requested if all user data is encrypted. +|2|Cryptographic Erase: All user data shall be erased +cryptographically. This is accomplished by deleting the encryption key. +|3–7|Reserved +|================= -p :: --pil=:: @@ -69,6 +82,16 @@ OPTIONS Protection Information: This field specifies whether end-to-end data protection is enabled and the type of protection information. Defaults to 0. ++ +[] +|================= +|Value|Definition +|0|Protection information is not enabled +|1|Protection information is enabled, Type 1 +|2|Protection information is enabled, Type 2 +|3|Protection information is enabled, Type 3 +|4–7|Reserved +|================= -m :: --ms=:: diff --git a/Documentation/nvme-security-recv.txt b/Documentation/nvme-security-recv.txt new file mode 100644 index 00000000..639e0962 --- /dev/null +++ b/Documentation/nvme-security-recv.txt @@ -0,0 +1,68 @@ +nvme-help(1) +============= + +NAME +---- +nvme-security-recv - Security Recv command + +SYNOPSIS +-------- +[verse] +'nvme security-recv' [] [--size= | -x ] + [--secp= | -p ] + [--spsp= | -s ] + [--tl= | -t ] + [-b | --raw-binary] + +DESCRIPTION +----------- +The Security Receive command transfers the status and data result of +one or more Security Send commands that were previously submitted to +the controller. + +The association between a Security Receive command and previous Security +Send commands is dependent on the Security Protocol. The format of the +data to be transferred is dependent on the Security Protocol. Refer to +SPC-4 for Security Protocol details. + +Each Security Receive command returns the appropriate data corresponding +to a Security Send command as defined by the rules of the Security +Protocol. The Security Receive command data may not be retained if there +is a loss of communication between the controller and host, or if a +controller reset occurs. + +OPTIONS +------- +-x :: +--size=:: + Size of buffer to allocate. One success it will be printed + to STDOUT. + +-p :: +--secp=:: + Security Protocol: This field specifies the security protocol + as defined in SPC-4. The controller shall fail the command with + Invalid Parameter indicated if a reserved value of the Security + Protocol is specified. + +-s :: +--spsp=:: + SP Specific: The value of this field is specific to the Security + Protocol as defined in SPC-4. + +-a :: +--al=:: + Allocation Length: The value of this field is specific to the + Security Protocol as defined in SPC-4. + +-b:: +--raw-binary:: + Print the raw buffer to stdout. Defaults to print in hex. + +EXAMPLES +-------- +No Examples + +NVME +---- +Part of the nvme-user suite diff --git a/Documentation/nvme-security-send.txt b/Documentation/nvme-security-send.txt new file mode 100644 index 00000000..1e443d77 --- /dev/null +++ b/Documentation/nvme-security-send.txt @@ -0,0 +1,60 @@ +nvme-help(1) +============= + +NAME +---- +nvme-security-send - Security Send command + +SYNOPSIS +-------- +[verse] +'nvme security-send' [] [--file= | -f ] + [--secp= | -p ] + [--spsp= | -s ] + [--tl= | -t ] + +DESCRIPTION +----------- +The Security Send command is used to transfer security protocol data +to the controller. The data structure transferred to the controller +as part of this command contains security protocol specific commands +to be performed by the controller. The data structure transferred may +also contain data or parameters associated with the security protocol +commands. Status and data that is to be returned to the host for the +security protocol commands submitted by a Security Send command are +retrieved with the Security Receive command. + +The association between a Security Send command and subsequent Security +Receive command is Security Protocol field dependent as defined in SPC-4. + +OPTIONS +------- +-f :: +--file=:: + Path to file used as the security protocol's payload. Required + argument. + +-p :: +--secp=:: + Security Protocol: This field specifies the security protocol + as defined in SPC-4. The controller shall fail the command with + Invalid Parameter indicated if a reserved value of the Security + Protocol is specified. + +-s :: +--spsp=:: + SP Specific: The value of this field is specific to the Security + Protocol as defined in SPC-4. + +-t :: +--tl=:: + Transfer Length: The value of this field is specific to the + Security Protocol as defined in SPC-4. + +EXAMPLES +-------- +No Examples + +NVME +---- +Part of the nvme-user suite diff --git a/nvme.c b/nvme.c index e5443c18..dc068f8f 100644 --- a/nvme.c +++ b/nvme.c @@ -57,6 +57,8 @@ static const char *devicename; ENTRY(FW_DOWNLOAD, "fw-download", "Download new firmware", fw_download) \ ENTRY(ADMIN_PASSTHRU, "admin-passthru", "Submit arbitrary admin command, return results", admin_passthru) \ ENTRY(IO_PASSTHRU, "io-passthru", "Submit an arbitrary IO command, return results", io_passthru) \ + ENTRY(SECURITY_SEND, "security-send", "Submit a Security Send command, return results", sec_send) \ + ENTRY(SECURITY_RECV, "security-recv", "Submit a Security Receive command, return results", sec_recv) \ ENTRY(HELP, "help", "Display this help", help) #define ENTRY(i, n, h, f) \ @@ -896,7 +898,7 @@ static int fw_download(int argc, char **argv) if (fw_fd < 0) { fprintf(stderr, "no firmware file provided\n"); - exit(EINVAL); + return EINVAL; } err = fstat(fw_fd, &sb); if (err < 0) { @@ -1128,6 +1130,152 @@ static int set_feature(int argc, char **argv) return err; } +static int sec_send(int argc, char **argv) +{ + struct stat sb; + struct nvme_admin_cmd cmd; + int err, sec_fd = -1, opt, long_index = 0; + void *sec_buf; + unsigned int tl = 0; + unsigned short spsp = 0; + unsigned char secp = 0; + unsigned int sec_size; + static struct option opts[] = { + {"file", required_argument, 0, 'f'}, + {"secp", required_argument, 0, 'p'}, + {"spsp", required_argument, 0, 's'}, + {"tl", required_argument, 0, 't'}, + { 0, 0, 0, 0} + }; + + while ((opt = getopt_long(argc, (char **)argv, "f:p:s:t:", opts, + &long_index)) != -1) { + switch(opt) { + case 'f': + sec_fd = open(optarg, O_RDONLY); + break; + case 'p': + get_short(optarg, &spsp); + break; + case 's': + get_byte(optarg, &secp); + break; + case 't': + get_int(optarg, &tl); + break; + default: + return EINVAL; + } + } + get_dev(optind, argc, argv); + + if (sec_fd < 0) { + fprintf(stderr, "no firmware file provided\n"); + return EINVAL; + } + err = fstat(sec_fd, &sb); + if (err < 0) { + perror("fstat"); + return errno; + } + sec_size = sb.st_size; + if (posix_memalign(&sec_buf, getpagesize(), sec_size)) { + fprintf(stderr, "No memory for security size:%d\n", sec_size); + return ENOMEM; + } + + memset(&cmd, 0, sizeof(cmd)); + cmd.opcode = nvme_admin_security_send; + cmd.cdw10 = secp << 24 | spsp << 8; + cmd.cdw11 = tl; + cmd.data_len = sec_size; + cmd.addr = (__u64)sec_buf; + + err = ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd); + if (err < 0) + return errno; + else if (err != 0) + fprintf(stderr, "NVME Security Send Command Error:%d\n", err); + else + printf("NVME Security Send Command Success:%d\n", cmd.result); + return err; +} + +static int sec_recv(int argc, char **argv) +{ + struct nvme_admin_cmd cmd; + int err, opt, long_index = 0, raw = 0; + void *sec_buf = NULL; + unsigned int al = 0; + unsigned short spsp = 0; + unsigned char secp = 0; + unsigned int sec_size = 0; + static struct option opts[] = { + {"size", required_argument, 0, 'x'}, + {"file", required_argument, 0, 'f'}, + {"secp", required_argument, 0, 'p'}, + {"spsp", required_argument, 0, 's'}, + {"al", required_argument, 0, 't'}, + {"raw-binary", no_argument, 0, 'b'}, + { 0, 0, 0, 0} + }; + + while ((opt = getopt_long(argc, (char **)argv, "f:p:s:t:", opts, + &long_index)) != -1) { + switch(opt) { + case 'x': + get_int(optarg, &sec_size); + break; + case 'p': + get_short(optarg, &spsp); + break; + case 's': + get_byte(optarg, &secp); + break; + case 't': + get_int(optarg, &al); + break; + case 'b': + raw = 1; + break; + default: + return EINVAL; + } + } + get_dev(optind, argc, argv); + + if (sec_size) { + if (posix_memalign(&sec_buf, getpagesize(), sec_size)) { + fprintf(stderr, "No memory for security size:%d\n", + sec_size); + return ENOMEM; + } + } + + memset(&cmd, 0, sizeof(cmd)); + cmd.opcode = nvme_admin_security_recv; + cmd.cdw10 = secp << 24 | spsp << 8; + cmd.cdw11 = al; + cmd.data_len = sec_size; + cmd.addr = (__u64)sec_buf; + + err = ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd); + if (err < 0) + return errno; + else if (err != 0) + fprintf(stderr, "NVME Security Receivce Command Error:%d\n", + err); + else { + if (!raw) { + printf("NVME Security Receivce Command Success:%d\n", + cmd.result); + d(sec_buf, sec_size, 16, 1); + } else if (sec_size) + d_raw((unsigned char *)&sec_buf, sec_size); + } + return err; +} + static int io_passthru(int argc, char **argv) { fprintf(stderr, "%s: not implemented yet\n", __func__);