All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v9 00/13] ndctl: add security support
@ 2019-01-18  2:38 Dave Jiang
  2019-01-18  2:38 ` [PATCH v9 01/13] ndctl: add support for display security state Dave Jiang
                   ` (13 more replies)
  0 siblings, 14 replies; 24+ messages in thread
From: Dave Jiang @ 2019-01-18  2:38 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

The following series implements mechanisms that utilize the sysfs knobs
provided by the kernel in order to support the Intel DSM v1.8 spec
that provides security to NVDIMM. The following abilities are added:
1. display security state
2. enable/update passphrase
3. disable passphrase
4. freeze security
5. secure erase
6. overwrite
7. master passphrase enable/update

v9:
- Add install-encrypt-key command. (Dan)
- Change enable-passphrase to setup-passphrase. (Dan)
- Change disable-passphrase to remove-passphrase. (Dan)
- Change ndctl_dimm_get_security() to return state directly and remove
  ndctl_dimm_security_supported(). (Dan)
- Remove ND_SECURITY_UNSUPPORTED state
- change ND_SECURITY_* to NDCTL_SECURITY_*
- Fix man page issues (Dan, Jane)
- Define NDCTL_KEYSDIR in config.h (Dan)
- Break check_key_run_and_discard() to 3 helper functions. (Dan)
- Remove key path input parameter. (Dan)
- Remove master key input parameter. (Dan)
- Fixup various issues in security unit test script. (Vishal)

v8:
- Additional cleanup on test script. (Vishal)
- Change load-keys script into internal command for ndctl. (Dan)

v7:
- Added option to provide path to key directory. (Vishal)
- Cleaned up shell scripts. (Vishal)
- Cleaned up documentation. (Vishal)
- Addressed various comments from Vishal.

v6:
- Fix spelling and grammar errors for documentation. (Jing)
- Change bool for indicate master passphrase and old passphrase to enum.
- Fix key load script master key name.
- Update to match v15 of kernel patch series.

v5:
- Updated to match latest kernel interface (encrypted keys)
- Added overwrite support
- Added support for DSM v1.8 master passphrase operations
- Removed upcall related code
- Moved security state to enum (Dan)
- Change security output "security_state" to just "security". (Dan)
- Break out enable and update passphrase operation. (Dan)
- Security build can be compiled out when keyutils does not exist. (Dan)
- Move all keyutils related operations to libndctl. (Dan)

v4:
- Updated to match latest kernel interface.
- Added unit test for all security calls

v3:
- Added support to inject keys in order to update nvdimm security.

v2:
- Fixup the upcall util to match recent kernel updates for nvdimm security.

---

Dave Jiang (13):
      ndctl: add support for display security state
      ndctl: add command for ndctl to receive the key encryption key (master)
      ndctl: add passphrase update to ndctl
      ndctl: add disable security support
      ndctl: add support for freeze security
      ndctl: add support for sanitize dimm
      ndctl: add unit test for security ops (minus overwrite)
      ndctl: add modprobe conf file and load-keys ndctl command
      ndctl: add overwrite operation support
      ndctl: add wait-overwrite support
      ndctl: master phassphrase management support
      ndctl: add master secure erase support
      ndctl: documentation for security and key management


 Documentation/ndctl/Makefile.am                   |   10 
 Documentation/ndctl/intel-nvdimm-security.txt     |  139 +++++
 Documentation/ndctl/ndctl-freeze-security.txt     |   60 ++
 Documentation/ndctl/ndctl-install-encrypt-key.txt |   31 +
 Documentation/ndctl/ndctl-list.txt                |    8 
 Documentation/ndctl/ndctl-load-keys.txt           |   43 ++
 Documentation/ndctl/ndctl-remove-passphrase.txt   |   28 +
 Documentation/ndctl/ndctl-sanitize-dimm.txt       |   48 ++
 Documentation/ndctl/ndctl-setup-passphrase.txt    |   41 +
 Documentation/ndctl/ndctl-update-passphrase.txt   |   43 ++
 Documentation/ndctl/ndctl-wait-overwrite.txt      |   31 +
 Makefile.am                                       |    4 
 configure.ac                                      |   17 +
 contrib/nvdimm-security.conf                      |    1 
 ndctl.spec.in                                     |    3 
 ndctl/Makefile.am                                 |    5 
 ndctl/builtin.h                                   |    8 
 ndctl/dimm.c                                      |  232 ++++++++
 ndctl/kek.c                                       |  133 +++++
 ndctl/lib/Makefile.am                             |    8 
 ndctl/lib/dimm.c                                  |  183 +++++++
 ndctl/lib/keys.c                                  |  581 +++++++++++++++++++++
 ndctl/lib/libndctl.c                              |   31 +
 ndctl/lib/libndctl.sym                            |   16 +
 ndctl/lib/private.h                               |    1 
 ndctl/libndctl.h                                  |   79 +++
 ndctl/load-keys.c                                 |  257 +++++++++
 ndctl/ndctl.c                                     |    8 
 test/Makefile.am                                  |    4 
 test/security.sh                                  |  223 ++++++++
 util/json.c                                       |   17 +
 31 files changed, 2280 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/ndctl/intel-nvdimm-security.txt
 create mode 100644 Documentation/ndctl/ndctl-freeze-security.txt
 create mode 100644 Documentation/ndctl/ndctl-install-encrypt-key.txt
 create mode 100644 Documentation/ndctl/ndctl-load-keys.txt
 create mode 100644 Documentation/ndctl/ndctl-remove-passphrase.txt
 create mode 100644 Documentation/ndctl/ndctl-sanitize-dimm.txt
 create mode 100644 Documentation/ndctl/ndctl-setup-passphrase.txt
 create mode 100644 Documentation/ndctl/ndctl-update-passphrase.txt
 create mode 100644 Documentation/ndctl/ndctl-wait-overwrite.txt
 create mode 100644 contrib/nvdimm-security.conf
 create mode 100644 ndctl/kek.c
 create mode 100644 ndctl/lib/keys.c
 create mode 100644 ndctl/load-keys.c
 create mode 100755 test/security.sh

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

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

* [PATCH v9 01/13] ndctl: add support for display security state
  2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
@ 2019-01-18  2:38 ` Dave Jiang
  2019-01-18  2:38 ` [PATCH v9 02/13] ndctl: add command for ndctl to receive the key encryption key (master) Dave Jiang
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Dave Jiang @ 2019-01-18  2:38 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Adding libndctl API call for retrieving security state for a DIMM and also
adding support to ndctl list for displaying security state.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 Documentation/ndctl/ndctl-list.txt |    8 ++++++++
 ndctl/lib/dimm.c                   |   33 +++++++++++++++++++++++++++++++++
 ndctl/lib/libndctl.sym             |    1 +
 ndctl/libndctl.h                   |   11 +++++++++++
 util/json.c                        |   17 +++++++++++++++++
 5 files changed, 70 insertions(+)

diff --git a/Documentation/ndctl/ndctl-list.txt b/Documentation/ndctl/ndctl-list.txt
index e24c8f40..bdd69add 100644
--- a/Documentation/ndctl/ndctl-list.txt
+++ b/Documentation/ndctl/ndctl-list.txt
@@ -98,6 +98,14 @@ include::xable-region-options.txt[]
 -D::
 --dimms::
 	Include dimm info in the listing
+[verse]
+{
+  "dev":"nmem0",
+  "id":"cdab-0a-07e0-ffffffff",
+  "handle":0,
+  "phys_id":0,
+  "security:":"disabled"
+}
 
 -H::
 --health::
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
index 11a7efe9..712223fc 100644
--- a/ndctl/lib/dimm.c
+++ b/ndctl/lib/dimm.c
@@ -598,3 +598,36 @@ NDCTL_EXPORT unsigned long ndctl_dimm_get_available_labels(
 
 	return strtoul(buf, NULL, 0);
 }
+
+NDCTL_EXPORT enum ndctl_security_state ndctl_dimm_get_security(
+		struct ndctl_dimm *dimm)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	char *path = dimm->dimm_buf;
+	int len = dimm->buf_len;
+	char buf[64];
+	int rc;
+
+	if (snprintf(path, len, "%s/security", dimm->dimm_path) >= len) {
+		err(ctx, "%s: buffer too small!\n",
+				ndctl_dimm_get_devname(dimm));
+		return NDCTL_SECURITY_INVALID;
+	}
+
+	rc = sysfs_read_attr(ctx, path, buf);
+	if (rc < 0)
+		return NDCTL_SECURITY_INVALID;
+
+	if (strcmp(buf, "disabled") == 0)
+		return NDCTL_SECURITY_DISABLED;
+	else if (strcmp(buf, "unlocked") == 0)
+		return NDCTL_SECURITY_UNLOCKED;
+	else if (strcmp(buf, "locked") == 0)
+		return NDCTL_SECURITY_LOCKED;
+	else if (strcmp(buf, "frozen") == 0)
+		return NDCTL_SECURITY_FROZEN;
+	else if (strcmp(buf, "overwrite") == 0)
+		return NDCTL_SECURITY_OVERWRITE;
+
+	return NDCTL_SECURITY_INVALID;
+}
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index 275db92e..0888c824 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -390,4 +390,5 @@ LIBNDCTL_19 {
 global:
 	ndctl_cmd_xlat_firmware_status;
 	ndctl_cmd_submit_xlat;
+	ndctl_dimm_get_security;
 } LIBNDCTL_18;
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index e55a5932..e228c64f 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -684,6 +684,17 @@ int ndctl_dimm_fw_update_supported(struct ndctl_dimm *dimm);
 int ndctl_cmd_xlat_firmware_status(struct ndctl_cmd *cmd);
 int ndctl_cmd_submit_xlat(struct ndctl_cmd *cmd);
 
+enum ndctl_security_state {
+	NDCTL_SECURITY_INVALID = -1,
+	NDCTL_SECURITY_DISABLED = 0,
+	NDCTL_SECURITY_UNLOCKED,
+	NDCTL_SECURITY_LOCKED,
+	NDCTL_SECURITY_FROZEN,
+	NDCTL_SECURITY_OVERWRITE,
+};
+
+enum ndctl_security_state ndctl_dimm_get_security(struct ndctl_dimm *dimm);
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
diff --git a/util/json.c b/util/json.c
index 5c3424e2..9dc420ce 100644
--- a/util/json.c
+++ b/util/json.c
@@ -164,6 +164,7 @@ struct json_object *util_dimm_to_json(struct ndctl_dimm *dimm,
 	unsigned int handle = ndctl_dimm_get_handle(dimm);
 	unsigned short phys_id = ndctl_dimm_get_phys_id(dimm);
 	struct json_object *jobj;
+	enum ndctl_security_state sstate;
 
 	if (!jdimm)
 		return NULL;
@@ -243,6 +244,22 @@ struct json_object *util_dimm_to_json(struct ndctl_dimm *dimm,
 		json_object_object_add(jdimm, "flag_smart_event", jobj);
 	}
 
+	sstate = ndctl_dimm_get_security(dimm);
+	if (sstate == NDCTL_SECURITY_DISABLED)
+		jobj = json_object_new_string("disabled");
+	else if (sstate == NDCTL_SECURITY_UNLOCKED)
+		jobj = json_object_new_string("unlocked");
+	else if (sstate == NDCTL_SECURITY_LOCKED)
+		jobj = json_object_new_string("locked");
+	else if (sstate == NDCTL_SECURITY_FROZEN)
+		jobj = json_object_new_string("frozen");
+	else if (sstate == NDCTL_SECURITY_OVERWRITE)
+		jobj = json_object_new_string("overwrite");
+	else
+		jobj = NULL;
+	if (jobj)
+		json_object_object_add(jdimm, "security", jobj);
+
 	return jdimm;
  err:
 	json_object_put(jdimm);

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

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

* [PATCH v9 02/13] ndctl: add command for ndctl to receive the key encryption key (master)
  2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
  2019-01-18  2:38 ` [PATCH v9 01/13] ndctl: add support for display security state Dave Jiang
@ 2019-01-18  2:38 ` Dave Jiang
  2019-01-18 20:58   ` Verma, Vishal L
  2019-01-23 17:45   ` Dan Williams
  2019-01-18  2:38 ` [PATCH v9 03/13] ndctl: add passphrase update to ndctl Dave Jiang
                   ` (11 subsequent siblings)
  13 siblings, 2 replies; 24+ messages in thread
From: Dave Jiang @ 2019-01-18  2:38 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Add command that allows the user to provide the master encryption key name
to be installed in the key material directory where ndctl can refer to
for later security operations.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 Documentation/ndctl/Makefile.am                   |    3 
 Documentation/ndctl/ndctl-install-encrypt-key.txt |   31 +++++
 configure.ac                                      |    3 
 ndctl/Makefile.am                                 |    4 -
 ndctl/builtin.h                                   |    1 
 ndctl/kek.c                                       |  133 +++++++++++++++++++++
 ndctl/lib/libndctl.c                              |   31 +++++
 ndctl/lib/libndctl.sym                            |    1 
 ndctl/lib/private.h                               |    1 
 ndctl/libndctl.h                                  |    1 
 ndctl/ndctl.c                                     |    1 
 11 files changed, 208 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/ndctl/ndctl-install-encrypt-key.txt
 create mode 100644 ndctl/kek.c

diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am
index a30b139b..7cb7bd6b 100644
--- a/Documentation/ndctl/Makefile.am
+++ b/Documentation/ndctl/Makefile.am
@@ -47,7 +47,8 @@ man1_MANS = \
 	ndctl-inject-smart.1 \
 	ndctl-update-firmware.1 \
 	ndctl-list.1 \
-	ndctl-monitor.1
+	ndctl-monitor.1 \
+	ndctl-install-encrypt-key.1
 
 CLEANFILES = $(man1_MANS)
 
diff --git a/Documentation/ndctl/ndctl-install-encrypt-key.txt b/Documentation/ndctl/ndctl-install-encrypt-key.txt
new file mode 100644
index 00000000..d00463e3
--- /dev/null
+++ b/Documentation/ndctl/ndctl-install-encrypt-key.txt
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+
+ndctl-install-encrypt-key(1)
+============================
+
+NAME
+----
+ndctl-install-encrypt-key - store encryption key name for nvdimm bus
+
+SYNOPSIS
+--------
+[verse]
+'ndctl install-encrypt-key <ndbus0> [<ndbus1>..<ndbusN>] [-k <master encryption key] [<options>]
+
+Take the provided master encryption key handle and store it in a file that
+A file would be created for the designated bus provider.
+i.e. /etc/ndctl/keys/nfit_test.0.kek
+The command only succeeds on bus(es) that contain nvdimms with security support.
+
+OPTIONS
+-------
+-k::
+--kek=::
+	Key encryption key (master key) handle. The key handle has the format
+	of <key type>:<key name>. i.e. trusted:nvdimm-master.
+
+-v::
+--verbose::
+	Turn on debug output
+
+include::../copyright.txt[]
diff --git a/configure.ac b/configure.ac
index a02a2d80..61e91e0a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -159,6 +159,9 @@ ndctl_monitorconf=monitor.conf
 AC_SUBST([ndctl_monitorconfdir])
 AC_SUBST([ndctl_monitorconf])
 
+ndctl_keysdir=${sysconfdir}/ndctl/keys
+AC_SUBST([ndctl_keysdir])
+
 my_CFLAGS="\
 -Wall \
 -Wchar-subscripts \
diff --git a/ndctl/Makefile.am b/ndctl/Makefile.am
index 97de1814..e412dbf7 100644
--- a/ndctl/Makefile.am
+++ b/ndctl/Makefile.am
@@ -8,6 +8,7 @@ config.h: Makefile.am
 	$(AM_V_GEN) echo "/* Autogenerated by ndctl/Makefile.am */" >$@
 	$(AM_V_GEN) echo '#define NDCTL_CONF_FILE \
 		"$(ndctl_monitorconfdir)/$(ndctl_monitorconf)"' >>$@
+	$(AM_V_GEN) echo '#define NDCTL_KEYS_DIR  "$(ndctl_keysdir)"' >>$@
 
 ndctl_SOURCES = ndctl.c \
 		bus.c \
@@ -23,7 +24,8 @@ ndctl_SOURCES = ndctl.c \
 		util/json-firmware.c \
 		inject-error.c \
 		inject-smart.c \
-		monitor.c
+		monitor.c \
+		kek.c
 
 if ENABLE_DESTRUCTIVE
 ndctl_SOURCES += ../test/blk_namespaces.c \
diff --git a/ndctl/builtin.h b/ndctl/builtin.h
index 17300df0..4af34f04 100644
--- a/ndctl/builtin.h
+++ b/ndctl/builtin.h
@@ -32,4 +32,5 @@ int cmd_bat(int argc, const char **argv, struct ndctl_ctx *ctx);
 #endif
 int cmd_update_firmware(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_inject_smart(int argc, const char **argv, struct ndctl_ctx *ctx);
+int cmd_install_kek(int argc, const char **argv, struct ndctl_ctx *ctx);
 #endif /* _NDCTL_BUILTIN_H_ */
diff --git a/ndctl/kek.c b/ndctl/kek.c
new file mode 100644
index 00000000..1cb1555e
--- /dev/null
+++ b/ndctl/kek.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2019 Intel Corporation. All rights reserved. */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <util/json.h>
+#include <util/filter.h>
+#include <util/log.h>
+#include <json-c/json.h>
+#include <ndctl/config.h>
+#include <ndctl/libndctl.h>
+#include <util/parse-options.h>
+#include <ccan/array_size/array_size.h>
+
+#include <ndctl.h>
+
+static struct parameters {
+	const char *kek;
+	bool verbose;
+} param;
+
+static int store_kek(const char *provider, const char *kek)
+{
+	char path[PATH_MAX];
+	FILE *fp;
+	ssize_t rc, wrote = 0;
+	int size = strlen(kek);
+
+	rc = sprintf(path, "%s/%s.kek", NDCTL_KEYS_DIR, provider);
+	if (rc < 0) {
+		perror("sprintf kek path failed");
+		return rc;
+	}
+
+	fp = fopen(path, "w+");
+	if (!fp) {
+		fprintf(stderr, "Opening file %s failed: %s\n",
+				path, strerror(errno));
+		return -errno;
+	}
+
+	do {
+		rc = fwrite(kek + wrote, 1, size - wrote, fp);
+		if (rc < 0) {
+			fprintf(stderr, "writing file %s failed: %s\n",
+					path, strerror(errno));
+			fclose(fp);
+			return -errno;
+		}
+		wrote += rc;
+	} while (wrote != size);
+
+	fclose(fp);
+	printf("key handle %s installed to %s\n", kek, path);
+	return 0;
+}
+
+int cmd_install_kek(int argc, const char **argv, struct ndctl_ctx *ctx)
+{
+	const struct option options[] = {
+		OPT_BOOLEAN('v',"verbose", &param.verbose, "turn on debug"),
+		OPT_STRING('k', "kek", &param.kek, "kek",
+				"Key encription key (master)"),
+		OPT_END(),
+	};
+	const char * const u[] = {
+		"ndctl intall-encrypt-key <ndbus0> [<ndbus1>..<ndbusN>] [-k <master encryption key>]",
+		NULL
+	};
+	int i, rc;
+	bool all = false;
+
+	argc = parse_options(argc, argv, options, u, 0);
+
+	if (argc == 0) {
+		usage_with_options(u, options);
+		return -EINVAL;
+	}
+
+	if (!param.kek) {
+		usage_with_options(u, options);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < argc; i++) {
+		if (strcmp(argv[i], "all") == 0) {
+			argv[0] = "all";
+			argc = 1;
+			all = true;
+			break;
+		}
+	}
+
+	if (param.verbose)
+		ndctl_set_log_priority(ctx, LOG_DEBUG);
+
+	for (i = 0; i < argc; i++) {
+		struct ndctl_bus *bus;
+		struct ndctl_dimm *dimm;
+		bool security = false;
+
+		ndctl_bus_foreach(ctx, bus) {
+			if (!util_bus_filter(bus, argv[i]) && !all)
+				continue;
+
+			ndctl_dimm_foreach(bus, dimm) {
+				if (ndctl_dimm_get_security(dimm) >= 0) {
+					security = true;
+					break;
+				}
+			}
+
+			if (!security)
+				continue;
+
+			rc = store_kek(ndctl_bus_get_provider(bus),
+					param.kek);
+			if (rc < 0)
+				fprintf(stderr, "store kek %s for bus %s failed\n",
+						param.kek, ndctl_bus_get_devname(bus));
+
+		}
+	}
+
+	return 0;
+}
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 830b7913..b255eb1b 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -36,6 +36,7 @@
 #include <ndctl/namespace.h>
 #include <daxctl/libdaxctl.h>
 #include <ndctl/libndctl-nfit.h>
+#include <ndctl/config.h>
 #include "private.h"
 
 static uuid_t null_uuid;
@@ -620,6 +621,7 @@ static void free_bus(struct ndctl_bus *bus, struct list_head *head)
 	free(bus->bus_buf);
 	free(bus->wait_probe_path);
 	free(bus->scrub_path);
+	free(bus->kek_handle);
 	free(bus);
 }
 
@@ -812,6 +814,28 @@ static void parse_dimm_flags(struct ndctl_dimm *dimm, char *flags)
 				ndctl_dimm_get_devname(dimm), flags);
 }
 
+static int bus_retrieve_kek_handle(struct ndctl_bus *bus)
+{
+	char path[PATH_MAX];
+	FILE *fp;
+	ssize_t rc;
+
+	rc = sprintf(path, "%s/%s.kek", NDCTL_KEYS_DIR,
+			ndctl_bus_get_provider(bus));
+	if (rc < 0)
+		return -errno;
+
+	fp = fopen(path, "r");
+	if (!fp)
+		return -errno;
+
+	if (fscanf(fp, "%ms", &bus->kek_handle) == EOF)
+		return -errno;
+
+	fclose(fp);
+	return 0;
+}
+
 static void *add_bus(void *parent, int id, const char *ctl_base)
 {
 	char buf[SYSFS_ATTR_SIZE];
@@ -890,6 +914,8 @@ static void *add_bus(void *parent, int id, const char *ctl_base)
 			return bus_dup;
 		}
 
+	bus_retrieve_kek_handle(bus);
+
 	list_add(&ctx->busses, &bus->list);
 	free(path);
 
@@ -5396,3 +5422,8 @@ NDCTL_EXPORT struct daxctl_region *ndctl_dax_get_daxctl_region(
 
 	return dax->region;
 }
+
+NDCTL_EXPORT const char *ndctl_bus_get_kek_handle(struct ndctl_bus *bus)
+{
+	return bus->kek_handle;
+}
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index 0888c824..6d5e6606 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -391,4 +391,5 @@ global:
 	ndctl_cmd_xlat_firmware_status;
 	ndctl_cmd_submit_xlat;
 	ndctl_dimm_get_security;
+	ndctl_bus_get_kek_handle;
 } LIBNDCTL_18;
diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h
index a387b0b5..a860f0db 100644
--- a/ndctl/lib/private.h
+++ b/ndctl/lib/private.h
@@ -172,6 +172,7 @@ struct ndctl_bus {
 	char *scrub_path;
 	unsigned long cmd_mask;
 	unsigned long nfit_dsm_mask;
+	char *kek_handle;
 };
 
 /**
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index e228c64f..b0cc4543 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -694,6 +694,7 @@ enum ndctl_security_state {
 };
 
 enum ndctl_security_state ndctl_dimm_get_security(struct ndctl_dimm *dimm);
+const char *ndctl_bus_get_kek_handle(struct ndctl_bus *bus);
 
 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/ndctl/ndctl.c b/ndctl/ndctl.c
index b01594e0..bd11ec03 100644
--- a/ndctl/ndctl.c
+++ b/ndctl/ndctl.c
@@ -90,6 +90,7 @@ static struct cmd_struct commands[] = {
 	{ "start-scrub", { cmd_start_scrub } },
 	{ "list", { cmd_list } },
 	{ "monitor", { cmd_monitor } },
+	{ "install-encrypt-key", { cmd_install_kek } },
 	{ "help", { cmd_help } },
 	#ifdef ENABLE_TEST
 	{ "test", { cmd_test } },

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

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

* [PATCH v9 03/13] ndctl: add passphrase update to ndctl
  2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
  2019-01-18  2:38 ` [PATCH v9 01/13] ndctl: add support for display security state Dave Jiang
  2019-01-18  2:38 ` [PATCH v9 02/13] ndctl: add command for ndctl to receive the key encryption key (master) Dave Jiang
@ 2019-01-18  2:38 ` Dave Jiang
  2019-01-23 18:21   ` Dan Williams
  2019-01-18  2:38 ` [PATCH v9 04/13] ndctl: add disable security support Dave Jiang
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 24+ messages in thread
From: Dave Jiang @ 2019-01-18  2:38 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Add API call for triggering sysfs knob to update the security for a DIMM
in libndctl. Also add the ndctl "update-passphrase" to trigger the
operation.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 Documentation/ndctl/Makefile.am                 |    4 
 Documentation/ndctl/ndctl-setup-passphrase.txt  |   34 ++
 Documentation/ndctl/ndctl-update-passphrase.txt |   36 ++
 configure.ac                                    |   14 +
 ndctl.spec.in                                   |    2 
 ndctl/builtin.h                                 |    2 
 ndctl/dimm.c                                    |   68 +++-
 ndctl/lib/Makefile.am                           |    8 
 ndctl/lib/dimm.c                                |   24 +
 ndctl/lib/keys.c                                |  387 +++++++++++++++++++++++
 ndctl/lib/libndctl.sym                          |    3 
 ndctl/libndctl.h                                |   31 ++
 ndctl/ndctl.c                                   |    2 
 13 files changed, 603 insertions(+), 12 deletions(-)
 create mode 100644 Documentation/ndctl/ndctl-setup-passphrase.txt
 create mode 100644 Documentation/ndctl/ndctl-update-passphrase.txt
 create mode 100644 ndctl/lib/keys.c

diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am
index 7cb7bd6b..7b155d4d 100644
--- a/Documentation/ndctl/Makefile.am
+++ b/Documentation/ndctl/Makefile.am
@@ -48,7 +48,9 @@ man1_MANS = \
 	ndctl-update-firmware.1 \
 	ndctl-list.1 \
 	ndctl-monitor.1 \
-	ndctl-install-encrypt-key.1
+	ndctl-install-encrypt-key.1 \
+	ndctl-setup-passphrase.1 \
+	ndctl-update-passphrase.1
 
 CLEANFILES = $(man1_MANS)
 
diff --git a/Documentation/ndctl/ndctl-setup-passphrase.txt b/Documentation/ndctl/ndctl-setup-passphrase.txt
new file mode 100644
index 00000000..7d8a1abb
--- /dev/null
+++ b/Documentation/ndctl/ndctl-setup-passphrase.txt
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+
+ndctl-setup-passphrase(1)
+=========================
+
+NAME
+----
+ndctl-setup-passphrase - setup and enable the security passphrase for an NVDIMM
+
+SYNOPSIS
+--------
+[verse]
+'ndctl setup-passphrase' <nmem0> [<nmem1>..<nmemN>] [<options>]
+
+DESCRIPTION
+-----------
+Enable the security passphrase for one or more NVDIMMs.
+
+Prerequisite for command to succeed:
+1. The master key has already been loaded into the user key ring.
+2. ndctl install-encrypt-key has been executed successfully.
+
+The encrypted key blobs will be created by ndctl in /etc/ndctl/keys directory
+with the file name of "nvdimm_<dimm unique id>_<hostname>.blob".
+
+The command will fail if the nvdimm key is already in the user key ring and/or
+the key blob already resides in /etc/nvdimm.
+
+OPTIONS
+-------
+<dimm>::
+include::xable-dimm-options.txt[]
+
+include::../copyright.txt[]
diff --git a/Documentation/ndctl/ndctl-update-passphrase.txt b/Documentation/ndctl/ndctl-update-passphrase.txt
new file mode 100644
index 00000000..ff49ae2d
--- /dev/null
+++ b/Documentation/ndctl/ndctl-update-passphrase.txt
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+
+ndctl-update-passphrase(1)
+==========================
+
+NAME
+----
+ndctl-update-passphrase - update the security passphrase for an NVDIMM
+
+SYNOPSIS
+--------
+[verse]
+'ndctl update-passphrase' <nmem0> [<nmem1>..<nmemN>] [<options>]
+
+DESCRIPTION
+-----------
+Update the security passphrase for one or more NVDIMMs.
+Prerequisite for command to succeed:
+1. The master key has already been loaded into the user key ring.
+2. ndctl install-encrypt-key has been executed successfully.
+3. setup-passphrase has successfully been executed previously on the NVDIMM
+   or NVDIMM has been successfully unlocked by the kernel.
+
+The updated key blobs will be created by ndctl in /etc/ndctl/keys directory
+with the file name of "nvdimm_<dimm unique id>_<hostname>.blob".
+
+OPTIONS
+-------
+<dimm>::
+include::xable-dimm-options.txt[]
+
+include::../copyright.txt[]
+
+SEE ALSO:
+---------
+linkndctl:ndctl-setup-passphrase[1]
diff --git a/configure.ac b/configure.ac
index 61e91e0a..3c909cd0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -154,11 +154,25 @@ fi
 AC_SUBST([systemd_unitdir])
 AM_CONDITIONAL([ENABLE_SYSTEMD_UNITS], [test "x$with_systemd" = "xyes"])
 
+
 ndctl_monitorconfdir=${sysconfdir}/ndctl
 ndctl_monitorconf=monitor.conf
 AC_SUBST([ndctl_monitorconfdir])
 AC_SUBST([ndctl_monitorconf])
 
+AC_ARG_WITH([keyutils],
+	    AS_HELP_STRING([--with-keyutils],
+			[Enable keyutils functionality (security).  @<:@default=yes@:>@]), [], [with_keyutils=yes])
+
+if test "x$with_keyutils" = "xyes"; then
+	AC_CHECK_HEADERS([keyutils.h],,[
+		AC_MSG_ERROR([keyutils.h not found, consider installing
+			      keyutils-libs-devel.])
+		])
+fi
+AS_IF([test "x$with_keyutils" = "xyes"],
+	[AC_DEFINE([ENABLE_KEYUTILS], [1], [Enable keyutils support])])
+AM_CONDITIONAL([ENABLE_KEYUTILS], [test "x$with_keyutils" = "xyes"])
 ndctl_keysdir=${sysconfdir}/ndctl/keys
 AC_SUBST([ndctl_keysdir])
 
diff --git a/ndctl.spec.in b/ndctl.spec.in
index bc4d65c1..3956d81d 100644
--- a/ndctl.spec.in
+++ b/ndctl.spec.in
@@ -21,6 +21,7 @@ BuildRequires:	pkgconfig(uuid)
 BuildRequires:	pkgconfig(json-c)
 BuildRequires:	pkgconfig(bash-completion)
 BuildRequires:	pkgconfig(systemd)
+BuildRequires:	keyutils-libs-devel
 
 %description
 Utility library for managing the "libnvdimm" subsystem.  The "libnvdimm"
@@ -118,6 +119,7 @@ make check
 %{_mandir}/man1/ndctl*
 %{bashcompdir}/
 %{_unitdir}/ndctl-monitor.service
+%{_sysconfdir}/ndctl/keys/
 
 %config(noreplace) %{_sysconfdir}/ndctl/monitor.conf
 
diff --git a/ndctl/builtin.h b/ndctl/builtin.h
index 4af34f04..33c04983 100644
--- a/ndctl/builtin.h
+++ b/ndctl/builtin.h
@@ -33,4 +33,6 @@ int cmd_bat(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_update_firmware(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_inject_smart(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_install_kek(int argc, const char **argv, struct ndctl_ctx *ctx);
+int cmd_passphrase_setup(int argc, const char **argv, struct ndctl_ctx *ctx);
+int cmd_passphrase_update(int argc, const char **argv, struct ndctl_ctx *ctx);
 #endif /* _NDCTL_BUILTIN_H_ */
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index c717beeb..bea7cf62 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -40,6 +40,18 @@ struct action_context {
 	struct update_context update;
 };
 
+static struct parameters {
+	const char *bus;
+	const char *outfile;
+	const char *infile;
+	const char *labelversion;
+	bool force;
+	bool json;
+	bool verbose;
+} param = {
+	.labelversion = "1.1",
+};
+
 static int action_disable(struct ndctl_dimm *dimm, struct action_context *actx)
 {
 	if (ndctl_dimm_is_active(dimm)) {
@@ -824,17 +836,29 @@ static int action_update(struct ndctl_dimm *dimm, struct action_context *actx)
 	return rc;
 }
 
-static struct parameters {
-	const char *bus;
-	const char *outfile;
-	const char *infile;
-	const char *labelversion;
-	bool force;
-	bool json;
-	bool verbose;
-} param = {
-	.labelversion = "1.1",
-};
+static int action_key_enable(struct ndctl_dimm *dimm,
+		struct action_context *actx)
+{
+	if (ndctl_dimm_get_security(dimm) < 0) {
+		error("%s: security operation not supported\n",
+				ndctl_dimm_get_devname(dimm));
+		return -EOPNOTSUPP;
+	}
+
+	return ndctl_dimm_enable_key(dimm);
+}
+
+static int action_key_update(struct ndctl_dimm *dimm,
+		struct action_context *actx)
+{
+	if (ndctl_dimm_get_security(dimm) < 0) {
+		error("%s: security operation not supported\n",
+				ndctl_dimm_get_devname(dimm));
+		return -EOPNOTSUPP;
+	}
+
+	return ndctl_dimm_update_key(dimm);
+}
 
 static int __action_init(struct ndctl_dimm *dimm,
 		enum ndctl_namespace_version version, int chk_only)
@@ -1181,3 +1205,25 @@ int cmd_update_firmware(int argc, const char **argv, struct ndctl_ctx *ctx)
 			count > 1 ? "s" : "");
 	return count >= 0 ? 0 : EXIT_FAILURE;
 }
+
+int cmd_passphrase_update(int argc, const char **argv, struct ndctl_ctx *ctx)
+{
+	int count = dimm_action(argc, argv, ctx, action_key_update,
+			base_options,
+			"ndctl update-passphrase <nmem0> [<nmem1>..<nmemN>] [<options>]");
+
+	fprintf(stderr, "passphrase updated for %d nmem%s.\n", count >= 0 ? count : 0,
+			count > 1 ? "s" : "");
+	return count >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_passphrase_setup(int argc, const char **argv, struct ndctl_ctx *ctx)
+{
+	int count = dimm_action(argc, argv, ctx, action_key_enable,
+			base_options,
+			"ndctl setup-passphrase <nmem0> [<nmem1>..<nmemN>] [<options>]");
+
+	fprintf(stderr, "passphrase enabled for %d nmem%s.\n", count >= 0 ? count : 0,
+			count > 1 ? "s" : "");
+	return count >= 0 ? 0 : EXIT_FAILURE;
+}
diff --git a/ndctl/lib/Makefile.am b/ndctl/lib/Makefile.am
index 77970399..6b9bde43 100644
--- a/ndctl/lib/Makefile.am
+++ b/ndctl/lib/Makefile.am
@@ -24,12 +24,20 @@ libndctl_la_SOURCES =\
 	firmware.c \
 	libndctl.c
 
+if ENABLE_KEYUTILS
+libndctl_la_SOURCES += keys.c
+endif
+
 libndctl_la_LIBADD =\
 	../../daxctl/lib/libdaxctl.la \
 	$(UDEV_LIBS) \
 	$(UUID_LIBS) \
 	$(KMOD_LIBS)
 
+if ENABLE_KEYUTILS
+libndctl_la_LIBADD += -lkeyutils
+endif
+
 EXTRA_DIST += libndctl.sym
 
 libndctl_la_LDFLAGS = $(AM_LDFLAGS) \
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
index 712223fc..72b6f66c 100644
--- a/ndctl/lib/dimm.c
+++ b/ndctl/lib/dimm.c
@@ -631,3 +631,27 @@ NDCTL_EXPORT enum ndctl_security_state ndctl_dimm_get_security(
 
 	return NDCTL_SECURITY_INVALID;
 }
+
+static int write_security(struct ndctl_dimm *dimm, const char *cmd)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	char *path = dimm->dimm_buf;
+	int len = dimm->buf_len;
+
+	if (snprintf(path, len, "%s/security", dimm->dimm_path) >= len) {
+		err(ctx, "%s: buffer too small!\n",
+				ndctl_dimm_get_devname(dimm));
+		return -ERANGE;
+	}
+
+	return sysfs_write_attr(ctx, path, cmd);
+}
+
+NDCTL_EXPORT int ndctl_dimm_update_passphrase(struct ndctl_dimm *dimm,
+		long ckey, long nkey)
+{
+	char buf[SYSFS_ATTR_SIZE];
+
+	sprintf(buf, "update %ld %ld\n", ckey, nkey);
+	return write_security(dimm, buf);
+}
diff --git a/ndctl/lib/keys.c b/ndctl/lib/keys.c
new file mode 100644
index 00000000..1ae0ff02
--- /dev/null
+++ b/ndctl/lib/keys.c
@@ -0,0 +1,387 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2018 Intel Corporation. All rights reserved. */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <keyutils.h>
+#include <syslog.h>
+
+#include <ndctl.h>
+#include <ndctl/libndctl.h>
+#include "private.h"
+
+static int get_key_path(struct ndctl_dimm *dimm, char *path,
+		enum ndctl_key_type key_type)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	char hostname[HOST_NAME_MAX];
+	int rc;
+
+	rc = gethostname(hostname, HOST_NAME_MAX);
+	if (rc < 0) {
+		err(ctx, "gethostname: %s\n", strerror(errno));
+		return -errno;
+	}
+
+	if (key_type == ND_USER_OLD_KEY) {
+		rc = sprintf(path, "%s/nvdimmold_%s_%s.blob",
+				NDCTL_KEYS_DIR,
+				ndctl_dimm_get_unique_id(dimm),
+				hostname);
+	} else {
+		rc = sprintf(path, "%s/nvdimm_%s_%s.blob",
+				NDCTL_KEYS_DIR,
+				ndctl_dimm_get_unique_id(dimm),
+				hostname);
+	}
+
+	if (rc < 0) {
+		err(ctx, "error setting path: %s\n", strerror(errno));
+		return -errno;
+	}
+
+	return 0;
+}
+
+static int get_key_desc(struct ndctl_dimm *dimm, char *desc,
+		enum ndctl_key_type key_type)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	int rc;
+
+	if (key_type == ND_USER_OLD_KEY)
+		rc = sprintf(desc, "nvdimm-old:%s",
+				ndctl_dimm_get_unique_id(dimm));
+	else
+		rc = sprintf(desc, "nvdimm:%s",
+				ndctl_dimm_get_unique_id(dimm));
+
+	if (rc < 0) {
+		err(ctx, "error setting key description: %s\n",
+				strerror(errno));
+		return -errno;
+	}
+
+	return 0;
+}
+
+static char *load_key_blob(struct ndctl_ctx *ctx, const char *path, int *size)
+{
+	struct stat st;
+	FILE *bfile = NULL;
+	ssize_t read;
+	int rc;
+	char *blob, *pl;
+	char prefix[] = "load ";
+
+	rc = stat(path, &st);
+	if (rc < 0) {
+		err(ctx, "stat: %s\n", strerror(errno));
+		return NULL;
+	}
+	if ((st.st_mode & S_IFMT) != S_IFREG) {
+		err(ctx, "%s not a regular file\n", path);
+		return NULL;
+	}
+
+	if (st.st_size == 0 || st.st_size > 4096) {
+		err(ctx, "Invalid blob file size\n");
+		return NULL;
+	}
+
+	*size = st.st_size + sizeof(prefix) - 1;
+	blob = malloc(*size);
+	if (!blob) {
+		err(ctx, "Unable to allocate memory for blob\n");
+		return NULL;
+	}
+
+	bfile = fopen(path, "r");
+	if (!bfile) {
+		err(ctx, "Unable to open %s: %s\n", path, strerror(errno));
+		free(blob);
+		return NULL;
+	}
+
+	memcpy(blob, prefix, sizeof(prefix) - 1);
+	pl = blob + sizeof(prefix) - 1;
+	read = fread(pl, st.st_size, 1, bfile);
+	if (read < 0) {
+		err(ctx, "Failed to read from blob file: %s\n",
+				strerror(errno));
+		free(blob);
+		fclose(bfile);
+		return NULL;
+	}
+
+	fclose(bfile);
+	return blob;
+}
+
+static key_serial_t dimm_check_key(struct ndctl_dimm *dimm,
+		enum ndctl_key_type key_type)
+{
+	char desc[ND_KEY_DESC_SIZE];
+	int rc;
+
+	rc = get_key_desc(dimm, desc, key_type);
+	if (rc < 0)
+		return rc;
+
+	return keyctl_search(KEY_SPEC_USER_KEYRING, "encrypted", desc, 0);
+}
+
+static key_serial_t dimm_create_key(struct ndctl_dimm *dimm)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	char desc[ND_KEY_DESC_SIZE];
+	char path[PATH_MAX];
+	char cmd[ND_KEY_CMD_SIZE];
+	key_serial_t key;
+	void *buffer;
+	int rc;
+	ssize_t size;
+	FILE *fp;
+	ssize_t wrote;
+	struct stat st;
+
+	if (ndctl_dimm_is_active(dimm)) {
+		err(ctx, "regions active on %s, op failed\n",
+				ndctl_dimm_get_devname(dimm));
+		return -EBUSY;
+	}
+
+	rc = get_key_desc(dimm, desc, ND_USER_KEY);
+	if (rc < 0)
+		return rc;
+
+	/* make sure it's not already in the key ring */
+	key = keyctl_search(KEY_SPEC_USER_KEYRING, "encrypted", desc, 0);
+	if (key > 0) {
+		err(ctx, "Error: key already present in user keyring\n");
+		return -EEXIST;
+	}
+
+	rc = get_key_path(dimm, path, ND_USER_KEY);
+	if (rc < 0)
+		return rc;
+
+	rc = stat(path, &st);
+	if (rc == 0) {
+		err(ctx, "%s already exists!\n", path);
+		return -EEXIST;
+	}
+
+	rc = sprintf(cmd, "new enc32 %s 32",
+			ndctl_bus_get_kek_handle(ndctl_dimm_get_bus(dimm)));
+	if (rc < 0) {
+		err(ctx, "sprintf: %s\n", strerror(errno));
+		return -errno;
+	}
+
+	key = add_key("encrypted", desc, cmd, strlen(cmd),
+			KEY_SPEC_USER_KEYRING);
+	if (key < 0) {
+		err(ctx, "add_key failed: %s\n", strerror(errno));
+		return -errno;
+	}
+
+	size = keyctl_read_alloc(key, &buffer);
+	if (size < 0) {
+		err(ctx, "keyctl_read_alloc failed: %s\n", strerror(errno));
+		keyctl_unlink(key, KEY_SPEC_USER_KEYRING);
+		return rc;
+	}
+
+	fp = fopen(path, "w");
+	if (!fp) {
+		rc = -errno;
+		err(ctx, "Unable to open file %s: %s\n",
+				path, strerror(errno));
+		free(buffer);
+		return rc;
+	}
+
+	 wrote = fwrite(buffer, 1, size, fp);
+	 if (wrote != size) {
+		 if (wrote == -1)
+			 rc = -errno;
+		 else
+			 rc = -EIO;
+		 err(ctx, "Failed to write to %s: %s\n",
+				 path, strerror(-rc));
+		 free(buffer);
+		 return rc;
+	 }
+
+	 fclose(fp);
+	 free(buffer);
+	 return key;
+}
+
+static key_serial_t dimm_load_key(struct ndctl_dimm *dimm,
+		enum ndctl_key_type key_type)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	key_serial_t key;
+	char desc[ND_KEY_DESC_SIZE];
+	char path[PATH_MAX];
+	int rc;
+	char *blob;
+	int size;
+
+	if (ndctl_dimm_is_active(dimm)) {
+		err(ctx, "regions active on %s, op failed\n",
+				ndctl_dimm_get_devname(dimm));
+		return -EBUSY;
+	}
+
+	rc = get_key_desc(dimm, desc, key_type);
+	if (rc < 0)
+		return rc;
+
+	rc = get_key_path(dimm, path, key_type);
+	if (rc < 0)
+		return rc;
+
+	blob = load_key_blob(ctx, path, &size);
+	if (!blob)
+		return -ENOMEM;
+
+	key = add_key("encrypted", desc, blob, size, KEY_SPEC_USER_KEYRING);
+	free(blob);
+	if (key < 0) {
+		err(ctx, "add_key failed: %s\n", strerror(errno));
+		return -errno;
+	}
+
+	return key;
+}
+
+/*
+ * The function will check to see if the existing key is there and remove
+ * from user key ring if it is. Rename the existing key blob to old key
+ * blob, and then attempt to inject the key as old key into the user key
+ * ring.
+ */
+static key_serial_t move_key_to_old(struct ndctl_dimm *dimm)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	int rc;
+	key_serial_t key;
+	char old_path[PATH_MAX];
+	char new_path[PATH_MAX];
+
+	if (ndctl_dimm_is_active(dimm)) {
+		err(ctx, "regions active on %s, op failed\n",
+				ndctl_dimm_get_devname(dimm));
+		return -EBUSY;
+	}
+
+	key = dimm_check_key(dimm, ND_USER_KEY);
+	if (key > 0)
+		keyctl_unlink(key, KEY_SPEC_USER_KEYRING);
+
+	rc = get_key_path(dimm, old_path, ND_USER_KEY);
+	if (rc < 0)
+		return rc;
+
+	rc = get_key_path(dimm, new_path, ND_USER_OLD_KEY);
+	if (rc < 0)
+		return rc;
+
+	rc = rename(old_path, new_path);
+	if (rc < 0) {
+		err(ctx, "rename failed from %s to %s: %s\n",
+				old_path, new_path, strerror(errno));
+		return -errno;
+	}
+
+	return dimm_load_key(dimm, ND_USER_OLD_KEY);
+}
+
+static int dimm_remove_key(struct ndctl_dimm *dimm,
+		enum ndctl_key_type key_type)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	key_serial_t key;
+	char path[PATH_MAX];
+	int rc;
+
+	key = dimm_check_key(dimm, key_type);
+	if (key > 0)
+		keyctl_unlink(key, KEY_SPEC_USER_KEYRING);
+
+	rc = get_key_path(dimm, path, key_type);
+	if (rc < 0)
+		return rc;
+
+	rc = unlink(path);
+	if (rc < 0) {
+		err(ctx, "delete file %s failed: %s\n",
+				path, strerror(errno));
+		return -errno;
+	}
+
+	return 0;
+}
+
+NDCTL_EXPORT int ndctl_dimm_enable_key(struct ndctl_dimm *dimm)
+{
+	key_serial_t key;
+	int rc;
+
+	key = dimm_create_key(dimm);
+	if (key < 0)
+		return key;
+
+	rc = ndctl_dimm_update_passphrase(dimm, 0, key);
+	if (rc < 0) {
+		dimm_remove_key(dimm, ND_USER_KEY);
+		return rc;
+	}
+
+	return 0;
+}
+
+NDCTL_EXPORT int ndctl_dimm_update_key(struct ndctl_dimm *dimm)
+{
+	int rc;
+	key_serial_t old_key, new_key;
+
+	/*
+	 * 1. check if current key is loaded and remove
+	 * 2. move current key blob to old key blob
+	 * 3. load old key blob
+	 * 4. trigger change key with old and new key
+	 * 5. remove old key
+	 * 6. remove old key blob
+	 */
+	old_key = move_key_to_old(dimm);
+	if (old_key < 0)
+		return old_key;
+
+	new_key = dimm_create_key(dimm);
+	/* need to create new key here */
+	if (new_key < 0) {
+		new_key = dimm_load_key(dimm, ND_USER_KEY);
+		if (new_key < 0)
+			return new_key;
+	}
+
+	rc = ndctl_dimm_update_passphrase(dimm, old_key, new_key);
+	if (rc < 0)
+		return rc;
+
+	rc = dimm_remove_key(dimm, ND_USER_OLD_KEY);
+	if (rc < 0)
+		return rc;
+
+	return 0;
+}
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index 6d5e6606..ce05d604 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -392,4 +392,7 @@ global:
 	ndctl_cmd_submit_xlat;
 	ndctl_dimm_get_security;
 	ndctl_bus_get_kek_handle;
+	ndctl_dimm_enable_key;
+	ndctl_dimm_update_key;
+	ndctl_dimm_update_passphrase;
 } LIBNDCTL_18;
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index b0cc4543..727dedcf 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -19,6 +19,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <limits.h>
+#include <keyutils.h>
 
 #ifdef HAVE_UUID
 #include <uuid/uuid.h>
@@ -681,9 +682,14 @@ enum ND_FW_STATUS ndctl_cmd_fw_xlat_firmware_status(struct ndctl_cmd *cmd);
 struct ndctl_cmd *ndctl_dimm_cmd_new_ack_shutdown_count(struct ndctl_dimm *dimm);
 int ndctl_dimm_fw_update_supported(struct ndctl_dimm *dimm);
 
+
 int ndctl_cmd_xlat_firmware_status(struct ndctl_cmd *cmd);
 int ndctl_cmd_submit_xlat(struct ndctl_cmd *cmd);
 
