aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-04-15 19:48:51 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-04-15 19:48:51 -0400
commit618d919cae2fcaadc752f27ddac8b939da8b441a (patch)
treedef6e581d1787e1cd2f758c7e1c5917ac4441dba
parent5512320c9f6f2acd7972c05400473c2338325339 (diff)
parent2170a0d53bee1a6c1a4ebd042f99d85aafc6c0ea (diff)
Merge tag 'libnvdimm-fixes-5.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull libnvdimm fixes from Dan Williams: "I debated holding this back for the v5.2 merge window due to the size of the "zero-key" changes, but affected users would benefit from having the fixes sooner. It did not make sense to change the zero-key semantic in isolation for the "secure-erase" command, but instead include it for all security commands. The short background on the need for these changes is that some NVDIMM platforms enable security with a default zero-key rather than let the OS specify the initial key. This makes the security enabling that landed in v5.0 unusable for some users. Summary: - Compatibility fix for nvdimm-security implementations with a default zero-key. - Miscellaneous small fixes for out-of-bound accesses, cleanup after initialization failures, and missing debug messages" * tag 'libnvdimm-fixes-5.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: tools/testing/nvdimm: Retain security state after overwrite libnvdimm/pmem: fix a possible OOB access when read and write pmem libnvdimm/security, acpi/nfit: unify zero-key for all security commands libnvdimm/security: provide fix for secure-erase to use zero-key libnvdimm/btt: Fix a kmemdup failure check libnvdimm/namespace: Fix a potential NULL pointer dereference acpi/nfit: Always dump _DSM output payload
-rw-r--r--drivers/acpi/nfit/core.c12
-rw-r--r--drivers/acpi/nfit/intel.c10
-rw-r--r--drivers/nvdimm/btt_devs.c18
-rw-r--r--drivers/nvdimm/namespace_devs.c5
-rw-r--r--drivers/nvdimm/pmem.c8
-rw-r--r--drivers/nvdimm/security.c118
-rw-r--r--tools/testing/nvdimm/test/nfit.c17
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
225out_put_id:
226 ida_simple_remove(&nd_region->btt_ida, nd_btt->id);
227
228out_nd_btt:
229 kfree(nd_btt);
230 return NULL;
223} 231}
224 232
225struct device *nd_btt_create(struct nd_region *nd_region) 233struct 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;
22module_param(key_revalidate, bool, 0444); 22module_param(key_revalidate, bool, 0444);
23MODULE_PARM_DESC(key_revalidate, "Require key validation at init."); 23MODULE_PARM_DESC(key_revalidate, "Require key validation at init.");
24 24
25static const char zero_key[NVDIMM_PASSPHRASE_LEN];
26
25static void *key_data(struct key *key) 27static 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
80static 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
78static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm, 90static 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
108static struct key *nvdimm_key_revalidate(struct nvdimm *nvdimm) 120static 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
139static 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
133static int __nvdimm_security_unlock(struct nvdimm *nvdimm) 165static 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)];
146struct nfit_test_sec { 146struct 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
226static struct gen_pool *nfit_pool; 227static struct gen_pool *nfit_pool;
227 228
229static const char zero_key[NVDIMM_PASSPHRASE_LEN];
230
228static struct nfit_test *to_nfit_test(struct device *dev) 231static 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