1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * CBC: Cipher Block Chaining mode
5 * Copyright (c) 2006-2016 Herbert Xu <herbert@gondor.apana.org.au>
8 #include <crypto/algapi.h>
9 #include <crypto/internal/cipher.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>
17 static int crypto_cbc_encrypt_segment(struct skcipher_walk
*walk
,
18 struct crypto_skcipher
*skcipher
)
20 unsigned int bsize
= crypto_skcipher_blocksize(skcipher
);
21 void (*fn
)(struct crypto_tfm
*, u8
*, const u8
*);
22 unsigned int nbytes
= walk
->nbytes
;
23 u8
*src
= walk
->src
.virt
.addr
;
24 u8
*dst
= walk
->dst
.virt
.addr
;
25 struct crypto_cipher
*cipher
;
26 struct crypto_tfm
*tfm
;
29 cipher
= skcipher_cipher_simple(skcipher
);
30 tfm
= crypto_cipher_tfm(cipher
);
31 fn
= crypto_cipher_alg(cipher
)->cia_encrypt
;
34 crypto_xor(iv
, src
, bsize
);
36 memcpy(iv
, dst
, bsize
);
40 } while ((nbytes
-= bsize
) >= bsize
);
45 static int crypto_cbc_encrypt_inplace(struct skcipher_walk
*walk
,
46 struct crypto_skcipher
*skcipher
)
48 unsigned int bsize
= crypto_skcipher_blocksize(skcipher
);
49 void (*fn
)(struct crypto_tfm
*, u8
*, const u8
*);
50 unsigned int nbytes
= walk
->nbytes
;
51 u8
*src
= walk
->src
.virt
.addr
;
52 struct crypto_cipher
*cipher
;
53 struct crypto_tfm
*tfm
;
56 cipher
= skcipher_cipher_simple(skcipher
);
57 tfm
= crypto_cipher_tfm(cipher
);
58 fn
= crypto_cipher_alg(cipher
)->cia_encrypt
;
61 crypto_xor(src
, iv
, bsize
);
66 } while ((nbytes
-= bsize
) >= bsize
);
68 memcpy(walk
->iv
, iv
, bsize
);
73 static int crypto_cbc_encrypt(struct skcipher_request
*req
)
75 struct crypto_skcipher
*skcipher
= crypto_skcipher_reqtfm(req
);
76 struct skcipher_walk walk
;
79 err
= skcipher_walk_virt(&walk
, req
, false);
82 if (walk
.src
.virt
.addr
== walk
.dst
.virt
.addr
)
83 err
= crypto_cbc_encrypt_inplace(&walk
, skcipher
);
85 err
= crypto_cbc_encrypt_segment(&walk
, skcipher
);
86 err
= skcipher_walk_done(&walk
, err
);
92 static int crypto_cbc_decrypt_segment(struct skcipher_walk
*walk
,
93 struct crypto_skcipher
*skcipher
)
95 unsigned int bsize
= crypto_skcipher_blocksize(skcipher
);
96 void (*fn
)(struct crypto_tfm
*, u8
*, const u8
*);
97 unsigned int nbytes
= walk
->nbytes
;
98 u8
*src
= walk
->src
.virt
.addr
;
99 u8
*dst
= walk
->dst
.virt
.addr
;
100 struct crypto_cipher
*cipher
;
101 struct crypto_tfm
*tfm
;
104 cipher
= skcipher_cipher_simple(skcipher
);
105 tfm
= crypto_cipher_tfm(cipher
);
106 fn
= crypto_cipher_alg(cipher
)->cia_decrypt
;
110 crypto_xor(dst
, iv
, bsize
);
115 } while ((nbytes
-= bsize
) >= bsize
);
117 memcpy(walk
->iv
, iv
, bsize
);
122 static int crypto_cbc_decrypt_inplace(struct skcipher_walk
*walk
,
123 struct crypto_skcipher
*skcipher
)
125 unsigned int bsize
= crypto_skcipher_blocksize(skcipher
);
126 void (*fn
)(struct crypto_tfm
*, u8
*, const u8
*);
127 unsigned int nbytes
= walk
->nbytes
;
128 u8
*src
= walk
->src
.virt
.addr
;
129 u8 last_iv
[MAX_CIPHER_BLOCKSIZE
];
130 struct crypto_cipher
*cipher
;
131 struct crypto_tfm
*tfm
;
133 cipher
= skcipher_cipher_simple(skcipher
);
134 tfm
= crypto_cipher_tfm(cipher
);
135 fn
= crypto_cipher_alg(cipher
)->cia_decrypt
;
137 /* Start of the last block. */
138 src
+= nbytes
- (nbytes
& (bsize
- 1)) - bsize
;
139 memcpy(last_iv
, src
, bsize
);
143 if ((nbytes
-= bsize
) < bsize
)
145 crypto_xor(src
, src
- bsize
, bsize
);
149 crypto_xor(src
, walk
->iv
, bsize
);
150 memcpy(walk
->iv
, last_iv
, bsize
);
155 static int crypto_cbc_decrypt(struct skcipher_request
*req
)
157 struct crypto_skcipher
*skcipher
= crypto_skcipher_reqtfm(req
);
158 struct skcipher_walk walk
;
161 err
= skcipher_walk_virt(&walk
, req
, false);
163 while (walk
.nbytes
) {
164 if (walk
.src
.virt
.addr
== walk
.dst
.virt
.addr
)
165 err
= crypto_cbc_decrypt_inplace(&walk
, skcipher
);
167 err
= crypto_cbc_decrypt_segment(&walk
, skcipher
);
168 err
= skcipher_walk_done(&walk
, err
);
174 static int crypto_cbc_create(struct crypto_template
*tmpl
, struct rtattr
**tb
)
176 struct skcipher_instance
*inst
;
177 struct crypto_alg
*alg
;
180 inst
= skcipher_alloc_instance_simple(tmpl
, tb
);
182 return PTR_ERR(inst
);
184 alg
= skcipher_ialg_simple(inst
);
187 if (!is_power_of_2(alg
->cra_blocksize
))
190 inst
->alg
.encrypt
= crypto_cbc_encrypt
;
191 inst
->alg
.decrypt
= crypto_cbc_decrypt
;
193 err
= skcipher_register_instance(tmpl
, inst
);
202 static struct crypto_template crypto_cbc_tmpl
= {
204 .create
= crypto_cbc_create
,
205 .module
= THIS_MODULE
,
208 static int __init
crypto_cbc_module_init(void)
210 return crypto_register_template(&crypto_cbc_tmpl
);
213 static void __exit
crypto_cbc_module_exit(void)
215 crypto_unregister_template(&crypto_cbc_tmpl
);
218 subsys_initcall(crypto_cbc_module_init
);
219 module_exit(crypto_cbc_module_exit
);
221 MODULE_LICENSE("GPL");
222 MODULE_DESCRIPTION("CBC block cipher mode of operation");
223 MODULE_ALIAS_CRYPTO("cbc");