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


Reply via email to