[PATCH 12/12] fscrypt-crypt-util: add support for per extent KDF

Daniel Vacek <[email protected]>
Newsgroups org.kernel.vger.linux-xfs,net.sourceforge.lists.linux-f2fs-devel,org.kernel.vger.fstests,org.kernel.vger.linux-btrfs,org.kernel.vger.linux-ext4,org.kernel.vger.linux-fscrypt
Message-ID <[email protected]>
When deriving a key for extent, fscrypt uses different salt. Add the
support for this.

Signed-off-by: Daniel Vacek <[email protected]>
---
 common/encrypt           | 13 +++++++++----
 src/fscrypt-crypt-util.c | 12 +++++++++++-
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/common/encrypt b/common/encrypt
index 4c3fd904..2485b69a 100644
--- a/common/encrypt
+++ b/common/encrypt
@@ -836,7 +836,7 @@ _do_verify_ciphertext_for_encryption_policy()
 	local blocksize=$(_get_block_size $SCRATCH_MNT)
 	local test_contents_files=()
 	local test_filenames_files=()
-	local i src dir dst inode blocklist \
+	local i src dir dst inode blocklist context_per_extent \
 	      padding_flag padding dir_inode len name f nonce decrypted_name
 
 	# Create files whose encrypted contents we'll verify.  For each, save
@@ -891,19 +891,24 @@ _do_verify_ciphertext_for_encryption_policy()
 	# Now unmount the filesystem and verify the ciphertext we just wrote.
 	_scratch_unmount
 
+	case $FSTYP in
+	btrfs)	context_per_extent=--context-per-extent;;
+	*)	context_per_extent=;;
+	esac
+
 	echo "Verifying encrypted file contents" >> $seqres.full
 	for f in "${test_contents_files[@]}"; do
 		read -r src inode blocklist <<< "$f"
 		nonce=$(_get_encryption_data_nonce $SCRATCH_DEV $inode)
 		_dump_ciphertext_blocks $SCRATCH_DEV $blocklist > $tmp.actual_contents
 		$crypt_contents_cmd $contents_encryption_mode $raw_key_hex \
-			--file-nonce=$nonce --inode-number=$inode \
-                        < $src > $tmp.expected_contents
+			--file-nonce=$nonce $context_per_extent --inode-number=$inode \
+			< $src > $tmp.expected_contents
 		if ! cmp $tmp.expected_contents $tmp.actual_contents; then
 			_fail "Expected encrypted contents != actual encrypted contents.  File: $f"
 		fi
 		$crypt_contents_cmd $contents_encryption_mode $raw_key_hex \
-			--decrypt --file-nonce=$nonce --inode-number=$inode \
+			--decrypt --file-nonce=$nonce $context_per_extent --inode-number=$inode \
 			< $tmp.actual_contents > $tmp.decrypted_contents
 		if ! cmp $src $tmp.decrypted_contents; then
 			_fail "Contents decryption sanity check failed.  File: $f"
diff --git a/src/fscrypt-crypt-util.c b/src/fscrypt-crypt-util.c
index f51b3669..1403edb5 100644
--- a/src/fscrypt-crypt-util.c
+++ b/src/fscrypt-crypt-util.c
@@ -75,6 +75,7 @@ static void usage(FILE *fp)
 "                                replicate the en/decryption that is done when\n"
 "                                the filesystem is given a hardware-wrapped key.\n"
 "  --file-nonce=NONCE          File's nonce as a 32-character hex string\n"
+"  --context-per-extent        Derive the key for per extent context.\n"
 "  --fs-uuid=UUID              The filesystem UUID as a 32-character hex string.\n"
 "                                Required for --iv-ino-lblk-32 and\n"
 "                                --iv-ino-lblk-64; otherwise is unused.\n"
@@ -2162,6 +2163,7 @@ struct key_and_iv_params {
 	bool direct_key;
 	bool iv_ino_lblk_64;
 	bool iv_ino_lblk_32;
+	bool context_per_extent;
 	u64 data_unit_index;
 	u64 inode_number;
 	u8 fs_uuid[UUID_SIZE];
@@ -2176,6 +2178,7 @@ struct key_and_iv_params {
 #define HKDF_CONTEXT_IV_INO_LBLK_32_KEY	6
 #define HKDF_CONTEXT_INODE_HASH_KEY	7
 #define HKDF_CONTEXT_KEY_IDENTIFIER_FOR_HW_WRAPPED_KEY 8
+#define HKDF_CONTEXT_PER_EXTENT_ENC_KEY	9
 
 /* Hash the file's inode number using SipHash keyed by a derived key */
 static u32 hash_inode_number(const struct key_and_iv_params *params)
@@ -2366,7 +2369,9 @@ static void derive_real_key(const struct key_and_iv_params *params,
 		} else {
 			if (!params->file_nonce_specified)
 				die("--kdf=HKDF-SHA512 requires --file-nonce or --iv-ino-lblk-{64,32}");
-			info[infolen++] = HKDF_CONTEXT_PER_FILE_ENC_KEY;
+			info[infolen++] = params->context_per_extent?
+						HKDF_CONTEXT_PER_EXTENT_ENC_KEY:
+						HKDF_CONTEXT_PER_FILE_ENC_KEY;
 			memcpy(&info[infolen], params->file_nonce,
 			       FILE_NONCE_SIZE);
 			infolen += FILE_NONCE_SIZE;
@@ -2481,6 +2486,7 @@ enum {
 	OPT_DUMP_KEY_IDENTIFIER,
 	OPT_ENABLE_HW_KDF,
 	OPT_FILE_NONCE,
+	OPT_CONTEXT_PER_EXTENT,
 	OPT_FS_UUID,
 	OPT_HELP,
 	OPT_INODE_NUMBER,
@@ -2500,6 +2506,7 @@ static const struct option longopts[] = {
 	{ "dump-key-identifier", no_argument,   NULL, OPT_DUMP_KEY_IDENTIFIER },
 	{ "enable-hw-kdf",   no_argument,       NULL, OPT_ENABLE_HW_KDF },
 	{ "file-nonce",      required_argument, NULL, OPT_FILE_NONCE },
+	{ "context-per-extent", no_argument,    NULL, OPT_CONTEXT_PER_EXTENT },
 	{ "fs-uuid",         required_argument, NULL, OPT_FS_UUID },
 	{ "help",            no_argument,       NULL, OPT_HELP },
 	{ "inode-number",    required_argument, NULL, OPT_INODE_NUMBER },
@@ -2572,6 +2579,9 @@ int main(int argc, char *argv[])
 				die("Invalid file nonce: %s", optarg);
 			params.file_nonce_specified = true;
 			break;
+		case OPT_CONTEXT_PER_EXTENT:
+			params.context_per_extent = true;
+			break;
 		case OPT_FS_UUID:
 			if (hex2bin(optarg, params.fs_uuid, UUID_SIZE)
 			    != UUID_SIZE)
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.