[PATCH 3/5] fscrypt: use HKDF library functions

Marco Baffo <[email protected]>
Newsgroups org.infradead.lists.linux-nvme,org.kernel.vger.linux-crypto,org.kernel.vger.linux-fscrypt,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Convert fscrypt to the common HKDF-SHA512 helpers without changing its
derived keys. The info bytes are processed in the same order as before.
An empty salt is equivalent to the previous 64-byte all-zero salt after
HMAC key padding.

Signed-off-by: Marco Baffo <[email protected]>
---
 fs/crypto/hkdf.c | 56 +++++++++++-------------------------------------
 1 file changed, 13 insertions(+), 43 deletions(-)

diff --git a/fs/crypto/hkdf.c b/fs/crypto/hkdf.c
index 706f56d0076e..7df7d466a3e4 100644
--- a/fs/crypto/hkdf.c
+++ b/fs/crypto/hkdf.c
@@ -1,8 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Implementation of HKDF ("HMAC-based Extract-and-Expand Key Derivation
- * Function"), aka RFC 5869.  See also the original paper (Krawczyk 2010):
- * "Cryptographic Extraction and Key Derivation: The HKDF Scheme".
+ * Key derivation using HKDF-SHA512.
  *
  * This is used to derive keys from the fscrypt master keys (or from the
  * "software secrets" which hardware derives from the fscrypt master keys, in
@@ -11,6 +9,8 @@
  * Copyright 2019 Google LLC
  */
 
+#include <crypto/hkdf.h>
+
 #include "fscrypt_private.h"
 
 /*
@@ -24,19 +24,11 @@
  * HKDF-SHA512 being much faster than HKDF-SHA256, as the longer digest size of
  * SHA-512 causes HKDF-Expand to only need to do one iteration rather than two.
  */
-#define HKDF_HASHLEN		SHA512_DIGEST_SIZE
 
 /*
- * HKDF consists of two steps:
- *
- * 1. HKDF-Extract: extract a pseudorandom key of length HKDF_HASHLEN bytes from
- *    the input keying material and optional salt.
- * 2. HKDF-Expand: expand the pseudorandom key into output keying material of
- *    any length, parameterized by an application-specific info string.
- *
  * HKDF-Extract can be skipped if the input is already a pseudorandom key of
- * length HKDF_HASHLEN bytes.  However, cipher modes other than AES-256-XTS take
- * shorter keys, and we don't want to force users of those modes to provide
+ * length SHA512_DIGEST_SIZE bytes.  However, cipher modes other than AES-256-XTS
+ * take shorter keys, and we don't want to force users of those modes to provide
  * unnecessarily long master keys.  Thus fscrypt still does HKDF-Extract.  No
  * salt is used, since fscrypt master keys should already be pseudorandom and
  * there's no way to persist a random salt per master key from kernel mode.
@@ -50,13 +42,7 @@
 void fscrypt_init_hkdf(struct hmac_sha512_key *hkdf, const u8 *master_key,
 		       unsigned int master_key_size)
 {
-	static const u8 default_salt[HKDF_HASHLEN];
-	u8 prk[HKDF_HASHLEN];
-
-	hmac_sha512_usingrawkey(default_salt, sizeof(default_salt),
-				master_key, master_key_size, prk);
-	hmac_sha512_preparekey(hkdf, prk, sizeof(prk));
-	memzero_explicit(prk, sizeof(prk));
+	hkdf_sha512_extract(hkdf, NULL, 0, master_key, master_key_size);
 }
 
 /*
@@ -73,28 +59,12 @@ void fscrypt_hkdf_expand(const struct hmac_sha512_key *hkdf, u8 context,
 			 const u8 *info, unsigned int infolen,
 			 u8 *okm, unsigned int okmlen)
 {
-	struct hmac_sha512_ctx ctx;
-	u8 counter = 1;
-	u8 tmp[HKDF_HASHLEN];
-
-	WARN_ON_ONCE(okmlen > 255 * HKDF_HASHLEN);
+	const struct hkdf_seg info_segs[] = {
+		{ .data = "fscrypt\0", .len = 8 },
+		{ .data = &context, .len = 1 },
+		{ .data = info, .len = infolen },
+	};
 
-	for (unsigned int i = 0; i < okmlen; i += HKDF_HASHLEN) {
-		hmac_sha512_init(&ctx, hkdf);
-		if (i != 0)
-			hmac_sha512_update(&ctx, &okm[i - HKDF_HASHLEN],
-					   HKDF_HASHLEN);
-		hmac_sha512_update(&ctx, "fscrypt\0", 8);
-		hmac_sha512_update(&ctx, &context, 1);
-		hmac_sha512_update(&ctx, info, infolen);
-		hmac_sha512_update(&ctx, &counter, 1);
-		if (okmlen - i < HKDF_HASHLEN) {
-			hmac_sha512_final(&ctx, tmp);
-			memcpy(&okm[i], tmp, okmlen - i);
-			memzero_explicit(tmp, sizeof(tmp));
-		} else {
-			hmac_sha512_final(&ctx, &okm[i]);
-		}
-		counter++;
-	}
+	hkdf_sha512_expand(hkdf, info_segs, ARRAY_SIZE(info_segs),
+			   okm, okmlen);
 }
-- 
2.43.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.