The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/crypto/hmac.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Cryptographic API.
    3  *
    4  * HMAC: Keyed-Hashing for Message Authentication (RFC2104).
    5  *
    6  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
    7  * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
    8  *
    9  * The HMAC implementation is derived from USAGI.
   10  * Copyright (c) 2002 Kazunori Miyazawa <miyazawa@linux-ipv6.org> / USAGI
   11  *
   12  * This program is free software; you can redistribute it and/or modify it
   13  * under the terms of the GNU General Public License as published by the Free
   14  * Software Foundation; either version 2 of the License, or (at your option)
   15  * any later version.
   16  *
   17  */
   18 
   19 #include <crypto/internal/hash.h>
   20 #include <crypto/scatterwalk.h>
   21 #include <linux/err.h>
   22 #include <linux/init.h>
   23 #include <linux/kernel.h>
   24 #include <linux/module.h>
   25 #include <linux/scatterlist.h>
   26 #include <linux/string.h>
   27 
   28 struct hmac_ctx {
   29         struct crypto_shash *hash;
   30 };
   31 
   32 static inline void *align_ptr(void *p, unsigned int align)
   33 {
   34         return (void *)ALIGN((unsigned long)p, align);
   35 }
   36 
   37 static inline struct hmac_ctx *hmac_ctx(struct crypto_shash *tfm)
   38 {
   39         return align_ptr(crypto_shash_ctx_aligned(tfm) +
   40                          crypto_shash_statesize(tfm) * 2,
   41                          crypto_tfm_ctx_alignment());
   42 }
   43 
   44 static int hmac_setkey(struct crypto_shash *parent,
   45                        const u8 *inkey, unsigned int keylen)
   46 {
   47         int bs = crypto_shash_blocksize(parent);
   48         int ds = crypto_shash_digestsize(parent);
   49         int ss = crypto_shash_statesize(parent);
   50         char *ipad = crypto_shash_ctx_aligned(parent);
   51         char *opad = ipad + ss;
   52         struct hmac_ctx *ctx = align_ptr(opad + ss,
   53                                          crypto_tfm_ctx_alignment());
   54         struct crypto_shash *hash = ctx->hash;
   55         struct {
   56                 struct shash_desc shash;
   57                 char ctx[crypto_shash_descsize(hash)];
   58         } desc;
   59         unsigned int i;
   60 
   61         desc.shash.tfm = hash;
   62         desc.shash.flags = crypto_shash_get_flags(parent) &
   63                             CRYPTO_TFM_REQ_MAY_SLEEP;
   64 
   65         if (keylen > bs) {
   66                 int err;
   67 
   68                 err = crypto_shash_digest(&desc.shash, inkey, keylen, ipad);
   69                 if (err)
   70                         return err;
   71 
   72                 keylen = ds;
   73         } else
   74                 memcpy(ipad, inkey, keylen);
   75 
   76         memset(ipad + keylen, 0, bs - keylen);
   77         memcpy(opad, ipad, bs);
   78 
   79         for (i = 0; i < bs; i++) {
   80                 ipad[i] ^= 0x36;
   81                 opad[i] ^= 0x5c;
   82         }
   83 
   84         return crypto_shash_init(&desc.shash) ?:
   85                crypto_shash_update(&desc.shash, ipad, bs) ?:
   86                crypto_shash_export(&desc.shash, ipad) ?:
   87                crypto_shash_init(&desc.shash) ?:
   88                crypto_shash_update(&desc.shash, opad, bs) ?:
   89                crypto_shash_export(&desc.shash, opad);
   90 }
   91 
   92 static int hmac_export(struct shash_desc *pdesc, void *out)
   93 {
   94         struct shash_desc *desc = shash_desc_ctx(pdesc);
   95 
   96         desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
   97 
   98         return crypto_shash_export(desc, out);
   99 }
  100 
  101 static int hmac_import(struct shash_desc *pdesc, const void *in)
  102 {
  103         struct shash_desc *desc = shash_desc_ctx(pdesc);
  104         struct hmac_ctx *ctx = hmac_ctx(pdesc->tfm);
  105 
  106         desc->tfm = ctx->hash;
  107         desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
  108 
  109         return crypto_shash_import(desc, in);
  110 }
  111 
  112 static int hmac_init(struct shash_desc *pdesc)
  113 {
  114         return hmac_import(pdesc, crypto_shash_ctx_aligned(pdesc->tfm));
  115 }
  116 
  117 static int hmac_update(struct shash_desc *pdesc,
  118                        const u8 *data, unsigned int nbytes)
  119 {
  120         struct shash_desc *desc = shash_desc_ctx(pdesc);
  121 
  122         desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
  123 
  124         return crypto_shash_update(desc, data, nbytes);
  125 }
  126 
  127 static int hmac_final(struct shash_desc *pdesc, u8 *out)
  128 {
  129         struct crypto_shash *parent = pdesc->tfm;
  130         int ds = crypto_shash_digestsize(parent);
  131         int ss = crypto_shash_statesize(parent);
  132         char *opad = crypto_shash_ctx_aligned(parent) + ss;
  133         struct shash_desc *desc = shash_desc_ctx(pdesc);
  134 
  135         desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
  136 
  137         return crypto_shash_final(desc, out) ?:
  138                crypto_shash_import(desc, opad) ?:
  139                crypto_shash_finup(desc, out, ds, out);
  140 }
  141 
  142 static int hmac_finup(struct shash_desc *pdesc, const u8 *data,
  143                       unsigned int nbytes, u8 *out)
  144 {
  145 
  146         struct crypto_shash *parent = pdesc->tfm;
  147         int ds = crypto_shash_digestsize(parent);
  148         int ss = crypto_shash_statesize(parent);
  149         char *opad = crypto_shash_ctx_aligned(parent) + ss;
  150         struct shash_desc *desc = shash_desc_ctx(pdesc);
  151 
  152         desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
  153 
  154         return crypto_shash_finup(desc, data, nbytes, out) ?:
  155                crypto_shash_import(desc, opad) ?:
  156                crypto_shash_finup(desc, out, ds, out);
  157 }
  158 
  159 static int hmac_init_tfm(struct crypto_tfm *tfm)
  160 {
  161         struct crypto_shash *parent = __crypto_shash_cast(tfm);
  162         struct crypto_shash *hash;
  163         struct crypto_instance *inst = (void *)tfm->__crt_alg;
  164         struct crypto_shash_spawn *spawn = crypto_instance_ctx(inst);
  165         struct hmac_ctx *ctx = hmac_ctx(parent);
  166 
  167         hash = crypto_spawn_shash(spawn);
  168         if (IS_ERR(hash))
  169                 return PTR_ERR(hash);
  170 
  171         parent->descsize = sizeof(struct shash_desc) +
  172                            crypto_shash_descsize(hash);
  173 
  174         ctx->hash = hash;
  175         return 0;
  176 }
  177 
  178 static void hmac_exit_tfm(struct crypto_tfm *tfm)
  179 {
  180         struct hmac_ctx *ctx = hmac_ctx(__crypto_shash_cast(tfm));
  181         crypto_free_shash(ctx->hash);
  182 }
  183 
  184 static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
  185 {
  186         struct shash_instance *inst;
  187         struct crypto_alg *alg;
  188         struct shash_alg *salg;
  189         int err;
  190         int ds;
  191         int ss;
  192 
  193         err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH);
  194         if (err)
  195                 return err;
  196 
  197         salg = shash_attr_alg(tb[1], 0, 0);
  198         if (IS_ERR(salg))
  199                 return PTR_ERR(salg);
  200 
  201         err = -EINVAL;
  202         ds = salg->digestsize;
  203         ss = salg->statesize;
  204         alg = &salg->base;
  205         if (ds > alg->cra_blocksize ||
  206             ss < alg->cra_blocksize)
  207                 goto out_put_alg;
  208 
  209         inst = shash_alloc_instance("hmac", alg);
  210         err = PTR_ERR(inst);
  211         if (IS_ERR(inst))
  212                 goto out_put_alg;
  213 
  214         err = crypto_init_shash_spawn(shash_instance_ctx(inst), salg,
  215                                       shash_crypto_instance(inst));
  216         if (err)
  217                 goto out_free_inst;
  218 
  219         inst->alg.base.cra_priority = alg->cra_priority;
  220         inst->alg.base.cra_blocksize = alg->cra_blocksize;
  221         inst->alg.base.cra_alignmask = alg->cra_alignmask;
  222 
  223         ss = ALIGN(ss, alg->cra_alignmask + 1);
  224         inst->alg.digestsize = ds;
  225         inst->alg.statesize = ss;
  226 
  227         inst->alg.base.cra_ctxsize = sizeof(struct hmac_ctx) +
  228                                      ALIGN(ss * 2, crypto_tfm_ctx_alignment());
  229 
  230         inst->alg.base.cra_init = hmac_init_tfm;
  231         inst->alg.base.cra_exit = hmac_exit_tfm;
  232 
  233         inst->alg.init = hmac_init;
  234         inst->alg.update = hmac_update;
  235         inst->alg.final = hmac_final;
  236         inst->alg.finup = hmac_finup;
  237         inst->alg.export = hmac_export;
  238         inst->alg.import = hmac_import;
  239         inst->alg.setkey = hmac_setkey;
  240 
  241         err = shash_register_instance(tmpl, inst);
  242         if (err) {
  243 out_free_inst:
  244                 shash_free_instance(shash_crypto_instance(inst));
  245         }
  246 
  247 out_put_alg:
  248         crypto_mod_put(alg);
  249         return err;
  250 }
  251 
  252 static struct crypto_template hmac_tmpl = {
  253         .name = "hmac",
  254         .create = hmac_create,
  255         .free = shash_free_instance,
  256         .module = THIS_MODULE,
  257 };
  258 
  259 static int __init hmac_module_init(void)
  260 {
  261         return crypto_register_template(&hmac_tmpl);
  262 }
  263 
  264 static void __exit hmac_module_exit(void)
  265 {
  266         crypto_unregister_template(&hmac_tmpl);
  267 }
  268 
  269 module_init(hmac_module_init);
  270 module_exit(hmac_module_exit);
  271 
  272 MODULE_LICENSE("GPL");
  273 MODULE_DESCRIPTION("HMAC hash algorithm");

Cache object: 48ea553b8c3b1e515e0b4111b034a8e9


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.