All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Biggers <ebiggers@kernel.org>
To: fstests@vger.kernel.org
Cc: linux-fscrypt@vger.kernel.org, Satya Tangirala <satyat@google.com>
Subject: [PATCH v2 1/5] fscrypt-crypt-util: create key_and_iv_params structure
Date: Mon,  2 Dec 2019 15:01:51 -0800	[thread overview]
Message-ID: <20191202230155.99071-2-ebiggers@kernel.org> (raw)
In-Reply-To: <20191202230155.99071-1-ebiggers@kernel.org>

From: Eric Biggers <ebiggers@google.com>

In preparation for adding 3 more input parameters to get_key_and_iv(),
create a structure to hold the input parameters so that the code doesn't
get too unwieldy.

Signed-off-by: Eric Biggers <ebiggers@google.com>
---
 src/fscrypt-crypt-util.c | 82 +++++++++++++++++++++-------------------
 1 file changed, 44 insertions(+), 38 deletions(-)

diff --git a/src/fscrypt-crypt-util.c b/src/fscrypt-crypt-util.c
index f5fd8386..bafc15e0 100644
--- a/src/fscrypt-crypt-util.c
+++ b/src/fscrypt-crypt-util.c
@@ -1694,66 +1694,75 @@ static u8 parse_mode_number(const char *arg)
 	return num;
 }
 
+struct key_and_iv_params {
+	u8 master_key[MAX_KEY_SIZE];
+	int master_key_size;
+	enum kdf_algorithm kdf;
+	u8 mode_num;
+	u8 file_nonce[FILE_NONCE_SIZE];
+	bool file_nonce_specified;
+};
+
 /*
  * 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 u8 *master_key, size_t master_key_size,
-			   enum kdf_algorithm kdf,
-			   u8 mode_num, const u8 nonce[FILE_NONCE_SIZE],
+static void get_key_and_iv(const struct key_and_iv_params *params,
 			   u8 *real_key, size_t real_key_size,
 			   struct fscrypt_iv *iv)
 {
-	bool nonce_in_iv = false;
+	bool file_nonce_in_iv = false;
 	struct aes_key aes_key;
 	u8 info[8 + 1 + FILE_NONCE_SIZE] = "fscrypt";
 	size_t infolen = 8;
 	size_t i;
 
-	ASSERT(real_key_size <= master_key_size);
+	ASSERT(real_key_size <= params->master_key_size);
 
 	memset(iv, 0, sizeof(*iv));
 
-	switch (kdf) {
+	switch (params->kdf) {
 	case KDF_NONE:
-		if (mode_num != 0)
+		if (params->mode_num != 0)
 			die("--mode-num isn't supported with --kdf=none");
-		memcpy(real_key, master_key, real_key_size);
-		nonce_in_iv = true;
+		memcpy(real_key, params->master_key, real_key_size);
+		file_nonce_in_iv = true;
 		break;
 	case KDF_AES_128_ECB:
-		if (nonce == NULL)
+		if (!params->file_nonce_specified)
 			die("--file-nonce is required with --kdf=AES-128-ECB");
-		if (mode_num != 0)
+		if (params->mode_num != 0)
 			die("--mode-num isn't supported with --kdf=AES-128-ECB");
 		STATIC_ASSERT(FILE_NONCE_SIZE == AES_128_KEY_SIZE);
 		ASSERT(real_key_size % AES_BLOCK_SIZE == 0);
-		aes_setkey(&aes_key, nonce, AES_128_KEY_SIZE);
+		aes_setkey(&aes_key, params->file_nonce, AES_128_KEY_SIZE);
 		for (i = 0; i < real_key_size; i += AES_BLOCK_SIZE)
-			aes_encrypt(&aes_key, &master_key[i], &real_key[i]);
+			aes_encrypt(&aes_key, &params->master_key[i],
+				    &real_key[i]);
 		break;
 	case KDF_HKDF_SHA512:
-		if (mode_num != 0) {
+		if (params->mode_num != 0) {
 			info[infolen++] = 3; /* HKDF_CONTEXT_PER_MODE_KEY */
-			info[infolen++] = mode_num;
-			nonce_in_iv = true;
-		} else if (nonce != NULL) {
+			info[infolen++] = params->mode_num;
+			file_nonce_in_iv = true;
+		} else if (params->file_nonce_specified) {
 			info[infolen++] = 2; /* HKDF_CONTEXT_PER_FILE_KEY */
-			memcpy(&info[infolen], nonce, FILE_NONCE_SIZE);
+			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");
 		}
