nvdimm.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 1/2] libnvdimm/security: Support a zero-key for secure-erase
@ 2019-03-26 17:06 Dave Jiang
  2019-03-26 17:07 ` [PATCH v4 2/2] libnvdimm/security, acpi/nfit: move other seucrity commands to utilize zero key Dave Jiang
  2019-03-26 20:28 ` [PATCH v4 1/2] libnvdimm/security: Support a zero-key for secure-erase Dan Williams
  0 siblings, 2 replies; 3+ messages in thread
From: Dave Jiang @ 2019-03-26 17:06 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Adding support to allow secure erase to happen when security state is not
enabled. Key data of 0's will be passed in.

Some other security commands already use zero keys. This is to unifiy
semantics cross commands with respect to using zero keys.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
v4: No change

v3:
- Add note in commit header about syncing zero key usage. (Dan)

v2:
- Make patch header explicitly zero key (Dan)
- Declare global static zero key (Dan)
- Make nfit_test explicitly test zero key (Dan)

 drivers/nvdimm/security.c        |   17 ++++++++++++-----
 tools/testing/nvdimm/test/nfit.c |   11 +++++++++--
 2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c
index f8bb746a549f..6bea6852bf27 100644
--- a/drivers/nvdimm/security.c
+++ b/drivers/nvdimm/security.c
@@ -22,6 +22,8 @@ static bool key_revalidate = true;
 module_param(key_revalidate, bool, 0444);
 MODULE_PARM_DESC(key_revalidate, "Require key validation at init.");
 
+static const char zero_key[NVDIMM_PASSPHRASE_LEN];
+
 static void *key_data(struct key *key)
 {
 	struct encrypted_key_payload *epayload = dereference_key_locked(key);
@@ -286,8 +288,9 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid,
 {
 	struct device *dev = &nvdimm->dev;
 	struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
-	struct key *key;
+	struct key *key = NULL;
 	int rc;
+	const void *data;
 
 	/* The bus lock should be held at the top level of the call stack */
 	lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
@@ -319,11 +322,15 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid,
 		return -EOPNOTSUPP;
 	}
 
-	key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY);
-	if (!key)
-		return -ENOKEY;
+	if (keyid != 0) {
+		key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY);
+		if (!key)
+			return -ENOKEY;
+		data = key_data(key);
+	} else
+		data = zero_key;
 
-	rc = nvdimm->sec.ops->erase(nvdimm, key_data(key), pass_type);
+	rc = nvdimm->sec.ops->erase(nvdimm, data, pass_type);
 	dev_dbg(dev, "key: %d erase%s: %s\n", key_serial(key),
 			pass_type == NVDIMM_MASTER ? "(master)" : "(user)",
 			rc == 0 ? "success" : "fail");
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index b579f962451d..cad719876ef4 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -225,6 +225,8 @@ static struct workqueue_struct *nfit_wq;
 
 static struct gen_pool *nfit_pool;
 
