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