Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fscrypt: add an HKDF-SHA512 implementation

Add an implementation of HKDF (RFC 5869) to fscrypt, for the purpose of
deriving additional key material from the fscrypt master keys for v2
encryption policies. HKDF is a key derivation function built on top of
HMAC. We choose SHA-512 for the underlying unkeyed hash, and use an
"hmac(sha512)" transform allocated from the crypto API.

We'll be using this to replace the AES-ECB based KDF currently used to
derive the per-file encryption keys. While the AES-ECB based KDF is
believed to meet the original security requirements, it is nonstandard
and has problems that don't exist in modern KDFs such as HKDF:

1. It's reversible. Given a derived key and nonce, an attacker can
easily compute the master key. This is okay if the master key and
derived keys are equally hard to compromise, but now we'd like to be
more robust against threats such as a derived key being compromised
through a timing attack, or a derived key for an in-use file being
compromised after the master key has already been removed.

2. It doesn't evenly distribute the entropy from the master key; each 16
input bytes only affects the corresponding 16 output bytes.

3. It isn't easily extensible to deriving other values or keys, such as
a public hash for securely identifying the key, or per-mode keys.
Per-mode keys will be immediately useful for Adiantum encryption, for
which fscrypt currently uses the master key directly, introducing
unnecessary usage constraints. Per-mode keys will also be useful for
hardware inline encryption, which is currently being worked on.

HKDF solves all the above problems.

Reviewed-by: Paul Crowley <paulcrowley@google.com>
Reviewed-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Eric Biggers <ebiggers@google.com>

