[PATCH v6 11/12] ndctl: add master secure erase support
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 --- Documentation/ndctl/ndctl-sanitize-dimm.txt |6 + ndctl/dimm.c| 14 +++-- ndctl/lib/dimm.c|9 ndctl/lib/keys.c| 30 --- ndctl/lib/libndctl.sym |1 + ndctl/libndctl.h|7 +- 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/Documentation/ndctl/ndctl-sanitize-dimm.txt b/Documentation/ndctl/ndctl-sanitize-dimm.txt index beb4b2f9..7b036318 100644 --- a/Documentation/ndctl/ndctl-sanitize-dimm.txt +++ b/Documentation/ndctl/ndctl-sanitize-dimm.txt @@ -33,4 +33,10 @@ 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[] diff --git a/ndctl/dimm.c b/ndctl/dimm.c index c60ef96e..b2d50e28 100644 --- a/ndctl/dimm.c +++ b/ndctl/dimm.c @@ -907,6 +907,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. @@ -917,7 +923,9 @@ 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; } @@ -1048,7 +1056,9 @@ OPT_BOOLEAN('M', "master-passphrase", ¶m.master_pass, \ OPT_BOOLEAN('c', "crypto-erase", ¶m.crypto_erase, \ "crypto erase a dimm"), \ OPT_BOOLEAN('o', "overwrite", ¶m.overwrite, \ - "overwrite a dimm") + "overwrite a dimm"), \ +OPT_BOOLEAN('M', "master-passphrase", ¶m.master_pass, \ + "use master passphrase") static const struct option read_options[] = { BASE_OPTIONS(), diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c index 07513b4b..a8013e4b 100644 --- a/ndctl/lib/dimm.c +++ b/ndctl/lib/dimm.c @@ -777,3 +777,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 1d395b48..51532c7a 100644 --- a/ndctl/lib/keys.c +++ b/ndctl/lib/keys.c @@ -437,13 +437,14 @@ NDCTL_EXPORT int ndctl_dimm_update_key(struct ndctl_dimm *dimm, } static int check_key_run_and_discard(struct ndctl_dimm *dimm, - int (*run_op)(struct ndctl_dimm *, long), const char *name) + int (*run_op)(struct ndctl_dimm *, long), const char *name, + enum ndctl_key_type key_type) { struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm); key_serial_t key; int rc; - 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); if (key < 0 && run_op != ndctl_dimm_overwrite) { @@ -460,8 +461,12 @@ static int check_key_run_and_discard(struct ndctl_dimm *dimm, return rc; } + /* we do not delete the key if master secure erase */ + if (key_type == ND_MASTER_KEY) + return 0; + if (key) { - rc = dimm_remove_key(dimm, ND_USER_KEY); + rc = dimm_remove_key(dimm, key_type); if (rc < 0) err(ctx, "Unable to cleanup key.\n"); } @@ -471,17 +476,26 @@ static int check_key_run_and_discard(struct ndctl_dimm *dimm, NDCTL_EXPORT int ndctl_dimm_disable_key(struct ndctl_dimm *dimm) { return check_key_run_and_discard(dimm, ndctl_dimm_disable_passphrase, - "disable passphrase"); + "disable passphrase", ND_USER_KEY); } -NDCTL_EXPORT
[PATCH v6 06/12] ndctl: add unit test for security ops (minus overwrite)
Add unit test for security enable, disable, update, erase, unlock, and freeze. Signed-off-by: Dave Jiang --- test/Makefile.am |4 + test/security.sh | 191 ++ 2 files changed, 195 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 ..5238c9c4 --- /dev/null +++ b/test/security.sh @@ -0,0 +1,191 @@ +#!/bin/bash -Ex +# SPDX-License-Identifier: GPL-2.0 +# Copyright(c) 2018 Intel Corporation. All rights reserved. + +rc=77 +dev="" +id="" +dev_no="" +sstate="" +KEYPATH="/etc/ndctl/keys" +UNLOCK="/sys/devices/platform/nfit_test.0/nfit_test_dimm/test_dimm" +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 .[0].dev | tr -d '"') + [ -n "$dev" ] || err "$LINENO" + id=$($NDCTL list -b $NFIT_TEST_BUS0 -D | jq .[0].id | tr -d '"') + [ -n "$id" ] || err "$LINENO" +} + +setup_keys() +{ + if [ ! -f $MASTERPATH ]; then + keyctl add user $MASTERKEY "`dd if=/dev/urandom bs=1 count=32 2>/dev/null`" @u + keyctl pipe `keyctl search @u user $MASTERKEY` > $MASTERPATH + else + echo "Unclean setup. Please cleanup $MASTERPATH file." + exit 1 + fi +} + +test_cleanup() +{ + keyctl unlink `keyctl search @u encrypted nvdimm:$id` + keyctl unlink `keyctl search @u user $MASTERKEY` + rm -f $KEYPATH/nvdimm_$id\_`hostname`.blob + rm -f $MASTERPATH +} + +locking_dimm() +{ + $NDCTL disable-dimm $dev + dev_no=$(echo $dev | cut -b 5-) + echo 1 > "$UNLOCK$dev_no/lock_dimm" + get_security_state + if [ "$sstate" != "locked" ]; then + echo "Incorrect security state: $sstate expected: disabled" + exit 1 + fi +} + +get_security_state() +{ + sstate=$($NDCTL list -i -b $NFIT_TEST_BUS0 -d $dev | jq .[].dimms[0].security | tr -d '"') + [ -n "$sstate" ] || err "$LINENO" +} + +enable_passphrase() +{ + $NDCTL enable-passphrase -m user:$MASTERKEY $dev + get_security_state + if [ "$sstate" != "unlocked" ]; then + echo "Incorrect security state: $sstate expected: unlocked" + exit 1 + fi +} + +disable_passphrase() +{ + $NDCTL disable-passphrase $dev + get_security_state + if [ "$sstate" != "disabled" ]; then + echo "Incorrect security state: $sstate expected: disabled" + exit 1 + fi +} + +erase_security() +{ + $NDCTL sanitize-dimm -c $dev + get_security_state + if [ "$sstate" != "disabled" ]; then + echo "Incorrect security state: $sstate expected: disabled" + exit 1 + fi +} + +update_security() +{ + $NDCTL update-passphrase -m user:$MASTERKEY $dev + get_security_state + if [ "$sstate" != "unlocked" ]; then + echo "Incorrect security state: $sstate expected: unlocked" + exit 1 + fi +} + +freeze_security() +{ + $NDCTL freeze-security $dev +} + +test_1_security_enable_and_disable() +{ + enable_passphrase + disable_passphrase +} + +test_2_security_enable_and_update() +{ + enable_passphrase + update_security + disable_passphrase +} + +test_3_security_enable_and_erase() +{ + enable_passphrase + erase_security +} + +test_4_security_unlocking() +{ + enable_passphrase + locking_dimm + $NDCTL enable-dimm $dev + get_security_state + if [ "$sstate" != "unlocked" ]; then + echo "Incorrect security state: $sstate expected: unlocked" + exit 1 + fi + $NDCTL disable-region -b $NFIT_TEST_BUS0 all + disable_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() +{ + enable_passphrase + freeze_security + get_security_state + if [ "$sstate" != "frozen" ]; then + echo "Incorrect security state: $sstate expected: frozen" + exit 1 + fi + $NDCTL disable-passphrase $dev && { echo "diable succeed after frozen"; exit 1; } + get_security_state + echo $sstate + if [ "$sstate" != "frozen" ]; then + echo "Incorrect security state: $sstate expected: disabled" + exit 1 + fi +} + +check_min_kver "4.21" || do_skip
[PATCH v6 07/12] ndctl: setup modprobe rules
Adding reference config file for modprobe.d in order to trigger the reference script that will inject keys associated with the nvdimms into the kernel user ring for unlock. Signed-off-by: Dave Jiang --- Makefile.am | 10 ++ contrib/ndctl-loadkeys.sh| 24 contrib/nvdimm_modprobe.conf |1 + 3 files changed, 35 insertions(+) create mode 100755 contrib/ndctl-loadkeys.sh create mode 100644 contrib/nvdimm_modprobe.conf diff --git a/Makefile.am b/Makefile.am index e0c463a3..5a3f03aa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -42,6 +42,16 @@ bashcompletiondir = $(BASH_COMPLETION_DIR) dist_bashcompletion_DATA = contrib/ndctl endif +load_key_file = contrib/ndctl-loadkeys.sh +load_keydir = $(sysconfdir)/ndctl/ +load_key_DATA = $(load_key_file) +EXTRA_DIST += $(load_key_file) + +modprobe_file = contrib/nvdimm_modprobe.conf +modprobedir = $(sysconfdir)/modprobe.d/ +modprobe_DATA = $(modprobe_file) +EXTRA_DIST += $(modprobe_file) + noinst_LIBRARIES = libccan.a libccan_a_SOURCES = \ ccan/str/str.h \ diff --git a/contrib/ndctl-loadkeys.sh b/contrib/ndctl-loadkeys.sh new file mode 100755 index ..dae0a88a --- /dev/null +++ b/contrib/ndctl-loadkeys.sh @@ -0,0 +1,24 @@ +#!/bin/bash -Ex + +# This script assumes a single master key for all DIMMs + +KEY_PATH=/etc/ndctl/keys +TPMH_PATH=$KEY_PATH/tpm.handle +KEYTPE="" +TPM_HANDLE="" +id="" + +if [ -f $TPMH_PATH ]; then + KEYTYPE=trusted + TPM_HANDLE="keyhandle=`cat $TPMH_PATH`" +else + KEYTYPE=user +fi + +keyctl show | grep -q nvdimm-master || keyctl add $KEYTYPE nvdimm-master "load `cat $KEY_PATH/nvdimm-master.blob` $TPM_HANDLE" @u > /dev/null + +for i in `ls -1 $KEY_PATH/nvdimm_*.blob`; +do + id=`echo $i | cut -d'_' -f2` + keyctl add encrypted nvdimm:$id "load `cat $i`" @u +done diff --git a/contrib/nvdimm_modprobe.conf b/contrib/nvdimm_modprobe.conf new file mode 100644 index ..b113d8d7 --- /dev/null +++ b/contrib/nvdimm_modprobe.conf @@ -0,0 +1 @@ +install libnvdimm /usr/sbin/ndctl-loadkeys.sh ; /sbin/modprobe --ignore-install libnvdimm $CMDLINE_OPTS ___ Linux-nvdimm mailing list Linux-nvdimm@lists.01.org https://lists.01.org/mailman/listinfo/linux-nvdimm
[PATCH v6 01/12] ndctl: add support for display security state
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 --- Documentation/ndctl/ndctl-list.txt |8 ndctl/lib/dimm.c | 37 ndctl/lib/libndctl.sym |5 + ndctl/libndctl.h | 13 + util/json.c| 31 ++ 5 files changed, 94 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-", + "handle":0, + "phys_id":0, + "security:":"disabled" +} -H:: --health:: diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c index 5e41734d..cd2895c9 100644 --- a/ndctl/lib/dimm.c +++ b/ndctl/lib/dimm.c @@ -583,3 +583,40 @@ NDCTL_EXPORT unsigned long ndctl_dimm_get_available_labels( return strtoul(buf, NULL, 0); } + +NDCTL_EXPORT int ndctl_dimm_get_security(struct ndctl_dimm *dimm, + enum nd_security_state *state) +{ + 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 -ERANGE; + } + + rc = sysfs_read_attr(ctx, path, buf); + if (rc < 0) + return rc; + + if (strcmp(buf, "unsupported") == 0) + *state = ND_SECURITY_UNSUPPORTED; + else if (strcmp(buf, "disabled") == 0) + *state = ND_SECURITY_DISABLED; + else if (strcmp(buf, "unlocked") == 0) + *state = ND_SECURITY_UNLOCKED; + else if (strcmp(buf, "locked") == 0) + *state = ND_SECURITY_LOCKED; + else if (strcmp(buf, "frozen") == 0) + *state = ND_SECURITY_FROZEN; + else if (strcmp(buf, "overwrite") == 0) + *state = ND_SECURITY_OVERWRITE; + else + *state = ND_SECURITY_INVALID; + + return 0; +} diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym index 6c4c8b4d..1bd63fa1 100644 --- a/ndctl/lib/libndctl.sym +++ b/ndctl/lib/libndctl.sym @@ -385,3 +385,8 @@ global: ndctl_namespace_get_next_badblock; ndctl_dimm_get_dirty_shutdown; } LIBNDCTL_17; + +LIBNDCTL_19 { +global: + ndctl_dimm_get_security; +} LIBNDCTL_18; diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h index 62cef9e8..a9f9167a 100644 --- a/ndctl/libndctl.h +++ b/ndctl/libndctl.h @@ -681,6 +681,19 @@ 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); +enum nd_security_state { + ND_SECURITY_INVALID = -1, + ND_SECURITY_UNSUPPORTED = 0, + ND_SECURITY_DISABLED, + ND_SECURITY_UNLOCKED, + ND_SECURITY_LOCKED, + ND_SECURITY_FROZEN, + ND_SECURITY_OVERWRITE, +}; + +int ndctl_dimm_get_security(struct ndctl_dimm *dimm, + enum nd_security_state *sstate); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/util/json.c b/util/json.c index 5c3424e2..e3b9e72e 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 nd_security_state sstate; if (!jdimm) return NULL; @@ -243,6 +244,36 @@ struct json_object *util_dimm_to_json(struct ndctl_dimm *dimm, json_object_object_add(jdimm, "flag_smart_event", jobj); } + if (ndctl_dimm_get_security(dimm, &sstate) == 0) { + switch (sstate) { + case ND_SECURITY_UNSUPPORTED: + jobj = json_object_new_string("unsupported"); + break; + case ND_SECURITY_DISABLED: + jobj = json_object_new_string("disabled"); + break; + case ND_SECURITY_UNLOCKED: + jobj = json_object_new_string("unlocked"); + break; + case ND_SECURITY_LOCKED: + jobj = json_object_new_string("locked"); + break; + case ND_SECURITY_FROZEN: + jobj = json_object_new_string("frozen"); +
[PATCH v6 00/12] ndctl: add security support
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 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 (12): ndctl: add support for display security state 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: setup modprobe rules ndctl: add overwrite operation support ndctl: add overwrite-wait support ndctl: master phassphrase management support ndctl: add master secure erase support ndctl: documentation for security and key management Documentation/ndctl/Makefile.am |8 Documentation/ndctl/intel-nvdimm-security.txt| 139 ++ Documentation/ndctl/ndctl-disable-passphrase.txt | 29 + Documentation/ndctl/ndctl-enable-passphrase.txt | 44 ++ Documentation/ndctl/ndctl-freeze-security.txt| 22 + Documentation/ndctl/ndctl-list.txt |8 Documentation/ndctl/ndctl-sanitize-dimm.txt | 44 ++ Documentation/ndctl/ndctl-update-passphrase.txt | 40 ++ Documentation/ndctl/ndctl-wait-overwrite.txt | 31 + Makefile.am | 10 builtin.h|6 configure.ac | 14 + contrib/ndctl-loadkeys.sh| 24 + contrib/nvdimm_modprobe.conf |1 ndctl.spec.in|2 ndctl/Makefile.am|3 ndctl/dimm.c | 242 ++- ndctl/lib/Makefile.am|8 ndctl/lib/dimm.c | 203 + ndctl/lib/keys.c | 501 ++ ndctl/lib/libndctl.sym | 19 + ndctl/libndctl.h | 76 +++ ndctl/ndctl.c|6 test/Makefile.am |4 test/security.sh | 191 util/json.c | 31 + 26 files changed, 1693 insertions(+), 13 deletions(-) create mode 100644 Documentation/ndctl/intel-nvdimm-security.txt create mode 100644 Documentation/ndctl/ndctl-disable-passphrase.txt create mode 100644 Documentation/ndctl/ndctl-enable-passphrase.txt create mode 100644 Documentation/ndctl/ndctl-freeze-security.txt create mode 100644 Documentation/ndctl/ndctl-sanitize-dimm.txt create mode 100644 Documentation/ndctl/ndctl-update-passphrase.txt create mode 100644 Documentation/ndctl/ndctl-wait-overwrite.txt create mode 100755 contrib/ndctl-loadkeys.sh create mode 100644 contrib/nvdimm_modprobe.conf create mode 100644 ndctl/lib/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
[PATCH v6 02/12] ndctl: add passphrase update to ndctl
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 --- Documentation/ndctl/Makefile.am |4 Documentation/ndctl/ndctl-enable-passphrase.txt | 35 ++ Documentation/ndctl/ndctl-update-passphrase.txt | 33 ++ builtin.h |2 configure.ac| 14 + ndctl.spec.in |2 ndctl/Makefile.am |3 ndctl/dimm.c| 86 - ndctl/lib/Makefile.am |8 ndctl/lib/dimm.c| 39 ++ ndctl/lib/keys.c| 389 +++ ndctl/lib/libndctl.sym |4 ndctl/libndctl.h| 31 ++ ndctl/ndctl.c |2 14 files changed, 639 insertions(+), 13 deletions(-) create mode 100644 Documentation/ndctl/ndctl-enable-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 a30b139b..7adb 100644 --- a/Documentation/ndctl/Makefile.am +++ b/Documentation/ndctl/Makefile.am @@ -47,7 +47,9 @@ man1_MANS = \ ndctl-inject-smart.1 \ ndctl-update-firmware.1 \ ndctl-list.1 \ - ndctl-monitor.1 + ndctl-monitor.1 \ + ndctl-enable-passphrase.1 \ + ndctl-update-passphrase.1 CLEANFILES = $(man1_MANS) diff --git a/Documentation/ndctl/ndctl-enable-passphrase.txt b/Documentation/ndctl/ndctl-enable-passphrase.txt new file mode 100644 index ..8de5410c --- /dev/null +++ b/Documentation/ndctl/ndctl-enable-passphrase.txt @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0 + +ndctl-enable-passphrase(1) +== + +NAME + +ndctl-enable-passphrase - enabling the security passphrase for a NVDIMM + +SYNOPSIS + +[verse] +'ndctl enable-passphrase' [] + +DESCRIPTION +--- +Provide a generic interface for enabling security for NVDIMM. +It is expected that the master key has already been loaded into the user +key ring. The encrypted key blobs will be created in /etc/nvdimm directory +with the file name of "nvdimm--.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. Do not touch the /etc/nvdimm +directory and let ndctl manage the keys, unless you know what you are doing. + +OPTIONS +--- +:: +include::xable-dimm-options.txt[] + +-m:: +--master=:: + Key name for the master key used to seal the NVDIMM security keys. + +include::../copyright.txt[] diff --git a/Documentation/ndctl/ndctl-update-passphrase.txt b/Documentation/ndctl/ndctl-update-passphrase.txt new file mode 100644 index ..9ed39cca --- /dev/null +++ b/Documentation/ndctl/ndctl-update-passphrase.txt @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0 + +ndctl-update-passphrase(1) +== + +NAME + +ndctl-update-passphrase - update the security passphrase for a NVDIMM + +SYNOPSIS + +[verse] +'ndctl update-passphrase' [] + +DESCRIPTION +--- +Provide a generic interface for updating security key for NVDIMM. +It is expected that the current and the new (if new master key is desired) +master key has already been loaded into the user key ring. The new encrypted +key blobs will be created in /etc/nvdimm directory +with the file name of "nvdimm--.blob". + +OPTIONS +--- +:: +include::xable-dimm-options.txt[] + +-m:: +--master:: + New key name for the master key to seal the new nvdimm key, or the + existing master key name. i.e trusted:master-key. + +include::../copyright.txt[] diff --git a/builtin.h b/builtin.h index 675a6ce7..ed018d96 100644 --- a/builtin.h +++ b/builtin.h @@ -48,4 +48,6 @@ int cmd_bat(int argc, const char **argv, void *ctx); #endif int cmd_update_firmware(int argc, const char **argv, void *ctx); int cmd_inject_smart(int argc, const char **argv, void *ctx); +int cmd_passphrase_setup(int argc, const char **argv, void *ctx); +int cmd_passphrase_update(int argc, const char **argv, void *ctx); #endif /* _NDCTL_BUILTIN_H_ */ diff --git a/configure.ac b/configure.ac index bb6b0332..ac4f56c3 100644 --- a/configure.ac +++ b/configure.ac @@ -153,6 +153,20 @@ fi AC_SUBST([systemd_unitdir]) AM_CONDITIONAL([ENABLE_SYSTEMD_UNITS], [test "x$with_systemd" = "xyes"]) +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
[PATCH v6 12/12] ndctl: documentation for security and key management
Adding the theory of operation for Intel DSM operations. Signed-off-by: Dave Jiang --- Documentation/ndctl/intel-nvdimm-security.txt| 139 ++ Documentation/ndctl/ndctl-disable-passphrase.txt |2 Documentation/ndctl/ndctl-enable-passphrase.txt |4 + Documentation/ndctl/ndctl-freeze-security.txt|2 Documentation/ndctl/ndctl-sanitize-dimm.txt |2 Documentation/ndctl/ndctl-update-passphrase.txt |2 6 files changed, 151 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 ..0c9a41a4 --- /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. Ndctl supports 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 DSM that is not supported by +ndctl is the unlock DSM, which is left to the kernel to manage. + +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 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 trusted key from the Trusted Platform +Module (TPM). However, a trusted master key generated by the TPM can also +be used. And 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 minimal the master key is already +in the kernel 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 + +All operations expect the relevant regions associated to the nvdimm are +disabled before proceeding, except overwrite. Overwrite expects the +relevant nvdimm also be disabled. + +The follow on 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. The said script will inject the master key and the +related encrypted keys into the kernel user key ring. A reference modprobe +config file and a setup script have been provided by ndctl. When the +nvdimm driver probes, 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 user key ring. +3. Finally, create the unlock DSM and 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. + +ENABLE USER PASSPHRASE +-- +To enable the user passphrase for a DIMM, it is expected that the master key +is already in the kernel user key ring and the master key name is passed to +ndctl so it can do key management. An encrypted key with a 32byte 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 +designated key blob storage directory (/etc/ndctl/keys as default). The user is +responsible for backing up the dimm key blobs to a secure location. When a key +is successfully loaded into the kernel user key ring, the payload is decrypted +and can be ac
[PATCH v6 05/12] ndctl: add support for sanitize dimm
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 --- Documentation/ndctl/Makefile.am |3 +- Documentation/ndctl/ndctl-sanitize-dimm.txt | 32 + builtin.h |1 + ndctl/dimm.c| 51 +++ ndctl/lib/dimm.c|8 ndctl/lib/keys.c| 19 -- ndctl/lib/libndctl.sym |2 + ndctl/libndctl.h|7 ndctl/ndctl.c |1 + 9 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 Documentation/ndctl/ndctl-sanitize-dimm.txt diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am index a97f193d..bbea9674 100644 --- a/Documentation/ndctl/Makefile.am +++ b/Documentation/ndctl/Makefile.am @@ -51,7 +51,8 @@ man1_MANS = \ ndctl-enable-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 ..a6802d30 --- /dev/null +++ b/Documentation/ndctl/ndctl-sanitize-dimm.txt @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 + +ndctl-sanitize-dimm(1) +== + +NAME + +ndctl-sanitize-dimm - sanitize the data on the NVDIMM + +SYNOPSIS + +[verse] +'ndctl sanitize' [] + +DESCRIPTION +--- +Provide a generic interface to crypto erase a NVDIMM. +Ndctl will search the user key ring for the associated DIMM. If no key is +found, it will attempt to load the key blob from the expected location. Ndctl +will remove the key and the key blob once security is disabled. + +OPTIONS +--- +:: +include::xable-dimm-options.txt[] + +-c:: +--crypto-erase:: + Replaces encryption keys and securely erases the data. This does not + change label data. This is the default sanitize method. + +include::../copyright.txt[] diff --git a/builtin.h b/builtin.h index 827295da..db0f2858 100644 --- a/builtin.h +++ b/builtin.h @@ -52,4 +52,5 @@ int cmd_passphrase_setup(int argc, const char **argv, void *ctx); int cmd_passphrase_update(int argc, const char **argv, void *ctx); int cmd_disable_passphrase(int argc, const char **argv, void *ctx); int cmd_freeze_security(int argc, const char **argv, void *ctx); +int cmd_sanitize_dimm(int argc, const char **argv, void *ctx); #endif /* _NDCTL_BUILTIN_H_ */ diff --git a/ndctl/dimm.c b/ndctl/dimm.c index 6476b6e5..ae674f78 100644 --- a/ndctl/dimm.c +++ b/ndctl/dimm.c @@ -46,6 +46,7 @@ static struct parameters { const char *infile; const char *labelversion; const char *master_key; + bool crypto_erase; bool force; bool json; bool verbose; @@ -891,6 +892,35 @@ 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_security_supported(dimm)) { + error("%s: security operation not supported\n", + ndctl_dimm_get_devname(dimm)); + return -EOPNOTSUPP; + } + + /* +* Setting crypto erase to be default. The other method will be +* overwrite. +*/ + if (!param.crypto_erase) { + 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; + } + + return 0; +} + static int __action_init(struct ndctl_dimm *dimm, enum ndctl_namespace_version version, int chk_only) { @@ -984,6 +1014,10 @@ OPT_STRING('V', "label-version", ¶m.labelversion, "version-number", \ OPT_STRING('m', "master-key", ¶m.master_key, ":", \ "master key for security") +#define SANITIZE_OPTIONS() \ +OPT_BOOLEAN('c', "crypto-erase", ¶m.crypto_erase, \ + "crypto erase a dimm") + static const struct option read_options[] = { BASE_OPTIONS(), READ_OPTIONS(), @@ -1019,6 +1053,12 @@ static const struct option key_options[] = { OPT_END(), }; +static const struct option sanitize_options[] = { + BASE_OPTIONS(), + SANITIZE_OPTIONS(), + OPT_END(), +}; + static int dimm_action(int argc, const char **argv, void *ctx, int (*action)(struct ndctl_dimm *dimm, struct action_context *actx), const struct option *opti
[PATCH v6 03/12] ndctl: add disable security support
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 --- Documentation/ndctl/Makefile.am |3 ++ Documentation/ndctl/ndctl-disable-passphrase.txt | 27 + builtin.h|1 + ndctl/dimm.c | 22 + ndctl/lib/dimm.c |9 +++ ndctl/lib/keys.c | 28 ++ ndctl/lib/libndctl.sym |2 ++ ndctl/libndctl.h |7 ++ ndctl/ndctl.c|1 + 9 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 Documentation/ndctl/ndctl-disable-passphrase.txt diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am index 7adb..31570a77 100644 --- a/Documentation/ndctl/Makefile.am +++ b/Documentation/ndctl/Makefile.am @@ -49,7 +49,8 @@ man1_MANS = \ ndctl-list.1 \ ndctl-monitor.1 \ ndctl-enable-passphrase.1 \ - ndctl-update-passphrase.1 + ndctl-update-passphrase.1 \ + ndctl-disable-passphrase.1 CLEANFILES = $(man1_MANS) diff --git a/Documentation/ndctl/ndctl-disable-passphrase.txt b/Documentation/ndctl/ndctl-disable-passphrase.txt new file mode 100644 index ..e921eb23 --- /dev/null +++ b/Documentation/ndctl/ndctl-disable-passphrase.txt @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 + +ndctl-disable-passphrase(1) +=== + +NAME + +ndctl-disable-passphrase - disabling passphrase for an NVDIMM + +SYNOPSIS + +[verse] +'ndctl disable-passphrase' [] + +DESCRIPTION +--- +Provide a generic interface for disabling passphrase for NVDIMM. +Ndctl will search the user key ring for the associated DIMM. If no key is +found, it will attempt to load the key blob from the expected location. Ndctl +will remove the key and the key blob once passphrase is disabled. + +OPTIONS +--- +:: +include::xable-dimm-options.txt[] + +include::../copyright.txt[] diff --git a/builtin.h b/builtin.h index ed018d96..8d8f61e2 100644 --- a/builtin.h +++ b/builtin.h @@ -50,4 +50,5 @@ int cmd_update_firmware(int argc, const char **argv, void *ctx); int cmd_inject_smart(int argc, const char **argv, void *ctx); int cmd_passphrase_setup(int argc, const char **argv, void *ctx); int cmd_passphrase_update(int argc, const char **argv, void *ctx); +int cmd_disable_passphrase(int argc, const char **argv, void *ctx); #endif /* _NDCTL_BUILTIN_H_ */ diff --git a/ndctl/dimm.c b/ndctl/dimm.c index 581be497..edb4b9d7 100644 --- a/ndctl/dimm.c +++ b/ndctl/dimm.c @@ -861,6 +861,18 @@ static int action_key_update(struct ndctl_dimm *dimm, return ndctl_dimm_update_key(dimm, param.master_key); } +static int action_passphrase_disable(struct ndctl_dimm *dimm, + struct action_context *actx) +{ + if (!ndctl_dimm_security_supported(dimm)) { + error("%s: security operation not supported\n", + ndctl_dimm_get_devname(dimm)); + return -EOPNOTSUPP; + } + + return ndctl_dimm_disable_key(dimm); +} + static int __action_init(struct ndctl_dimm *dimm, enum ndctl_namespace_version version, int chk_only) { @@ -1245,3 +1257,13 @@ int cmd_passphrase_setup(int argc, const char **argv, void *ctx) count > 1 ? "s" : ""); return count >= 0 ? 0 : EXIT_FAILURE; } + +int cmd_disable_passphrase(int argc, const char **argv, void *ctx) +{ + int count = dimm_action(argc, argv, ctx, action_passphrase_disable, base_options, + "ndctl disable-passphrase [..] []"); + + fprintf(stderr, "passphrase disabled %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 2da0d01a..9cc22016 100644 --- a/ndctl/lib/dimm.c +++ b/ndctl/lib/dimm.c @@ -659,3 +659,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 a005c6a6..779e82af 100644 --- a/ndctl/lib/keys.c +++ b/ndctl/lib/keys.c @@ -387,3 +387,31 @@ NDCTL_EXPORT int ndctl_dimm_update_key(struct ndctl_dimm *dimm, return 0; } + +NDCTL_EXPORT int ndctl_dimm_disable_key(struct ndctl_dimm *dimm) +{ + struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm);
[PATCH v6 08/12] ndctl: add overwrite operation support
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 --- Documentation/ndctl/ndctl-sanitize-dimm.txt |4 ndctl/dimm.c| 21 ndctl/lib/dimm.c|8 ndctl/lib/keys.c| 28 --- ndctl/lib/libndctl.sym |2 ++ ndctl/libndctl.h|7 +++ 6 files changed, 55 insertions(+), 15 deletions(-) diff --git a/Documentation/ndctl/ndctl-sanitize-dimm.txt b/Documentation/ndctl/ndctl-sanitize-dimm.txt index a6802d30..beb4b2f9 100644 --- a/Documentation/ndctl/ndctl-sanitize-dimm.txt +++ b/Documentation/ndctl/ndctl-sanitize-dimm.txt @@ -29,4 +29,8 @@ include::xable-dimm-options.txt[] Replaces encryption keys and securely erases the data. 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[] diff --git a/ndctl/dimm.c b/ndctl/dimm.c index ae674f78..6b1ee47f 100644 --- a/ndctl/dimm.c +++ b/ndctl/dimm.c @@ -47,6 +47,7 @@ static struct parameters { const char *labelversion; const char *master_key; bool crypto_erase; + bool overwrite; bool force; bool json; bool verbose; @@ -907,7 +908,7 @@ static int action_sanitize_dimm(struct ndctl_dimm *dimm, * Setting crypto erase to be default. The other method will be * overwrite. */ - if (!param.crypto_erase) { + if (!param.crypto_erase && !param.overwrite) { param.crypto_erase = true; printf("No santize method passed in, default to crypto-erase\n"); } @@ -918,6 +919,12 @@ static int action_sanitize_dimm(struct ndctl_dimm *dimm, return rc; } + if (param.overwrite) { + rc = ndctl_dimm_overwrite_key(dimm); + if (rc < 0) + return rc; + } + return 0; } @@ -1016,7 +1023,9 @@ OPT_STRING('m', "master-key", ¶m.master_key, ":", \ #define SANITIZE_OPTIONS() \ OPT_BOOLEAN('c', "crypto-erase", ¶m.crypto_erase, \ - "crypto erase a dimm") + "crypto erase a dimm"), \ +OPT_BOOLEAN('o', "overwrite", ¶m.overwrite, \ + "overwrite a dimm") static const struct option read_options[] = { BASE_OPTIONS(), @@ -1342,7 +1351,11 @@ int cmd_sanitize_dimm(int argc, const char **argv, void *ctx) sanitize_options, "ndctl sanitize-dimm [..] []"); - 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 6da29c1e..2dff80f0 100644 --- a/ndctl/lib/dimm.c +++ b/ndctl/lib/dimm.c @@ -681,3 +681,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 130c29ed..fcf300bb 100644 --- a/ndctl/lib/keys.c +++ b/ndctl/lib/keys.c @@ -85,10 +85,9 @@ static char *load_key_blob(struct ndctl_ctx *ctx, const char *path, int *size) char prefix[] = "load "; rc = stat(path, &st); - if (rc < 0) { - err(ctx, "stat: %s\n", strerror(errno)); + if (rc < 0) return NULL; - } + if ((st.st_mode & S_IFMT) != S_IFREG) { err(ctx, "%s not a regular file\n", path); return NULL; @@ -324,10 +323,8 @@ static int dimm_remove_key(struct ndctl_dimm *dimm, } rc = unlink(path); - if (rc < 0) { - err(ctx, "unlink: %s\n", strerror(errno)); + if (rc < 0) return -errno; - } return 0; } @@ -398,10 +395,11 @@ static int check_key_run_and_discard(struct ndctl_dimm *dimm, key = dimm_check_key(dimm, false); if (key < 0) { key = dimm_load_ke
[PATCH v6 04/12] ndctl: add support for freeze security
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 --- Documentation/ndctl/Makefile.am |3 ++- Documentation/ndctl/ndctl-freeze-security.txt | 20 ++ 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, 59 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 31570a77..a97f193d 100644 --- a/Documentation/ndctl/Makefile.am +++ b/Documentation/ndctl/Makefile.am @@ -50,7 +50,8 @@ man1_MANS = \ ndctl-monitor.1 \ ndctl-enable-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 ..4e9d2d61 --- /dev/null +++ b/Documentation/ndctl/ndctl-freeze-security.txt @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0 + +ndctl-freeze-security(1) + + +NAME + +ndctl-freeze-security - enabling or freeze the security for an NVDIMM + +SYNOPSIS + +[verse] +'ndctl freeze-security' + +DESCRIPTION +--- +Provide a generic interface to freeze the security for NVDIMM. Once security +is frozen, no other security operations can succeed until reboot happens. + +include::../copyright.txt[] diff --git a/builtin.h b/builtin.h index 8d8f61e2..827295da 100644 --- a/builtin.h +++ b/builtin.h @@ -51,4 +51,5 @@ int cmd_inject_smart(int argc, const char **argv, void *ctx); int cmd_passphrase_setup(int argc, const char **argv, void *ctx); int cmd_passphrase_update(int argc, const char **argv, void *ctx); int cmd_disable_passphrase(int argc, const char **argv, void *ctx); +int cmd_freeze_security(int argc, const char **argv, void *ctx); #endif /* _NDCTL_BUILTIN_H_ */ diff --git a/ndctl/dimm.c b/ndctl/dimm.c index edb4b9d7..6476b6e5 100644 --- a/ndctl/dimm.c +++ b/ndctl/dimm.c @@ -873,6 +873,24 @@ static int action_passphrase_disable(struct ndctl_dimm *dimm, return ndctl_dimm_disable_key(dimm); } +static int action_security_freeze(struct ndctl_dimm *dimm, + struct action_context *actx) +{ + int rc; + + if (!ndctl_dimm_security_supported(dimm)) { + 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) { @@ -1267,3 +1285,13 @@ int cmd_disable_passphrase(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 [..] []"); + + 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 9cc22016..227c7124 100644 --- a/ndctl/lib/dimm.c +++ b/ndctl/lib/dimm.c @@ -668,3 +668,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 90038e75..a1c56060 100644 --- a/ndctl/lib/libndctl.sym +++ b/ndctl/lib/libndctl.sym @@ -395,4 +395,5 @@ global: ndctl_dimm_update_passphrase; ndctl_dimm_disable_passphrase; ndctl_dimm_disable_key; + ndctl_dimm_freeze_security; } LIBNDCTL_18; diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h index 18cccbb1..7bb7132c 100644 --- a/ndctl/libndctl.h +++ b/ndctl/libndctl.h @@ -703,6 +703,7 @@ bool ndctl_dimm_security_supported(struct ndctl_dimm *dimm); int ndctl_dimm_update_passphrase(struct ndctl_dimm *dimm,
[PATCH v6 10/12] ndctl: master phassphrase management support
Adding master passphrase enabling and update to ndctl. This is a new feature from Intel DSM v1.8. Signed-off-by: Dave Jiang --- Documentation/ndctl/ndctl-enable-passphrase.txt |7 + Documentation/ndctl/ndctl-update-passphrase.txt |7 + ndctl/dimm.c| 11 ++ ndctl/lib/dimm.c|9 ++ ndctl/lib/keys.c| 113 +-- ndctl/lib/libndctl.sym |1 ndctl/libndctl.h| 14 ++- 7 files changed, 122 insertions(+), 40 deletions(-) diff --git a/Documentation/ndctl/ndctl-enable-passphrase.txt b/Documentation/ndctl/ndctl-enable-passphrase.txt index 8de5410c..6639ce8d 100644 --- a/Documentation/ndctl/ndctl-enable-passphrase.txt +++ b/Documentation/ndctl/ndctl-enable-passphrase.txt @@ -29,7 +29,12 @@ OPTIONS include::xable-dimm-options.txt[] -m:: ---master=:: +--master-key=:: Key name for the master key used to seal the NVDIMM security keys. +-M:: +--master-passphrase:: + Parameter to indicate 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 9ed39cca..e2ecacf5 100644 --- a/Documentation/ndctl/ndctl-update-passphrase.txt +++ b/Documentation/ndctl/ndctl-update-passphrase.txt @@ -26,8 +26,13 @@ OPTIONS include::xable-dimm-options.txt[] -m:: ---master:: +--master-key=:: New key name for the master key to seal the new nvdimm key, or the existing master key name. i.e trusted:master-key. +-M:: +--master-passphrase:: + Parameter to indicate that we are managing the master passphrase + instead of the user passphrase. + include::../copyright.txt[] diff --git a/ndctl/dimm.c b/ndctl/dimm.c index 21ffea1e..c60ef96e 100644 --- a/ndctl/dimm.c +++ b/ndctl/dimm.c @@ -48,6 +48,7 @@ static struct parameters { const char *master_key; bool crypto_erase; bool overwrite; + bool master_pass; bool force; bool json; bool verbose; @@ -848,7 +849,8 @@ static int action_key_enable(struct ndctl_dimm *dimm, return -EOPNOTSUPP; } - return ndctl_dimm_enable_key(dimm, param.master_key); + return ndctl_dimm_enable_key(dimm, param.master_key, + param.master_pass ? ND_MASTER_KEY : ND_USER_KEY); } static int action_key_update(struct ndctl_dimm *dimm, @@ -860,7 +862,8 @@ static int action_key_update(struct ndctl_dimm *dimm, return -EOPNOTSUPP; } - return ndctl_dimm_update_key(dimm, param.master_key); + return ndctl_dimm_update_key(dimm, param.master_key, + param.master_pass ? ND_MASTER_KEY : ND_USER_KEY); } static int action_passphrase_disable(struct ndctl_dimm *dimm, @@ -1037,7 +1040,9 @@ OPT_STRING('V', "label-version", ¶m.labelversion, "version-number", \ #define KEY_OPTIONS() \ OPT_STRING('m', "master-key", ¶m.master_key, ":", \ - "master key for security") + "master key for security"), \ +OPT_BOOLEAN('M', "master-passphrase", ¶m.master_pass, \ + "use master passphrase") #define SANITIZE_OPTIONS() \ OPT_BOOLEAN('c', "crypto-erase", ¶m.crypto_erase, \ diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c index d815b9fc..07513b4b 100644 --- a/ndctl/lib/dimm.c +++ b/ndctl/lib/dimm.c @@ -768,3 +768,12 @@ NDCTL_EXPORT int ndctl_dimm_wait_for_overwrite_completion( 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 fcf300bb..1d395b48 100644 --- a/ndctl/lib/keys.c +++ b/ndctl/lib/keys.c @@ -34,16 +34,29 @@ 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", - ND_PASS_PATH, - ndctl_dimm_get_unique_id(dimm), + switch (key_type) { + case ND_USER_OLD_KEY: + rc = sprintf(path, "%s/nvdimm-old_%s_%s.blob", + ND_PASS_PATH, ndctl_dimm_get_unique_id(dimm), hostname); - } else { + break; + case ND_USER_KEY: rc = sprintf(path, "%s/nvdimm_%s_%s.blob", - ND_PASS_PATH, - ndctl_dimm_get_unique_id(dimm), + ND_PASS_PATH, ndctl_dimm_get_unique_id(dimm), hostname); +
[PATCH v6 09/12] ndctl: add overwrite-wait support
Adding a monitoring command to ndctl in order to wait on the progress of overwrite. Signed-off-by: Dave Jiang --- Documentation/ndctl/Makefile.am |3 + Documentation/ndctl/ndctl-wait-overwrite.txt | 31 ++ builtin.h|1 ndctl/dimm.c | 27 + ndctl/lib/dimm.c | 79 ++ ndctl/lib/libndctl.sym |1 ndctl/libndctl.h |1 ndctl/ndctl.c|1 8 files changed, 143 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 bbea9674..a60a67e5 100644 --- a/Documentation/ndctl/Makefile.am +++ b/Documentation/ndctl/Makefile.am @@ -52,7 +52,8 @@ man1_MANS = \ ndctl-update-passphrase.1 \ ndctl-disable-passphrase.1 \ ndctl-freeze-security.1 \ - ndctl-sanitize-dimm.1 + ndctl-sanitize-dimm.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 ..97583a36 --- /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' [] + +DESCRIPTION +--- +The ernel provides a POLL(2) capable sysfs file ('security') to indicate +the state of overwrite. The 'ndctl wait-overwrite' operation waits for +'security', 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/builtin.h b/builtin.h index db0f2858..32bee59e 100644 --- a/builtin.h +++ b/builtin.h @@ -53,4 +53,5 @@ int cmd_passphrase_update(int argc, const char **argv, void *ctx); int cmd_disable_passphrase(int argc, const char **argv, void *ctx); int cmd_freeze_security(int argc, const char **argv, void *ctx); int cmd_sanitize_dimm(int argc, const char **argv, void *ctx); +int cmd_wait_overwrite(int argc, const char **argv, void *ctx); #endif /* _NDCTL_BUILTIN_H_ */ diff --git a/ndctl/dimm.c b/ndctl/dimm.c index 6b1ee47f..21ffea1e 100644 --- a/ndctl/dimm.c +++ b/ndctl/dimm.c @@ -928,6 +928,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_security_supported(dimm)) { + error("%s: security operation not supported\n", + ndctl_dimm_get_devname(dimm)); + return -EOPNOTSUPP; + } + + rc = ndctl_dimm_wait_for_overwrite_completion(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) { @@ -1359,3 +1377,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 [..] []"); + + return count >= 0 ? 0 : EXIT_FAILURE; +} diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c index 2dff80f0..d815b9fc 100644 --- a/ndctl/lib/dimm.c +++ b/ndctl/lib/dimm.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "private.h" static const char NSINDEX_SIGNATURE[] = "NAMESPACE_INDEX\0"; @@ -689,3 +690,81 @@ 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_for_overwrite_completion( + 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 <
Re: [driver-core PATCH v9 2/9] device core: Consolidate locking and unlocking of parent and device
somOn Thu, Dec 13, 2018 at 1:45 AM Alexander Duyck wrote: > > Try to consolidate all of the locking and unlocking of both the parent and > device when attaching or removing a driver from a given device. > > To do that I first consolidated the lock pattern into two functions > __device_driver_lock and __device_driver_unlock. After doing that I then > created functions specific to attaching and detaching the driver while > acquiring these locks. By doing this I was able to reduce the number of > spots where we touch need_parent_lock from 12 down to 4. > > This patch should produce no functional changes, it is meant to be a code > clean-up/consolidation only. > > Reviewed-by: Luis Chamberlain > Reviewed-by: Bart Van Assche > Reviewed-by: Dan Williams > Reviewed-by: Rafael J. Wysocki > Signed-off-by: Alexander Duyck > --- > drivers/base/base.h |2 + > drivers/base/bus.c | 23 ++-- > drivers/base/dd.c | 95 > --- > 3 files changed, 81 insertions(+), 39 deletions(-) > > diff --git a/drivers/base/base.h b/drivers/base/base.h > index 7a419a7a6235..3f22ebd6117a 100644 > --- a/drivers/base/base.h > +++ b/drivers/base/base.h > @@ -124,6 +124,8 @@ extern int driver_add_groups(struct device_driver *drv, > const struct attribute_group **groups); > extern void driver_remove_groups(struct device_driver *drv, > const struct attribute_group **groups); > +int device_driver_attach(struct device_driver *drv, struct device *dev); > +void device_driver_detach(struct device *dev); > > extern char *make_class_name(const char *name, struct kobject *kobj); > > diff --git a/drivers/base/bus.c b/drivers/base/bus.c > index b886b15cb53b..74054481007d 100644 > --- a/drivers/base/bus.c > +++ b/drivers/base/bus.c > @@ -184,11 +184,7 @@ static ssize_t unbind_store(struct device_driver *drv, > const char *buf, > > dev = bus_find_device_by_name(bus, NULL, buf); > if (dev && dev->driver == drv) { > - if (dev->parent && dev->bus->need_parent_lock) > - device_lock(dev->parent); > - device_release_driver(dev); > - if (dev->parent && dev->bus->need_parent_lock) > - device_unlock(dev->parent); > + device_driver_detach(dev); > err = count; > } > put_device(dev); > @@ -211,13 +207,7 @@ static ssize_t bind_store(struct device_driver *drv, > const char *buf, > > dev = bus_find_device_by_name(bus, NULL, buf); > if (dev && dev->driver == NULL && driver_match_device(drv, dev)) { > - if (dev->parent && bus->need_parent_lock) > - device_lock(dev->parent); > - device_lock(dev); > - err = driver_probe_device(drv, dev); > - device_unlock(dev); > - if (dev->parent && bus->need_parent_lock) > - device_unlock(dev->parent); > + err = device_driver_attach(drv, dev); > > if (err > 0) { > /* success */ > @@ -771,13 +761,8 @@ EXPORT_SYMBOL_GPL(bus_rescan_devices); > */ > int device_reprobe(struct device *dev) > { > - if (dev->driver) { > - if (dev->parent && dev->bus->need_parent_lock) > - device_lock(dev->parent); > - device_release_driver(dev); > - if (dev->parent && dev->bus->need_parent_lock) > - device_unlock(dev->parent); > - } > + if (dev->driver) > + device_driver_detach(dev); > return bus_rescan_devices_helper(dev, NULL); > } > EXPORT_SYMBOL_GPL(device_reprobe); > diff --git a/drivers/base/dd.c b/drivers/base/dd.c > index 74c194ac99df..f07c16277ed9 100644 > --- a/drivers/base/dd.c > +++ b/drivers/base/dd.c > @@ -867,6 +867,64 @@ void device_initial_probe(struct device *dev) > __device_attach(dev, true); > } > > +/* > + * __device_driver_lock - acquire locks needed to manipulate dev->drv > + * @dev: Device we will update driver info for > + * @parent: Parent device. Needed if the bus requires parent lock > + * > + * This function will take the required locks for manipulating dev->drv. > + * Normally this will just be the @dev lock, but when called for a USB > + * interface, @parent lock will be held as well. > + */ > +static void __device_driver_lock(struct device *dev, struct device *parent) > +{ > + if (parent && dev->bus->need_parent_lock) > + device_lock(parent); > + device_lock(dev); > +} > + > +/* > + * __device_driver_unlock - release locks needed to manipulate dev->drv > + * @dev: Device we will update driver info for > + * @parent: Parent device. Needed if the bus requires parent lock > + * > + * This function will release the required locks for manipulating dev->drv. > + * Normally this will just be the the @dev lock, but
RE: [External] Re: Snapshot target and DAX-capable devices
From: Mike Snitzer Sent: Thursday, December 13, 2018 6:43 AM > On Wed, Dec 12 2018 at 4:15pm -0500, > Theodore Y. Ts'o wrote: > > > On Wed, Dec 12, 2018 at 12:50:47PM -0500, Mike Snitzer wrote: > > > On Wed, Dec 12 2018 at 11:12am -0500, > > > Christoph Hellwig wrote: > > > > > > > Does it really make sense to enhance dm-snapshot? I thought all serious > > > > users of snapshots had moved on to dm-thinp? > > > > > > There are cases where dm-snapshot is still useful for people. But those > > > are very niche users. I'm not opposed to others proposing enhancements > > > for dm-snapshot in general but it is definitely not a priority (Google's > > > dm-bow is an example of a case where dm-snapshot may get extended to > > > fulfill google's needs). > > > > I would expect that dm-snapshot will be used quite a lot for > > short-lived snapshots (that only live during a database backup or an > > fsck run). I would hardly call that a "niche use case". > > dm-snapshot is only ~60% performant for 1 snapshot. Try to do > additional snapshots and performance crawls to a stop (though I haven't > reassessed performance in a while). > > dm-snapshot has been in Linux since before 2005, I don't know of all the > users of it -- maybe there are a ton of users who only take a single > temporary snapshot and we're all oblivious. > > Definitely not seeing many bugs against it (but it has been around > forever). I do know that there are relatively few people showing > interest in it. But for 4.21 I did stage a couple useful performance > fixes: > https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=dm-4. > 21&id=61d594bb7e1cf86dca49cbc9524eb80169d9fca6 > https://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=dm-4. > 21&id=d1f7898c7a1b24aa9ae670f9cc21b65e730827eb Hi Mike, Could these two patches be applied to current code of LVM? Although there is a difficult problem as mmap for dm-snapshot with DAX-capable, the two patches can be used for other complex DM targets when trying to implement DAX. [RFC PATCH v2 2/3] dm: expand hc_map in mapped_device for lack of map https://lkml.org/lkml/2018/11/21/273 [RFC PATCH v2 3/3] dm: expand valid types for dm-ioctl https://lkml.org/lkml/2018/11/21/276 Cheers, Huaisheng Ye ___ Linux-nvdimm mailing list Linux-nvdimm@lists.01.org https://lists.01.org/mailman/listinfo/linux-nvdimm