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/xcbc.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  * Copyright (C)2006 USAGI/WIDE Project
    3  *
    4  * This program is free software; you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation; either version 2 of the License, or
    7  * (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   17  *
   18  * Author:
   19  *      Kazunori Miyazawa <miyazawa@linux-ipv6.org>
   20  */
   21 
   22 #include <crypto/internal/hash.h>
   23 #include <linux/err.h>
   24 #include <linux/kernel.h>
   25 #include <linux/module.h>
   26 
   27 static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
   28                            0x02020202, 0x02020202, 0x02020202, 0x02020202,
   29                            0x03030303, 0x03030303, 0x03030303, 0x03030303};
   30 
   31 /*
   32  * +------------------------
   33  * | <parent tfm>
   34  * +------------------------
   35  * | xcbc_tfm_ctx
   36  * +------------------------
   37  * | consts (block size * 2)
   38  * +------------------------
   39  */
   40 struct xcbc_tfm_ctx {
   41         struct crypto_cipher *child;
   42         u8 ctx[];
   43 };
   44 
   45 /*
   46  * +------------------------
   47  * | <shash desc>
   48  * +------------------------
   49  * | xcbc_desc_ctx
   50  * +------------------------
   51  * | odds (block size)
   52  * +------------------------
   53  * | prev (block size)
   54  * +------------------------
   55  */
   56 struct xcbc_desc_ctx {
   57         unsigned int len;
   58         u8 ctx[];
   59 };
   60 
   61 static int crypto_xcbc_digest_setkey(struct crypto_shash *parent,
   62                                      const u8 *inkey, unsigned int keylen)
   63 {
   64         unsigned long alignmask = crypto_shash_alignmask(parent);
   65         struct xcbc_tfm_ctx *ctx = crypto_shash_ctx(parent);
   66         int bs = crypto_shash_blocksize(parent);
   67         u8 *consts = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
   68         int err = 0;
   69         u8 key1[bs];
   70 
   71         if ((err = crypto_cipher_setkey(ctx->child, inkey, keylen)))
   72                 return err;
   73 
   74         crypto_cipher_encrypt_one(ctx->child, consts, (u8 *)ks + bs);
   75         crypto_cipher_encrypt_one(ctx->child, consts + bs, (u8 *)ks + bs * 2);
   76         crypto_cipher_encrypt_one(ctx->child, key1, (u8 *)ks);
   77 
   78         return crypto_cipher_setkey(ctx->child, key1, bs);
   79 
   80 }
   81 
   82 static int crypto_xcbc_digest_init(struct shash_desc *pdesc)
   83 {
   84         unsigned long alignmask = crypto_shash_alignmask(pdesc->tfm);
   85         struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
   86         int bs = crypto_shash_blocksize(pdesc->tfm);
   87         u8 *prev = PTR_ALIGN(&ctx->ctx[0], alignmask + 1) + bs;
   88 
   89         ctx->len = 0;
   90         memset(prev, 0, bs);
   91 
   92         return 0;
   93 }
   94 
   95 static int crypto_xcbc_digest_update(struct shash_desc *pdesc, const u8 *p,
   96                                      unsigned int len)
   97 {
   98         struct crypto_shash *parent = pdesc->tfm;
   99         unsigned long alignmask = crypto_shash_alignmask(parent);
  100         struct xcbc_tfm_ctx *tctx = crypto_shash_ctx(parent);
  101         struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
  102         struct crypto_cipher *tfm = tctx->child;
  103         int bs = crypto_shash_blocksize(parent);
  104         u8 *odds = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
  105         u8 *prev = odds + bs;
  106 
  107         /* checking the data can fill the block */
  108         if ((ctx->len + len) <= bs) {
  109                 memcpy(odds + ctx->len, p, len);
  110                 ctx->len += len;
  111                 return 0;
  112         }
  113 
  114         /* filling odds with new data and encrypting it */
  115         memcpy(odds + ctx->len, p, bs - ctx->len);
  116         len -= bs - ctx->len;
  117         p += bs - ctx->len;
  118 
  119         crypto_xor(prev, odds, bs);
  120         crypto_cipher_encrypt_one(tfm, prev, prev);
  121 
  122         /* clearing the length */
  123         ctx->len = 0;
  124 
  125         /* encrypting the rest of data */
  126         while (len > bs) {
  127                 crypto_xor(prev, p, bs);
  128                 crypto_cipher_encrypt_one(tfm, prev, prev);
  129                 p += bs;
  130                 len -= bs;
  131         }
  132 
  133         /* keeping the surplus of blocksize */
  134         if (len) {
  135                 memcpy(odds, p, len);
  136                 ctx->len = len;
  137         }
  138 
  139         return 0;
  140 }
  141 
  142 static int crypto_xcbc_digest_final(struct shash_desc *pdesc, u8 *out)
  143 {
  144         struct crypto_shash *parent = pdesc->tfm;
  145         unsigned long alignmask = crypto_shash_alignmask(parent);
  146         struct xcbc_tfm_ctx *tctx = crypto_shash_ctx(parent);
  147         struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
  148         struct crypto_cipher *tfm = tctx->child;
  149         int bs = crypto_shash_blocksize(parent);
  150         u8 *consts = PTR_ALIGN(&tctx->ctx[0], alignmask + 1);
  151         u8 *odds = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
  152         u8 *prev = odds + bs;
  153         unsigned int offset = 0;
  154 
  155         if (ctx->len != bs) {
  156                 unsigned int rlen;
  157                 u8 *p = odds + ctx->len;
  158 
  159                 *p = 0x80;
  160                 p++;
  161 
  162                 rlen = bs - ctx->len -1;
  163                 if (rlen)
  164                         memset(p, 0, rlen);
  165 
  166                 offset += bs;
  167         }
  168 
  169         crypto_xor(prev, odds, bs);
  170         crypto_xor(prev, consts + offset, bs);
  171 
  172         crypto_cipher_encrypt_one(tfm, out, prev);
  173 
  174         return 0;
  175 }
  176 
  177 static int xcbc_init_tfm(struct crypto_tfm *tfm)
  178 {
  179         struct crypto_cipher *cipher;
  180         struct crypto_instance *inst = (void *)tfm->__crt_alg;
  181         struct crypto_spawn *spawn = crypto_instance_ctx(inst);
  182         struct xcbc_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
  183 
  184         cipher = crypto_spawn_cipher(spawn);
  185         if (IS_ERR(cipher))
  186                 return PTR_ERR(cipher);
  187 
  188         ctx->child = cipher;
  189 
  190         return 0;
  191 };
  192 
  193 static void xcbc_exit_tfm(struct crypto_tfm *tfm)
  194 {
  195         struct xcbc_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
  196         crypto_free_cipher(ctx->child);
  197 }
  198 
  199 static int xcbc_create(struct crypto_template *tmpl, struct rtattr **tb)
  200 {
  201         struct shash_instance *inst;
  202         struct crypto_alg *alg;
  203         unsigned long alignmask;
  204         int err;
  205 
  206         err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH);
  207         if (err)
  208                 return err;
  209 
  210         alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
  211                                   CRYPTO_ALG_TYPE_MASK);
  212         if (IS_ERR(alg))
  213                 return PTR_ERR(alg);
  214 
  215         switch(alg->cra_blocksize) {
  216         case 16:
  217                 break;
  218         default:
  219                 goto out_put_alg;
  220         }
  221 
  222         inst = shash_alloc_instance("xcbc", alg);
  223         err = PTR_ERR(inst);
  224         if (IS_ERR(inst))
  225                 goto out_put_alg;
  226 
  227         err = crypto_init_spawn(shash_instance_ctx(inst), alg,
  228                                 shash_crypto_instance(inst),
  229                                 CRYPTO_ALG_TYPE_MASK);
  230         if (err)
  231                 goto out_free_inst;
  232 
  233         alignmask = alg->cra_alignmask | 3;
  234         inst->alg.base.cra_alignmask = alignmask;
  235         inst->alg.base.cra_priority = alg->cra_priority;
  236         inst->alg.base.cra_blocksize = alg->cra_blocksize;
  237 
  238         inst->alg.digestsize = alg->cra_blocksize;
  239         inst->alg.descsize = ALIGN(sizeof(struct xcbc_desc_ctx),
  240                                    crypto_tfm_ctx_alignment()) +
  241                              (alignmask &
  242                               ~(crypto_tfm_ctx_alignment() - 1)) +
  243                              alg->cra_blocksize * 2;
  244 
  245         inst->alg.base.cra_ctxsize = ALIGN(sizeof(struct xcbc_tfm_ctx),
  246                                            alignmask + 1) +
  247                                      alg->cra_blocksize * 2;
  248         inst->alg.base.cra_init = xcbc_init_tfm;
  249         inst->alg.base.cra_exit = xcbc_exit_tfm;
  250 
  251         inst->alg.init = crypto_xcbc_digest_init;
  252         inst->alg.update = crypto_xcbc_digest_update;
  253         inst->alg.final = crypto_xcbc_digest_final;
  254         inst->alg.setkey = crypto_xcbc_digest_setkey;
  255 
  256         err = shash_register_instance(tmpl, inst);
  257         if (err) {
  258 out_free_inst:
  259                 shash_free_instance(shash_crypto_instance(inst));
  260         }
  261 
  262 out_put_alg:
  263         crypto_mod_put(alg);
  264         return err;
  265 }
  266 
  267 static struct crypto_template crypto_xcbc_tmpl = {
  268         .name = "xcbc",
  269         .create = xcbc_create,
  270         .free = shash_free_instance,
  271         .module = THIS_MODULE,
  272 };
  273 
  274 static int __init crypto_xcbc_module_init(void)
  275 {
  276         return crypto_register_template(&crypto_xcbc_tmpl);
  277 }
  278 
  279 static void __exit crypto_xcbc_module_exit(void)
  280 {
  281         crypto_unregister_template(&crypto_xcbc_tmpl);
  282 }
  283 
  284 module_init(crypto_xcbc_module_init);
  285 module_exit(crypto_xcbc_module_exit);
  286 
  287 MODULE_LICENSE("GPL");
  288 MODULE_DESCRIPTION("XCBC keyed hash algorithm");

Cache object: ebbb18035cc9e0b0cc52b37145a90c91


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