1db131ef9SHerbert Xu /* 2db131ef9SHerbert Xu * CBC: Cipher Block Chaining mode 3db131ef9SHerbert Xu * 4cc868d82SHerbert Xu * Copyright (c) 2006-2016 Herbert Xu <herbert@gondor.apana.org.au> 5db131ef9SHerbert Xu * 6db131ef9SHerbert Xu * This program is free software; you can redistribute it and/or modify it 7db131ef9SHerbert Xu * under the terms of the GNU General Public License as published by the Free 8db131ef9SHerbert Xu * Software Foundation; either version 2 of the License, or (at your option) 9db131ef9SHerbert Xu * any later version. 10db131ef9SHerbert Xu * 11db131ef9SHerbert Xu */ 12db131ef9SHerbert Xu 13e6c2e65cSMarcelo Cerri #include <crypto/algapi.h> 14cc868d82SHerbert Xu #include <crypto/cbc.h> 1579c65d17SHerbert Xu #include <crypto/internal/skcipher.h> 16db131ef9SHerbert Xu #include <linux/err.h> 17db131ef9SHerbert Xu #include <linux/init.h> 18db131ef9SHerbert Xu #include <linux/kernel.h> 1950b6544eSHerbert Xu #include <linux/log2.h> 20db131ef9SHerbert Xu #include <linux/module.h> 21db131ef9SHerbert Xu #include <linux/slab.h> 22db131ef9SHerbert Xu 23db131ef9SHerbert Xu struct crypto_cbc_ctx { 24db131ef9SHerbert Xu struct crypto_cipher *child; 25db131ef9SHerbert Xu }; 26db131ef9SHerbert Xu 2779c65d17SHerbert Xu static int crypto_cbc_setkey(struct crypto_skcipher *parent, const u8 *key, 28db131ef9SHerbert Xu unsigned int keylen) 29db131ef9SHerbert Xu { 3079c65d17SHerbert Xu struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(parent); 31db131ef9SHerbert Xu struct crypto_cipher *child = ctx->child; 32db131ef9SHerbert Xu int err; 33db131ef9SHerbert Xu 34db131ef9SHerbert Xu crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); 3579c65d17SHerbert Xu crypto_cipher_set_flags(child, crypto_skcipher_get_flags(parent) & 36db131ef9SHerbert Xu CRYPTO_TFM_REQ_MASK); 37db131ef9SHerbert Xu err = crypto_cipher_setkey(child, key, keylen); 3879c65d17SHerbert Xu crypto_skcipher_set_flags(parent, crypto_cipher_get_flags(child) & 39db131ef9SHerbert Xu CRYPTO_TFM_RES_MASK); 40db131ef9SHerbert Xu return err; 41db131ef9SHerbert Xu } 42db131ef9SHerbert Xu 4379c65d17SHerbert Xu static inline void crypto_cbc_encrypt_one(struct crypto_skcipher *tfm, 4479c65d17SHerbert Xu const u8 *src, u8 *dst) 45db131ef9SHerbert Xu { 4679c65d17SHerbert Xu struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); 4779c65d17SHerbert Xu 4879c65d17SHerbert Xu crypto_cipher_encrypt_one(ctx->child, dst, src); 4979c65d17SHerbert Xu } 5079c65d17SHerbert Xu 5179c65d17SHerbert Xu static int crypto_cbc_encrypt(struct skcipher_request *req) 5279c65d17SHerbert Xu { 5379c65d17SHerbert Xu return crypto_cbc_encrypt_walk(req, crypto_cbc_encrypt_one); 5479c65d17SHerbert Xu } 5579c65d17SHerbert Xu 5679c65d17SHerbert Xu static inline void crypto_cbc_decrypt_one(struct crypto_skcipher *tfm, 5779c65d17SHerbert Xu const u8 *src, u8 *dst) 5879c65d17SHerbert Xu { 5979c65d17SHerbert Xu struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); 6079c65d17SHerbert Xu 6179c65d17SHerbert Xu crypto_cipher_decrypt_one(ctx->child, dst, src); 6279c65d17SHerbert Xu } 6379c65d17SHerbert Xu 6479c65d17SHerbert Xu static int crypto_cbc_decrypt(struct skcipher_request *req) 6579c65d17SHerbert Xu { 6679c65d17SHerbert Xu struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 6779c65d17SHerbert Xu struct skcipher_walk walk; 68db131ef9SHerbert Xu int err; 69db131ef9SHerbert Xu 7079c65d17SHerbert Xu err = skcipher_walk_virt(&walk, req, false); 71db131ef9SHerbert Xu 7279c65d17SHerbert Xu while (walk.nbytes) { 7379c65d17SHerbert Xu err = crypto_cbc_decrypt_blocks(&walk, tfm, 7479c65d17SHerbert Xu crypto_cbc_decrypt_one); 7579c65d17SHerbert Xu err = skcipher_walk_done(&walk, err); 76db131ef9SHerbert Xu } 77db131ef9SHerbert Xu 78db131ef9SHerbert Xu return err; 79db131ef9SHerbert Xu } 80db131ef9SHerbert Xu 8179c65d17SHerbert Xu static int crypto_cbc_init_tfm(struct crypto_skcipher *tfm) 82db131ef9SHerbert Xu { 8379c65d17SHerbert Xu struct skcipher_instance *inst = skcipher_alg_instance(tfm); 8479c65d17SHerbert Xu struct crypto_spawn *spawn = skcipher_instance_ctx(inst); 8579c65d17SHerbert Xu struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); 862e306ee0SHerbert Xu struct crypto_cipher *cipher; 87db131ef9SHerbert Xu 882e306ee0SHerbert Xu cipher = crypto_spawn_cipher(spawn); 892e306ee0SHerbert Xu if (IS_ERR(cipher)) 902e306ee0SHerbert Xu return PTR_ERR(cipher); 91db131ef9SHerbert Xu 922e306ee0SHerbert Xu ctx->child = cipher; 93db131ef9SHerbert Xu return 0; 94db131ef9SHerbert Xu } 95db131ef9SHerbert Xu 9679c65d17SHerbert Xu static void crypto_cbc_exit_tfm(struct crypto_skcipher *tfm) 97db131ef9SHerbert Xu { 9879c65d17SHerbert Xu struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); 9979c65d17SHerbert Xu 100db131ef9SHerbert Xu crypto_free_cipher(ctx->child); 101db131ef9SHerbert Xu } 102db131ef9SHerbert Xu 10379c65d17SHerbert Xu static void crypto_cbc_free(struct skcipher_instance *inst) 104db131ef9SHerbert Xu { 10579c65d17SHerbert Xu crypto_drop_skcipher(skcipher_instance_ctx(inst)); 10679c65d17SHerbert Xu kfree(inst); 10779c65d17SHerbert Xu } 10879c65d17SHerbert Xu 10979c65d17SHerbert Xu static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb) 11079c65d17SHerbert Xu { 11179c65d17SHerbert Xu struct skcipher_instance *inst; 112e6c2e65cSMarcelo Cerri struct crypto_attr_type *algt; 11379c65d17SHerbert Xu struct crypto_spawn *spawn; 114db131ef9SHerbert Xu struct crypto_alg *alg; 115e6c2e65cSMarcelo Cerri u32 mask; 116ebc610e5SHerbert Xu int err; 117db131ef9SHerbert Xu 11879c65d17SHerbert Xu err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER); 119ebc610e5SHerbert Xu if (err) 12079c65d17SHerbert Xu return err; 12179c65d17SHerbert Xu 12279c65d17SHerbert Xu inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); 12379c65d17SHerbert Xu if (!inst) 12479c65d17SHerbert Xu return -ENOMEM; 125ebc610e5SHerbert Xu 126e6c2e65cSMarcelo Cerri algt = crypto_get_attr_type(tb); 127e6c2e65cSMarcelo Cerri err = PTR_ERR(algt); 128e6c2e65cSMarcelo Cerri if (IS_ERR(algt)) 129e6c2e65cSMarcelo Cerri goto err_free_inst; 130e6c2e65cSMarcelo Cerri 131e6c2e65cSMarcelo Cerri mask = CRYPTO_ALG_TYPE_MASK | 132e6c2e65cSMarcelo Cerri crypto_requires_off(algt->type, algt->mask, 133e6c2e65cSMarcelo Cerri CRYPTO_ALG_NEED_FALLBACK); 134e6c2e65cSMarcelo Cerri 135e6c2e65cSMarcelo Cerri alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, mask); 13679c65d17SHerbert Xu err = PTR_ERR(alg); 137db131ef9SHerbert Xu if (IS_ERR(alg)) 13879c65d17SHerbert Xu goto err_free_inst; 139db131ef9SHerbert Xu 14079c65d17SHerbert Xu spawn = skcipher_instance_ctx(inst); 14179c65d17SHerbert Xu err = crypto_init_spawn(spawn, alg, skcipher_crypto_instance(inst), 14279c65d17SHerbert Xu CRYPTO_ALG_TYPE_MASK); 14379c65d17SHerbert Xu crypto_mod_put(alg); 14479c65d17SHerbert Xu if (err) 14579c65d17SHerbert Xu goto err_free_inst; 14679c65d17SHerbert Xu 14779c65d17SHerbert Xu err = crypto_inst_setname(skcipher_crypto_instance(inst), "cbc", alg); 14879c65d17SHerbert Xu if (err) 14979c65d17SHerbert Xu goto err_drop_spawn; 15079c65d17SHerbert Xu 15179c65d17SHerbert Xu err = -EINVAL; 15250b6544eSHerbert Xu if (!is_power_of_2(alg->cra_blocksize)) 15379c65d17SHerbert Xu goto err_drop_spawn; 15450b6544eSHerbert Xu 15579c65d17SHerbert Xu inst->alg.base.cra_priority = alg->cra_priority; 15679c65d17SHerbert Xu inst->alg.base.cra_blocksize = alg->cra_blocksize; 15779c65d17SHerbert Xu inst->alg.base.cra_alignmask = alg->cra_alignmask; 158db131ef9SHerbert Xu 15979c65d17SHerbert Xu inst->alg.ivsize = alg->cra_blocksize; 16079c65d17SHerbert Xu inst->alg.min_keysize = alg->cra_cipher.cia_min_keysize; 16179c65d17SHerbert Xu inst->alg.max_keysize = alg->cra_cipher.cia_max_keysize; 162db131ef9SHerbert Xu 16379c65d17SHerbert Xu inst->alg.base.cra_ctxsize = sizeof(struct crypto_cbc_ctx); 164db131ef9SHerbert Xu 16579c65d17SHerbert Xu inst->alg.init = crypto_cbc_init_tfm; 16679c65d17SHerbert Xu inst->alg.exit = crypto_cbc_exit_tfm; 167db131ef9SHerbert Xu 16879c65d17SHerbert Xu inst->alg.setkey = crypto_cbc_setkey; 16979c65d17SHerbert Xu inst->alg.encrypt = crypto_cbc_encrypt; 17079c65d17SHerbert Xu inst->alg.decrypt = crypto_cbc_decrypt; 171db131ef9SHerbert Xu 17279c65d17SHerbert Xu inst->free = crypto_cbc_free; 173db131ef9SHerbert Xu 17479c65d17SHerbert Xu err = skcipher_register_instance(tmpl, inst); 17579c65d17SHerbert Xu if (err) 17679c65d17SHerbert Xu goto err_drop_spawn; 17779c65d17SHerbert Xu 17879c65d17SHerbert Xu out: 17979c65d17SHerbert Xu return err; 18079c65d17SHerbert Xu 18179c65d17SHerbert Xu err_drop_spawn: 18279c65d17SHerbert Xu crypto_drop_spawn(spawn); 18379c65d17SHerbert Xu err_free_inst: 184db131ef9SHerbert Xu kfree(inst); 18579c65d17SHerbert Xu goto out; 186db131ef9SHerbert Xu } 187db131ef9SHerbert Xu 188db131ef9SHerbert Xu static struct crypto_template crypto_cbc_tmpl = { 189db131ef9SHerbert Xu .name = "cbc", 19079c65d17SHerbert Xu .create = crypto_cbc_create, 191db131ef9SHerbert Xu .module = THIS_MODULE, 192db131ef9SHerbert Xu }; 193db131ef9SHerbert Xu 194db131ef9SHerbert Xu static int __init crypto_cbc_module_init(void) 195db131ef9SHerbert Xu { 196db131ef9SHerbert Xu return crypto_register_template(&crypto_cbc_tmpl); 197db131ef9SHerbert Xu } 198db131ef9SHerbert Xu 199db131ef9SHerbert Xu static void __exit crypto_cbc_module_exit(void) 200db131ef9SHerbert Xu { 201db131ef9SHerbert Xu crypto_unregister_template(&crypto_cbc_tmpl); 202db131ef9SHerbert Xu } 203db131ef9SHerbert Xu 204db131ef9SHerbert Xu module_init(crypto_cbc_module_init); 205db131ef9SHerbert Xu module_exit(crypto_cbc_module_exit); 206db131ef9SHerbert Xu 207db131ef9SHerbert Xu MODULE_LICENSE("GPL"); 208db131ef9SHerbert Xu MODULE_DESCRIPTION("CBC block cipher algorithm"); 2094943ba16SKees Cook MODULE_ALIAS_CRYPTO("cbc"); 210