+static const char zero_key[NVDIMM_PASSPHRASE_LEN];
+
 static struct nfit_test *to_nfit_test(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -1059,8 +1061,7 @@ static int nd_intel_test_cmd_secure_erase(struct nfit_test *t,
 	struct device *dev = &t->pdev.dev;
 	struct nfit_test_sec *sec = &dimm_sec_info[dimm];
 
-	if (!(sec->state & ND_INTEL_SEC_STATE_ENABLED) ||
-			(sec->state & ND_INTEL_SEC_STATE_FROZEN)) {
+	if (sec->state & ND_INTEL_SEC_STATE_FROZEN) {
 		nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE;
 		dev_dbg(dev, "secure erase: wrong security state\n");
 	} else if (memcmp(nd_cmd->passphrase, sec->passphrase,
@@ -1068,6 +1069,12 @@ static int nd_intel_test_cmd_secure_erase(struct nfit_test *t,
 		nd_cmd->status = ND_INTEL_STATUS_INVALID_PASS;
 		dev_dbg(dev, "secure erase: wrong passphrase\n");
 	} else {
+		if (!(sec->state & ND_INTEL_SEC_STATE_ENABLED)
+				&& (memcmp(nd_cmd->passphrase, zero_key,
+					ND_INTEL_PASSPHRASE_SIZE) != 0)) {
+			dev_dbg(dev, "invalid zero key\n");
+			return 0;
+		}
 		memset(sec->passphrase, 0, ND_INTEL_PASSPHRASE_SIZE);
 		memset(sec->master_passphrase, 0, ND_INTEL_PASSPHRASE_SIZE);
 		sec->state = 0;

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH v4 2/2] libnvdimm/security, acpi/nfit: move other seucrity commands to utilize zero key
  2019-03-26 17:06 [PATCH v4 1/2] libnvdimm/security: Support a zero-key for secure-erase Dave Jiang
@ 2019-03-26 17:07 ` Dave Jiang
  2019-03-26 20:28 ` [PATCH v4 1/2] libnvdimm/security: Support a zero-key for secure-erase Dan Williams
  1 sibling, 0 replies; 3+ messages in thread
From: Dave Jiang @ 2019-03-26 17:07 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Sync update passphrase and overwrite to utilize the the same mechansim for
zero key.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
v4:
- Remove deprecated code to detect NULL key in acpi/nfit. (Dan)
v3:
- new patch. sync rest of the commands to use zero key. (Dan)

 drivers/acpi/nfit/intel.c |   10 ++++------
 drivers/nvdimm/security.c |   28 +++++++++++++++-------------
 2 files changed, 19 insertions(+), 19 deletions(-)

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,
 	if (!test_bit(cmd, &nfit_mem->dsm_mask))
 		return -ENOTTY;
 
-	if (old_data)
-		memcpy(nd_cmd.cmd.old_pass, old_data->data,
-				sizeof(nd_cmd.cmd.old_pass));
+	memcpy(nd_cmd.cmd.old_pass, old_data->data,
+			sizeof(nd_cmd.cmd.old_pass));
 	memcpy(nd_cmd.cmd.new_pass, new_data->data,
 			sizeof(nd_cmd.cmd.new_pass));
 	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,
 
 	/* flush all cache before we erase DIMM */
 	nvdimm_invalidate_cache();
-	if (nkey)
-		memcpy(nd_cmd.cmd.passphrase, nkey->data,
-				sizeof(nd_cmd.cmd.passphrase));
+	memcpy(nd_cmd.cmd.passphrase, nkey->data,
+			sizeof(nd_cmd.cmd.passphrase));
 	rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
 	if (rc < 0)
 		return rc;
diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c
index 6bea6852bf27..429cb3cbc1c3 100644
--- a/drivers/nvdimm/security.c
+++ b/drivers/nvdimm/security.c
@@ -235,8 +235,9 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid,
 {
 	struct device *dev = &nvdimm->dev;
 	struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
-	struct key *key, *newkey;
+	struct key *key = NULL, *newkey;
 	int rc;
+	const void *data;
 
 	/* The bus lock should be held at the top level of the call stack */
 	lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
@@ -251,13 +252,13 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid,
 		return -EIO;
 	}
 
-	if (keyid == 0)
-		key = NULL;
-	else {
+	if (keyid != 0) {
 		key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY);
 		if (!key)
 			return -ENOKEY;
-	}
+		data = key_data(key);
+	} else
+		data = zero_key;
 
 	newkey = nvdimm_lookup_user_key(nvdimm, new_keyid, NVDIMM_NEW_KEY);
 	if (!newkey) {
@@ -265,8 +266,8 @@ int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid,
 		return -ENOKEY;
 	}
 
-	rc = nvdimm->sec.ops->change_key(nvdimm, key ? key_data(key) : NULL,
-			key_data(newkey), pass_type);
+	rc = nvdimm->sec.ops->change_key(nvdimm, data, key_data(newkey),
+			pass_type);
 	dev_dbg(dev, "key: %d %d update%s: %s\n",
 			key_serial(key), key_serial(newkey),
 			pass_type == NVDIMM_MASTER ? "(master)" : "(user)",
@@ -344,8 +345,9 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid)
 {
 	struct device *dev = &nvdimm->dev;
 	struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
-	struct key *key;
+	struct key *key = NULL;
 	int rc;
+	const void *data;
 
 	/* The bus lock should be held at the top level of the call stack */
 	lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
@@ -375,15 +377,15 @@ int nvdimm_security_overwrite(struct nvdimm *nvdimm, unsigned int keyid)
 		return -EBUSY;
 	}
 
-	if (keyid == 0)
-		key = NULL;
-	else {
+	if (keyid != 0) {
 		key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY);
 		if (!key)
 			return -ENOKEY;
-	}
+		data = key_data(key);
+	} else
+		data = zero_key;
 
-	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),
 			rc == 0 ? "success" : "fail");
 

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v4 1/2] libnvdimm/security: Support a zero-key for secure-erase
  2019-03-26 17:06 [PATCH v4 1/2] libnvdimm/security: Support a zero-key for secure-erase Dave Jiang
  2019-03-26 17:07 ` [PATCH v4 2/2] libnvdimm/security, acpi/nfit: move other seucrity commands to utilize zero key Dave Jiang
@ 2019-03-26 20:28 ` Dan Williams
  1 sibling, 0 replies; 3+ messages in thread
From: Dan Williams @ 2019-03-26 20:28 UTC (permalink / raw)
  To: Dave Jiang; +Cc: linux-nvdimm

On Tue, Mar 26, 2019 at 10:06 AM Dave Jiang <dave.jiang@intel.com> wrote:
>
> Adding support to allow secure erase to happen when security state is not
> enabled. Key data of 0's will be passed in.

That still sounds more like a feature than a fix, and if I'm looking
closer than the fix is to make sure that all nvdimm_lookup_user_key()
invocations always return data, at least for all the "current / old"
passphrase cases. Because, afaics there's no way to unlock a DIMM if a
platform implements a zero-key default.

Also the current "freeze on no key" functionality will fail if the
DIMM expects the zero-key.

nvdimm_lookup_user_key(good_key_id, current_key) => user key payload

nvdimm_lookup_user_key(bad_key_id) => zero key payload, but should
fail if this was the key-id for the new-passphrase / key

nvdimm_lookup_user_key(0) => zero key payload.

This guarantees that zero-key semantic is uniform across all current /
old-passphrase use cases.

> Some other security commands already use zero keys. This is to unifiy
> semantics cross commands with respect to using zero keys.

We should say a bit why this is important and the knowledge that there
are some platforms that default to a zero-key. This is the primary
justification for the change. For a -rc change of this nature the
status as a fix needs to be clear otherwise it will be deferred to
v5.2. For example if I were Linus I would reject any patch that starts
"Adding support" and not read the rest of the changelog at this stage
of the development cycle.
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-03-26 20:29 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-26 17:06 [PATCH v4 1/2] libnvdimm/security: Support a zero-key for secure-erase Dave Jiang
2019-03-26 17:07 ` [PATCH v4 2/2] libnvdimm/security, acpi/nfit: move other seucrity commands to utilize zero key Dave Jiang
2019-03-26 20:28 ` [PATCH v4 1/2] libnvdimm/security: Support a zero-key for secure-erase Dan Williams

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).