Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later 2 : : /* 3 : : * CBC: Cipher Block Chaining mode 4 : : * 5 : : * Copyright (c) 2006-2016 Herbert Xu <herbert@gondor.apana.org.au> 6 : : */ 7 : : 8 : : #include <crypto/algapi.h> 9 : : #include <crypto/cbc.h> 10 : : #include <crypto/internal/skcipher.h> 11 : : #include <linux/err.h> 12 : : #include <linux/init.h> 13 : : #include <linux/kernel.h> 14 : : #include <linux/log2.h> 15 : : #include <linux/module.h> 16 : : 17 : 0 : static inline void crypto_cbc_encrypt_one(struct crypto_skcipher *tfm, 18 : : const u8 *src, u8 *dst) 19 : : { 20 : : crypto_cipher_encrypt_one(skcipher_cipher_simple(tfm), dst, src); 21 : 0 : } 22 : : 23 : 0 : static int crypto_cbc_encrypt(struct skcipher_request *req) 24 : : { 25 : 0 : return crypto_cbc_encrypt_walk(req, crypto_cbc_encrypt_one); 26 : : } 27 : : 28 : 0 : static inline void crypto_cbc_decrypt_one(struct crypto_skcipher *tfm, 29 : : const u8 *src, u8 *dst) 30 : : { 31 : : crypto_cipher_decrypt_one(skcipher_cipher_simple(tfm), dst, src); 32 : 0 : } 33 : : 34 : 0 : static int crypto_cbc_decrypt(struct skcipher_request *req) 35 : : { 36 : : struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 37 : : struct skcipher_walk walk; 38 : : int err; 39 : : 40 : 0 : err = skcipher_walk_virt(&walk, req, false); 41 : : 42 : 0 : while (walk.nbytes) { 43 : 0 : err = crypto_cbc_decrypt_blocks(&walk, tfm, 44 : : crypto_cbc_decrypt_one); 45 : 0 : err = skcipher_walk_done(&walk, err); 46 : : } 47 : : 48 : 0 : return err; 49 : : } 50 : : 51 : 0 : static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb) 52 : : { 53 : : struct skcipher_instance *inst; 54 : : struct crypto_alg *alg; 55 : : int err; 56 : : 57 : 0 : inst = skcipher_alloc_instance_simple(tmpl, tb, &alg); 58 : 0 : if (IS_ERR(inst)) 59 : 0 : return PTR_ERR(inst); 60 : : 61 : : err = -EINVAL; 62 : 0 : if (!is_power_of_2(alg->cra_blocksize)) 63 : : goto out_free_inst; 64 : : 65 : 0 : inst->alg.encrypt = crypto_cbc_encrypt; 66 : 0 : inst->alg.decrypt = crypto_cbc_decrypt; 67 : : 68 : 0 : err = skcipher_register_instance(tmpl, inst); 69 : 0 : if (err) 70 : : goto out_free_inst; 71 : : goto out_put_alg; 72 : : 73 : : out_free_inst: 74 : 0 : inst->free(inst); 75 : : out_put_alg: 76 : 0 : crypto_mod_put(alg); 77 : 0 : return err; 78 : : } 79 : : 80 : : static struct crypto_template crypto_cbc_tmpl = { 81 : : .name = "cbc", 82 : : .create = crypto_cbc_create, 83 : : .module = THIS_MODULE, 84 : : }; 85 : : 86 : 3 : static int __init crypto_cbc_module_init(void) 87 : : { 88 : 3 : return crypto_register_template(&crypto_cbc_tmpl); 89 : : } 90 : : 91 : 0 : static void __exit crypto_cbc_module_exit(void) 92 : : { 93 : 0 : crypto_unregister_template(&crypto_cbc_tmpl); 94 : 0 : } 95 : : 96 : : subsys_initcall(crypto_cbc_module_init); 97 : : module_exit(crypto_cbc_module_exit); 98 : : 99 : : MODULE_LICENSE("GPL"); 100 : : MODULE_DESCRIPTION("CBC block cipher mode of operation"); 101 : : MODULE_ALIAS_CRYPTO("cbc");