From: Eric Biggers <ebiggers@kernel.org>
To: fstests@vger.kernel.org
Cc: linux-fscrypt@vger.kernel.org,
Bartosz Golaszewski <brgl@bgdev.pl>,
Gaurav Kashyap <quic_gaurkash@quicinc.com>
Subject: [PATCH v2 2/3] common/encrypt: support hardware-wrapped key testing
Date: Thu, 12 Dec 2024 21:28:38 -0800 [thread overview]
Message-ID: <20241213052840.314921-3-ebiggers@kernel.org> (raw)
In-Reply-To: <20241213052840.314921-1-ebiggers@kernel.org>
From: Eric Biggers <ebiggers@google.com>
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 <ebiggers@google.com>
---
common/config | 1 +
common/encrypt | 80 +++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 77 insertions(+), 4 deletions(-)
diff --git a/common/config b/common/config
index fcff0660..091405b3 100644
--- a/common/config
+++ b/common/config
@@ -233,10 +233,11 @@ export BLKZONE_PROG="$(type -P blkzone)"
export GZIP_PROG="$(type -P gzip)"
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)"
# use 'udevadm settle' or 'udevsettle' to wait for lv to be settled.
# newer systems have udevadm command but older systems like RHEL5 don't.
# But if neither one is available, just set it to "sleep 1" to wait for lv to
# be settled
diff --git a/common/encrypt b/common/encrypt
index d90a566a..1caca767 100644
--- a/common/encrypt
+++ b/common/encrypt
@@ -150,10 +150,46 @@ _require_encryption_policy_support()
$KEYCTL_PROG clear $TEST_KEYRING_ID
fi
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
ext4|f2fs)
_scratch_mkfs -O encrypt
@@ -249,18 +285,21 @@ _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.
_num_to_hex()
{
@@ -405,10 +444,25 @@ _add_enckey()
shift 2
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
local raw_key=$2
shift 2
@@ -851,19 +905,21 @@ _fscrypt_mode_name_to_num()
# 'v2': test a v2 encryption policy
# 'direct': test the DIRECT_KEY policy flag
# '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()
{
local contents_encryption_mode=$1
local filenames_encryption_mode=$2
local opt
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=""
local crypt_util_filename_args=""
local expected_identifier
@@ -888,10 +944,15 @@ _verify_ciphertext_for_encryption_policy()
(( policy_flags |= FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32 ))
;;
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]}"
;;
esac
done
@@ -927,10 +988,13 @@ _verify_ciphertext_for_encryption_policy()
fi
fi
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
_require_get_ciphertext_filename_support
if (( policy_version == 1 )); then
@@ -956,15 +1020,23 @@ _verify_ciphertext_for_encryption_policy()
crypt_util_contents_args+="$crypt_util_args"
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
fi
local raw_key_hex=$(echo "$raw_key" | tr -d '\\x')
--
2.47.1
next prev parent reply other threads:[~2024-12-13 5:28 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-13 5:28 [PATCH v2 0/3] xfstests: test the fscrypt hardware-wrapped key support Eric Biggers
2024-12-13 5:28 ` [PATCH v2 1/3] fscrypt-crypt-util: add hardware KDF support Eric Biggers
2024-12-13 5:28 ` Eric Biggers [this message]
2024-12-13 5:28 ` [PATCH v2 3/3] generic: verify ciphertext with hardware-wrapped keys Eric Biggers
2025-01-07 13:59 ` [PATCH v2 0/3] xfstests: test the fscrypt hardware-wrapped key support Zorro Lang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241213052840.314921-3-ebiggers@kernel.org \
--to=ebiggers@kernel.org \
--cc=brgl@bgdev.pl \
--cc=fstests@vger.kernel.org \
--cc=linux-fscrypt@vger.kernel.org \
--cc=quic_gaurkash@quicinc.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox