xref: /linux/crypto/hmac.c (revision 4ba24fef3eb3b142197135223b90ced2f319cd53)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * Cryptographic API.
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * HMAC: Keyed-Hashing for Message Authentication (RFC2104).
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
70796ae06SHerbert Xu  * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * The HMAC implementation is derived from USAGI.
101da177e4SLinus Torvalds  * Copyright (c) 2002 Kazunori Miyazawa <miyazawa@linux-ipv6.org> / USAGI
111da177e4SLinus Torvalds  *
121da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify it
131da177e4SLinus Torvalds  * under the terms of the GNU General Public License as published by the Free
141da177e4SLinus Torvalds  * Software Foundation; either version 2 of the License, or (at your option)
151da177e4SLinus Torvalds  * any later version.
161da177e4SLinus Torvalds  *
171da177e4SLinus Torvalds  */
180796ae06SHerbert Xu 
195f7082edSHerbert Xu #include <crypto/internal/hash.h>
20b2ab4a57SHerbert Xu #include <crypto/scatterwalk.h>
210796ae06SHerbert Xu #include <linux/err.h>
220796ae06SHerbert Xu #include <linux/init.h>
230796ae06SHerbert Xu #include <linux/kernel.h>
240796ae06SHerbert Xu #include <linux/module.h>
25378f058cSDavid Hardeman #include <linux/scatterlist.h>
260796ae06SHerbert Xu #include <linux/string.h>
270796ae06SHerbert Xu 
280796ae06SHerbert Xu struct hmac_ctx {
290b767b4dSHerbert Xu 	struct crypto_shash *hash;
300796ae06SHerbert Xu };
311da177e4SLinus Torvalds 
320796ae06SHerbert Xu static inline void *align_ptr(void *p, unsigned int align)
330796ae06SHerbert Xu {
340796ae06SHerbert Xu 	return (void *)ALIGN((unsigned long)p, align);
350796ae06SHerbert Xu }
360796ae06SHerbert Xu 
378bd1209cSHerbert Xu static inline struct hmac_ctx *hmac_ctx(struct crypto_shash *tfm)
380796ae06SHerbert Xu {
398bd1209cSHerbert Xu 	return align_ptr(crypto_shash_ctx_aligned(tfm) +
400b767b4dSHerbert Xu 			 crypto_shash_statesize(tfm) * 2,
418bd1209cSHerbert Xu 			 crypto_tfm_ctx_alignment());
420796ae06SHerbert Xu }
430796ae06SHerbert Xu 
448bd1209cSHerbert Xu static int hmac_setkey(struct crypto_shash *parent,
450796ae06SHerbert Xu 		       const u8 *inkey, unsigned int keylen)
460796ae06SHerbert Xu {
478bd1209cSHerbert Xu 	int bs = crypto_shash_blocksize(parent);
488bd1209cSHerbert Xu 	int ds = crypto_shash_digestsize(parent);
490b767b4dSHerbert Xu 	int ss = crypto_shash_statesize(parent);
508bd1209cSHerbert Xu 	char *ipad = crypto_shash_ctx_aligned(parent);
510b767b4dSHerbert Xu 	char *opad = ipad + ss;
520b767b4dSHerbert Xu 	struct hmac_ctx *ctx = align_ptr(opad + ss,
538bd1209cSHerbert Xu 					 crypto_tfm_ctx_alignment());
540b767b4dSHerbert Xu 	struct crypto_shash *hash = ctx->hash;
55ffb32e97SJan-Simon Möller 	SHASH_DESC_ON_STACK(shash, hash);
560796ae06SHerbert Xu 	unsigned int i;
570796ae06SHerbert Xu 
58ffb32e97SJan-Simon Möller 	shash->tfm = hash;
59ffb32e97SJan-Simon Möller 	shash->flags = crypto_shash_get_flags(parent)
60ffb32e97SJan-Simon Möller 		& CRYPTO_TFM_REQ_MAY_SLEEP;
610b767b4dSHerbert Xu 
620796ae06SHerbert Xu 	if (keylen > bs) {
630796ae06SHerbert Xu 		int err;
640796ae06SHerbert Xu 
65ffb32e97SJan-Simon Möller 		err = crypto_shash_digest(shash, inkey, keylen, ipad);
660796ae06SHerbert Xu 		if (err)
670796ae06SHerbert Xu 			return err;
680796ae06SHerbert Xu 
690796ae06SHerbert Xu 		keylen = ds;
700b767b4dSHerbert Xu 	} else
710796ae06SHerbert Xu 		memcpy(ipad, inkey, keylen);
720b767b4dSHerbert Xu 
730796ae06SHerbert Xu 	memset(ipad + keylen, 0, bs - keylen);
740796ae06SHerbert Xu 	memcpy(opad, ipad, bs);
750796ae06SHerbert Xu 
760796ae06SHerbert Xu 	for (i = 0; i < bs; i++) {
770796ae06SHerbert Xu 		ipad[i] ^= 0x36;
780796ae06SHerbert Xu 		opad[i] ^= 0x5c;
790796ae06SHerbert Xu 	}
800796ae06SHerbert Xu 
81ffb32e97SJan-Simon Möller 	return crypto_shash_init(shash) ?:
82ffb32e97SJan-Simon Möller 	       crypto_shash_update(shash, ipad, bs) ?:
83ffb32e97SJan-Simon Möller 	       crypto_shash_export(shash, ipad) ?:
84ffb32e97SJan-Simon Möller 	       crypto_shash_init(shash) ?:
85ffb32e97SJan-Simon Möller 	       crypto_shash_update(shash, opad, bs) ?:
86ffb32e97SJan-Simon Möller 	       crypto_shash_export(shash, opad);
870b767b4dSHerbert Xu }
880b767b4dSHerbert Xu 
890b767b4dSHerbert Xu static int hmac_export(struct shash_desc *pdesc, void *out)
900b767b4dSHerbert Xu {
910b767b4dSHerbert Xu 	struct shash_desc *desc = shash_desc_ctx(pdesc);
920b767b4dSHerbert Xu 
930b767b4dSHerbert Xu 	desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
940b767b4dSHerbert Xu 
950b767b4dSHerbert Xu 	return crypto_shash_export(desc, out);
960b767b4dSHerbert Xu }
970b767b4dSHerbert Xu 
980b767b4dSHerbert Xu static int hmac_import(struct shash_desc *pdesc, const void *in)
990b767b4dSHerbert Xu {
1000b767b4dSHerbert Xu 	struct shash_desc *desc = shash_desc_ctx(pdesc);
1010b767b4dSHerbert Xu 	struct hmac_ctx *ctx = hmac_ctx(pdesc->tfm);
1020b767b4dSHerbert Xu 
1030b767b4dSHerbert Xu 	desc->tfm = ctx->hash;
1040b767b4dSHerbert Xu 	desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
1050b767b4dSHerbert Xu 
1060b767b4dSHerbert Xu 	return crypto_shash_import(desc, in);
1070796ae06SHerbert Xu }
1080796ae06SHerbert Xu 
1098bd1209cSHerbert Xu static int hmac_init(struct shash_desc *pdesc)
1100796ae06SHerbert Xu {
1110b767b4dSHerbert Xu 	return hmac_import(pdesc, crypto_shash_ctx_aligned(pdesc->tfm));
1120796ae06SHerbert Xu }
1130796ae06SHerbert Xu 
1148bd1209cSHerbert Xu static int hmac_update(struct shash_desc *pdesc,
1158bd1209cSHerbert Xu 		       const u8 *data, unsigned int nbytes)
1160796ae06SHerbert Xu {
1178bd1209cSHerbert Xu 	struct shash_desc *desc = shash_desc_ctx(pdesc);
1180796ae06SHerbert Xu 
1198bd1209cSHerbert Xu 	desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
1200796ae06SHerbert Xu 
1218bd1209cSHerbert Xu 	return crypto_shash_update(desc, data, nbytes);
1220796ae06SHerbert Xu }
1230796ae06SHerbert Xu 
1248bd1209cSHerbert Xu static int hmac_final(struct shash_desc *pdesc, u8 *out)
1250796ae06SHerbert Xu {
1268bd1209cSHerbert Xu 	struct crypto_shash *parent = pdesc->tfm;
1278bd1209cSHerbert Xu 	int ds = crypto_shash_digestsize(parent);
1280b767b4dSHerbert Xu 	int ss = crypto_shash_statesize(parent);
1290b767b4dSHerbert Xu 	char *opad = crypto_shash_ctx_aligned(parent) + ss;
1308bd1209cSHerbert Xu 	struct shash_desc *desc = shash_desc_ctx(pdesc);
1310796ae06SHerbert Xu 
1328bd1209cSHerbert Xu 	desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
1330796ae06SHerbert Xu 
1340b767b4dSHerbert Xu 	return crypto_shash_final(desc, out) ?:
1350b767b4dSHerbert Xu 	       crypto_shash_import(desc, opad) ?:
1360b767b4dSHerbert Xu 	       crypto_shash_finup(desc, out, ds, out);
1370796ae06SHerbert Xu }
1380796ae06SHerbert Xu 
1398bd1209cSHerbert Xu static int hmac_finup(struct shash_desc *pdesc, const u8 *data,
1400796ae06SHerbert Xu 		      unsigned int nbytes, u8 *out)
1410796ae06SHerbert Xu {
1428bd1209cSHerbert Xu 
1438bd1209cSHerbert Xu 	struct crypto_shash *parent = pdesc->tfm;
1448bd1209cSHerbert Xu 	int ds = crypto_shash_digestsize(parent);
1450b767b4dSHerbert Xu 	int ss = crypto_shash_statesize(parent);
1460b767b4dSHerbert Xu 	char *opad = crypto_shash_ctx_aligned(parent) + ss;
1478bd1209cSHerbert Xu 	struct shash_desc *desc = shash_desc_ctx(pdesc);
1480796ae06SHerbert Xu 
1498bd1209cSHerbert Xu 	desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
1500796ae06SHerbert Xu 
1510b767b4dSHerbert Xu 	return crypto_shash_finup(desc, data, nbytes, out) ?:
1520b767b4dSHerbert Xu 	       crypto_shash_import(desc, opad) ?:
1530b767b4dSHerbert Xu 	       crypto_shash_finup(desc, out, ds, out);
1540796ae06SHerbert Xu }
1550796ae06SHerbert Xu 
1560796ae06SHerbert Xu static int hmac_init_tfm(struct crypto_tfm *tfm)
1570796ae06SHerbert Xu {
1588bd1209cSHerbert Xu 	struct crypto_shash *parent = __crypto_shash_cast(tfm);
1598bd1209cSHerbert Xu 	struct crypto_shash *hash;
1600796ae06SHerbert Xu 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
1618bd1209cSHerbert Xu 	struct crypto_shash_spawn *spawn = crypto_instance_ctx(inst);
1628bd1209cSHerbert Xu 	struct hmac_ctx *ctx = hmac_ctx(parent);
1630796ae06SHerbert Xu 
1648bd1209cSHerbert Xu 	hash = crypto_spawn_shash(spawn);
1652e306ee0SHerbert Xu 	if (IS_ERR(hash))
1662e306ee0SHerbert Xu 		return PTR_ERR(hash);
1670796ae06SHerbert Xu 
1688bd1209cSHerbert Xu 	parent->descsize = sizeof(struct shash_desc) +
1698bd1209cSHerbert Xu 			   crypto_shash_descsize(hash);
1708bd1209cSHerbert Xu 
1710b767b4dSHerbert Xu 	ctx->hash = hash;
1720796ae06SHerbert Xu 	return 0;
1730796ae06SHerbert Xu }
1740796ae06SHerbert Xu 
1750796ae06SHerbert Xu static void hmac_exit_tfm(struct crypto_tfm *tfm)
1760796ae06SHerbert Xu {
1778bd1209cSHerbert Xu 	struct hmac_ctx *ctx = hmac_ctx(__crypto_shash_cast(tfm));
1780b767b4dSHerbert Xu 	crypto_free_shash(ctx->hash);
1790796ae06SHerbert Xu }
1800796ae06SHerbert Xu 
1818bd1209cSHerbert Xu static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
1820796ae06SHerbert Xu {
1838bd1209cSHerbert Xu 	struct shash_instance *inst;
1840796ae06SHerbert Xu 	struct crypto_alg *alg;
1858bd1209cSHerbert Xu 	struct shash_alg *salg;
186ebc610e5SHerbert Xu 	int err;
187ca786dc7SHerbert Xu 	int ds;
1880b767b4dSHerbert Xu 	int ss;
1890796ae06SHerbert Xu 
1908bd1209cSHerbert Xu 	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH);
191ebc610e5SHerbert Xu 	if (err)
1928bd1209cSHerbert Xu 		return err;
193ebc610e5SHerbert Xu 
1948bd1209cSHerbert Xu 	salg = shash_attr_alg(tb[1], 0, 0);
1958bd1209cSHerbert Xu 	if (IS_ERR(salg))
1968bd1209cSHerbert Xu 		return PTR_ERR(salg);
1970796ae06SHerbert Xu 
1988bd1209cSHerbert Xu 	err = -EINVAL;
1998bd1209cSHerbert Xu 	ds = salg->digestsize;
2000b767b4dSHerbert Xu 	ss = salg->statesize;
2018bd1209cSHerbert Xu 	alg = &salg->base;
2020b767b4dSHerbert Xu 	if (ds > alg->cra_blocksize ||
2030b767b4dSHerbert Xu 	    ss < alg->cra_blocksize)
204ca786dc7SHerbert Xu 		goto out_put_alg;
205ca786dc7SHerbert Xu 
2068bd1209cSHerbert Xu 	inst = shash_alloc_instance("hmac", alg);
2073b3fc322SHerbert Xu 	err = PTR_ERR(inst);
2080796ae06SHerbert Xu 	if (IS_ERR(inst))
2090796ae06SHerbert Xu 		goto out_put_alg;
2100796ae06SHerbert Xu 
2118bd1209cSHerbert Xu 	err = crypto_init_shash_spawn(shash_instance_ctx(inst), salg,
2128bd1209cSHerbert Xu 				      shash_crypto_instance(inst));
2138bd1209cSHerbert Xu 	if (err)
2148bd1209cSHerbert Xu 		goto out_free_inst;
2150796ae06SHerbert Xu 
2168bd1209cSHerbert Xu 	inst->alg.base.cra_priority = alg->cra_priority;
2178bd1209cSHerbert Xu 	inst->alg.base.cra_blocksize = alg->cra_blocksize;
2188bd1209cSHerbert Xu 	inst->alg.base.cra_alignmask = alg->cra_alignmask;
2190796ae06SHerbert Xu 
2200b767b4dSHerbert Xu 	ss = ALIGN(ss, alg->cra_alignmask + 1);
2218bd1209cSHerbert Xu 	inst->alg.digestsize = ds;
2220b767b4dSHerbert Xu 	inst->alg.statesize = ss;
2230796ae06SHerbert Xu 
2248bd1209cSHerbert Xu 	inst->alg.base.cra_ctxsize = sizeof(struct hmac_ctx) +
2250b767b4dSHerbert Xu 				     ALIGN(ss * 2, crypto_tfm_ctx_alignment());
2260796ae06SHerbert Xu 
2278bd1209cSHerbert Xu 	inst->alg.base.cra_init = hmac_init_tfm;
2288bd1209cSHerbert Xu 	inst->alg.base.cra_exit = hmac_exit_tfm;
2298bd1209cSHerbert Xu 
2308bd1209cSHerbert Xu 	inst->alg.init = hmac_init;
2318bd1209cSHerbert Xu 	inst->alg.update = hmac_update;
2328bd1209cSHerbert Xu 	inst->alg.final = hmac_final;
2338bd1209cSHerbert Xu 	inst->alg.finup = hmac_finup;
2340b767b4dSHerbert Xu 	inst->alg.export = hmac_export;
2350b767b4dSHerbert Xu 	inst->alg.import = hmac_import;
2368bd1209cSHerbert Xu 	inst->alg.setkey = hmac_setkey;
2378bd1209cSHerbert Xu 
2388bd1209cSHerbert Xu 	err = shash_register_instance(tmpl, inst);
2398bd1209cSHerbert Xu 	if (err) {
2408bd1209cSHerbert Xu out_free_inst:
2418bd1209cSHerbert Xu 		shash_free_instance(shash_crypto_instance(inst));
2428bd1209cSHerbert Xu 	}
2430796ae06SHerbert Xu 
2440796ae06SHerbert Xu out_put_alg:
2450796ae06SHerbert Xu 	crypto_mod_put(alg);
2468bd1209cSHerbert Xu 	return err;
2470796ae06SHerbert Xu }
2480796ae06SHerbert Xu 
2490796ae06SHerbert Xu static struct crypto_template hmac_tmpl = {
2500796ae06SHerbert Xu 	.name = "hmac",
2518bd1209cSHerbert Xu 	.create = hmac_create,
2528bd1209cSHerbert Xu 	.free = shash_free_instance,
2530796ae06SHerbert Xu 	.module = THIS_MODULE,
2540796ae06SHerbert Xu };
2550796ae06SHerbert Xu 
2560796ae06SHerbert Xu static int __init hmac_module_init(void)
2570796ae06SHerbert Xu {
2580796ae06SHerbert Xu 	return crypto_register_template(&hmac_tmpl);
2590796ae06SHerbert Xu }
2600796ae06SHerbert Xu 
2610796ae06SHerbert Xu static void __exit hmac_module_exit(void)
2620796ae06SHerbert Xu {
2630796ae06SHerbert Xu 	crypto_unregister_template(&hmac_tmpl);
2640796ae06SHerbert Xu }
2650796ae06SHerbert Xu 
2660796ae06SHerbert Xu module_init(hmac_module_init);
2670796ae06SHerbert Xu module_exit(hmac_module_exit);
2680796ae06SHerbert Xu 
2690796ae06SHerbert Xu MODULE_LICENSE("GPL");
2700796ae06SHerbert Xu MODULE_DESCRIPTION("HMAC hash algorithm");
271*4943ba16SKees Cook MODULE_ALIAS_CRYPTO("hmac");
272