]> Git Repo - J-linux.git/blob - drivers/cxl/security.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / cxl / security.c
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>
9 #include "cxlmem.h"
10 #include "cxl.h"
11
12 static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm,
13                                                  enum nvdimm_passphrase_type ptype)
14 {
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 {
21                 __le32 flags;
22         } out;
23         struct cxl_mbox_cmd mbox_cmd;
24         u32 sec_out;
25         int rc;
26
27         mbox_cmd = (struct cxl_mbox_cmd) {
28                 .opcode = CXL_MBOX_OP_GET_SECURITY_STATE,
29                 .size_out = sizeof(out),
30                 .payload_out = &out,
31         };
32
33         rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
34         if (rc < 0)
35                 return 0;
36
37         sec_out = le32_to_cpu(out.flags);
38         /* cache security state */
39         mds->security.state = sec_out;
40
41         if (ptype == NVDIMM_MASTER) {
42                 if (sec_out & CXL_PMEM_SEC_STATE_MASTER_PASS_SET)
43                         set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
44                 else
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;
49         }
50
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);
55
56                 if (sec_out & CXL_PMEM_SEC_STATE_LOCKED)
57                         set_bit(NVDIMM_SECURITY_LOCKED, &security_flags);
58                 else
59                         set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
60         } else {
61                 set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
62         }
63
64         return security_flags;
65 }
66
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)
71 {
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;
77
78         set_pass = (struct cxl_set_pass) {
79                 .type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
80                                                  CXL_PMEM_SEC_PASS_USER,
81         };
82         memcpy(set_pass.old_pass, old_data->data, NVDIMM_PASSPHRASE_LEN);
83         memcpy(set_pass.new_pass, new_data->data, NVDIMM_PASSPHRASE_LEN);
84
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,
89         };
90
91         return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
92 }
93
94 static int __cxl_pmem_security_disable(struct nvdimm *nvdimm,
95                                        const struct nvdimm_key_data *key_data,
96                                        enum nvdimm_passphrase_type ptype)
97 {
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;
103
104         dis_pass = (struct cxl_disable_pass) {
105                 .type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
106                                                  CXL_PMEM_SEC_PASS_USER,
107         };
108         memcpy(dis_pass.pass, key_data->data, NVDIMM_PASSPHRASE_LEN);
109
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,
114         };
115
116         return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
117 }
118
119 static int cxl_pmem_security_disable(struct nvdimm *nvdimm,
120                                      const struct nvdimm_key_data *key_data)
121 {
122         return __cxl_pmem_security_disable(nvdimm, key_data, NVDIMM_USER);
123 }
124
125 static int cxl_pmem_security_disable_master(struct nvdimm *nvdimm,
126                                             const struct nvdimm_key_data *key_data)
127 {
128         return __cxl_pmem_security_disable(nvdimm, key_data, NVDIMM_MASTER);
129 }
130
131 static int cxl_pmem_security_freeze(struct nvdimm *nvdimm)
132 {
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,
138         };
139
140         return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
141 }
142
143 static int cxl_pmem_security_unlock(struct nvdimm *nvdimm,
144                                     const struct nvdimm_key_data *key_data)
145 {
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;
151         int rc;
152
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,
157                 .payload_in = pass,
158         };
159
160         rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
161         if (rc < 0)
162                 return rc;
163
164         return 0;
165 }
166
167 static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm,
168                                               const struct nvdimm_key_data *key,
169                                               enum nvdimm_passphrase_type ptype)
170 {
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;
176         int rc;
177
178         erase = (struct cxl_pass_erase) {
179                 .type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
180                                                  CXL_PMEM_SEC_PASS_USER,
181         };
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,
187         };
188
189         rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
190         if (rc < 0)
191                 return rc;
192
193         return 0;
194 }
195
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,
204 };
205
206 const struct nvdimm_security_ops *cxl_security_ops = &__cxl_security_ops;
This page took 0.03496 seconds and 4 git commands to generate.