diff mbox series

[4/4] ndctl/test: Add CXL test for security

Message ID 166379417897.433612.16268594042547006566.stgit@djiang5-desk3.ch.intel.com (mailing list archive)
State New, archived
Headers show
Series ndctl: Add security test for cxl devices through nvdimm | expand

Commit Message

Dave Jiang Sept. 21, 2022, 9:02 p.m. UTC
Create security-cxl.sh based off of security.sh for nfit security testing.
The test will test a cxl_test based security commands enabling through
nvdimm.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
---
 test/common          |    7 +
 test/meson.build     |    7 +
 test/security-cxl.sh |  282 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 296 insertions(+)
 create mode 100755 test/security-cxl.sh

Comments

Verma, Vishal L Dec. 13, 2022, 11:22 p.m. UTC | #1
On Wed, 2022-09-21 at 14:02 -0700, Dave Jiang wrote:
> Create security-cxl.sh based off of security.sh for nfit security testing.
> The test will test a cxl_test based security commands enabling through
> nvdimm.

Since the new test is largely a copy of the NFIT security test, I think
it might be better to split out the common portions into a script that
can be sourced, and then from the main tests, call functions defined by
the sourced script with appropriate arguments to specify the module
(cxl_test) and bus ($CXL_TEST_BUS).

If the actual test sequence of tests 1 through 6 is the same between
NFIT and CXL, those could be wrapped in a run_security_tests wrapper
which can be called as:

  run_security_tests "cxl_test" "$CXL_TEST_BUS"

or

  run_security_tests "nfit_test" "$NFIT_TEST_BUS0"


This would allow Jeff's recent fix to get pulled in for the CXL test
too.

> 
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> ---
>  test/common          |    7 +
>  test/meson.build     |    7 +
>  test/security-cxl.sh |  282 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 296 insertions(+)
>  create mode 100755 test/security-cxl.sh

I think in line with the other cxl tests, a better name would be
cxl-security.sh

