LCOV - code coverage report
Current view: top level - crypto - hmac.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_qemu_modules_combined.info Lines: 2 94 2.1 %
Date: 2020-09-30 20:25:01 Functions: 1 12 8.3 %
Branches: 0 46 0.0 %

           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                 :        404 : static int __init hmac_module_init(void)
     250                 :            : {
     251                 :        404 :         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");

Generated by: LCOV version 1.14