+#define ND_PASSPHRASE_SIZE	32
+#define ND_KEY_DESC_LEN	22
+#define ND_KEY_DESC_PREFIX  7
+
 enum ndctl_security_state {
 	NDCTL_SECURITY_INVALID = -1,
 	NDCTL_SECURITY_DISABLED = 0,
@@ -695,6 +701,31 @@ enum ndctl_security_state {
 
 enum ndctl_security_state ndctl_dimm_get_security(struct ndctl_dimm *dimm);
 const char *ndctl_bus_get_kek_handle(struct ndctl_bus *bus);
+int ndctl_dimm_update_passphrase(struct ndctl_dimm *dimm,
+		long ckey, long nkey);
+
+enum ndctl_key_type {
+	ND_USER_KEY,
+	ND_USER_OLD_KEY,
+};
+
+#ifdef ENABLE_KEYUTILS
+int ndctl_dimm_enable_key(struct ndctl_dimm *dimm);
+int ndctl_dimm_update_key(struct ndctl_dimm *dimm);
+#else
+static inline int ndctl_dimm_enable_key(struct ndctl_dimm *dimm)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int ndctl_dimm_update_key(struct ndctl_dimm *dimm)
+{
+	return -EOPNOTSUPP;
+}
+#endif
+
+#define ND_KEY_DESC_SIZE	128
+#define ND_KEY_CMD_SIZE		128
 
 #ifdef __cplusplus
 } /* extern "C" */
diff --git a/ndctl/ndctl.c b/ndctl/ndctl.c
index bd11ec03..a715f69a 100644
--- a/ndctl/ndctl.c
+++ b/ndctl/ndctl.c
@@ -88,6 +88,8 @@ static struct cmd_struct commands[] = {
 	{ "inject-smart", { cmd_inject_smart } },
 	{ "wait-scrub", { cmd_wait_scrub } },
 	{ "start-scrub", { cmd_start_scrub } },
+	{ "setup-passphrase", { cmd_passphrase_setup } },
+	{ "update-passphrase", { cmd_passphrase_update } },
 	{ "list", { cmd_list } },
 	{ "monitor", { cmd_monitor } },
 	{ "install-encrypt-key", { cmd_install_kek } },

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

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

* [PATCH v9 04/13] ndctl: add disable security support
  2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
                   ` (2 preceding siblings ...)
  2019-01-18  2:38 ` [PATCH v9 03/13] ndctl: add passphrase update to ndctl Dave Jiang
@ 2019-01-18  2:38 ` Dave Jiang
  2019-01-18  2:38 ` [PATCH v9 05/13] ndctl: add support for freeze security Dave Jiang
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Dave Jiang @ 2019-01-18  2:38 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Add support for disable security to libndctl and also command line option
of "disable-passphrase" for ndctl. This provides a way to disable security
on the nvdimm.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 Documentation/ndctl/Makefile.am                 |    3 ++
 Documentation/ndctl/ndctl-remove-passphrase.txt |   26 +++++++++++++++++++++
 ndctl/builtin.h                                 |    1 +
 ndctl/dimm.c                                    |   23 ++++++++++++++++++
 ndctl/lib/dimm.c                                |    9 +++++++
 ndctl/lib/keys.c                                |   29 +++++++++++++++++++++++
 ndctl/lib/libndctl.sym                          |    2 ++
 ndctl/libndctl.h                                |    7 ++++++
 ndctl/ndctl.c                                   |    1 +
 9 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ndctl/ndctl-remove-passphrase.txt

diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am
index 7b155d4d..96519653 100644
--- a/Documentation/ndctl/Makefile.am
+++ b/Documentation/ndctl/Makefile.am
@@ -50,7 +50,8 @@ man1_MANS = \
 	ndctl-monitor.1 \
 	ndctl-install-encrypt-key.1 \
 	ndctl-setup-passphrase.1 \
-	ndctl-update-passphrase.1
+	ndctl-update-passphrase.1 \
+	ndctl-disable-passphrase.1
 
 CLEANFILES = $(man1_MANS)
 
diff --git a/Documentation/ndctl/ndctl-remove-passphrase.txt b/Documentation/ndctl/ndctl-remove-passphrase.txt
new file mode 100644
index 00000000..17ff905b
--- /dev/null
+++ b/Documentation/ndctl/ndctl-remove-passphrase.txt
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+
+ndctl-remove-passphrase(1)
+===========================
+
+NAME
+----
+ndctl-remove-passphrase - Stop a DIMM from locking at power-loss and requiring a passphrase to access media
+
+SYNOPSIS
+--------
+[verse]
+'ndctl remove-passphrase' <nmem0> [<nmem1>..<nmemN>] [<options>]
+
+DESCRIPTION
+-----------
+Search the user key ring for the associated NVDIMM key. If not found,
+attempt to load the key blob. After disabling the passphrase successfully,
+remove the key and the key blob.
+
+OPTIONS
+-------
+<dimm>::
+include::xable-dimm-options.txt[]
+
+include::../copyright.txt[]
diff --git a/ndctl/builtin.h b/ndctl/builtin.h
index 33c04983..3d71cb30 100644
--- a/ndctl/builtin.h
+++ b/ndctl/builtin.h
@@ -35,4 +35,5 @@ int cmd_inject_smart(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_install_kek(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_passphrase_setup(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_passphrase_update(int argc, const char **argv, struct ndctl_ctx *ctx);
+int cmd_passphrase_remove(int argc, const char **argv, struct ndctl_ctx *ctx);
 #endif /* _NDCTL_BUILTIN_H_ */
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index bea7cf62..f71eafe7 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -860,6 +860,18 @@ static int action_key_update(struct ndctl_dimm *dimm,
 	return ndctl_dimm_update_key(dimm);
 }
 
+static int action_passphrase_remove(struct ndctl_dimm *dimm,
+		struct action_context *actx)
+{
+	if (ndctl_dimm_get_security(dimm) < 0) {
+		error("%s: security operation not supported\n",
+				ndctl_dimm_get_devname(dimm));
+		return -EOPNOTSUPP;
+	}
+
+	return ndctl_dimm_remove_key(dimm);
+}
+
 static int __action_init(struct ndctl_dimm *dimm,
 		enum ndctl_namespace_version version, int chk_only)
 {
@@ -1227,3 +1239,14 @@ int cmd_passphrase_setup(int argc, const char **argv, struct ndctl_ctx *ctx)
 			count > 1 ? "s" : "");
 	return count >= 0 ? 0 : EXIT_FAILURE;
 }
+
+int cmd_passphrase_remove(int argc, const char **argv, void *ctx)
+{
+	int count = dimm_action(argc, argv, ctx, action_passphrase_remove,
+			base_options,
+			"ndctl remove-passphrase <nmem0> [<nmem1>..<nmemN>] [<options>]");
+
+	fprintf(stderr, "passphrase removed for %d nmem%s.\n", count >= 0 ? count : 0,
+			count > 1 ? "s" : "");
+	return count >= 0 ? 0 : EXIT_FAILURE;
+}
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
index 72b6f66c..a944c9af 100644
--- a/ndctl/lib/dimm.c
+++ b/ndctl/lib/dimm.c
@@ -655,3 +655,12 @@ NDCTL_EXPORT int ndctl_dimm_update_passphrase(struct ndctl_dimm *dimm,
 	sprintf(buf, "update %ld %ld\n", ckey, nkey);
 	return write_security(dimm, buf);
 }
+
+NDCTL_EXPORT int ndctl_dimm_disable_passphrase(struct ndctl_dimm *dimm,
+		long key)
+{
+	char buf[SYSFS_ATTR_SIZE];
+
+	sprintf(buf, "disable %ld\n", key);
+	return write_security(dimm, buf);
+}
diff --git a/ndctl/lib/keys.c b/ndctl/lib/keys.c
index 1ae0ff02..fe618870 100644
--- a/ndctl/lib/keys.c
+++ b/ndctl/lib/keys.c
@@ -13,6 +13,7 @@
 #include <syslog.h>
 
 #include <ndctl.h>
+#include <ndctl/config.h>
 #include <ndctl/libndctl.h>
 #include "private.h"
 
@@ -385,3 +386,31 @@ NDCTL_EXPORT int ndctl_dimm_update_key(struct ndctl_dimm *dimm)
 
 	return 0;
 }
+
+NDCTL_EXPORT int ndctl_dimm_remove_key(struct ndctl_dimm *dimm)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	key_serial_t key;
+	int rc;
+
+	key = dimm_check_key(dimm, false);
+	if (key < 0) {
+		key = dimm_load_key(dimm, false);
+		if (key < 0) {
+			err(ctx, "Unable to load key\n");
+			return -ENOKEY;
+		}
+	}
+
+	rc = ndctl_dimm_disable_passphrase(dimm, key);
+	if (rc < 0) {
+		err(ctx, "Failed to disable security for %s\n",
+				ndctl_dimm_get_devname(dimm));
+		return rc;
+	}
+
+	rc = dimm_remove_key(dimm, false);
+	if (rc < 0)
+		err(ctx, "Unable to cleanup key.\n");
+	return 0;
+}
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index ce05d604..ed387ac0 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -395,4 +395,6 @@ global:
 	ndctl_dimm_enable_key;
 	ndctl_dimm_update_key;
 	ndctl_dimm_update_passphrase;
+	ndctl_dimm_disable_passphrase;
+	ndctl_dimm_remove_key;
 } LIBNDCTL_18;
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index 727dedcf..823e4cff 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -703,6 +703,7 @@ enum ndctl_security_state ndctl_dimm_get_security(struct ndctl_dimm *dimm);
 const char *ndctl_bus_get_kek_handle(struct ndctl_bus *bus);
 int ndctl_dimm_update_passphrase(struct ndctl_dimm *dimm,
 		long ckey, long nkey);
+int ndctl_dimm_disable_passphrase(struct ndctl_dimm *dimm, long key);
 
 enum ndctl_key_type {
 	ND_USER_KEY,
@@ -712,6 +713,7 @@ enum ndctl_key_type {
 #ifdef ENABLE_KEYUTILS
 int ndctl_dimm_enable_key(struct ndctl_dimm *dimm);
 int ndctl_dimm_update_key(struct ndctl_dimm *dimm);
+int ndctl_dimm_remove_key(struct ndctl_dimm *dimm);
 #else
 static inline int ndctl_dimm_enable_key(struct ndctl_dimm *dimm)
 {
@@ -722,6 +724,11 @@ static inline int ndctl_dimm_update_key(struct ndctl_dimm *dimm)
 {
 	return -EOPNOTSUPP;
 }
+
+static inline int ndctl_dimm_remove_key(struct ndctl_dimm *dimm)
+{
+	return -EOPNOTSUPP;
+}
 #endif
 
 #define ND_KEY_DESC_SIZE	128
diff --git a/ndctl/ndctl.c b/ndctl/ndctl.c
index a715f69a..11f640c0 100644
--- a/ndctl/ndctl.c
+++ b/ndctl/ndctl.c
@@ -90,6 +90,7 @@ static struct cmd_struct commands[] = {
 	{ "start-scrub", { cmd_start_scrub } },
 	{ "setup-passphrase", { cmd_passphrase_setup } },
 	{ "update-passphrase", { cmd_passphrase_update } },
+	{ "remove-passphrase", { cmd_passphrase_remove } },
 	{ "list", { cmd_list } },
 	{ "monitor", { cmd_monitor } },
 	{ "install-encrypt-key", { cmd_install_kek } },

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

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

* [PATCH v9 05/13] ndctl: add support for freeze security
  2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
                   ` (3 preceding siblings ...)
  2019-01-18  2:38 ` [PATCH v9 04/13] ndctl: add disable security support Dave Jiang
@ 2019-01-18  2:38 ` Dave Jiang
  2019-01-18  2:38 ` [PATCH v9 06/13] ndctl: add support for sanitize dimm Dave Jiang
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Dave Jiang @ 2019-01-18  2:38 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Add support for freeze security to libndctl and also command line option
of "freeze-security" for ndctl. This will lock the ability to make changes
to the NVDIMM security.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 Documentation/ndctl/Makefile.am               |    3 +
 Documentation/ndctl/ndctl-freeze-security.txt |   58 +++++++++++++++++++++++++
 ndctl/builtin.h                               |    1 
 ndctl/dimm.c                                  |   28 ++++++++++++
 ndctl/lib/dimm.c                              |    5 ++
 ndctl/lib/libndctl.sym                        |    1 
 ndctl/libndctl.h                              |    1 
 ndctl/ndctl.c                                 |    1 
 8 files changed, 97 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ndctl/ndctl-freeze-security.txt

diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am
index 96519653..f4230ead 100644
--- a/Documentation/ndctl/Makefile.am
+++ b/Documentation/ndctl/Makefile.am
@@ -51,7 +51,8 @@ man1_MANS = \
 	ndctl-install-encrypt-key.1 \
 	ndctl-setup-passphrase.1 \
 	ndctl-update-passphrase.1 \
-	ndctl-disable-passphrase.1
+	ndctl-disable-passphrase.1 \
+	ndctl-freeze-security.1
 
 CLEANFILES = $(man1_MANS)
 
diff --git a/Documentation/ndctl/ndctl-freeze-security.txt b/Documentation/ndctl/ndctl-freeze-security.txt
new file mode 100644
index 00000000..d14b8a39
--- /dev/null
+++ b/Documentation/ndctl/ndctl-freeze-security.txt
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0
+
+ndctl-freeze-security(1)
+========================
+
+NAME
+----
+ndctl-freeze-security - Set the given DIMM(s) to reject future security operations
+
+SYNOPSIS
+--------
+[verse]
+'ndctl freeze-security' <nmem0> [<nmem1>..<nmemN>] [<options>]
+
+DESCRIPTION
+-----------
+Prevent any further security operations on the given DIMMs until the
+next reboot. This is used in scenarios where the administrator has
+taken all expected security actions for the current boot and wants the
+DIMM to enforce / lock the current state.
+
+EXAMPLES
+--------
+
+[verse]
+ndctl list -d nmem0
+[
+  {
+    "dev":"nmem0",
+    "id":"cdab-0a-07e0-ffffffff",
+    "handle":0,
+    "phys_id":0,
+    "security":"unlocked"
+  }
+]
+
+[verse]
+ndctl freeze-security  nmem0
+security freezed 1 nmem.
+
+[verse]
+ndctl list -d nmem0
+[
+  {
+    "dev":"nmem0",
+    "id":"cdab-0a-07e0-ffffffff",
+    "handle":0,
+    "phys_id":0,
+    "security":"frozen"
+  }
+]
+
+OPTIONS
+-------
+<dimm>::
+include::xable-dimm-options.txt[]
+
+include::../copyright.txt[]
diff --git a/ndctl/builtin.h b/ndctl/builtin.h
index 3d71cb30..8434766d 100644
--- a/ndctl/builtin.h
+++ b/ndctl/builtin.h
@@ -36,4 +36,5 @@ int cmd_install_kek(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_passphrase_setup(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_passphrase_update(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_passphrase_remove(int argc, const char **argv, struct ndctl_ctx *ctx);
+int cmd_freeze_security(int argc, const char **argv, struct ndctl_ctx *ctx);
 #endif /* _NDCTL_BUILTIN_H_ */
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index f71eafe7..3222def6 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -872,6 +872,24 @@ static int action_passphrase_remove(struct ndctl_dimm *dimm,
 	return ndctl_dimm_remove_key(dimm);
 }
 
+static int action_security_freeze(struct ndctl_dimm *dimm,
+		struct action_context *actx)
+{
+	int rc;
+
+	if (ndctl_dimm_get_security(dimm) < 0) {
+		error("%s: security operation not supported\n",
+				ndctl_dimm_get_devname(dimm));
+		return -EOPNOTSUPP;
+	}
+
+	rc = ndctl_dimm_freeze_security(dimm);
+	if (rc < 0)
+		error("Failed to freeze security for %s\n",
+				ndctl_dimm_get_devname(dimm));
+	return rc;
+}
+
 static int __action_init(struct ndctl_dimm *dimm,
 		enum ndctl_namespace_version version, int chk_only)
 {
@@ -1250,3 +1268,13 @@ int cmd_passphrase_remove(int argc, const char **argv, void *ctx)
 			count > 1 ? "s" : "");
 	return count >= 0 ? 0 : EXIT_FAILURE;
 }
+
+int cmd_freeze_security(int argc, const char **argv, void *ctx)
+{
+	int count = dimm_action(argc, argv, ctx, action_security_freeze, base_options,
+			"ndctl freeze-security <nmem0> [<nmem1>..<nmemN>] [<options>]");
+
+	fprintf(stderr, "security freezed %d nmem%s.\n", count >= 0 ? count : 0,
+			count > 1 ? "s" : "");
+	return count >= 0 ? 0 : EXIT_FAILURE;
+}
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
index a944c9af..0a7eaaef 100644
--- a/ndctl/lib/dimm.c
+++ b/ndctl/lib/dimm.c
@@ -664,3 +664,8 @@ NDCTL_EXPORT int ndctl_dimm_disable_passphrase(struct ndctl_dimm *dimm,
 	sprintf(buf, "disable %ld\n", key);
 	return write_security(dimm, buf);
 }
+
+NDCTL_EXPORT int ndctl_dimm_freeze_security(struct ndctl_dimm *dimm)
+{
+	return write_security(dimm, "freeze");
+}
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index ed387ac0..dfcf4977 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -397,4 +397,5 @@ global:
 	ndctl_dimm_update_passphrase;
 	ndctl_dimm_disable_passphrase;
 	ndctl_dimm_remove_key;
+	ndctl_dimm_freeze_security;
 } LIBNDCTL_18;
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index 823e4cff..839d39f1 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -704,6 +704,7 @@ const char *ndctl_bus_get_kek_handle(struct ndctl_bus *bus);
 int ndctl_dimm_update_passphrase(struct ndctl_dimm *dimm,
 		long ckey, long nkey);
 int ndctl_dimm_disable_passphrase(struct ndctl_dimm *dimm, long key);
+int ndctl_dimm_freeze_security(struct ndctl_dimm *dimm);
 
 enum ndctl_key_type {
 	ND_USER_KEY,
diff --git a/ndctl/ndctl.c b/ndctl/ndctl.c
index 11f640c0..d3b47e26 100644
--- a/ndctl/ndctl.c
+++ b/ndctl/ndctl.c
@@ -91,6 +91,7 @@ static struct cmd_struct commands[] = {
 	{ "setup-passphrase", { cmd_passphrase_setup } },
 	{ "update-passphrase", { cmd_passphrase_update } },
 	{ "remove-passphrase", { cmd_passphrase_remove } },
+	{ "freeze-security", { cmd_freeze_security } },
 	{ "list", { cmd_list } },
 	{ "monitor", { cmd_monitor } },
 	{ "install-encrypt-key", { cmd_install_kek } },

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

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

* [PATCH v9 06/13] ndctl: add support for sanitize dimm
  2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
                   ` (4 preceding siblings ...)
  2019-01-18  2:38 ` [PATCH v9 05/13] ndctl: add support for freeze security Dave Jiang
@ 2019-01-18  2:38 ` Dave Jiang
  2019-01-18  2:39 ` [PATCH v9 07/13] ndctl: add unit test for security ops (minus overwrite) Dave Jiang
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Dave Jiang @ 2019-01-18  2:38 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Add support to secure erase to libndctl and also command line option
of "sanitize-dimm" for ndctl. This will initiate the request to crypto
erase a DIMM.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 Documentation/ndctl/Makefile.am             |    3 +
 Documentation/ndctl/ndctl-sanitize-dimm.txt |   30 +++++++++++++
 ndctl/builtin.h                             |    1 
 ndctl/dimm.c                                |   29 ++++++++++++
 ndctl/lib/dimm.c                            |    8 +++
 ndctl/lib/keys.c                            |   63 +++++++++++++++++++++++++--
 ndctl/lib/libndctl.sym                      |    2 +
 ndctl/libndctl.h                            |    7 +++
 ndctl/ndctl.c                               |    1 
 9 files changed, 138 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/ndctl/ndctl-sanitize-dimm.txt

diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am
index f4230ead..2e535940 100644
--- a/Documentation/ndctl/Makefile.am
+++ b/Documentation/ndctl/Makefile.am
@@ -52,7 +52,8 @@ man1_MANS = \
 	ndctl-setup-passphrase.1 \
 	ndctl-update-passphrase.1 \
 	ndctl-disable-passphrase.1 \
-	ndctl-freeze-security.1
+	ndctl-freeze-security.1 \
+	ndctl-sanitize-dimm.1
 
 CLEANFILES = $(man1_MANS)
 
diff --git a/Documentation/ndctl/ndctl-sanitize-dimm.txt b/Documentation/ndctl/ndctl-sanitize-dimm.txt
new file mode 100644
index 00000000..f95be28f
--- /dev/null
+++ b/Documentation/ndctl/ndctl-sanitize-dimm.txt
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+
+ndctl-sanitize-dimm(1)
+======================
+
+NAME
+----
+ndctl-sanitize-dimm - Perform a cryptographic destruction of the contents of the given NVDIMM(s).
+
+SYNOPSIS
+--------
+[verse]
+'ndctl sanitize-dimm' <nmem0> [<nmem1>..<nmemN>] [<options>]
+
+DESCRIPTION
+-----------
+Search the user key ring for the associated NVDIMM. If not found,
+attempt to load the key blob from the default location. After disabling
+the passphrase, remove the key and the key blob.
+
+OPTIONS
+-------
+<dimm>::
+include::xable-dimm-options.txt[]
+
+include::../copyright.txt[]
+
+SEE ALSO
+--------
+https://trustedcomputinggroup.org/wp-content/uploads/TCG_SWG_SIIS_Version_1_07_Revision_1_00.pdf [Trusted Computing Group Storage Interface Interactions Specification]
diff --git a/ndctl/builtin.h b/ndctl/builtin.h
index 8434766d..3d8f4ce7 100644
--- a/ndctl/builtin.h
+++ b/ndctl/builtin.h
@@ -37,4 +37,5 @@ int cmd_passphrase_setup(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_passphrase_update(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_passphrase_remove(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_freeze_security(int argc, const char **argv, struct ndctl_ctx *ctx);
+int cmd_sanitize_dimm(int argc, const char **argv, struct ndctl_ctx *ctx);
 #endif /* _NDCTL_BUILTIN_H_ */
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index 3222def6..c346b7fb 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -890,6 +890,24 @@ static int action_security_freeze(struct ndctl_dimm *dimm,
 	return rc;
 }
 
+static int action_sanitize_dimm(struct ndctl_dimm *dimm,
+		struct action_context *actx)
+{
+	int rc;
+
+	if (ndctl_dimm_get_security(dimm) < 0) {
+		error("%s: security operation not supported\n",
+				ndctl_dimm_get_devname(dimm));
+		return -EOPNOTSUPP;
+	}
+
+	rc = ndctl_dimm_secure_erase_key(dimm);
+	if (rc < 0)
+		return rc;
+
+	return 0;
+}
+
 static int __action_init(struct ndctl_dimm *dimm,
 		enum ndctl_namespace_version version, int chk_only)
 {
@@ -1278,3 +1296,14 @@ int cmd_freeze_security(int argc, const char **argv, void *ctx)
 			count > 1 ? "s" : "");
 	return count >= 0 ? 0 : EXIT_FAILURE;
 }
+
+int cmd_sanitize_dimm(int argc, const char **argv, void *ctx)
+{
+	int count = dimm_action(argc, argv, ctx, action_sanitize_dimm,
+			base_options,
+			"ndctl sanitize-dimm <nmem0> [<nmem1>..<nmemN>] [<options>]");
+
+	fprintf(stderr, "sanitized %d nmem%s.\n", count >= 0 ? count : 0,
+			count > 1 ? "s" : "");
+	return count >= 0 ? 0 : EXIT_FAILURE;
+}
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
index 0a7eaaef..50650738 100644
--- a/ndctl/lib/dimm.c
+++ b/ndctl/lib/dimm.c
@@ -669,3 +669,11 @@ NDCTL_EXPORT int ndctl_dimm_freeze_security(struct ndctl_dimm *dimm)
 {
 	return write_security(dimm, "freeze");
 }
+
+NDCTL_EXPORT int ndctl_dimm_secure_erase(struct ndctl_dimm *dimm, long key)
+{
+	char buf[SYSFS_ATTR_SIZE];
+
+	sprintf(buf, "erase %ld\n", key);
+	return write_security(dimm, buf);
+}
diff --git a/ndctl/lib/keys.c b/ndctl/lib/keys.c
index fe618870..5353bdc4 100644
--- a/ndctl/lib/keys.c
+++ b/ndctl/lib/keys.c
@@ -387,11 +387,10 @@ NDCTL_EXPORT int ndctl_dimm_update_key(struct ndctl_dimm *dimm)
 	return 0;
 }
 
-NDCTL_EXPORT int ndctl_dimm_remove_key(struct ndctl_dimm *dimm)
+static key_serial_t check_dimm_key(struct ndctl_dimm *dimm)
 {
 	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
 	key_serial_t key;
-	int rc;
 
 	key = dimm_check_key(dimm, false);
 	if (key < 0) {
@@ -402,15 +401,69 @@ NDCTL_EXPORT int ndctl_dimm_remove_key(struct ndctl_dimm *dimm)
 		}
 	}
 
-	rc = ndctl_dimm_disable_passphrase(dimm, key);
+	return key;
+}
+
+static int run_key_op(struct ndctl_dimm *dimm,
+		key_serial_t key,
+		int (*run_op)(struct ndctl_dimm *, long), const char *name)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	int rc;
+
+	rc = run_op(dimm, key);
 	if (rc < 0) {
-		err(ctx, "Failed to disable security for %s\n",
+		err(ctx, "Failed %s for %s\n", name,
 				ndctl_dimm_get_devname(dimm));
 		return rc;
 	}
 
+	return 0;
+}
+
+static int discard_key(struct ndctl_dimm *dimm)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	int rc;
+
 	rc = dimm_remove_key(dimm, false);
-	if (rc < 0)
+	if (rc < 0) {
 		err(ctx, "Unable to cleanup key.\n");
+		return rc;
+	}
 	return 0;
 }
+
+NDCTL_EXPORT int ndctl_dimm_remove_key(struct ndctl_dimm *dimm)
+{
+	key_serial_t key;
+	int rc;
+
+	key = check_dimm_key(dimm);
+	if (key < 0)
+		return key;
+
+	rc = run_key_op(dimm, key, ndctl_dimm_disable_passphrase,
+			"remove passphrase");
+	if (rc < 0)
+		return rc;
+
+	return discard_key(dimm);
+}
+
+NDCTL_EXPORT int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm)
+{
+	key_serial_t key;
+	int rc;
+
+	key = check_dimm_key(dimm);
+	if (key < 0)
+		return key;
+
+	rc = run_key_op(dimm, key, ndctl_dimm_secure_erase,
+			"crypto erase");
+	if (rc < 0)
+		return rc;
+
+	return discard_key(dimm);
+}
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index dfcf4977..f4b487d4 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -398,4 +398,6 @@ global:
 	ndctl_dimm_disable_passphrase;
 	ndctl_dimm_remove_key;
 	ndctl_dimm_freeze_security;
+	ndctl_dimm_secure_erase;
+	ndctl_dimm_secure_erase_key;
 } LIBNDCTL_18;
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index 839d39f1..05c39e8e 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -705,6 +705,7 @@ int ndctl_dimm_update_passphrase(struct ndctl_dimm *dimm,
 		long ckey, long nkey);
 int ndctl_dimm_disable_passphrase(struct ndctl_dimm *dimm, long key);
 int ndctl_dimm_freeze_security(struct ndctl_dimm *dimm);
+int ndctl_dimm_secure_erase(struct ndctl_dimm *dimm, long key);
 
 enum ndctl_key_type {
 	ND_USER_KEY,
@@ -715,6 +716,7 @@ enum ndctl_key_type {
 int ndctl_dimm_enable_key(struct ndctl_dimm *dimm);
 int ndctl_dimm_update_key(struct ndctl_dimm *dimm);
 int ndctl_dimm_remove_key(struct ndctl_dimm *dimm);
+int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm);
 #else
 static inline int ndctl_dimm_enable_key(struct ndctl_dimm *dimm)
 {
@@ -730,6 +732,11 @@ static inline int ndctl_dimm_remove_key(struct ndctl_dimm *dimm)
 {
 	return -EOPNOTSUPP;
 }
+
+static inline int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm)
+{
+	return -EOPNOTSUPP;
+}
 #endif
 
 #define ND_KEY_DESC_SIZE	128
diff --git a/ndctl/ndctl.c b/ndctl/ndctl.c
index d3b47e26..283ccc33 100644
--- a/ndctl/ndctl.c
+++ b/ndctl/ndctl.c
@@ -92,6 +92,7 @@ static struct cmd_struct commands[] = {
 	{ "update-passphrase", { cmd_passphrase_update } },
 	{ "remove-passphrase", { cmd_passphrase_remove } },
 	{ "freeze-security", { cmd_freeze_security } },
+	{ "sanitize-dimm", { cmd_sanitize_dimm } },
 	{ "list", { cmd_list } },
 	{ "monitor", { cmd_monitor } },
 	{ "install-encrypt-key", { cmd_install_kek } },

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

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

* [PATCH v9 07/13] ndctl: add unit test for security ops (minus overwrite)
  2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
                   ` (5 preceding siblings ...)
  2019-01-18  2:38 ` [PATCH v9 06/13] ndctl: add support for sanitize dimm Dave Jiang
@ 2019-01-18  2:39 ` Dave Jiang
  2019-01-18  2:39 ` [PATCH v9 08/13] ndctl: add modprobe conf file and load-keys ndctl command Dave Jiang
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Dave Jiang @ 2019-01-18  2:39 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Add unit test for security enable, disable, update, erase, unlock, and
freeze.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 test/Makefile.am |    4 +
 test/security.sh |  223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 227 insertions(+)
 create mode 100755 test/security.sh

diff --git a/test/Makefile.am b/test/Makefile.am
index ebdd23f6..42009c31 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -27,6 +27,10 @@ TESTS =\
 	max_available_extent_ns.sh \
 	pfn-meta-errors.sh
 
+if ENABLE_KEYUTILS
+TESTS += security.sh
+endif
+
 check_PROGRAMS =\
 	libndctl \
 	dsm-fail \
diff --git a/test/security.sh b/test/security.sh
new file mode 100755
index 00000000..4892ee0c
--- /dev/null
+++ b/test/security.sh
@@ -0,0 +1,223 @@
+#!/bin/bash -Ex
+# SPDX-License-Identifier: GPL-2.0
+# Copyright(c) 2018 Intel Corporation. All rights reserved.
+
+rc=77
+dev=""
+id=""
+keypath="/etc/ndctl/keys"
+masterkey="nvdimm-master-test"
+masterpath="$keypath/$masterkey"
+
+. ./common
+
+trap 'err $LINENO' ERR
+
+setup()
+{
+	$NDCTL disable-region -b "$NFIT_TEST_BUS0" all
+}
+
+detect()
+{
+	dev="$($NDCTL list -b "$NFIT_TEST_BUS0" -D | jq -r .[0].dev)"
+	[ -n "$dev" ] || err "$LINENO"
+	id="$($NDCTL list -b "$NFIT_TEST_BUS0" -D | jq -r .[0].id)"
+	[ -n "$id" ] || err "$LINENO"
+}
+
+setup_keys()
+{
+	if [ ! -d "$keypath" ]; then
+		mkdir -p "$keypath"
+	fi
+
+	dd if=/dev/urandom bs=1 count=32 2>/dev/null | keyctl padd user "$masterkey" @u
+	keyctl pipe "$(keyctl search @u user $masterkey)" > "$masterpath"
+	$NDCTL install-encrypt-key "$NFIT_TEST_BUS0" -k user:"$masterkey"
+}
+
+test_cleanup()
+{
+	if keyctl search @u encrypted nvdimm:"$id"; then
+		keyctl unlink "$(keyctl search @u encrypted nvdimm:"$id")"
+	fi
+
+	if keyctl search @u user "$masterkey"; then
+		keyctl unlink "$(keyctl search @u user $masterkey)"
+	fi
+
+	if [ -f "$keypath"/nvdimm_"$id"_"$(hostname)".blob ]; then
+		rm -f "$keypath"/nvdimm_"$id"_"$(hostname)".blob
+	fi
+
+	if [ -f $masterpath ]; then
+		rm -f "$masterpath"
+	fi
+
+	rm -f "$keypath"/"$NFIT_TEST_BUS0".kek
+}
+
+lock_dimm()
+{
+	$NDCTL disable-dimm "$dev"
+	# convert nmemX --> test_dimmY
+	# for now this is the only user of such a conversion so we can leave it
+	# inline once a subsequent user arrives we can refactor this to a
+	# helper in test/common:
+	#   get_test_dimm_path "nfit_test.0" "nmem3"
+	handle="$(ndctl list -b "$NFIT_TEST_BUS0"  -d "$dev" -i | jq -r .[].dimms[0].handle)"
+	test_dimm_path=""
+	for test_dimm in /sys/devices/platform/"$NFIT_TEST_BUS0"/nfit_test_dimm/test_dimm*; do
+		td_handle_file="$test_dimm/handle"
+		test -e "$td_handle_file" || continue
+		td_handle="$(cat "$td_handle_file")"
+		if [[ "$td_handle" -eq "$handle" ]]; then
+			test_dimm_path="$test_dimm"
+			break
+		fi
+	done
+	test -d "$test_dimm_path"
+
+	# now lock the dimm
+	echo 1 > "${test_dimm_path}/lock_dimm"
+	sstate="$(get_security_state)"
+	if [ "$sstate" != "locked" ]; then
+		echo "Incorrect security state: $sstate expected: locked"
+		err "$LINENO"
+	fi
+}
+
+get_security_state()
+{
+	$NDCTL list -i -b "$NFIT_TEST_BUS0" -d "$dev" | jq -r .[].dimms[0].security
+}
+
+setup_passphrase()
+{
+	$NDCTL setup-passphrase "$dev"
+	sstate="$(get_security_state)"
+	if [ "$sstate" != "unlocked" ]; then
+		echo "Incorrect security state: $sstate expected: unlocked"
+		err "$LINENO"
+	fi
+}
+
+remove_passphrase()
+{
+	$NDCTL remove-passphrase "$dev"
+	sstate="$(get_security_state)"
+	if [ "$sstate" != "disabled" ]; then
+		echo "Incorrect security state: $sstate expected: disabled"
+		err "$LINENO"
+	fi
+}
+
+erase_security()
+{
+	$NDCTL sanitize-dimm -c "$dev"
+	sstate="$(get_security_state)"
+	if [ "$sstate" != "disabled" ]; then
+		echo "Incorrect security state: $sstate expected: disabled"
+		err "$LINENO"
+	fi
+}
+
+update_security()
+{
+	$NDCTL update-passphrase "$dev"
+	sstate="$(get_security_state)"
+	if [ "$sstate" != "unlocked" ]; then
+		echo "Incorrect security state: $sstate expected: unlocked"
+		err "$LINENO"
+	fi
+}
+
+freeze_security()
+{
+	$NDCTL freeze-security "$dev"
+}
+
+test_1_security_setup_and_remove()
+{
+	setup_passphrase
+	remove_passphrase
+}
+
+test_2_security_setup_and_update()
+{
+	setup_passphrase
+	update_security
+	remove_passphrase
+}
+
+test_3_security_setup_and_erase()
+{
+	setup_passphrase
+	erase_security
+}
+
+test_4_security_unlock()
+{
+	setup_passphrase
+	lock_dimm
+	$NDCTL enable-dimm "$dev"
+	sstate="$(get_security_state)"
+	if [ "$sstate" != "unlocked" ]; then
+		echo "Incorrect security state: $sstate expected: unlocked"
+		err "$LINENO"
+	fi
+	$NDCTL disable-region -b "$NFIT_TEST_BUS0" all
+	remove_passphrase
+}
+
+# this should always be the last test. with security frozen, nfit_test must
+# be removed and is no longer usable
+test_5_security_freeze()
+{
+	setup_passphrase
+	freeze_security
+	sstate="$(get_security_state)"
+	if [ "$sstate" != "frozen" ]; then
+		echo "Incorrect security state: $sstate expected: frozen"
+		err "$LINENO"
+	fi
+	$NDCTL remove-passphrase "$dev" && { echo "remove succeed after frozen"; }
+	sstate="$(get_security_state)"
+	echo "$sstate"
+	if [ "$sstate" != "frozen" ]; then
+		echo "Incorrect security state: $sstate expected: frozen"
+		err "$LINENO"
+	fi
+}
+
+check_min_kver "5.0" || do_skip "may lack security handling"
+uid="$(keyctl show | grep -Eo "_uid.[0-9]+" | head -1 | cut -d. -f2-)"
+if [ "$uid" -ne 0 ]; then
+	do_skip "run as root or with a sudo login shell for test to work"
+fi
+
+modprobe nfit_test
+setup
+check_prereq "keyctl"
+rc=1
+detect
+test_cleanup
+setup_keys
+echo "Test 1, security setup and remove"
+test_1_security_setup_and_remove
+echo "Test 2, security setup, update, and remove"
+test_2_security_setup_and_update
+echo "Test 3, security setup and erase"
+test_3_security_setup_and_erase
+echo "Test 4, unlock dimm"
+test_4_security_unlock
+
+# Freeze should always be run last because it locks security state and require
+# nfit_test module unload.
+echo "Test 5, freeze security"
+test_5_security_freeze
+
+test_cleanup
+_cleanup
+exit 0

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

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

* [PATCH v9 08/13] ndctl: add modprobe conf file and load-keys ndctl command
  2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
                   ` (6 preceding siblings ...)
  2019-01-18  2:39 ` [PATCH v9 07/13] ndctl: add unit test for security ops (minus overwrite) Dave Jiang
@ 2019-01-18  2:39 ` Dave Jiang
  2019-01-23 18:25   ` Dan Williams
  2019-01-18  2:39 ` [PATCH v9 09/13] ndctl: add overwrite operation support Dave Jiang
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 24+ messages in thread
From: Dave Jiang @ 2019-01-18  2:39 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Add load-keys command to ndctl. This will attempt to load the master key
and the related encrypted keys for nvdimms. Also add reference config file
for modprobe.d in order to call ndctl load-keys and inject keys associated
with the nvdimms into the kernel user ring for unlock.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 Documentation/ndctl/Makefile.am         |    3 
 Documentation/ndctl/ndctl-load-keys.txt |   43 +++++
 Makefile.am                             |    4 
 contrib/nvdimm-security.conf            |    1 
 ndctl.spec.in                           |    1 
 ndctl/Makefile.am                       |    3 
 ndctl/builtin.h                         |    1 
 ndctl/lib/keys.c                        |   64 +++++---
 ndctl/lib/libndctl.sym                  |    1 
 ndctl/libndctl.h                        |    2 
 ndctl/load-keys.c                       |  257 +++++++++++++++++++++++++++++++
 ndctl/ndctl.c                           |    1 
 12 files changed, 357 insertions(+), 24 deletions(-)
 create mode 100644 Documentation/ndctl/ndctl-load-keys.txt
 create mode 100644 contrib/nvdimm-security.conf
 create mode 100644 ndctl/load-keys.c

diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am
index 2e535940..2481361f 100644
--- a/Documentation/ndctl/Makefile.am
+++ b/Documentation/ndctl/Makefile.am
@@ -53,7 +53,8 @@ man1_MANS = \
 	ndctl-update-passphrase.1 \
 	ndctl-disable-passphrase.1 \
 	ndctl-freeze-security.1 \
-	ndctl-sanitize-dimm.1
+	ndctl-sanitize-dimm.1 \
+	ndctl-load-keys.1
 
 CLEANFILES = $(man1_MANS)
 
diff --git a/Documentation/ndctl/ndctl-load-keys.txt b/Documentation/ndctl/ndctl-load-keys.txt
new file mode 100644
index 00000000..f153e9d7
--- /dev/null
+++ b/Documentation/ndctl/ndctl-load-keys.txt
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+
+ndctl-load-keys(1)
+==================
+
+NAME
+----
+ndctl-load-keys - load encrypted keys with security passphrases for NVDIMM
+
+SYNOPSIS
+--------
+[verse]
+'ndctl load-keys' [<options>]
+
+DESCRIPTION
+-----------
+Provide a command to load the master key and the nvdimm encrypted keys for
+NVDIMM security operations. This command is expected to be called during
+initialization and before the libnvdimm kernel module is loaded. This works
+in conjunction with the provided module config file.
+
+NOTE: All nvdimm keys files are expected to be in format of:
+nvdimm_<id>_hostname
+The char '_' is used to deliminate the components in the file name. The char
+'_' can be used for any purpose starting with the hostname component and after.
+
+This command is typically never called directly by a user. It is only run via
+modprobe during early init.
+
+OPTIONS
+-------
+-p::
+--key-path=::
+	Path to where key related files reside. This parameter is optional
+	and the default is set to /etc/ndctl/keys.
+
+-t::
+--tpm-handle=::
+	Provide the TPM handle (should be a string such as 0x81000001) can
+	be optional if the key path contains a file called tpm.handle which
+	has the handle.
+
+include::../copyright.txt[]
diff --git a/Makefile.am b/Makefile.am
index e0c463a3..df8797ef 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -42,6 +42,10 @@ bashcompletiondir = $(BASH_COMPLETION_DIR)
 dist_bashcompletion_DATA = contrib/ndctl
 endif
 
+modprobe_file = contrib/nvdimm-security.conf
+modprobedir = $(sysconfdir)/modprobe.d/
+modprobe_DATA = $(modprobe_file)
+
 noinst_LIBRARIES = libccan.a
 libccan_a_SOURCES = \
 	ccan/str/str.h \
diff --git a/contrib/nvdimm-security.conf b/contrib/nvdimm-security.conf
new file mode 100644
index 00000000..e2bb7c0a
--- /dev/null
+++ b/contrib/nvdimm-security.conf
@@ -0,0 +1 @@
+install libnvdimm /usr/bin/ndctl load-keys ; /sbin/modprobe --ignore-install libnvdimm $CMDLINE_OPTS
diff --git a/ndctl.spec.in b/ndctl.spec.in
index 3956d81d..0353c7e3 100644
--- a/ndctl.spec.in
+++ b/ndctl.spec.in
@@ -120,6 +120,7 @@ make check
 %{bashcompdir}/
 %{_unitdir}/ndctl-monitor.service
 %{_sysconfdir}/ndctl/keys/
+%{_sysconfdir}/modprobe.d/nvdimm-security.conf
 
 %config(noreplace) %{_sysconfdir}/ndctl/monitor.conf
 
diff --git a/ndctl/Makefile.am b/ndctl/Makefile.am
index e412dbf7..193dea74 100644
--- a/ndctl/Makefile.am
+++ b/ndctl/Makefile.am
@@ -25,7 +25,8 @@ ndctl_SOURCES = ndctl.c \
 		inject-error.c \
 		inject-smart.c \
 		monitor.c \
-		kek.c
+		kek.c \
+		load-keys.c
 
 if ENABLE_DESTRUCTIVE
 ndctl_SOURCES += ../test/blk_namespaces.c \
diff --git a/ndctl/builtin.h b/ndctl/builtin.h
index 3d8f4ce7..416e4564 100644
--- a/ndctl/builtin.h
+++ b/ndctl/builtin.h
@@ -38,4 +38,5 @@ int cmd_passphrase_update(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_passphrase_remove(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_freeze_security(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_sanitize_dimm(int argc, const char **argv, struct ndctl_ctx *ctx);
+int cmd_load_keys(int argc, const char **argv, struct ndctl_ctx *ctx);
 #endif /* _NDCTL_BUILTIN_H_ */
diff --git a/ndctl/lib/keys.c b/ndctl/lib/keys.c
index 5353bdc4..2fb2c305 100644
--- a/ndctl/lib/keys.c
+++ b/ndctl/lib/keys.c
@@ -72,16 +72,23 @@ static int get_key_desc(struct ndctl_dimm *dimm, char *desc,
 	return 0;
 }
 
-static char *load_key_blob(struct ndctl_ctx *ctx, const char *path, int *size)
+NDCTL_EXPORT char *ndctl_load_key_blob(struct ndctl_ctx *ctx,
+		const char *path, int *size, const char *postfix, int dirfd)
 {
 	struct stat st;
-	FILE *bfile = NULL;
-	ssize_t read;
-	int rc;
-	char *blob, *pl;
+	ssize_t read_bytes = 0;
+	int rc, fd;
+	char *blob, *pl, *rdptr;
 	char prefix[] = "load ";
 
-	rc = stat(path, &st);
+	fd = openat(dirfd, path, O_RDONLY);
+	if (fd < 0) {
+		err(ctx, "failed to open file %s: %s\n",
+				path, strerror(errno));
+		return NULL;
+	}
+
+	rc = fstat(fd, &st);
 	if (rc < 0) {
 		err(ctx, "stat: %s\n", strerror(errno));
 		return NULL;
@@ -97,31 +104,44 @@ static char *load_key_blob(struct ndctl_ctx *ctx, const char *path, int *size)
 	}
 
 	*size = st.st_size + sizeof(prefix) - 1;
+	/*
+	 * We need to increment postfix and space.
+	 * "keyhandle=" is 10 bytes, plus null termination.
+	 */
+	if (postfix)
+		*size += strlen(postfix) + 10 + 1;
 	blob = malloc(*size);
 	if (!blob) {
 		err(ctx, "Unable to allocate memory for blob\n");
 		return NULL;
 	}
 
-	bfile = fopen(path, "r");
-	if (!bfile) {
-		err(ctx, "Unable to open %s: %s\n", path, strerror(errno));
-		free(blob);
-		return NULL;
-	}
-
 	memcpy(blob, prefix, sizeof(prefix) - 1);
 	pl = blob + sizeof(prefix) - 1;
-	read = fread(pl, st.st_size, 1, bfile);
-	if (read < 0) {
-		err(ctx, "Failed to read from blob file: %s\n",
-				strerror(errno));
-		free(blob);
-		fclose(bfile);
-		return NULL;
+
+	rdptr = pl;
+	do {
+		rc = read(fd, rdptr, st.st_size - read_bytes);
+		if (rc < 0) {
+			err(ctx, "Failed to read from blob file: %s\n",
+					strerror(errno));
+			free(blob);
+			close(fd);
+			return NULL;
+		}
+		read_bytes += rc;
+		rdptr += rc;
+	} while (read_bytes != st.st_size);
+
+	close(fd);
+
+	if (postfix) {
+		pl += read_bytes;
+		*pl = ' ';
+		pl++;
+		rc = sprintf(pl, "keyhandle=%s", postfix);
 	}
 
-	fclose(bfile);
 	return blob;
 }
 
@@ -251,7 +271,7 @@ static key_serial_t dimm_load_key(struct ndctl_dimm *dimm,
 	if (rc < 0)
 		return rc;
 
-	blob = load_key_blob(ctx, path, &size);
+	blob = ndctl_load_key_blob(ctx, path, &size, NULL, -1);
 	if (!blob)
 		return -ENOMEM;
 
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index f4b487d4..238c2e1c 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -390,6 +390,7 @@ LIBNDCTL_19 {
 global:
 	ndctl_cmd_xlat_firmware_status;
 	ndctl_cmd_submit_xlat;
+	ndctl_load_key_blob;
 	ndctl_dimm_get_security;
 	ndctl_bus_get_kek_handle;
 	ndctl_dimm_enable_key;
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index 05c39e8e..83cce8c4 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -699,6 +699,8 @@ enum ndctl_security_state {
 	NDCTL_SECURITY_OVERWRITE,
 };
 
+char *ndctl_load_key_blob(struct ndctl_ctx *ctx,
+		const char *path, int *size, const char *postfix, int dirfd);
 enum ndctl_security_state ndctl_dimm_get_security(struct ndctl_dimm *dimm);
 const char *ndctl_bus_get_kek_handle(struct ndctl_bus *bus);
 int ndctl_dimm_update_passphrase(struct ndctl_dimm *dimm,
diff --git a/ndctl/load-keys.c b/ndctl/load-keys.c
new file mode 100644
index 00000000..077e520e
--- /dev/null
+++ b/ndctl/load-keys.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2019 Intel Corporation. All rights reserved. */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
+
+#include <util/json.h>
+#include <util/filter.h>
+#include <json-c/json.h>
+#include <ndctl/libndctl.h>
+#include <util/parse-options.h>
+#include <ccan/array_size/array_size.h>
+
+#include <ndctl.h>
+
+static struct parameters {
+	const char *key_path;
+	const char *tpm_handle;
+} param;
+
+enum key_type {
+	KEY_USER = 0,
+	KEY_TRUSTED,
+};
+
+static const char *key_names[] = {"user", "trusted"};
+
+static struct loadkeys {
+	enum key_type key_type;
+	DIR *dir;
+	int dirfd;
+} loadkey_ctx;
+
+static int load_master_key(struct ndctl_ctx *ctx, struct loadkeys *lk_ctx,
+		const char *keypath)
+{
+	key_serial_t key;
+	char *blob;
+	int size, rc;
+	char path[PATH_MAX];
+
+	rc = sprintf(path, "%s/nvdimm-master.blob", keypath);
+	if (rc < 0)
+		return -errno;
+
+	if (param.tpm_handle)
+		lk_ctx->key_type = KEY_TRUSTED;
+	else
+		lk_ctx->key_type = KEY_USER;
+
+	key = keyctl_search(KEY_SPEC_USER_KEYRING,
+			key_names[lk_ctx->key_type], "nvdimm-master", 0);
+	if (key > 0)	/* check to see if key already loaded */
+		return 0;
+
+	if (key < 0 && errno != ENOKEY) {
+		fprintf(stderr, "keyctl_search() failed: %s\n",
+				strerror(errno));
+		return -errno;
+	}
+
+	blob = ndctl_load_key_blob(ctx, path, &size, param.tpm_handle, -1);
+	if (!blob)
+		return -ENOMEM;
+
+	key = add_key(key_names[lk_ctx->key_type], "nvdimm-master",
+			blob, size, KEY_SPEC_USER_KEYRING);
+	free(blob);
+	if (key < 0) {
+		fprintf(stderr, "add_key failed: %s\n", strerror(errno));
+		return -errno;
+	}
+
+	printf("nvdimm master key loaded.\n");
+
+	return 0;
+}
+
+static int load_dimm_keys(struct ndctl_ctx *ctx, struct loadkeys *lk_ctx)
+{
+	int rc;
+	struct dirent *dent;
+	char *fname, *id, *blob;
+	char desc[ND_KEY_DESC_SIZE];
+	int size, count = 0;
+	key_serial_t key;
+
+	while ((dent = readdir(lk_ctx->dir)) != NULL) {
+		if (dent->d_type != DT_REG)
+			continue;
+
+		fname = strdup(dent->d_name);
+		if (!fname) {
+			fprintf(stderr, "Unable to strdup %s\n",
+					dent->d_name);
+			return -ENOMEM;
+		}
+
+		/*
+		 * We want to pick up the second member of the file name
+		 * as the nvdimm id.
+		 */
+		id = strtok(fname, "_");
+		if (!id)
+			continue;
+		if (strcmp(id, "nvdimm") != 0)
+			continue;
+		id = strtok(NULL, "_");
+		if (!id)
+			continue;
+
+		blob = ndctl_load_key_blob(ctx, dent->d_name, &size, NULL,
+				lk_ctx->dirfd);
+		if (!blob) {
+			free(fname);
+			continue;
+		}
+
+		rc = sprintf(desc, "nvdimm:%s", id);
+		if (rc < 0) {
+			free(fname);
+			free(blob);
+			continue;
+		}
+
+		key = add_key("encrypted", desc, blob, size,
+				KEY_SPEC_USER_KEYRING);
+		if (key < 0)
+			fprintf(stderr, "add_key failed: %s\n",
+					strerror(errno));
+		else
+			count++;
+		free(fname);
+		free(blob);
+	}
+
+	printf("%d nvdimm keys loaded\n", count);
+
+	return 0;
+}
+
+static int check_tpm_handle(struct ndctl_ctx *ctx, struct loadkeys *lk_ctx)
+{
+	int fd, rc;
+	FILE *fs;
+	char *buf;
+
+	fd = openat(lk_ctx->dirfd, "tpm.handle", O_RDONLY);
+	if (fd < 0)
+		return -errno;
+
+	fs = fdopen(fd, "r");
+	if (!fs) {
+		fprintf(stderr, "Failed to open file stream: %s\n",
+				strerror(errno));
+		return -errno;
+	}
+
+	rc = fscanf(fs, "%ms", &buf);
+	if (rc < 0) {
+		rc = -errno;
+		fprintf(stderr, "Failed to read file: %s\n", strerror(errno));
+		fclose(fs);
+		return rc;
+	}
+
+	param.tpm_handle = buf;
+	fclose(fs);
+	return 0;
+}
+
+static int load_keys(struct ndctl_ctx *ctx, struct loadkeys *lk_ctx,
+		const char *keypath, const char *tpmhandle)
+{
+	int rc;
+
+	rc = chdir(keypath);
+	if (rc < 0) {
+		rc = -errno;
+		fprintf(stderr, "Change current work dir to %s failed: %s\n",
+				param.key_path, strerror(errno));
+		rc = -errno;
+		goto erropen;
+	}
+
+	lk_ctx->dir = opendir(param.key_path);
+	if (!lk_ctx->dir) {
+		fprintf(stderr, "Unable to open dir %s: %s\n",
+				param.key_path, strerror(errno));
+		rc = -errno;
+		goto erropen;
+	}
+
+	lk_ctx->dirfd = open(param.key_path, O_DIRECTORY);
+	if (lk_ctx->dirfd < 0) {
+		fprintf(stderr, "Unable to open dir %s: %s\n",
+				param.key_path, strerror(errno));
+		rc = -errno;
+		goto erropen;
+	}
+
+	if (!tpmhandle) {
+		rc = check_tpm_handle(ctx, lk_ctx);
+		if (rc < 0) {
+			rc = -errno;
+			goto erropen;
+		}
+	}
+
+	rc = load_master_key(ctx, lk_ctx, param.key_path);
+	if (rc < 0)
+		goto out;
+
+	rc = load_dimm_keys(ctx, lk_ctx);
+	if (rc < 0)
+		goto out;
+
+     out:
+	close(lk_ctx->dirfd);
+ erropen:
+	closedir(lk_ctx->dir);
+	return rc;
+}
+
+int cmd_load_keys(int argc, const char **argv, struct ndctl_ctx *ctx)
+{
+	const struct option options[] = {
+		OPT_FILENAME('p', "key-path", &param.key_path, "key-path",
+				"override the default key path"),
+		OPT_STRING('t', "tpm-handle", &param.tpm_handle, "tpm-handle",
+				"TPM handle for trusted key"),
+		OPT_END(),
+	};
+	const char *const u[] = {
+		"ndctl load-keys [<options>]",
+		NULL
+	};
+	int i;
+
+	argc = parse_options(argc, argv, options, u, 0);
+	for (i = 0; i < argc; i++)
+		error("unknown parameter \"%s\"\n", argv[i]);
+	if (argc)
+		usage_with_options(u, options);
+
+	if (!param.key_path)
+		param.key_path = strdup(NDCTL_KEYS_DIR);
+
+	return load_keys(ctx, &loadkey_ctx, param.key_path, param.tpm_handle);
+}
diff --git a/ndctl/ndctl.c b/ndctl/ndctl.c
index 283ccc33..f6d0e235 100644
--- a/ndctl/ndctl.c
+++ b/ndctl/ndctl.c
@@ -93,6 +93,7 @@ static struct cmd_struct commands[] = {
 	{ "remove-passphrase", { cmd_passphrase_remove } },
 	{ "freeze-security", { cmd_freeze_security } },
 	{ "sanitize-dimm", { cmd_sanitize_dimm } },
+	{ "load-keys", { cmd_load_keys } },
 	{ "list", { cmd_list } },
 	{ "monitor", { cmd_monitor } },
 	{ "install-encrypt-key", { cmd_install_kek } },

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

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

* [PATCH v9 09/13] ndctl: add overwrite operation support
  2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
                   ` (7 preceding siblings ...)
  2019-01-18  2:39 ` [PATCH v9 08/13] ndctl: add modprobe conf file and load-keys ndctl command Dave Jiang
@ 2019-01-18  2:39 ` Dave Jiang
  2019-01-18  2:39 ` [PATCH v9 10/13] ndctl: add wait-overwrite support Dave Jiang
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Dave Jiang @ 2019-01-18  2:39 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Add support for overwrite to libndctl. The operation will be triggered
by the sanitize-dimm command with -o switch. This will initiate the request
to wipe the entire nvdimm. Success return of the command only indicate
overwrite has started and does not indicate completion of overwrite.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 Documentation/ndctl/ndctl-sanitize-dimm.txt |   12 ++++++-
 ndctl/dimm.c                                |   47 ++++++++++++++++++++++++---
 ndctl/lib/dimm.c                            |    8 +++++
 ndctl/lib/keys.c                            |   33 ++++++++++++++++---
 ndctl/lib/libndctl.sym                      |    2 +
 ndctl/libndctl.h                            |    7 ++++
 6 files changed, 97 insertions(+), 12 deletions(-)

diff --git a/Documentation/ndctl/ndctl-sanitize-dimm.txt b/Documentation/ndctl/ndctl-sanitize-dimm.txt
index f95be28f..158392bf 100644
--- a/Documentation/ndctl/ndctl-sanitize-dimm.txt
+++ b/Documentation/ndctl/ndctl-sanitize-dimm.txt
@@ -5,7 +5,7 @@ ndctl-sanitize-dimm(1)
 
 NAME
 ----
-ndctl-sanitize-dimm - Perform a cryptographic destruction of the contents of the given NVDIMM(s).
+ndctl-sanitize-dimm - Perform a cryptographic destruction or overwrite of the contents of the given NVDIMM(s).
 
 SYNOPSIS
 --------
@@ -23,6 +23,16 @@ OPTIONS
 <dimm>::
 include::xable-dimm-options.txt[]
 
+-c::
+--crypto-erase::
+	Replace the media encryption key causing all existing data to read as
+	cipher text with the new key.  This does not
+	change label data. This is the default sanitize method.
+
+-o::
+--ovewrite::
+	Wipe the entire DIMM, including label data. Can take significant time.
+
 include::../copyright.txt[]
 
 SEE ALSO
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index c346b7fb..2b259a4f 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -45,6 +45,8 @@ static struct parameters {
 	const char *outfile;
 	const char *infile;
 	const char *labelversion;
+	bool crypto_erase;
+	bool overwrite;
 	bool force;
 	bool json;
 	bool verbose;
@@ -901,9 +903,26 @@ static int action_sanitize_dimm(struct ndctl_dimm *dimm,
 		return -EOPNOTSUPP;
 	}
 
-	rc = ndctl_dimm_secure_erase_key(dimm);
-	if (rc < 0)
-		return rc;
+	/*
+	 * Setting crypto erase to be default. The other method will be
+	 * overwrite.
+	 */
+	if (!param.crypto_erase && !param.overwrite) {
+		param.crypto_erase = true;
+		printf("No santize method passed in, default to crypto-erase\n");
+	}
+
+	if (param.crypto_erase) {
+		rc = ndctl_dimm_secure_erase_key(dimm);
+		if (rc < 0)
+			return rc;
+	}
+
+	if (param.overwrite) {
+		rc = ndctl_dimm_overwrite_key(dimm);
+		if (rc < 0)
+			return rc;
+	}
 
 	return 0;
 }
@@ -997,6 +1016,12 @@ OPT_BOOLEAN('f', "force", &param.force, \
 OPT_STRING('V', "label-version", &param.labelversion, "version-number", \
 	"namespace label specification version (default: 1.1)")
 
+#define SANITIZE_OPTIONS() \
+OPT_BOOLEAN('c', "crypto-erase", &param.crypto_erase, \
+		"crypto erase a dimm"), \
+OPT_BOOLEAN('o', "overwrite", &param.overwrite, \
+		"overwrite a dimm")
+
 static const struct option read_options[] = {
 	BASE_OPTIONS(),
 	READ_OPTIONS(),
@@ -1026,6 +1051,12 @@ static const struct option init_options[] = {
 	OPT_END(),
 };
 
+static const struct option sanitize_options[] = {
+	BASE_OPTIONS(),
+	SANITIZE_OPTIONS(),
+	OPT_END(),
+};
+
 static int dimm_action(int argc, const char **argv, struct ndctl_ctx *ctx,
 		int (*action)(struct ndctl_dimm *dimm, struct action_context *actx),
 		const struct option *options, const char *usage)
@@ -1300,10 +1331,14 @@ int cmd_freeze_security(int argc, const char **argv, void *ctx)
 int cmd_sanitize_dimm(int argc, const char **argv, void *ctx)
 {
 	int count = dimm_action(argc, argv, ctx, action_sanitize_dimm,
-			base_options,
+			sanitize_options,
 			"ndctl sanitize-dimm <nmem0> [<nmem1>..<nmemN>] [<options>]");
 
-	fprintf(stderr, "sanitized %d nmem%s.\n", count >= 0 ? count : 0,
-			count > 1 ? "s" : "");
+	if (param.overwrite)
+		fprintf(stderr, "overwrite issued for %d nmem%s.\n",
+				count >= 0 ? count : 0, count > 1 ? "s" : "");
+	else
+		fprintf(stderr, "sanitized %d nmem%s.\n",
+				count >= 0 ? count : 0, count > 1 ? "s" : "");
 	return count >= 0 ? 0 : EXIT_FAILURE;
 }
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
index 50650738..d7b70ebf 100644
--- a/ndctl/lib/dimm.c
+++ b/ndctl/lib/dimm.c
@@ -677,3 +677,11 @@ NDCTL_EXPORT int ndctl_dimm_secure_erase(struct ndctl_dimm *dimm, long key)
 	sprintf(buf, "erase %ld\n", key);
 	return write_security(dimm, buf);
 }
+
+NDCTL_EXPORT int ndctl_dimm_overwrite(struct ndctl_dimm *dimm, long key)
+{
+	char buf[SYSFS_ATTR_SIZE];
+
+	sprintf(buf, "overwrite %ld\n", key);
+	return write_security(dimm, buf);
+}
diff --git a/ndctl/lib/keys.c b/ndctl/lib/keys.c
index 2fb2c305..50784284 100644
--- a/ndctl/lib/keys.c
+++ b/ndctl/lib/keys.c
@@ -93,6 +93,7 @@ NDCTL_EXPORT char *ndctl_load_key_blob(struct ndctl_ctx *ctx,
 		err(ctx, "stat: %s\n", strerror(errno));
 		return NULL;
 	}
+
 	if ((st.st_mode & S_IFMT) != S_IFREG) {
 		err(ctx, "%s not a regular file\n", path);
 		return NULL;
@@ -407,7 +408,7 @@ NDCTL_EXPORT int ndctl_dimm_update_key(struct ndctl_dimm *dimm)
 	return 0;
 }
 
-static key_serial_t check_dimm_key(struct ndctl_dimm *dimm)
+static key_serial_t check_dimm_key(struct ndctl_dimm *dimm, bool need_key)
 {
 	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
 	key_serial_t key;
@@ -415,10 +416,11 @@ static key_serial_t check_dimm_key(struct ndctl_dimm *dimm)
 	key = dimm_check_key(dimm, false);
 	if (key < 0) {
 		key = dimm_load_key(dimm, false);
-		if (key < 0) {
+		if (key < 0 && need_key) {
 			err(ctx, "Unable to load key\n");
 			return -ENOKEY;
-		}
+		} else
+			key = 0;
 	}
 
 	return key;
@@ -451,6 +453,7 @@ static int discard_key(struct ndctl_dimm *dimm)
 		err(ctx, "Unable to cleanup key.\n");
 		return rc;
 	}
+
 	return 0;
 }
 
@@ -459,7 +462,7 @@ NDCTL_EXPORT int ndctl_dimm_remove_key(struct ndctl_dimm *dimm)
 	key_serial_t key;
 	int rc;
 
-	key = check_dimm_key(dimm);
+	key = check_dimm_key(dimm, true);
 	if (key < 0)
 		return key;
 
@@ -476,7 +479,7 @@ NDCTL_EXPORT int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm)
 	key_serial_t key;
 	int rc;
 
-	key = check_dimm_key(dimm);
+	key = check_dimm_key(dimm, true);
 	if (key < 0)
 		return key;
 
@@ -487,3 +490,23 @@ NDCTL_EXPORT int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm)
 
 	return discard_key(dimm);
 }
+
+NDCTL_EXPORT int ndctl_dimm_overwrite_key(struct ndctl_dimm *dimm)
+{
+	key_serial_t key;
+	int rc;
+
+	key = check_dimm_key(dimm, false);
+	if (key < 0)
+		return key;
+
+	rc = run_key_op(dimm, key, ndctl_dimm_overwrite,
+			"overwrite");
+	if (rc < 0)
+		return rc;
+
+	if (key > 0)
+		return discard_key(dimm);
+
+	return 0;
+}
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index 238c2e1c..130bf889 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -401,4 +401,6 @@ global:
 	ndctl_dimm_freeze_security;
 	ndctl_dimm_secure_erase;
 	ndctl_dimm_secure_erase_key;
+	ndctl_dimm_overwrite;
+	ndctl_dimm_overwrite_key;
 } LIBNDCTL_18;
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index 83cce8c4..5826cbfb 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -708,6 +708,7 @@ int ndctl_dimm_update_passphrase(struct ndctl_dimm *dimm,
 int ndctl_dimm_disable_passphrase(struct ndctl_dimm *dimm, long key);
 int ndctl_dimm_freeze_security(struct ndctl_dimm *dimm);
 int ndctl_dimm_secure_erase(struct ndctl_dimm *dimm, long key);
+int ndctl_dimm_overwrite(struct ndctl_dimm *dimm, long key);
 
 enum ndctl_key_type {
 	ND_USER_KEY,
@@ -719,6 +720,7 @@ int ndctl_dimm_enable_key(struct ndctl_dimm *dimm);
 int ndctl_dimm_update_key(struct ndctl_dimm *dimm);
 int ndctl_dimm_remove_key(struct ndctl_dimm *dimm);
 int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm);
+int ndctl_dimm_overwrite_key(struct ndctl_dimm *dimm);
 #else
 static inline int ndctl_dimm_enable_key(struct ndctl_dimm *dimm)
 {
@@ -739,6 +741,11 @@ static inline int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm)
 {
 	return -EOPNOTSUPP;
 }
+
+static inline int ndctl_dimm_overwrite_key(struct ndctl_dimm *dimm)
+{
+	return -EOPNOTSUPP;
+}
 #endif
 
 #define ND_KEY_DESC_SIZE	128

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

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

* [PATCH v9 10/13] ndctl: add wait-overwrite support
  2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
                   ` (8 preceding siblings ...)
  2019-01-18  2:39 ` [PATCH v9 09/13] ndctl: add overwrite operation support Dave Jiang
@ 2019-01-18  2:39 ` Dave Jiang
  2019-01-18  2:39 ` [PATCH v9 11/13] ndctl: master phassphrase management support Dave Jiang
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Dave Jiang @ 2019-01-18  2:39 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Add a blocking 'wait-overwrite' command to ndctl to let a user wait for an
overwrite operation on a dimm to complete.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 Documentation/ndctl/Makefile.am              |    3 +
 Documentation/ndctl/ndctl-wait-overwrite.txt |   31 ++++++++++
 ndctl/builtin.h                              |    1 
 ndctl/dimm.c                                 |   27 +++++++++
 ndctl/lib/dimm.c                             |   78 ++++++++++++++++++++++++++
 ndctl/lib/libndctl.sym                       |    1 
 ndctl/libndctl.h                             |    1 
 ndctl/ndctl.c                                |    1 
 8 files changed, 142 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ndctl/ndctl-wait-overwrite.txt

diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am
index 2481361f..77161cf5 100644
--- a/Documentation/ndctl/Makefile.am
+++ b/Documentation/ndctl/Makefile.am
@@ -54,7 +54,8 @@ man1_MANS = \
 	ndctl-disable-passphrase.1 \
 	ndctl-freeze-security.1 \
 	ndctl-sanitize-dimm.1 \
-	ndctl-load-keys.1
+	ndctl-load-keys.1 \
+	ndctl-wait-overwrite.1
 
 CLEANFILES = $(man1_MANS)
 
diff --git a/Documentation/ndctl/ndctl-wait-overwrite.txt b/Documentation/ndctl/ndctl-wait-overwrite.txt
new file mode 100644
index 00000000..5d4c72ef
--- /dev/null
+++ b/Documentation/ndctl/ndctl-wait-overwrite.txt
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+
+ndctl-wait-overwrite(1)
+=======================
+
+NAME
+----
+ndctl-wait-overwrite - wait for nvdimm overwrite operation to complete
+
+SYNOPSIS
+--------
+[verse]
+'ndctl wait-overwrite' <dimm> [<options>]
+
+DESCRIPTION
+-----------
+The kernel provides a POLL(2) capable sysfs file ('security') to indicate
+the state of overwrite. The 'ndctl wait-overwrite' operation waits for
+a change in the state of the 'security' file across all specified dimms.
+
+OPTIONS
+-------
+-v::
+--verbose::
+	Emit debug messages for the overwrite wait process
+
+include::../copyright.txt[]
+
+SEE ALSO
+--------
+linkndctl:ndctl-sanitize-dimm[1]
diff --git a/ndctl/builtin.h b/ndctl/builtin.h
index 416e4564..3e4fd14f 100644
--- a/ndctl/builtin.h
+++ b/ndctl/builtin.h
@@ -39,4 +39,5 @@ int cmd_passphrase_remove(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_freeze_security(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_sanitize_dimm(int argc, const char **argv, struct ndctl_ctx *ctx);
 int cmd_load_keys(int argc, const char **argv, struct ndctl_ctx *ctx);
+int cmd_wait_overwrite(int argc, const char **argv, struct ndctl_ctx *ctx);
 #endif /* _NDCTL_BUILTIN_H_ */
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index 2b259a4f..df0c187c 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -927,6 +927,24 @@ static int action_sanitize_dimm(struct ndctl_dimm *dimm,
 	return 0;
 }
 
+static int action_wait_overwrite(struct ndctl_dimm *dimm,
+		struct action_context *actx)
+{
+	int rc;
+
+	if (ndctl_dimm_get_security(dimm) < 0) {
+		error("%s: security operation not supported\n",
+				ndctl_dimm_get_devname(dimm));
+		return -EOPNOTSUPP;
+	}
+
+	rc = ndctl_dimm_wait_overwrite(dimm);
+	if (rc == 1)
+		printf("%s: overwrite completed.\n",
+				ndctl_dimm_get_devname(dimm));
+	return rc;
+}
+
 static int __action_init(struct ndctl_dimm *dimm,
 		enum ndctl_namespace_version version, int chk_only)
 {
@@ -1342,3 +1360,12 @@ int cmd_sanitize_dimm(int argc, const char **argv, void *ctx)
 				count >= 0 ? count : 0, count > 1 ? "s" : "");
 	return count >= 0 ? 0 : EXIT_FAILURE;
 }
+
+int cmd_wait_overwrite(int argc, const char **argv, void *ctx)
+{
+	int count = dimm_action(argc, argv, ctx, action_wait_overwrite,
+			base_options,
+			"ndctl wait-overwrite <nmem0> [<nmem1>..<nmemN>] [<options>]");
+
+	return count >= 0 ? 0 : EXIT_FAILURE;
+}
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
index d7b70ebf..150e337a 100644
--- a/ndctl/lib/dimm.c
+++ b/ndctl/lib/dimm.c
@@ -16,6 +16,7 @@
 #include <util/bitmap.h>
 #include <util/sysfs.h>
 #include <stdlib.h>
+#include <poll.h>
 #include "private.h"
 
 static const char NSINDEX_SIGNATURE[] = "NAMESPACE_INDEX\0";
@@ -685,3 +686,80 @@ NDCTL_EXPORT int ndctl_dimm_overwrite(struct ndctl_dimm *dimm, long key)
 	sprintf(buf, "overwrite %ld\n", key);
 	return write_security(dimm, buf);
 }
+
+NDCTL_EXPORT int ndctl_dimm_wait_overwrite(struct ndctl_dimm *dimm)
+{
+	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
+	struct pollfd fds;
+	char buf[SYSFS_ATTR_SIZE];
+	int fd = 0, rc;
+	char *path = dimm->dimm_buf;
+	int len = dimm->buf_len;
+
+	if (snprintf(path, len, "%s/security", dimm->dimm_path) >= len) {
+		err(ctx, "%s: buffer too small!\n",
+				ndctl_dimm_get_devname(dimm));
+		return -ERANGE;
+	}
+
+	fd = open(path, O_RDONLY|O_CLOEXEC);
+	if (fd < 0) {
+		rc = -errno;
+		err(ctx, "open: %s\n", strerror(errno));
+		return rc;
+	}
+	memset(&fds, 0, sizeof(fds));
+	fds.fd = fd;
+
+	rc = sysfs_read_attr(ctx, path, buf);
+	if (rc < 0) {
+		rc = -EOPNOTSUPP;
+		goto out;
+	}
+	/* skipping if we aren't in overwrite state */
+	if (strcmp(buf, "overwrite") != 0) {
+		rc = 0;
+		goto out;
+	}
+
+	for (;;) {
+		rc = sysfs_read_attr(ctx, path, buf);
+		if (rc < 0) {
+			rc = -EOPNOTSUPP;
+			break;
+		}
+
+		if (strcmp(buf, "overwrite") == 0) {
+			rc = poll(&fds, 1, -1);
+			if (rc < 0) {
+				rc = -errno;
+				err(ctx, "poll error: %s\n", strerror(errno));
+				break;
+			}
+			dbg(ctx, "poll wake: revents: %d\n", fds.revents);
+			if (pread(fd, buf, 1, 0) == -1) {
+				rc = -errno;
+				break;
+			}
+			fds.revents = 0;
+		} else {
+			if (strcmp(buf, "disabled") == 0)
+				rc = 1;
+			break;
+		}
+	}
+
+	if (rc == 1)
+		dbg(ctx, "%s: overwrite complete\n",
+				ndctl_dimm_get_devname(dimm));
+	else if (rc == 0)
+		dbg(ctx, "%s: ovewrite skipped\n",
+				ndctl_dimm_get_devname(dimm));
+	else
+		dbg(ctx, "%s: overwrite error waiting for complete\n",
+				ndctl_dimm_get_devname(dimm));
+
+ out:
+	close(fd);
+	return rc;
+}
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index 130bf889..9550537c 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -403,4 +403,5 @@ global:
 	ndctl_dimm_secure_erase_key;
 	ndctl_dimm_overwrite;
 	ndctl_dimm_overwrite_key;
+	ndctl_dimm_wait_overwrite;
 } LIBNDCTL_18;
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index 5826cbfb..09225df9 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -709,6 +709,7 @@ int ndctl_dimm_disable_passphrase(struct ndctl_dimm *dimm, long key);
 int ndctl_dimm_freeze_security(struct ndctl_dimm *dimm);
 int ndctl_dimm_secure_erase(struct ndctl_dimm *dimm, long key);
 int ndctl_dimm_overwrite(struct ndctl_dimm *dimm, long key);
+int ndctl_dimm_wait_overwrite(struct ndctl_dimm *dimm);
 
 enum ndctl_key_type {
 	ND_USER_KEY,
diff --git a/ndctl/ndctl.c b/ndctl/ndctl.c
index f6d0e235..d357ff3d 100644
--- a/ndctl/ndctl.c
+++ b/ndctl/ndctl.c
@@ -94,6 +94,7 @@ static struct cmd_struct commands[] = {
 	{ "freeze-security", { cmd_freeze_security } },
 	{ "sanitize-dimm", { cmd_sanitize_dimm } },
 	{ "load-keys", { cmd_load_keys } },
+	{ "wait-overwrite", { cmd_wait_overwrite } },
 	{ "list", { cmd_list } },
 	{ "monitor", { cmd_monitor } },
 	{ "install-encrypt-key", { cmd_install_kek } },

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

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

* [PATCH v9 11/13] ndctl: master phassphrase management support
  2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
                   ` (9 preceding siblings ...)
  2019-01-18  2:39 ` [PATCH v9 10/13] ndctl: add wait-overwrite support Dave Jiang
@ 2019-01-18  2:39 ` Dave Jiang
  2019-01-18  2:39 ` [PATCH v9 12/13] ndctl: add master secure erase support Dave Jiang
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 24+ messages in thread
From: Dave Jiang @ 2019-01-18  2:39 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Adding master passphrase enabling and update to ndctl. This is a new
feature from Intel DSM v1.8.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 Documentation/ndctl/ndctl-setup-passphrase.txt  |    5 +
 Documentation/ndctl/ndctl-update-passphrase.txt |    5 +
 ndctl/dimm.c                                    |   21 ++++
 ndctl/lib/dimm.c                                |    9 ++
 ndctl/lib/keys.c                                |  110 ++++++++++++++++++-----
 ndctl/lib/libndctl.sym                          |    1 
 ndctl/libndctl.h                                |   16 +++
 7 files changed, 133 insertions(+), 34 deletions(-)

diff --git a/Documentation/ndctl/ndctl-setup-passphrase.txt b/Documentation/ndctl/ndctl-setup-passphrase.txt
index 7d8a1abb..044e9deb 100644
--- a/Documentation/ndctl/ndctl-setup-passphrase.txt
+++ b/Documentation/ndctl/ndctl-setup-passphrase.txt
@@ -31,4 +31,9 @@ OPTIONS
 <dimm>::
 include::xable-dimm-options.txt[]
 
+-m::
+--master-passphrase::
+	Indicates that we are managing the master passphrase instead of the
+	user passphrase.
+
 include::../copyright.txt[]
diff --git a/Documentation/ndctl/ndctl-update-passphrase.txt b/Documentation/ndctl/ndctl-update-passphrase.txt
index ff49ae2d..09e69832 100644
--- a/Documentation/ndctl/ndctl-update-passphrase.txt
+++ b/Documentation/ndctl/ndctl-update-passphrase.txt
@@ -29,6 +29,11 @@ OPTIONS
 <dimm>::
 include::xable-dimm-options.txt[]
 
+-m::
+--master-passphrase::
+	Parameter to indicate that we are managing the master passphrase
+	instead of the user passphrase.
+
 include::../copyright.txt[]
 
 SEE ALSO:
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index df0c187c..4a7cca8e 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -47,6 +47,7 @@ static struct parameters {
 	const char *labelversion;
 	bool crypto_erase;
 	bool overwrite;
+	bool master_pass;
 	bool force;
 	bool json;
 	bool verbose;
@@ -847,7 +848,8 @@ static int action_key_enable(struct ndctl_dimm *dimm,
 		return -EOPNOTSUPP;
 	}
 
-	return ndctl_dimm_enable_key(dimm);
+	return ndctl_dimm_enable_key(dimm,
+			param.master_pass ? ND_MASTER_KEY : ND_USER_KEY);
 }
 
 static int action_key_update(struct ndctl_dimm *dimm,
@@ -859,7 +861,8 @@ static int action_key_update(struct ndctl_dimm *dimm,
 		return -EOPNOTSUPP;
 	}
 
-	return ndctl_dimm_update_key(dimm);
+	return ndctl_dimm_update_key(dimm,
+			param.master_pass ? ND_MASTER_KEY : ND_USER_KEY);
 }
 
 static int action_passphrase_remove(struct ndctl_dimm *dimm,
@@ -1040,6 +1043,10 @@ OPT_BOOLEAN('c', "crypto-erase", &param.crypto_erase, \
 OPT_BOOLEAN('o', "overwrite", &param.overwrite, \
 		"overwrite a dimm")
 
+#define MASTER_OPTIONS() \
+OPT_BOOLEAN('m', "master-passphrase", &param.master_pass, \
+		"use master passphrase")
+
 static const struct option read_options[] = {
 	BASE_OPTIONS(),
 	READ_OPTIONS(),
@@ -1069,9 +1076,15 @@ static const struct option init_options[] = {
 	OPT_END(),
 };
 
+static const struct option master_options[] = {
+	BASE_OPTIONS(),
+	MASTER_OPTIONS(),
+};
+
 static const struct option sanitize_options[] = {
 	BASE_OPTIONS(),
 	SANITIZE_OPTIONS(),
+	MASTER_OPTIONS(),
 	OPT_END(),
 };
 
@@ -1306,7 +1319,7 @@ int cmd_update_firmware(int argc, const char **argv, struct ndctl_ctx *ctx)
 int cmd_passphrase_update(int argc, const char **argv, struct ndctl_ctx *ctx)
 {
 	int count = dimm_action(argc, argv, ctx, action_key_update,
-			base_options,
+			master_options,
 			"ndctl update-passphrase <nmem0> [<nmem1>..<nmemN>] [<options>]");
 
 	fprintf(stderr, "passphrase updated for %d nmem%s.\n", count >= 0 ? count : 0,
@@ -1317,7 +1330,7 @@ int cmd_passphrase_update(int argc, const char **argv, struct ndctl_ctx *ctx)
 int cmd_passphrase_setup(int argc, const char **argv, struct ndctl_ctx *ctx)
 {
 	int count = dimm_action(argc, argv, ctx, action_key_enable,
-			base_options,
+			master_options,
 			"ndctl setup-passphrase <nmem0> [<nmem1>..<nmemN>] [<options>]");
 
 	fprintf(stderr, "passphrase enabled for %d nmem%s.\n", count >= 0 ? count : 0,
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
index 150e337a..5c65d171 100644
--- a/ndctl/lib/dimm.c
+++ b/ndctl/lib/dimm.c
@@ -763,3 +763,12 @@ NDCTL_EXPORT int ndctl_dimm_wait_overwrite(struct ndctl_dimm *dimm)
 	close(fd);
 	return rc;
 }
+
+NDCTL_EXPORT int ndctl_dimm_update_master_passphrase(struct ndctl_dimm *dimm,
+		long ckey, long nkey)
+{
+	char buf[SYSFS_ATTR_SIZE];
+
+	sprintf(buf, "master_update %ld %ld\n", ckey, nkey);
+	return write_security(dimm, buf);
+}
diff --git a/ndctl/lib/keys.c b/ndctl/lib/keys.c
index 50784284..9abff45b 100644
--- a/ndctl/lib/keys.c
+++ b/ndctl/lib/keys.c
@@ -30,16 +30,33 @@ static int get_key_path(struct ndctl_dimm *dimm, char *path,
 		return -errno;
 	}
 
-	if (key_type == ND_USER_OLD_KEY) {
-		rc = sprintf(path, "%s/nvdimmold_%s_%s.blob",
+	switch (key_type) {
+	case ND_USER_OLD_KEY:
+		rc = sprintf(path, "%s/nvdimm-old_%s_%s.blob",
 				NDCTL_KEYS_DIR,
 				ndctl_dimm_get_unique_id(dimm),
 				hostname);
-	} else {
+		break;
+	case ND_USER_KEY:
 		rc = sprintf(path, "%s/nvdimm_%s_%s.blob",
 				NDCTL_KEYS_DIR,
 				ndctl_dimm_get_unique_id(dimm),
 				hostname);
+		break;
+	case ND_MASTER_OLD_KEY:
+		rc = sprintf(path, "%s/nvdimm-master-old_%s_%s.blob",
+				NDCTL_KEYS_DIR,
+				ndctl_dimm_get_unique_id(dimm),
+				hostname);
+		break;
+	case ND_MASTER_KEY:
+		rc = sprintf(path, "%s/nvdimm-master_%s_%s.blob",
+				NDCTL_KEYS_DIR,
+				ndctl_dimm_get_unique_id(dimm),
+				hostname);
+		break;
+	default:
+		return -EINVAL;
 	}
 
 	if (rc < 0) {
@@ -56,12 +73,26 @@ static int get_key_desc(struct ndctl_dimm *dimm, char *desc,
 	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
 	int rc;
 
-	if (key_type == ND_USER_OLD_KEY)
+	switch (key_type) {
+	case ND_USER_OLD_KEY:
 		rc = sprintf(desc, "nvdimm-old:%s",
 				ndctl_dimm_get_unique_id(dimm));
-	else
+		break;
+	case ND_USER_KEY:
 		rc = sprintf(desc, "nvdimm:%s",
 				ndctl_dimm_get_unique_id(dimm));
+		break;
+	case ND_MASTER_OLD_KEY:
+		rc = sprintf(desc, "nvdimm-master-old:%s",
+				ndctl_dimm_get_unique_id(dimm));
+		break;
+	case ND_MASTER_KEY:
+		rc = sprintf(desc, "nvdimm-master:%s",
+				ndctl_dimm_get_unique_id(dimm));
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	if (rc < 0) {
 		err(ctx, "error setting key description: %s\n",
@@ -159,7 +190,8 @@ static key_serial_t dimm_check_key(struct ndctl_dimm *dimm,
 	return keyctl_search(KEY_SPEC_USER_KEYRING, "encrypted", desc, 0);
 }
 
-static key_serial_t dimm_create_key(struct ndctl_dimm *dimm)
+static key_serial_t dimm_create_key(struct ndctl_dimm *dimm,
+		enum ndctl_key_type key_type)
 {
 	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
 	char desc[ND_KEY_DESC_SIZE];
@@ -179,7 +211,7 @@ static key_serial_t dimm_create_key(struct ndctl_dimm *dimm)
 		return -EBUSY;
 	}
 
-	rc = get_key_desc(dimm, desc, ND_USER_KEY);
+	rc = get_key_desc(dimm, desc, key_type);
 	if (rc < 0)
 		return rc;
 
@@ -190,7 +222,7 @@ static key_serial_t dimm_create_key(struct ndctl_dimm *dimm)
 		return -EEXIST;
 	}
 
-	rc = get_key_path(dimm, path, ND_USER_KEY);
+	rc = get_key_path(dimm, path, key_type);
 	if (rc < 0)
 		return rc;
 
@@ -292,13 +324,15 @@ static key_serial_t dimm_load_key(struct ndctl_dimm *dimm,
  * blob, and then attempt to inject the key as old key into the user key
  * ring.
  */
-static key_serial_t move_key_to_old(struct ndctl_dimm *dimm)
+static key_serial_t move_key_to_old(struct ndctl_dimm *dimm,
+		enum ndctl_key_type key_type)
 {
 	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
 	int rc;
 	key_serial_t key;
 	char old_path[PATH_MAX];
 	char new_path[PATH_MAX];
+	enum ndctl_key_type okey_type;
 
 	if (ndctl_dimm_is_active(dimm)) {
 		err(ctx, "regions active on %s, op failed\n",
@@ -306,15 +340,22 @@ static key_serial_t move_key_to_old(struct ndctl_dimm *dimm)
 		return -EBUSY;
 	}
 
-	key = dimm_check_key(dimm, ND_USER_KEY);
+	key = dimm_check_key(dimm, key_type);
 	if (key > 0)
 		keyctl_unlink(key, KEY_SPEC_USER_KEYRING);
 
-	rc = get_key_path(dimm, old_path, ND_USER_KEY);
+	if (key_type == ND_USER_KEY)
+		okey_type = ND_USER_OLD_KEY;
+	else if (key_type == ND_MASTER_KEY)
+		okey_type = ND_MASTER_OLD_KEY;
+	else
+		return -EINVAL;
+
+	rc = get_key_path(dimm, old_path, key_type);
 	if (rc < 0)
 		return rc;
 
-	rc = get_key_path(dimm, new_path, ND_USER_OLD_KEY);
+	rc = get_key_path(dimm, new_path, okey_type);
 	if (rc < 0)
 		return rc;
 
@@ -325,7 +366,7 @@ static key_serial_t move_key_to_old(struct ndctl_dimm *dimm)
 		return -errno;
 	}
 
-	return dimm_load_key(dimm, ND_USER_OLD_KEY);
+	return dimm_load_key(dimm, okey_type);
 }
 
 static int dimm_remove_key(struct ndctl_dimm *dimm,
@@ -354,28 +395,41 @@ static int dimm_remove_key(struct ndctl_dimm *dimm,
 	return 0;
 }
 
-NDCTL_EXPORT int ndctl_dimm_enable_key(struct ndctl_dimm *dimm)
+NDCTL_EXPORT int ndctl_dimm_enable_key(struct ndctl_dimm *dimm,
+		enum ndctl_key_type key_type)
 {
 	key_serial_t key;
 	int rc;
 
-	key = dimm_create_key(dimm);
+	key = dimm_create_key(dimm, key_type);
 	if (key < 0)
 		return key;
 
-	rc = ndctl_dimm_update_passphrase(dimm, 0, key);
+	if (key_type == ND_MASTER_KEY)
+		rc = ndctl_dimm_update_master_passphrase(dimm, 0, key);
+	else
+		rc = ndctl_dimm_update_passphrase(dimm, 0, key);
 	if (rc < 0) {
-		dimm_remove_key(dimm, ND_USER_KEY);
+		dimm_remove_key(dimm, key_type);
 		return rc;
 	}
 
 	return 0;
 }
 
-NDCTL_EXPORT int ndctl_dimm_update_key(struct ndctl_dimm *dimm)
+NDCTL_EXPORT int ndctl_dimm_update_key(struct ndctl_dimm *dimm,
+		enum ndctl_key_type key_type)
 {
 	int rc;
 	key_serial_t old_key, new_key;
+	enum ndctl_key_type okey_type;
+
+	if (key_type == ND_USER_KEY)
+		okey_type = ND_USER_OLD_KEY;
+	else if (key_type == ND_MASTER_KEY)
+		okey_type = ND_MASTER_OLD_KEY;
+	else
+		return -EINVAL;
 
 	/*
 	 * 1. check if current key is loaded and remove
@@ -385,23 +439,27 @@ NDCTL_EXPORT int ndctl_dimm_update_key(struct ndctl_dimm *dimm)
 	 * 5. remove old key
 	 * 6. remove old key blob
 	 */
-	old_key = move_key_to_old(dimm);
+	old_key = move_key_to_old(dimm, key_type);
 	if (old_key < 0)
 		return old_key;
 
-	new_key = dimm_create_key(dimm);
+	new_key = dimm_create_key(dimm, key_type);
 	/* need to create new key here */
 	if (new_key < 0) {
-		new_key = dimm_load_key(dimm, ND_USER_KEY);
+		new_key = dimm_load_key(dimm, key_type);
 		if (new_key < 0)
 			return new_key;
 	}
 
-	rc = ndctl_dimm_update_passphrase(dimm, old_key, new_key);
+	if (key_type == ND_MASTER_KEY)
+		rc = ndctl_dimm_update_master_passphrase(dimm,
+				old_key, new_key);
+	else
+		rc = ndctl_dimm_update_passphrase(dimm, old_key, new_key);
 	if (rc < 0)
 		return rc;
 
-	rc = dimm_remove_key(dimm, ND_USER_OLD_KEY);
+	rc = dimm_remove_key(dimm, okey_type);
 	if (rc < 0)
 		return rc;
 
@@ -413,9 +471,9 @@ static key_serial_t check_dimm_key(struct ndctl_dimm *dimm, bool need_key)
 	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
 	key_serial_t key;
 
-	key = dimm_check_key(dimm, false);
+	key = dimm_check_key(dimm, ND_USER_KEY);
 	if (key < 0) {
-		key = dimm_load_key(dimm, false);
+		key = dimm_load_key(dimm, ND_USER_KEY);
 		if (key < 0 && need_key) {
 			err(ctx, "Unable to load key\n");
 			return -ENOKEY;
@@ -448,7 +506,7 @@ static int discard_key(struct ndctl_dimm *dimm)
 	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
 	int rc;
 
-	rc = dimm_remove_key(dimm, false);
+	rc = dimm_remove_key(dimm, ND_USER_KEY);
 	if (rc < 0) {
 		err(ctx, "Unable to cleanup key.\n");
 		return rc;
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index 9550537c..fd260aae 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -404,4 +404,5 @@ global:
 	ndctl_dimm_overwrite;
 	ndctl_dimm_overwrite_key;
 	ndctl_dimm_wait_overwrite;
+	ndctl_dimm_update_master_passphrase;
 } LIBNDCTL_18;
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index 09225df9..7a5236b8 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -710,25 +710,33 @@ int ndctl_dimm_freeze_security(struct ndctl_dimm *dimm);
 int ndctl_dimm_secure_erase(struct ndctl_dimm *dimm, long key);
 int ndctl_dimm_overwrite(struct ndctl_dimm *dimm, long key);
 int ndctl_dimm_wait_overwrite(struct ndctl_dimm *dimm);
+int ndctl_dimm_update_master_passphrase(struct ndctl_dimm *dimm,
+		long ckey, long nkey);
 
 enum ndctl_key_type {
 	ND_USER_KEY,
 	ND_USER_OLD_KEY,
+	ND_MASTER_KEY,
+	ND_MASTER_OLD_KEY,
 };
 
 #ifdef ENABLE_KEYUTILS
-int ndctl_dimm_enable_key(struct ndctl_dimm *dimm);
-int ndctl_dimm_update_key(struct ndctl_dimm *dimm);
+int ndctl_dimm_enable_key(struct ndctl_dimm *dimm,
+		enum ndctl_key_type key_type);
+int ndctl_dimm_update_key(struct ndctl_dimm *dimm,
+		enum ndctl_key_type key_type);
 int ndctl_dimm_remove_key(struct ndctl_dimm *dimm);
 int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm);
 int ndctl_dimm_overwrite_key(struct ndctl_dimm *dimm);
 #else
-static inline int ndctl_dimm_enable_key(struct ndctl_dimm *dimm)
+static inline int ndctl_dimm_enable_key(struct ndctl_dimm *dimm,
+		enum ndctl_key_type key_type);
 {
 	return -EOPNOTSUPP;
 }
 
-static inline int ndctl_dimm_update_key(struct ndctl_dimm *dimm)
+static inline int ndctl_dimm_update_key(struct ndctl_dimm *dimm,
+		enum ndctl_key_type key_type)
 {
 	return -EOPNOTSUPP;
 }

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

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

* [PATCH v9 12/13] ndctl: add master secure erase support
  2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
                   ` (10 preceding siblings ...)
  2019-01-18  2:39 ` [PATCH v9 11/13] ndctl: master phassphrase management support Dave Jiang
@ 2019-01-18  2:39 ` Dave Jiang
  2019-01-18  2:39 ` [PATCH v9 13/13] ndctl: documentation for security and key management Dave Jiang
  2019-01-18 17:32 ` [PATCH v9 00/13] ndctl: add security support Dave Jiang
  13 siblings, 0 replies; 24+ messages in thread
From: Dave Jiang @ 2019-01-18  2:39 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Intel DSM v1.8 introduced the concept of master passphrase and allowing
nvdimm to be secure erased via the master passphrase in addition to the
user passphrase. Add ndctl support to provide master passphrase secure
erase.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 Documentation/ndctl/ndctl-sanitize-dimm.txt |    6 +++++
 ndctl/dimm.c                                |   13 ++++++++++-
 ndctl/lib/dimm.c                            |    9 ++++++++
 ndctl/lib/keys.c                            |   31 ++++++++++++++++++---------
 ndctl/lib/libndctl.sym                      |    1 +
 ndctl/libndctl.h                            |    7 ++++--
 6 files changed, 53 insertions(+), 14 deletions(-)

diff --git a/Documentation/ndctl/ndctl-sanitize-dimm.txt b/Documentation/ndctl/ndctl-sanitize-dimm.txt
index 158392bf..b01360d2 100644
--- a/Documentation/ndctl/ndctl-sanitize-dimm.txt
+++ b/Documentation/ndctl/ndctl-sanitize-dimm.txt
@@ -33,6 +33,12 @@ include::xable-dimm-options.txt[]
 --ovewrite::
 	Wipe the entire DIMM, including label data. Can take significant time.
 
+-M::
+--master_passphrase::
+	Parameter to indicate that we are managing the master passphrase
+	instead of the user passphrase. This only is applicable to the
+	crypto-erase option.
+
 include::../copyright.txt[]
 
 SEE ALSO
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
index 4a7cca8e..77dc6960 100644
--- a/ndctl/dimm.c
+++ b/ndctl/dimm.c
@@ -906,6 +906,12 @@ static int action_sanitize_dimm(struct ndctl_dimm *dimm,
 		return -EOPNOTSUPP;
 	}
 
+	if (param.overwrite && param.master_pass) {
+		error("%s: overwrite does not support master passphrase\n",
+				ndctl_dimm_get_devname(dimm));
+		return -EINVAL;
+	}
+
 	/*
 	 * Setting crypto erase to be default. The other method will be
 	 * overwrite.
@@ -916,7 +922,8 @@ static int action_sanitize_dimm(struct ndctl_dimm *dimm,
 	}
 
 	if (param.crypto_erase) {
-		rc = ndctl_dimm_secure_erase_key(dimm);
+		rc = ndctl_dimm_secure_erase_key(dimm, param.master_pass ?
+				ND_MASTER_KEY : ND_USER_KEY);
 		if (rc < 0)
 			return rc;
 	}
@@ -1041,7 +1048,9 @@ OPT_STRING('V', "label-version", &param.labelversion, "version-number", \
 OPT_BOOLEAN('c', "crypto-erase", &param.crypto_erase, \
 		"crypto erase a dimm"), \
 OPT_BOOLEAN('o', "overwrite", &param.overwrite, \
-		"overwrite a dimm")
+		"overwrite a dimm"), \
+OPT_BOOLEAN('M', "master-passphrase", &param.master_pass, \
+		"use master passphrase")
 
 #define MASTER_OPTIONS() \
 OPT_BOOLEAN('m', "master-passphrase", &param.master_pass, \
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
index 5c65d171..0a4ca797 100644
--- a/ndctl/lib/dimm.c
+++ b/ndctl/lib/dimm.c
@@ -772,3 +772,12 @@ NDCTL_EXPORT int ndctl_dimm_update_master_passphrase(struct ndctl_dimm *dimm,
 	sprintf(buf, "master_update %ld %ld\n", ckey, nkey);
 	return write_security(dimm, buf);
 }
+
+NDCTL_EXPORT int ndctl_dimm_master_secure_erase(struct ndctl_dimm *dimm,
+		long key)
+{
+	char buf[SYSFS_ATTR_SIZE];
+
+	sprintf(buf, "master_erase %ld\n", key);
+	return write_security(dimm, buf);
+}
diff --git a/ndctl/lib/keys.c b/ndctl/lib/keys.c
index 9abff45b..4d89074d 100644
--- a/ndctl/lib/keys.c
+++ b/ndctl/lib/keys.c
@@ -466,14 +466,15 @@ NDCTL_EXPORT int ndctl_dimm_update_key(struct ndctl_dimm *dimm,
 	return 0;
 }
 
-static key_serial_t check_dimm_key(struct ndctl_dimm *dimm, bool need_key)
+static key_serial_t check_dimm_key(struct ndctl_dimm *dimm, bool need_key,
+		enum ndctl_key_type key_type)
 {
 	struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
 	key_serial_t key;
 
-	key = dimm_check_key(dimm, ND_USER_KEY);
+	key = dimm_check_key(dimm, key_type);
 	if (key < 0) {
-		key = dimm_load_key(dimm, ND_USER_KEY);
+		key = dimm_load_key(dimm, key_type);
 		if (key < 0 && need_key) {
 			err(ctx, "Unable to load key\n");
 			return -ENOKEY;
@@ -520,7 +521,7 @@ NDCTL_EXPORT int ndctl_dimm_remove_key(struct ndctl_dimm *dimm)
 	key_serial_t key;
 	int rc;
 
-	key = check_dimm_key(dimm, true);
+	key = check_dimm_key(dimm, true, ND_USER_KEY);
 	if (key < 0)
 		return key;
 
@@ -532,21 +533,31 @@ NDCTL_EXPORT int ndctl_dimm_remove_key(struct ndctl_dimm *dimm)
 	return discard_key(dimm);
 }
 
-NDCTL_EXPORT int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm)
+NDCTL_EXPORT int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm,
+		enum ndctl_key_type key_type)
 {
 	key_serial_t key;
 	int rc;
 
-	key = check_dimm_key(dimm, true);
+	key = check_dimm_key(dimm, true, key_type);
 	if (key < 0)
 		return key;
 
-	rc = run_key_op(dimm, key, ndctl_dimm_secure_erase,
-			"crypto erase");
+	if (key_type == ND_MASTER_KEY)
+		rc = run_key_op(dimm, key, ndctl_dimm_master_secure_erase,
+				"master crypto erase");
+	else if (key_type == ND_USER_KEY)
+		rc = run_key_op(dimm, key, ndctl_dimm_secure_erase,
+				"crypto erase");
+	else
+		rc = -EINVAL;
 	if (rc < 0)
 		return rc;
 
-	return discard_key(dimm);
+	if (key_type == ND_USER_KEY)
+		return discard_key(dimm);
+
+	return 0;
 }
 
 NDCTL_EXPORT int ndctl_dimm_overwrite_key(struct ndctl_dimm *dimm)
@@ -554,7 +565,7 @@ NDCTL_EXPORT int ndctl_dimm_overwrite_key(struct ndctl_dimm *dimm)
 	key_serial_t key;
 	int rc;
 
-	key = check_dimm_key(dimm, false);
+	key = check_dimm_key(dimm, false, ND_USER_KEY);
 	if (key < 0)
 		return key;
 
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index fd260aae..b4edf0e8 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -405,4 +405,5 @@ global:
 	ndctl_dimm_overwrite_key;
 	ndctl_dimm_wait_overwrite;
 	ndctl_dimm_update_master_passphrase;
+	ndctl_dimm_master_secure_erase;
 } LIBNDCTL_18;
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index 7a5236b8..1840c48c 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -712,6 +712,7 @@ int ndctl_dimm_overwrite(struct ndctl_dimm *dimm, long key);
 int ndctl_dimm_wait_overwrite(struct ndctl_dimm *dimm);
 int ndctl_dimm_update_master_passphrase(struct ndctl_dimm *dimm,
 		long ckey, long nkey);
+int ndctl_dimm_master_secure_erase(struct ndctl_dimm *dimm, long key);
 
 enum ndctl_key_type {
 	ND_USER_KEY,
@@ -726,7 +727,8 @@ int ndctl_dimm_enable_key(struct ndctl_dimm *dimm,
 int ndctl_dimm_update_key(struct ndctl_dimm *dimm,
 		enum ndctl_key_type key_type);
 int ndctl_dimm_remove_key(struct ndctl_dimm *dimm);
-int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm);
+int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm,
+		enum ndctl_key_type key_type);
 int ndctl_dimm_overwrite_key(struct ndctl_dimm *dimm);
 #else
 static inline int ndctl_dimm_enable_key(struct ndctl_dimm *dimm,
@@ -746,7 +748,8 @@ static inline int ndctl_dimm_remove_key(struct ndctl_dimm *dimm)
 	return -EOPNOTSUPP;
 }
 
-static inline int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm)
+static inline int ndctl_dimm_secure_erase_key(struct ndctl_dimm *dimm,
+		enum ndctl_key_type key_type)
 {
 	return -EOPNOTSUPP;
 }

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

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

* [PATCH v9 13/13] ndctl: documentation for security and key management
  2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
                   ` (11 preceding siblings ...)
  2019-01-18  2:39 ` [PATCH v9 12/13] ndctl: add master secure erase support Dave Jiang
@ 2019-01-18  2:39 ` Dave Jiang
  2019-01-18 23:29   ` Verma, Vishal L
  2019-01-18 17:32 ` [PATCH v9 00/13] ndctl: add security support Dave Jiang
  13 siblings, 1 reply; 24+ messages in thread
From: Dave Jiang @ 2019-01-18  2:39 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm

Add a "Theory of Operation" section describing the Intel DSM operations to
the relevant man pages.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 Documentation/ndctl/intel-nvdimm-security.txt   |  139 +++++++++++++++++++++++
 Documentation/ndctl/ndctl-freeze-security.txt   |    2 
 Documentation/ndctl/ndctl-remove-passphrase.txt |    2 
 Documentation/ndctl/ndctl-sanitize-dimm.txt     |    2 
 Documentation/ndctl/ndctl-setup-passphrase.txt  |    2 
 Documentation/ndctl/ndctl-update-passphrase.txt |    2 
 6 files changed, 149 insertions(+)
 create mode 100644 Documentation/ndctl/intel-nvdimm-security.txt

diff --git a/Documentation/ndctl/intel-nvdimm-security.txt b/Documentation/ndctl/intel-nvdimm-security.txt
new file mode 100644
index 00000000..f1de511d
--- /dev/null
+++ b/Documentation/ndctl/intel-nvdimm-security.txt
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+
+THEORY OF OPERATOIN
+-------------------
+With the introduction of Intel Device Specific Methods (DSM) specification
+v1.7 and v1.8 [1], security DSMs were introduced. The operations supported by
+ndctl are enable passhprase, update passphrase, disable security,
+freeze security, secure (crypto) erase, overwrite, master passphrase enable,
+master passphrase update, and master passphrase secure (crypto) erase.
+The 'unlock' DSM is not supported by ndctl, that is left for the kernel to
+manage with some assistance from userspace.
+
+The security management for nvdimm is composed of two parts. The front end
+utilizes the Linux key management framework (trusted and encrypted keys [2]).
+It uses the keyutils on the user side and Linux key management APIs in
+the kernel. The backend takes the decrypted payload of the key and passes the
+plaintext payload to the nvdimm for processing.
+
+Unlike typical DSMs, the security DSMs are managed through the 'security'
+sysfs attribute under the dimm devices rather than an ioctl call by libndctl.
+The relevant key id is written to the 'security' attribute and the kernel will
+pull that key from the kernel's user key ring for processing.
+
+The entire security process starts with a master key that is used to seal the
+encrypted keys that are used to protect the passphrase for each nvdimm. We
+recommend using the *system* master key from the Trusted Platform
+Module (TPM), but a master key generated by the TPM can also
+be used. For testing purposes a user key with randomized payload can
+also be served as a master key. See [2] for details. To perform any security
+operations, it is expected that at the minimum the master key is already
+in the kernel's user keyring as shown in example below:
+
+> keyctl show
+Session Keyring
+ 736023423 --alswrv      0     0  keyring: _ses
+ 675104189 --alswrv      0 65534   \_ keyring: _uid.0
+ 680187394 --alswrv      0     0       \_ trusted: nvdimm-master
+
+Except for 'overwrite', all operations expect the relevant regions associated
+with the nvdimm are disabled before proceeding. For 'overwrite', in addition
+to the regions, the dimm itself is expected to be disabled.
+
+The following sections describe specifics of each security features.
+
+UNLOCK
+------
+Unlock is performed by the kernel, however a preparation step must happen
+before the unlock DSM can be issued by the kernel. The expectation is that
+during initramfs, a setup script is called before the libnvdimm module is
+loaded by modprobe. This script script will inject the master key and the
+related encrypted keys into the kernel's user key ring. A reference modprobe
+config file and a setup script have been provided by ndctl. During the 'probe'
+of the nvdimm driver, it will:
+1. First, check the security state of the device and see if the DIMM is locked
+2. Request the associated encrypted key from the kernel's user key ring.
+3. Finally, create the unlock DSM, copy the decrypted payload into the DSM
+   passphrase field, and issue the DSM to unlock the DIMM.
+
+If the DIMM is already unlocked, the kernel will attempt to revalidate the key.
+This can be overriden with a kernel module parameter. If we fail to revalidate
+the key, the kernel will freeze the security and disallow any further security
+configuration changes.
+
+SETUP USER PASSPHRASE
+----------------------
+To setup the user passphrase for a DIMM, it is expected that the master key
+is already in the kernel's user key ring and the master key name is passed to
+ndctl so it can do key management. An encrypted key with a 32 bytes payload
+and encrypted key format 'enc32' is created and sealed by the master key. Be
+aware that the passphrase is never provided by or visible to the user.
+The decrypted payload for the encrypted key will be randomly generated by the
+kernel and userspace does not have access to this decrypted payload. When the
+encrypted key is created, a binary blob of the encrypted key is written to the
+key blob storage directory (/etc/ndctl/keys). The user is responsible for
+backing up the dimm key blobs to a secure location. When a key is successfully
+loaded into the kernel's user key ring, the payload is decrypted
+and can be accessed by the kernel.
+
+Key ids are written to the 'security' sysfs attribute with the command "update".
+A key id of 0 is provided for the old key id. The kernel will see that the
+update call is an enable call because the 0 old key id. A "passphrase update"
+DSM is issued by the kernel with the old passphrase as 0s.
+
+UPDATE USER PASSPHRASE
+----------------------
+The update user passphrase operation uses the same DSM command as enable user
+passphrase. Most of the work is done on the key management side. The user will
+provide a new master key name for the new passphrase key or use the existing
+one. ndctl will use whatever master key name that is passed in. The following
+operations are performed for update:
+1. Remove the associated encrypted key from the kernel's user key ring.
+2. Rename the key blob to old.
+3. Load the now old key blob into kernel's user key ring with "old" name.
+4. Create new encrypted key and seal with master key.
+5. Generate new key blob.
+6. Send DSM with old and new passphrase via the decrypted key payloads.
+7. On success, remove old key from key ring and old key blob.
+
+REMOVE USER PASSPHRASE
+-----------------------
+The current key id is written to sysfs by ndctl. Upon successfully disabling
+the passphrase, the key is removed from the kernel's user keyring, and the
+associated key blob is deleted.
+
+CRYPTO (SECURE) ERASE
+---------------------
+This operation is similar to passphrase-disable. The kernel will issue
+WBINVD before and after the operation to ensure no data corruption from a stale
+CPU cache. Use ndctl's sanitize-dimm command with the --crypto-erase option to
+perform this operation.
+
+OVERWRITE
+---------
+The overwrite operation wipes the entire nvdimm. The operation can take
+a significant amount of time. Issuing a command is very similar to
+"passphrase-disable" and "secure erase". However, when the command returns
+successfully it just means overwrite has been successfully started.
+The wait-overwrite command for ndctl can be used to wait on the nvdimms that
+are performing overwrite until the operation is completed. Upon successful
+completion of the operation, wbinvd will be issued by the kernel.
+The "sanitize-dimm" command with the --overwrite option is used via ndctl.
+If both --crypto-erase and --overwrite options are passed in, the crypt-erase
+will be issued first before overwrite.
+
+SECURITY FREEZE
+---------------
+This operation requires no key to succeed. ndctl will issue the DSM command
+and upon completion, the security commands besides status query will be locked
+out until the next boot.
+
+MASTER PASSPHRASE SETUP, UPDATE, and CRYPTO ERASE
+-----------------------------------------------------------
+These operations are similar to the user passphrase enable and update. The only
+difference is that a different encrypted key is being used for the master
+passphrase operations. Note that master passphrase has no relation to the
+master key for encryption.
+
+[1] http://pmem.io/documents/NVDIMM_DSM_Interface-V1.8.pdf
+[2] https://www.kernel.org/doc/Documentation/security/keys/trusted-encrypted.rst
diff --git a/Documentation/ndctl/ndctl-freeze-security.txt b/Documentation/ndctl/ndctl-freeze-security.txt
index d14b8a39..43ea81eb 100644
--- a/Documentation/ndctl/ndctl-freeze-security.txt
+++ b/Documentation/ndctl/ndctl-freeze-security.txt
@@ -55,4 +55,6 @@ OPTIONS
 <dimm>::
 include::xable-dimm-options.txt[]
 
+include::intel-nvdimm-security.txt[]
+
 include::../copyright.txt[]
diff --git a/Documentation/ndctl/ndctl-remove-passphrase.txt b/Documentation/ndctl/ndctl-remove-passphrase.txt
index 17ff905b..df83eaee 100644
--- a/Documentation/ndctl/ndctl-remove-passphrase.txt
+++ b/Documentation/ndctl/ndctl-remove-passphrase.txt
@@ -23,4 +23,6 @@ OPTIONS
 <dimm>::
 include::xable-dimm-options.txt[]
 
+include::intel-nvdimm-security.txt[]
+
 include::../copyright.txt[]
diff --git a/Documentation/ndctl/ndctl-sanitize-dimm.txt b/Documentation/ndctl/ndctl-sanitize-dimm.txt
index b01360d2..d28d7013 100644
--- a/Documentation/ndctl/ndctl-sanitize-dimm.txt
+++ b/Documentation/ndctl/ndctl-sanitize-dimm.txt
@@ -39,6 +39,8 @@ include::xable-dimm-options.txt[]
 	instead of the user passphrase. This only is applicable to the
 	crypto-erase option.
 
+include::intel-nvdimm-security.txt[]
+
 include::../copyright.txt[]
 
 SEE ALSO
diff --git a/Documentation/ndctl/ndctl-setup-passphrase.txt b/Documentation/ndctl/ndctl-setup-passphrase.txt
index 044e9deb..a80e5138 100644
--- a/Documentation/ndctl/ndctl-setup-passphrase.txt
+++ b/Documentation/ndctl/ndctl-setup-passphrase.txt
@@ -36,4 +36,6 @@ include::xable-dimm-options.txt[]
 	Indicates that we are managing the master passphrase instead of the
 	user passphrase.
 
+include::intel-nvdimm-security.txt[]
+
 include::../copyright.txt[]
diff --git a/Documentation/ndctl/ndctl-update-passphrase.txt b/Documentation/ndctl/ndctl-update-passphrase.txt
index 09e69832..05bd1ded 100644
--- a/Documentation/ndctl/ndctl-update-passphrase.txt
+++ b/Documentation/ndctl/ndctl-update-passphrase.txt
@@ -34,6 +34,8 @@ include::xable-dimm-options.txt[]
 	Parameter to indicate that we are managing the master passphrase
 	instead of the user passphrase.
 
+include::intel-nvdimm-security.txt[]
+
 include::../copyright.txt[]
 
 SEE ALSO:

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

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

* Re: [PATCH v9 00/13] ndctl: add security support
  2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
                   ` (12 preceding siblings ...)
  2019-01-18  2:39 ` [PATCH v9 13/13] ndctl: documentation for security and key management Dave Jiang
@ 2019-01-18 17:32 ` Dave Jiang
  13 siblings, 0 replies; 24+ messages in thread
From: Dave Jiang @ 2019-01-18 17:32 UTC (permalink / raw)
  To: vishal.l.verma, dan.j.williams; +Cc: linux-nvdimm



On 1/17/19 7:38 PM, Dave Jiang wrote:
> The following series implements mechanisms that utilize the sysfs knobs
> provided by the kernel in order to support the Intel DSM v1.8 spec
> that provides security to NVDIMM. The following abilities are added:
> 1. display security state
> 2. enable/update passphrase
> 3. disable passphrase
> 4. freeze security
> 5. secure erase
> 6. overwrite
> 7. master passphrase enable/update
> 
> v9:
> - Add install-encrypt-key command. (Dan)
> - Change enable-passphrase to setup-passphrase. (Dan)
> - Change disable-passphrase to remove-passphrase. (Dan)
> - Change ndctl_dimm_get_security() to return state directly and remove
>   ndctl_dimm_security_supported(). (Dan)
> - Remove ND_SECURITY_UNSUPPORTED state
> - change ND_SECURITY_* to NDCTL_SECURITY_*
> - Fix man page issues (Dan, Jane)
> - Define NDCTL_KEYSDIR in config.h (Dan)
> - Break check_key_run_and_discard() to 3 helper functions. (Dan)
> - Remove key path input parameter. (Dan)
> - Remove master key input parameter. (Dan)
> - Fixup various issues in security unit test script. (Vishal)

Left out one thing:
- Moved the load key script to an ndctl command load-keys. (Dan)

> 
> v8:
> - Additional cleanup on test script. (Vishal)
> - Change load-keys script into internal command for ndctl. (Dan)
> 
> v7:
> - Added option to provide path to key directory. (Vishal)
> - Cleaned up shell scripts. (Vishal)
> - Cleaned up documentation. (Vishal)
> - Addressed various comments from Vishal.
> 
> v6:
> - Fix spelling and grammar errors for documentation. (Jing)
> - Change bool for indicate master passphrase and old passphrase to enum.
> - Fix key load script master key name.
> - Update to match v15 of kernel patch series.
> 
> v5:
> - Updated to match latest kernel interface (encrypted keys)
> - Added overwrite support
> - Added support for DSM v1.8 master passphrase operations
> - Removed upcall related code
> - Moved security state to enum (Dan)
> - Change security output "security_state" to just "security". (Dan)
> - Break out enable and update passphrase operation. (Dan)
> - Security build can be compiled out when keyutils does not exist. (Dan)
> - Move all keyutils related operations to libndctl. (Dan)
> 
> v4:
> - Updated to match latest kernel interface.
> - Added unit test for all security calls
> 
> v3:
> - Added support to inject keys in order to update nvdimm security.
> 
> v2:
> - Fixup the upcall util to match recent kernel updates for nvdimm security.
> 
> ---
> 
> Dave Jiang (13):
>       ndctl: add support for display security state
>       ndctl: add command for ndctl to receive the key encryption key (master)
>       ndctl: add passphrase update to ndctl
>       ndctl: add disable security support
>       ndctl: add support for freeze security
>       ndctl: add support for sanitize dimm
>       ndctl: add unit test for security ops (minus overwrite)
>       ndctl: add modprobe conf file and load-keys ndctl command
>       ndctl: add overwrite operation support
>       ndctl: add wait-overwrite support
>       ndctl: master phassphrase management support
>       ndctl: add master secure erase support
>       ndctl: documentation for security and key management
> 
> 
>  Documentation/ndctl/Makefile.am                   |   10 
>  Documentation/ndctl/intel-nvdimm-security.txt     |  139 +++++
>  Documentation/ndctl/ndctl-freeze-security.txt     |   60 ++
>  Documentation/ndctl/ndctl-install-encrypt-key.txt |   31 +
>  Documentation/ndctl/ndctl-list.txt                |    8 
>  Documentation/ndctl/ndctl-load-keys.txt           |   43 ++
>  Documentation/ndctl/ndctl-remove-passphrase.txt   |   28 +
>  Documentation/ndctl/ndctl-sanitize-dimm.txt       |   48 ++
>  Documentation/ndctl/ndctl-setup-passphrase.txt    |   41 +
>  Documentation/ndctl/ndctl-update-passphrase.txt   |   43 ++
>  Documentation/ndctl/ndctl-wait-overwrite.txt      |   31 +
>  Makefile.am                                       |    4 
>  configure.ac                                      |   17 +
>  contrib/nvdimm-security.conf                      |    1 
>  ndctl.spec.in                                     |    3 
>  ndctl/Makefile.am                                 |    5 
>  ndctl/builtin.h                                   |    8 
>  ndctl/dimm.c                                      |  232 ++++++++
>  ndctl/kek.c                                       |  133 +++++
>  ndctl/lib/Makefile.am                             |    8 
>  ndctl/lib/dimm.c                                  |  183 +++++++
>  ndctl/lib/keys.c                                  |  581 +++++++++++++++++++++
>  ndctl/lib/libndctl.c                              |   31 +
>  ndctl/lib/libndctl.sym                            |   16 +
>  ndctl/lib/private.h                               |    1 
>  ndctl/libndctl.h                                  |   79 +++
>  ndctl/load-keys.c                                 |  257 +++++++++
>  ndctl/ndctl.c                                     |    8 
>  test/Makefile.am                                  |    4 
>  test/security.sh                                  |  223 ++++++++
>  util/json.c                                       |   17 +
>  31 files changed, 2280 insertions(+), 13 deletions(-)
>  create mode 100644 Documentation/ndctl/intel-nvdimm-security.txt
>  create mode 100644 Documentation/ndctl/ndctl-freeze-security.txt
>  create mode 100644 Documentation/ndctl/ndctl-install-encrypt-key.txt
>  create mode 100644 Documentation/ndctl/ndctl-load-keys.txt
>  create mode 100644 Documentation/ndctl/ndctl-remove-passphrase.txt
>  create mode 100644 Documentation/ndctl/ndctl-sanitize-dimm.txt
>  create mode 100644 Documentation/ndctl/ndctl-setup-passphrase.txt
>  create mode 100644 Documentation/ndctl/ndctl-update-passphrase.txt
>  create mode 100644 Documentation/ndctl/ndctl-wait-overwrite.txt
>  create mode 100644 contrib/nvdimm-security.conf
>  create mode 100644 ndctl/kek.c
>  create mode 100644 ndctl/lib/keys.c
>  create mode 100644 ndctl/load-keys.c
>  create mode 100755 test/security.sh
> 
> --
> 
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* Re: [PATCH v9 02/13] ndctl: add command for ndctl to receive the key encryption key (master)
  2019-01-18  2:38 ` [PATCH v9 02/13] ndctl: add command for ndctl to receive the key encryption key (master) Dave Jiang
@ 2019-01-18 20:58   ` Verma, Vishal L
  2019-01-18 21:12     ` Dave Jiang
  2019-01-23 17:45   ` Dan Williams
  1 sibling, 1 reply; 24+ messages in thread
From: Verma, Vishal L @ 2019-01-18 20:58 UTC (permalink / raw)
  To: Williams, Dan J, Jiang, Dave; +Cc: linux-nvdimm


On Thu, 2019-01-17 at 19:38 -0700, Dave Jiang wrote:
> Add command that allows the user to provide the master encryption key name
> to be installed in the key material directory where ndctl can refer to
> for later security operations.
> 
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> ---
>  Documentation/ndctl/Makefile.am                   |    3 
>  Documentation/ndctl/ndctl-install-encrypt-key.txt |   31 +++++
>  configure.ac                                      |    3 
>  ndctl/Makefile.am                                 |    4 -
>  ndctl/builtin.h                                   |    1 
>  ndctl/kek.c                                       |  133 +++++++++++++++++++++
>  ndctl/lib/libndctl.c                              |   31 +++++
>  ndctl/lib/libndctl.sym                            |    1 
>  ndctl/lib/private.h                               |    1 
>  ndctl/libndctl.h                                  |    1 
>  ndctl/ndctl.c                                     |    1 
>  11 files changed, 208 insertions(+), 2 deletions(-)
>  create mode 100644 Documentation/ndctl/ndctl-install-encrypt-key.txt
>  create mode 100644 ndctl/kek.c
> 
> diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am
> index a30b139b..7cb7bd6b 100644
> --- a/Documentation/ndctl/Makefile.am
> +++ b/Documentation/ndctl/Makefile.am
> @@ -47,7 +47,8 @@ man1_MANS = \
>  	ndctl-inject-smart.1 \
>  	ndctl-update-firmware.1 \
>  	ndctl-list.1 \
> -	ndctl-monitor.1
> +	ndctl-monitor.1 \
> +	ndctl-install-encrypt-key.1

I think Dan's feedback was to call this command setup-passphrase?
By 'install-encrypt-key' it seems unclear whether you mean "install
encrypted key" vs. "install a key and encrypt it"
Alternatively, the command can simply be 'install-kek', and the
synopsis/description can expand on what 'kek' is and how it is used.

>  
>  CLEANFILES = $(man1_MANS)
>  
> diff --git a/Documentation/ndctl/ndctl-install-encrypt-key.txt b/Documentation/ndctl/ndctl-install-encrypt-key.txt
> new file mode 100644
> index 00000000..d00463e3
> --- /dev/null
> +++ b/Documentation/ndctl/ndctl-install-encrypt-key.txt
> @@ -0,0 +1,31 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +ndctl-install-encrypt-key(1)
> +============================
> +
> +NAME
> +----
> +ndctl-install-encrypt-key - store encryption key name for nvdimm bus

"store the encryption key handle for an nvdimm bus"

> +
> +SYNOPSIS
> +--------
> +[verse]
> +'ndctl install-encrypt-key <ndbus0> [<ndbus1>..<ndbusN>] [-k <master encryption key] [<options>]
> +
> +Take the provided master encryption key handle and store it in a file that

This sentence seems incomplete?

> +A file would be created for the designated bus provider.
> +i.e. /etc/ndctl/keys/nfit_test.0.kek

With the makefile-vars-in-man-pages patch[1], all instances of hard
coding this path in the documentation can now be converted to use the
new scheme, and that should keep the man pages in sync with the actual
build options.

[1]: https://patchwork.kernel.org/patch/10771507/


> +The command only succeeds on bus(es) that contain nvdimms with security support.

This should be implied and is true for any command - the command will
only work if the underlying feature is supported by the DIMM/platform,
so I think we can omit this sentence.

I think you had a 'Description' section before, I think it is valuable
to retain it and add a blurb about the keyctl steps that might be
needed before invoking this command.
> +
> +OPTIONS
> +-------
> +-k::
> +--kek=::
> +	Key encryption key (master key) handle. The key handle has the format
> +	of <key type>:<key name>. i.e. trusted:nvdimm-master.
> +
> +-v::
> +--verbose::
> +	Turn on debug output
> +
> +include::../copyright.txt[]
> 
> 

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

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

* Re: [PATCH v9 02/13] ndctl: add command for ndctl to receive the key encryption key (master)
  2019-01-18 20:58   ` Verma, Vishal L
@ 2019-01-18 21:12     ` Dave Jiang
  2019-01-23 17:08       ` Dan Williams
  0 siblings, 1 reply; 24+ messages in thread
From: Dave Jiang @ 2019-01-18 21:12 UTC (permalink / raw)
  To: Verma, Vishal L, Williams, Dan J; +Cc: linux-nvdimm



On 1/18/19 1:58 PM, Verma, Vishal L wrote:
> 
> On Thu, 2019-01-17 at 19:38 -0700, Dave Jiang wrote:
>> Add command that allows the user to provide the master encryption key name
>> to be installed in the key material directory where ndctl can refer to
>> for later security operations.
>>
>> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
>> ---
>>  Documentation/ndctl/Makefile.am                   |    3 
>>  Documentation/ndctl/ndctl-install-encrypt-key.txt |   31 +++++
>>  configure.ac                                      |    3 
>>  ndctl/Makefile.am                                 |    4 -
>>  ndctl/builtin.h                                   |    1 
>>  ndctl/kek.c                                       |  133 +++++++++++++++++++++
>>  ndctl/lib/libndctl.c                              |   31 +++++
>>  ndctl/lib/libndctl.sym                            |    1 
>>  ndctl/lib/private.h                               |    1 
>>  ndctl/libndctl.h                                  |    1 
>>  ndctl/ndctl.c                                     |    1 
>>  11 files changed, 208 insertions(+), 2 deletions(-)
>>  create mode 100644 Documentation/ndctl/ndctl-install-encrypt-key.txt
>>  create mode 100644 ndctl/kek.c
>>
>> diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am
>> index a30b139b..7cb7bd6b 100644
>> --- a/Documentation/ndctl/Makefile.am
>> +++ b/Documentation/ndctl/Makefile.am
>> @@ -47,7 +47,8 @@ man1_MANS = \
>>  	ndctl-inject-smart.1 \
>>  	ndctl-update-firmware.1 \
>>  	ndctl-list.1 \
>> -	ndctl-monitor.1
>> +	ndctl-monitor.1 \
>> +	ndctl-install-encrypt-key.1
> 
> I think Dan's feedback was to call this command setup-passphrase?
> By 'install-encrypt-key' it seems unclear whether you mean "install
> encrypted key" vs. "install a key and encrypt it"
> Alternatively, the command can simply be 'install-kek', and the
> synopsis/description can expand on what 'kek' is and how it is used.

It probably should be called install encrypted key or install encryption
key. The next patch has setup-passphrase. This isn't it.

> 
>>  
>>  CLEANFILES = $(man1_MANS)
>>  
>> diff --git a/Documentation/ndctl/ndctl-install-encrypt-key.txt b/Documentation/ndctl/ndctl-install-encrypt-key.txt
>> new file mode 100644
>> index 00000000..d00463e3
>> --- /dev/null
>> +++ b/Documentation/ndctl/ndctl-install-encrypt-key.txt
>> @@ -0,0 +1,31 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +ndctl-install-encrypt-key(1)
>> +============================
>> +
>> +NAME
>> +----
>> +ndctl-install-encrypt-key - store encryption key name for nvdimm bus
> 
> "store the encryption key handle for an nvdimm bus"
> 
>> +
>> +SYNOPSIS
>> +--------
>> +[verse]
>> +'ndctl install-encrypt-key <ndbus0> [<ndbus1>..<ndbusN>] [-k <master encryption key] [<options>]
>> +
>> +Take the provided master encryption key handle and store it in a file that
> 
> This sentence seems incomplete?
> 
>> +A file would be created for the designated bus provider.
>> +i.e. /etc/ndctl/keys/nfit_test.0.kek
> 
> With the makefile-vars-in-man-pages patch[1], all instances of hard
> coding this path in the documentation can now be converted to use the
> new scheme, and that should keep the man pages in sync with the actual
> build options.
> 
> [1]: https://patchwork.kernel.org/patch/10771507/
> 
> 
>> +The command only succeeds on bus(es) that contain nvdimms with security support.
> 
> This should be implied and is true for any command - the command will
> only work if the underlying feature is supported by the DIMM/platform,
> so I think we can omit this sentence.
> 
> I think you had a 'Description' section before, I think it is valuable
> to retain it and add a blurb about the keyctl steps that might be
> needed before invoking this command.
>> +
>> +OPTIONS
>> +-------
>> +-k::
>> +--kek=::
>> +	Key encryption key (master key) handle. The key handle has the format
>> +	of <key type>:<key name>. i.e. trusted:nvdimm-master.
>> +
>> +-v::
>> +--verbose::
>> +	Turn on debug output
>> +
>> +include::../copyright.txt[]
>>
>>
> 
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* Re: [PATCH v9 13/13] ndctl: documentation for security and key management
  2019-01-18  2:39 ` [PATCH v9 13/13] ndctl: documentation for security and key management Dave Jiang
@ 2019-01-18 23:29   ` Verma, Vishal L
  2019-01-18 23:33     ` Dave Jiang
  0 siblings, 1 reply; 24+ messages in thread
From: Verma, Vishal L @ 2019-01-18 23:29 UTC (permalink / raw)
  To: Williams, Dan J, Jiang, Dave; +Cc: linux-nvdimm


On Thu, 2019-01-17 at 19:39 -0700, Dave Jiang wrote:
> Add a "Theory of Operation" section describing the Intel DSM operations to
> the relevant man pages.
> 
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> ---
>  Documentation/ndctl/intel-nvdimm-security.txt   |  139 +++++++++++++++++++++++
>  Documentation/ndctl/ndctl-freeze-security.txt   |    2 
>  Documentation/ndctl/ndctl-remove-passphrase.txt |    2 
>  Documentation/ndctl/ndctl-sanitize-dimm.txt     |    2 
>  Documentation/ndctl/ndctl-setup-passphrase.txt  |    2 
>  Documentation/ndctl/ndctl-update-passphrase.txt |    2 

Should this also be also be added to the new command,
install-kek/install-encryption-key?

>  6 files changed, 149 insertions(+)
>  create mode 100644 Documentation/ndctl/intel-nvdimm-security.txt

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

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

* Re: [PATCH v9 13/13] ndctl: documentation for security and key management
  2019-01-18 23:29   ` Verma, Vishal L
@ 2019-01-18 23:33     ` Dave Jiang
  0 siblings, 0 replies; 24+ messages in thread
From: Dave Jiang @ 2019-01-18 23:33 UTC (permalink / raw)
  To: Verma, Vishal L, Williams, Dan J; +Cc: linux-nvdimm



On 1/18/19 4:29 PM, Verma, Vishal L wrote:
> 
> On Thu, 2019-01-17 at 19:39 -0700, Dave Jiang wrote:
>> Add a "Theory of Operation" section describing the Intel DSM operations to
>> the relevant man pages.
>>
>> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
>> ---
>>  Documentation/ndctl/intel-nvdimm-security.txt   |  139 +++++++++++++++++++++++
>>  Documentation/ndctl/ndctl-freeze-security.txt   |    2 
>>  Documentation/ndctl/ndctl-remove-passphrase.txt |    2 
>>  Documentation/ndctl/ndctl-sanitize-dimm.txt     |    2 
>>  Documentation/ndctl/ndctl-setup-passphrase.txt  |    2 
>>  Documentation/ndctl/ndctl-update-passphrase.txt |    2 
> 
> Should this also be also be added to the new command,
> install-kek/install-encryption-key?

Yep. Good catch!

> 
>>  6 files changed, 149 insertions(+)
>>  create mode 100644 Documentation/ndctl/intel-nvdimm-security.txt
> 
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* Re: [PATCH v9 02/13] ndctl: add command for ndctl to receive the key encryption key (master)
  2019-01-18 21:12     ` Dave Jiang
@ 2019-01-23 17:08       ` Dan Williams
  0 siblings, 0 replies; 24+ messages in thread
From: Dan Williams @ 2019-01-23 17:08 UTC (permalink / raw)
  To: Dave Jiang; +Cc: linux-nvdimm

On Fri, Jan 18, 2019 at 1:12 PM Dave Jiang <dave.jiang@intel.com> wrote:
>
>
>
> On 1/18/19 1:58 PM, Verma, Vishal L wrote:
> >
> > On Thu, 2019-01-17 at 19:38 -0700, Dave Jiang wrote:
> >> Add command that allows the user to provide the master encryption key name
> >> to be installed in the key material directory where ndctl can refer to
> >> for later security operations.
> >>
> >> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> >> ---
> >>  Documentation/ndctl/Makefile.am                   |    3
> >>  Documentation/ndctl/ndctl-install-encrypt-key.txt |   31 +++++
> >>  configure.ac                                      |    3
> >>  ndctl/Makefile.am                                 |    4 -
> >>  ndctl/builtin.h                                   |    1
> >>  ndctl/kek.c                                       |  133 +++++++++++++++++++++
> >>  ndctl/lib/libndctl.c                              |   31 +++++
> >>  ndctl/lib/libndctl.sym                            |    1
> >>  ndctl/lib/private.h                               |    1
> >>  ndctl/libndctl.h                                  |    1
> >>  ndctl/ndctl.c                                     |    1
> >>  11 files changed, 208 insertions(+), 2 deletions(-)
> >>  create mode 100644 Documentation/ndctl/ndctl-install-encrypt-key.txt
> >>  create mode 100644 ndctl/kek.c
> >>
> >> diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am
> >> index a30b139b..7cb7bd6b 100644
> >> --- a/Documentation/ndctl/Makefile.am
> >> +++ b/Documentation/ndctl/Makefile.am
> >> @@ -47,7 +47,8 @@ man1_MANS = \
> >>      ndctl-inject-smart.1 \
> >>      ndctl-update-firmware.1 \
> >>      ndctl-list.1 \
> >> -    ndctl-monitor.1
> >> +    ndctl-monitor.1 \
> >> +    ndctl-install-encrypt-key.1
> >
> > I think Dan's feedback was to call this command setup-passphrase?
> > By 'install-encrypt-key' it seems unclear whether you mean "install
> > encrypted key" vs. "install a key and encrypt it"
> > Alternatively, the command can simply be 'install-kek', and the
> > synopsis/description can expand on what 'kek' is and how it is used.
>
> It probably should be called install encrypted key or install encryption
> key. The next patch has setup-passphrase. This isn't it.

True, but is it more: configure-key than install-key? All we're doing
at this point is recording the key details into a configuration file.
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* Re: [PATCH v9 02/13] ndctl: add command for ndctl to receive the key encryption key (master)
  2019-01-18  2:38 ` [PATCH v9 02/13] ndctl: add command for ndctl to receive the key encryption key (master) Dave Jiang
  2019-01-18 20:58   ` Verma, Vishal L
@ 2019-01-23 17:45   ` Dan Williams
  2019-01-24  1:07     ` Verma, Vishal L
  1 sibling, 1 reply; 24+ messages in thread
From: Dan Williams @ 2019-01-23 17:45 UTC (permalink / raw)
  To: Dave Jiang; +Cc: linux-nvdimm

On Thu, Jan 17, 2019 at 6:38 PM Dave Jiang <dave.jiang@intel.com> wrote:
>
> Add command that allows the user to provide the master encryption key name
> to be installed in the key material directory where ndctl can refer to
> for later security operations.
>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> ---
>  Documentation/ndctl/Makefile.am                   |    3
>  Documentation/ndctl/ndctl-install-encrypt-key.txt |   31 +++++
>  configure.ac                                      |    3
>  ndctl/Makefile.am                                 |    4 -
>  ndctl/builtin.h                                   |    1
>  ndctl/kek.c                                       |  133 +++++++++++++++++++++
>  ndctl/lib/libndctl.c                              |   31 +++++
>  ndctl/lib/libndctl.sym                            |    1
>  ndctl/lib/private.h                               |    1
>  ndctl/libndctl.h                                  |    1
>  ndctl/ndctl.c                                     |    1
>  11 files changed, 208 insertions(+), 2 deletions(-)
>  create mode 100644 Documentation/ndctl/ndctl-install-encrypt-key.txt
>  create mode 100644 ndctl/kek.c
>
> diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am
> index a30b139b..7cb7bd6b 100644
> --- a/Documentation/ndctl/Makefile.am
> +++ b/Documentation/ndctl/Makefile.am
> @@ -47,7 +47,8 @@ man1_MANS = \
>         ndctl-inject-smart.1 \
>         ndctl-update-firmware.1 \
>         ndctl-list.1 \
> -       ndctl-monitor.1
> +       ndctl-monitor.1 \
> +       ndctl-install-encrypt-key.1
>
>  CLEANFILES = $(man1_MANS)
>
> diff --git a/Documentation/ndctl/ndctl-install-encrypt-key.txt b/Documentation/ndctl/ndctl-install-encrypt-key.txt
> new file mode 100644
> index 00000000..d00463e3
> --- /dev/null
> +++ b/Documentation/ndctl/ndctl-install-encrypt-key.txt
> @@ -0,0 +1,31 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +ndctl-install-encrypt-key(1)
> +============================
> +
> +NAME
> +----
> +ndctl-install-encrypt-key - store encryption key name for nvdimm bus
> +
> +SYNOPSIS
> +--------
> +[verse]
> +'ndctl install-encrypt-key <ndbus0> [<ndbus1>..<ndbusN>] [-k <master encryption key] [<options>]
> +
> +Take the provided master encryption key handle and store it in a file that
> +A file would be created for the designated bus provider.
> +i.e. /etc/ndctl/keys/nfit_test.0.kek
> +The command only succeeds on bus(es) that contain nvdimms with security support.
> +
> +OPTIONS
> +-------
> +-k::
> +--kek=::
> +       Key encryption key (master key) handle. The key handle has the format
> +       of <key type>:<key name>. i.e. trusted:nvdimm-master.
> +
> +-v::
> +--verbose::
> +       Turn on debug output
> +
> +include::../copyright.txt[]
> diff --git a/configure.ac b/configure.ac
> index a02a2d80..61e91e0a 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -159,6 +159,9 @@ ndctl_monitorconf=monitor.conf
>  AC_SUBST([ndctl_monitorconfdir])
>  AC_SUBST([ndctl_monitorconf])
>
> +ndctl_keysdir=${sysconfdir}/ndctl/keys
> +AC_SUBST([ndctl_keysdir])
> +
>  my_CFLAGS="\
>  -Wall \
>  -Wchar-subscripts \
> diff --git a/ndctl/Makefile.am b/ndctl/Makefile.am
> index 97de1814..e412dbf7 100644
> --- a/ndctl/Makefile.am
> +++ b/ndctl/Makefile.am
> @@ -8,6 +8,7 @@ config.h: Makefile.am
>         $(AM_V_GEN) echo "/* Autogenerated by ndctl/Makefile.am */" >$@
>         $(AM_V_GEN) echo '#define NDCTL_CONF_FILE \
>                 "$(ndctl_monitorconfdir)/$(ndctl_monitorconf)"' >>$@
> +       $(AM_V_GEN) echo '#define NDCTL_KEYS_DIR  "$(ndctl_keysdir)"' >>$@
>
>  ndctl_SOURCES = ndctl.c \
>                 bus.c \
> @@ -23,7 +24,8 @@ ndctl_SOURCES = ndctl.c \
>                 util/json-firmware.c \
>                 inject-error.c \
>                 inject-smart.c \
> -               monitor.c
> +               monitor.c \
> +               kek.c
>
>  if ENABLE_DESTRUCTIVE
>  ndctl_SOURCES += ../test/blk_namespaces.c \
> diff --git a/ndctl/builtin.h b/ndctl/builtin.h
> index 17300df0..4af34f04 100644
> --- a/ndctl/builtin.h
> +++ b/ndctl/builtin.h
> @@ -32,4 +32,5 @@ int cmd_bat(int argc, const char **argv, struct ndctl_ctx *ctx);
>  #endif
>  int cmd_update_firmware(int argc, const char **argv, struct ndctl_ctx *ctx);
>  int cmd_inject_smart(int argc, const char **argv, struct ndctl_ctx *ctx);
> +int cmd_install_kek(int argc, const char **argv, struct ndctl_ctx *ctx);
>  #endif /* _NDCTL_BUILTIN_H_ */
> diff --git a/ndctl/kek.c b/ndctl/kek.c
> new file mode 100644
> index 00000000..1cb1555e
> --- /dev/null
> +++ b/ndctl/kek.c
> @@ -0,0 +1,133 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright(c) 2019 Intel Corporation. All rights reserved. */
> +
> +#include <stdio.h>
> +#include <errno.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <limits.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <dirent.h>
> +#include <fcntl.h>
> +#include <util/json.h>
> +#include <util/filter.h>
> +#include <util/log.h>
> +#include <json-c/json.h>
> +#include <ndctl/config.h>
> +#include <ndctl/libndctl.h>
> +#include <util/parse-options.h>
> +#include <ccan/array_size/array_size.h>
> +
> +#include <ndctl.h>
> +
> +static struct parameters {
> +       const char *kek;
> +       bool verbose;
> +} param;
> +
> +static int store_kek(const char *provider, const char *kek)
> +{
> +       char path[PATH_MAX];
> +       FILE *fp;
> +       ssize_t rc, wrote = 0;
> +       int size = strlen(kek);
> +
> +       rc = sprintf(path, "%s/%s.kek", NDCTL_KEYS_DIR, provider);
> +       if (rc < 0) {
> +               perror("sprintf kek path failed");
> +               return rc;
> +       }
> +
> +       fp = fopen(path, "w+");
> +       if (!fp) {
> +               fprintf(stderr, "Opening file %s failed: %s\n",
> +                               path, strerror(errno));
> +               return -errno;
> +       }
> +
> +       do {
> +               rc = fwrite(kek + wrote, 1, size - wrote, fp);
> +               if (rc < 0) {
> +                       fprintf(stderr, "writing file %s failed: %s\n",
> +                                       path, strerror(errno));
> +                       fclose(fp);
> +                       return -errno;
> +               }
> +               wrote += rc;
> +       } while (wrote != size);
> +
> +       fclose(fp);
> +       printf("key handle %s installed to %s\n", kek, path);
> +       return 0;

So the format of this file is just name it by the bus provider and
store the flat key name inside? That would seem to make supporting a
key per-dimm more complicated in the future.

It would be nice to steal the git config file handling since it could
do something like this:

[ key "<description>" ]
    bus = <provider>
    dimm = <dimm unique-id>
    file = <path to key data>

Where multiple keys can be recorded by unique descriptions and the
properties can be used as a match spec to scope that key to a set of
DIMMs. For example a system-wide master key

[ key "system-master" ]
    bus = all
    file = key.blob

...and the following would identify a kek for a single dimm.

[ key "dimm0" ]
    dimm = "8680-57341200"
    file = key.blob

...the roadblock of course being how easy (or not easy) it is to steal
the config file capabilities from git.

Too complicated? Other ideas?
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* Re: [PATCH v9 03/13] ndctl: add passphrase update to ndctl
  2019-01-18  2:38 ` [PATCH v9 03/13] ndctl: add passphrase update to ndctl Dave Jiang
@ 2019-01-23 18:21   ` Dan Williams
  0 siblings, 0 replies; 24+ messages in thread
From: Dan Williams @ 2019-01-23 18:21 UTC (permalink / raw)
  To: Dave Jiang; +Cc: linux-nvdimm

On Thu, Jan 17, 2019 at 6:38 PM Dave Jiang <dave.jiang@intel.com> wrote:
>
> Add API call for triggering sysfs knob to update the security for a DIMM
> in libndctl. Also add the ndctl "update-passphrase" to trigger the
> operation.
>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> ---
>  Documentation/ndctl/Makefile.am                 |    4
>  Documentation/ndctl/ndctl-setup-passphrase.txt  |   34 ++
>  Documentation/ndctl/ndctl-update-passphrase.txt |   36 ++
>  configure.ac                                    |   14 +
>  ndctl.spec.in                                   |    2
>  ndctl/builtin.h                                 |    2
>  ndctl/dimm.c                                    |   68 +++-
>  ndctl/lib/Makefile.am                           |    8
>  ndctl/lib/dimm.c                                |   24 +
>  ndctl/lib/keys.c                                |  387 +++++++++++++++++++++++
>  ndctl/lib/libndctl.sym                          |    3
>  ndctl/libndctl.h                                |   31 ++
>  ndctl/ndctl.c                                   |    2
>  13 files changed, 603 insertions(+), 12 deletions(-)
>  create mode 100644 Documentation/ndctl/ndctl-setup-passphrase.txt
>  create mode 100644 Documentation/ndctl/ndctl-update-passphrase.txt
>  create mode 100644 ndctl/lib/keys.c
[..]
> diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
> index 712223fc..72b6f66c 100644
> --- a/ndctl/lib/dimm.c
> +++ b/ndctl/lib/dimm.c
> @@ -631,3 +631,27 @@ NDCTL_EXPORT enum ndctl_security_state ndctl_dimm_get_security(
[..]
> +NDCTL_EXPORT int ndctl_dimm_update_passphrase(struct ndctl_dimm *dimm,
[..]
> diff --git a/ndctl/lib/keys.c b/ndctl/lib/keys.c
> new file mode 100644
> index 00000000..1ae0ff02
> --- /dev/null
> +++ b/ndctl/lib/keys.c
> @@ -0,0 +1,387 @@
[..]
> +NDCTL_EXPORT int ndctl_dimm_enable_key(struct ndctl_dimm *dimm)
[..]
> +NDCTL_EXPORT int ndctl_dimm_update_key(struct ndctl_dimm *dimm)

So, a general comment. I'm having a hard time envisioning how these
apis and other exports further in the series make sense to a consumer
that is not ndctl/dimm.c? There's quite a bit of assumptions of built
around how the ndctl command uses the keys that makes these apis not
generically useful to anyone else.

Exporting ndctl_dimm_get_security() makes sense because that's
generic, all of these other exports seem specific to the ndctl
implementation / scheme. It would be great to eventually have an api
for 3rd party key management implementations, but I think that's a v65
(or later) concern and we should export as little as possible until it
is clear how a 3rd party implementation would consume the apis.

I think the only private detail of the dimm that needs to be exported
is the raw sysfs interactions. Everything else should be private to
the ndctl use case in something like ndctl/util/keys.c, not publicly
exported in ndctl/lib/keys.
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* Re: [PATCH v9 08/13] ndctl: add modprobe conf file and load-keys ndctl command
  2019-01-18  2:39 ` [PATCH v9 08/13] ndctl: add modprobe conf file and load-keys ndctl command Dave Jiang
@ 2019-01-23 18:25   ` Dan Williams
  0 siblings, 0 replies; 24+ messages in thread
From: Dan Williams @ 2019-01-23 18:25 UTC (permalink / raw)
  To: Dave Jiang; +Cc: linux-nvdimm

On Thu, Jan 17, 2019 at 6:39 PM Dave Jiang <dave.jiang@intel.com> wrote:
>
> Add load-keys command to ndctl. This will attempt to load the master key
> and the related encrypted keys for nvdimms. Also add reference config file
> for modprobe.d in order to call ndctl load-keys and inject keys associated
> with the nvdimms into the kernel user ring for unlock.
>
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> ---
>  Documentation/ndctl/Makefile.am         |    3
>  Documentation/ndctl/ndctl-load-keys.txt |   43 +++++
>  Makefile.am                             |    4
>  contrib/nvdimm-security.conf            |    1
>  ndctl.spec.in                           |    1
>  ndctl/Makefile.am                       |    3
>  ndctl/builtin.h                         |    1
>  ndctl/lib/keys.c                        |   64 +++++---
>  ndctl/lib/libndctl.sym                  |    1
>  ndctl/libndctl.h                        |    2
>  ndctl/load-keys.c                       |  257 +++++++++++++++++++++++++++++++
>  ndctl/ndctl.c                           |    1
>  12 files changed, 357 insertions(+), 24 deletions(-)
>  create mode 100644 Documentation/ndctl/ndctl-load-keys.txt
>  create mode 100644 contrib/nvdimm-security.conf
>  create mode 100644 ndctl/load-keys.c
[..]
> -static char *load_key_blob(struct ndctl_ctx *ctx, const char *path, int *size)
> +NDCTL_EXPORT char *ndctl_load_key_blob(struct ndctl_ctx *ctx,
> +               const char *path, int *size, const char *postfix, int dirfd)

As another example of the comment in patch3 this api seems
particularly difficult to describe how a 3rd party could use it
without subscribing to all of the assumptions of the ndctl
implementation.
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* Re: [PATCH v9 02/13] ndctl: add command for ndctl to receive the key encryption key (master)
  2019-01-23 17:45   ` Dan Williams
@ 2019-01-24  1:07     ` Verma, Vishal L
  0 siblings, 0 replies; 24+ messages in thread
From: Verma, Vishal L @ 2019-01-24  1:07 UTC (permalink / raw)
  To: Williams, Dan J, Jiang, Dave; +Cc: linux-nvdimm


On Wed, 2019-01-23 at 09:45 -0800, Dan Williams wrote:
> > 

[..]

> On Thu, Jan 17, 2019 at 6:38 PM Dave Jiang <dave.jiang@intel.com> wrote:
> > +static int store_kek(const char *provider, const char *kek)
> > +{
> > +       char path[PATH_MAX];
> > +       FILE *fp;
> > +       ssize_t rc, wrote = 0;
> > +       int size = strlen(kek);
> > +
> > +       rc = sprintf(path, "%s/%s.kek", NDCTL_KEYS_DIR, provider);
> > +       if (rc < 0) {
> > +               perror("sprintf kek path failed");
> > +               return rc;
> > +       }
> > +
> > +       fp = fopen(path, "w+");
> > +       if (!fp) {
> > +               fprintf(stderr, "Opening file %s failed: %s\n",
> > +                               path, strerror(errno));
> > +               return -errno;
> > +       }
> > +
> > +       do {
> > +               rc = fwrite(kek + wrote, 1, size - wrote, fp);
> > +               if (rc < 0) {
> > +                       fprintf(stderr, "writing file %s failed: %s\n",
> > +                                       path, strerror(errno));
> > +                       fclose(fp);
> > +                       return -errno;
> > +               }
> > +               wrote += rc;
> > +       } while (wrote != size);
> > +
> > +       fclose(fp);
> > +       printf("key handle %s installed to %s\n", kek, path);
> > +       return 0;
> 
> So the format of this file is just name it by the bus provider and
> store the flat key name inside? That would seem to make supporting a
> key per-dimm more complicated in the future.
> 
> It would be nice to steal the git config file handling since it could
> do something like this:
> 
> [ key "<description>" ]
>     bus = <provider>
>     dimm = <dimm unique-id>
>     file = <path to key data>
> 
> Where multiple keys can be recorded by unique descriptions and the
> properties can be used as a match spec to scope that key to a set of
> DIMMs. For example a system-wide master key
> 
> [ key "system-master" ]
>     bus = all
>     file = key.blob
> 
> ...and the following would identify a kek for a single dimm.
> 
> [ key "dimm0" ]
>     dimm = "8680-57341200"
>     file = key.blob
> 
> ...the roadblock of course being how easy (or not easy) it is to steal
> the config file capabilities from git.
> 
> Too complicated? Other ideas?

I like the general scheme..

But it sounds like a pre-requisite for this might be the config rework
that we will have for ndctl-monitor in the future. I'm trying to think
of how this will tie in with that - ideally we have one global config
file, and that includes sections for different commands. Ideally keys
also get described there.. Maybe each [key "foo"] section can be such a
top level section?

The other option is a security specific config file, but if we're
unifying the config file handling, I think this should be part of it
from the start.

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

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

end of thread, other threads:[~2019-01-24  1:07 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-18  2:38 [PATCH v9 00/13] ndctl: add security support Dave Jiang
2019-01-18  2:38 ` [PATCH v9 01/13] ndctl: add support for display security state Dave Jiang
2019-01-18  2:38 ` [PATCH v9 02/13] ndctl: add command for ndctl to receive the key encryption key (master) Dave Jiang
2019-01-18 20:58   ` Verma, Vishal L
2019-01-18 21:12     ` Dave Jiang
2019-01-23 17:08       ` Dan Williams
2019-01-23 17:45   ` Dan Williams
2019-01-24  1:07     ` Verma, Vishal L
2019-01-18  2:38 ` [PATCH v9 03/13] ndctl: add passphrase update to ndctl Dave Jiang
2019-01-23 18:21   ` Dan Williams
2019-01-18  2:38 ` [PATCH v9 04/13] ndctl: add disable security support Dave Jiang
2019-01-18  2:38 ` [PATCH v9 05/13] ndctl: add support for freeze security Dave Jiang
2019-01-18  2:38 ` [PATCH v9 06/13] ndctl: add support for sanitize dimm Dave Jiang
2019-01-18  2:39 ` [PATCH v9 07/13] ndctl: add unit test for security ops (minus overwrite) Dave Jiang
2019-01-18  2:39 ` [PATCH v9 08/13] ndctl: add modprobe conf file and load-keys ndctl command Dave Jiang
2019-01-23 18:25   ` Dan Williams
2019-01-18  2:39 ` [PATCH v9 09/13] ndctl: add overwrite operation support Dave Jiang
2019-01-18  2:39 ` [PATCH v9 10/13] ndctl: add wait-overwrite support Dave Jiang
2019-01-18  2:39 ` [PATCH v9 11/13] ndctl: master phassphrase management support Dave Jiang
2019-01-18  2:39 ` [PATCH v9 12/13] ndctl: add master secure erase support Dave Jiang
2019-01-18  2:39 ` [PATCH v9 13/13] ndctl: documentation for security and key management Dave Jiang
2019-01-18 23:29   ` Verma, Vishal L
2019-01-18 23:33     ` Dave Jiang
2019-01-18 17:32 ` [PATCH v9 00/13] ndctl: add security support Dave Jiang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.