-		hkdf_sha512(master_key, master_key_size, NULL, 0,
-			    info, infolen, real_key, real_key_size);
+		hkdf_sha512(params->master_key, params->master_key_size,
+			    NULL, 0, info, infolen, real_key, real_key_size);
 		break;
 	default:
 		ASSERT(0);
 	}
 
-	if (nonce_in_iv && nonce != NULL)
-		memcpy(&iv->bytes[8], nonce, FILE_NONCE_SIZE);
+	if (file_nonce_in_iv && params->file_nonce_specified)
+		memcpy(&iv->bytes[8], params->file_nonce, FILE_NONCE_SIZE);
 }
 
 enum {
@@ -1781,19 +1790,16 @@ int main(int argc, char *argv[])
 {
 	size_t block_size = 4096;
 	bool decrypting = false;
-	u8 _file_nonce[FILE_NONCE_SIZE];
-	u8 *file_nonce = NULL;
-	enum kdf_algorithm kdf = KDF_NONE;
-	u8 mode_num = 0;
+	struct key_and_iv_params params;
 	size_t padding = 0;
 	const struct fscrypt_cipher *cipher;
-	u8 master_key[MAX_KEY_SIZE];
-	int master_key_size;
 	u8 real_key[MAX_KEY_SIZE];
 	struct fscrypt_iv iv;
 	char *tmp;
 	int c;
 
+	memset(&params, 0, sizeof(params));
+
 	aes_init();
 
 #ifdef ENABLE_ALG_TESTS
@@ -1816,19 +1822,19 @@ int main(int argc, char *argv[])
 			decrypting = true;
 			break;
 		case OPT_FILE_NONCE:
-			if (hex2bin(optarg, _file_nonce, FILE_NONCE_SIZE) !=
-			    FILE_NONCE_SIZE)
+			if (hex2bin(optarg, params.file_nonce, FILE_NONCE_SIZE)
+			    != FILE_NONCE_SIZE)
 				die("Invalid file nonce: %s", optarg);
-			file_nonce = _file_nonce;
+			params.file_nonce_specified = true;
 			break;
 		case OPT_HELP:
 			usage(stdout);
 			return 0;
 		case OPT_KDF:
-			kdf = parse_kdf_algorithm(optarg);
+			params.kdf = parse_kdf_algorithm(optarg);
 			break;
 		case OPT_MODE_NUM:
-			mode_num = parse_mode_number(optarg);
+			params.mode_num = parse_mode_number(optarg);
 			break;
 		case OPT_PADDING:
 			padding = strtoul(optarg, &tmp, 10);
@@ -1857,14 +1863,14 @@ int main(int argc, char *argv[])
 		die("Block size of %zu bytes is too small for cipher %s",
 		    block_size, cipher->name);
 
-	master_key_size = hex2bin(argv[1], master_key, MAX_KEY_SIZE);
-	if (master_key_size < 0)
+	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]);
-	if (master_key_size < cipher->keysize)
+	if (params.master_key_size < cipher->keysize)
 		die("Master key is too short for cipher %s", cipher->name);
 
-	get_key_and_iv(master_key, master_key_size, kdf, mode_num, file_nonce,
-		       real_key, cipher->keysize, &iv);
+	get_key_and_iv(&params, real_key, cipher->keysize, &iv);
 
 	crypt_loop(cipher, real_key, &iv, decrypting, block_size, padding);
 	return 0;
-- 
2.24.0.393.g34dc348eaf-goog


  reply	other threads:[~2019-12-02 23:02 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-02 23:01 [PATCH v2 0/5] xfstests: verify ciphertext of IV_INO_LBLK_64 encryption policies Eric Biggers
2019-12-02 23:01 ` Eric Biggers [this message]
2019-12-02 23:01 ` [PATCH v2 2/5] fscrypt-crypt-util: add HKDF context constants Eric Biggers
2019-12-02 23:01 ` [PATCH v2 3/5] common/encrypt: create named variables for UAPI constants Eric Biggers
2019-12-02 23:01 ` [PATCH v2 4/5] common/encrypt: support verifying ciphertext of IV_INO_LBLK_64 policies Eric Biggers
2019-12-02 23:01 ` [PATCH v2 5/5] generic: verify ciphertext of IV_INO_LBLK_64 encryption policies Eric Biggers
2019-12-09 18:18 ` [PATCH v2 0/5] xfstests: " Eric Biggers
2020-01-03 16:46   ` Eric Biggers
2020-01-06  2:55     ` Eryu Guan

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=20191202230155.99071-2-ebiggers@kernel.org \
    --to=ebiggers@kernel.org \
    --cc=fstests@vger.kernel.org \
    --cc=linux-fscrypt@vger.kernel.org \
    --cc=satyat@google.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.