> 
> diff --git a/test/common b/test/common
> index 65615cc09a3e..e13b79728b0c 100644
> --- a/test/common
> +++ b/test/common
> @@ -47,6 +47,7 @@ fi
>  #
>  NFIT_TEST_BUS0="nfit_test.0"
>  NFIT_TEST_BUS1="nfit_test.1"
> +CXL_TEST_BUS="cxl_test"
>  ACPI_BUS="ACPI.NFIT"
>  E820_BUS="e820"
>  
> @@ -125,6 +126,12 @@ _cleanup()
>         modprobe -r nfit_test
>  }
>  
> +_cxl_cleanup()
> +{
> +       $NDCTL disable-region -b $CXL_TEST_BUS all
> +       modprobe -r cxl_test
> +}
> +
>  # json2var
>  # stdin: json
>  #
> diff --git a/test/meson.build b/test/meson.build
> index 5953c286d13f..485deb89bbe2 100644
> --- a/test/meson.build
> +++ b/test/meson.build
> @@ -219,6 +219,13 @@ if get_option('keyutils').enabled()
>    ]
>  endif
>  
> +if get_option('keyutils').enabled()
> +  security_cxl = find_program('security-cxl.sh')
> +  tests += [
> +    [ 'security-cxl.sh', security_cxl, 'ndctl' ]
> +  ]
> +endif
> +
>  foreach t : tests
>    test(t[0], t[1],
>      is_parallel : false,
> diff --git a/test/security-cxl.sh b/test/security-cxl.sh
> new file mode 100755
> index 000000000000..0ec9b335bf41
> --- /dev/null
> +++ b/test/security-cxl.sh
> @@ -0,0 +1,282 @@
> +#!/bin/bash -Ex
> +# SPDX-License-Identifier: GPL-2.0
> +# Copyright (C) 2022 Intel Corporation. All rights reserved.
> +
> +rc=77
> +dev=""
> +id=""
> +keypath="/etc/ndctl/keys"
> +masterkey="nvdimm-master"
> +masterpath="$keypath/$masterkey.blob"
> +backup_key=0
> +backup_handle=0
> +
> +. $(dirname $0)/common
> +
> +trap 'err $LINENO' ERR
> +
> +setup()
> +{
> +       $NDCTL disable-region -b "$CXL_TEST_BUS" all
> +}
> +
> +detect()
> +{
> +       dev="$($NDCTL list -b "$CXL_TEST_BUS" -D | jq -r 'sort_by(.id) | .[0].dev')"
> +       [ -n "$dev" ] || err "$LINENO"
> +       id="$($NDCTL list -b "$CXL_TEST_BUS" -D | jq -r 'sort_by(.id) | .[0].id')"
> +       [ -n "$id" ] || err "$LINENO"
> +}
> +
> +setup_keys()
> +{
> +       if [ ! -d "$keypath" ]; then
> +               mkdir -p "$keypath"
> +       fi
> +
> +       if [ -f "$masterpath" ]; then
> +               mv "$masterpath" "$masterpath.bak"
> +               backup_key=1
> +       fi
> +       if [ -f "$keypath/tpm.handle" ]; then
> +               mv "$keypath/tpm.handle" "$keypath/tpm.handle.bak"
> +               backup_handle=1
> +       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"
> +}
> +
> +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
> +}
> +
> +post_cleanup()
> +{
> +       if [ -f $masterpath ]; then
> +               rm -f "$masterpath"
> +       fi
> +       if [ "$backup_key" -eq 1 ]; then
> +               mv "$masterpath.bak" "$masterpath"
> +       fi
> +       if [ "$backup_handle" -eq 1 ]; then
> +               mv "$keypath/tpm.handle.bak" "$keypath/tpm.handle"
> +       fi
> +}
> +
> +lock_dimm()
> +{
> +       $NDCTL disable-dimm "$dev"
> +       test_dimm_path=""
> +
> +       nmem_rpath=$(readlink -f "/sys/bus/nd/devices/${dev}")
> +       nmem_bus=$(dirname ${nmem_rpath});
> +       bus_provider_path="${nmem_bus}/provider"
> +       test -e "$bus_provider_path" || err "$LINENO"
> +       bus_provider=$(cat ${bus_provider_path})
> +
> +       [[ "$bus_provider" == "$CXL_TEST_BUS" ]] || err "$LINENO"
> +       bus="cxl"
> +       nmem_provider_path="/sys/bus/nd/devices/${dev}/${bus}/provider"
> +       nmem_provider=$(cat ${nmem_provider_path})
> +
> +       test_dimm_path=$(readlink -f /sys/bus/$bus/devices/${nmem_provider})
> +       test_dimm_path=$(dirname $(dirname ${test_dimm_path}))/security_lock
> +
> +       test -e "$test_dimm_path"
> +
> +       # now lock the dimm
> +       echo 1 > "${test_dimm_path}"
> +       sstate="$(get_security_state)"
> +       if [ "$sstate" != "locked" ]; then
> +               echo "Incorrect security state: $sstate expected: locked"
> +               err "$LINENO"
> +       fi
> +}
> +
> +get_frozen_state()
> +{
> +       $NDCTL list -i -b "$CXL_TEST_BUS" -d "$dev" | jq -r .[].dimms[0].security_frozen
> +}
> +
> +get_security_state()
> +{
> +       $NDCTL list -i -b "$CXL_TEST_BUS" -d "$dev" | jq -r .[].dimms[0].security
> +}
> +
> +setup_passphrase()
> +{
> +       $NDCTL setup-passphrase "$dev" -k user:"$masterkey"
> +       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 "$CXL_TEST_BUS" all
> +       remove_passphrase
> +}
> +
> +# This should always be the last nvdimm security test.
> +# with security frozen, cxl_test must be removed and is no longer usable
> +test_5_security_freeze()
> +{
> +       setup_passphrase
> +       freeze_security
> +       sstate="$(get_security_state)"
> +       fstate="$(get_frozen_state)"
> +       if [ "$fstate" != "true" ]; then
> +               echo "Incorrect security state: expected: frozen"
> +               err "$LINENO"
> +       fi
> +
> +       # need to simulate a soft reboot here to clean up
> +       lock_dimm
> +       $NDCTL enable-dimm "$dev"
> +       sstate="$(get_security_state)"
> +       if [ "$sstate" != "unlocked" ]; then
> +               echo "Incorrect security state: $sstate expected: unlocked"
> +               err "$LINENO"
> +       fi
> +}
> +
> +test_6_load_keys()
> +{
> +       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
> +
> +       $NDCTL load-keys
> +
> +       if keyctl search @u user "$masterkey"; then
> +               echo "master key loaded"
> +       else
> +               echo "master key failed to loaded"
> +               err "$LINENO"
> +       fi
> +
> +       if keyctl search @u encrypted nvdimm:"$id"; then
> +               echo "dimm key loaded"
> +       else
> +               echo "dimm key failed to load"
> +               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 cxl_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 the last nvdimm security test because it locks
> +# security state and require cxl_test module unload. However, this does
> +# not impact any key management testing via libkeyctl.
> +echo "Test 5, freeze security"
> +test_5_security_freeze
> +
> +# Load-keys is independent of actual nvdimm security and is part of key
> +# mangement testing.
> +echo "Test 6, test load-keys"
> +test_6_load_keys
> +
> +test_cleanup
> +post_cleanup
> +_cxl_cleanup
> +exit 0
> 
>
Dan Williams Dec. 14, 2022, 1:02 a.m. UTC | #2
Dave Jiang wrote:
> Create security-cxl.sh based off of security.sh for nfit security testing.
> The test will test a cxl_test based security commands enabling through
> nvdimm.
> 
> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
> ---
>  test/common          |    7 +
>  test/meson.build     |    7 +
>  test/security-cxl.sh |  282 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 296 insertions(+)
>  create mode 100755 test/security-cxl.sh
> 
> diff --git a/test/common b/test/common
> index 65615cc09a3e..e13b79728b0c 100644
> --- a/test/common
> +++ b/test/common
> @@ -47,6 +47,7 @@ fi
>  #
>  NFIT_TEST_BUS0="nfit_test.0"
>  NFIT_TEST_BUS1="nfit_test.1"
> +CXL_TEST_BUS="cxl_test"
>  ACPI_BUS="ACPI.NFIT"
>  E820_BUS="e820"
>  
> @@ -125,6 +126,12 @@ _cleanup()
>  	modprobe -r nfit_test
>  }
>  
> +_cxl_cleanup()
> +{
> +	$NDCTL disable-region -b $CXL_TEST_BUS all
> +	modprobe -r cxl_test
> +}
> +
>  # json2var
>  # stdin: json
>  #
> diff --git a/test/meson.build b/test/meson.build
> index 5953c286d13f..485deb89bbe2 100644
> --- a/test/meson.build
> +++ b/test/meson.build
> @@ -219,6 +219,13 @@ if get_option('keyutils').enabled()
>    ]
>  endif
>  
> +if get_option('keyutils').enabled()
> +  security_cxl = find_program('security-cxl.sh')
> +  tests += [
> +    [ 'security-cxl.sh', security_cxl, 'ndctl' ]
> +  ]
> +endif
> +

