* [PATCH v2 0/5] xfstests: fscrypt test cleanups
@ 2022-03-13 1:05 Eric Biggers
2022-03-13 1:05 ` [PATCH v2 1/5] fscrypt-crypt-util: use an explicit --direct-key option Eric Biggers
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Eric Biggers @ 2022-03-13 1:05 UTC (permalink / raw)
To: fstests; +Cc: linux-fscrypt
This series makes some minor improvements to the fscrypt ciphertext
verification tests. I've split these out from my series
"[RFC PATCH 0/8] xfstests: test the fscrypt hardware-wrapped key support"
(https://lore.kernel.org/fstests/20220228074722.77008-1-ebiggers@kernel.org/T/#u)
and updated them slightly. These can be applied now.
I've verified that all the 'encrypt' group tests still pass with this
series applied.
Eric Biggers (5):
fscrypt-crypt-util: use an explicit --direct-key option
fscrypt-crypt-util: refactor get_key_and_iv()
fscrypt-crypt-util: add support for dumping key identifier
common/encrypt: log full ciphertext verification params
common/encrypt: verify the key identifiers
common/encrypt | 34 +++++--
src/fscrypt-crypt-util.c | 193 ++++++++++++++++++++++++++-------------
2 files changed, 159 insertions(+), 68 deletions(-)
--
2.35.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/5] fscrypt-crypt-util: use an explicit --direct-key option
2022-03-13 1:05 [PATCH v2 0/5] xfstests: fscrypt test cleanups Eric Biggers
@ 2022-03-13 1:05 ` Eric Biggers
2022-03-13 1:05 ` [PATCH v2 2/5] fscrypt-crypt-util: refactor get_key_and_iv() Eric Biggers
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Eric Biggers @ 2022-03-13 1:05 UTC (permalink / raw)
To: fstests; +Cc: linux-fscrypt
From: Eric Biggers <ebiggers@google.com>
Make fscrypt-crypt-util use an option --direct-key to specify the use of
the DIRECT_KEY method for key derivation and IV generation. Previously,
this method was implicitly detected via --mode-num being given without
either --iv-ino-lblk-64 or --iv-ino-lblk-32, or --kdf=none being given
in combination with --file-nonce.
The benefit of this change is that it makes the various options to
fscrypt-crypt-util behave more consistently. --direct-key,
--iv-ino-lblk-64, and --iv-ino-lblk-32 now all work similarly (they
select a key derivation and IV generation method); likewise, --mode-num,
--file-nonce, --inode-number, and --fs-uuid now all work similarly (they
provide information that key derivation and IV generation may need).
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
common/encrypt | 10 ++++----
src/fscrypt-crypt-util.c | 52 ++++++++++++++++++++++++----------------
2 files changed, 36 insertions(+), 26 deletions(-)
diff --git a/common/encrypt b/common/encrypt
index f90c4ef0..2cf02ca0 100644
--- a/common/encrypt
+++ b/common/encrypt
@@ -842,27 +842,25 @@ _verify_ciphertext_for_encryption_policy()
set_encpolicy_args+=" -c $contents_mode_num"
set_encpolicy_args+=" -n $filenames_mode_num"
+ crypt_util_contents_args+=" --mode-num=$contents_mode_num"
+ crypt_util_filename_args+=" --mode-num=$filenames_mode_num"
if (( policy_version > 1 )); then
set_encpolicy_args+=" -v 2"
crypt_util_args+=" --kdf=HKDF-SHA512"
if (( policy_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY )); then
- crypt_util_args+=" --mode-num=$contents_mode_num"
+ crypt_util_args+=" --direct-key"
elif (( policy_flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 )); then
crypt_util_args+=" --iv-ino-lblk-64"
- crypt_util_contents_args+=" --mode-num=$contents_mode_num"
- crypt_util_filename_args+=" --mode-num=$filenames_mode_num"
elif (( policy_flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32 )); then
crypt_util_args+=" --iv-ino-lblk-32"
- crypt_util_contents_args+=" --mode-num=$contents_mode_num"
- crypt_util_filename_args+=" --mode-num=$filenames_mode_num"
fi
else
if (( policy_flags & ~FSCRYPT_POLICY_FLAG_DIRECT_KEY )); then
_fail "unsupported flags for v1 policy: $policy_flags"
fi
if (( policy_flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY )); then
- crypt_util_args+=" --kdf=none"
+ crypt_util_args+=" --direct-key --kdf=none"
else
crypt_util_args+=" --kdf=AES-128-ECB"
fi
diff --git a/src/fscrypt-crypt-util.c b/src/fscrypt-crypt-util.c
index 03cc3c4a..e5992275 100644
--- a/src/fscrypt-crypt-util.c
+++ b/src/fscrypt-crypt-util.c
@@ -64,6 +64,8 @@ static void usage(FILE *fp)
" --block-size=BLOCK_SIZE Encrypt each BLOCK_SIZE bytes independently.\n"
" Default: 4096 bytes\n"
" --decrypt Decrypt instead of encrypt\n"
+" --direct-key Use the format where the IVs include the file\n"
+" nonce and the same key is shared across files.\n"
" --file-nonce=NONCE File's nonce as a 32-character hex string\n"
" --fs-uuid=UUID The filesystem UUID as a 32-character hex string.\n"
" Required for --iv-ino-lblk-32 and\n"
@@ -76,11 +78,10 @@ static void usage(FILE *fp)
" 32-bit variant.\n"
" --iv-ino-lblk-64 Use the format where the IVs include the inode\n"
" number and the same key is shared across files.\n"
-" Requires --kdf=HKDF-SHA512, --fs-uuid,\n"
-" --inode-number, and --mode-num.\n"
" --kdf=KDF Key derivation function to use: AES-128-ECB,\n"
" HKDF-SHA512, or none. Default: none\n"
-" --mode-num=NUM Derive per-mode key using mode number NUM\n"
+" --mode-num=NUM The encryption mode number. This may be required\n"
+" for key derivation, depending on other options.\n"
" --padding=PADDING If last block is partial, zero-pad it to next\n"
" PADDING-byte boundary. Default: BLOCK_SIZE\n"
, fp);
@@ -1790,6 +1791,7 @@ struct key_and_iv_params {
u8 mode_num;
u8 file_nonce[FILE_NONCE_SIZE];
bool file_nonce_specified;
+ bool direct_key;
bool iv_ino_lblk_64;
bool iv_ino_lblk_32;
u64 block_number;
@@ -1835,7 +1837,7 @@ static void get_key_and_iv(const struct key_and_iv_params *params,
u8 *real_key, size_t real_key_size,
union fscrypt_iv *iv)
{
- bool file_nonce_in_iv = false;
+ int iv_methods = 0;
struct aes_key aes_key;
u8 info[8 + 1 + 1 + UUID_SIZE] = "fscrypt";
size_t infolen = 8;
@@ -1848,11 +1850,22 @@ static void get_key_and_iv(const struct key_and_iv_params *params,
/* Overridden later for iv_ino_lblk_{64,32} */
iv->block_number = cpu_to_le64(params->block_number);
- if (params->iv_ino_lblk_64 || params->iv_ino_lblk_32) {
+ iv_methods += params->direct_key;
+ iv_methods += params->iv_ino_lblk_64;
+ iv_methods += params->iv_ino_lblk_32;
+ if (iv_methods > 1)
+ die("Conflicting IV methods specified");
+ if (iv_methods > 0 && params->kdf == KDF_AES_128_ECB)
+ die("--kdf=AES-128-ECB is incompatible with IV method options");
+
+ if (params->direct_key) {
+ if (!params->file_nonce_specified)
+ die("--direct-key requires --file-nonce");
+ if (params->kdf != KDF_NONE && params->mode_num == 0)
+ die("--direct-key with KDF requires --mode-num");
+ } else if (params->iv_ino_lblk_64 || params->iv_ino_lblk_32) {
const char *opt = params->iv_ino_lblk_64 ? "--iv-ino-lblk-64" :
"--iv-ino-lblk-32";
- if (params->iv_ino_lblk_64 && params->iv_ino_lblk_32)
- die("--iv-ino-lblk-64 and --iv-ino-lblk-32 are mutually exclusive");
if (params->kdf != KDF_HKDF_SHA512)
die("%s requires --kdf=HKDF-SHA512", opt);
if (!params->fs_uuid_specified)
@@ -1869,16 +1882,11 @@ static void get_key_and_iv(const struct key_and_iv_params *params,
switch (params->kdf) {
case KDF_NONE:
- if (params->mode_num != 0)
- die("--mode-num isn't supported with --kdf=none");
memcpy(real_key, params->master_key, real_key_size);
- file_nonce_in_iv = true;
break;
case KDF_AES_128_ECB:
if (!params->file_nonce_specified)
- die("--file-nonce is required with --kdf=AES-128-ECB");
- if (params->mode_num != 0)
- die("--mode-num isn't supported with --kdf=AES-128-ECB");
+ die("--kdf=AES-128-ECB requires --file-nonce");
STATIC_ASSERT(FILE_NONCE_SIZE == AES_128_KEY_SIZE);
ASSERT(real_key_size % AES_BLOCK_SIZE == 0);
aes_setkey(&aes_key, params->file_nonce, AES_128_KEY_SIZE);
@@ -1887,7 +1895,10 @@ static void get_key_and_iv(const struct key_and_iv_params *params,
&real_key[i]);
break;
case KDF_HKDF_SHA512:
- if (params->iv_ino_lblk_64) {
+ if (params->direct_key) {
+ info[infolen++] = HKDF_CONTEXT_DIRECT_KEY;
+ info[infolen++] = params->mode_num;
+ } else if (params->iv_ino_lblk_64) {
info[infolen++] = HKDF_CONTEXT_IV_INO_LBLK_64_KEY;
info[infolen++] = params->mode_num;
memcpy(&info[infolen], params->fs_uuid, UUID_SIZE);
@@ -1903,17 +1914,13 @@ static void get_key_and_iv(const struct key_and_iv_params *params,
cpu_to_le32(hash_inode_number(params) +
params->block_number);
iv->inode_number = 0;
- } else if (params->mode_num != 0) {
- info[infolen++] = HKDF_CONTEXT_DIRECT_KEY;
- info[infolen++] = params->mode_num;
- file_nonce_in_iv = true;
} else if (params->file_nonce_specified) {
info[infolen++] = HKDF_CONTEXT_PER_FILE_ENC_KEY;
memcpy(&info[infolen], params->file_nonce,
FILE_NONCE_SIZE);
infolen += FILE_NONCE_SIZE;
} else {
- die("With --kdf=HKDF-SHA512, at least one of --file-nonce and --mode-num must be specified");
+ die("--kdf=HKDF-SHA512 requires --file-nonce or --iv-ino-lblk-{64,32}");
}
hkdf_sha512(params->master_key, params->master_key_size,
NULL, 0, info, infolen, real_key, real_key_size);
@@ -1922,7 +1929,7 @@ static void get_key_and_iv(const struct key_and_iv_params *params,
ASSERT(0);
}
- if (file_nonce_in_iv && params->file_nonce_specified)
+ if (params->direct_key)
memcpy(iv->nonce, params->file_nonce, FILE_NONCE_SIZE);
}
@@ -1930,6 +1937,7 @@ enum {
OPT_BLOCK_NUMBER,
OPT_BLOCK_SIZE,
OPT_DECRYPT,
+ OPT_DIRECT_KEY,
OPT_FILE_NONCE,
OPT_FS_UUID,
OPT_HELP,
@@ -1945,6 +1953,7 @@ static const struct option longopts[] = {
{ "block-number", required_argument, NULL, OPT_BLOCK_NUMBER },
{ "block-size", required_argument, NULL, OPT_BLOCK_SIZE },
{ "decrypt", no_argument, NULL, OPT_DECRYPT },
+ { "direct-key", no_argument, NULL, OPT_DIRECT_KEY },
{ "file-nonce", required_argument, NULL, OPT_FILE_NONCE },
{ "fs-uuid", required_argument, NULL, OPT_FS_UUID },
{ "help", no_argument, NULL, OPT_HELP },
@@ -1999,6 +2008,9 @@ int main(int argc, char *argv[])
case OPT_DECRYPT:
decrypting = true;
break;
+ case OPT_DIRECT_KEY:
+ params.direct_key = true;
+ break;
case OPT_FILE_NONCE:
if (hex2bin(optarg, params.file_nonce, FILE_NONCE_SIZE)
!= FILE_NONCE_SIZE)
--
2.35.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/5] fscrypt-crypt-util: refactor get_key_and_iv()
2022-03-13 1:05 [PATCH v2 0/5] xfstests: fscrypt test cleanups Eric Biggers
2022-03-13 1:05 ` [PATCH v2 1/5] fscrypt-crypt-util: use an explicit --direct-key option Eric Biggers
@ 2022-03-13 1:05 ` Eric Biggers
2022-03-13 1:05 ` [PATCH v2 3/5] fscrypt-crypt-util: add support for dumping key identifier Eric Biggers
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Eric Biggers @ 2022-03-13 1:05 UTC (permalink / raw)
To: fstests; +Cc: linux-fscrypt
From: Eric Biggers <ebiggers@google.com>
Split get_key_and_iv() into two distinct parts: (1) deriving the key and
(2) generating the IV. Also, check for the presence of needed options
just before they are used rather than doing it all up-front.
These changes should make this code much easier to understand.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
src/fscrypt-crypt-util.c | 124 ++++++++++++++++++++++-----------------
1 file changed, 70 insertions(+), 54 deletions(-)
diff --git a/src/fscrypt-crypt-util.c b/src/fscrypt-crypt-util.c
index e5992275..124eb23f 100644
--- a/src/fscrypt-crypt-util.c
+++ b/src/fscrypt-crypt-util.c
@@ -1818,6 +1818,9 @@ static u32 hash_inode_number(const struct key_and_iv_params *params)
} hash_key;
info[8] = HKDF_CONTEXT_INODE_HASH_KEY;
+
+ if (params->kdf != KDF_HKDF_SHA512)
+ die("--iv-ino-lblk-32 requires --kdf=HKDF-SHA512");
hkdf_sha512(params->master_key, params->master_key_size,
NULL, 0, info, sizeof(info),
hash_key.bytes, sizeof(hash_key));
@@ -1828,16 +1831,9 @@ static u32 hash_inode_number(const struct key_and_iv_params *params)
return (u32)siphash_1u64(hash_key.words, params->inode_number);
}
-/*
- * Get the key and starting IV with which the encryption will actually be done.
- * If a KDF was specified, a subkey is derived from the master key and the mode
- * number or file nonce. Otherwise, the master key is used directly.
- */
-static void get_key_and_iv(const struct key_and_iv_params *params,
- u8 *real_key, size_t real_key_size,
- union fscrypt_iv *iv)
+static void derive_real_key(const struct key_and_iv_params *params,
+ u8 *real_key, size_t real_key_size)
{
- int iv_methods = 0;
struct aes_key aes_key;
u8 info[8 + 1 + 1 + UUID_SIZE] = "fscrypt";
size_t infolen = 8;
@@ -1845,41 +1841,6 @@ static void get_key_and_iv(const struct key_and_iv_params *params,
ASSERT(real_key_size <= params->master_key_size);
- memset(iv, 0, sizeof(*iv));
-
- /* Overridden later for iv_ino_lblk_{64,32} */
- iv->block_number = cpu_to_le64(params->block_number);
-
- iv_methods += params->direct_key;
- iv_methods += params->iv_ino_lblk_64;
- iv_methods += params->iv_ino_lblk_32;
- if (iv_methods > 1)
- die("Conflicting IV methods specified");
- if (iv_methods > 0 && params->kdf == KDF_AES_128_ECB)
- die("--kdf=AES-128-ECB is incompatible with IV method options");
-
- if (params->direct_key) {
- if (!params->file_nonce_specified)
- die("--direct-key requires --file-nonce");
- if (params->kdf != KDF_NONE && params->mode_num == 0)
- die("--direct-key with KDF requires --mode-num");
- } else if (params->iv_ino_lblk_64 || params->iv_ino_lblk_32) {
- const char *opt = params->iv_ino_lblk_64 ? "--iv-ino-lblk-64" :
- "--iv-ino-lblk-32";
- if (params->kdf != KDF_HKDF_SHA512)
- die("%s requires --kdf=HKDF-SHA512", opt);
- if (!params->fs_uuid_specified)
- die("%s requires --fs-uuid", opt);
- if (params->inode_number == 0)
- die("%s requires --inode-number", opt);
- if (params->mode_num == 0)
- die("%s requires --mode-num", opt);
- if (params->block_number > UINT32_MAX)
- die("%s can't use --block-number > UINT32_MAX", opt);
- if (params->inode_number > UINT32_MAX)
- die("%s can't use --inode-number > UINT32_MAX", opt);
- }
-
switch (params->kdf) {
case KDF_NONE:
memcpy(real_key, params->master_key, real_key_size);
@@ -1896,31 +1857,35 @@ static void get_key_and_iv(const struct key_and_iv_params *params,
break;
case KDF_HKDF_SHA512:
if (params->direct_key) {
+ if (params->mode_num == 0)
+ die("--direct-key with KDF requires --mode-num");
info[infolen++] = HKDF_CONTEXT_DIRECT_KEY;
info[infolen++] = params->mode_num;
} else if (params->iv_ino_lblk_64) {
+ if (params->mode_num == 0)
+ die("--iv-ino-lblk-64 with KDF requires --mode-num");
+ if (!params->fs_uuid_specified)
+ die("--iv-ino-lblk-64 with KDF requires --fs-uuid");
info[infolen++] = HKDF_CONTEXT_IV_INO_LBLK_64_KEY;
info[infolen++] = params->mode_num;
memcpy(&info[infolen], params->fs_uuid, UUID_SIZE);
infolen += UUID_SIZE;
- iv->block_number32 = cpu_to_le32(params->block_number);
- iv->inode_number = cpu_to_le32(params->inode_number);
} else if (params->iv_ino_lblk_32) {
+ if (params->mode_num == 0)
+ die("--iv-ino-lblk-32 with KDF requires --mode-num");
+ if (!params->fs_uuid_specified)
+ die("--iv-ino-lblk-32 with KDF requires --fs-uuid");
info[infolen++] = HKDF_CONTEXT_IV_INO_LBLK_32_KEY;
info[infolen++] = params->mode_num;
memcpy(&info[infolen], params->fs_uuid, UUID_SIZE);
infolen += UUID_SIZE;
- iv->block_number32 =
- cpu_to_le32(hash_inode_number(params) +
- params->block_number);
- iv->inode_number = 0;
- } else if (params->file_nonce_specified) {
+ } 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;
memcpy(&info[infolen], params->file_nonce,
FILE_NONCE_SIZE);
infolen += FILE_NONCE_SIZE;
- } else {
- die("--kdf=HKDF-SHA512 requires --file-nonce or --iv-ino-lblk-{64,32}");
}
hkdf_sha512(params->master_key, params->master_key_size,
NULL, 0, info, infolen, real_key, real_key_size);
@@ -1928,9 +1893,60 @@ static void get_key_and_iv(const struct key_and_iv_params *params,
default:
ASSERT(0);
}
+}
- if (params->direct_key)
+static void generate_iv(const struct key_and_iv_params *params,
+ union fscrypt_iv *iv)
+{
+ memset(iv, 0, sizeof(*iv));
+ if (params->direct_key) {
+ if (!params->file_nonce_specified)
+ die("--direct-key requires --file-nonce");
+ iv->block_number = cpu_to_le64(params->block_number);
memcpy(iv->nonce, params->file_nonce, FILE_NONCE_SIZE);
+ } else if (params->iv_ino_lblk_64) {
+ if (params->block_number > UINT32_MAX)
+ die("iv-ino-lblk-64 can't use --block-number > UINT32_MAX");
+ if (params->inode_number == 0)
+ die("iv-ino-lblk-64 requires --inode-number");
+ if (params->inode_number > UINT32_MAX)
+ die("iv-ino-lblk-64 can't use --inode-number > UINT32_MAX");
+ iv->block_number32 = cpu_to_le32(params->block_number);
+ iv->inode_number = cpu_to_le32(params->inode_number);
+ } else if (params->iv_ino_lblk_32) {
+ if (params->block_number > UINT32_MAX)
+ die("iv-ino-lblk-32 can't use --block-number > UINT32_MAX");
+ if (params->inode_number == 0)
+ die("iv-ino-lblk-32 requires --inode-number");
+ iv->block_number32 = cpu_to_le32(hash_inode_number(params) +
+ params->block_number);
+ } else {
+ iv->block_number = cpu_to_le64(params->block_number);
+ }
+}
+
+/*
+ * Get the key and starting IV with which the encryption will actually be done.
+ * If a KDF was specified, then a subkey is derived from the master key.
+ * Otherwise, the master key is used directly.
+ */
+static void get_key_and_iv(const struct key_and_iv_params *params,
+ u8 *real_key, size_t real_key_size,
+ union fscrypt_iv *iv)
+{
+ int iv_methods = 0;
+
+ iv_methods += params->direct_key;
+ iv_methods += params->iv_ino_lblk_64;
+ iv_methods += params->iv_ino_lblk_32;
+ if (iv_methods > 1)
+ die("Conflicting IV methods specified");
+ if (iv_methods > 0 && params->kdf == KDF_AES_128_ECB)
+ die("--kdf=AES-128-ECB is incompatible with IV method options");
+
+ derive_real_key(params, real_key, real_key_size);
+
+ generate_iv(params, iv);
}
enum {
--
2.35.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 3/5] fscrypt-crypt-util: add support for dumping key identifier
2022-03-13 1:05 [PATCH v2 0/5] xfstests: fscrypt test cleanups Eric Biggers
2022-03-13 1:05 ` [PATCH v2 1/5] fscrypt-crypt-util: use an explicit --direct-key option Eric Biggers
2022-03-13 1:05 ` [PATCH v2 2/5] fscrypt-crypt-util: refactor get_key_and_iv() Eric Biggers
@ 2022-03-13 1:05 ` Eric Biggers
2022-03-13 1:05 ` [PATCH v2 4/5] common/encrypt: log full ciphertext verification params Eric Biggers
2022-03-13 1:05 ` [PATCH v2 5/5] common/encrypt: verify the key identifiers Eric Biggers
4 siblings, 0 replies; 6+ messages in thread
From: Eric Biggers @ 2022-03-13 1:05 UTC (permalink / raw)
To: fstests; +Cc: linux-fscrypt
From: Eric Biggers <ebiggers@google.com>
Add an option to fscrypt-crypt-util to make it compute the key
identifier for the given key. This will allow testing the correctness
of the filesystem's key identifier computation.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
src/fscrypt-crypt-util.c | 51 ++++++++++++++++++++++++++++++++++++----
1 file changed, 46 insertions(+), 5 deletions(-)
diff --git a/src/fscrypt-crypt-util.c b/src/fscrypt-crypt-util.c
index 124eb23f..ffb9534d 100644
--- a/src/fscrypt-crypt-util.c
+++ b/src/fscrypt-crypt-util.c
@@ -46,7 +46,7 @@
static void usage(FILE *fp)
{
fputs(
-"Usage: " PROGRAM_NAME " [OPTION]... CIPHER MASTER_KEY\n"
+"Usage: " PROGRAM_NAME " [OPTION]... [CIPHER | --dump-key-identifier] MASTER_KEY\n"
"\n"
"Utility for verifying fscrypt-encrypted data. This program encrypts\n"
"(or decrypts) the data on stdin using the given CIPHER with the given\n"
@@ -66,6 +66,8 @@ static void usage(FILE *fp)
" --decrypt Decrypt instead of encrypt\n"
" --direct-key Use the format where the IVs include the file\n"
" nonce and the same key is shared across files.\n"
+" --dump-key-identifier Instead of encrypting/decrypting data, just\n"
+" compute and dump the key identifier.\n"
" --file-nonce=NONCE File's nonce as a 32-character hex string\n"
" --fs-uuid=UUID The filesystem UUID as a 32-character hex string.\n"
" Required for --iv-ino-lblk-32 and\n"
@@ -1949,11 +1951,38 @@ static void get_key_and_iv(const struct key_and_iv_params *params,
generate_iv(params, iv);
}
+static void do_dump_key_identifier(const struct key_and_iv_params *params)
+{
+ u8 info[9] = "fscrypt";
+ u8 key_identifier[16];
+ int i;
+
+ info[8] = HKDF_CONTEXT_KEY_IDENTIFIER;
+
+ if (params->kdf != KDF_HKDF_SHA512)
+ die("--dump-key-identifier requires --kdf=HKDF-SHA512");
+ hkdf_sha512(params->master_key, params->master_key_size,
+ NULL, 0, info, sizeof(info),
+ key_identifier, sizeof(key_identifier));
+
+ for (i = 0; i < sizeof(key_identifier); i++)
+ printf("%02x", key_identifier[i]);
+}
+
+static void parse_master_key(const char *arg, struct key_and_iv_params *params)
+{
+ params->master_key_size = hex2bin(arg, params->master_key,
+ MAX_KEY_SIZE);
+ if (params->master_key_size < 0)
+ die("Invalid master_key: %s", arg);
+}
+
enum {
OPT_BLOCK_NUMBER,
OPT_BLOCK_SIZE,
OPT_DECRYPT,
OPT_DIRECT_KEY,
+ OPT_DUMP_KEY_IDENTIFIER,
OPT_FILE_NONCE,
OPT_FS_UUID,
OPT_HELP,
@@ -1970,6 +1999,7 @@ static const struct option longopts[] = {
{ "block-size", required_argument, NULL, OPT_BLOCK_SIZE },
{ "decrypt", no_argument, NULL, OPT_DECRYPT },
{ "direct-key", no_argument, NULL, OPT_DIRECT_KEY },
+ { "dump-key-identifier", no_argument, NULL, OPT_DUMP_KEY_IDENTIFIER },
{ "file-nonce", required_argument, NULL, OPT_FILE_NONCE },
{ "fs-uuid", required_argument, NULL, OPT_FS_UUID },
{ "help", no_argument, NULL, OPT_HELP },
@@ -1986,6 +2016,7 @@ int main(int argc, char *argv[])
{
size_t block_size = 4096;
bool decrypting = false;
+ bool dump_key_identifier = false;
struct key_and_iv_params params;
size_t padding = 0;
const struct fscrypt_cipher *cipher;
@@ -2027,6 +2058,9 @@ int main(int argc, char *argv[])
case OPT_DIRECT_KEY:
params.direct_key = true;
break;
+ case OPT_DUMP_KEY_IDENTIFIER:
+ dump_key_identifier = true;
+ break;
case OPT_FILE_NONCE:
if (hex2bin(optarg, params.file_nonce, FILE_NONCE_SIZE)
!= FILE_NONCE_SIZE)
@@ -2074,6 +2108,15 @@ int main(int argc, char *argv[])
argc -= optind;
argv += optind;
+ if (dump_key_identifier) {
+ if (argc != 1) {
+ usage(stderr);
+ return 2;
+ }
+ parse_master_key(argv[0], ¶ms);
+ do_dump_key_identifier(¶ms);
+ return 0;
+ }
if (argc != 2) {
usage(stderr);
return 2;
@@ -2087,10 +2130,8 @@ int main(int argc, char *argv[])
die("Block size of %zu bytes is too small for cipher %s",
block_size, cipher->name);
- params.master_key_size = hex2bin(argv[1], params.master_key,
- MAX_KEY_SIZE);
- if (params.master_key_size < 0)
- die("Invalid master_key: %s", argv[1]);
+ parse_master_key(argv[1], ¶ms);
+
if (params.master_key_size < cipher->keysize)
die("Master key is too short for cipher %s", cipher->name);
--
2.35.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 4/5] common/encrypt: log full ciphertext verification params
2022-03-13 1:05 [PATCH v2 0/5] xfstests: fscrypt test cleanups Eric Biggers
` (2 preceding siblings ...)
2022-03-13 1:05 ` [PATCH v2 3/5] fscrypt-crypt-util: add support for dumping key identifier Eric Biggers
@ 2022-03-13 1:05 ` Eric Biggers
2022-03-13 1:05 ` [PATCH v2 5/5] common/encrypt: verify the key identifiers Eric Biggers
4 siblings, 0 replies; 6+ messages in thread
From: Eric Biggers @ 2022-03-13 1:05 UTC (permalink / raw)
To: fstests; +Cc: linux-fscrypt
From: Eric Biggers <ebiggers@google.com>
To help with debugging, log some additional information to $seqres.full.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
common/encrypt | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/common/encrypt b/common/encrypt
index 2cf02ca0..cf402570 100644
--- a/common/encrypt
+++ b/common/encrypt
@@ -908,6 +908,17 @@ _verify_ciphertext_for_encryption_policy()
echo -e "\tfilenames_encryption_mode: $filenames_encryption_mode"
[ $# -ne 0 ] && echo -e "\toptions: $*"
+ cat >> $seqres.full <<EOF
+Full ciphertext verification parameters:
+ contents_encryption_mode = $contents_encryption_mode
+ filenames_encryption_mode = $filenames_encryption_mode
+ policy_flags = $policy_flags
+ set_encpolicy_args = $set_encpolicy_args
+ keyspec = $keyspec
+ raw_key_hex = $raw_key_hex
+ crypt_util_contents_args = $crypt_util_contents_args
+ crypt_util_filename_args = $crypt_util_filename_args
+EOF
_do_verify_ciphertext_for_encryption_policy \
"$contents_encryption_mode" \
"$filenames_encryption_mode" \
--
2.35.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 5/5] common/encrypt: verify the key identifiers
2022-03-13 1:05 [PATCH v2 0/5] xfstests: fscrypt test cleanups Eric Biggers
` (3 preceding siblings ...)
2022-03-13 1:05 ` [PATCH v2 4/5] common/encrypt: log full ciphertext verification params Eric Biggers
@ 2022-03-13 1:05 ` Eric Biggers
4 siblings, 0 replies; 6+ messages in thread
From: Eric Biggers @ 2022-03-13 1:05 UTC (permalink / raw)
To: fstests; +Cc: linux-fscrypt
From: Eric Biggers <ebiggers@google.com>
As part of all the ciphertext verification tests, verify that the
filesystem correctly computed the key identifier from the key the test
generated. This uses fscrypt-crypt-util to compute the key identifier.
Previously this was only being tested indirectly, via the tests that
happen to use the hardcoded $TEST_RAW_KEY and $TEST_KEY_IDENTIFIER.
The new check provides better coverage.
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
common/encrypt | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/common/encrypt b/common/encrypt
index cf402570..78a574bd 100644
--- a/common/encrypt
+++ b/common/encrypt
@@ -812,6 +812,7 @@ _verify_ciphertext_for_encryption_policy()
local crypt_util_args=""
local crypt_util_contents_args=""
local crypt_util_filename_args=""
+ local expected_identifier
shift 2
for opt; do
@@ -902,6 +903,18 @@ _verify_ciphertext_for_encryption_policy()
fi
local raw_key_hex=$(echo "$raw_key" | tr -d '\\x')
+ if (( policy_version > 1 )); then
+ echo "Verifying key identifier" >> $seqres.full
+ expected_identifier=$($here/src/fscrypt-crypt-util \
+ --dump-key-identifier "$raw_key_hex" \
+ $crypt_util_args)
+ if [ "$expected_identifier" != "$keyspec" ]; then
+ echo "KEY IDENTIFIER MISMATCH!"
+ echo " Expected: $expected_identifier"
+ echo " Actual: $keyspec"
+ fi
+ fi
+
echo
echo -e "Verifying ciphertext with parameters:"
echo -e "\tcontents_encryption_mode: $contents_encryption_mode"
--
2.35.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2022-03-13 1:06 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-03-13 1:05 [PATCH v2 0/5] xfstests: fscrypt test cleanups Eric Biggers
2022-03-13 1:05 ` [PATCH v2 1/5] fscrypt-crypt-util: use an explicit --direct-key option Eric Biggers
2022-03-13 1:05 ` [PATCH v2 2/5] fscrypt-crypt-util: refactor get_key_and_iv() Eric Biggers
2022-03-13 1:05 ` [PATCH v2 3/5] fscrypt-crypt-util: add support for dumping key identifier Eric Biggers
2022-03-13 1:05 ` [PATCH v2 4/5] common/encrypt: log full ciphertext verification params Eric Biggers
2022-03-13 1:05 ` [PATCH v2 5/5] common/encrypt: verify the key identifiers Eric Biggers
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).