LCOV - code coverage report
Current view: top level - crypto - seqiv.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 2 97 2.1 %
Date: 2022-04-01 14:58:12 Functions: 1 8 12.5 %
Branches: 0 46 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  * seqiv: Sequence Number IV Generator
       4                 :            :  *
       5                 :            :  * This generator generates an IV based on a sequence number by xoring it
       6                 :            :  * with a salt.  This algorithm is mainly useful for CTR and similar modes.
       7                 :            :  *
       8                 :            :  * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
       9                 :            :  */
      10                 :            : 
      11                 :            : #include <crypto/internal/geniv.h>
      12                 :            : #include <crypto/scatterwalk.h>
      13                 :            : #include <crypto/skcipher.h>
      14                 :            : #include <linux/err.h>
      15                 :            : #include <linux/init.h>
      16                 :            : #include <linux/kernel.h>
      17                 :            : #include <linux/module.h>
      18                 :            : #include <linux/slab.h>
      19                 :            : #include <linux/string.h>
      20                 :            : 
      21                 :          0 : static void seqiv_aead_encrypt_complete2(struct aead_request *req, int err)
      22                 :            : {
      23         [ #  # ]:          0 :         struct aead_request *subreq = aead_request_ctx(req);
      24                 :          0 :         struct crypto_aead *geniv;
      25                 :            : 
      26         [ #  # ]:          0 :         if (err == -EINPROGRESS)
      27                 :            :                 return;
      28                 :            : 
      29         [ #  # ]:          0 :         if (err)
      30                 :          0 :                 goto out;
      31                 :            : 
      32                 :          0 :         geniv = crypto_aead_reqtfm(req);
      33                 :          0 :         memcpy(req->iv, subreq->iv, crypto_aead_ivsize(geniv));
      34                 :            : 
      35                 :          0 : out:
      36                 :          0 :         kzfree(subreq->iv);
      37                 :            : }
      38                 :            : 
      39                 :          0 : static void seqiv_aead_encrypt_complete(struct crypto_async_request *base,
      40                 :            :                                         int err)
      41                 :            : {
      42                 :          0 :         struct aead_request *req = base->data;
      43                 :            : 
      44                 :          0 :         seqiv_aead_encrypt_complete2(req, err);
      45                 :          0 :         aead_request_complete(req, err);
      46                 :          0 : }
      47                 :            : 
      48                 :          0 : static int seqiv_aead_encrypt(struct aead_request *req)
      49                 :            : {
      50         [ #  # ]:          0 :         struct crypto_aead *geniv = crypto_aead_reqtfm(req);
      51         [ #  # ]:          0 :         struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
      52         [ #  # ]:          0 :         struct aead_request *subreq = aead_request_ctx(req);
      53                 :          0 :         crypto_completion_t compl;
      54                 :          0 :         void *data;
      55                 :          0 :         u8 *info;
      56                 :          0 :         unsigned int ivsize = 8;
      57                 :          0 :         int err;
      58                 :            : 
      59         [ #  # ]:          0 :         if (req->cryptlen < ivsize)
      60                 :            :                 return -EINVAL;
      61                 :            : 
      62         [ #  # ]:          0 :         aead_request_set_tfm(subreq, ctx->child);
      63                 :            : 
      64                 :          0 :         compl = req->base.complete;
      65                 :          0 :         data = req->base.data;
      66                 :          0 :         info = req->iv;
      67                 :            : 
      68         [ #  # ]:          0 :         if (req->src != req->dst) {
      69                 :          0 :                 SYNC_SKCIPHER_REQUEST_ON_STACK(nreq, ctx->sknull);
      70                 :            : 
      71                 :          0 :                 skcipher_request_set_sync_tfm(nreq, ctx->sknull);
      72                 :          0 :                 skcipher_request_set_callback(nreq, req->base.flags,
      73                 :            :                                               NULL, NULL);
      74                 :          0 :                 skcipher_request_set_crypt(nreq, req->src, req->dst,
      75                 :          0 :                                            req->assoclen + req->cryptlen,
      76                 :            :                                            NULL);
      77                 :            : 
      78                 :          0 :                 err = crypto_skcipher_encrypt(nreq);
      79         [ #  # ]:          0 :                 if (err)
      80                 :          0 :                         return err;
      81                 :            :         }
      82                 :            : 
      83         [ #  # ]:          0 :         if (unlikely(!IS_ALIGNED((unsigned long)info,
      84                 :            :                                  crypto_aead_alignmask(geniv) + 1))) {
      85         [ #  # ]:          0 :                 info = kmemdup(req->iv, ivsize, req->base.flags &
      86                 :            :                                CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
      87                 :            :                                GFP_ATOMIC);
      88         [ #  # ]:          0 :                 if (!info)
      89                 :            :                         return -ENOMEM;
      90                 :            : 
      91                 :            :                 compl = seqiv_aead_encrypt_complete;
      92                 :            :                 data = req;
      93                 :            :         }
      94                 :            : 
      95                 :          0 :         aead_request_set_callback(subreq, req->base.flags, compl, data);
      96                 :          0 :         aead_request_set_crypt(subreq, req->dst, req->dst,
      97                 :          0 :                                req->cryptlen - ivsize, info);
      98                 :          0 :         aead_request_set_ad(subreq, req->assoclen + ivsize);
      99                 :            : 
     100                 :          0 :         crypto_xor(info, ctx->salt, ivsize);
     101                 :          0 :         scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1);
     102                 :            : 
     103                 :          0 :         err = crypto_aead_encrypt(subreq);
     104         [ #  # ]:          0 :         if (unlikely(info != req->iv))
     105                 :          0 :                 seqiv_aead_encrypt_complete2(req, err);
     106                 :            :         return err;
     107                 :            : }
     108                 :            : 
     109                 :          0 : static int seqiv_aead_decrypt(struct aead_request *req)
     110                 :            : {
     111         [ #  # ]:          0 :         struct crypto_aead *geniv = crypto_aead_reqtfm(req);
     112         [ #  # ]:          0 :         struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
     113         [ #  # ]:          0 :         struct aead_request *subreq = aead_request_ctx(req);
     114                 :          0 :         crypto_completion_t compl;
     115                 :          0 :         void *data;
     116                 :          0 :         unsigned int ivsize = 8;
     117                 :            : 
     118         [ #  # ]:          0 :         if (req->cryptlen < ivsize + crypto_aead_authsize(geniv))
     119                 :            :                 return -EINVAL;
     120                 :            : 
     121                 :          0 :         aead_request_set_tfm(subreq, ctx->child);
     122                 :            : 
     123                 :          0 :         compl = req->base.complete;
     124                 :          0 :         data = req->base.data;
     125                 :            : 
     126                 :          0 :         aead_request_set_callback(subreq, req->base.flags, compl, data);
     127                 :          0 :         aead_request_set_crypt(subreq, req->src, req->dst,
     128                 :            :                                req->cryptlen - ivsize, req->iv);
     129                 :          0 :         aead_request_set_ad(subreq, req->assoclen + ivsize);
     130                 :            : 
     131                 :          0 :         scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0);
     132                 :            : 
     133                 :          0 :         return crypto_aead_decrypt(subreq);
     134                 :            : }
     135                 :            : 
     136                 :          0 : static int seqiv_aead_create(struct crypto_template *tmpl, struct rtattr **tb)
     137                 :            : {
     138                 :          0 :         struct aead_instance *inst;
     139                 :          0 :         int err;
     140                 :            : 
     141                 :          0 :         inst = aead_geniv_alloc(tmpl, tb, 0, 0);
     142                 :            : 
     143         [ #  # ]:          0 :         if (IS_ERR(inst))
     144                 :          0 :                 return PTR_ERR(inst);
     145                 :            : 
     146                 :          0 :         err = -EINVAL;
     147         [ #  # ]:          0 :         if (inst->alg.ivsize != sizeof(u64))
     148                 :          0 :                 goto free_inst;
     149                 :            : 
     150                 :          0 :         inst->alg.encrypt = seqiv_aead_encrypt;
     151                 :          0 :         inst->alg.decrypt = seqiv_aead_decrypt;
     152                 :            : 
     153                 :          0 :         inst->alg.init = aead_init_geniv;
     154                 :          0 :         inst->alg.exit = aead_exit_geniv;
     155                 :            : 
     156                 :          0 :         inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx);
     157                 :          0 :         inst->alg.base.cra_ctxsize += inst->alg.ivsize;
     158                 :            : 
     159                 :          0 :         err = aead_register_instance(tmpl, inst);
     160         [ #  # ]:          0 :         if (err) {
     161                 :          0 : free_inst:
     162                 :          0 :                 inst->free(inst);
     163                 :            :         }
     164                 :            :         return err;
     165                 :            : }
     166                 :            : 
     167                 :          0 : static int seqiv_create(struct crypto_template *tmpl, struct rtattr **tb)
     168                 :            : {
     169                 :          0 :         struct crypto_attr_type *algt;
     170                 :            : 
     171                 :          0 :         algt = crypto_get_attr_type(tb);
     172         [ #  # ]:          0 :         if (IS_ERR(algt))
     173                 :          0 :                 return PTR_ERR(algt);
     174                 :            : 
     175         [ #  # ]:          0 :         if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK)
     176                 :            :                 return -EINVAL;
     177                 :            : 
     178                 :          0 :         return seqiv_aead_create(tmpl, tb);
     179                 :            : }
     180                 :            : 
     181                 :            : static struct crypto_template seqiv_tmpl = {
     182                 :            :         .name = "seqiv",
     183                 :            :         .create = seqiv_create,
     184                 :            :         .module = THIS_MODULE,
     185                 :            : };
     186                 :            : 
     187                 :          3 : static int __init seqiv_module_init(void)
     188                 :            : {
     189                 :          3 :         return crypto_register_template(&seqiv_tmpl);
     190                 :            : }
     191                 :            : 
     192                 :          0 : static void __exit seqiv_module_exit(void)
     193                 :            : {
     194                 :          0 :         crypto_unregister_template(&seqiv_tmpl);
     195                 :          0 : }
     196                 :            : 
     197                 :            : subsys_initcall(seqiv_module_init);
     198                 :            : module_exit(seqiv_module_exit);
     199                 :            : 
     200                 :            : MODULE_LICENSE("GPL");
     201                 :            : MODULE_DESCRIPTION("Sequence Number IV Generator");
     202                 :            : MODULE_ALIAS_CRYPTO("seqiv");

Generated by: LCOV version 1.14