I had this folded on top for my local testing:

diff --git a/test/meson.build b/test/meson.build
index c9853421ce69..1df115f82fef 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -216,15 +216,10 @@ endif
 
 if get_option('keyutils').enabled()
   security = find_program('security.sh')
-  tests += [
-    [ 'security.sh', security, 'ndctl' ]
-  ]
-endif
-
-if get_option('keyutils').enabled()
   security_cxl = find_program('security-cxl.sh')
   tests += [
-    [ 'security-cxl.sh', security_cxl, 'ndctl' ]
+    [ 'security.sh', security, 'ndctl' ],
+    [ 'security-cxl.sh', security_cxl, 'cxl' ],
   ]
 endif

...although I like Vishal's suggestion to name this cxl-security.sh to
match the other cxl test in the suite.
diff mbox series

Patch

diff --git a/test/common b/test/common
index 65615cc09a3e..e13b79728b0c 100644
--- a/test/common
+++ b/test/common
@@ -47,6 +47,7 @@  fi
 #
 NFIT_TEST_BUS0="nfit_test.0"
 NFIT_TEST_BUS1="nfit_test.1"
+CXL_TEST_BUS="cxl_test"
 ACPI_BUS="ACPI.NFIT"
 E820_BUS="e820"
 
@@ -125,6 +126,12 @@  _cleanup()
 	modprobe -r nfit_test
 }
 
+_cxl_cleanup()
+{
+	$NDCTL disable-region -b $CXL_TEST_BUS all
+	modprobe -r cxl_test
+}
+
 # json2var
 # stdin: json
 #
diff --git a/test/meson.build b/test/meson.build
index 5953c286d13f..485deb89bbe2 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -219,6 +219,13 @@  if get_option('keyutils').enabled()
   ]
 endif
 
