diff options
| -rw-r--r-- | drivers/acpi/nfit/core.c | 12 | ||||
| -rw-r--r-- | drivers/acpi/nfit/intel.c | 10 | ||||
| -rw-r--r-- | drivers/nvdimm/btt_devs.c | 18 | ||||
| -rw-r--r-- | drivers/nvdimm/namespace_devs.c | 5 | ||||
| -rw-r--r-- | drivers/nvdimm/pmem.c | 8 | ||||
| -rw-r--r-- | drivers/nvdimm/security.c | 118 | ||||
| -rw-r--r-- | tools/testing/nvdimm/test/nfit.c | 17 |
7 files changed, 117 insertions, 71 deletions
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 5a389a4f4f65..f1ed0befe303 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c | |||
| @@ -567,6 +567,12 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, | |||
| 567 | goto out; | 567 | goto out; |
| 568 | } | 568 | } |
| 569 | 569 | ||
| 570 | dev_dbg(dev, "%s cmd: %s output length: %d\n", dimm_name, | ||
| 571 | cmd_name, out_obj->buffer.length); | ||
| 572 | print_hex_dump_debug(cmd_name, DUMP_PREFIX_OFFSET, 4, 4, | ||
| 573 | out_obj->buffer.pointer, | ||
| 574 | min_t(u32, 128, out_obj->buffer.length), true); | ||
| 575 | |||
| 570 | if (call_pkg) { | 576 | if (call_pkg) { |
| 571 | call_pkg->nd_fw_size = out_obj->buffer.length; | 577 | call_pkg->nd_fw_size = out_obj->buffer.length; |
| 572 | memcpy(call_pkg->nd_payload + call_pkg->nd_size_in, | 578 | memcpy(call_pkg->nd_payload + call_pkg->nd_size_in, |
| @@ -585,12 +591,6 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, | |||
| 585 | return 0; | 591 | return 0; |
| 586 | } | 592 | } |
| 587 | 593 | ||
| 588 | dev_dbg(dev, "%s cmd: %s output length: %d\n", dimm_name, | ||
| 589 | cmd_name, out_obj->buffer.length); | ||
| 590 | print_hex_dump_debug(cmd_name, DUMP_PREFIX_OFFSET, 4, 4, | ||
| 591 | out_obj->buffer.pointer, | ||
| 592 | min_t(u32, 128, out_obj->buffer.length), true); | ||
| 593 | |||
| 594 | for (i = 0, offset = 0; i < desc->out_num; i++) { | 594 | for (i = 0, offset = 0; i < desc->out_num; i++) { |
| 595 | u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i, buf, | 595 | u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i, buf, |
| 596 | (u32 *) out_obj->buffer.pointer, | 596 | (u32 *) out_obj->buffer.pointer, |
diff --git a/drivers/acpi/nfit/intel.c b/drivers/acpi/nfit/intel.c index f70de71f79d6..cddd0fcf622c 100644 --- a/drivers/acpi/nfit/intel.c +++ b/drivers/acpi/nfit/intel.c | |||
| @@ -122,9 +122,8 @@ static int intel_security_change_key(struct nvdimm *nvdimm, | |||
| 122 | if (!test_bit(cmd, &nfit_mem->dsm_mask)) | 122 | if (!test_bit(cmd, &nfit_mem->dsm_mask)) |
| 123 | return -ENOTTY; | 123 | return -ENOTTY; |
| 124 | 124 | ||
| 125 | if (old_data) | 125 | memcpy(nd_cmd.cmd.old_pass, old_data->data, |
| 126 | memcpy(nd_cmd.cmd.old_pass, old_data->data, | 126 | sizeof(nd_cmd.cmd.old_pass)); |
| 127 | sizeof(nd_cmd.cmd.old_pass)); | ||
| 128 | memcpy(nd_cmd.cmd.new_pass, new_data->data, | 127 | memcpy(nd_cmd.cmd.new_pass, new_data->data, |
| 129 | sizeof(nd_cmd.cmd.new_pass)); | 128 | sizeof(nd_cmd.cmd.new_pass)); |
| 130 | rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); | 129 | rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); |
| @@ -336,9 +335,8 @@ static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm, | |||
| 336 | 335 | ||
| 337 | /* flush all cache before we erase DIMM */ | 336 | /* flush all cache before we erase DIMM */ |
| 338 | nvdimm_invalidate_cache(); | 337 | nvdimm_invalidate_cache(); |
| 339 | if (nkey) | 338 | memcpy(nd_cmd.cmd.passphrase, nkey->data, |
| 340 | memcpy(nd_cmd.cmd.passphrase, nkey->data, | 339 | sizeof(nd_cmd.cmd.passphrase)); |
| 341 | sizeof(nd_cmd.cmd.passphrase)); | ||
| 342 | rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); | 340 | rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); |
| 343 | if (rc < 0) | 341 | if (rc < 0) |
| 344 | return rc; | 342 | return rc; |
diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c index b72a303176c7..9486acc08402 100644 --- a/drivers/nvdimm/btt_devs.c +++ b/drivers/nvdimm/btt_devs.c | |||
| @@ -198,14 +198,15 @@ static struct device *__nd_btt_create(struct nd_region *nd_region, | |||
| 198 | return NULL; | 198 | return NULL; |
| 199 | 199 | ||
| 200 | nd_btt->id = ida_simple_get(&nd_region->btt_ida, 0, 0, GFP_KERNEL); | 200 | nd_btt->id = ida_simple_get(&nd_region->btt_ida, 0, 0, GFP_KERNEL); |
| 201 | if (nd_btt->id < 0) { | 201 | if (nd_btt->id < 0) |
| 202 | kfree(nd_btt); | 202 | goto out_nd_btt; |
| 203 | return NULL; | ||
| 204 | } | ||
| 205 | 203 | ||
| 206 | nd_btt->lbasize = lbasize; | 204 | nd_btt->lbasize = lbasize; |
| 207 | if (uuid) | 205 | if (uuid) { |
| 208 | uuid = kmemdup(uuid, 16, GFP_KERNEL); | 206 | uuid = kmemdup(uuid, 16, GFP_KERNEL); |
| 207 | if (!uuid) | ||
| 208 | goto out_put_id; | ||
| 209 | } | ||
| 209 | nd_btt->uuid = uuid; | 210 | nd_btt->uuid = uuid; |
| 210 | dev = &nd_btt->dev; | 211 | dev = &nd_btt->dev; |
| 211 | dev_set_name(dev, "btt%d.%d", nd_region->id, nd_btt->id); | 212 | dev_set_name(dev, "btt%d.%d", nd_region->id, nd_btt->id); |
| @@ -220,6 +221,13 @@ static struct device *__nd_btt_create(struct nd_region *nd_region, | |||
| 220 | return NULL; | 221 | return NULL; |
| 221 | } | 222 | } |
| 222 | return dev; | 223 | return dev; |
| 224 | |||
| 225 | out_put_id: | ||
| 226 | ida_simple_remove(&nd_region->btt_ida, nd_btt->id); | ||
| 227 | |||
| 228 | out_nd_btt: | ||
| 229 | kfree(nd_btt); | ||
| 230 | return NULL; | ||
| 223 | } | 231 | } |
| 224 | 232 | ||
| 225 | struct device *nd_btt_create(struct nd_region *nd_region) | 233 | struct device *nd_btt_create(struct nd_region *nd_region) |
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index 7849bf1812c4..f293556cbbf6 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c | |||
| @@ -2249,9 +2249,12 @@ static struct device *create_namespace_blk(struct nd_region *nd_region, | |||
| 2249 | if (!nsblk->uuid) | 2249 | if (!nsblk->uuid) |
| 2250 | goto blk_err; | 2250 | goto blk_err; |
| 2251 | memcpy(name, nd_label->name, NSLABEL_NAME_LEN); | 2251 | memcpy(name, nd_label->name, NSLABEL_NAME_LEN); |
| 2252 | if (name[0]) | 2252 | if (name[0]) { |
| 2253 | nsblk->alt_name = kmemdup(name, NSLABEL_NAME_LEN, | 2253 | nsblk->alt_name = kmemdup(name, NSLABEL_NAME_LEN, |
| 2254 | GFP_KERNEL); | 2254 | GFP_KERNEL); |
| 2255 | if (!nsblk->alt_name) | ||
| 2256 | goto blk_err; | ||
| 2257 | } | ||
| 2255 | res = nsblk_add_resource(nd_region, ndd, nsblk, | 2258 | res = nsblk_add_resource(nd_region, ndd, nsblk, |
| 2256 | __le64_to_cpu(nd_label->dpa)); | 2259 | __le64_to_cpu(nd_label->dpa)); |
| 2257 | if (!res) | 2260 | if (!res) |
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index bc2f700feef8..0279eb1da3ef 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c | |||
| @@ -113,13 +113,13 @@ static void write_pmem(void *pmem_addr, struct page *page, | |||
| 113 | 113 | ||
| 114 | while (len) { | 114 | while (len) { |
| 115 | mem = kmap_atomic(page); | 115 | mem = kmap_atomic(page); |
| 116 | chunk = min_t(unsigned int, len, PAGE_SIZE); | 116 | chunk = min_t(unsigned int, len, PAGE_SIZE - off); |
| 117 | memcpy_flushcache(pmem_addr, mem + off, chunk); | 117 | memcpy_flushcache(pmem_addr, mem + off, chunk); |
| 118 | kunmap_atomic(mem); | 118 | kunmap_atomic(mem); |
| 119 | len -= chunk; | 119 | len -= chunk; |
| 120 | off = 0; | 120 | off = 0; |
| 121 | page++; | 121 | page++; |
| 122 | pmem_addr += PAGE_SIZE; | 122 | pmem_addr += chunk; |
| 123 | } | 123 | } |
| 124 | } | 124 | } |
| 125 | 125 | ||
| @@ -132,7 +132,7 @@ static blk_status_t read_pmem(struct page *page, unsigned int off, | |||
| 132 | 132 | ||
| 133 | while (len) { | 133 | while (len) { |
| 134 | mem = kmap_atomic(page); | 134 | mem = kmap_atomic(page); |
| 135 | chunk = min_t(unsigned int, len, PAGE_SIZE); | 135 | chunk = min_t(unsigned int, len, PAGE_SIZE - off); |
| 136 | rem = memcpy_mcsafe(mem + off, pmem_addr, chunk); | 136 | rem = memcpy_mcsafe(mem + off, pmem_addr, chunk); |
| 137 | kunmap_atomic(mem); | 137 | kunmap_atomic(mem); |
| 138 | if (rem) | 138 | if (rem) |
| @@ -140,7 +140,7 @@ static blk_status_t read_pmem(struct page *page, unsigned int off, | |||
| 140 | len -= chunk; | 140 | len -= chunk; |
| 141 | off = 0; | 141 | off = 0; |
| 142 | page++; | 142 | page++; |
| 143 | pmem_addr += PAGE_SIZE; | 143 | pmem_addr += chunk; |
| 144 | } | 144 | } |
| 145 | return BLK_STS_OK; | 145 | return BLK_STS_OK; |
| 146 | } | 146 | } |
diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c index f8bb746a549f..a570f2263a42 100644 --- a/drivers/nvdimm/security.c +++ b/drivers/nvdimm/security.c | |||
| @@ -22,6 +22,8 @@ static bool key_revalidate = true; | |||
| 22 | module_param(key_revalidate, bool, 0444); | 22 | module_param(key_revalidate, bool, 0444); |
| 23 | MODULE_PARM_DESC(key_revalidate, "Require key validation at init."); | 23 | MODULE_PARM_DESC(key_revalidate, "Require key validation at init."); |
| 24 | 24 | ||
| 25 | static const char zero_key[NVDIMM_PASSPHRASE_LEN]; | ||
| 26 | |||
| 25 | static void *key_data(struct key *key) | 27 | static void *key_data(struct key *key) |
| 26 | { | 28 | { |
| 27 | struct encrypted_key_payload *epayload = dereference_key_locked(key); | 29 | struct encrypted_key_payload *epayload = dereference_key_locked(key); |
| @@ -75,6 +77,16 @@ static struct key *nvdimm_request_key(struct nvdimm *nvdimm) | |||
| 75 | return key; | 77 | return key; |
| 76 | } | 78 | } |
| 77 | 79 | ||
| 80 | static const void *nvdimm_get_key_payload(struct nvdimm *nvdimm, | ||
| 81 | struct key **key) | ||
| 82 | { | ||
| 83 | *key = nvdimm_request_key(nvdimm); | ||
| 84 | if (!*key) | ||
| 85 | return zero_key; | ||
| 86 | |||
| 87 | return key_data(*key); | ||
| 88 | } | ||
| 89 | |||
| 78 | static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm, | 90 | static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm, |
| 79 | key_serial_t id, int subclass) | 91 | key_serial_t id, int subclass) |
| 80 | { | 92 | { |
| @@ -105,36 +117,57 @@ static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm, | |||
| 105 | return key; | 117 | return key; |
| 106 | } | 118 | } |
| 107 | 119 | ||
| 108 | static struct key *nvdimm_key_revalidate(struct nvdimm *nvdimm) | 120 | static const void *nvdimm_get_user_key_payload(struct nvdimm *nvdimm, |
| 121 | key_serial_t id, int subclass, struct key **key) | ||
| 122 | { | ||
| 123 | *key = NULL; | ||
| 124 | if (id == 0) { | ||
| 125 | if (subclass == NVDIMM_BASE_KEY) | ||
| 126 | return zero_key; | ||
| 127 | else | ||
| 128 | return NULL; | ||
| 129 | } | ||
| 130 | |||
| 131 | *key = nvdimm_lookup_user_key(nvdimm, id, subclass); | ||
| 132 | if (!*key) | ||
| 133 | return NULL; | ||
| 134 | |||
| 135 | return key_data(*key); | ||
| 136 | } | ||
| 137 | |||
| 138 | |||
| 139 | static int nvdimm_key_revalidate(struct nvdimm *nvdimm) | ||
| 109 | { | 140 | { |
| 110 | struct key *key; | 141 | struct key *key; |
| 111 | int rc; | 142 | int rc; |
| 143 | const void *data; | ||
| 112 | 144 | ||
| 113 | if (!nvdimm->sec.ops->change_key) | 145 | if (!nvdimm->sec.ops->change_key) |
| 114 | return NULL; | 146 | return -EOPNOTSUPP; |
| 115 | 147 | ||
| 116 | key = nvdimm_request_key(nvdimm); | 148 | data = nvdimm_get_key_payload(nvdimm, &key); |
| 117 | if (!key) | ||
| 118 | return NULL; | ||
| 119 | 149 | ||
| 120 | /* | 150 | /* |
| 121 | * Send the same key to the hardware as new and old key to | 151 | * Send the same key to the hardware as new and old key to |
| 122 | * verify that the key is good. | 152 | * verify that the key is good. |
| 123 | */ | 153 | */ |
| 124 | rc = nvdimm->sec.ops->change_key(nvdimm, key_data(key), | 154 | rc = nvdimm->sec.ops->change_key(nvdimm, data, data, NVDIMM_USER); |
| 125 | key_data(key), NVDIMM_USER); | ||
| 126 | if (rc < 0) { | 155 | if (rc < 0) { |
| 127 | nvdimm_put_key(key); | 156 | nvdimm_put_key(key); |
| 128 | key = NULL; | 157 | return rc; |
| 129 | } | 158 | } |
| 130 | return key; | 159 | |
| 160 | nvdimm_put_key(key); | ||
| 161 | nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER); | ||
| 162 | return 0; | ||
| 131 | } | 163 | } |
| 132 | 164 | ||
| 133 | static int __nvdimm_security_unlock(struct nvdimm *nvdimm) | 165 | static int __nvdimm_security_unlock(struct nvdimm *nvdimm) |
| 134 | { | 166 | { |
| 135 | struct device *dev = &nvdimm->dev; | 167 | struct device *dev = &nvdimm->dev; |
| 136 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | 168 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); |
| 137 | struct key *key = NULL; | 169 | struct key *key; |
| 170 | const void *data; | ||
| 138 | int rc; | 171 | int rc; |
| 139 | 172 | ||
| 140 | /* The bus lock should be held at the top level of the call stack */ | 173 | /* The bus lock should be held at the top level of the call stack */ |
| @@ -160,16 +193,11 @@ static int __nvdimm_security_unlock(struct nvdimm *nvdimm) | |||
| 160 | if (!key_revalidate) | 193 | if (!key_revalidate) |
| 161 | return 0; | 194 | return 0; |
| 162 | 195 | ||
| 163 | key = nvdimm_key_revalidate(nvdimm); | 196 | return nvdimm_key_revalidate(nvdimm); |
| 164 | if (!key) | ||
| 165 | return nvdimm_security_freeze(nvdimm); | ||
| 166 | } else | 197 | } else |
| 167 | key = nvdimm_request_key(nvdimm); | 198 | data = nvdimm_get_key_payload(nvdimm, &key); |
| 168 | 199 | ||
| 169 | if (!key) | 200 | rc = nvdimm->sec.ops->unlock(nvdimm, data); |
| 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), | 201 | dev_dbg(dev, "key: %d unlock: %s\n", key_serial(key), |
| 174 | rc == 0 ? "success" : "fail"); | 202 | rc == 0 ? "success" : "fail"); |
| 175 | 203 | ||
| @@ -195,6 +223,7 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid) | |||
| 195 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | 223 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); |
| 196 | struct key *key; | 224 | struct key *key; |
| 197 | int rc; | 225 | int rc; |
| 226 | const void *data; | ||
| 198 | 227 | ||
| 199 | /* The bus lock should be held at the top level of the call stack */ | 228 | /* The bus lock should be held at the top level of the call stack */ |
| 200 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); | 229 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); |
| @@ -214,11 +243,12 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid) | |||
| 214 | return -EBUSY; | 243 | return -EBUSY; |
| 215 | } | 244 | } |
| 216 | 245 | ||
| 217 | key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); | 246 | data = nvdimm_get_user_key_payload(nvdimm, keyid, |
| 218 | if (!key) | 247 | NVDIMM_BASE_KEY, &key); |
| 248 | if (!data) | ||
| 219 | return -ENOKEY; | 249 | return -ENOKEY; |
| 220 | 250 | ||
| 221 | rc = nvdimm->sec.ops->disable(nvdimm, key_data(key)); | 251 | rc = nvdimm->sec.ops->disable(nvdimm, data); |
| 222 | dev_dbg(dev, "key: %d disable: %s\n", key_serial(key), | 252 | dev_dbg(dev, "key: %d disable: %s\n", key_serial(key), |
| 223 | rc == 0 ? "success" : "fail"); | 253 | rc == 0 ? "success" : "fail"); |
| 224 | 254 | ||
| @@ -235,6 +265,7 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid, | |||
| 235 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | 265 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); |
| 236 | struct key *key, *newkey; | 266 | struct key *key, *newkey; |
| 237 | int rc; | 267 | int rc; |
| 268 | const void *data, *newdata; | ||
| 238 | 269 | ||
| 239 | /* The bus lock should be held at the top level of the call stack */ | 270 | /* The bus lock should be held at the top level of the call stack */ |
| 240 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); | 271 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); |
| @@ -249,22 +280,19 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid, | |||
| 249 | return -EIO; | 280 | return -EIO; |
| 250 | } | 281 | } |
| 251 | 282 | ||
| 252 | if (keyid == 0) | 283 | data = nvdimm_get_user_key_payload(nvdimm, keyid, |
| 253 | key = NULL; | 284 | NVDIMM_BASE_KEY, &key); |
| 254 | else { | 285 | if (!data) |
| 255 | key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); | 286 | return -ENOKEY; |
| 256 | if (!key) | ||
| 257 | return -ENOKEY; | ||
| 258 | } | ||
| 259 | 287 | ||
| 260 | newkey = nvdimm_lookup_user_key(nvdimm, new_keyid, NVDIMM_NEW_KEY); | 288 | newdata = nvdimm_get_user_key_payload(nvdimm, new_keyid, |
| 261 | if (!newkey) { | 289 | NVDIMM_NEW_KEY, &newkey); |
| 290 | if (!newdata) { | ||
| 262 | nvdimm_put_key(key); | 291 | nvdimm_put_key(key); |
| 263 | return -ENOKEY; | 292 | return -ENOKEY; |
| 264 | } | 293 | } |
| 265 | 294 | ||
| 266 | rc = nvdimm->sec.ops->change_key(nvdimm, key ? key_data(key) : NULL, | 295 | rc = nvdimm->sec.ops->change_key(nvdimm, data, newdata, pass_type); |
| 267 | key_data(newkey), pass_type); | ||
| 268 | dev_dbg(dev, "key: %d %d update%s: %s\n", | 296 | dev_dbg(dev, "key: %d %d update%s: %s\n", |
| 269 | key_serial(key), key_serial(newkey), | 297 | key_serial(key), key_serial(newkey), |
| 270 | pass_type == NVDIMM_MASTER ? "(master)" : "(user)", | 298 | pass_type == NVDIMM_MASTER ? "(master)" : "(user)", |
| @@ -286,8 +314,9 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid, | |||
| 286 | { | 314 | { |
| 287 | struct device *dev = &nvdimm->dev; | 315 | struct device *dev = &nvdimm->dev; |
| 288 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | 316 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); |
| 289 | struct key *key; | 317 | struct key *key = NULL; |
| 290 | int rc; | 318 | int rc; |
| 319 | const void *data; | ||
| 291 | 320 | ||
| 292 | /* The bus lock should be held at the top level of the call stack */ | 321 | /* The bus lock should be held at the top level of the call stack */ |
| 293 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); | 322 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); |
| @@ -319,11 +348,12 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid, | |||
| 319 | return -EOPNOTSUPP; | 348 | return -EOPNOTSUPP; |
| 320 | } | 349 | } |
| 321 | 350 | ||
| 322 | key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); | 351 | data = nvdimm_get_user_key_payload(nvdimm, keyid, |
| 323 | if (!key) | 352 | NVDIMM_BASE_KEY, &key); |
| 353 | if (!data) | ||
| 324 | return -ENOKEY; | 354 | return -ENOKEY; |
| 325 | 355 | ||
| 326 | rc = nvdimm->sec.ops->erase(nvdimm, key_data(key), pass_type); | 356 | rc = nvdimm->sec.ops->erase(nvdimm, data, pass_type); |
| 327 | dev_dbg(dev, "key: %d erase%s: %s\n", key_serial(key), | 357 | dev_dbg(dev, "key: %d erase%s: %s\n", key_serial(key), |
| 328 | pass_type == NVDIMM_MASTER ? "(master)" : "(user)", | 358 | pass_type == NVDIMM_MASTER ? "(master)" : "(user)", |
| 329 | rc == 0 ? "success" : "fail"); | 359 | rc == 0 ? "success" : "fail"); |
| @@ -337,8 +367,9 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid) | |||
| 337 | { | 367 | { |
| 338 | struct device *dev = &nvdimm->dev; | 368 | struct device *dev = &nvdimm->dev; |
| 339 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | 369 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); |
| 340 | struct key *key; | 370 | struct key *key = NULL; |
| 341 | int rc; | 371 | int rc; |
| 372 | const void *data; | ||
| 342 | 373 | ||
| 343 | /* The bus lock should be held at the top level of the call stack */ | 374 | /* The bus lock should be held at the top level of the call stack */ |
| 344 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); | 375 | lockdep_assert_held(&nvdimm_bus->reconfig_mutex); |
| @@ -368,15 +399,12 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid) | |||
| 368 | return -EBUSY; | 399 | return -EBUSY; |
| 369 | } | 400 | } |
| 370 | 401 | ||
| 371 | if (keyid == 0) | 402 | data = nvdimm_get_user_key_payload(nvdimm, keyid, |
| 372 | key = NULL; | 403 | NVDIMM_BASE_KEY, &key); |
| 373 | else { | 404 | if (!data) |
| 374 | key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); | 405 | return -ENOKEY; |
| 375 | if (!key) | ||
| 376 | return -ENOKEY; | ||
| 377 | } | ||
| 378 | 406 | ||
| 379 | rc = nvdimm->sec.ops->overwrite(nvdimm, key ? key_data(key) : NULL); | 407 | rc = nvdimm->sec.ops->overwrite(nvdimm, data); |
| 380 | dev_dbg(dev, "key: %d overwrite submission: %s\n", key_serial(key), | 408 | dev_dbg(dev, "key: %d overwrite submission: %s\n", key_serial(key), |
| 381 | rc == 0 ? "success" : "fail"); | 409 | rc == 0 ? "success" : "fail"); |
| 382 | 410 | ||
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index b579f962451d..85ffdcfa596b 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c | |||
| @@ -146,6 +146,7 @@ static int dimm_fail_cmd_code[ARRAY_SIZE(handle)]; | |||
| 146 | struct nfit_test_sec { | 146 | struct nfit_test_sec { |
| 147 | u8 state; | 147 | u8 state; |
| 148 | u8 ext_state; | 148 | u8 ext_state; |
| 149 | u8 old_state; | ||
| 149 | u8 passphrase[32]; | 150 | u8 passphrase[32]; |
| 150 | u8 master_passphrase[32]; | 151 | u8 master_passphrase[32]; |
| 151 | u64 overwrite_end_time; | 152 | u64 overwrite_end_time; |
| @@ -225,6 +226,8 @@ static struct workqueue_struct *nfit_wq; | |||
| 225 | 226 | ||
| 226 | static struct gen_pool *nfit_pool; | 227 | static struct gen_pool *nfit_pool; |
| 227 | 228 | ||
| 229 | static const char zero_key[NVDIMM_PASSPHRASE_LEN]; | ||
| 230 | |||
| 228 | static struct nfit_test *to_nfit_test(struct device *dev) | 231 | static struct nfit_test *to_nfit_test(struct device *dev) |
| 229 | { | 232 | { |
| 230 | struct platform_device *pdev = to_platform_device(dev); | 233 | struct platform_device *pdev = to_platform_device(dev); |
| @@ -1059,8 +1062,7 @@ static int nd_intel_test_cmd_secure_erase(struct nfit_test *t, | |||
| 1059 | struct device *dev = &t->pdev.dev; | 1062 | struct device *dev = &t->pdev.dev; |
| 1060 | struct nfit_test_sec *sec = &dimm_sec_info[dimm]; | 1063 | struct nfit_test_sec *sec = &dimm_sec_info[dimm]; |
| 1061 | 1064 | ||
| 1062 | if (!(sec->state & ND_INTEL_SEC_STATE_ENABLED) || | 1065 | if (sec->state & ND_INTEL_SEC_STATE_FROZEN) { |
| 1063 | (sec->state & ND_INTEL_SEC_STATE_FROZEN)) { | ||
| 1064 | nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE; | 1066 | nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE; |
| 1065 | dev_dbg(dev, "secure erase: wrong security state\n"); | 1067 | dev_dbg(dev, "secure erase: wrong security state\n"); |
| 1066 | } else if (memcmp(nd_cmd->passphrase, sec->passphrase, | 1068 | } else if (memcmp(nd_cmd->passphrase, sec->passphrase, |
| @@ -1068,6 +1070,12 @@ static int nd_intel_test_cmd_secure_erase(struct nfit_test *t, | |||
| 1068 | nd_cmd->status = ND_INTEL_STATUS_INVALID_PASS; | 1070 | nd_cmd->status = ND_INTEL_STATUS_INVALID_PASS; |
| 1069 | dev_dbg(dev, "secure erase: wrong passphrase\n"); | 1071 | dev_dbg(dev, "secure erase: wrong passphrase\n"); |
| 1070 | } else { | 1072 | } else { |
| 1073 | if (!(sec->state & ND_INTEL_SEC_STATE_ENABLED) | ||
| 1074 | && (memcmp(nd_cmd->passphrase, zero_key, | ||
| 1075 | ND_INTEL_PASSPHRASE_SIZE) != 0)) { | ||
| 1076 | dev_dbg(dev, "invalid zero key\n"); | ||
| 1077 | return 0; | ||
| 1078 | } | ||
| 1071 | memset(sec->passphrase, 0, ND_INTEL_PASSPHRASE_SIZE); | 1079 | memset(sec->passphrase, 0, ND_INTEL_PASSPHRASE_SIZE); |
| 1072 | memset(sec->master_passphrase, 0, ND_INTEL_PASSPHRASE_SIZE); | 1080 | memset(sec->master_passphrase, 0, ND_INTEL_PASSPHRASE_SIZE); |
| 1073 | sec->state = 0; | 1081 | sec->state = 0; |
| @@ -1093,7 +1101,7 @@ static int nd_intel_test_cmd_overwrite(struct nfit_test *t, | |||
| 1093 | return 0; | 1101 | return 0; |
| 1094 | } | 1102 | } |
| 1095 | 1103 | ||
| 1096 | memset(sec->passphrase, 0, ND_INTEL_PASSPHRASE_SIZE); | 1104 | sec->old_state = sec->state; |
| 1097 | sec->state = ND_INTEL_SEC_STATE_OVERWRITE; | 1105 | sec->state = ND_INTEL_SEC_STATE_OVERWRITE; |
| 1098 | dev_dbg(dev, "overwrite progressing.\n"); | 1106 | dev_dbg(dev, "overwrite progressing.\n"); |
| 1099 | sec->overwrite_end_time = get_jiffies_64() + 5 * HZ; | 1107 | sec->overwrite_end_time = get_jiffies_64() + 5 * HZ; |
| @@ -1115,7 +1123,8 @@ static int nd_intel_test_cmd_query_overwrite(struct nfit_test *t, | |||
| 1115 | 1123 | ||
| 1116 | if (time_is_before_jiffies64(sec->overwrite_end_time)) { | 1124 | if (time_is_before_jiffies64(sec->overwrite_end_time)) { |
| 1117 | sec->overwrite_end_time = 0; | 1125 | sec->overwrite_end_time = 0; |
| 1118 | sec->state = 0; | 1126 | sec->state = sec->old_state; |
| 1127 | sec->old_state = 0; | ||
| 1119 | sec->ext_state = ND_INTEL_SEC_ESTATE_ENABLED; | 1128 | sec->ext_state = ND_INTEL_SEC_ESTATE_ENABLED; |
| 1120 | dev_dbg(dev, "overwrite is complete\n"); | 1129 | dev_dbg(dev, "overwrite is complete\n"); |
| 1121 | } else | 1130 | } else |
