1
2
3
4
5
6
7
8
9
10
11
12#include <crypto/hash.h>
13#include <crypto/sha2.h>
14
15#include "fscrypt_private.h"
16
17
18
19
20
21
22
23#define HKDF_HMAC_ALG "hmac(sha512)"
24#define HKDF_HASHLEN SHA512_DIGEST_SIZE
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43static 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 int err;
48
49 err = crypto_shash_setkey(hmac_tfm, default_salt, HKDF_HASHLEN);
50 if (err)
51 return err;
52
53 return crypto_shash_tfm_digest(hmac_tfm, ikm, ikmlen, prk);
54}
55
56
57
58
59
60
61
62
63int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
64 unsigned int master_key_size)
65{
66 struct crypto_shash *hmac_tfm;
67 u8 prk[HKDF_HASHLEN];
68 int err;
69
70 hmac_tfm = crypto_alloc_shash(HKDF_HMAC_ALG, 0, 0);
71 if (IS_ERR(hmac_tfm)) {
72 fscrypt_err(NULL, "Error allocating " HKDF_HMAC_ALG ": %ld",
73 PTR_ERR(hmac_tfm));
74 return PTR_ERR(hmac_tfm);
75 }
76
77 if (WARN_ON(crypto_shash_digestsize(hmac_tfm) != sizeof(prk))) {
78 err = -EINVAL;
79 goto err_free_tfm;
80 }
81
82 err = hkdf_extract(hmac_tfm, master_key, master_key_size, prk);
83 if (err)
84 goto err_free_tfm;
85
86 err = crypto_shash_setkey(hmac_tfm, prk, sizeof(prk));
87 if (err)
88 goto err_free_tfm;
89
90 hkdf->hmac_tfm = hmac_tfm;
91 goto out;
92
93err_free_tfm:
94 crypto_free_shash(hmac_tfm);
95out:
96 memzero_explicit(prk, sizeof(prk));
97 return err;
98}
99
100
101
102
103
104
105
106
107
108
109
110
111int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,
112 const u8 *info, unsigned int infolen,
113 u8 *okm, unsigned int okmlen)
114{
115 SHASH_DESC_ON_STACK(desc, hkdf->hmac_tfm);
116 u8 prefix[9];
117 unsigned int i;
118 int err;
119 const u8 *prev = NULL;
120 u8 counter = 1;
121 u8 tmp[HKDF_HASHLEN];
122
123 if (WARN_ON(okmlen > 255 * HKDF_HASHLEN))
124 return -EINVAL;
125
126 desc->tfm = hkdf->hmac_tfm;
127
128 memcpy(prefix, "fscrypt\0", 8);
129 prefix[8] = context;
130
131 for (i = 0; i < okmlen; i += HKDF_HASHLEN) {
132
133 err = crypto_shash_init(desc);
134 if (err)
135 goto out;
136
137 if (prev) {
138 err = crypto_shash_update(desc, prev, HKDF_HASHLEN);
139 if (err)
140 goto out;
141 }
142
143 err = crypto_shash_update(desc, prefix, sizeof(prefix));
144 if (err)
145 goto out;
146
147 err = crypto_shash_update(desc, info, infolen);
148 if (err)
149 goto out;
150
151 BUILD_BUG_ON(sizeof(counter) != 1);
152 if (okmlen - i < HKDF_HASHLEN) {
153 err = crypto_shash_finup(desc, &counter, 1, tmp);
154 if (err)
155 goto out;
156 memcpy(&okm[i], tmp, okmlen - i);
157 memzero_explicit(tmp, sizeof(tmp));
158 } else {
159 err = crypto_shash_finup(desc, &counter, 1, &okm[i]);
160 if (err)
161 goto out;
162 }
163 counter++;
164 prev = &okm[i];
165 }
166 err = 0;
167out:
168 if (unlikely(err))
169 memzero_explicit(okm, okmlen);
170 shash_desc_zero(desc);
171 return err;
172}
173
174void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf)
175{
176 crypto_free_shash(hkdf->hmac_tfm);
177}
178