From: Eric Biggers Date: Fri, 13 Dec 2024 05:28:38 +0000 (-0800) Subject: common/encrypt: support hardware-wrapped key testing X-Git-Tag: v2025.01.12~12 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=91e779a8bed1fdd403191f2fe94cc286ec69428e;p=xfstests-dev.git common/encrypt: support hardware-wrapped key testing To support testing the kernel's support for hardware-wrapped inline encryption keys, update _verify_ciphertext_for_encryption_policy() to support a hw_wrapped_key option. Signed-off-by: Eric Biggers Reviewed-by: Zorro Lang Signed-off-by: Zorro Lang --- diff --git a/common/config b/common/config index 5f86fc2c..77f3fc15 100644 --- a/common/config +++ b/common/config @@ -234,6 +234,7 @@ export BTRFS_IMAGE_PROG="$(type -P btrfs-image)" export BTRFS_MAP_LOGICAL_PROG=$(type -P btrfs-map-logical) export PARTED_PROG="$(type -P parted)" export XFS_PROPERTY_PROG="$(type -P xfs_property)" +export FSCRYPTCTL_PROG="$(type -P fscryptctl)" # udev wait functions. # diff --git a/common/encrypt b/common/encrypt index 52f23cd0..d4f6e3dc 100644 --- a/common/encrypt +++ b/common/encrypt @@ -152,6 +152,42 @@ _require_encryption_policy_support() rm -r $dir } +# Require that the scratch filesystem accepts the "inlinecrypt" mount option. +# +# This does not check whether the scratch block device has any specific inline +# encryption capabilities. +_require_scratch_inlinecrypt() +{ + _require_scratch + _scratch_mkfs &>> $seqres.full + if ! _try_scratch_mount -o inlinecrypt &>> $seqres.full; then + _notrun "filesystem doesn't support -o inlinecrypt" + fi +} + +# Require that the given block device supports hardware-wrapped inline +# encryption keys, and require that a command-line tool that supports +# importing/generating/preparing them is available. +_require_hw_wrapped_key_support() +{ + local dev=$1 + + echo "Checking for HW-wrapped key support on $dev" >> $seqres.full + local sysfs_dir=$(_sysfs_dev $dev) + if [ ! -e $sysfs_dir/queue ]; then + sysfs_dir=$sysfs_dir/.. + fi + if [ ! -e $sysfs_dir/queue/crypto/hw_wrapped_keys ]; then + _notrun "$dev doesn't support hardware-wrapped inline encryption keys" + fi + + echo "Checking for fscryptctl support for HW-wrapped keys" >> $seqres.full + _require_command "$FSCRYPTCTL_PROG" fscryptctl + if ! "$FSCRYPTCTL_PROG" --help | grep -q "import_hw_wrapped_key"; then + _notrun "fscryptctl too old; doesn't support hardware-wrapped inline encryption keys" + fi +} + _scratch_mkfs_encrypted() { case $FSTYP in @@ -251,14 +287,17 @@ _generate_key_descriptor() # Generate a raw encryption key, but don't add it to any keyring yet. _generate_raw_encryption_key() { + local size=${1:-64} local raw="" local i - for ((i = 0; i < 64; i++)); do + for ((i = 0; i < $size; i++)); do raw="${raw}\\x$(printf "%02x" $(( $RANDOM % 256 )))" done echo $raw } +RAW_HW_KEY_SIZE=32 + # Serialize an integer into a CPU-endian bytestring of the given length, and # print it as a string where each byte is hex-escaped. For example, # `_num_to_hex 1000 4` == "\xe8\x03\x00\x00" if the CPU is little endian. @@ -407,6 +446,21 @@ _add_enckey() echo -ne "$raw_key" | $XFS_IO_PROG -c "add_enckey $*" "$mnt" } +# Create a hardware-wrapped key from the given raw key using the given block +# device, add it to the given filesystem, and print the resulting key +# identifier. +_add_hw_wrapped_key() +{ + local dev=$1 + local mnt=$2 + local raw_key=$3 + + echo -ne "$raw_key" | \ + $FSCRYPTCTL_PROG import_hw_wrapped_key "$dev" | \ + $FSCRYPTCTL_PROG prepare_hw_wrapped_key "$dev" | \ + $FSCRYPTCTL_PROG add_key --hw-wrapped-key "$mnt" +} + _user_do_add_enckey() { local mnt=$1 @@ -853,6 +907,7 @@ _fscrypt_mode_name_to_num() # 'iv_ino_lblk_64': test the IV_INO_LBLK_64 policy flag # 'iv_ino_lblk_32': test the IV_INO_LBLK_32 policy flag # 'log2_dusize=N': test the log2_data_unit_size field +# 'hw_wrapped_key': use a hardware-wrapped inline encryption key # _verify_ciphertext_for_encryption_policy() { @@ -862,6 +917,7 @@ _verify_ciphertext_for_encryption_policy() local policy_version=1 local policy_flags=0 local log2_dusize=0 + local hw_wrapped_key=false local set_encpolicy_args="" local crypt_util_args="" local crypt_util_contents_args="" @@ -890,6 +946,11 @@ _verify_ciphertext_for_encryption_policy() log2_dusize=*) log2_dusize=$(echo "$opt" | sed 's/^log2_dusize=//') ;; + hw_wrapped_key) + hw_wrapped_key=true + crypt_util_args+=" --enable-hw-kdf" + crypt_util_contents_args+=" --use-inlinecrypt-key" + ;; *) _fail "Unknown option '$opt' passed to ${FUNCNAME[0]}" ;; @@ -929,6 +990,9 @@ _verify_ciphertext_for_encryption_policy() set_encpolicy_args=${set_encpolicy_args# } _require_scratch_encryption $set_encpolicy_args -f $policy_flags + if $hw_wrapped_key; then + _require_hw_wrapped_key_support $SCRATCH_DEV + fi _require_test_program "fscrypt-crypt-util" _require_xfs_io_command "fiemap" _require_get_encryption_nonce_support @@ -958,11 +1022,19 @@ _verify_ciphertext_for_encryption_policy() crypt_util_filename_args+="$crypt_util_args" echo "Generating encryption key" >> $seqres.full - local raw_key=$(_generate_raw_encryption_key) if (( policy_version > 1 )); then - local keyspec=$(_add_enckey $SCRATCH_MNT "$raw_key" \ - | awk '{print $NF}') + if $hw_wrapped_key; then + local raw_key=$(_generate_raw_encryption_key \ + $RAW_HW_KEY_SIZE) + local keyspec=$(_add_hw_wrapped_key $SCRATCH_DEV \ + $SCRATCH_MNT "$raw_key") + else + local raw_key=$(_generate_raw_encryption_key) + local keyspec=$(_add_enckey $SCRATCH_MNT "$raw_key" | \ + awk '{print $NF}') + fi else + local raw_key=$(_generate_raw_encryption_key) local keyspec=$(_generate_key_descriptor) _init_session_keyring _add_session_encryption_key $keyspec $raw_key