12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Cryptographic API.
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * HMAC: Keyed-Hashing for Message Authentication (RFC2104).
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
80796ae06SHerbert Xu * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
91da177e4SLinus Torvalds *
101da177e4SLinus Torvalds * The HMAC implementation is derived from USAGI.
111da177e4SLinus Torvalds * Copyright (c) 2002 Kazunori Miyazawa <miyazawa@linux-ipv6.org> / USAGI
121da177e4SLinus Torvalds */
130796ae06SHerbert Xu
1403d7db56SCorentin LABBE #include <crypto/hmac.h>
155f7082edSHerbert Xu #include <crypto/internal/hash.h>
16b2ab4a57SHerbert Xu #include <crypto/scatterwalk.h>
170796ae06SHerbert Xu #include <linux/err.h>
1837f36e57SStephan Müller #include <linux/fips.h>
190796ae06SHerbert Xu #include <linux/init.h>
200796ae06SHerbert Xu #include <linux/kernel.h>
210796ae06SHerbert Xu #include <linux/module.h>
22378f058cSDavid Hardeman #include <linux/scatterlist.h>
230796ae06SHerbert Xu #include <linux/string.h>
240796ae06SHerbert Xu
250796ae06SHerbert Xu struct hmac_ctx {
260b767b4dSHerbert Xu struct crypto_shash *hash;
270796ae06SHerbert Xu };
281da177e4SLinus Torvalds
align_ptr(void * p,unsigned int align)290796ae06SHerbert Xu static inline void *align_ptr(void *p, unsigned int align)
300796ae06SHerbert Xu {
310796ae06SHerbert Xu return (void *)ALIGN((unsigned long)p, align);
320796ae06SHerbert Xu }
330796ae06SHerbert Xu
hmac_ctx(struct crypto_shash * tfm)348bd1209cSHerbert Xu static inline struct hmac_ctx *hmac_ctx(struct crypto_shash *tfm)
350796ae06SHerbert Xu {
368bd1209cSHerbert Xu return align_ptr(crypto_shash_ctx_aligned(tfm) +
370b767b4dSHerbert Xu crypto_shash_statesize(tfm) * 2,
388bd1209cSHerbert Xu crypto_tfm_ctx_alignment());
390796ae06SHerbert Xu }
400796ae06SHerbert Xu
hmac_setkey(struct crypto_shash * parent,const u8 * inkey,unsigned int keylen)418bd1209cSHerbert Xu static int hmac_setkey(struct crypto_shash *parent,
420796ae06SHerbert Xu const u8 *inkey, unsigned int keylen)
430796ae06SHerbert Xu {
448bd1209cSHerbert Xu int bs = crypto_shash_blocksize(parent);
458bd1209cSHerbert Xu int ds = crypto_shash_digestsize(parent);
460b767b4dSHerbert Xu int ss = crypto_shash_statesize(parent);
478bd1209cSHerbert Xu char *ipad = crypto_shash_ctx_aligned(parent);
480b767b4dSHerbert Xu char *opad = ipad + ss;
490b767b4dSHerbert Xu struct hmac_ctx *ctx = align_ptr(opad + ss,
508bd1209cSHerbert Xu crypto_tfm_ctx_alignment());
510b767b4dSHerbert Xu struct crypto_shash *hash = ctx->hash;
52ffb32e97SJan-Simon Möller SHASH_DESC_ON_STACK(shash, hash);
530796ae06SHerbert Xu unsigned int i;
540796ae06SHerbert Xu
5537f36e57SStephan Müller if (fips_enabled && (keylen < 112 / 8))
5637f36e57SStephan Müller return -EINVAL;
5737f36e57SStephan Müller
58ffb32e97SJan-Simon Möller shash->tfm = hash;
590b767b4dSHerbert Xu
600796ae06SHerbert Xu if (keylen > bs) {
610796ae06SHerbert Xu int err;
620796ae06SHerbert Xu
63ffb32e97SJan-Simon Möller err = crypto_shash_digest(shash, inkey, keylen, ipad);
640796ae06SHerbert Xu if (err)
650796ae06SHerbert Xu return err;
660796ae06SHerbert Xu
670796ae06SHerbert Xu keylen = ds;
680b767b4dSHerbert Xu } else
690796ae06SHerbert Xu memcpy(ipad, inkey, keylen);
700b767b4dSHerbert Xu
710796ae06SHerbert Xu memset(ipad + keylen, 0, bs - keylen);
720796ae06SHerbert Xu memcpy(opad, ipad, bs);
730796ae06SHerbert Xu
740796ae06SHerbert Xu for (i = 0; i < bs; i++) {
7503d7db56SCorentin LABBE ipad[i] ^= HMAC_IPAD_VALUE;
7603d7db56SCorentin LABBE opad[i] ^= HMAC_OPAD_VALUE;
770796ae06SHerbert Xu }
780796ae06SHerbert Xu
79ffb32e97SJan-Simon Möller return crypto_shash_init(shash) ?:
80ffb32e97SJan-Simon Möller crypto_shash_update(shash, ipad, bs) ?:
81ffb32e97SJan-Simon Möller crypto_shash_export(shash, ipad) ?:
82ffb32e97SJan-Simon Möller crypto_shash_init(shash) ?:
83ffb32e97SJan-Simon Möller crypto_shash_update(shash, opad, bs) ?:
84ffb32e97SJan-Simon Möller crypto_shash_export(shash, opad);
850b767b4dSHerbert Xu }
860b767b4dSHerbert Xu
hmac_export(struct shash_desc * pdesc,void * out)870b767b4dSHerbert Xu static int hmac_export(struct shash_desc *pdesc, void *out)
880b767b4dSHerbert Xu {
890b767b4dSHerbert Xu struct shash_desc *desc = shash_desc_ctx(pdesc);
900b767b4dSHerbert Xu
910b767b4dSHerbert Xu return crypto_shash_export(desc, out);
920b767b4dSHerbert Xu }
930b767b4dSHerbert Xu
hmac_import(struct shash_desc * pdesc,const void * in)940b767b4dSHerbert Xu static int hmac_import(struct shash_desc *pdesc, const void *in)
950b767b4dSHerbert Xu {
960b767b4dSHerbert Xu struct shash_desc *desc = shash_desc_ctx(pdesc);
970b767b4dSHerbert Xu struct hmac_ctx *ctx = hmac_ctx(pdesc->tfm);
980b767b4dSHerbert Xu
990b767b4dSHerbert Xu desc->tfm = ctx->hash;
1000b767b4dSHerbert Xu
1010b767b4dSHerbert Xu return crypto_shash_import(desc, in);
1020796ae06SHerbert Xu }
1030796ae06SHerbert Xu
hmac_init(struct shash_desc * pdesc)1048bd1209cSHerbert Xu static int hmac_init(struct shash_desc *pdesc)
1050796ae06SHerbert Xu {
1060b767b4dSHerbert Xu return hmac_import(pdesc, crypto_shash_ctx_aligned(pdesc->tfm));
1070796ae06SHerbert Xu }
1080796ae06SHerbert Xu
hmac_update(struct shash_desc * pdesc,const u8 * data,unsigned int nbytes)1098bd1209cSHerbert Xu static int hmac_update(struct shash_desc *pdesc,
1108bd1209cSHerbert Xu const u8 *data, unsigned int nbytes)
1110796ae06SHerbert Xu {
1128bd1209cSHerbert Xu struct shash_desc *desc = shash_desc_ctx(pdesc);
1130796ae06SHerbert Xu
1148bd1209cSHerbert Xu return crypto_shash_update(desc, data, nbytes);
1150796ae06SHerbert Xu }
1160796ae06SHerbert Xu
hmac_final(struct shash_desc * pdesc,u8 * out)1178bd1209cSHerbert Xu static int hmac_final(struct shash_desc *pdesc, u8 *out)
1180796ae06SHerbert Xu {
1198bd1209cSHerbert Xu struct crypto_shash *parent = pdesc->tfm;
1208bd1209cSHerbert Xu int ds = crypto_shash_digestsize(parent);
1210b767b4dSHerbert Xu int ss = crypto_shash_statesize(parent);
1220b767b4dSHerbert Xu char *opad = crypto_shash_ctx_aligned(parent) + ss;
1238bd1209cSHerbert Xu struct shash_desc *desc = shash_desc_ctx(pdesc);
1240796ae06SHerbert Xu
1250b767b4dSHerbert Xu return crypto_shash_final(desc, out) ?:
1260b767b4dSHerbert Xu crypto_shash_import(desc, opad) ?:
1270b767b4dSHerbert Xu crypto_shash_finup(desc, out, ds, out);
1280796ae06SHerbert Xu }
1290796ae06SHerbert Xu
hmac_finup(struct shash_desc * pdesc,const u8 * data,unsigned int nbytes,u8 * out)1308bd1209cSHerbert Xu static int hmac_finup(struct shash_desc *pdesc, const u8 *data,
1310796ae06SHerbert Xu unsigned int nbytes, u8 *out)
1320796ae06SHerbert Xu {
1338bd1209cSHerbert Xu
1348bd1209cSHerbert Xu struct crypto_shash *parent = pdesc->tfm;
1358bd1209cSHerbert Xu int ds = crypto_shash_digestsize(parent);
1360b767b4dSHerbert Xu int ss = crypto_shash_statesize(parent);
1370b767b4dSHerbert Xu char *opad = crypto_shash_ctx_aligned(parent) + ss;
1388bd1209cSHerbert Xu struct shash_desc *desc = shash_desc_ctx(pdesc);
1390796ae06SHerbert Xu
1400b767b4dSHerbert Xu return crypto_shash_finup(desc, data, nbytes, out) ?:
1410b767b4dSHerbert Xu crypto_shash_import(desc, opad) ?:
1420b767b4dSHerbert Xu crypto_shash_finup(desc, out, ds, out);
1430796ae06SHerbert Xu }
1440796ae06SHerbert Xu
hmac_init_tfm(struct crypto_shash * parent)145d9e1670bSHerbert Xu static int hmac_init_tfm(struct crypto_shash *parent)
1460796ae06SHerbert Xu {
1478bd1209cSHerbert Xu struct crypto_shash *hash;
148d9e1670bSHerbert Xu struct shash_instance *inst = shash_alg_instance(parent);
149d9e1670bSHerbert Xu struct crypto_shash_spawn *spawn = shash_instance_ctx(inst);
1508bd1209cSHerbert Xu struct hmac_ctx *ctx = hmac_ctx(parent);
1510796ae06SHerbert Xu
1528bd1209cSHerbert Xu hash = crypto_spawn_shash(spawn);
1532e306ee0SHerbert Xu if (IS_ERR(hash))
1542e306ee0SHerbert Xu return PTR_ERR(hash);
1550796ae06SHerbert Xu
1568bd1209cSHerbert Xu parent->descsize = sizeof(struct shash_desc) +
1578bd1209cSHerbert Xu crypto_shash_descsize(hash);
1588bd1209cSHerbert Xu
1590b767b4dSHerbert Xu ctx->hash = hash;
1600796ae06SHerbert Xu return 0;
1610796ae06SHerbert Xu }
1620796ae06SHerbert Xu
hmac_clone_tfm(struct crypto_shash * dst,struct crypto_shash * src)163*8538e60dSHerbert Xu static int hmac_clone_tfm(struct crypto_shash *dst, struct crypto_shash *src)
164*8538e60dSHerbert Xu {
165*8538e60dSHerbert Xu struct hmac_ctx *sctx = hmac_ctx(src);
166*8538e60dSHerbert Xu struct hmac_ctx *dctx = hmac_ctx(dst);
167*8538e60dSHerbert Xu struct crypto_shash *hash;
168*8538e60dSHerbert Xu
169*8538e60dSHerbert Xu hash = crypto_clone_shash(sctx->hash);
170*8538e60dSHerbert Xu if (IS_ERR(hash))
171*8538e60dSHerbert Xu return PTR_ERR(hash);
172*8538e60dSHerbert Xu
173*8538e60dSHerbert Xu dctx->hash = hash;
174*8538e60dSHerbert Xu return 0;
175*8538e60dSHerbert Xu }
176*8538e60dSHerbert Xu
hmac_exit_tfm(struct crypto_shash * parent)177d9e1670bSHerbert Xu static void hmac_exit_tfm(struct crypto_shash *parent)
1780796ae06SHerbert Xu {
179d9e1670bSHerbert Xu struct hmac_ctx *ctx = hmac_ctx(parent);
1800b767b4dSHerbert Xu
1810796ae06SHerbert Xu crypto_free_shash(ctx->hash);
1820796ae06SHerbert Xu }
1838bd1209cSHerbert Xu
hmac_create(struct crypto_template * tmpl,struct rtattr ** tb)1840796ae06SHerbert Xu static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
1858bd1209cSHerbert Xu {
18639e7a283SEric Biggers struct shash_instance *inst;
1870796ae06SHerbert Xu struct crypto_shash_spawn *spawn;
1888bd1209cSHerbert Xu struct crypto_alg *alg;
1897bcb2c99SEric Biggers struct shash_alg *salg;
190ebc610e5SHerbert Xu u32 mask;
191ca786dc7SHerbert Xu int err;
1920b767b4dSHerbert Xu int ds;
1930796ae06SHerbert Xu int ss;
1947bcb2c99SEric Biggers
195ebc610e5SHerbert Xu err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH, &mask);
1968bd1209cSHerbert Xu if (err)
197ebc610e5SHerbert Xu return err;
19839e7a283SEric Biggers
19939e7a283SEric Biggers inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
20039e7a283SEric Biggers if (!inst)
20139e7a283SEric Biggers return -ENOMEM;
20239e7a283SEric Biggers spawn = shash_instance_ctx(inst);
20339e7a283SEric Biggers
2047bcb2c99SEric Biggers err = crypto_grab_shash(spawn, shash_crypto_instance(inst),
20539e7a283SEric Biggers crypto_attr_alg_name(tb[1]), 0, mask);
20639e7a283SEric Biggers if (err)
20739e7a283SEric Biggers goto err_free_inst;
208af3ff804SEric Biggers salg = crypto_spawn_shash_alg(spawn);
2090796ae06SHerbert Xu alg = &salg->base;
210c2881789SEric Biggers
2118bd1209cSHerbert Xu /* The underlying hash algorithm must not require a key */
212c2881789SEric Biggers err = -EINVAL;
21339e7a283SEric Biggers if (crypto_shash_alg_needs_key(salg))
214af3ff804SEric Biggers goto err_free_inst;
2158bd1209cSHerbert Xu
2160b767b4dSHerbert Xu ds = salg->digestsize;
2170b767b4dSHerbert Xu ss = salg->statesize;
2180b767b4dSHerbert Xu if (ds > alg->cra_blocksize ||
21939e7a283SEric Biggers ss < alg->cra_blocksize)
220ca786dc7SHerbert Xu goto err_free_inst;
22139e7a283SEric Biggers
2228bd1209cSHerbert Xu err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg);
22339e7a283SEric Biggers if (err)
2240796ae06SHerbert Xu goto err_free_inst;
2258bd1209cSHerbert Xu
2268bd1209cSHerbert Xu inst->alg.base.cra_priority = alg->cra_priority;
2278bd1209cSHerbert Xu inst->alg.base.cra_blocksize = alg->cra_blocksize;
2280796ae06SHerbert Xu inst->alg.base.cra_alignmask = alg->cra_alignmask;
2290b767b4dSHerbert Xu
2308bd1209cSHerbert Xu ss = ALIGN(ss, alg->cra_alignmask + 1);
2310b767b4dSHerbert Xu inst->alg.digestsize = ds;
2320796ae06SHerbert Xu inst->alg.statesize = ss;
2338bd1209cSHerbert Xu
2340b767b4dSHerbert Xu inst->alg.base.cra_ctxsize = sizeof(struct hmac_ctx) +
2350796ae06SHerbert Xu ALIGN(ss * 2, crypto_tfm_ctx_alignment());
2368bd1209cSHerbert Xu
2378bd1209cSHerbert Xu inst->alg.init = hmac_init;
2388bd1209cSHerbert Xu inst->alg.update = hmac_update;
2398bd1209cSHerbert Xu inst->alg.final = hmac_final;
2400b767b4dSHerbert Xu inst->alg.finup = hmac_finup;
2410b767b4dSHerbert Xu inst->alg.export = hmac_export;
2428bd1209cSHerbert Xu inst->alg.import = hmac_import;
243d9e1670bSHerbert Xu inst->alg.setkey = hmac_setkey;
244*8538e60dSHerbert Xu inst->alg.init_tfm = hmac_init_tfm;
245d9e1670bSHerbert Xu inst->alg.clone_tfm = hmac_clone_tfm;
2468bd1209cSHerbert Xu inst->alg.exit_tfm = hmac_exit_tfm;
247a39c66ccSEric Biggers
248a39c66ccSEric Biggers inst->free = shash_free_singlespawn_instance;
2498bd1209cSHerbert Xu
2508bd1209cSHerbert Xu err = shash_register_instance(tmpl, inst);
25139e7a283SEric Biggers if (err) {
252a39c66ccSEric Biggers err_free_inst:
2538bd1209cSHerbert Xu shash_free_singlespawn_instance(inst);
2548bd1209cSHerbert Xu }
2550796ae06SHerbert Xu return err;
2560796ae06SHerbert Xu }
2570796ae06SHerbert Xu
2580796ae06SHerbert Xu static struct crypto_template hmac_tmpl = {
2598bd1209cSHerbert Xu .name = "hmac",
2600796ae06SHerbert Xu .create = hmac_create,
2610796ae06SHerbert Xu .module = THIS_MODULE,
2620796ae06SHerbert Xu };
2630796ae06SHerbert Xu
hmac_module_init(void)2640796ae06SHerbert Xu static int __init hmac_module_init(void)
2650796ae06SHerbert Xu {
2660796ae06SHerbert Xu return crypto_register_template(&hmac_tmpl);
2670796ae06SHerbert Xu }
2680796ae06SHerbert Xu
hmac_module_exit(void)2690796ae06SHerbert Xu static void __exit hmac_module_exit(void)
2700796ae06SHerbert Xu {
2710796ae06SHerbert Xu crypto_unregister_template(&hmac_tmpl);
2720796ae06SHerbert Xu }
273c4741b23SEric Biggers
2740796ae06SHerbert Xu subsys_initcall(hmac_module_init);
2750796ae06SHerbert Xu module_exit(hmac_module_exit);
2760796ae06SHerbert Xu
2770796ae06SHerbert Xu MODULE_LICENSE("GPL");
2784943ba16SKees Cook MODULE_DESCRIPTION("HMAC hash algorithm");
279 MODULE_ALIAS_CRYPTO("hmac");
280