Back to home page

LXR

 
 

    


0001 /*
0002  * CBC: Cipher Block Chaining mode
0003  *
0004  * Copyright (c) 2006-2016 Herbert Xu <herbert@gondor.apana.org.au>
0005  *
0006  * This program is free software; you can redistribute it and/or modify it
0007  * under the terms of the GNU General Public License as published by the Free
0008  * Software Foundation; either version 2 of the License, or (at your option)
0009  * any later version.
0010  *
0011  */
0012 
0013 #include <crypto/cbc.h>
0014 #include <crypto/internal/skcipher.h>
0015 #include <linux/err.h>
0016 #include <linux/init.h>
0017 #include <linux/kernel.h>
0018 #include <linux/log2.h>
0019 #include <linux/module.h>
0020 #include <linux/slab.h>
0021 
0022 struct crypto_cbc_ctx {
0023     struct crypto_cipher *child;
0024 };
0025 
0026 static int crypto_cbc_setkey(struct crypto_skcipher *parent, const u8 *key,
0027                  unsigned int keylen)
0028 {
0029     struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(parent);
0030     struct crypto_cipher *child = ctx->child;
0031     int err;
0032 
0033     crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
0034     crypto_cipher_set_flags(child, crypto_skcipher_get_flags(parent) &
0035                        CRYPTO_TFM_REQ_MASK);
0036     err = crypto_cipher_setkey(child, key, keylen);
0037     crypto_skcipher_set_flags(parent, crypto_cipher_get_flags(child) &
0038                       CRYPTO_TFM_RES_MASK);
0039     return err;
0040 }
0041 
0042 static inline void crypto_cbc_encrypt_one(struct crypto_skcipher *tfm,
0043                       const u8 *src, u8 *dst)
0044 {
0045     struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
0046 
0047     crypto_cipher_encrypt_one(ctx->child, dst, src);
0048 }
0049 
0050 static int crypto_cbc_encrypt(struct skcipher_request *req)
0051 {
0052     return crypto_cbc_encrypt_walk(req, crypto_cbc_encrypt_one);
0053 }
0054 
0055 static inline void crypto_cbc_decrypt_one(struct crypto_skcipher *tfm,
0056                       const u8 *src, u8 *dst)
0057 {
0058     struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
0059 
0060     crypto_cipher_decrypt_one(ctx->child, dst, src);
0061 }
0062 
0063 static int crypto_cbc_decrypt(struct skcipher_request *req)
0064 {
0065     struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
0066     struct skcipher_walk walk;
0067     int err;
0068 
0069     err = skcipher_walk_virt(&walk, req, false);
0070 
0071     while (walk.nbytes) {
0072         err = crypto_cbc_decrypt_blocks(&walk, tfm,
0073                         crypto_cbc_decrypt_one);
0074         err = skcipher_walk_done(&walk, err);
0075     }
0076 
0077     return err;
0078 }
0079 
0080 static int crypto_cbc_init_tfm(struct crypto_skcipher *tfm)
0081 {
0082     struct skcipher_instance *inst = skcipher_alg_instance(tfm);
0083     struct crypto_spawn *spawn = skcipher_instance_ctx(inst);
0084     struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
0085     struct crypto_cipher *cipher;
0086 
0087     cipher = crypto_spawn_cipher(spawn);
0088     if (IS_ERR(cipher))
0089         return PTR_ERR(cipher);
0090 
0091     ctx->child = cipher;
0092     return 0;
0093 }
0094 
0095 static void crypto_cbc_exit_tfm(struct crypto_skcipher *tfm)
0096 {
0097     struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
0098 
0099     crypto_free_cipher(ctx->child);
0100 }
0101 
0102 static void crypto_cbc_free(struct skcipher_instance *inst)
0103 {
0104     crypto_drop_skcipher(skcipher_instance_ctx(inst));
0105     kfree(inst);
0106 }
0107 
0108 static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb)
0109 {
0110     struct skcipher_instance *inst;
0111     struct crypto_spawn *spawn;
0112     struct crypto_alg *alg;
0113     int err;
0114 
0115     err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER);
0116     if (err)
0117         return err;
0118 
0119     inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
0120     if (!inst)
0121         return -ENOMEM;
0122 
0123     alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
0124                   CRYPTO_ALG_TYPE_MASK);
0125     err = PTR_ERR(alg);
0126     if (IS_ERR(alg))
0127         goto err_free_inst;
0128 
0129     spawn = skcipher_instance_ctx(inst);
0130     err = crypto_init_spawn(spawn, alg, skcipher_crypto_instance(inst),
0131                 CRYPTO_ALG_TYPE_MASK);
0132     crypto_mod_put(alg);
0133     if (err)
0134         goto err_free_inst;
0135 
0136     err = crypto_inst_setname(skcipher_crypto_instance(inst), "cbc", alg);
0137     if (err)
0138         goto err_drop_spawn;
0139 
0140     err = -EINVAL;
0141     if (!is_power_of_2(alg->cra_blocksize))
0142         goto err_drop_spawn;
0143 
0144     inst->alg.base.cra_priority = alg->cra_priority;
0145     inst->alg.base.cra_blocksize = alg->cra_blocksize;
0146     inst->alg.base.cra_alignmask = alg->cra_alignmask;
0147 
0148     /* We access the data as u32s when xoring. */
0149     inst->alg.base.cra_alignmask |= __alignof__(u32) - 1;
0150 
0151     inst->alg.ivsize = alg->cra_blocksize;
0152     inst->alg.min_keysize = alg->cra_cipher.cia_min_keysize;
0153     inst->alg.max_keysize = alg->cra_cipher.cia_max_keysize;
0154 
0155     inst->alg.base.cra_ctxsize = sizeof(struct crypto_cbc_ctx);
0156 
0157     inst->alg.init = crypto_cbc_init_tfm;
0158     inst->alg.exit = crypto_cbc_exit_tfm;
0159 
0160     inst->alg.setkey = crypto_cbc_setkey;
0161     inst->alg.encrypt = crypto_cbc_encrypt;
0162     inst->alg.decrypt = crypto_cbc_decrypt;
0163 
0164     inst->free = crypto_cbc_free;
0165 
0166     err = skcipher_register_instance(tmpl, inst);
0167     if (err)
0168         goto err_drop_spawn;
0169 
0170 out:
0171     return err;
0172 
0173 err_drop_spawn:
0174     crypto_drop_spawn(spawn);
0175 err_free_inst:
0176     kfree(inst);
0177     goto out;
0178 }
0179 
0180 static struct crypto_template crypto_cbc_tmpl = {
0181     .name = "cbc",
0182     .create = crypto_cbc_create,
0183     .module = THIS_MODULE,
0184 };
0185 
0186 static int __init crypto_cbc_module_init(void)
0187 {
0188     return crypto_register_template(&crypto_cbc_tmpl);
0189 }
0190 
0191 static void __exit crypto_cbc_module_exit(void)
0192 {
0193     crypto_unregister_template(&crypto_cbc_tmpl);
0194 }
0195 
0196 module_init(crypto_cbc_module_init);
0197 module_exit(crypto_cbc_module_exit);
0198 
0199 MODULE_LICENSE("GPL");
0200 MODULE_DESCRIPTION("CBC block cipher algorithm");
0201 MODULE_ALIAS_CRYPTO("cbc");