1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright(c) 2022 Intel Corporation. All rights reserved. */
3 #include <linux/libnvdimm.h>
4 #include <linux/unaligned.h>
5 #include <linux/module.h>
6 #include <linux/async.h>
7 #include <linux/slab.h>
8 #include <linux/memregion.h>
12 static unsigned long cxl_pmem_get_security_flags(struct nvdimm
*nvdimm
,
13 enum nvdimm_passphrase_type ptype
)
15 struct cxl_nvdimm
*cxl_nvd
= nvdimm_provider_data(nvdimm
);
16 struct cxl_memdev
*cxlmd
= cxl_nvd
->cxlmd
;
17 struct cxl_mailbox
*cxl_mbox
= &cxlmd
->cxlds
->cxl_mbox
;
18 struct cxl_memdev_state
*mds
= to_cxl_memdev_state(cxlmd
->cxlds
);
19 unsigned long security_flags
= 0;
20 struct cxl_get_security_output
{
23 struct cxl_mbox_cmd mbox_cmd
;
27 mbox_cmd
= (struct cxl_mbox_cmd
) {
28 .opcode
= CXL_MBOX_OP_GET_SECURITY_STATE
,
29 .size_out
= sizeof(out
),
33 rc
= cxl_internal_send_cmd(cxl_mbox
, &mbox_cmd
);
37 sec_out
= le32_to_cpu(out
.flags
);
38 /* cache security state */
39 mds
->security
.state
= sec_out
;
41 if (ptype
== NVDIMM_MASTER
) {
42 if (sec_out
& CXL_PMEM_SEC_STATE_MASTER_PASS_SET
)
43 set_bit(NVDIMM_SECURITY_UNLOCKED
, &security_flags
);
45 set_bit(NVDIMM_SECURITY_DISABLED
, &security_flags
);
46 if (sec_out
& CXL_PMEM_SEC_STATE_MASTER_PLIMIT
)
47 set_bit(NVDIMM_SECURITY_FROZEN
, &security_flags
);
48 return security_flags
;
51 if (sec_out
& CXL_PMEM_SEC_STATE_USER_PASS_SET
) {
52 if (sec_out
& CXL_PMEM_SEC_STATE_FROZEN
||
53 sec_out
& CXL_PMEM_SEC_STATE_USER_PLIMIT
)
54 set_bit(NVDIMM_SECURITY_FROZEN
, &security_flags
);
56 if (sec_out
& CXL_PMEM_SEC_STATE_LOCKED
)
57 set_bit(NVDIMM_SECURITY_LOCKED
, &security_flags
);
59 set_bit(NVDIMM_SECURITY_UNLOCKED
, &security_flags
);
61 set_bit(NVDIMM_SECURITY_DISABLED
, &security_flags
);
64 return security_flags
;
67 static int cxl_pmem_security_change_key(struct nvdimm
*nvdimm
,
68 const struct nvdimm_key_data
*old_data
,
69 const struct nvdimm_key_data
*new_data
,
70 enum nvdimm_passphrase_type ptype
)
72 struct cxl_nvdimm
*cxl_nvd
= nvdimm_provider_data(nvdimm
);
73 struct cxl_memdev
*cxlmd
= cxl_nvd
->cxlmd
;
74 struct cxl_mailbox
*cxl_mbox
= &cxlmd
->cxlds
->cxl_mbox
;
75 struct cxl_mbox_cmd mbox_cmd
;
76 struct cxl_set_pass set_pass
;
78 set_pass
= (struct cxl_set_pass
) {
79 .type
= ptype
== NVDIMM_MASTER
? CXL_PMEM_SEC_PASS_MASTER
:
80 CXL_PMEM_SEC_PASS_USER
,
82 memcpy(set_pass
.old_pass
, old_data
->data
, NVDIMM_PASSPHRASE_LEN
);
83 memcpy(set_pass
.new_pass
, new_data
->data
, NVDIMM_PASSPHRASE_LEN
);
85 mbox_cmd
= (struct cxl_mbox_cmd
) {
86 .opcode
= CXL_MBOX_OP_SET_PASSPHRASE
,
87 .size_in
= sizeof(set_pass
),
88 .payload_in
= &set_pass
,
91 return cxl_internal_send_cmd(cxl_mbox
, &mbox_cmd
);
94 static int __cxl_pmem_security_disable(struct nvdimm
*nvdimm
,
95 const struct nvdimm_key_data
*key_data
,
96 enum nvdimm_passphrase_type ptype
)
98 struct cxl_nvdimm
*cxl_nvd
= nvdimm_provider_data(nvdimm
);
99 struct cxl_memdev
*cxlmd
= cxl_nvd
->cxlmd
;
100 struct cxl_mailbox
*cxl_mbox
= &cxlmd
->cxlds
->cxl_mbox
;
101 struct cxl_disable_pass dis_pass
;
102 struct cxl_mbox_cmd mbox_cmd
;
104 dis_pass
= (struct cxl_disable_pass
) {
105 .type
= ptype
== NVDIMM_MASTER
? CXL_PMEM_SEC_PASS_MASTER
:
106 CXL_PMEM_SEC_PASS_USER
,
108 memcpy(dis_pass
.pass
, key_data
->data
, NVDIMM_PASSPHRASE_LEN
);
110 mbox_cmd
= (struct cxl_mbox_cmd
) {
111 .opcode
= CXL_MBOX_OP_DISABLE_PASSPHRASE
,
112 .size_in
= sizeof(dis_pass
),
113 .payload_in
= &dis_pass
,
116 return cxl_internal_send_cmd(cxl_mbox
, &mbox_cmd
);
119 static int cxl_pmem_security_disable(struct nvdimm
*nvdimm
,
120 const struct nvdimm_key_data
*key_data
)
122 return __cxl_pmem_security_disable(nvdimm
, key_data
, NVDIMM_USER
);
125 static int cxl_pmem_security_disable_master(struct nvdimm
*nvdimm
,
126 const struct nvdimm_key_data
*key_data
)
128 return __cxl_pmem_security_disable(nvdimm
, key_data
, NVDIMM_MASTER
);
131 static int cxl_pmem_security_freeze(struct nvdimm
*nvdimm
)
133 struct cxl_nvdimm
*cxl_nvd
= nvdimm_provider_data(nvdimm
);
134 struct cxl_memdev
*cxlmd
= cxl_nvd
->cxlmd
;
135 struct cxl_mailbox
*cxl_mbox
= &cxlmd
->cxlds
->cxl_mbox
;
136 struct cxl_mbox_cmd mbox_cmd
= {
137 .opcode
= CXL_MBOX_OP_FREEZE_SECURITY
,
140 return cxl_internal_send_cmd(cxl_mbox
, &mbox_cmd
);
143 static int cxl_pmem_security_unlock(struct nvdimm
*nvdimm
,
144 const struct nvdimm_key_data
*key_data
)
146 struct cxl_nvdimm
*cxl_nvd
= nvdimm_provider_data(nvdimm
);
147 struct cxl_memdev
*cxlmd
= cxl_nvd
->cxlmd
;
148 struct cxl_mailbox
*cxl_mbox
= &cxlmd
->cxlds
->cxl_mbox
;
149 u8 pass
[NVDIMM_PASSPHRASE_LEN
];
150 struct cxl_mbox_cmd mbox_cmd
;
153 memcpy(pass
, key_data
->data
, NVDIMM_PASSPHRASE_LEN
);
154 mbox_cmd
= (struct cxl_mbox_cmd
) {
155 .opcode
= CXL_MBOX_OP_UNLOCK
,
156 .size_in
= NVDIMM_PASSPHRASE_LEN
,
160 rc
= cxl_internal_send_cmd(cxl_mbox
, &mbox_cmd
);
167 static int cxl_pmem_security_passphrase_erase(struct nvdimm
*nvdimm
,
168 const struct nvdimm_key_data
*key
,
169 enum nvdimm_passphrase_type ptype
)
171 struct cxl_nvdimm
*cxl_nvd
= nvdimm_provider_data(nvdimm
);
172 struct cxl_memdev
*cxlmd
= cxl_nvd
->cxlmd
;
173 struct cxl_mailbox
*cxl_mbox
= &cxlmd
->cxlds
->cxl_mbox
;
174 struct cxl_mbox_cmd mbox_cmd
;
175 struct cxl_pass_erase erase
;
178 erase
= (struct cxl_pass_erase
) {
179 .type
= ptype
== NVDIMM_MASTER
? CXL_PMEM_SEC_PASS_MASTER
:
180 CXL_PMEM_SEC_PASS_USER
,
182 memcpy(erase
.pass
, key
->data
, NVDIMM_PASSPHRASE_LEN
);
183 mbox_cmd
= (struct cxl_mbox_cmd
) {
184 .opcode
= CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE
,
185 .size_in
= sizeof(erase
),
186 .payload_in
= &erase
,
189 rc
= cxl_internal_send_cmd(cxl_mbox
, &mbox_cmd
);
196 static const struct nvdimm_security_ops __cxl_security_ops
= {
197 .get_flags
= cxl_pmem_get_security_flags
,
198 .change_key
= cxl_pmem_security_change_key
,
199 .disable
= cxl_pmem_security_disable
,
200 .freeze
= cxl_pmem_security_freeze
,
201 .unlock
= cxl_pmem_security_unlock
,
202 .erase
= cxl_pmem_security_passphrase_erase
,
203 .disable_master
= cxl_pmem_security_disable_master
,
206 const struct nvdimm_security_ops
*cxl_security_ops
= &__cxl_security_ops
;