1 // SPDX-License-Identifier: GPL-2.0-or-later << 2 /* 1 /* 3 * Cryptographic API. 2 * Cryptographic API. 4 * 3 * 5 * HMAC: Keyed-Hashing for Message Authenticat 4 * HMAC: Keyed-Hashing for Message Authentication (RFC2104). 6 * 5 * 7 * Copyright (c) 2002 James Morris <jmorris@in 6 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> 8 * Copyright (c) 2006 Herbert Xu <herbert@gond << 9 * 7 * 10 * The HMAC implementation is derived from USA 8 * The HMAC implementation is derived from USAGI. 11 * Copyright (c) 2002 Kazunori Miyazawa <miyaz 9 * Copyright (c) 2002 Kazunori Miyazawa <miyazawa@linux-ipv6.org> / USAGI >> 10 * >> 11 * This program is free software; you can redistribute it and/or modify it >> 12 * under the terms of the GNU General Public License as published by the Free >> 13 * Software Foundation; either version 2 of the License, or (at your option) >> 14 * any later version. >> 15 * 12 */ 16 */ >> 17 #include <linux/crypto.h> >> 18 #include <linux/mm.h> >> 19 #include <linux/highmem.h> >> 20 #include <linux/slab.h> >> 21 #include <asm/scatterlist.h> >> 22 #include "internal.h" 13 23 14 #include <crypto/hmac.h> !! 24 static void hash_key(struct crypto_tfm *tfm, u8 *key, unsigned int keylen) 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];', the << 28 u8 pads[]; << 29 }; << 30 << 31 static int hmac_setkey(struct crypto_shash *pa << 32 const u8 *inkey, unsign << 33 { << 34 int bs = crypto_shash_blocksize(parent << 35 int ds = crypto_shash_digestsize(paren << 36 int ss = crypto_shash_statesize(parent << 37 struct hmac_ctx *tctx = crypto_shash_c << 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(shas << 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(shash) ?: << 69 crypto_shash_update(shash, ipad << 70 crypto_shash_export(shash, ipad << 71 crypto_shash_init(shash) ?: << 72 crypto_shash_update(shash, opad << 73 crypto_shash_export(shash, opad << 74 } << 75 << 76 static int hmac_export(struct shash_desc *pdes << 77 { 25 { 78 struct shash_desc *desc = shash_desc_c !! 26 struct scatterlist tmp; 79 !! 27 80 return crypto_shash_export(desc, out); !! 28 tmp.page = virt_to_page(key); >> 29 tmp.offset = ((long)key & ~PAGE_MASK); >> 30 tmp.length = keylen; >> 31 crypto_digest_digest(tfm, &tmp, 1, key); >> 32 81 } 33 } 82 34 83 static int hmac_import(struct shash_desc *pdes !! 35 int crypto_alloc_hmac_block(struct crypto_tfm *tfm) 84 { 36 { 85 struct shash_desc *desc = shash_desc_c !! 37 int ret = 0; 86 const struct hmac_ctx *tctx = crypto_s << 87 38 88 desc->tfm = tctx->hash; !! 39 BUG_ON(!crypto_tfm_alg_blocksize(tfm)); >> 40 >> 41 tfm->crt_digest.dit_hmac_block = kmalloc(crypto_tfm_alg_blocksize(tfm), >> 42 GFP_KERNEL); >> 43 if (tfm->crt_digest.dit_hmac_block == NULL) >> 44 ret = -ENOMEM; 89 45 90 return crypto_shash_import(desc, in); !! 46 return ret; >> 47 91 } 48 } 92 49 93 static int hmac_init(struct shash_desc *pdesc) !! 50 void crypto_free_hmac_block(struct crypto_tfm *tfm) 94 { 51 { 95 const struct hmac_ctx *tctx = crypto_s !! 52 if (tfm->crt_digest.dit_hmac_block) 96 !! 53 kfree(tfm->crt_digest.dit_hmac_block); 97 return hmac_import(pdesc, &tctx->pads[ << 98 } << 99 << 100 static int hmac_update(struct shash_desc *pdes << 101 const u8 *data, unsigne << 102 { << 103 struct shash_desc *desc = shash_desc_c << 104 << 105 return crypto_shash_update(desc, data, << 106 } 54 } 107 55 108 static int hmac_final(struct shash_desc *pdesc !! 56 void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen) 109 { 57 { 110 struct crypto_shash *parent = pdesc->t !! 58 unsigned int i; 111 int ds = crypto_shash_digestsize(paren !! 59 struct scatterlist tmp; 112 int ss = crypto_shash_statesize(parent !! 60 char *ipad = tfm->crt_digest.dit_hmac_block; 113 const struct hmac_ctx *tctx = crypto_s !! 61 114 const u8 *opad = &tctx->pads[ss]; !! 62 if (*keylen > crypto_tfm_alg_blocksize(tfm)) { 115 struct shash_desc *desc = shash_desc_c !! 63 hash_key(tfm, key, *keylen); 116 !! 64 *keylen = crypto_tfm_alg_digestsize(tfm); 117 return crypto_shash_final(desc, out) ? !! 65 } 118 crypto_shash_import(desc, opad) << 119 crypto_shash_finup(desc, out, d << 120 } << 121 << 122 static int hmac_finup(struct shash_desc *pdesc << 123 unsigned int nbytes, u8 << 124 { << 125 << 126 struct crypto_shash *parent = pdesc->t << 127 int ds = crypto_shash_digestsize(paren << 128 int ss = crypto_shash_statesize(parent << 129 const struct hmac_ctx *tctx = crypto_s << 130 const u8 *opad = &tctx->pads[ss]; << 131 struct shash_desc *desc = shash_desc_c << 132 << 133 return crypto_shash_finup(desc, data, << 134 crypto_shash_import(desc, opad) << 135 crypto_shash_finup(desc, out, d << 136 } << 137 66 138 static int hmac_init_tfm(struct crypto_shash * !! 67 memset(ipad, 0, crypto_tfm_alg_blocksize(tfm)); 139 { !! 68 memcpy(ipad, key, *keylen); 140 struct crypto_shash *hash; << 141 struct shash_instance *inst = shash_al << 142 struct crypto_shash_spawn *spawn = sha << 143 struct hmac_ctx *tctx = crypto_shash_c << 144 << 145 hash = crypto_spawn_shash(spawn); << 146 if (IS_ERR(hash)) << 147 return PTR_ERR(hash); << 148 69 149 parent->descsize = sizeof(struct shash !! 70 for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) 150 crypto_shash_descsi !! 71 ipad[i] ^= 0x36; 151 72 152 tctx->hash = hash; !! 73 tmp.page = virt_to_page(ipad); 153 return 0; !! 74 tmp.offset = ((long)ipad & ~PAGE_MASK); >> 75 tmp.length = crypto_tfm_alg_blocksize(tfm); >> 76 >> 77 crypto_digest_init(tfm); >> 78 crypto_digest_update(tfm, &tmp, 1); 154 } 79 } 155 80 156 static int hmac_clone_tfm(struct crypto_shash !! 81 void crypto_hmac_update(struct crypto_tfm *tfm, >> 82 struct scatterlist *sg, unsigned int nsg) 157 { 83 { 158 struct hmac_ctx *sctx = crypto_shash_c !! 84 crypto_digest_update(tfm, sg, nsg); 159 struct hmac_ctx *dctx = crypto_shash_c << 160 struct crypto_shash *hash; << 161 << 162 hash = crypto_clone_shash(sctx->hash); << 163 if (IS_ERR(hash)) << 164 return PTR_ERR(hash); << 165 << 166 dctx->hash = hash; << 167 return 0; << 168 } 85 } 169 86 170 static void hmac_exit_tfm(struct crypto_shash !! 87 void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key, >> 88 unsigned int *keylen, u8 *out) 171 { 89 { 172 struct hmac_ctx *tctx = crypto_shash_c !! 90 unsigned int i; 173 !! 91 struct scatterlist tmp; 174 crypto_free_shash(tctx->hash); !! 92 char *opad = tfm->crt_digest.dit_hmac_block; 175 } !! 93 176 !! 94 if (*keylen > crypto_tfm_alg_blocksize(tfm)) { 177 static int hmac_create(struct crypto_template !! 95 hash_key(tfm, key, *keylen); 178 { !! 96 *keylen = crypto_tfm_alg_digestsize(tfm); 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, CRYPT << 189 if (err) << 190 return err; << 191 << 192 inst = kzalloc(sizeof(*inst) + sizeof( << 193 if (!inst) << 194 return -ENOMEM; << 195 spawn = shash_instance_ctx(inst); << 196 << 197 err = crypto_grab_shash(spawn, shash_c << 198 crypto_attr_al << 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 << 205 err = -EINVAL; << 206 if (crypto_shash_alg_needs_key(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(shash_crypto << 216 if (err) << 217 goto err_free_inst; << 218 << 219 inst->alg.base.cra_priority = alg->cra << 220 inst->alg.base.cra_blocksize = alg->cr << 221 inst->alg.base.cra_ctxsize = sizeof(st << 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_in << 237 << 238 err = shash_register_instance(tmpl, in << 239 if (err) { << 240 err_free_inst: << 241 shash_free_singlespawn_instanc << 242 } 97 } 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 98 252 static int __init hmac_module_init(void) !! 99 crypto_digest_final(tfm, out); 253 { << 254 return crypto_register_template(&hmac_ << 255 } << 256 << 257 static void __exit hmac_module_exit(void) << 258 { << 259 crypto_unregister_template(&hmac_tmpl) << 260 } << 261 100 262 subsys_initcall(hmac_module_init); !! 101 memset(opad, 0, crypto_tfm_alg_blocksize(tfm)); 263 module_exit(hmac_module_exit); !! 102 memcpy(opad, key, *keylen); >> 103 >> 104 for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) >> 105 opad[i] ^= 0x5c; >> 106 >> 107 tmp.page = virt_to_page(opad); >> 108 tmp.offset = ((long)opad & ~PAGE_MASK); >> 109 tmp.length = crypto_tfm_alg_blocksize(tfm); >> 110 >> 111 crypto_digest_init(tfm); >> 112 crypto_digest_update(tfm, &tmp, 1); >> 113 >> 114 tmp.page = virt_to_page(out); >> 115 tmp.offset = ((long)out & ~PAGE_MASK); >> 116 tmp.length = crypto_tfm_alg_digestsize(tfm); >> 117 >> 118 crypto_digest_update(tfm, &tmp, 1); >> 119 crypto_digest_final(tfm, out); >> 120 } >> 121 >> 122 void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, >> 123 struct scatterlist *sg, unsigned int nsg, u8 *out) >> 124 { >> 125 crypto_hmac_init(tfm, key, keylen); >> 126 crypto_hmac_update(tfm, sg, nsg); >> 127 crypto_hmac_final(tfm, key, keylen, out); >> 128 } >> 129 >> 130 EXPORT_SYMBOL_GPL(crypto_hmac_init); >> 131 EXPORT_SYMBOL_GPL(crypto_hmac_update); >> 132 EXPORT_SYMBOL_GPL(crypto_hmac_final); >> 133 EXPORT_SYMBOL_GPL(crypto_hmac); 264 134 265 MODULE_LICENSE("GPL"); << 266 MODULE_DESCRIPTION("HMAC hash algorithm"); << 267 MODULE_ALIAS_CRYPTO("hmac"); << 268 135
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.