summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/nfit/intel.c59
-rw-r--r--drivers/nvdimm/bus.c2
-rw-r--r--drivers/nvdimm/dimm_devs.c59
-rw-r--r--drivers/nvdimm/nd-core.h21
-rw-r--r--drivers/nvdimm/security.c99
-rw-r--r--include/linux/libnvdimm.h9
-rw-r--r--tools/testing/nvdimm/dimm_devs.c19
7 files changed, 141 insertions, 127 deletions
diff --git a/drivers/acpi/nfit/intel.c b/drivers/acpi/nfit/intel.c
index cddd0fcf622c..1113b679cd7b 100644
--- a/drivers/acpi/nfit/intel.c
+++ b/drivers/acpi/nfit/intel.c
@@ -7,10 +7,11 @@
7#include "intel.h" 7#include "intel.h"
8#include "nfit.h" 8#include "nfit.h"
9 9
10static enum nvdimm_security_state intel_security_state(struct nvdimm *nvdimm, 10static unsigned long intel_security_flags(struct nvdimm *nvdimm,
11 enum nvdimm_passphrase_type ptype) 11 enum nvdimm_passphrase_type ptype)
12{ 12{
13 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 13 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
14 unsigned long security_flags = 0;
14 struct { 15 struct {
15 struct nd_cmd_pkg pkg; 16 struct nd_cmd_pkg pkg;
16 struct nd_intel_get_security_state cmd; 17 struct nd_intel_get_security_state cmd;
@@ -27,7 +28,7 @@ static enum nvdimm_security_state intel_security_state(struct nvdimm *nvdimm,
27 int rc; 28 int rc;
28 29
29 if (!test_bit(NVDIMM_INTEL_GET_SECURITY_STATE, &nfit_mem->dsm_mask)) 30 if (!test_bit(NVDIMM_INTEL_GET_SECURITY_STATE, &nfit_mem->dsm_mask))
30 return -ENXIO; 31 return 0;
31 32
32 /* 33 /*
33 * Short circuit the state retrieval while we are doing overwrite. 34 * Short circuit the state retrieval while we are doing overwrite.
@@ -35,38 +36,42 @@ static enum nvdimm_security_state intel_security_state(struct nvdimm *nvdimm,
35 * until the overwrite DSM completes. 36 * until the overwrite DSM completes.
36 */ 37 */
37 if (nvdimm_in_overwrite(nvdimm) && ptype == NVDIMM_USER) 38 if (nvdimm_in_overwrite(nvdimm) && ptype == NVDIMM_USER)
38 return NVDIMM_SECURITY_OVERWRITE; 39 return BIT(NVDIMM_SECURITY_OVERWRITE);
39 40
40 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); 41 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
41 if (rc < 0) 42 if (rc < 0 || nd_cmd.cmd.status) {
42 return rc; 43 pr_err("%s: security state retrieval failed (%d:%#x)\n",
43 if (nd_cmd.cmd.status) 44 nvdimm_name(nvdimm), rc, nd_cmd.cmd.status);
44 return -EIO; 45 return 0;
46 }
45 47
46 /* check and see if security is enabled and locked */ 48 /* check and see if security is enabled and locked */
47 if (ptype == NVDIMM_MASTER) { 49 if (ptype == NVDIMM_MASTER) {
48 if (nd_cmd.cmd.extended_state & ND_INTEL_SEC_ESTATE_ENABLED) 50 if (nd_cmd.cmd.extended_state & ND_INTEL_SEC_ESTATE_ENABLED)
49 return NVDIMM_SECURITY_UNLOCKED; 51 set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
50 else if (nd_cmd.cmd.extended_state & 52 else
51 ND_INTEL_SEC_ESTATE_PLIMIT) 53 set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
52 return NVDIMM_SECURITY_FROZEN; 54 if (nd_cmd.cmd.extended_state & ND_INTEL_SEC_ESTATE_PLIMIT)
53 } else { 55 set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
54 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_UNSUPPORTED) 56 return security_flags;
55 return -ENXIO;
56 else if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_ENABLED) {
57 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_LOCKED)
58 return NVDIMM_SECURITY_LOCKED;
59 else if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_FROZEN
60 || nd_cmd.cmd.state &
61 ND_INTEL_SEC_STATE_PLIMIT)
62 return NVDIMM_SECURITY_FROZEN;
63 else
64 return NVDIMM_SECURITY_UNLOCKED;
65 }
66 } 57 }
67 58
68 /* this should cover master security disabled as well */ 59 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_UNSUPPORTED)
69 return NVDIMM_SECURITY_DISABLED; 60 return 0;
61
62 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_ENABLED) {
63 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_FROZEN ||
64 nd_cmd.cmd.state & ND_INTEL_SEC_STATE_PLIMIT)
65 set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
66
67 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_LOCKED)
68 set_bit(NVDIMM_SECURITY_LOCKED, &security_flags);
69 else
70 set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
71 } else
72 set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
73
74 return security_flags;
70} 75}
71 76
72static int intel_security_freeze(struct nvdimm *nvdimm) 77static int intel_security_freeze(struct nvdimm *nvdimm)
@@ -371,7 +376,7 @@ static void nvdimm_invalidate_cache(void)
371#endif 376#endif
372 377
373static const struct nvdimm_security_ops __intel_security_ops = { 378static const struct nvdimm_security_ops __intel_security_ops = {
374 .state = intel_security_state, 379 .get_flags = intel_security_flags,
375 .freeze = intel_security_freeze, 380 .freeze = intel_security_freeze,
376 .change_key = intel_security_change_key, 381 .change_key = intel_security_change_key,
377 .disable = intel_security_disable, 382 .disable = intel_security_disable,
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 798c5c4aea9c..29479d3b01b0 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -400,7 +400,7 @@ static int child_unregister(struct device *dev, void *data)
400 400
401 /* We are shutting down. Make state frozen artificially. */ 401 /* We are shutting down. Make state frozen artificially. */
402 nvdimm_bus_lock(dev); 402 nvdimm_bus_lock(dev);
403 nvdimm->sec.state = NVDIMM_SECURITY_FROZEN; 403 set_bit(NVDIMM_SECURITY_FROZEN, &nvdimm->sec.flags);
404 if (test_and_clear_bit(NDD_WORK_PENDING, &nvdimm->flags)) 404 if (test_and_clear_bit(NDD_WORK_PENDING, &nvdimm->flags))
405 dev_put = true; 405 dev_put = true;
406 nvdimm_bus_unlock(dev); 406 nvdimm_bus_unlock(dev);
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index 29a065e769ea..53330625fe07 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -372,24 +372,27 @@ __weak ssize_t security_show(struct device *dev,
372{ 372{
373 struct nvdimm *nvdimm = to_nvdimm(dev); 373 struct nvdimm *nvdimm = to_nvdimm(dev);
374 374
375 switch (nvdimm->sec.state) { 375 if (test_bit(NVDIMM_SECURITY_DISABLED, &nvdimm->sec.flags))
376 case NVDIMM_SECURITY_DISABLED:
377 return sprintf(buf, "disabled\n"); 376 return sprintf(buf, "disabled\n");
378 case NVDIMM_SECURITY_UNLOCKED: 377 if (test_bit(NVDIMM_SECURITY_UNLOCKED, &nvdimm->sec.flags))
379 return sprintf(buf, "unlocked\n"); 378 return sprintf(buf, "unlocked\n");
380 case NVDIMM_SECURITY_LOCKED: 379 if (test_bit(NVDIMM_SECURITY_LOCKED, &nvdimm->sec.flags))
381 return sprintf(buf, "locked\n"); 380 return sprintf(buf, "locked\n");
382 case NVDIMM_SECURITY_FROZEN: 381 if (test_bit(NVDIMM_SECURITY_OVERWRITE, &nvdimm->sec.flags))
383 return sprintf(buf, "frozen\n");
384 case NVDIMM_SECURITY_OVERWRITE:
385 return sprintf(buf, "overwrite\n"); 382 return sprintf(buf, "overwrite\n");
386 default:
387 return -ENOTTY;
388 }
389
390 return -ENOTTY; 383 return -ENOTTY;
391} 384}
392 385
386static ssize_t frozen_show(struct device *dev,
387 struct device_attribute *attr, char *buf)
388{
389 struct nvdimm *nvdimm = to_nvdimm(dev);
390
391 return sprintf(buf, "%d\n", test_bit(NVDIMM_SECURITY_FROZEN,
392 &nvdimm->sec.flags));
393}
394static DEVICE_ATTR_RO(frozen);
395
393#define OPS \ 396#define OPS \
394 C( OP_FREEZE, "freeze", 1), \ 397 C( OP_FREEZE, "freeze", 1), \
395 C( OP_DISABLE, "disable", 2), \ 398 C( OP_DISABLE, "disable", 2), \
@@ -501,6 +504,7 @@ static struct attribute *nvdimm_attributes[] = {
501 &dev_attr_commands.attr, 504 &dev_attr_commands.attr,
502 &dev_attr_available_slots.attr, 505 &dev_attr_available_slots.attr,
503 &dev_attr_security.attr, 506 &dev_attr_security.attr,
507 &dev_attr_frozen.attr,
504 NULL, 508 NULL,
505}; 509};
506 510
@@ -509,17 +513,24 @@ static umode_t nvdimm_visible(struct kobject *kobj, struct attribute *a, int n)
509 struct device *dev = container_of(kobj, typeof(*dev), kobj); 513 struct device *dev = container_of(kobj, typeof(*dev), kobj);
510 struct nvdimm *nvdimm = to_nvdimm(dev); 514 struct nvdimm *nvdimm = to_nvdimm(dev);
511 515
512 if (a != &dev_attr_security.attr) 516 if (a != &dev_attr_security.attr && a != &dev_attr_frozen.attr)
513 return a->mode; 517 return a->mode;
514 if (nvdimm->sec.state < 0) 518 if (!nvdimm->sec.flags)
515 return 0; 519 return 0;
516 /* Are there any state mutation ops? */ 520
517 if (nvdimm->sec.ops->freeze || nvdimm->sec.ops->disable 521 if (a == &dev_attr_security.attr) {
518 || nvdimm->sec.ops->change_key 522 /* Are there any state mutation ops (make writable)? */
519 || nvdimm->sec.ops->erase 523 if (nvdimm->sec.ops->freeze || nvdimm->sec.ops->disable
520 || nvdimm->sec.ops->overwrite) 524 || nvdimm->sec.ops->change_key
525 || nvdimm->sec.ops->erase
526 || nvdimm->sec.ops->overwrite)
527 return a->mode;
528 return 0444;
529 }
530
531 if (nvdimm->sec.ops->freeze)
521 return a->mode; 532 return a->mode;
522 return 0444; 533 return 0;
523} 534}
524 535
525struct attribute_group nvdimm_attribute_group = { 536struct attribute_group nvdimm_attribute_group = {
@@ -569,8 +580,8 @@ struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus,
569 * attribute visibility. 580 * attribute visibility.
570 */ 581 */
571 /* get security state and extended (master) state */ 582 /* get security state and extended (master) state */
572 nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); 583 nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
573 nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, NVDIMM_MASTER); 584 nvdimm->sec.ext_flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER);
574 nd_device_register(dev); 585 nd_device_register(dev);
575 586
576 return nvdimm; 587 return nvdimm;
@@ -588,7 +599,7 @@ int nvdimm_security_setup_events(struct device *dev)
588{ 599{
589 struct nvdimm *nvdimm = to_nvdimm(dev); 600 struct nvdimm *nvdimm = to_nvdimm(dev);
590 601
591 if (nvdimm->sec.state < 0 || !nvdimm->sec.ops 602 if (!nvdimm->sec.flags || !nvdimm->sec.ops
592 || !nvdimm->sec.ops->overwrite) 603 || !nvdimm->sec.ops->overwrite)
593 return 0; 604 return 0;
594 nvdimm->sec.overwrite_state = sysfs_get_dirent(dev->kobj.sd, "security"); 605 nvdimm->sec.overwrite_state = sysfs_get_dirent(dev->kobj.sd, "security");
@@ -614,7 +625,7 @@ int nvdimm_security_freeze(struct nvdimm *nvdimm)
614 if (!nvdimm->sec.ops || !nvdimm->sec.ops->freeze) 625 if (!nvdimm->sec.ops || !nvdimm->sec.ops->freeze)
615 return -EOPNOTSUPP; 626 return -EOPNOTSUPP;
616 627
617 if (nvdimm->sec.state < 0) 628 if (!nvdimm->sec.flags)
618 return -EIO; 629 return -EIO;
619 630
620 if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) { 631 if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) {
@@ -623,7 +634,7 @@ int nvdimm_security_freeze(struct nvdimm *nvdimm)
623 } 634 }
624 635
625 rc = nvdimm->sec.ops->freeze(nvdimm); 636 rc = nvdimm->sec.ops->freeze(nvdimm);
626 nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); 637 nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
627 638
628 return rc; 639 return rc;
629} 640}
diff --git a/drivers/nvdimm/nd-core.h b/drivers/nvdimm/nd-core.h
index 0ac52b6eb00e..da2bbfd56d9f 100644
--- a/drivers/nvdimm/nd-core.h
+++ b/drivers/nvdimm/nd-core.h
@@ -39,21 +39,32 @@ struct nvdimm {
39 const char *dimm_id; 39 const char *dimm_id;
40 struct { 40 struct {
41 const struct nvdimm_security_ops *ops; 41 const struct nvdimm_security_ops *ops;
42 enum nvdimm_security_state state; 42 unsigned long flags;
43 enum nvdimm_security_state ext_state; 43 unsigned long ext_flags;
44 unsigned int overwrite_tmo; 44 unsigned int overwrite_tmo;
45 struct kernfs_node *overwrite_state; 45 struct kernfs_node *overwrite_state;
46 } sec; 46 } sec;
47 struct delayed_work dwork; 47 struct delayed_work dwork;
48}; 48};
49 49
50static inline enum nvdimm_security_state nvdimm_security_state( 50static inline unsigned long nvdimm_security_flags(
51 struct nvdimm *nvdimm, enum nvdimm_passphrase_type ptype) 51 struct nvdimm *nvdimm, enum nvdimm_passphrase_type ptype)
52{ 52{
53 u64 flags;
54 const u64 state_flags = 1UL << NVDIMM_SECURITY_DISABLED
55 | 1UL << NVDIMM_SECURITY_LOCKED
56 | 1UL << NVDIMM_SECURITY_UNLOCKED
57 | 1UL << NVDIMM_SECURITY_OVERWRITE;
58
53 if (!nvdimm->sec.ops) 59 if (!nvdimm->sec.ops)
54 return -ENXIO; 60 return 0;
55 61
56 return nvdimm->sec.ops->state(nvdimm, ptype); 62 flags = nvdimm->sec.ops->get_flags(nvdimm, ptype);
63 /* disabled, locked, unlocked, and overwrite are mutually exclusive */
64 dev_WARN_ONCE(&nvdimm->dev, hweight64(flags & state_flags) > 1,
65 "reported invalid security state: %#llx\n",
66 (unsigned long long) flags);
67 return flags;
57} 68}
58int nvdimm_security_freeze(struct nvdimm *nvdimm); 69int nvdimm_security_freeze(struct nvdimm *nvdimm);
59#if IS_ENABLED(CONFIG_NVDIMM_KEYS) 70#if IS_ENABLED(CONFIG_NVDIMM_KEYS)
diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c
index a570f2263a42..5862d0eee9db 100644
--- a/drivers/nvdimm/security.c
+++ b/drivers/nvdimm/security.c
@@ -158,7 +158,7 @@ static int nvdimm_key_revalidate(struct nvdimm *nvdimm)
158 } 158 }
159 159
160 nvdimm_put_key(key); 160 nvdimm_put_key(key);
161 nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); 161 nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
162 return 0; 162 return 0;
163} 163}
164 164
@@ -174,7 +174,7 @@ static int __nvdimm_security_unlock(struct nvdimm *nvdimm)
174 lockdep_assert_held(&nvdimm_bus->reconfig_mutex); 174 lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
175 175
176 if (!nvdimm->sec.ops || !nvdimm->sec.ops->unlock 176 if (!nvdimm->sec.ops || !nvdimm->sec.ops->unlock
177 || nvdimm->sec.state < 0) 177 || !nvdimm->sec.flags)
178 return -EIO; 178 return -EIO;
179 179
180 if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) { 180 if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) {
@@ -189,7 +189,7 @@ static int __nvdimm_security_unlock(struct nvdimm *nvdimm)
189 * freeze of the security configuration. I.e. if the OS does not 189 * freeze of the security configuration. I.e. if the OS does not
190 * have the key, security is being managed pre-OS. 190 * have the key, security is being managed pre-OS.
191 */ 191 */
192 if (nvdimm->sec.state == NVDIMM_SECURITY_UNLOCKED) { 192 if (test_bit(NVDIMM_SECURITY_UNLOCKED, &nvdimm->sec.flags)) {
193 if (!key_revalidate) 193 if (!key_revalidate)
194 return 0; 194 return 0;
195 195
@@ -202,7 +202,7 @@ static int __nvdimm_security_unlock(struct nvdimm *nvdimm)
202 rc == 0 ? "success" : "fail"); 202 rc == 0 ? "success" : "fail");
203 203
204 nvdimm_put_key(key); 204 nvdimm_put_key(key);
205 nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); 205 nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
206 return rc; 206 return rc;
207} 207}
208 208
@@ -217,6 +217,24 @@ int nvdimm_security_unlock(struct device *dev)
217 return rc; 217 return rc;
218} 218}
219 219
220static int check_security_state(struct nvdimm *nvdimm)
221{
222 struct device *dev = &nvdimm->dev;
223
224 if (test_bit(NVDIMM_SECURITY_FROZEN, &nvdimm->sec.flags)) {
225 dev_dbg(dev, "Incorrect security state: %#lx\n",
226 nvdimm->sec.flags);
227 return -EIO;
228 }
229
230 if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) {
231 dev_dbg(dev, "Security operation in progress.\n");
232 return -EBUSY;
233 }
234
235 return 0;
236}
237
220int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid) 238int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
221{ 239{
222 struct device *dev = &nvdimm->dev; 240 struct device *dev = &nvdimm->dev;
@@ -229,19 +247,12 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
229 lockdep_assert_held(&nvdimm_bus->reconfig_mutex); 247 lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
230 248
231 if (!nvdimm->sec.ops || !nvdimm->sec.ops->disable 249 if (!nvdimm->sec.ops || !nvdimm->sec.ops->disable
232 || nvdimm->sec.state < 0) 250 || !nvdimm->sec.flags)
233 return -EOPNOTSUPP; 251 return -EOPNOTSUPP;
234 252
235 if (nvdimm->sec.state >= NVDIMM_SECURITY_FROZEN) { 253 rc = check_security_state(nvdimm);
236 dev_dbg(dev, "Incorrect security state: %d\n", 254 if (rc)
237 nvdimm->sec.state); 255 return rc;
238 return -EIO;
239 }
240
241 if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) {
242 dev_dbg(dev, "Security operation in progress.\n");
243 return -EBUSY;
244 }
245 256
246 data = nvdimm_get_user_key_payload(nvdimm, keyid, 257 data = nvdimm_get_user_key_payload(nvdimm, keyid,
247 NVDIMM_BASE_KEY, &key); 258 NVDIMM_BASE_KEY, &key);
@@ -253,7 +264,7 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
253 rc == 0 ? "success" : "fail"); 264 rc == 0 ? "success" : "fail");
254 265
255 nvdimm_put_key(key); 266 nvdimm_put_key(key);
256 nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); 267 nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
257 return rc; 268 return rc;
258} 269}
259 270
@@ -271,14 +282,12 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid,
271 lockdep_assert_held(&nvdimm_bus->reconfig_mutex); 282 lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
272 283
273 if (!nvdimm->sec.ops || !nvdimm->sec.ops->change_key 284 if (!nvdimm->sec.ops || !nvdimm->sec.ops->change_key
274 || nvdimm->sec.state < 0) 285 || !nvdimm->sec.flags)
275 return -EOPNOTSUPP; 286 return -EOPNOTSUPP;
276 287
277 if (nvdimm->sec.state >= NVDIMM_SECURITY_FROZEN) { 288 rc = check_security_state(nvdimm);
278 dev_dbg(dev, "Incorrect security state: %d\n", 289 if (rc)
279 nvdimm->sec.state); 290 return rc;
280 return -EIO;
281 }
282 291
283 data = nvdimm_get_user_key_payload(nvdimm, keyid, 292 data = nvdimm_get_user_key_payload(nvdimm, keyid,
284 NVDIMM_BASE_KEY, &key); 293 NVDIMM_BASE_KEY, &key);
@@ -301,10 +310,10 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid,
301 nvdimm_put_key(newkey); 310 nvdimm_put_key(newkey);
302 nvdimm_put_key(key); 311 nvdimm_put_key(key);
303 if (pass_type == NVDIMM_MASTER) 312 if (pass_type == NVDIMM_MASTER)
304 nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, 313 nvdimm->sec.ext_flags = nvdimm_security_flags(nvdimm,
305 NVDIMM_MASTER); 314 NVDIMM_MASTER);
306 else 315 else
307 nvdimm->sec.state = nvdimm_security_state(nvdimm, 316 nvdimm->sec.flags = nvdimm_security_flags(nvdimm,
308 NVDIMM_USER); 317 NVDIMM_USER);
309 return rc; 318 return rc;
310} 319}
@@ -322,7 +331,7 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid,
322 lockdep_assert_held(&nvdimm_bus->reconfig_mutex); 331 lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
323 332
324 if (!nvdimm->sec.ops || !nvdimm->sec.ops->erase 333 if (!nvdimm->sec.ops || !nvdimm->sec.ops->erase
325 || nvdimm->sec.state < 0) 334 || !nvdimm->sec.flags)
326 return -EOPNOTSUPP; 335 return -EOPNOTSUPP;
327 336
328 if (atomic_read(&nvdimm->busy)) { 337 if (atomic_read(&nvdimm->busy)) {
@@ -330,18 +339,11 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid,
330 return -EBUSY; 339 return -EBUSY;
331 } 340 }
332 341
333 if (nvdimm->sec.state >= NVDIMM_SECURITY_FROZEN) { 342 rc = check_security_state(nvdimm);
334 dev_dbg(dev, "Incorrect security state: %d\n", 343 if (rc)
335 nvdimm->sec.state); 344 return rc;
336 return -EIO;
337 }
338
339 if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) {
340 dev_dbg(dev, "Security operation in progress.\n");
341 return -EBUSY;
342 }
343 345
344 if (nvdimm->sec.ext_state != NVDIMM_SECURITY_UNLOCKED 346 if (!test_bit(NVDIMM_SECURITY_UNLOCKED, &nvdimm->sec.ext_flags)
345 && pass_type == NVDIMM_MASTER) { 347 && pass_type == NVDIMM_MASTER) {
346 dev_dbg(dev, 348 dev_dbg(dev,
347 "Attempt to secure erase in wrong master state.\n"); 349 "Attempt to secure erase in wrong master state.\n");
@@ -359,7 +361,7 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid,
359 rc == 0 ? "success" : "fail"); 361 rc == 0 ? "success" : "fail");
360 362
361 nvdimm_put_key(key); 363 nvdimm_put_key(key);
362 nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); 364 nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
363 return rc; 365 return rc;
364} 366}
365 367
@@ -375,7 +377,7 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid)
375 lockdep_assert_held(&nvdimm_bus->reconfig_mutex); 377 lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
376 378
377 if (!nvdimm->sec.ops || !nvdimm->sec.ops->overwrite 379 if (!nvdimm->sec.ops || !nvdimm->sec.ops->overwrite
378 || nvdimm->sec.state < 0) 380 || !nvdimm->sec.flags)
379 return -EOPNOTSUPP; 381 return -EOPNOTSUPP;
380 382
381 if (atomic_read(&nvdimm->busy)) { 383 if (atomic_read(&nvdimm->busy)) {
@@ -388,16 +390,9 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid)
388 return -EINVAL; 390 return -EINVAL;
389 } 391 }
390 392
391 if (nvdimm->sec.state >= NVDIMM_SECURITY_FROZEN) { 393 rc = check_security_state(nvdimm);
392 dev_dbg(dev, "Incorrect security state: %d\n", 394 if (rc)
393 nvdimm->sec.state); 395 return rc;
394 return -EIO;
395 }
396
397 if (test_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags)) {
398 dev_dbg(dev, "Security operation in progress.\n");
399 return -EBUSY;
400 }
401 396
402 data = nvdimm_get_user_key_payload(nvdimm, keyid, 397 data = nvdimm_get_user_key_payload(nvdimm, keyid,
403 NVDIMM_BASE_KEY, &key); 398 NVDIMM_BASE_KEY, &key);
@@ -412,7 +407,7 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid)
412 if (rc == 0) { 407 if (rc == 0) {
413 set_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags); 408 set_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags);
414 set_bit(NDD_WORK_PENDING, &nvdimm->flags); 409 set_bit(NDD_WORK_PENDING, &nvdimm->flags);
415 nvdimm->sec.state = NVDIMM_SECURITY_OVERWRITE; 410 set_bit(NVDIMM_SECURITY_OVERWRITE, &nvdimm->sec.flags);
416 /* 411 /*
417 * Make sure we don't lose device while doing overwrite 412 * Make sure we don't lose device while doing overwrite
418 * query. 413 * query.
@@ -443,7 +438,7 @@ void __nvdimm_security_overwrite_query(struct nvdimm *nvdimm)
443 tmo = nvdimm->sec.overwrite_tmo; 438 tmo = nvdimm->sec.overwrite_tmo;
444 439
445 if (!nvdimm->sec.ops || !nvdimm->sec.ops->query_overwrite 440 if (!nvdimm->sec.ops || !nvdimm->sec.ops->query_overwrite
446 || nvdimm->sec.state < 0) 441 || !nvdimm->sec.flags)
447 return; 442 return;
448 443
449 rc = nvdimm->sec.ops->query_overwrite(nvdimm); 444 rc = nvdimm->sec.ops->query_overwrite(nvdimm);
@@ -467,8 +462,8 @@ void __nvdimm_security_overwrite_query(struct nvdimm *nvdimm)
467 clear_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags); 462 clear_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags);
468 clear_bit(NDD_WORK_PENDING, &nvdimm->flags); 463 clear_bit(NDD_WORK_PENDING, &nvdimm->flags);
469 put_device(&nvdimm->dev); 464 put_device(&nvdimm->dev);
470 nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); 465 nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
471 nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, NVDIMM_MASTER); 466 nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER);
472} 467}
473 468
474void nvdimm_security_overwrite_query(struct work_struct *work) 469void nvdimm_security_overwrite_query(struct work_struct *work)
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index 7a64b3ddb408..b6eddf912568 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -160,8 +160,11 @@ static inline struct nd_blk_region_desc *to_blk_region_desc(
160 160
161} 161}
162 162
163enum nvdimm_security_state { 163/*
164 NVDIMM_SECURITY_ERROR = -1, 164 * Note that separate bits for locked + unlocked are defined so that
165 * 'flags == 0' corresponds to an error / not-supported state.
166 */
167enum nvdimm_security_bits {
165 NVDIMM_SECURITY_DISABLED, 168 NVDIMM_SECURITY_DISABLED,
166 NVDIMM_SECURITY_UNLOCKED, 169 NVDIMM_SECURITY_UNLOCKED,
167 NVDIMM_SECURITY_LOCKED, 170 NVDIMM_SECURITY_LOCKED,
@@ -182,7 +185,7 @@ enum nvdimm_passphrase_type {
182}; 185};
183 186
184struct nvdimm_security_ops { 187struct nvdimm_security_ops {
185 enum nvdimm_security_state (*state)(struct nvdimm *nvdimm, 188 unsigned long (*get_flags)(struct nvdimm *nvdimm,
186 enum nvdimm_passphrase_type pass_type); 189 enum nvdimm_passphrase_type pass_type);
187 int (*freeze)(struct nvdimm *nvdimm); 190 int (*freeze)(struct nvdimm *nvdimm);
188 int (*change_key)(struct nvdimm *nvdimm, 191 int (*change_key)(struct nvdimm *nvdimm,
diff --git a/tools/testing/nvdimm/dimm_devs.c b/tools/testing/nvdimm/dimm_devs.c
index 2d4baf57822f..57bd27dedf1f 100644
--- a/tools/testing/nvdimm/dimm_devs.c
+++ b/tools/testing/nvdimm/dimm_devs.c
@@ -18,24 +18,13 @@ ssize_t security_show(struct device *dev,
18 * For the test version we need to poll the "hardware" in order 18 * For the test version we need to poll the "hardware" in order
19 * to get the updated status for unlock testing. 19 * to get the updated status for unlock testing.
20 */ 20 */
21 nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); 21 nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
22 nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, NVDIMM_MASTER);
23 22
24 switch (nvdimm->sec.state) { 23 if (test_bit(NVDIMM_SECURITY_DISABLED, &nvdimm->sec.flags))
25 case NVDIMM_SECURITY_DISABLED:
26 return sprintf(buf, "disabled\n"); 24 return sprintf(buf, "disabled\n");
27 case NVDIMM_SECURITY_UNLOCKED: 25 if (test_bit(NVDIMM_SECURITY_UNLOCKED, &nvdimm->sec.flags))
28 return sprintf(buf, "unlocked\n"); 26 return sprintf(buf, "unlocked\n");
29 case NVDIMM_SECURITY_LOCKED: 27 if (test_bit(NVDIMM_SECURITY_LOCKED, &nvdimm->sec.flags))
30 return sprintf(buf, "locked\n"); 28 return sprintf(buf, "locked\n");
31 case NVDIMM_SECURITY_FROZEN:
32 return sprintf(buf, "frozen\n");
33 case NVDIMM_SECURITY_OVERWRITE:
34 return sprintf(buf, "overwrite\n");
35 default:
36 return -ENOTTY;
37 }
38
39 return -ENOTTY; 29 return -ENOTTY;
40} 30}
41