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/ctr.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  * CTR: Counter mode
    3  *
    4  * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
    5  *
    6  * This program is free software; you can redistribute it and/or modify it
    7  * under the terms of the GNU General Public License as published by the Free
    8  * Software Foundation; either version 2 of the License, or (at your option)
    9  * any later version.
   10  *
   11  */
   12 
   13 #include <crypto/algapi.h>
   14 #include <crypto/ctr.h>
   15 #include <linux/err.h>
   16 #include <linux/init.h>
   17 #include <linux/kernel.h>
   18 #include <linux/module.h>
   19 #include <linux/random.h>
   20 #include <linux/scatterlist.h>
   21 #include <linux/slab.h>
   22 
   23 struct crypto_ctr_ctx {
   24         struct crypto_cipher *child;
   25 };
   26 
   27 struct crypto_rfc3686_ctx {
   28         struct crypto_blkcipher *child;
   29         u8 nonce[CTR_RFC3686_NONCE_SIZE];
   30 };
   31 
   32 static int crypto_ctr_setkey(struct crypto_tfm *parent, const u8 *key,
   33                              unsigned int keylen)
   34 {
   35         struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(parent);
   36         struct crypto_cipher *child = ctx->child;
   37         int err;
   38 
   39         crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
   40         crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
   41                                 CRYPTO_TFM_REQ_MASK);
   42         err = crypto_cipher_setkey(child, key, keylen);
   43         crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
   44                              CRYPTO_TFM_RES_MASK);
   45 
   46         return err;
   47 }
   48 
   49 static void crypto_ctr_crypt_final(struct blkcipher_walk *walk,
   50                                    struct crypto_cipher *tfm)
   51 {
   52         unsigned int bsize = crypto_cipher_blocksize(tfm);
   53         unsigned long alignmask = crypto_cipher_alignmask(tfm);
   54         u8 *ctrblk = walk->iv;
   55         u8 tmp[bsize + alignmask];
   56         u8 *keystream = PTR_ALIGN(tmp + 0, alignmask + 1);
   57         u8 *src = walk->src.virt.addr;
   58         u8 *dst = walk->dst.virt.addr;
   59         unsigned int nbytes = walk->nbytes;
   60 
   61         crypto_cipher_encrypt_one(tfm, keystream, ctrblk);
   62         crypto_xor(keystream, src, nbytes);
   63         memcpy(dst, keystream, nbytes);
   64 
   65         crypto_inc(ctrblk, bsize);
   66 }
   67 
   68 static int crypto_ctr_crypt_segment(struct blkcipher_walk *walk,
   69                                     struct crypto_cipher *tfm)
   70 {
   71         void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
   72                    crypto_cipher_alg(tfm)->cia_encrypt;
   73         unsigned int bsize = crypto_cipher_blocksize(tfm);
   74         u8 *ctrblk = walk->iv;
   75         u8 *src = walk->src.virt.addr;
   76         u8 *dst = walk->dst.virt.addr;
   77         unsigned int nbytes = walk->nbytes;
   78 
   79         do {
   80                 /* create keystream */
   81                 fn(crypto_cipher_tfm(tfm), dst, ctrblk);
   82                 crypto_xor(dst, src, bsize);
   83 
   84                 /* increment counter in counterblock */
   85                 crypto_inc(ctrblk, bsize);
   86 
   87                 src += bsize;
   88                 dst += bsize;
   89         } while ((nbytes -= bsize) >= bsize);
   90 
   91         return nbytes;
   92 }
   93 
   94 static int crypto_ctr_crypt_inplace(struct blkcipher_walk *walk,
   95                                     struct crypto_cipher *tfm)
   96 {
   97         void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
   98                    crypto_cipher_alg(tfm)->cia_encrypt;
   99         unsigned int bsize = crypto_cipher_blocksize(tfm);
  100         unsigned long alignmask = crypto_cipher_alignmask(tfm);
  101         unsigned int nbytes = walk->nbytes;
  102         u8 *ctrblk = walk->iv;
  103         u8 *src = walk->src.virt.addr;
  104         u8 tmp[bsize + alignmask];
  105         u8 *keystream = PTR_ALIGN(tmp + 0, alignmask + 1);
  106 
  107         do {
  108                 /* create keystream */
  109                 fn(crypto_cipher_tfm(tfm), keystream, ctrblk);
  110                 crypto_xor(src, keystream, bsize);
  111 
  112                 /* increment counter in counterblock */
  113                 crypto_inc(ctrblk, bsize);
  114 
  115                 src += bsize;
  116         } while ((nbytes -= bsize) >= bsize);
  117 
  118         return nbytes;
  119 }
  120 
  121 static int crypto_ctr_crypt(struct blkcipher_desc *desc,
  122                               struct scatterlist *dst, struct scatterlist *src,
  123                               unsigned int nbytes)
  124 {
  125         struct blkcipher_walk walk;
  126         struct crypto_blkcipher *tfm = desc->tfm;
  127         struct crypto_ctr_ctx *ctx = crypto_blkcipher_ctx(tfm);
  128         struct crypto_cipher *child = ctx->child;
  129         unsigned int bsize = crypto_cipher_blocksize(child);
  130         int err;
  131 
  132         blkcipher_walk_init(&walk, dst, src, nbytes);
  133         err = blkcipher_walk_virt_block(desc, &walk, bsize);
  134 
  135         while (walk.nbytes >= bsize) {
  136                 if (walk.src.virt.addr == walk.dst.virt.addr)
  137                         nbytes = crypto_ctr_crypt_inplace(&walk, child);
  138                 else
  139                         nbytes = crypto_ctr_crypt_segment(&walk, child);
  140 
  141                 err = blkcipher_walk_done(desc, &walk, nbytes);
  142         }
  143 
  144         if (walk.nbytes) {
  145                 crypto_ctr_crypt_final(&walk, child);
  146                 err = blkcipher_walk_done(desc, &walk, 0);
  147         }
  148 
  149         return err;
  150 }
  151 
  152 static int crypto_ctr_init_tfm(struct crypto_tfm *tfm)
  153 {
  154         struct crypto_instance *inst = (void *)tfm->__crt_alg;
  155         struct crypto_spawn *spawn = crypto_instance_ctx(inst);
  156         struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(tfm);
  157         struct crypto_cipher *cipher;
  158 
  159         cipher = crypto_spawn_cipher(spawn);
  160         if (IS_ERR(cipher))
  161                 return PTR_ERR(cipher);
  162 
  163         ctx->child = cipher;
  164 
  165         return 0;
  166 }
  167 
  168 static void crypto_ctr_exit_tfm(struct crypto_tfm *tfm)
  169 {
  170         struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(tfm);
  171 
  172         crypto_free_cipher(ctx->child);
  173 }
  174 
  175 static struct crypto_instance *crypto_ctr_alloc(struct rtattr **tb)
  176 {
  177         struct crypto_instance *inst;
  178         struct crypto_alg *alg;
  179         int err;
  180 
  181         err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
  182         if (err)
  183                 return ERR_PTR(err);
  184 
  185         alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER,
  186                                   CRYPTO_ALG_TYPE_MASK);
  187         if (IS_ERR(alg))
  188                 return ERR_CAST(alg);
  189 
  190         /* Block size must be >= 4 bytes. */
  191         err = -EINVAL;
  192         if (alg->cra_blocksize < 4)
  193                 goto out_put_alg;
  194 
  195         /* If this is false we'd fail the alignment of crypto_inc. */
  196         if (alg->cra_blocksize % 4)
  197                 goto out_put_alg;
  198 
  199         inst = crypto_alloc_instance("ctr", alg);
  200         if (IS_ERR(inst))
  201                 goto out;
  202 
  203         inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
  204         inst->alg.cra_priority = alg->cra_priority;
  205         inst->alg.cra_blocksize = 1;
  206         inst->alg.cra_alignmask = alg->cra_alignmask | (__alignof__(u32) - 1);
  207         inst->alg.cra_type = &crypto_blkcipher_type;
  208 
  209         inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
  210         inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
  211         inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
  212 
  213         inst->alg.cra_ctxsize = sizeof(struct crypto_ctr_ctx);
  214 
  215         inst->alg.cra_init = crypto_ctr_init_tfm;
  216         inst->alg.cra_exit = crypto_ctr_exit_tfm;
  217 
  218         inst->alg.cra_blkcipher.setkey = crypto_ctr_setkey;
  219         inst->alg.cra_blkcipher.encrypt = crypto_ctr_crypt;
  220         inst->alg.cra_blkcipher.decrypt = crypto_ctr_crypt;
  221 
  222         inst->alg.cra_blkcipher.geniv = "chainiv";
  223 
  224 out:
  225         crypto_mod_put(alg);
  226         return inst;
  227 
  228 out_put_alg:
  229         inst = ERR_PTR(err);
  230         goto out;
  231 }
  232 
  233 static void crypto_ctr_free(struct crypto_instance *inst)
  234 {
  235         crypto_drop_spawn(crypto_instance_ctx(inst));
  236         kfree(inst);
  237 }
  238 
  239 static struct crypto_template crypto_ctr_tmpl = {
  240         .name = "ctr",
  241         .alloc = crypto_ctr_alloc,
  242         .free = crypto_ctr_free,
  243         .module = THIS_MODULE,
  244 };
  245 
  246 static int crypto_rfc3686_setkey(struct crypto_tfm *parent, const u8 *key,
  247                                  unsigned int keylen)
  248 {
  249         struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(parent);
  250         struct crypto_blkcipher *child = ctx->child;
  251         int err;
  252 
  253         /* the nonce is stored in bytes at end of key */
  254         if (keylen < CTR_RFC3686_NONCE_SIZE)
  255                 return -EINVAL;
  256 
  257         memcpy(ctx->nonce, key + (keylen - CTR_RFC3686_NONCE_SIZE),
  258                CTR_RFC3686_NONCE_SIZE);
  259 
  260         keylen -= CTR_RFC3686_NONCE_SIZE;
  261 
  262         crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
  263         crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
  264                                           CRYPTO_TFM_REQ_MASK);
  265         err = crypto_blkcipher_setkey(child, key, keylen);
  266         crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
  267                                      CRYPTO_TFM_RES_MASK);
  268 
  269         return err;
  270 }
  271 
  272 static int crypto_rfc3686_crypt(struct blkcipher_desc *desc,
  273                                 struct scatterlist *dst,
  274                                 struct scatterlist *src, unsigned int nbytes)
  275 {
  276         struct crypto_blkcipher *tfm = desc->tfm;
  277         struct crypto_rfc3686_ctx *ctx = crypto_blkcipher_ctx(tfm);
  278         struct crypto_blkcipher *child = ctx->child;
  279         unsigned long alignmask = crypto_blkcipher_alignmask(tfm);
  280         u8 ivblk[CTR_RFC3686_BLOCK_SIZE + alignmask];
  281         u8 *iv = PTR_ALIGN(ivblk + 0, alignmask + 1);
  282         u8 *info = desc->info;
  283         int err;
  284 
  285         /* set up counter block */
  286         memcpy(iv, ctx->nonce, CTR_RFC3686_NONCE_SIZE);
  287         memcpy(iv + CTR_RFC3686_NONCE_SIZE, info, CTR_RFC3686_IV_SIZE);
  288 
  289         /* initialize counter portion of counter block */
  290         *(__be32 *)(iv + CTR_RFC3686_NONCE_SIZE + CTR_RFC3686_IV_SIZE) =
  291                 cpu_to_be32(1);
  292 
  293         desc->tfm = child;
  294         desc->info = iv;
  295         err = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
  296         desc->tfm = tfm;
  297         desc->info = info;
  298 
  299         return err;
  300 }
  301 
  302 static int crypto_rfc3686_init_tfm(struct crypto_tfm *tfm)
  303 {
  304         struct crypto_instance *inst = (void *)tfm->__crt_alg;
  305         struct crypto_spawn *spawn = crypto_instance_ctx(inst);
  306         struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
  307         struct crypto_blkcipher *cipher;
  308 
  309         cipher = crypto_spawn_blkcipher(spawn);
  310         if (IS_ERR(cipher))
  311                 return PTR_ERR(cipher);
  312 
  313         ctx->child = cipher;
  314 
  315         return 0;
  316 }
  317 
  318 static void crypto_rfc3686_exit_tfm(struct crypto_tfm *tfm)
  319 {
  320         struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
  321 
  322         crypto_free_blkcipher(ctx->child);
  323 }
  324 
  325 static struct crypto_instance *crypto_rfc3686_alloc(struct rtattr **tb)
  326 {
  327         struct crypto_instance *inst;
  328         struct crypto_alg *alg;
  329         int err;
  330 
  331         err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
  332         if (err)
  333                 return ERR_PTR(err);
  334 
  335         alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER,
  336                                   CRYPTO_ALG_TYPE_MASK);
  337         err = PTR_ERR(alg);
  338         if (IS_ERR(alg))
  339                 return ERR_PTR(err);
  340 
  341         /* We only support 16-byte blocks. */
  342         err = -EINVAL;
  343         if (alg->cra_blkcipher.ivsize != CTR_RFC3686_BLOCK_SIZE)
  344                 goto out_put_alg;
  345 
  346         /* Not a stream cipher? */
  347         if (alg->cra_blocksize != 1)
  348                 goto out_put_alg;
  349 
  350         inst = crypto_alloc_instance("rfc3686", alg);
  351         if (IS_ERR(inst))
  352                 goto out;
  353 
  354         inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
  355         inst->alg.cra_priority = alg->cra_priority;
  356         inst->alg.cra_blocksize = 1;
  357         inst->alg.cra_alignmask = alg->cra_alignmask;
  358         inst->alg.cra_type = &crypto_blkcipher_type;
  359 
  360         inst->alg.cra_blkcipher.ivsize = CTR_RFC3686_IV_SIZE;
  361         inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize
  362                                               + CTR_RFC3686_NONCE_SIZE;
  363         inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize
  364                                               + CTR_RFC3686_NONCE_SIZE;
  365 
  366         inst->alg.cra_blkcipher.geniv = "seqiv";
  367 
  368         inst->alg.cra_ctxsize = sizeof(struct crypto_rfc3686_ctx);
  369 
  370         inst->alg.cra_init = crypto_rfc3686_init_tfm;
  371         inst->alg.cra_exit = crypto_rfc3686_exit_tfm;
  372 
  373         inst->alg.cra_blkcipher.setkey = crypto_rfc3686_setkey;
  374         inst->alg.cra_blkcipher.encrypt = crypto_rfc3686_crypt;
  375         inst->alg.cra_blkcipher.decrypt = crypto_rfc3686_crypt;
  376 
  377 out:
  378         crypto_mod_put(alg);
  379         return inst;
  380 
  381 out_put_alg:
  382         inst = ERR_PTR(err);
  383         goto out;
  384 }
  385 
  386 static struct crypto_template crypto_rfc3686_tmpl = {
  387         .name = "rfc3686",
  388         .alloc = crypto_rfc3686_alloc,
  389         .free = crypto_ctr_free,
  390         .module = THIS_MODULE,
  391 };
  392 
  393 static int __init crypto_ctr_module_init(void)
  394 {
  395         int err;
  396 
  397         err = crypto_register_template(&crypto_ctr_tmpl);
  398         if (err)
  399                 goto out;
  400 
  401         err = crypto_register_template(&crypto_rfc3686_tmpl);
  402         if (err)
  403                 goto out_drop_ctr;
  404 
  405 out:
  406         return err;
  407 
  408 out_drop_ctr:
  409         crypto_unregister_template(&crypto_ctr_tmpl);
  410         goto out;
  411 }
  412 
  413 static void __exit crypto_ctr_module_exit(void)
  414 {
  415         crypto_unregister_template(&crypto_rfc3686_tmpl);
  416         crypto_unregister_template(&crypto_ctr_tmpl);
  417 }
  418 
  419 module_init(crypto_ctr_module_init);
  420 module_exit(crypto_ctr_module_exit);
  421 
  422 MODULE_LICENSE("GPL");
  423 MODULE_DESCRIPTION("CTR Counter block mode");
  424 MODULE_ALIAS("rfc3686");

Cache object: 16d7c17a7d91ba458f7d618f73ca0d7e


[ 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.