LCOV - code coverage report
Current view: top level - crypto - echainiv.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 2 76 2.6 %
Date: 2022-04-01 14:35:51 Functions: 1 5 20.0 %
Branches: 0 36 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  * echainiv: Encrypted Chain IV Generator
       4                 :            :  *
       5                 :            :  * This generator generates an IV based on a sequence number by multiplying
       6                 :            :  * it with a salt and then encrypting it with the same key as used to encrypt
       7                 :            :  * the plain text.  This algorithm requires that the block size be equal
       8                 :            :  * to the IV size.  It is mainly useful for CBC.
       9                 :            :  *
      10                 :            :  * This generator can only be used by algorithms where authentication
      11                 :            :  * is performed after encryption (i.e., authenc).
      12                 :            :  *
      13                 :            :  * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au>
      14                 :            :  */
      15                 :            : 
      16                 :            : #include <crypto/internal/geniv.h>
      17                 :            : #include <crypto/scatterwalk.h>
      18                 :            : #include <crypto/skcipher.h>
      19                 :            : #include <linux/err.h>
      20                 :            : #include <linux/init.h>
      21                 :            : #include <linux/kernel.h>
      22                 :            : #include <linux/module.h>
      23                 :            : #include <linux/slab.h>
      24                 :            : #include <linux/string.h>
      25                 :            : 
      26                 :          0 : static int echainiv_encrypt(struct aead_request *req)
      27                 :            : {
      28         [ #  # ]:          0 :         struct crypto_aead *geniv = crypto_aead_reqtfm(req);
      29         [ #  # ]:          0 :         struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
      30         [ #  # ]:          0 :         struct aead_request *subreq = aead_request_ctx(req);
      31                 :          0 :         __be64 nseqno;
      32                 :          0 :         u64 seqno;
      33                 :          0 :         u8 *info;
      34         [ #  # ]:          0 :         unsigned int ivsize = crypto_aead_ivsize(geniv);
      35                 :          0 :         int err;
      36                 :            : 
      37         [ #  # ]:          0 :         if (req->cryptlen < ivsize)
      38                 :            :                 return -EINVAL;
      39                 :            : 
      40         [ #  # ]:          0 :         aead_request_set_tfm(subreq, ctx->child);
      41                 :            : 
      42                 :          0 :         info = req->iv;
      43                 :            : 
      44         [ #  # ]:          0 :         if (req->src != req->dst) {
      45                 :          0 :                 SYNC_SKCIPHER_REQUEST_ON_STACK(nreq, ctx->sknull);
      46                 :            : 
      47                 :          0 :                 skcipher_request_set_sync_tfm(nreq, ctx->sknull);
      48                 :          0 :                 skcipher_request_set_callback(nreq, req->base.flags,
      49                 :            :                                               NULL, NULL);
      50                 :          0 :                 skcipher_request_set_crypt(nreq, req->src, req->dst,
      51                 :          0 :                                            req->assoclen + req->cryptlen,
      52                 :            :                                            NULL);
      53                 :            : 
      54                 :          0 :                 err = crypto_skcipher_encrypt(nreq);
      55         [ #  # ]:          0 :                 if (err)
      56                 :          0 :                         return err;
      57                 :            :         }
      58                 :            : 
      59                 :          0 :         aead_request_set_callback(subreq, req->base.flags,
      60                 :            :                                   req->base.complete, req->base.data);
      61                 :          0 :         aead_request_set_crypt(subreq, req->dst, req->dst,
      62                 :            :                                req->cryptlen, info);
      63                 :          0 :         aead_request_set_ad(subreq, req->assoclen);
      64                 :            : 
      65                 :          0 :         memcpy(&nseqno, info + ivsize - 8, 8);
      66                 :          0 :         seqno = be64_to_cpu(nseqno);
      67                 :          0 :         memset(info, 0, ivsize);
      68                 :            : 
      69                 :          0 :         scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1);
      70                 :            : 
      71                 :          0 :         do {
      72                 :          0 :                 u64 a;
      73                 :            : 
      74                 :          0 :                 memcpy(&a, ctx->salt + ivsize - 8, 8);
      75                 :            : 
      76                 :          0 :                 a |= 1;
      77                 :          0 :                 a *= seqno;
      78                 :            : 
      79                 :          0 :                 memcpy(info + ivsize - 8, &a, 8);
      80         [ #  # ]:          0 :         } while ((ivsize -= 8));
      81                 :            : 
      82                 :          0 :         return crypto_aead_encrypt(subreq);
      83                 :            : }
      84                 :            : 
      85                 :          0 : static int echainiv_decrypt(struct aead_request *req)
      86                 :            : {
      87         [ #  # ]:          0 :         struct crypto_aead *geniv = crypto_aead_reqtfm(req);
      88         [ #  # ]:          0 :         struct aead_geniv_ctx *ctx = crypto_aead_ctx(geniv);
      89         [ #  # ]:          0 :         struct aead_request *subreq = aead_request_ctx(req);
      90                 :          0 :         crypto_completion_t compl;
      91                 :          0 :         void *data;
      92         [ #  # ]:          0 :         unsigned int ivsize = crypto_aead_ivsize(geniv);
      93                 :            : 
      94         [ #  # ]:          0 :         if (req->cryptlen < ivsize)
      95                 :            :                 return -EINVAL;
      96                 :            : 
      97                 :          0 :         aead_request_set_tfm(subreq, ctx->child);
      98                 :            : 
      99                 :          0 :         compl = req->base.complete;
     100                 :          0 :         data = req->base.data;
     101                 :            : 
     102                 :          0 :         aead_request_set_callback(subreq, req->base.flags, compl, data);
     103                 :          0 :         aead_request_set_crypt(subreq, req->src, req->dst,
     104                 :            :                                req->cryptlen - ivsize, req->iv);
     105                 :          0 :         aead_request_set_ad(subreq, req->assoclen + ivsize);
     106                 :            : 
     107                 :          0 :         scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0);
     108                 :            : 
     109                 :          0 :         return crypto_aead_decrypt(subreq);
     110                 :            : }
     111                 :            : 
     112                 :          0 : static int echainiv_aead_create(struct crypto_template *tmpl,
     113                 :            :                                 struct rtattr **tb)
     114                 :            : {
     115                 :          0 :         struct aead_instance *inst;
     116                 :          0 :         int err;
     117                 :            : 
     118                 :          0 :         inst = aead_geniv_alloc(tmpl, tb, 0, 0);
     119                 :            : 
     120         [ #  # ]:          0 :         if (IS_ERR(inst))
     121                 :          0 :                 return PTR_ERR(inst);
     122                 :            : 
     123                 :          0 :         err = -EINVAL;
     124   [ #  #  #  # ]:          0 :         if (inst->alg.ivsize & (sizeof(u64) - 1) || !inst->alg.ivsize)
     125                 :          0 :                 goto free_inst;
     126                 :            : 
     127                 :          0 :         inst->alg.encrypt = echainiv_encrypt;
     128                 :          0 :         inst->alg.decrypt = echainiv_decrypt;
     129                 :            : 
     130                 :          0 :         inst->alg.init = aead_init_geniv;
     131                 :          0 :         inst->alg.exit = aead_exit_geniv;
     132                 :            : 
     133                 :          0 :         inst->alg.base.cra_ctxsize = sizeof(struct aead_geniv_ctx);
     134                 :          0 :         inst->alg.base.cra_ctxsize += inst->alg.ivsize;
     135                 :            : 
     136                 :          0 :         err = aead_register_instance(tmpl, inst);
     137         [ #  # ]:          0 :         if (err) {
     138                 :          0 : free_inst:
     139                 :          0 :                 inst->free(inst);
     140                 :            :         }
     141                 :            :         return err;
     142                 :            : }
     143                 :            : 
     144                 :            : static struct crypto_template echainiv_tmpl = {
     145                 :            :         .name = "echainiv",
     146                 :            :         .create = echainiv_aead_create,
     147                 :            :         .module = THIS_MODULE,
     148                 :            : };
     149                 :            : 
     150                 :         21 : static int __init echainiv_module_init(void)
     151                 :            : {
     152                 :         21 :         return crypto_register_template(&echainiv_tmpl);
     153                 :            : }
     154                 :            : 
     155                 :          0 : static void __exit echainiv_module_exit(void)
     156                 :            : {
     157                 :          0 :         crypto_unregister_template(&echainiv_tmpl);
     158                 :          0 : }
     159                 :            : 
     160                 :            : subsys_initcall(echainiv_module_init);
     161                 :            : module_exit(echainiv_module_exit);
     162                 :            : 
     163                 :            : MODULE_LICENSE("GPL");
     164                 :            : MODULE_DESCRIPTION("Encrypted Chain IV Generator");
     165                 :            : MODULE_ALIAS_CRYPTO("echainiv");

Generated by: LCOV version 1.14