1 /* 2 * CBC: Cipher Block Chaining mode 3 * 4 * Copyright (c) 2006-2016 Herbert Xu <herbert@gondor.apana.org.au> 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/cbc.h> 14 #include <crypto/internal/skcipher.h> 15 #include <linux/err.h> 16 #include <linux/init.h> 17 #include <linux/kernel.h> 18 #include <linux/log2.h> 19 #include <linux/module.h> 20 #include <linux/slab.h> 21 22 struct crypto_cbc_ctx { 23 struct crypto_cipher *child; 24 }; 25 26 static int crypto_cbc_setkey(struct crypto_skcipher *parent, const u8 *key, 27 unsigned int keylen) 28 { 29 struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(parent); 30 struct crypto_cipher *child = ctx->child; 31 int err; 32 33 crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); 34 crypto_cipher_set_flags(child, crypto_skcipher_get_flags(parent) & 35 CRYPTO_TFM_REQ_MASK); 36 err = crypto_cipher_setkey(child, key, keylen); 37 crypto_skcipher_set_flags(parent, crypto_cipher_get_flags(child) & 38 CRYPTO_TFM_RES_MASK); 39 return err; 40 } 41 42 static inline void crypto_cbc_encrypt_one(struct crypto_skcipher *tfm, 43 const u8 *src, u8 *dst) 44 { 45 struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); 46 47 crypto_cipher_encrypt_one(ctx->child, dst, src); 48 } 49 50 static int crypto_cbc_encrypt(struct skcipher_request *req) 51 { 52 return crypto_cbc_encrypt_walk(req, crypto_cbc_encrypt_one); 53 } 54 55 static inline void crypto_cbc_decrypt_one(struct crypto_skcipher *tfm, 56 const u8 *src, u8 *dst) 57 { 58 struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); 59 60 crypto_cipher_decrypt_one(ctx->child, dst, src); 61 } 62 63 static int crypto_cbc_decrypt(struct skcipher_request *req) 64 { 65 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 66 struct skcipher_walk walk; 67 int err; 68 69 err = skcipher_walk_virt(&walk, req, false); 70 71 while (walk.nbytes) { 72 err = crypto_cbc_decrypt_blocks(&walk, tfm, 73 crypto_cbc_decrypt_one); 74 err = skcipher_walk_done(&walk, err); 75 } 76 77 return err; 78 } 79 80 static int crypto_cbc_init_tfm(struct crypto_skcipher *tfm) 81 { 82 struct skcipher_instance *inst = skcipher_alg_instance(tfm); 83 struct crypto_spawn *spawn = skcipher_instance_ctx(inst); 84 struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); 85 struct crypto_cipher *cipher; 86 87 cipher = crypto_spawn_cipher(spawn); 88 if (IS_ERR(cipher)) 89 return PTR_ERR(cipher); 90 91 ctx->child = cipher; 92 return 0; 93 } 94 95 static void crypto_cbc_exit_tfm(struct crypto_skcipher *tfm) 96 { 97 struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); 98 99 crypto_free_cipher(ctx->child); 100 } 101 102 static void crypto_cbc_free(struct skcipher_instance *inst) 103 { 104 crypto_drop_skcipher(skcipher_instance_ctx(inst)); 105 kfree(inst); 106 } 107 108 static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb) 109 { 110 struct skcipher_instance *inst; 111 struct crypto_spawn *spawn; 112 struct crypto_alg *alg; 113 int err; 114 115 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER); 116 if (err) 117 return err; 118 119 inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); 120 if (!inst) 121 return -ENOMEM; 122 123 alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, 124 CRYPTO_ALG_TYPE_MASK); 125 err = PTR_ERR(alg); 126 if (IS_ERR(alg)) 127 goto err_free_inst; 128 129 spawn = skcipher_instance_ctx(inst); 130 err = crypto_init_spawn(spawn, alg, skcipher_crypto_instance(inst), 131 CRYPTO_ALG_TYPE_MASK); 132 crypto_mod_put(alg); 133 if (err) 134 goto err_free_inst; 135 136 err = crypto_inst_setname(skcipher_crypto_instance(inst), "cbc", alg); 137 if (err) 138 goto err_drop_spawn; 139 140 err = -EINVAL; 141 if (!is_power_of_2(alg->cra_blocksize)) 142 goto err_drop_spawn; 143 144 inst->alg.base.cra_priority = alg->cra_priority; 145 inst->alg.base.cra_blocksize = alg->cra_blocksize; 146 inst->alg.base.cra_alignmask = alg->cra_alignmask; 147 148 inst->alg.ivsize = alg->cra_blocksize; 149 inst->alg.min_keysize = alg->cra_cipher.cia_min_keysize; 150 inst->alg.max_keysize = alg->cra_cipher.cia_max_keysize; 151 152 inst->alg.base.cra_ctxsize = sizeof(struct crypto_cbc_ctx); 153 154 inst->alg.init = crypto_cbc_init_tfm; 155 inst->alg.exit = crypto_cbc_exit_tfm; 156 157 inst->alg.setkey = crypto_cbc_setkey; 158 inst->alg.encrypt = crypto_cbc_encrypt; 159 inst->alg.decrypt = crypto_cbc_decrypt; 160 161 inst->free = crypto_cbc_free; 162 163 err = skcipher_register_instance(tmpl, inst); 164 if (err) 165 goto err_drop_spawn; 166 167 out: 168 return err; 169 170 err_drop_spawn: 171 crypto_drop_spawn(spawn); 172 err_free_inst: 173 kfree(inst); 174 goto out; 175 } 176 177 static struct crypto_template crypto_cbc_tmpl = { 178 .name = "cbc", 179 .create = crypto_cbc_create, 180 .module = THIS_MODULE, 181 }; 182 183 static int __init crypto_cbc_module_init(void) 184 { 185 return crypto_register_template(&crypto_cbc_tmpl); 186 } 187 188 static void __exit crypto_cbc_module_exit(void) 189 { 190 crypto_unregister_template(&crypto_cbc_tmpl); 191 } 192 193 module_init(crypto_cbc_module_init); 194 module_exit(crypto_cbc_module_exit); 195 196 MODULE_LICENSE("GPL"); 197 MODULE_DESCRIPTION("CBC block cipher algorithm"); 198 MODULE_ALIAS_CRYPTO("cbc"); 199