Commit | Line | Data |
---|---|---|
4c6926a2 DJ |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright(c) 2018 Intel Corporation. All rights reserved. */ | |
3 | ||
4 | #include <linux/module.h> | |
5 | #include <linux/device.h> | |
6 | #include <linux/ndctl.h> | |
7 | #include <linux/slab.h> | |
8 | #include <linux/io.h> | |
9 | #include <linux/mm.h> | |
10 | #include <linux/cred.h> | |
11 | #include <linux/key.h> | |
12 | #include <linux/key-type.h> | |
13 | #include <keys/user-type.h> | |
14 | #include <keys/encrypted-type.h> | |
15 | #include "nd-core.h" | |
16 | #include "nd.h" | |
17 | ||
d2a4ac73 DJ |
18 | #define NVDIMM_BASE_KEY 0 |
19 | #define NVDIMM_NEW_KEY 1 | |
20 | ||
4c6926a2 DJ |
21 | static bool key_revalidate = true; |
22 | module_param(key_revalidate, bool, 0444); | |
23 | MODULE_PARM_DESC(key_revalidate, "Require key validation at init."); | |
24 | ||
25 | static void *key_data(struct key *key) | |
26 | { | |
27 | struct encrypted_key_payload *epayload = dereference_key_locked(key); | |
28 | ||
29 | lockdep_assert_held_read(&key->sem); | |
30 | ||
31 | return epayload->decrypted_data; | |
32 | } | |
33 | ||
34 | static void nvdimm_put_key(struct key *key) | |
35 | { | |
64e77c8c DJ |
36 | if (!key) |
37 | return; | |
38 | ||
4c6926a2 DJ |
39 | up_read(&key->sem); |
40 | key_put(key); | |
41 | } | |
42 | ||
43 | /* | |
44 | * Retrieve kernel key for DIMM and request from user space if | |
45 | * necessary. Returns a key held for read and must be put by | |
46 | * nvdimm_put_key() before the usage goes out of scope. | |
47 | */ | |
48 | static struct key *nvdimm_request_key(struct nvdimm *nvdimm) | |
49 | { | |
50 | struct key *key = NULL; | |
51 | static const char NVDIMM_PREFIX[] = "nvdimm:"; | |
52 | char desc[NVDIMM_KEY_DESC_LEN + sizeof(NVDIMM_PREFIX)]; | |
53 | struct device *dev = &nvdimm->dev; | |
54 | ||
55 | sprintf(desc, "%s%s", NVDIMM_PREFIX, nvdimm->dimm_id); | |
56 | key = request_key(&key_type_encrypted, desc, ""); | |
57 | if (IS_ERR(key)) { | |
58 | if (PTR_ERR(key) == -ENOKEY) | |
37379cfc | 59 | dev_dbg(dev, "request_key() found no key\n"); |
4c6926a2 | 60 | else |
37379cfc | 61 | dev_dbg(dev, "request_key() upcall failed\n"); |
4c6926a2 DJ |
62 | key = NULL; |
63 | } else { | |
64 | struct encrypted_key_payload *epayload; | |
65 | ||
66 | down_read(&key->sem); | |
67 | epayload = dereference_key_locked(key); | |
68 | if (epayload->decrypted_datalen != NVDIMM_PASSPHRASE_LEN) { | |
69 | up_read(&key->sem); | |
70 | key_put(key); | |
71 | key = NULL; | |
72 | } | |
73 | } | |
74 | ||
75 | return key; | |
76 | } | |
77 | ||
03b65b22 | 78 | static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm, |
d2a4ac73 | 79 | key_serial_t id, int subclass) |
03b65b22 DJ |
80 | { |
81 | key_ref_t keyref; | |
82 | struct key *key; | |
83 | struct encrypted_key_payload *epayload; | |
84 | struct device *dev = &nvdimm->dev; | |
85 | ||
86 | keyref = lookup_user_key(id, 0, 0); | |
87 | if (IS_ERR(keyref)) | |
88 | return NULL; | |
89 | ||
90 | key = key_ref_to_ptr(keyref); | |
91 | if (key->type != &key_type_encrypted) { | |
92 | key_put(key); | |
93 | return NULL; | |
94 | } | |
03b65b22 | 95 | |
d2a4ac73 | 96 | dev_dbg(dev, "%s: key found: %#x\n", __func__, key_serial(key)); |
03b65b22 | 97 | |
d2a4ac73 | 98 | down_read_nested(&key->sem, subclass); |
03b65b22 DJ |
99 | epayload = dereference_key_locked(key); |
100 | if (epayload->decrypted_datalen != NVDIMM_PASSPHRASE_LEN) { | |
101 | up_read(&key->sem); | |
102 | key_put(key); | |
103 | key = NULL; | |
104 | } | |
105 | return key; | |
106 | } | |
107 | ||
4c6926a2 DJ |
108 | static struct key *nvdimm_key_revalidate(struct nvdimm *nvdimm) |
109 | { | |
110 | struct key *key; | |
111 | int rc; | |
112 | ||
113 | if (!nvdimm->sec.ops->change_key) | |
114 | return NULL; | |
115 | ||
116 | key = nvdimm_request_key(nvdimm); | |
117 | if (!key) | |
118 | return NULL; | |
119 | ||
120 | /* | |
121 | * Send the same key to the hardware as new and old key to | |
122 | * verify that the key is good. | |
123 | */ | |
89fa9d8e DJ |
124 | rc = nvdimm->sec.ops->change_key(nvdimm, key_data(key), |
125 | key_data(key), NVDIMM_USER); | |
4c6926a2 DJ |
126 | if (rc < 0) { |
127 | nvdimm_put_key(key); | |
128 | key = NULL; | |
129 | } | |
130 | return key; | |
131 | } | |
132 | ||
133 | static int __nvdimm_security_unlock(struct nvdimm *nvdimm) | |
134 | { | |
135 | struct device *dev = &nvdimm->dev; | |
136 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | |
137 | struct key *key = NULL; | |
138 | int rc; | |
139 | ||
140 | /* The bus lock should be held at the top level of the call stack */ | |
141 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); | |
142 | ||
143 | if (!nvdimm->sec.ops || !nvdimm->sec.ops->unlock | |
144 | || nvdimm->sec.state < 0) | |
145 | return -EIO; | |
146 | ||
7d988097 | 147 | if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) { |
37379cfc | 148 | dev_dbg(dev, "Security operation in progress.\n"); |
7d988097 DJ |
149 | return -EBUSY; |
150 | } | |
151 | ||
4c6926a2 DJ |
152 | /* |
153 | * If the pre-OS has unlocked the DIMM, attempt to send the key | |
154 | * from request_key() to the hardware for verification. Failure | |
155 | * to revalidate the key against the hardware results in a | |
156 | * freeze of the security configuration. I.e. if the OS does not | |
157 | * have the key, security is being managed pre-OS. | |
158 | */ | |
159 | if (nvdimm->sec.state == NVDIMM_SECURITY_UNLOCKED) { | |
160 | if (!key_revalidate) | |
161 | return 0; | |
162 | ||
163 | key = nvdimm_key_revalidate(nvdimm); | |
164 | if (!key) | |
165 | return nvdimm_security_freeze(nvdimm); | |
166 | } else | |
167 | key = nvdimm_request_key(nvdimm); | |
168 | ||
169 | if (!key) | |
170 | return -ENOKEY; | |
171 | ||
172 | rc = nvdimm->sec.ops->unlock(nvdimm, key_data(key)); | |
173 | dev_dbg(dev, "key: %d unlock: %s\n", key_serial(key), | |
174 | rc == 0 ? "success" : "fail"); | |
175 | ||
176 | nvdimm_put_key(key); | |
89fa9d8e | 177 | nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); |
4c6926a2 DJ |
178 | return rc; |
179 | } | |
180 | ||
181 | int nvdimm_security_unlock(struct device *dev) | |
182 | { | |
183 | struct nvdimm *nvdimm = to_nvdimm(dev); | |
184 | int rc; | |
185 | ||
186 | nvdimm_bus_lock(dev); | |
187 | rc = __nvdimm_security_unlock(nvdimm); | |
188 | nvdimm_bus_unlock(dev); | |
189 | return rc; | |
190 | } | |
03b65b22 DJ |
191 | |
192 | int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid) | |
193 | { | |
194 | struct device *dev = &nvdimm->dev; | |
195 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | |
196 | struct key *key; | |
197 | int rc; | |
198 | ||
199 | /* The bus lock should be held at the top level of the call stack */ | |
200 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); | |
201 | ||
202 | if (!nvdimm->sec.ops || !nvdimm->sec.ops->disable | |
203 | || nvdimm->sec.state < 0) | |
204 | return -EOPNOTSUPP; | |
205 | ||
206 | if (nvdimm->sec.state >= NVDIMM_SECURITY_FROZEN) { | |
37379cfc | 207 | dev_dbg(dev, "Incorrect security state: %d\n", |
03b65b22 DJ |
208 | nvdimm->sec.state); |
209 | return -EIO; | |
210 | } | |
211 | ||
7d988097 | 212 | if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) { |
37379cfc | 213 | dev_dbg(dev, "Security operation in progress.\n"); |
7d988097 DJ |
214 | return -EBUSY; |
215 | } | |
216 | ||
d2a4ac73 | 217 | key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); |
03b65b22 DJ |
218 | if (!key) |
219 | return -ENOKEY; | |
220 | ||
221 | rc = nvdimm->sec.ops->disable(nvdimm, key_data(key)); | |
222 | dev_dbg(dev, "key: %d disable: %s\n", key_serial(key), | |
223 | rc == 0 ? "success" : "fail"); | |
224 | ||
225 | nvdimm_put_key(key); | |
89fa9d8e | 226 | nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); |
03b65b22 DJ |
227 | return rc; |
228 | } | |
d2a4ac73 DJ |
229 | |
230 | int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid, | |
89fa9d8e DJ |
231 | unsigned int new_keyid, |
232 | enum nvdimm_passphrase_type pass_type) | |
d2a4ac73 DJ |
233 | { |
234 | struct device *dev = &nvdimm->dev; | |
235 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | |
236 | struct key *key, *newkey; | |
237 | int rc; | |
238 | ||
239 | /* The bus lock should be held at the top level of the call stack */ | |
240 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); | |
241 | ||
242 | if (!nvdimm->sec.ops || !nvdimm->sec.ops->change_key | |
243 | || nvdimm->sec.state < 0) | |
244 | return -EOPNOTSUPP; | |
245 | ||
246 | if (nvdimm->sec.state >= NVDIMM_SECURITY_FROZEN) { | |
37379cfc | 247 | dev_dbg(dev, "Incorrect security state: %d\n", |
d2a4ac73 DJ |
248 | nvdimm->sec.state); |
249 | return -EIO; | |
250 | } | |
251 | ||
252 | if (keyid == 0) | |
253 | key = NULL; | |
254 | else { | |
255 | key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); | |
256 | if (!key) | |
257 | return -ENOKEY; | |
258 | } | |
259 | ||
260 | newkey = nvdimm_lookup_user_key(nvdimm, new_keyid, NVDIMM_NEW_KEY); | |
261 | if (!newkey) { | |
262 | nvdimm_put_key(key); | |
263 | return -ENOKEY; | |
264 | } | |
265 | ||
266 | rc = nvdimm->sec.ops->change_key(nvdimm, key ? key_data(key) : NULL, | |
89fa9d8e DJ |
267 | key_data(newkey), pass_type); |
268 | dev_dbg(dev, "key: %d %d update%s: %s\n", | |
d2a4ac73 | 269 | key_serial(key), key_serial(newkey), |
89fa9d8e | 270 | pass_type == NVDIMM_MASTER ? "(master)" : "(user)", |
d2a4ac73 DJ |
271 | rc == 0 ? "success" : "fail"); |
272 | ||
273 | nvdimm_put_key(newkey); | |
274 | nvdimm_put_key(key); | |
89fa9d8e DJ |
275 | if (pass_type == NVDIMM_MASTER) |
276 | nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, | |
277 | NVDIMM_MASTER); | |
278 | else | |
279 | nvdimm->sec.state = nvdimm_security_state(nvdimm, | |
280 | NVDIMM_USER); | |
d2a4ac73 DJ |
281 | return rc; |
282 | } | |
64e77c8c | 283 | |
89fa9d8e DJ |
284 | int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid, |
285 | enum nvdimm_passphrase_type pass_type) | |
64e77c8c DJ |
286 | { |
287 | struct device *dev = &nvdimm->dev; | |
288 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | |
289 | struct key *key; | |
290 | int rc; | |
291 | ||
292 | /* The bus lock should be held at the top level of the call stack */ | |
293 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); | |
294 | ||
295 | if (!nvdimm->sec.ops || !nvdimm->sec.ops->erase | |
296 | || nvdimm->sec.state < 0) | |
297 | return -EOPNOTSUPP; | |
298 | ||
299 | if (atomic_read(&nvdimm->busy)) { | |
37379cfc | 300 | dev_dbg(dev, "Unable to secure erase while DIMM active.\n"); |
64e77c8c DJ |
301 | return -EBUSY; |
302 | } | |
303 | ||
304 | if (nvdimm->sec.state >= NVDIMM_SECURITY_FROZEN) { | |
37379cfc | 305 | dev_dbg(dev, "Incorrect security state: %d\n", |
64e77c8c DJ |
306 | nvdimm->sec.state); |
307 | return -EIO; | |
308 | } | |
309 | ||
7d988097 | 310 | if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) { |
37379cfc | 311 | dev_dbg(dev, "Security operation in progress.\n"); |
7d988097 DJ |
312 | return -EBUSY; |
313 | } | |
314 | ||
89fa9d8e DJ |
315 | if (nvdimm->sec.ext_state != NVDIMM_SECURITY_UNLOCKED |
316 | && pass_type == NVDIMM_MASTER) { | |
37379cfc | 317 | dev_dbg(dev, |
89fa9d8e DJ |
318 | "Attempt to secure erase in wrong master state.\n"); |
319 | return -EOPNOTSUPP; | |
320 | } | |
321 | ||
64e77c8c DJ |
322 | key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); |
323 | if (!key) | |
324 | return -ENOKEY; | |
325 | ||
89fa9d8e DJ |
326 | rc = nvdimm->sec.ops->erase(nvdimm, key_data(key), pass_type); |
327 | dev_dbg(dev, "key: %d erase%s: %s\n", key_serial(key), | |
328 | pass_type == NVDIMM_MASTER ? "(master)" : "(user)", | |
64e77c8c DJ |
329 | rc == 0 ? "success" : "fail"); |
330 | ||
331 | nvdimm_put_key(key); | |
89fa9d8e | 332 | nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); |
64e77c8c DJ |
333 | return rc; |
334 | } | |
7d988097 DJ |
335 | |
336 | int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid) | |
337 | { | |
338 | struct device *dev = &nvdimm->dev; | |
339 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | |
340 | struct key *key; | |
341 | int rc; | |
342 | ||
343 | /* The bus lock should be held at the top level of the call stack */ | |
344 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); | |
345 | ||
346 | if (!nvdimm->sec.ops || !nvdimm->sec.ops->overwrite | |
347 | || nvdimm->sec.state < 0) | |
348 | return -EOPNOTSUPP; | |
349 | ||
350 | if (atomic_read(&nvdimm->busy)) { | |
37379cfc | 351 | dev_dbg(dev, "Unable to overwrite while DIMM active.\n"); |
7d988097 DJ |
352 | return -EBUSY; |
353 | } | |
354 | ||
355 | if (dev->driver == NULL) { | |
37379cfc | 356 | dev_dbg(dev, "Unable to overwrite while DIMM active.\n"); |
7d988097 DJ |
357 | return -EINVAL; |
358 | } | |
359 | ||
360 | if (nvdimm->sec.state >= NVDIMM_SECURITY_FROZEN) { | |
37379cfc | 361 | dev_dbg(dev, "Incorrect security state: %d\n", |
7d988097 DJ |
362 | nvdimm->sec.state); |
363 | return -EIO; | |
364 | } | |
365 | ||
366 | if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) { | |
37379cfc | 367 | dev_dbg(dev, "Security operation in progress.\n"); |
7d988097 DJ |
368 | return -EBUSY; |
369 | } | |
370 | ||
371 | if (keyid == 0) | |
372 | key = NULL; | |
373 | else { | |
374 | key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); | |
375 | if (!key) | |
376 | return -ENOKEY; | |
377 | } | |
378 | ||
379 | rc = nvdimm->sec.ops->overwrite(nvdimm, key ? key_data(key) : NULL); | |
380 | dev_dbg(dev, "key: %d overwrite submission: %s\n", key_serial(key), | |
381 | rc == 0 ? "success" : "fail"); | |
382 | ||
383 | nvdimm_put_key(key); | |
384 | if (rc == 0) { | |
385 | set_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags); | |
386 | set_bit(NDD_WORK_PENDING, &nvdimm->flags); | |
387 | nvdimm->sec.state = NVDIMM_SECURITY_OVERWRITE; | |
388 | /* | |
389 | * Make sure we don't lose device while doing overwrite | |
390 | * query. | |
391 | */ | |
392 | get_device(dev); | |
393 | queue_delayed_work(system_wq, &nvdimm->dwork, 0); | |
394 | } | |
89fa9d8e | 395 | |
7d988097 DJ |
396 | return rc; |
397 | } | |
398 | ||
399 | void __nvdimm_security_overwrite_query(struct nvdimm *nvdimm) | |
400 | { | |
401 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(&nvdimm->dev); | |
402 | int rc; | |
403 | unsigned int tmo; | |
404 | ||
405 | /* The bus lock should be held at the top level of the call stack */ | |
406 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); | |
407 | ||
408 | /* | |
409 | * Abort and release device if we no longer have the overwrite | |
410 | * flag set. It means the work has been canceled. | |
411 | */ | |
412 | if (!test_bit(NDD_WORK_PENDING, &nvdimm->flags)) | |
413 | return; | |
414 | ||
415 | tmo = nvdimm->sec.overwrite_tmo; | |
416 | ||
417 | if (!nvdimm->sec.ops || !nvdimm->sec.ops->query_overwrite | |
418 | || nvdimm->sec.state < 0) | |
419 | return; | |
420 | ||
421 | rc = nvdimm->sec.ops->query_overwrite(nvdimm); | |
422 | if (rc == -EBUSY) { | |
423 | ||
424 | /* setup delayed work again */ | |
425 | tmo += 10; | |
426 | queue_delayed_work(system_wq, &nvdimm->dwork, tmo * HZ); | |
427 | nvdimm->sec.overwrite_tmo = min(15U * 60U, tmo); | |
428 | return; | |
429 | } | |
430 | ||
431 | if (rc < 0) | |
37379cfc | 432 | dev_dbg(&nvdimm->dev, "overwrite failed\n"); |
7d988097 DJ |
433 | else |
434 | dev_dbg(&nvdimm->dev, "overwrite completed\n"); | |
435 | ||
436 | if (nvdimm->sec.overwrite_state) | |
437 | sysfs_notify_dirent(nvdimm->sec.overwrite_state); | |
438 | nvdimm->sec.overwrite_tmo = 0; | |
439 | clear_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags); | |
440 | clear_bit(NDD_WORK_PENDING, &nvdimm->flags); | |
441 | put_device(&nvdimm->dev); | |
89fa9d8e DJ |
442 | nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); |
443 | nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, NVDIMM_MASTER); | |
7d988097 DJ |
444 | } |
445 | ||
446 | void nvdimm_security_overwrite_query(struct work_struct *work) | |
447 | { | |
448 | struct nvdimm *nvdimm = | |
449 | container_of(work, typeof(*nvdimm), dwork.work); | |
450 | ||
451 | nvdimm_bus_lock(&nvdimm->dev); | |
452 | __nvdimm_security_overwrite_query(nvdimm); | |
453 | nvdimm_bus_unlock(&nvdimm->dev); | |
454 | } |