Back to home page

LXR

 
 

    


0001 /*
0002  * Copyright (C)2006 USAGI/WIDE Project
0003  *
0004  * This program is free software; you can redistribute it and/or modify
0005  * it under the terms of the GNU General Public License as published by
0006  * the Free Software Foundation; either version 2 of the License, or
0007  * (at your option) any later version.
0008  *
0009  * This program is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  * GNU General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU General Public License
0015  * along with this program; if not, write to the Free Software
0016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0017  *
0018  * Author:
0019  *  Kazunori Miyazawa <miyazawa@linux-ipv6.org>
0020  */
0021 
0022 #include <crypto/internal/hash.h>
0023 #include <linux/err.h>
0024 #include <linux/kernel.h>
0025 #include <linux/module.h>
0026 
0027 static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
0028                0x02020202, 0x02020202, 0x02020202, 0x02020202,
0029                0x03030303, 0x03030303, 0x03030303, 0x03030303};
0030 
0031 /*
0032  * +------------------------
0033  * | <parent tfm>
0034  * +------------------------
0035  * | xcbc_tfm_ctx
0036  * +------------------------
0037  * | consts (block size * 2)
0038  * +------------------------
0039  */
0040 struct xcbc_tfm_ctx {
0041     struct crypto_cipher *child;
0042     u8 ctx[];
0043 };
0044 
0045 /*
0046  * +------------------------
0047  * | <shash desc>
0048  * +------------------------
0049  * | xcbc_desc_ctx
0050  * +------------------------
0051  * | odds (block size)
0052  * +------------------------
0053  * | prev (block size)
0054  * +------------------------
0055  */
0056 struct xcbc_desc_ctx {
0057     unsigned int len;
0058     u8 ctx[];
0059 };
0060 
0061 static int crypto_xcbc_digest_setkey(struct crypto_shash *parent,
0062                      const u8 *inkey, unsigned int keylen)
0063 {
0064     unsigned long alignmask = crypto_shash_alignmask(parent);
0065     struct xcbc_tfm_ctx *ctx = crypto_shash_ctx(parent);
0066     int bs = crypto_shash_blocksize(parent);
0067     u8 *consts = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
0068     int err = 0;
0069     u8 key1[bs];
0070 
0071     if ((err = crypto_cipher_setkey(ctx->child, inkey, keylen)))
0072         return err;
0073 
0074     crypto_cipher_encrypt_one(ctx->child, consts, (u8 *)ks + bs);
0075     crypto_cipher_encrypt_one(ctx->child, consts + bs, (u8 *)ks + bs * 2);
0076     crypto_cipher_encrypt_one(ctx->child, key1, (u8 *)ks);
0077 
0078     return crypto_cipher_setkey(ctx->child, key1, bs);
0079 
0080 }
0081 
0082 static int crypto_xcbc_digest_init(struct shash_desc *pdesc)
0083 {
0084     unsigned long alignmask = crypto_shash_alignmask(pdesc->tfm);
0085     struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
0086     int bs = crypto_shash_blocksize(pdesc->tfm);
0087     u8 *prev = PTR_ALIGN(&ctx->ctx[0], alignmask + 1) + bs;
0088 
0089     ctx->len = 0;
0090     memset(prev, 0, bs);
0091 
0092     return 0;
0093 }
0094 
0095 static int crypto_xcbc_digest_update(struct shash_desc *pdesc, const u8 *p,
0096                      unsigned int len)
0097 {
0098     struct crypto_shash *parent = pdesc->tfm;
0099     unsigned long alignmask = crypto_shash_alignmask(parent);
0100     struct xcbc_tfm_ctx *tctx = crypto_shash_ctx(parent);
0101     struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
0102     struct crypto_cipher *tfm = tctx->child;
0103     int bs = crypto_shash_blocksize(parent);
0104     u8 *odds = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
0105     u8 *prev = odds + bs;
0106 
0107     /* checking the data can fill the block */
0108     if ((ctx->len + len) <= bs) {
0109         memcpy(odds + ctx->len, p, len);
0110         ctx->len += len;
0111         return 0;
0112     }
0113 
0114     /* filling odds with new data and encrypting it */
0115     memcpy(odds + ctx->len, p, bs - ctx->len);
0116     len -= bs - ctx->len;
0117     p += bs - ctx->len;
0118 
0119     crypto_xor(prev, odds, bs);
0120     crypto_cipher_encrypt_one(tfm, prev, prev);
0121 
0122     /* clearing the length */
0123     ctx->len = 0;
0124 
0125     /* encrypting the rest of data */
0126     while (len > bs) {
0127         crypto_xor(prev, p, bs);
0128         crypto_cipher_encrypt_one(tfm, prev, prev);
0129         p += bs;
0130         len -= bs;
0131     }
0132 
0133     /* keeping the surplus of blocksize */
0134     if (len) {
0135         memcpy(odds, p, len);
0136         ctx->len = len;
0137     }
0138 
0139     return 0;
0140 }
0141 
0142 static int crypto_xcbc_digest_final(struct shash_desc *pdesc, u8 *out)
0143 {
0144     struct crypto_shash *parent = pdesc->tfm;
0145     unsigned long alignmask = crypto_shash_alignmask(parent);
0146     struct xcbc_tfm_ctx *tctx = crypto_shash_ctx(parent);
0147     struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
0148     struct crypto_cipher *tfm = tctx->child;
0149     int bs = crypto_shash_blocksize(parent);
0150     u8 *consts = PTR_ALIGN(&tctx->ctx[0], alignmask + 1);
0151     u8 *odds = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
0152     u8 *prev = odds + bs;
0153     unsigned int offset = 0;
0154 
0155     if (ctx->len != bs) {
0156         unsigned int rlen;
0157         u8 *p = odds + ctx->len;
0158 
0159         *p = 0x80;
0160         p++;
0161 
0162         rlen = bs - ctx->len -1;
0163         if (rlen)
0164             memset(p, 0, rlen);
0165 
0166         offset += bs;
0167     }
0168 
0169     crypto_xor(prev, odds, bs);
0170     crypto_xor(prev, consts + offset, bs);
0171 
0172     crypto_cipher_encrypt_one(tfm, out, prev);
0173 
0174     return 0;
0175 }
0176 
0177 static int xcbc_init_tfm(struct crypto_tfm *tfm)
0178 {
0179     struct crypto_cipher *cipher;
0180     struct crypto_instance *inst = (void *)tfm->__crt_alg;
0181     struct crypto_spawn *spawn = crypto_instance_ctx(inst);
0182     struct xcbc_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
0183 
0184     cipher = crypto_spawn_cipher(spawn);
0185     if (IS_ERR(cipher))
0186         return PTR_ERR(cipher);
0187 
0188     ctx->child = cipher;
0189 
0190     return 0;
0191 };
0192 
0193 static void xcbc_exit_tfm(struct crypto_tfm *tfm)
0194 {
0195     struct xcbc_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
0196     crypto_free_cipher(ctx->child);
0197 }
0198 
0199 static int xcbc_create(struct crypto_template *tmpl, struct rtattr **tb)
0200 {
0201     struct shash_instance *inst;
0202     struct crypto_alg *alg;
0203     unsigned long alignmask;
0204     int err;
0205 
0206     err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH);
0207     if (err)
0208         return err;
0209 
0210     alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
0211                   CRYPTO_ALG_TYPE_MASK);
0212     if (IS_ERR(alg))
0213         return PTR_ERR(alg);
0214 
0215     switch(alg->cra_blocksize) {
0216     case 16:
0217         break;
0218     default:
0219         goto out_put_alg;
0220     }
0221 
0222     inst = shash_alloc_instance("xcbc", alg);
0223     err = PTR_ERR(inst);
0224     if (IS_ERR(inst))
0225         goto out_put_alg;
0226 
0227     err = crypto_init_spawn(shash_instance_ctx(inst), alg,
0228                 shash_crypto_instance(inst),
0229                 CRYPTO_ALG_TYPE_MASK);
0230     if (err)
0231         goto out_free_inst;
0232 
0233     alignmask = alg->cra_alignmask | 3;
0234     inst->alg.base.cra_alignmask = alignmask;
0235     inst->alg.base.cra_priority = alg->cra_priority;
0236     inst->alg.base.cra_blocksize = alg->cra_blocksize;
0237 
0238     inst->alg.digestsize = alg->cra_blocksize;
0239     inst->alg.descsize = ALIGN(sizeof(struct xcbc_desc_ctx),
0240                    crypto_tfm_ctx_alignment()) +
0241                  (alignmask &
0242                   ~(crypto_tfm_ctx_alignment() - 1)) +
0243                  alg->cra_blocksize * 2;
0244 
0245     inst->alg.base.cra_ctxsize = ALIGN(sizeof(struct xcbc_tfm_ctx),
0246                        alignmask + 1) +
0247                      alg->cra_blocksize * 2;
0248     inst->alg.base.cra_init = xcbc_init_tfm;
0249     inst->alg.base.cra_exit = xcbc_exit_tfm;
0250 
0251     inst->alg.init = crypto_xcbc_digest_init;
0252     inst->alg.update = crypto_xcbc_digest_update;
0253     inst->alg.final = crypto_xcbc_digest_final;
0254     inst->alg.setkey = crypto_xcbc_digest_setkey;
0255 
0256     err = shash_register_instance(tmpl, inst);
0257     if (err) {
0258 out_free_inst:
0259         shash_free_instance(shash_crypto_instance(inst));
0260     }
0261 
0262 out_put_alg:
0263     crypto_mod_put(alg);
0264     return err;
0265 }
0266 
0267 static struct crypto_template crypto_xcbc_tmpl = {
0268     .name = "xcbc",
0269     .create = xcbc_create,
0270     .free = shash_free_instance,
0271     .module = THIS_MODULE,
0272 };
0273 
0274 static int __init crypto_xcbc_module_init(void)
0275 {
0276     return crypto_register_template(&crypto_xcbc_tmpl);
0277 }
0278 
0279 static void __exit crypto_xcbc_module_exit(void)
0280 {
0281     crypto_unregister_template(&crypto_xcbc_tmpl);
0282 }
0283 
0284 module_init(crypto_xcbc_module_init);
0285 module_exit(crypto_xcbc_module_exit);
0286 
0287 MODULE_LICENSE("GPL");
0288 MODULE_DESCRIPTION("XCBC keyed hash algorithm");
0289 MODULE_ALIAS_CRYPTO("xcbc");