tools/testing/cxl: Add "Freeze Security State" security opcode support
[linux-block.git] / drivers / cxl / security.c
CommitLineData
32828115
DJ
1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright(c) 2022 Intel Corporation. All rights reserved. */
3#include <linux/libnvdimm.h>
4#include <asm/unaligned.h>
5#include <linux/module.h>
6#include <linux/async.h>
7#include <linux/slab.h>
8#include "cxlmem.h"
9#include "cxl.h"
10
11static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm,
12 enum nvdimm_passphrase_type ptype)
13{
14 struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
15 struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
16 struct cxl_dev_state *cxlds = cxlmd->cxlds;
17 unsigned long security_flags = 0;
18 u32 sec_out;
19 int rc;
20
21 rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_GET_SECURITY_STATE, NULL, 0,
22 &sec_out, sizeof(sec_out));
23 if (rc < 0)
24 return 0;
25
26 if (ptype == NVDIMM_MASTER) {
27 if (sec_out & CXL_PMEM_SEC_STATE_MASTER_PASS_SET)
28 set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
29 else
30 set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
31 if (sec_out & CXL_PMEM_SEC_STATE_MASTER_PLIMIT)
32 set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
33 return security_flags;
34 }
35
36 if (sec_out & CXL_PMEM_SEC_STATE_USER_PASS_SET) {
37 if (sec_out & CXL_PMEM_SEC_STATE_FROZEN ||
38 sec_out & CXL_PMEM_SEC_STATE_USER_PLIMIT)
39 set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
40
41 if (sec_out & CXL_PMEM_SEC_STATE_LOCKED)
42 set_bit(NVDIMM_SECURITY_LOCKED, &security_flags);
43 else
44 set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
45 } else {
46 set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
47 }
48
49 return security_flags;
50}
51
99746940
DJ
52static int cxl_pmem_security_change_key(struct nvdimm *nvdimm,
53 const struct nvdimm_key_data *old_data,
54 const struct nvdimm_key_data *new_data,
55 enum nvdimm_passphrase_type ptype)
56{
57 struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
58 struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
59 struct cxl_dev_state *cxlds = cxlmd->cxlds;
60 struct cxl_set_pass set_pass;
61 int rc;
62
63 set_pass.type = ptype == NVDIMM_MASTER ?
64 CXL_PMEM_SEC_PASS_MASTER : CXL_PMEM_SEC_PASS_USER;
65 memcpy(set_pass.old_pass, old_data->data, NVDIMM_PASSPHRASE_LEN);
66 memcpy(set_pass.new_pass, new_data->data, NVDIMM_PASSPHRASE_LEN);
67
68 rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_SET_PASSPHRASE,
69 &set_pass, sizeof(set_pass), NULL, 0);
70 return rc;
71}
72
c4ef680d
DJ
73static int cxl_pmem_security_disable(struct nvdimm *nvdimm,
74 const struct nvdimm_key_data *key_data)
75{
76 struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
77 struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
78 struct cxl_dev_state *cxlds = cxlmd->cxlds;
79 struct cxl_disable_pass dis_pass;
80 int rc;
81
82 dis_pass.type = CXL_PMEM_SEC_PASS_USER;
83 memcpy(dis_pass.pass, key_data->data, NVDIMM_PASSPHRASE_LEN);
84
85 rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_DISABLE_PASSPHRASE,
86 &dis_pass, sizeof(dis_pass), NULL, 0);
87 return rc;
88}
89
a072f7b7
DJ
90static int cxl_pmem_security_freeze(struct nvdimm *nvdimm)
91{
92 struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
93 struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
94 struct cxl_dev_state *cxlds = cxlmd->cxlds;
95
96 return cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_FREEZE_SECURITY, NULL, 0, NULL, 0);
97}
98
32828115
DJ
99static const struct nvdimm_security_ops __cxl_security_ops = {
100 .get_flags = cxl_pmem_get_security_flags,
99746940 101 .change_key = cxl_pmem_security_change_key,
c4ef680d 102 .disable = cxl_pmem_security_disable,
a072f7b7 103 .freeze = cxl_pmem_security_freeze,
32828115
DJ
104};
105
106const struct nvdimm_security_ops *cxl_security_ops = &__cxl_security_ops;