linux-fscrypt.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eric Biggers <ebiggers@kernel.org>
To: fstests@vger.kernel.org
Cc: linux-fscrypt@vger.kernel.org
Subject: [PATCH v2 2/5] fscrypt-crypt-util: refactor get_key_and_iv()
Date: Sat, 12 Mar 2022 17:05:56 -0800	[thread overview]
Message-ID: <20220313010559.545995-3-ebiggers@kernel.org> (raw)
In-Reply-To: <20220313010559.545995-1-ebiggers@kernel.org>

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


  parent reply	other threads:[~2022-03-13  1:06 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

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=20220313010559.545995-3-ebiggers@kernel.org \
    --to=ebiggers@kernel.org \
    --cc=fstests@vger.kernel.org \
    --cc=linux-fscrypt@vger.kernel.org \
    /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;
as well as URLs for NNTP newsgroup(s).