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
, u32 flags
)
56 struct crypto_lskcipher
**ctx
= crypto_lskcipher_ctx(tfm
);
57 bool final
= flags
& CRYPTO_LSKCIPHER_FLAG_FINAL
;
58 struct crypto_lskcipher
*cipher
= *ctx
;
62 rem
= crypto_cbc_encrypt_inplace(cipher
, dst
, len
, iv
);
64 rem
= crypto_cbc_encrypt_segment(cipher
, src
, dst
, len
, iv
);
66 return rem
&& final
? -EINVAL
: rem
;
69 static int crypto_cbc_decrypt_segment(struct crypto_lskcipher
*tfm
,
70 const u8
*src
, u8
*dst
, unsigned nbytes
,
73 unsigned int bsize
= crypto_lskcipher_blocksize(tfm
);
80 crypto_lskcipher_decrypt(tfm
, src
, dst
, bsize
, NULL
);
81 crypto_xor(dst
, iv
, bsize
);
86 } while ((nbytes
-= bsize
) >= bsize
);
88 memcpy(oiv
, iv
, bsize
);
94 static int crypto_cbc_decrypt_inplace(struct crypto_lskcipher
*tfm
,
95 u8
*src
, unsigned nbytes
, u8
*iv
)
97 unsigned int bsize
= crypto_lskcipher_blocksize(tfm
);
98 u8 last_iv
[MAX_CIPHER_BLOCKSIZE
];
103 /* Start of the last block. */
104 src
+= nbytes
- (nbytes
& (bsize
- 1)) - bsize
;
105 memcpy(last_iv
, src
, bsize
);
108 crypto_lskcipher_decrypt(tfm
, src
, src
, bsize
, NULL
);
109 if ((nbytes
-= bsize
) < bsize
)
111 crypto_xor(src
, src
- bsize
, bsize
);
115 crypto_xor(src
, iv
, bsize
);
116 memcpy(iv
, last_iv
, bsize
);
122 static int crypto_cbc_decrypt(struct crypto_lskcipher
*tfm
, const u8
*src
,
123 u8
*dst
, unsigned len
, u8
*iv
, u32 flags
)
125 struct crypto_lskcipher
**ctx
= crypto_lskcipher_ctx(tfm
);
126 bool final
= flags
& CRYPTO_LSKCIPHER_FLAG_FINAL
;
127 struct crypto_lskcipher
*cipher
= *ctx
;
131 rem
= crypto_cbc_decrypt_inplace(cipher
, dst
, len
, iv
);
133 rem
= crypto_cbc_decrypt_segment(cipher
, src
, dst
, len
, iv
);
135 return rem
&& final
? -EINVAL
: rem
;
138 static int crypto_cbc_create(struct crypto_template
*tmpl
, struct rtattr
**tb
)
140 struct lskcipher_instance
*inst
;
143 inst
= lskcipher_alloc_instance_simple(tmpl
, tb
);
145 return PTR_ERR(inst
);
148 if (!is_power_of_2(inst
->alg
.co
.base
.cra_blocksize
))
151 if (inst
->alg
.co
.statesize
)
154 inst
->alg
.encrypt
= crypto_cbc_encrypt
;
155 inst
->alg
.decrypt
= crypto_cbc_decrypt
;
157 err
= lskcipher_register_instance(tmpl
, inst
);
166 static struct crypto_template crypto_cbc_tmpl
= {
168 .create
= crypto_cbc_create
,
169 .module
= THIS_MODULE
,
172 static int __init
crypto_cbc_module_init(void)
174 return crypto_register_template(&crypto_cbc_tmpl
);
177 static void __exit
crypto_cbc_module_exit(void)
179 crypto_unregister_template(&crypto_cbc_tmpl
);
182 subsys_initcall(crypto_cbc_module_init
);
183 module_exit(crypto_cbc_module_exit
);
185 MODULE_LICENSE("GPL");
186 MODULE_DESCRIPTION("CBC block cipher mode of operation");
187 MODULE_ALIAS_CRYPTO("cbc");