Branch data Line data Source code
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/init.h> 19 : : #include <linux/kernel.h> 20 : : #include <linux/module.h> 21 : : #include <linux/scatterlist.h> 22 : : #include <linux/string.h> 23 : : 24 : : struct hmac_ctx { 25 : : struct crypto_shash *hash; 26 : : }; 27 : : 28 : : static inline void *align_ptr(void *p, unsigned int align) 29 : : { 30 : 0 : return (void *)ALIGN((unsigned long)p, align); 31 : : } 32 : : 33 : : static inline struct hmac_ctx *hmac_ctx(struct crypto_shash *tfm) 34 : : { 35 : 0 : return align_ptr(crypto_shash_ctx_aligned(tfm) + 36 : : crypto_shash_statesize(tfm) * 2, 37 : : crypto_tfm_ctx_alignment()); 38 : : } 39 : : 40 : 0 : static int hmac_setkey(struct crypto_shash *parent, 41 : : const u8 *inkey, unsigned int keylen) 42 : : { 43 : : int bs = crypto_shash_blocksize(parent); 44 : : int ds = crypto_shash_digestsize(parent); 45 : : int ss = crypto_shash_statesize(parent); 46 : : char *ipad = crypto_shash_ctx_aligned(parent); 47 : 0 : char *opad = ipad + ss; 48 : 0 : struct hmac_ctx *ctx = align_ptr(opad + ss, 49 : : crypto_tfm_ctx_alignment()); 50 : 0 : struct crypto_shash *hash = ctx->hash; 51 : : SHASH_DESC_ON_STACK(shash, hash); 52 : : unsigned int i; 53 : : 54 : 0 : shash->tfm = hash; 55 : : 56 : 0 : if (keylen > bs) { 57 : : int err; 58 : : 59 : 0 : err = crypto_shash_digest(shash, inkey, keylen, ipad); 60 : 0 : if (err) 61 : : return err; 62 : : 63 : : keylen = ds; 64 : : } else 65 : 0 : memcpy(ipad, inkey, keylen); 66 : : 67 : 0 : memset(ipad + keylen, 0, bs - keylen); 68 : 0 : memcpy(opad, ipad, bs); 69 : : 70 : 0 : for (i = 0; i < bs; i++) { 71 : 0 : ipad[i] ^= HMAC_IPAD_VALUE; 72 : 0 : opad[i] ^= HMAC_OPAD_VALUE; 73 : : } 74 : : 75 : 0 : return crypto_shash_init(shash) ?: 76 : 0 : crypto_shash_update(shash, ipad, bs) ?: 77 : 0 : crypto_shash_export(shash, ipad) ?: 78 : 0 : crypto_shash_init(shash) ?: 79 : 0 : crypto_shash_update(shash, opad, bs) ?: 80 : : crypto_shash_export(shash, opad); 81 : : } 82 : : 83 : 0 : static int hmac_export(struct shash_desc *pdesc, void *out) 84 : : { 85 : : struct shash_desc *desc = shash_desc_ctx(pdesc); 86 : : 87 : 0 : return crypto_shash_export(desc, out); 88 : : } 89 : : 90 : 0 : static int hmac_import(struct shash_desc *pdesc, const void *in) 91 : : { 92 : : struct shash_desc *desc = shash_desc_ctx(pdesc); 93 : 0 : struct hmac_ctx *ctx = hmac_ctx(pdesc->tfm); 94 : : 95 : 0 : desc->tfm = ctx->hash; 96 : : 97 : 0 : return crypto_shash_import(desc, in); 98 : : } 99 : : 100 : 0 : static int hmac_init(struct shash_desc *pdesc) 101 : : { 102 : 0 : return hmac_import(pdesc, crypto_shash_ctx_aligned(pdesc->tfm)); 103 : : } 104 : : 105 : 0 : static int hmac_update(struct shash_desc *pdesc, 106 : : const u8 *data, unsigned int nbytes) 107 : : { 108 : : struct shash_desc *desc = shash_desc_ctx(pdesc); 109 : : 110 : 0 : return crypto_shash_update(desc, data, nbytes); 111 : : } 112 : : 113 : 0 : static int hmac_final(struct shash_desc *pdesc, u8 *out) 114 : : { 115 : 0 : struct crypto_shash *parent = pdesc->tfm; 116 : : int ds = crypto_shash_digestsize(parent); 117 : : int ss = crypto_shash_statesize(parent); 118 : 0 : char *opad = crypto_shash_ctx_aligned(parent) + ss; 119 : : struct shash_desc *desc = shash_desc_ctx(pdesc); 120 : : 121 : 0 : return crypto_shash_final(desc, out) ?: 122 : 0 : crypto_shash_import(desc, opad) ?: 123 : : crypto_shash_finup(desc, out, ds, out); 124 : : } 125 : : 126 : 0 : static int hmac_finup(struct shash_desc *pdesc, const u8 *data, 127 : : unsigned int nbytes, u8 *out) 128 : : { 129 : : 130 : 0 : struct crypto_shash *parent = pdesc->tfm; 131 : : int ds = crypto_shash_digestsize(parent); 132 : : int ss = crypto_shash_statesize(parent); 133 : 0 : char *opad = crypto_shash_ctx_aligned(parent) + ss; 134 : : struct shash_desc *desc = shash_desc_ctx(pdesc); 135 : : 136 : 0 : return crypto_shash_finup(desc, data, nbytes, out) ?: 137 : 0 : crypto_shash_import(desc, opad) ?: 138 : : crypto_shash_finup(desc, out, ds, out); 139 : : } 140 : : 141 : 0 : static int hmac_init_tfm(struct crypto_tfm *tfm) 142 : : { 143 : : struct crypto_shash *parent = __crypto_shash_cast(tfm); 144 : : struct crypto_shash *hash; 145 : 0 : struct crypto_instance *inst = (void *)tfm->__crt_alg; 146 : : struct crypto_shash_spawn *spawn = crypto_instance_ctx(inst); 147 : : struct hmac_ctx *ctx = hmac_ctx(parent); 148 : : 149 : : hash = crypto_spawn_shash(spawn); 150 : 0 : if (IS_ERR(hash)) 151 : 0 : return PTR_ERR(hash); 152 : : 153 : 0 : parent->descsize = sizeof(struct shash_desc) + 154 : : crypto_shash_descsize(hash); 155 : 0 : if (WARN_ON(parent->descsize > HASH_MAX_DESCSIZE)) { 156 : : crypto_free_shash(hash); 157 : 0 : return -EINVAL; 158 : : } 159 : : 160 : 0 : ctx->hash = hash; 161 : 0 : return 0; 162 : : } 163 : : 164 : 0 : static void hmac_exit_tfm(struct crypto_tfm *tfm) 165 : : { 166 : : struct hmac_ctx *ctx = hmac_ctx(__crypto_shash_cast(tfm)); 167 : 0 : crypto_free_shash(ctx->hash); 168 : 0 : } 169 : : 170 : 0 : static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb) 171 : : { 172 : : struct shash_instance *inst; 173 : : struct crypto_alg *alg; 174 : : struct shash_alg *salg; 175 : : int err; 176 : : int ds; 177 : : int ss; 178 : : 179 : 0 : err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH); 180 : 0 : if (err) 181 : : return err; 182 : : 183 : 0 : salg = shash_attr_alg(tb[1], 0, 0); 184 : 0 : if (IS_ERR(salg)) 185 : 0 : return PTR_ERR(salg); 186 : 0 : alg = &salg->base; 187 : : 188 : : /* The underlying hash algorithm must be unkeyed */ 189 : : err = -EINVAL; 190 : 0 : if (crypto_shash_alg_has_setkey(salg)) 191 : : goto out_put_alg; 192 : : 193 : 0 : ds = salg->digestsize; 194 : 0 : ss = salg->statesize; 195 : 0 : if (ds > alg->cra_blocksize || 196 : : ss < alg->cra_blocksize) 197 : : goto out_put_alg; 198 : : 199 : : inst = shash_alloc_instance("hmac", alg); 200 : : err = PTR_ERR(inst); 201 : 0 : if (IS_ERR(inst)) 202 : : goto out_put_alg; 203 : : 204 : 0 : err = crypto_init_shash_spawn(shash_instance_ctx(inst), salg, 205 : : shash_crypto_instance(inst)); 206 : 0 : if (err) 207 : : goto out_free_inst; 208 : : 209 : 0 : inst->alg.base.cra_priority = alg->cra_priority; 210 : 0 : inst->alg.base.cra_blocksize = alg->cra_blocksize; 211 : 0 : inst->alg.base.cra_alignmask = alg->cra_alignmask; 212 : : 213 : 0 : ss = ALIGN(ss, alg->cra_alignmask + 1); 214 : 0 : inst->alg.digestsize = ds; 215 : 0 : inst->alg.statesize = ss; 216 : : 217 : 0 : inst->alg.base.cra_ctxsize = sizeof(struct hmac_ctx) + 218 : 0 : ALIGN(ss * 2, crypto_tfm_ctx_alignment()); 219 : : 220 : 0 : inst->alg.base.cra_init = hmac_init_tfm; 221 : 0 : inst->alg.base.cra_exit = hmac_exit_tfm; 222 : : 223 : 0 : inst->alg.init = hmac_init; 224 : 0 : inst->alg.update = hmac_update; 225 : 0 : inst->alg.final = hmac_final; 226 : 0 : inst->alg.finup = hmac_finup; 227 : 0 : inst->alg.export = hmac_export; 228 : 0 : inst->alg.import = hmac_import; 229 : 0 : inst->alg.setkey = hmac_setkey; 230 : : 231 : 0 : err = shash_register_instance(tmpl, inst); 232 : 0 : if (err) { 233 : : out_free_inst: 234 : 0 : shash_free_instance(shash_crypto_instance(inst)); 235 : : } 236 : : 237 : : out_put_alg: 238 : 0 : crypto_mod_put(alg); 239 : 0 : return err; 240 : : } 241 : : 242 : : static struct crypto_template hmac_tmpl = { 243 : : .name = "hmac", 244 : : .create = hmac_create, 245 : : .free = shash_free_instance, 246 : : .module = THIS_MODULE, 247 : : }; 248 : : 249 : 3 : static int __init hmac_module_init(void) 250 : : { 251 : 3 : return crypto_register_template(&hmac_tmpl); 252 : : } 253 : : 254 : 0 : static void __exit hmac_module_exit(void) 255 : : { 256 : 0 : crypto_unregister_template(&hmac_tmpl); 257 : 0 : } 258 : : 259 : : subsys_initcall(hmac_module_init); 260 : : module_exit(hmac_module_exit); 261 : : 262 : : MODULE_LICENSE("GPL"); 263 : : MODULE_DESCRIPTION("HMAC hash algorithm"); 264 : : MODULE_ALIAS_CRYPTO("hmac");