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/internal/skcipher.h>
10 #include <linux/init.h>
11 #include <linux/kernel.h>
12 #include <linux/log2.h>
13 #include <linux/module.h>
15 static int crypto_cbc_encrypt_segment(struct crypto_lskcipher
*tfm
,
16 const u8
*src
, u8
*dst
, unsigned nbytes
,
19 unsigned int bsize
= crypto_lskcipher_blocksize(tfm
);
21 for (; nbytes
>= bsize
; src
+= bsize
, dst
+= bsize
, nbytes
-= bsize
) {
22 crypto_xor(iv
, src
, bsize
);
23 crypto_lskcipher_encrypt(tfm
, iv
, dst
, bsize
, NULL
);
24 memcpy(iv
, dst
, bsize
);
30 static int crypto_cbc_encrypt_inplace(struct crypto_lskcipher
*tfm
,
31 u8
*src
, unsigned nbytes
, u8
*oiv
)
33 unsigned int bsize
= crypto_lskcipher_blocksize(tfm
);
40 crypto_xor(src
, iv
, bsize
);
41 crypto_lskcipher_encrypt(tfm
, src
, src
, bsize
, NULL
);
45 } while ((nbytes
-= bsize
) >= bsize
);
47 memcpy(oiv
, iv
, bsize
);
53 static int crypto_cbc_encrypt(struct crypto_lskcipher
*tfm
, const u8
*src
,
54 u8
*dst
, unsigned len
, u8
*iv
, bool final
)
56 struct crypto_lskcipher
**ctx
= crypto_lskcipher_ctx(tfm
);
57 struct crypto_lskcipher
*cipher
= *ctx
;
61 rem
= crypto_cbc_encrypt_inplace(cipher
, dst
, len
, iv
);
63 rem
= crypto_cbc_encrypt_segment(cipher
, src
, dst
, len
, iv
);
65 return rem
&& final
? -EINVAL
: rem
;
68 static int crypto_cbc_decrypt_segment(struct crypto_lskcipher
*tfm
,
69 const u8
*src
, u8
*dst
, unsigned nbytes
,
72 unsigned int bsize
= crypto_lskcipher_blocksize(tfm
);
79 crypto_lskcipher_decrypt(tfm
, src
, dst
, bsize
, NULL
);
80 crypto_xor(dst
, iv
, bsize
);
85 } while ((nbytes
-= bsize
) >= bsize
);
87 memcpy(oiv
, iv
, bsize
);
93 static int crypto_cbc_decrypt_inplace(struct crypto_lskcipher
*tfm
,
94 u8
*src
, unsigned nbytes
, u8
*iv
)
96 unsigned int bsize
= crypto_lskcipher_blocksize(tfm
);
97 u8 last_iv
[MAX_CIPHER_BLOCKSIZE
];
102 /* Start of the last block. */
103 src
+= nbytes
- (nbytes
& (bsize
- 1)) - bsize
;
104 memcpy(last_iv
, src
, bsize
);
107 crypto_lskcipher_decrypt(tfm
, src
, src
, bsize
, NULL
);
108 if ((nbytes
-= bsize
) < bsize
)
110 crypto_xor(src
, src
- bsize
, bsize
);
114 crypto_xor(src
, iv
, bsize
);
115 memcpy(iv
, last_iv
, bsize
);
121 static int crypto_cbc_decrypt(struct crypto_lskcipher
*tfm
, const u8
*src
,
122 u8
*dst
, unsigned len
, u8
*iv
, bool final
)
124 struct crypto_lskcipher
**ctx
= crypto_lskcipher_ctx(tfm
);
125 struct crypto_lskcipher
*cipher
= *ctx
;
129 rem
= crypto_cbc_decrypt_inplace(cipher
, dst
, len
, iv
);
131 rem
= crypto_cbc_decrypt_segment(cipher
, src
, dst
, len
, iv
);
133 return rem
&& final
? -EINVAL
: rem
;
136 static int crypto_cbc_create(struct crypto_template
*tmpl
, struct rtattr
**tb
)
138 struct lskcipher_instance
*inst
;
141 inst
= lskcipher_alloc_instance_simple(tmpl
, tb
);
143 return PTR_ERR(inst
);
146 if (!is_power_of_2(inst
->alg
.co
.base
.cra_blocksize
))
149 inst
->alg
.encrypt
= crypto_cbc_encrypt
;
150 inst
->alg
.decrypt
= crypto_cbc_decrypt
;
152 err
= lskcipher_register_instance(tmpl
, inst
);
161 static struct crypto_template crypto_cbc_tmpl
= {
163 .create
= crypto_cbc_create
,
164 .module
= THIS_MODULE
,
167 static int __init
crypto_cbc_module_init(void)
169 return crypto_register_template(&crypto_cbc_tmpl
);
172 static void __exit
crypto_cbc_module_exit(void)
174 crypto_unregister_template(&crypto_cbc_tmpl
);
177 subsys_initcall(crypto_cbc_module_init
);
178 module_exit(crypto_cbc_module_exit
);
180 MODULE_LICENSE("GPL");
181 MODULE_DESCRIPTION("CBC block cipher mode of operation");
182 MODULE_ALIAS_CRYPTO("cbc");