LCOV - code coverage report
Current view: top level - crypto - hmac.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 2 132 1.5 %
Date: 2022-03-28 15:32:58 Functions: 1 12 8.3 %
Branches: 0 64 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                 :          0 : static inline void *align_ptr(void *p, unsigned int align)
      29                 :            : {
      30                 :          0 :         return (void *)ALIGN((unsigned long)p, align);
      31                 :            : }
      32                 :            : 
      33                 :          0 : static inline struct hmac_ctx *hmac_ctx(struct crypto_shash *tfm)
      34                 :            : {
      35                 :          0 :         return align_ptr(crypto_shash_ctx_aligned(tfm) +
      36                 :          0 :                          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         [ #  # ]:          0 :         int bs = crypto_shash_blocksize(parent);
      44         [ #  # ]:          0 :         int ds = crypto_shash_digestsize(parent);
      45         [ #  # ]:          0 :         int ss = crypto_shash_statesize(parent);
      46         [ #  # ]:          0 :         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                 :          0 :         SHASH_DESC_ON_STACK(shash, hash);
      52                 :          0 :         unsigned int i;
      53                 :            : 
      54                 :          0 :         shash->tfm = hash;
      55                 :            : 
      56         [ #  # ]:          0 :         if (keylen > bs) {
      57                 :          0 :                 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                 :          0 :         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         [ #  # ]:          0 :         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                 :          0 :         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                 :          0 :         int ds = crypto_shash_digestsize(parent);
     117                 :          0 :         int ss = crypto_shash_statesize(parent);
     118                 :          0 :         char *opad = crypto_shash_ctx_aligned(parent) + ss;
     119                 :          0 :         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                 :          0 :                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                 :          0 :         int ds = crypto_shash_digestsize(parent);
     132                 :          0 :         int ss = crypto_shash_statesize(parent);
     133                 :          0 :         char *opad = crypto_shash_ctx_aligned(parent) + ss;
     134                 :          0 :         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                 :          0 :                crypto_shash_finup(desc, out, ds, out);
     139                 :            : }
     140                 :            : 
     141                 :          0 : static int hmac_init_tfm(struct crypto_shash *parent)
     142                 :            : {
     143                 :          0 :         struct crypto_shash *hash;
     144                 :          0 :         struct shash_instance *inst = shash_alg_instance(parent);
     145                 :          0 :         struct crypto_shash_spawn *spawn = shash_instance_ctx(inst);
     146                 :          0 :         struct hmac_ctx *ctx = hmac_ctx(parent);
     147                 :            : 
     148                 :          0 :         hash = crypto_spawn_shash(spawn);
     149         [ #  # ]:          0 :         if (IS_ERR(hash))
     150                 :          0 :                 return PTR_ERR(hash);
     151                 :            : 
     152                 :          0 :         parent->descsize = sizeof(struct shash_desc) +
     153                 :            :                            crypto_shash_descsize(hash);
     154                 :            : 
     155                 :          0 :         ctx->hash = hash;
     156                 :          0 :         return 0;
     157                 :            : }
     158                 :            : 
     159                 :          0 : static void hmac_exit_tfm(struct crypto_shash *parent)
     160                 :            : {
     161                 :          0 :         struct hmac_ctx *ctx = hmac_ctx(parent);
     162                 :          0 :         crypto_free_shash(ctx->hash);
     163                 :          0 : }
     164                 :            : 
     165                 :          0 : static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
     166                 :            : {
     167                 :          0 :         struct shash_instance *inst;
     168                 :          0 :         struct crypto_shash_spawn *spawn;
     169                 :          0 :         struct crypto_alg *alg;
     170                 :          0 :         struct shash_alg *salg;
     171                 :          0 :         int err;
     172                 :          0 :         int ds;
     173                 :          0 :         int ss;
     174                 :            : 
     175                 :          0 :         err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH);
     176         [ #  # ]:          0 :         if (err)
     177                 :            :                 return err;
     178                 :            : 
     179                 :          0 :         inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
     180         [ #  # ]:          0 :         if (!inst)
     181                 :            :                 return -ENOMEM;
     182                 :          0 :         spawn = shash_instance_ctx(inst);
     183                 :            : 
     184                 :          0 :         err = crypto_grab_shash(spawn, shash_crypto_instance(inst),
     185                 :            :                                 crypto_attr_alg_name(tb[1]), 0, 0);
     186         [ #  # ]:          0 :         if (err)
     187                 :          0 :                 goto err_free_inst;
     188         [ #  # ]:          0 :         salg = crypto_spawn_shash_alg(spawn);
     189                 :          0 :         alg = &salg->base;
     190                 :            : 
     191                 :            :         /* The underlying hash algorithm must not require a key */
     192                 :          0 :         err = -EINVAL;
     193   [ #  #  #  # ]:          0 :         if (crypto_shash_alg_needs_key(salg))
     194                 :          0 :                 goto err_free_inst;
     195                 :            : 
     196                 :          0 :         ds = salg->digestsize;
     197                 :          0 :         ss = salg->statesize;
     198   [ #  #  #  # ]:          0 :         if (ds > alg->cra_blocksize ||
     199                 :            :             ss < alg->cra_blocksize)
     200                 :          0 :                 goto err_free_inst;
     201                 :            : 
     202                 :          0 :         err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg);
     203         [ #  # ]:          0 :         if (err)
     204                 :          0 :                 goto err_free_inst;
     205                 :            : 
     206                 :          0 :         inst->alg.base.cra_priority = alg->cra_priority;
     207                 :          0 :         inst->alg.base.cra_blocksize = alg->cra_blocksize;
     208                 :          0 :         inst->alg.base.cra_alignmask = alg->cra_alignmask;
     209                 :            : 
     210                 :          0 :         ss = ALIGN(ss, alg->cra_alignmask + 1);
     211                 :          0 :         inst->alg.digestsize = ds;
     212                 :          0 :         inst->alg.statesize = ss;
     213                 :            : 
     214                 :          0 :         inst->alg.base.cra_ctxsize = sizeof(struct hmac_ctx) +
     215                 :          0 :                                      ALIGN(ss * 2, crypto_tfm_ctx_alignment());
     216                 :            : 
     217                 :          0 :         inst->alg.init = hmac_init;
     218                 :          0 :         inst->alg.update = hmac_update;
     219                 :          0 :         inst->alg.final = hmac_final;
     220                 :          0 :         inst->alg.finup = hmac_finup;
     221                 :          0 :         inst->alg.export = hmac_export;
     222                 :          0 :         inst->alg.import = hmac_import;
     223                 :          0 :         inst->alg.setkey = hmac_setkey;
     224                 :          0 :         inst->alg.init_tfm = hmac_init_tfm;
     225                 :          0 :         inst->alg.exit_tfm = hmac_exit_tfm;
     226                 :            : 
     227                 :          0 :         inst->free = shash_free_singlespawn_instance;
     228                 :            : 
     229                 :          0 :         err = shash_register_instance(tmpl, inst);
     230         [ #  # ]:          0 :         if (err) {
     231                 :          0 : err_free_inst:
     232                 :          0 :                 shash_free_singlespawn_instance(inst);
     233                 :            :         }
     234                 :            :         return err;
     235                 :            : }
     236                 :            : 
     237                 :            : static struct crypto_template hmac_tmpl = {
     238                 :            :         .name = "hmac",
     239                 :            :         .create = hmac_create,
     240                 :            :         .module = THIS_MODULE,
     241                 :            : };
     242                 :            : 
     243                 :         28 : static int __init hmac_module_init(void)
     244                 :            : {
     245                 :         28 :         return crypto_register_template(&hmac_tmpl);
     246                 :            : }
     247                 :            : 
     248                 :          0 : static void __exit hmac_module_exit(void)
     249                 :            : {
     250                 :          0 :         crypto_unregister_template(&hmac_tmpl);
     251                 :          0 : }
     252                 :            : 
     253                 :            : subsys_initcall(hmac_module_init);
     254                 :            : module_exit(hmac_module_exit);
     255                 :            : 
     256                 :            : MODULE_LICENSE("GPL");
     257                 :            : MODULE_DESCRIPTION("HMAC hash algorithm");
     258                 :            : MODULE_ALIAS_CRYPTO("hmac");

Generated by: LCOV version 1.14