+if get_option('keyutils').enabled()
+  security_cxl = find_program('security-cxl.sh')
+  tests += [
+    [ 'security-cxl.sh', security_cxl, 'ndctl' ]
+  ]
+endif
+
 foreach t : tests
   test(t[0], t[1],
     is_parallel : false,
diff --git a/test/security-cxl.sh b/test/security-cxl.sh
new file mode 100755
index 000000000000..0ec9b335bf41
--- /dev/null
+++ b/test/security-cxl.sh
@@ -0,0 +1,282 @@ 
+#!/bin/bash -Ex
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2022 Intel Corporation. All rights reserved.
+
+rc=77
+dev=""
+id=""
+keypath="/etc/ndctl/keys"
+masterkey="nvdimm-master"
+masterpath="$keypath/$masterkey.blob"
+backup_key=0
+backup_handle=0
+
+. $(dirname $0)/common
+
+trap 'err $LINENO' ERR
+
+setup()
+{
+	$NDCTL disable-region -b "$CXL_TEST_BUS" all
+}
+
+detect()
+{
+	dev="$($NDCTL list -b "$CXL_TEST_BUS" -D | jq -r 'sort_by(.id) | .[0].dev')"
+	[ -n "$dev" ] || err "$LINENO"
+	id="$($NDCTL list -b "$CXL_TEST_BUS" -D | jq -r 'sort_by(.id) | .[0].id')"
+	[ -n "$id" ] || err "$LINENO"
+}
+
+setup_keys()
+{
+	if [ ! -d "$keypath" ]; then
+		mkdir -p "$keypath"
+	fi
+
+	if [ -f "$masterpath" ]; then
+		mv "$masterpath" "$masterpath.bak"
+		backup_key=1
+	fi
+	if [ -f "$keypath/tpm.handle" ]; then
+		mv "$keypath/tpm.handle" "$keypath/tpm.handle.bak"
+		backup_handle=1
+	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"
+}
+
+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
+}
+
+post_cleanup()
+{
+	if [ -f $masterpath ]; then
+		rm -f "$masterpath"
+	fi
+	if [ "$backup_key" -eq 1 ]; then
+		mv "$masterpath.bak" "$masterpath"
+	fi
+	if [ "$backup_handle" -eq 1 ]; then
+		mv "$keypath/tpm.handle.bak" "$keypath/tpm.handle"
+	fi
+}
+
+lock_dimm()
+{
+	$NDCTL disable-dimm "$dev"
+	test_dimm_path=""
+
+	nmem_rpath=$(readlink -f "/sys/bus/nd/devices/${dev}")
+	nmem_bus=$(dirname ${nmem_rpath});
+	bus_provider_path="${nmem_bus}/provider"
+	test -e "$bus_provider_path" || err "$LINENO"
+	bus_provider=$(cat ${bus_provider_path})
+
+	[[ "$bus_provider" == "$CXL_TEST_BUS" ]] || err "$LINENO"
+	bus="cxl"
+	nmem_provider_path="/sys/bus/nd/devices/${dev}/${bus}/provider"
+	nmem_provider=$(cat ${nmem_provider_path})
+
+	test_dimm_path=$(readlink -f /sys/bus/$bus/devices/${nmem_provider})
+	test_dimm_path=$(dirname $(dirname ${test_dimm_path}))/security_lock
+
+	test -e "$test_dimm_path"
+
+	# now lock the dimm
+	echo 1 > "${test_dimm_path}"
+	sstate="$(get_security_state)"
+	if [ "$sstate" != "locked" ]; then
+		echo "Incorrect security state: $sstate expected: locked"
+		err "$LINENO"
+	fi
+}
+
+get_frozen_state()
+{
+	$NDCTL list -i -b "$CXL_TEST_BUS" -d "$dev" | jq -r .[].dimms[0].security_frozen
+}
+
+get_security_state()
+{
+	$NDCTL list -i -b "$CXL_TEST_BUS" -d "$dev" | jq -r .[].dimms[0].security
+}
+
+setup_passphrase()
+{
+	$NDCTL setup-passphrase "$dev" -k user:"$masterkey"
+	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 "$CXL_TEST_BUS" all
+	remove_passphrase
+}
+
+# This should always be the last nvdimm security test.
+# with security frozen, cxl_test must be removed and is no longer usable
+test_5_security_freeze()
+{
+	setup_passphrase
+	freeze_security
+	sstate="$(get_security_state)"
+	fstate="$(get_frozen_state)"
+	if [ "$fstate" != "true" ]; then
+		echo "Incorrect security state: expected: frozen"
+		err "$LINENO"
+	fi
+
+	# need to simulate a soft reboot here to clean up
+	lock_dimm
+	$NDCTL enable-dimm "$dev"
+	sstate="$(get_security_state)"
+	if [ "$sstate" != "unlocked" ]; then
+		echo "Incorrect security state: $sstate expected: unlocked"
+		err "$LINENO"
+	fi
+}
+
+test_6_load_keys()
+{
+	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
+
+	$NDCTL load-keys
+
+	if keyctl search @u user "$masterkey"; then
+		echo "master key loaded"
+	else
+		echo "master key failed to loaded"
+		err "$LINENO"
+	fi
+
+	if keyctl search @u encrypted nvdimm:"$id"; then
+		echo "dimm key loaded"
+	else
+		echo "dimm key failed to load"
+		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 cxl_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 the last nvdimm security test because it locks
+# security state and require cxl_test module unload. However, this does
+# not impact any key management testing via libkeyctl.
+echo "Test 5, freeze security"
+test_5_security_freeze
+
+# Load-keys is independent of actual nvdimm security and is part of key
+# mangement testing.
+echo "Test 6, test load-keys"
+test_6_load_keys
+
+test_cleanup
+post_cleanup
+_cxl_cleanup
+exit 0