cxl/pmem: Add "Set Passphrase" security command support
authorDave Jiang <dave.jiang@intel.com>
Wed, 30 Nov 2022 19:21:47 +0000 (12:21 -0700)
committerDan Williams <dan.j.williams@intel.com>
Thu, 1 Dec 2022 20:42:35 +0000 (12:42 -0800)
Create callback function to support the nvdimm_security_ops ->change_key()
callback. Translate the operation to send "Set Passphrase" security command
for CXL memory device. The operation supports setting a passphrase for the
CXL persistent memory device. It also supports the changing of the
currently set passphrase. The operation allows manipulation of a user
passphrase or a master passphrase.

See CXL rev3.0 spec section 8.2.9.8.6.2 for reference.

However, the spec leaves a gap WRT master passphrase usages. The spec does
not define any ways to retrieve the status of if the support of master
passphrase is available for the device, nor does the commands that utilize
master passphrase will return a specific error that indicates master
passphrase is not supported. If using a device does not support master
passphrase and a command is issued with a master passphrase, the error
message returned by the device will be ambiguous.

Reviewed-by: Davidlohr Bueso <dave@stgolabs.net>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Link: https://lore.kernel.org/r/166983610751.2734609.4445075071552032091.stgit@djiang5-desk3.ch.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/cxl/core/mbox.c
drivers/cxl/cxlmem.h
drivers/cxl/security.c
include/uapi/linux/cxl_mem.h

index 6907ee1f43e0d5883dc1183a1f132f226f64fab6..2fdafa697e6a02e1dc381a0060d6ae2bbb15071e 100644 (file)
@@ -66,6 +66,7 @@ static struct cxl_mem_command cxl_mem_commands[CXL_MEM_COMMAND_ID_MAX] = {
        CXL_CMD(SCAN_MEDIA, 0x11, 0, 0),
        CXL_CMD(GET_SCAN_MEDIA, 0, CXL_VARIABLE_PAYLOAD, 0),
        CXL_CMD(GET_SECURITY_STATE, 0, 0x4, 0),
+       CXL_CMD(SET_PASSPHRASE, 0x60, 0, 0),
 };
 
 /*
index 25d1d8fa7d1e3f09e4f520c62d45716d823e23fa..725b08148524b50ee33693e2031c76888e140ab1 100644 (file)
@@ -274,6 +274,7 @@ enum cxl_opcode {
        CXL_MBOX_OP_SCAN_MEDIA          = 0x4304,
        CXL_MBOX_OP_GET_SCAN_MEDIA      = 0x4305,
        CXL_MBOX_OP_GET_SECURITY_STATE  = 0x4500,
+       CXL_MBOX_OP_SET_PASSPHRASE      = 0x4501,
        CXL_MBOX_OP_MAX                 = 0x10000
 };
 
@@ -380,6 +381,20 @@ struct cxl_mem_command {
 #define CXL_PMEM_SEC_STATE_USER_PLIMIT         0x10
 #define CXL_PMEM_SEC_STATE_MASTER_PLIMIT       0x20
 
+/* set passphrase input payload */
+struct cxl_set_pass {
+       u8 type;
+       u8 reserved[31];
+       /* CXL field using NVDIMM define, same length */
+       u8 old_pass[NVDIMM_PASSPHRASE_LEN];
+       u8 new_pass[NVDIMM_PASSPHRASE_LEN];
+} __packed;
+
+enum {
+       CXL_PMEM_SEC_PASS_MASTER = 0,
+       CXL_PMEM_SEC_PASS_USER,
+};
+
 int cxl_mbox_send_cmd(struct cxl_dev_state *cxlds, u16 opcode, void *in,
                      size_t in_size, void *out, size_t out_size);
 int cxl_dev_state_identify(struct cxl_dev_state *cxlds);
index 8061730842163290179ef5ff247990a7fe2cc410..5365646230c358a86bab2ae023c9fe4e61a0f8d1 100644 (file)
@@ -49,8 +49,30 @@ static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm,
        return security_flags;
 }
 
+static int cxl_pmem_security_change_key(struct nvdimm *nvdimm,
+                                       const struct nvdimm_key_data *old_data,
+                                       const struct nvdimm_key_data *new_data,
+                                       enum nvdimm_passphrase_type ptype)
+{
+       struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
+       struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
+       struct cxl_dev_state *cxlds = cxlmd->cxlds;
+       struct cxl_set_pass set_pass;
+       int rc;
+
+       set_pass.type = ptype == NVDIMM_MASTER ?
+               CXL_PMEM_SEC_PASS_MASTER : CXL_PMEM_SEC_PASS_USER;
+       memcpy(set_pass.old_pass, old_data->data, NVDIMM_PASSPHRASE_LEN);
+       memcpy(set_pass.new_pass, new_data->data, NVDIMM_PASSPHRASE_LEN);
+
+       rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_SET_PASSPHRASE,
+                              &set_pass, sizeof(set_pass), NULL, 0);
+       return rc;
+}
+
 static const struct nvdimm_security_ops __cxl_security_ops = {
        .get_flags = cxl_pmem_get_security_flags,
+       .change_key = cxl_pmem_security_change_key,
 };
 
 const struct nvdimm_security_ops *cxl_security_ops = &__cxl_security_ops;
index cdc6049683ce68260d326975fe671611940c2a72..9da047e9b038138fcb24af6961c8f4411ace2b29 100644 (file)
@@ -42,6 +42,7 @@
        ___C(SCAN_MEDIA, "Scan Media"),                                   \
        ___C(GET_SCAN_MEDIA, "Get Scan Media Results"),                   \
        ___C(GET_SECURITY_STATE, "Get Security State"),                   \
+       ___C(SET_PASSPHRASE, "Set Passphrase"),                           \
        ___C(MAX, "invalid / last command")
 
 #define ___C(a, b) CXL_MEM_COMMAND_ID_##a