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)1638538e60dSHerbert Xu static int hmac_clone_tfm(struct crypto_shash *dst, struct crypto_shash *src)
1648538e60dSHerbert Xu {
1658538e60dSHerbert Xu struct hmac_ctx *sctx = hmac_ctx(src);
1668538e60dSHerbert Xu struct hmac_ctx *dctx = hmac_ctx(dst);
1678538e60dSHerbert Xu struct crypto_shash *hash;
1688538e60dSHerbert Xu
1698538e60dSHerbert Xu hash = crypto_clone_shash(sctx->hash);
1708538e60dSHerbert Xu if (IS_ERR(hash))
1718538e60dSHerbert Xu return PTR_ERR(hash);
1728538e60dSHerbert Xu
1738538e60dSHerbert Xu dctx->hash = hash;
1748538e60dSHerbert Xu return 0;
1758538e60dSHerbert Xu }
1768538e60dSHerbert 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);
180*f75bd28bSFranziska Naepelt
1810b767b4dSHerbert Xu crypto_free_shash(ctx->hash);
1820796ae06SHerbert Xu }
1830796ae06SHerbert Xu
hmac_create(struct crypto_template * tmpl,struct rtattr ** tb)1848bd1209cSHerbert Xu static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
1850796ae06SHerbert Xu {
1868bd1209cSHerbert Xu struct shash_instance *inst;
18739e7a283SEric Biggers struct crypto_shash_spawn *spawn;
1880796ae06SHerbert Xu struct crypto_alg *alg;
1898bd1209cSHerbert Xu struct shash_alg *salg;
1907bcb2c99SEric Biggers u32 mask;
191ebc610e5SHerbert Xu int err;
192ca786dc7SHerbert Xu int ds;
1930b767b4dSHerbert Xu int ss;
1940796ae06SHerbert Xu
1957bcb2c99SEric Biggers err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH, &mask);
196ebc610e5SHerbert Xu if (err)
1978bd1209cSHerbert Xu return err;
198ebc610e5SHerbert Xu
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
20439e7a283SEric Biggers err = crypto_grab_shash(spawn, shash_crypto_instance(inst),
2057bcb2c99SEric Biggers crypto_attr_alg_name(tb[1]), 0, mask);
20639e7a283SEric Biggers if (err)
20739e7a283SEric Biggers goto err_free_inst;
20839e7a283SEric Biggers salg = crypto_spawn_shash_alg(spawn);
209af3ff804SEric Biggers alg = &salg->base;
2100796ae06SHerbert Xu
211c2881789SEric Biggers /* The underlying hash algorithm must not require a key */
2128bd1209cSHerbert Xu err = -EINVAL;
213c2881789SEric Biggers if (crypto_shash_alg_needs_key(salg))
21439e7a283SEric Biggers goto err_free_inst;
215af3ff804SEric Biggers
2168bd1209cSHerbert Xu ds = salg->digestsize;
2170b767b4dSHerbert Xu ss = salg->statesize;
2180b767b4dSHerbert Xu if (ds > alg->cra_blocksize ||
2190b767b4dSHerbert Xu ss < alg->cra_blocksize)
22039e7a283SEric Biggers goto err_free_inst;
221ca786dc7SHerbert Xu
22239e7a283SEric Biggers err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg);
2238bd1209cSHerbert Xu if (err)
22439e7a283SEric Biggers goto err_free_inst;
2250796ae06SHerbert Xu
2268bd1209cSHerbert Xu inst->alg.base.cra_priority = alg->cra_priority;
2278bd1209cSHerbert Xu inst->alg.base.cra_blocksize = alg->cra_blocksize;
2288bd1209cSHerbert Xu inst->alg.base.cra_alignmask = alg->cra_alignmask;
2290796ae06SHerbert Xu
2300b767b4dSHerbert Xu ss = ALIGN(ss, alg->cra_alignmask + 1);
2318bd1209cSHerbert Xu inst->alg.digestsize = ds;
2320b767b4dSHerbert Xu inst->alg.statesize = ss;
2330796ae06SHerbert Xu
2348bd1209cSHerbert Xu inst->alg.base.cra_ctxsize = sizeof(struct hmac_ctx) +
2350b767b4dSHerbert Xu ALIGN(ss * 2, crypto_tfm_ctx_alignment());
2360796ae06SHerbert Xu
2378bd1209cSHerbert Xu inst->alg.init = hmac_init;
2388bd1209cSHerbert Xu inst->alg.update = hmac_update;
2398bd1209cSHerbert Xu inst->alg.final = hmac_final;
2408bd1209cSHerbert Xu inst->alg.finup = hmac_finup;
2410b767b4dSHerbert Xu inst->alg.export = hmac_export;
2420b767b4dSHerbert Xu inst->alg.import = hmac_import;
2438bd1209cSHerbert Xu inst->alg.setkey = hmac_setkey;
244d9e1670bSHerbert Xu inst->alg.init_tfm = hmac_init_tfm;
2458538e60dSHerbert Xu inst->alg.clone_tfm = hmac_clone_tfm;
246d9e1670bSHerbert Xu inst->alg.exit_tfm = hmac_exit_tfm;
2478bd1209cSHerbert Xu
248a39c66ccSEric Biggers inst->free = shash_free_singlespawn_instance;
249a39c66ccSEric Biggers
2508bd1209cSHerbert Xu err = shash_register_instance(tmpl, inst);
2518bd1209cSHerbert Xu if (err) {
25239e7a283SEric Biggers err_free_inst:
253a39c66ccSEric Biggers shash_free_singlespawn_instance(inst);
2548bd1209cSHerbert Xu }
2558bd1209cSHerbert Xu return err;
2560796ae06SHerbert Xu }
2570796ae06SHerbert Xu
2580796ae06SHerbert Xu static struct crypto_template hmac_tmpl = {
2590796ae06SHerbert Xu .name = "hmac",
2608bd1209cSHerbert 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 }
2730796ae06SHerbert Xu
274c4741b23SEric Biggers subsys_initcall(hmac_module_init);
2750796ae06SHerbert Xu module_exit(hmac_module_exit);
2760796ae06SHerbert Xu
2770796ae06SHerbert Xu MODULE_LICENSE("GPL");
2780796ae06SHerbert Xu MODULE_DESCRIPTION("HMAC hash algorithm");
2794943ba16SKees Cook MODULE_ALIAS_CRYPTO("hmac");
280