]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
NVMe: Add security send/receive support
authorKeith Busch <keith.busch@intel.com>
Mon, 1 Dec 2014 19:00:22 +0000 (12:00 -0700)
committerKeith Busch <keith.busch@intel.com>
Mon, 1 Dec 2014 19:00:22 +0000 (12:00 -0700)
Signed-off-by: Keith Busch <keith.busch@intel.com>
Documentation/nvme-format.txt
Documentation/nvme-security-recv.txt [new file with mode: 0644]
Documentation/nvme-security-send.txt [new file with mode: 0644]
nvme.c

index db6baa07e140bf5a2105aae0f39936177245c8ad..646588544c96030c2c4b0ed26d8547ea013a9960 100644 (file)
@@ -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>::
 --pil=<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>::
 --ms=<ms>::
diff --git a/Documentation/nvme-security-recv.txt b/Documentation/nvme-security-recv.txt
new file mode 100644 (file)
index 0000000..639e096
--- /dev/null
@@ -0,0 +1,68 @@
+nvme-help(1)
+=============
+
+NAME
+----
+nvme-security-recv - Security Recv command
+
+SYNOPSIS
+--------
+[verse]
+'nvme security-recv' [<device>] [--size=<size> | -x <size>]
+                   [--secp=<security-protocol> | -p <security-protocol>]
+                   [--spsp=<protocol-specific> | -s <protocol-specific>]
+                   [--tl=<transfer-length> | -t <transfer-length>]
+                   [-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=<size>::
+       Size of buffer to allocate. One success it will be printed
+       to STDOUT.
+
+-p <security-protocol>::
+--secp=<security-protocol>::
+       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 <security-protocol-specific>::
+--spsp=<security-protocol-specific>::
+       SP Specific: The value of this field is specific to the Security
+       Protocol as defined in SPC-4.
+
+-a <allocation-length>::
+--al=<allocation-length>::
+       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 (file)
index 0000000..1e443d7
--- /dev/null
@@ -0,0 +1,60 @@
+nvme-help(1)
+=============
+
+NAME
+----
+nvme-security-send - Security Send command
+
+SYNOPSIS
+--------
+[verse]
+'nvme security-send' [<device>] [--file=<file> | -f <file>]
+                   [--secp=<security-protocol> | -p <security-protocol>]
+                   [--spsp=<protocol-specific> | -s <protocol-specific>]
+                   [--tl=<transfer-length> | -t <transfer-length>]
+
+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>::
+--file=<file>::
+       Path to file used as the security protocol's payload. Required
+       argument.
+
+-p <security-protocol>::
+--secp=<security-protocol>::
+       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 <security-protocol-specific>::
+--spsp=<security-protocol-specific>::
+       SP Specific: The value of this field is specific to the Security
+       Protocol as defined in SPC-4.
+
+-t <trans-length>::
+--tl=<trans-length>::
+       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 e5443c188049fed7e33b3ba8fd06d781f137976d..dc068f8f1e428d59c092296962fa623a2463dab5 100644 (file)
--- 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__);