Commit d2e5b643 authored by Dave Jiang's avatar Dave Jiang Committed by Dan Williams

libnvdimm/security, acpi/nfit: unify zero-key for all security commands

With zero-key defined, we can remove previous detection of key id 0 or null
key in order to deal with a zero-key situation. Syncing all security
commands to use the zero-key. Helper functions are introduced to return the
data that points to the actual key payload or the zero_key. This helps
uniformly handle the key material even with zero_key.
Signed-off-by: default avatarDave Jiang <dave.jiang@intel.com>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent 037c8489
...@@ -122,9 +122,8 @@ static int intel_security_change_key(struct nvdimm *nvdimm, ...@@ -122,9 +122,8 @@ static int intel_security_change_key(struct nvdimm *nvdimm,
if (!test_bit(cmd, &nfit_mem->dsm_mask)) if (!test_bit(cmd, &nfit_mem->dsm_mask))
return -ENOTTY; return -ENOTTY;
if (old_data) memcpy(nd_cmd.cmd.old_pass, old_data->data,
memcpy(nd_cmd.cmd.old_pass, old_data->data, sizeof(nd_cmd.cmd.old_pass));
sizeof(nd_cmd.cmd.old_pass));
memcpy(nd_cmd.cmd.new_pass, new_data->data, memcpy(nd_cmd.cmd.new_pass, new_data->data,
sizeof(nd_cmd.cmd.new_pass)); sizeof(nd_cmd.cmd.new_pass));
rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); 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,9 +335,8 @@ static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm,
/* flush all cache before we erase DIMM */ /* flush all cache before we erase DIMM */
nvdimm_invalidate_cache(); nvdimm_invalidate_cache();
if (nkey) memcpy(nd_cmd.cmd.passphrase, nkey->data,
memcpy(nd_cmd.cmd.passphrase, nkey->data, sizeof(nd_cmd.cmd.passphrase));
sizeof(nd_cmd.cmd.passphrase));
rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
if (rc < 0) if (rc < 0)
return rc; return rc;
......
...@@ -77,6 +77,16 @@ static struct key *nvdimm_request_key(struct nvdimm *nvdimm) ...@@ -77,6 +77,16 @@ static struct key *nvdimm_request_key(struct nvdimm *nvdimm)
return key; return key;
} }
static const void *nvdimm_get_key_payload(struct nvdimm *nvdimm,
struct key **key)
{
*key = nvdimm_request_key(nvdimm);
if (!*key)
return zero_key;
return key_data(*key);
}
static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm, static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm,
key_serial_t id, int subclass) key_serial_t id, int subclass)
{ {
...@@ -107,36 +117,57 @@ static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm, ...@@ -107,36 +117,57 @@ static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm,
return key; return key;
} }
static struct key *nvdimm_key_revalidate(struct nvdimm *nvdimm) static const void *nvdimm_get_user_key_payload(struct nvdimm *nvdimm,
key_serial_t id, int subclass, struct key **key)
{
*key = NULL;
if (id == 0) {
if (subclass == NVDIMM_BASE_KEY)
return zero_key;
else
return NULL;
}
*key = nvdimm_lookup_user_key(nvdimm, id, subclass);
if (!*key)
return NULL;
return key_data(*key);
}
static int nvdimm_key_revalidate(struct nvdimm *nvdimm)
{ {
struct key *key; struct key *key;
int rc; int rc;
const void *data;
if (!nvdimm->sec.ops->change_key) if (!nvdimm->sec.ops->change_key)
return NULL; return -EOPNOTSUPP;
key = nvdimm_request_key(nvdimm); data = nvdimm_get_key_payload(nvdimm, &key);
if (!key)
return NULL;
/* /*
* Send the same key to the hardware as new and old key to * Send the same key to the hardware as new and old key to
* verify that the key is good. * verify that the key is good.
*/ */
rc = nvdimm->sec.ops->change_key(nvdimm, key_data(key), rc = nvdimm->sec.ops->change_key(nvdimm, data, data, NVDIMM_USER);
key_data(key), NVDIMM_USER);
if (rc < 0) { if (rc < 0) {
nvdimm_put_key(key); nvdimm_put_key(key);
key = NULL; return rc;
} }
return key;
nvdimm_put_key(key);
nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER);
return 0;
} }
static int __nvdimm_security_unlock(struct nvdimm *nvdimm) static int __nvdimm_security_unlock(struct nvdimm *nvdimm)
{ {
struct device *dev = &nvdimm->dev; struct device *dev = &nvdimm->dev;
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
struct key *key = NULL; struct key *key;
const void *data;
int rc; int rc;
/* The bus lock should be held at the top level of the call stack */ /* The bus lock should be held at the top level of the call stack */
...@@ -162,16 +193,11 @@ static int __nvdimm_security_unlock(struct nvdimm *nvdimm) ...@@ -162,16 +193,11 @@ static int __nvdimm_security_unlock(struct nvdimm *nvdimm)
if (!key_revalidate) if (!key_revalidate)
return 0; return 0;
key = nvdimm_key_revalidate(nvdimm); return nvdimm_key_revalidate(nvdimm);
if (!key)
return nvdimm_security_freeze(nvdimm);
} else } else
key = nvdimm_request_key(nvdimm); data = nvdimm_get_key_payload(nvdimm, &key);
if (!key) rc = nvdimm->sec.ops->unlock(nvdimm, data);
return -ENOKEY;
rc = nvdimm->sec.ops->unlock(nvdimm, key_data(key));
dev_dbg(dev, "key: %d unlock: %s\n", key_serial(key), dev_dbg(dev, "key: %d unlock: %s\n", key_serial(key),
rc == 0 ? "success" : "fail"); rc == 0 ? "success" : "fail");
...@@ -197,6 +223,7 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid) ...@@ -197,6 +223,7 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
struct key *key; struct key *key;
int rc; int rc;
const void *data;
/* The bus lock should be held at the top level of the call stack */ /* The bus lock should be held at the top level of the call stack */
lockdep_assert_held(&nvdimm_bus->reconfig_mutex); lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
...@@ -216,11 +243,12 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid) ...@@ -216,11 +243,12 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
return -EBUSY; return -EBUSY;
} }
key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); data = nvdimm_get_user_key_payload(nvdimm, keyid,
if (!key) NVDIMM_BASE_KEY, &key);
if (!data)
return -ENOKEY; return -ENOKEY;
rc = nvdimm->sec.ops->disable(nvdimm, key_data(key)); rc = nvdimm->sec.ops->disable(nvdimm, data);
dev_dbg(dev, "key: %d disable: %s\n", key_serial(key), dev_dbg(dev, "key: %d disable: %s\n", key_serial(key),
rc == 0 ? "success" : "fail"); rc == 0 ? "success" : "fail");
...@@ -237,6 +265,7 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid, ...@@ -237,6 +265,7 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid,
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
struct key *key, *newkey; struct key *key, *newkey;
int rc; int rc;
const void *data, *newdata;
/* The bus lock should be held at the top level of the call stack */ /* The bus lock should be held at the top level of the call stack */
lockdep_assert_held(&nvdimm_bus->reconfig_mutex); lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
...@@ -251,22 +280,19 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid, ...@@ -251,22 +280,19 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid,
return -EIO; return -EIO;
} }
if (keyid == 0) data = nvdimm_get_user_key_payload(nvdimm, keyid,
key = NULL; NVDIMM_BASE_KEY, &key);
else { if (!data)
key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); return -ENOKEY;
if (!key)
return -ENOKEY;
}
newkey = nvdimm_lookup_user_key(nvdimm, new_keyid, NVDIMM_NEW_KEY); newdata = nvdimm_get_user_key_payload(nvdimm, new_keyid,
if (!newkey) { NVDIMM_NEW_KEY, &newkey);
if (!newdata) {
nvdimm_put_key(key); nvdimm_put_key(key);
return -ENOKEY; return -ENOKEY;
} }
rc = nvdimm->sec.ops->change_key(nvdimm, key ? key_data(key) : NULL, rc = nvdimm->sec.ops->change_key(nvdimm, data, newdata, pass_type);
key_data(newkey), pass_type);
dev_dbg(dev, "key: %d %d update%s: %s\n", dev_dbg(dev, "key: %d %d update%s: %s\n",
key_serial(key), key_serial(newkey), key_serial(key), key_serial(newkey),
pass_type == NVDIMM_MASTER ? "(master)" : "(user)", pass_type == NVDIMM_MASTER ? "(master)" : "(user)",
...@@ -322,13 +348,10 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid, ...@@ -322,13 +348,10 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if (keyid != 0) { data = nvdimm_get_user_key_payload(nvdimm, keyid,
key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); NVDIMM_BASE_KEY, &key);
if (!key) if (!data)
return -ENOKEY; return -ENOKEY;
data = key_data(key);
} else
data = zero_key;
rc = nvdimm->sec.ops->erase(nvdimm, data, pass_type); rc = nvdimm->sec.ops->erase(nvdimm, data, pass_type);
dev_dbg(dev, "key: %d erase%s: %s\n", key_serial(key), dev_dbg(dev, "key: %d erase%s: %s\n", key_serial(key),
...@@ -344,8 +367,9 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid) ...@@ -344,8 +367,9 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid)
{ {
struct device *dev = &nvdimm->dev; struct device *dev = &nvdimm->dev;
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
struct key *key; struct key *key = NULL;
int rc; int rc;
const void *data;
/* The bus lock should be held at the top level of the call stack */ /* The bus lock should be held at the top level of the call stack */
lockdep_assert_held(&nvdimm_bus->reconfig_mutex); lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
...@@ -375,15 +399,12 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid) ...@@ -375,15 +399,12 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid)
return -EBUSY; return -EBUSY;
} }
if (keyid == 0) data = nvdimm_get_user_key_payload(nvdimm, keyid,
key = NULL; NVDIMM_BASE_KEY, &key);
else { if (!data)
key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY); return -ENOKEY;
if (!key)
return -ENOKEY;
}
rc = nvdimm->sec.ops->overwrite(nvdimm, key ? key_data(key) : NULL); rc = nvdimm->sec.ops->overwrite(nvdimm, data);
dev_dbg(dev, "key: %d overwrite submission: %s\n", key_serial(key), dev_dbg(dev, "key: %d overwrite submission: %s\n", key_serial(key),
rc == 0 ? "success" : "fail"); rc == 0 ? "success" : "fail");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment