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 : 0 : 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 : 0 : 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 : 0 : struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 37 : 0 : struct skcipher_walk walk; 38 : 0 : 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 : 0 : struct skcipher_instance *inst; 54 : 0 : struct crypto_alg *alg; 55 : 0 : int err; 56 : : 57 : 0 : inst = skcipher_alloc_instance_simple(tmpl, tb); 58 [ # # ]: 0 : if (IS_ERR(inst)) 59 : 0 : return PTR_ERR(inst); 60 : : 61 [ # # ]: 0 : alg = skcipher_ialg_simple(inst); 62 : : 63 : 0 : err = -EINVAL; 64 [ # # # # ]: 0 : if (!is_power_of_2(alg->cra_blocksize)) 65 : 0 : goto out_free_inst; 66 : : 67 : 0 : inst->alg.encrypt = crypto_cbc_encrypt; 68 : 0 : inst->alg.decrypt = crypto_cbc_decrypt; 69 : : 70 : 0 : err = skcipher_register_instance(tmpl, inst); 71 [ # # ]: 0 : if (err) { 72 : 0 : out_free_inst: 73 : 0 : inst->free(inst); 74 : : } 75 : : 76 : : return err; 77 : : } 78 : : 79 : : static struct crypto_template crypto_cbc_tmpl = { 80 : : .name = "cbc", 81 : : .create = crypto_cbc_create, 82 : : .module = THIS_MODULE, 83 : : }; 84 : : 85 : 78 : static int __init crypto_cbc_module_init(void) 86 : : { 87 : 78 : return crypto_register_template(&crypto_cbc_tmpl); 88 : : } 89 : : 90 : 0 : static void __exit crypto_cbc_module_exit(void) 91 : : { 92 : 0 : crypto_unregister_template(&crypto_cbc_tmpl); 93 : 0 : } 94 : : 95 : : subsys_initcall(crypto_cbc_module_init); 96 : : module_exit(crypto_cbc_module_exit); 97 : : 98 : : MODULE_LICENSE("GPL"); 99 : : MODULE_DESCRIPTION("CBC block cipher mode of operation"); 100 : : MODULE_ALIAS_CRYPTO("cbc");