Branch data Line data Source code
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 : 0 : 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 : 0 : err = crypto_shash_setkey(hmac_tfm, default_salt, HKDF_HASHLEN);
51 [ # # ]: 0 : if (err)
52 : : return err;
53 : :
54 : 0 : desc->tfm = hmac_tfm;
55 : 0 : err = crypto_shash_digest(desc, ikm, ikmlen, prk);
56 : : shash_desc_zero(desc);
57 : 0 : 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 : 0 : 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 : 0 : hmac_tfm = crypto_alloc_shash(HKDF_HMAC_ALG, 0, 0);
75 [ # # ]: 0 : if (IS_ERR(hmac_tfm)) {
76 : 0 : fscrypt_err(NULL, "Error allocating " HKDF_HMAC_ALG ": %ld",
77 : : PTR_ERR(hmac_tfm));
78 : 0 : return PTR_ERR(hmac_tfm);
79 : : }
80 : :
81 [ # # # # ]: 0 : if (WARN_ON(crypto_shash_digestsize(hmac_tfm) != sizeof(prk))) {
82 : : err = -EINVAL;
83 : : goto err_free_tfm;
84 : : }
85 : :
86 : 0 : err = hkdf_extract(hmac_tfm, master_key, master_key_size, prk);
87 [ # # ]: 0 : if (err)
88 : : goto err_free_tfm;
89 : :
90 : 0 : err = crypto_shash_setkey(hmac_tfm, prk, sizeof(prk));
91 [ # # ]: 0 : if (err)
92 : : goto err_free_tfm;
93 : :
94 : 0 : hkdf->hmac_tfm = hmac_tfm;
95 : 0 : goto out;
96 : :
97 : : err_free_tfm:
98 : : crypto_free_shash(hmac_tfm);
99 : : out:
100 : : memzero_explicit(prk, sizeof(prk));
101 : 0 : 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 : 0 : 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 : 0 : u8 counter = 1;
125 : : u8 tmp[HKDF_HASHLEN];
126 : :
127 [ # # # # ]: 0 : if (WARN_ON(okmlen > 255 * HKDF_HASHLEN))
128 : : return -EINVAL;
129 : :
130 : 0 : desc->tfm = hkdf->hmac_tfm;
131 : :
132 : 0 : memcpy(prefix, "fscrypt\0", 8);
133 : 0 : prefix[8] = context;
134 : :
135 [ # # ]: 0 : for (i = 0; i < okmlen; i += HKDF_HASHLEN) {
136 : :
137 : : err = crypto_shash_init(desc);
138 [ # # ]: 0 : if (err)
139 : : goto out;
140 : :
141 [ # # ]: 0 : if (prev) {
142 : 0 : err = crypto_shash_update(desc, prev, HKDF_HASHLEN);
143 [ # # ]: 0 : if (err)
144 : : goto out;
145 : : }
146 : :
147 : 0 : err = crypto_shash_update(desc, prefix, sizeof(prefix));
148 [ # # ]: 0 : if (err)
149 : : goto out;
150 : :
151 : 0 : err = crypto_shash_update(desc, info, infolen);
152 [ # # ]: 0 : if (err)
153 : : goto out;
154 : :
155 : : BUILD_BUG_ON(sizeof(counter) != 1);
156 [ # # ]: 0 : if (okmlen - i < HKDF_HASHLEN) {
157 : 0 : err = crypto_shash_finup(desc, &counter, 1, tmp);
158 [ # # ]: 0 : if (err)
159 : : goto out;
160 : 0 : memcpy(&okm[i], tmp, okmlen - i);
161 : : memzero_explicit(tmp, sizeof(tmp));
162 : : } else {
163 : 0 : err = crypto_shash_finup(desc, &counter, 1, &okm[i]);
164 [ # # ]: 0 : if (err)
165 : : goto out;
166 : : }
167 : 0 : counter++;
168 : 0 : prev = &okm[i];
169 : : }
170 : : err = 0;
171 : : out:
172 [ # # ]: 0 : if (unlikely(err))
173 : : memzero_explicit(okm, okmlen); /* so caller doesn't need to */
174 : : shash_desc_zero(desc);
175 : 0 : return err;
176 : : }
177 : :
178 : 0 : void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf)
179 : : {
180 : 0 : crypto_free_shash(hkdf->hmac_tfm);
181 : 0 : }
|