+199
+2
fs/crypto/Kconfig
··· 7 7 select CRYPTO_ECB 8 8 select CRYPTO_XTS 9 9 select CRYPTO_CTS 10 + select CRYPTO_SHA512 11 + select CRYPTO_HMAC 10 12 select KEYS 11 13 help 12 14 Enable encryption of files and directories. This
+1
fs/crypto/Makefile
··· 3 3 4 4 fscrypto-y := crypto.o \ 5 5 fname.o \ 6 + hkdf.o \ 6 7 hooks.o \ 7 8 keyring.o \ 8 9 keysetup.o \
+15
fs/crypto/fscrypt_private.h
··· 172 172 u32 orig_len, u32 max_len, 173 173 u32 *encrypted_len_ret); 174 174 175 + /* hkdf.c */ 176 + 177 + struct fscrypt_hkdf { 178 + struct crypto_shash *hmac_tfm; 179 + }; 180 + 181 + extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key, 182 + unsigned int master_key_size); 183 + 184 + extern int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context, 185 + const u8 *info, unsigned int infolen, 186 + u8 *okm, unsigned int okmlen); 187 + 188 + extern void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf); 189 + 175 190 /* keyring.c */ 176 191 177 192 /*
+181
fs/crypto/hkdf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Implementation of HKDF ("HMAC-based Extract-and-Expand Key Derivation 4 + * Function"), aka RFC 5869. See also the original paper (Krawczyk 2010): 5 + * "Cryptographic Extraction and Key Derivation: The HKDF Scheme". 6 + * 7 + * This is used to derive keys from the fscrypt master keys. 8 + * 9 + * Copyright 2019 Google LLC 10 + */ 11 + 12 + #include <crypto/hash.h> 13 + #include <crypto/sha.h> 14 + 15 + #include "fscrypt_private.h" 16 + 17 + /* 18 + * HKDF supports any unkeyed cryptographic hash algorithm, but fscrypt uses 19 + * SHA-512 because it is reasonably secure and efficient; and since it produces 20 + * a 64-byte digest, deriving an AES-256-XTS key preserves all 64 bytes of 21 + * entropy from the master key and requires only one iteration of HKDF-Expand. 22 + */ 23 + #define HKDF_HMAC_ALG "hmac(sha512)" 24 + #define HKDF_HASHLEN SHA512_DIGEST_SIZE 25 + 26 + /* 27 + * HKDF consists of two steps: 28 + * 29 + * 1. HKDF-Extract: extract a pseudorandom key of length HKDF_HASHLEN bytes from 30 + * the input keying material and optional salt. 31 + * 2. HKDF-Expand: expand the pseudorandom key into output keying material of 32 + * any length, parameterized by an application-specific info string. 33 + * 34 + * HKDF-Extract can be skipped if the input is already a pseudorandom key of 35 + * length HKDF_HASHLEN bytes. However, cipher modes other than AES-256-XTS take 36 + * shorter keys, and we don't want to force users of those modes to provide 37 + * unnecessarily long master keys. Thus fscrypt still does HKDF-Extract. No 38 + * salt is used, since fscrypt master keys should already be pseudorandom and 39 + * there's no way to persist a random salt per master key from kernel mode. 40 + */ 41 + 42 + /* HKDF-Extract (RFC 5869 section 2.2), unsalted */ 43 + static int hkdf_extract(struct crypto_shash *hmac_tfm, const u8 *ikm, 44 + unsigned int ikmlen, u8 prk[HKDF_HASHLEN]) 45 + { 46 + static const u8 default_salt[HKDF_HASHLEN]; 47 + SHASH_DESC_ON_STACK(desc, hmac_tfm); 48 + int err; 49 + 50 + err = crypto_shash_setkey(hmac_tfm, default_salt, HKDF_HASHLEN); 51 + if (err) 52 + return err; 53 + 54 + desc->tfm = hmac_tfm; 55 + err = crypto_shash_digest(desc, ikm, ikmlen, prk); 56 + shash_desc_zero(desc); 57 + return err; 58 + } 59 + 60 + /* 61 + * Compute HKDF-Extract using the given master key as the input keying material, 62 + * and prepare an HMAC transform object keyed by the resulting pseudorandom key. 63 + * 64 + * Afterwards, the keyed HMAC transform object can be used for HKDF-Expand many 65 + * times without having to recompute HKDF-Extract each time. 66 + */ 67 + int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key, 68 + unsigned int master_key_size) 69 + { 70 + struct crypto_shash *hmac_tfm; 71 + u8 prk[HKDF_HASHLEN]; 72 + int err; 73 + 74 + hmac_tfm = crypto_alloc_shash(HKDF_HMAC_ALG, 0, 0); 75 + if (IS_ERR(hmac_tfm)) { 76 + fscrypt_err(NULL, "Error allocating " HKDF_HMAC_ALG ": %ld", 77 + PTR_ERR(hmac_tfm)); 78 + return PTR_ERR(hmac_tfm); 79 + } 80 + 81 + if (WARN_ON(crypto_shash_digestsize(hmac_tfm) != sizeof(prk))) { 82 + err = -EINVAL; 83 + goto err_free_tfm; 84 + } 85 + 86 + err = hkdf_extract(hmac_tfm, master_key, master_key_size, prk); 87 + if (err) 88 + goto err_free_tfm; 89 + 90 + err = crypto_shash_setkey(hmac_tfm, prk, sizeof(prk)); 91 + if (err) 92 + goto err_free_tfm; 93 + 94 + hkdf->hmac_tfm = hmac_tfm; 95 + goto out; 96 + 97 + err_free_tfm: 98 + crypto_free_shash(hmac_tfm); 99 + out: 100 + memzero_explicit(prk, sizeof(prk)); 101 + return err; 102 + } 103 + 104 + /* 105 + * HKDF-Expand (RFC 5869 section 2.3). This expands the pseudorandom key, which 106 + * was already keyed into 'hkdf->hmac_tfm' by fscrypt_init_hkdf(), into 'okmlen' 107 + * bytes of output keying material parameterized by the application-specific 108 + * 'info' of length 'infolen' bytes, prefixed by "fscrypt\0" and the 'context' 109 + * byte. This is thread-safe and may be called by multiple threads in parallel. 110 + * 111 + * ('context' isn't part of the HKDF specification; it's just a prefix fscrypt 112 + * adds to its application-specific info strings to guarantee that it doesn't 113 + * accidentally repeat an info string when using HKDF for different purposes.) 114 + */ 115 + int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context, 116 + const u8 *info, unsigned int infolen, 117 + u8 *okm, unsigned int okmlen) 118 + { 119 + SHASH_DESC_ON_STACK(desc, hkdf->hmac_tfm); 120 + u8 prefix[9]; 121 + unsigned int i; 122 + int err; 123 + const u8 *prev = NULL; 124 + u8 counter = 1; 125 + u8 tmp[HKDF_HASHLEN]; 126 + 127 + if (WARN_ON(okmlen > 255 * HKDF_HASHLEN)) 128 + return -EINVAL; 129 + 130 + desc->tfm = hkdf->hmac_tfm; 131 + 132 + memcpy(prefix, "fscrypt\0", 8); 133 + prefix[8] = context; 134 + 135 + for (i = 0; i < okmlen; i += HKDF_HASHLEN) { 136 + 137 + err = crypto_shash_init(desc); 138 + if (err) 139 + goto out; 140 + 141 + if (prev) { 142 + err = crypto_shash_update(desc, prev, HKDF_HASHLEN); 143 + if (err) 144 + goto out; 145 + } 146 + 147 + err = crypto_shash_update(desc, prefix, sizeof(prefix)); 148 + if (err) 149 + goto out; 150 + 151 + err = crypto_shash_update(desc, info, infolen); 152 + if (err) 153 + goto out; 154 + 155 + BUILD_BUG_ON(sizeof(counter) != 1); 156 + if (okmlen - i < HKDF_HASHLEN) { 157 + err = crypto_shash_finup(desc, &counter, 1, tmp); 158 + if (err) 159 + goto out; 160 + memcpy(&okm[i], tmp, okmlen - i); 161 + memzero_explicit(tmp, sizeof(tmp)); 162 + } else { 163 + err = crypto_shash_finup(desc, &counter, 1, &okm[i]); 164 + if (err) 165 + goto out; 166 + } 167 + counter++; 168 + prev = &okm[i]; 169 + } 170 + err = 0; 171 + out: 172 + if (unlikely(err)) 173 + memzero_explicit(okm, okmlen); /* so caller doesn't need to */ 174 + shash_desc_zero(desc); 175 + return err; 176 + } 177 + 178 + void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf) 179 + { 180 + crypto_free_shash(hkdf->hmac_tfm); 181 + }