1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Cryptographic API. |
4 | * |
5 | * HMAC: Keyed-Hashing for Message Authentication (RFC2104). |
6 | * |
7 | * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> |
8 | * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> |
9 | * |
10 | * The HMAC implementation is derived from USAGI. |
11 | * Copyright (c) 2002 Kazunori Miyazawa <miyazawa@linux-ipv6.org> / USAGI |
12 | */ |
13 | |
14 | #include <crypto/hmac.h> |
15 | #include <crypto/internal/hash.h> |
16 | #include <crypto/scatterwalk.h> |
17 | #include <linux/err.h> |
18 | #include <linux/fips.h> |
19 | #include <linux/init.h> |
20 | #include <linux/kernel.h> |
21 | #include <linux/module.h> |
22 | #include <linux/scatterlist.h> |
23 | #include <linux/string.h> |
24 | |
25 | struct hmac_ctx { |
26 | struct crypto_shash *hash; |
27 | /* Contains 'u8 ipad[statesize];', then 'u8 opad[statesize];' */ |
28 | u8 pads[]; |
29 | }; |
30 | |
31 | static int hmac_setkey(struct crypto_shash *parent, |
32 | const u8 *inkey, unsigned int keylen) |
33 | { |
34 | int bs = crypto_shash_blocksize(tfm: parent); |
35 | int ds = crypto_shash_digestsize(tfm: parent); |
36 | int ss = crypto_shash_statesize(tfm: parent); |
37 | struct hmac_ctx *tctx = crypto_shash_ctx(tfm: parent); |
38 | struct crypto_shash *hash = tctx->hash; |
39 | u8 *ipad = &tctx->pads[0]; |
40 | u8 *opad = &tctx->pads[ss]; |
41 | SHASH_DESC_ON_STACK(shash, hash); |
42 | unsigned int i; |
43 | |
44 | if (fips_enabled && (keylen < 112 / 8)) |
45 | return -EINVAL; |
46 | |
47 | shash->tfm = hash; |
48 | |
49 | if (keylen > bs) { |
50 | int err; |
51 | |
52 | err = crypto_shash_digest(desc: shash, data: inkey, len: keylen, out: ipad); |
53 | if (err) |
54 | return err; |
55 | |
56 | keylen = ds; |
57 | } else |
58 | memcpy(ipad, inkey, keylen); |
59 | |
60 | memset(ipad + keylen, 0, bs - keylen); |
61 | memcpy(opad, ipad, bs); |
62 | |
63 | for (i = 0; i < bs; i++) { |
64 | ipad[i] ^= HMAC_IPAD_VALUE; |
65 | opad[i] ^= HMAC_OPAD_VALUE; |
66 | } |
67 | |
68 | return crypto_shash_init(desc: shash) ?: |
69 | crypto_shash_update(desc: shash, data: ipad, len: bs) ?: |
70 | crypto_shash_export(desc: shash, out: ipad) ?: |
71 | crypto_shash_init(desc: shash) ?: |
72 | crypto_shash_update(desc: shash, data: opad, len: bs) ?: |
73 | crypto_shash_export(desc: shash, out: opad); |
74 | } |
75 | |
76 | static int hmac_export(struct shash_desc *pdesc, void *out) |
77 | { |
78 | struct shash_desc *desc = shash_desc_ctx(desc: pdesc); |
79 | |
80 | return crypto_shash_export(desc, out); |
81 | } |
82 | |
83 | static int hmac_import(struct shash_desc *pdesc, const void *in) |
84 | { |
85 | struct shash_desc *desc = shash_desc_ctx(desc: pdesc); |
86 | const struct hmac_ctx *tctx = crypto_shash_ctx(tfm: pdesc->tfm); |
87 | |
88 | desc->tfm = tctx->hash; |
89 | |
90 | return crypto_shash_import(desc, in); |
91 | } |
92 | |
93 | static int hmac_init(struct shash_desc *pdesc) |
94 | { |
95 | const struct hmac_ctx *tctx = crypto_shash_ctx(tfm: pdesc->tfm); |
96 | |
97 | return hmac_import(pdesc, in: &tctx->pads[0]); |
98 | } |
99 | |
100 | static int hmac_update(struct shash_desc *pdesc, |
101 | const u8 *data, unsigned int nbytes) |
102 | { |
103 | struct shash_desc *desc = shash_desc_ctx(desc: pdesc); |
104 | |
105 | return crypto_shash_update(desc, data, len: nbytes); |
106 | } |
107 | |
108 | static int hmac_final(struct shash_desc *pdesc, u8 *out) |
109 | { |
110 | struct crypto_shash *parent = pdesc->tfm; |
111 | int ds = crypto_shash_digestsize(tfm: parent); |
112 | int ss = crypto_shash_statesize(tfm: parent); |
113 | const struct hmac_ctx *tctx = crypto_shash_ctx(tfm: parent); |
114 | const u8 *opad = &tctx->pads[ss]; |
115 | struct shash_desc *desc = shash_desc_ctx(desc: pdesc); |
116 | |
117 | return crypto_shash_final(desc, out) ?: |
118 | crypto_shash_import(desc, in: opad) ?: |
119 | crypto_shash_finup(desc, data: out, len: ds, out); |
120 | } |
121 | |
122 | static int hmac_finup(struct shash_desc *pdesc, const u8 *data, |
123 | unsigned int nbytes, u8 *out) |
124 | { |
125 | |
126 | struct crypto_shash *parent = pdesc->tfm; |
127 | int ds = crypto_shash_digestsize(tfm: parent); |
128 | int ss = crypto_shash_statesize(tfm: parent); |
129 | const struct hmac_ctx *tctx = crypto_shash_ctx(tfm: parent); |
130 | const u8 *opad = &tctx->pads[ss]; |
131 | struct shash_desc *desc = shash_desc_ctx(desc: pdesc); |
132 | |
133 | return crypto_shash_finup(desc, data, len: nbytes, out) ?: |
134 | crypto_shash_import(desc, in: opad) ?: |
135 | crypto_shash_finup(desc, data: out, len: ds, out); |
136 | } |
137 | |
138 | static int hmac_init_tfm(struct crypto_shash *parent) |
139 | { |
140 | struct crypto_shash *hash; |
141 | struct shash_instance *inst = shash_alg_instance(shash: parent); |
142 | struct crypto_shash_spawn *spawn = shash_instance_ctx(inst); |
143 | struct hmac_ctx *tctx = crypto_shash_ctx(tfm: parent); |
144 | |
145 | hash = crypto_spawn_shash(spawn); |
146 | if (IS_ERR(ptr: hash)) |
147 | return PTR_ERR(ptr: hash); |
148 | |
149 | parent->descsize = sizeof(struct shash_desc) + |
150 | crypto_shash_descsize(tfm: hash); |
151 | |
152 | tctx->hash = hash; |
153 | return 0; |
154 | } |
155 | |
156 | static int hmac_clone_tfm(struct crypto_shash *dst, struct crypto_shash *src) |
157 | { |
158 | struct hmac_ctx *sctx = crypto_shash_ctx(tfm: src); |
159 | struct hmac_ctx *dctx = crypto_shash_ctx(tfm: dst); |
160 | struct crypto_shash *hash; |
161 | |
162 | hash = crypto_clone_shash(tfm: sctx->hash); |
163 | if (IS_ERR(ptr: hash)) |
164 | return PTR_ERR(ptr: hash); |
165 | |
166 | dctx->hash = hash; |
167 | return 0; |
168 | } |
169 | |
170 | static void hmac_exit_tfm(struct crypto_shash *parent) |
171 | { |
172 | struct hmac_ctx *tctx = crypto_shash_ctx(tfm: parent); |
173 | |
174 | crypto_free_shash(tfm: tctx->hash); |
175 | } |
176 | |
177 | static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb) |
178 | { |
179 | struct shash_instance *inst; |
180 | struct crypto_shash_spawn *spawn; |
181 | struct crypto_alg *alg; |
182 | struct shash_alg *salg; |
183 | u32 mask; |
184 | int err; |
185 | int ds; |
186 | int ss; |
187 | |
188 | err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH, mask_ret: &mask); |
189 | if (err) |
190 | return err; |
191 | |
192 | inst = kzalloc(size: sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); |
193 | if (!inst) |
194 | return -ENOMEM; |
195 | spawn = shash_instance_ctx(inst); |
196 | |
197 | err = crypto_grab_shash(spawn, inst: shash_crypto_instance(inst), |
198 | name: crypto_attr_alg_name(rta: tb[1]), type: 0, mask); |
199 | if (err) |
200 | goto err_free_inst; |
201 | salg = crypto_spawn_shash_alg(spawn); |
202 | alg = &salg->base; |
203 | |
204 | /* The underlying hash algorithm must not require a key */ |
205 | err = -EINVAL; |
206 | if (crypto_shash_alg_needs_key(alg: salg)) |
207 | goto err_free_inst; |
208 | |
209 | ds = salg->digestsize; |
210 | ss = salg->statesize; |
211 | if (ds > alg->cra_blocksize || |
212 | ss < alg->cra_blocksize) |
213 | goto err_free_inst; |
214 | |
215 | err = crypto_inst_setname(inst: shash_crypto_instance(inst), name: tmpl->name, alg); |
216 | if (err) |
217 | goto err_free_inst; |
218 | |
219 | inst->alg.base.cra_priority = alg->cra_priority; |
220 | inst->alg.base.cra_blocksize = alg->cra_blocksize; |
221 | inst->alg.base.cra_ctxsize = sizeof(struct hmac_ctx) + (ss * 2); |
222 | |
223 | inst->alg.digestsize = ds; |
224 | inst->alg.statesize = ss; |
225 | inst->alg.init = hmac_init; |
226 | inst->alg.update = hmac_update; |
227 | inst->alg.final = hmac_final; |
228 | inst->alg.finup = hmac_finup; |
229 | inst->alg.export = hmac_export; |
230 | inst->alg.import = hmac_import; |
231 | inst->alg.setkey = hmac_setkey; |
232 | inst->alg.init_tfm = hmac_init_tfm; |
233 | inst->alg.clone_tfm = hmac_clone_tfm; |
234 | inst->alg.exit_tfm = hmac_exit_tfm; |
235 | |
236 | inst->free = shash_free_singlespawn_instance; |
237 | |
238 | err = shash_register_instance(tmpl, inst); |
239 | if (err) { |
240 | err_free_inst: |
241 | shash_free_singlespawn_instance(inst); |
242 | } |
243 | return err; |
244 | } |
245 | |
246 | static struct crypto_template hmac_tmpl = { |
247 | .name = "hmac" , |
248 | .create = hmac_create, |
249 | .module = THIS_MODULE, |
250 | }; |
251 | |
252 | static int __init hmac_module_init(void) |
253 | { |
254 | return crypto_register_template(tmpl: &hmac_tmpl); |
255 | } |
256 | |
257 | static void __exit hmac_module_exit(void) |
258 | { |
259 | crypto_unregister_template(tmpl: &hmac_tmpl); |
260 | } |
261 | |
262 | subsys_initcall(hmac_module_init); |
263 | module_exit(hmac_module_exit); |
264 | |
265 | MODULE_LICENSE("GPL" ); |
266 | MODULE_DESCRIPTION("HMAC hash algorithm" ); |
267 | MODULE_ALIAS_CRYPTO("hmac" ); |
268 | |