2 * CTS: Cipher Text Stealing mode
5 * The Regents of the University of Michigan
8 * Permission is granted to use, copy, create derivative works
9 * and redistribute this software and such derivative works
10 * for any purpose, so long as the name of The University of
11 * Michigan is not used in any advertising or publicity
12 * pertaining to the use of distribution of this software
13 * without specific, written prior authorization. If the
14 * above copyright notice or any other identification of the
15 * University of Michigan is included in any copy of any
16 * portion of this software, then the disclaimer below must
19 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
20 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
21 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
22 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
23 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
25 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
26 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
27 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
28 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
29 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
33 /* Derived from various:
34 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
38 * This is the Cipher Text Stealing mode as described by
39 * Section 8 of rfc2040 and referenced by rfc3962.
40 * rfc3962 includes errata information in its Appendix A.
43 #include <crypto/algapi.h>
44 #include <linux/err.h>
45 #include <linux/init.h>
46 #include <linux/kernel.h>
47 #include <linux/log2.h>
48 #include <linux/module.h>
49 #include <linux/scatterlist.h>
50 #include <crypto/scatterwalk.h>
51 #include <linux/slab.h>
53 struct crypto_cts_ctx
{
54 struct crypto_blkcipher
*child
;
57 static int crypto_cts_setkey(struct crypto_tfm
*parent
, const u8
*key
,
60 struct crypto_cts_ctx
*ctx
= crypto_tfm_ctx(parent
);
61 struct crypto_blkcipher
*child
= ctx
->child
;
64 crypto_blkcipher_clear_flags(child
, CRYPTO_TFM_REQ_MASK
);
65 crypto_blkcipher_set_flags(child
, crypto_tfm_get_flags(parent
) &
67 err
= crypto_blkcipher_setkey(child
, key
, keylen
);
68 crypto_tfm_set_flags(parent
, crypto_blkcipher_get_flags(child
) &
73 static int cts_cbc_encrypt(struct crypto_cts_ctx
*ctx
,
74 struct blkcipher_desc
*desc
,
75 struct scatterlist
*dst
,
76 struct scatterlist
*src
,
80 int bsize
= crypto_blkcipher_blocksize(desc
->tfm
);
81 u8 tmp
[bsize
], tmp2
[bsize
];
82 struct blkcipher_desc lcldesc
;
83 struct scatterlist sgsrc
[1], sgdst
[1];
84 int lastn
= nbytes
- bsize
;
86 u8 s
[bsize
* 2], d
[bsize
* 2];
92 memset(s
, 0, sizeof(s
));
93 scatterwalk_map_and_copy(s
, src
, offset
, nbytes
, 0);
95 memcpy(iv
, desc
->info
, bsize
);
97 lcldesc
.tfm
= ctx
->child
;
99 lcldesc
.flags
= desc
->flags
;
101 sg_set_buf(&sgsrc
[0], s
, bsize
);
102 sg_set_buf(&sgdst
[0], tmp
, bsize
);
103 err
= crypto_blkcipher_encrypt_iv(&lcldesc
, sgdst
, sgsrc
, bsize
);
105 memcpy(d
+ bsize
, tmp
, lastn
);
109 sg_set_buf(&sgsrc
[0], s
+ bsize
, bsize
);
110 sg_set_buf(&sgdst
[0], tmp2
, bsize
);
111 err
= crypto_blkcipher_encrypt_iv(&lcldesc
, sgdst
, sgsrc
, bsize
);
113 memcpy(d
, tmp2
, bsize
);
115 scatterwalk_map_and_copy(d
, dst
, offset
, nbytes
, 1);
117 memcpy(desc
->info
, tmp2
, bsize
);
122 static int crypto_cts_encrypt(struct blkcipher_desc
*desc
,
123 struct scatterlist
*dst
, struct scatterlist
*src
,
126 struct crypto_cts_ctx
*ctx
= crypto_blkcipher_ctx(desc
->tfm
);
127 int bsize
= crypto_blkcipher_blocksize(desc
->tfm
);
128 int tot_blocks
= (nbytes
+ bsize
- 1) / bsize
;
129 int cbc_blocks
= tot_blocks
> 2 ? tot_blocks
- 2 : 0;
130 struct blkcipher_desc lcldesc
;
133 lcldesc
.tfm
= ctx
->child
;
134 lcldesc
.info
= desc
->info
;
135 lcldesc
.flags
= desc
->flags
;
137 if (tot_blocks
== 1) {
138 err
= crypto_blkcipher_encrypt_iv(&lcldesc
, dst
, src
, bsize
);
139 } else if (nbytes
<= bsize
* 2) {
140 err
= cts_cbc_encrypt(ctx
, desc
, dst
, src
, 0, nbytes
);
142 /* do normal function for tot_blocks - 2 */
143 err
= crypto_blkcipher_encrypt_iv(&lcldesc
, dst
, src
,
146 /* do cts for final two blocks */
147 err
= cts_cbc_encrypt(ctx
, desc
, dst
, src
,
149 nbytes
- (cbc_blocks
* bsize
));
156 static int cts_cbc_decrypt(struct crypto_cts_ctx
*ctx
,
157 struct blkcipher_desc
*desc
,
158 struct scatterlist
*dst
,
159 struct scatterlist
*src
,
163 int bsize
= crypto_blkcipher_blocksize(desc
->tfm
);
165 struct blkcipher_desc lcldesc
;
166 struct scatterlist sgsrc
[1], sgdst
[1];
167 int lastn
= nbytes
- bsize
;
169 u8 s
[bsize
* 2], d
[bsize
* 2];
175 scatterwalk_map_and_copy(s
, src
, offset
, nbytes
, 0);
177 lcldesc
.tfm
= ctx
->child
;
179 lcldesc
.flags
= desc
->flags
;
181 /* 1. Decrypt Cn-1 (s) to create Dn (tmp)*/
182 memset(iv
, 0, sizeof(iv
));
183 sg_set_buf(&sgsrc
[0], s
, bsize
);
184 sg_set_buf(&sgdst
[0], tmp
, bsize
);
185 err
= crypto_blkcipher_decrypt_iv(&lcldesc
, sgdst
, sgsrc
, bsize
);
188 /* 2. Pad Cn with zeros at the end to create C of length BB */
189 memset(iv
, 0, sizeof(iv
));
190 memcpy(iv
, s
+ bsize
, lastn
);
191 /* 3. Exclusive-or Dn (tmp) with C (iv) to create Xn (tmp) */
192 crypto_xor(tmp
, iv
, bsize
);
193 /* 4. Select the first Ln bytes of Xn (tmp) to create Pn */
194 memcpy(d
+ bsize
, tmp
, lastn
);
196 /* 5. Append the tail (BB - Ln) bytes of Xn (tmp) to Cn to create En */
197 memcpy(s
+ bsize
+ lastn
, tmp
+ lastn
, bsize
- lastn
);
198 /* 6. Decrypt En to create Pn-1 */
199 memset(iv
, 0, sizeof(iv
));
200 sg_set_buf(&sgsrc
[0], s
+ bsize
, bsize
);
201 sg_set_buf(&sgdst
[0], d
, bsize
);
202 err
= crypto_blkcipher_decrypt_iv(&lcldesc
, sgdst
, sgsrc
, bsize
);
204 /* XOR with previous block */
205 crypto_xor(d
, desc
->info
, bsize
);
207 scatterwalk_map_and_copy(d
, dst
, offset
, nbytes
, 1);
209 memcpy(desc
->info
, s
, bsize
);
213 static int crypto_cts_decrypt(struct blkcipher_desc
*desc
,
214 struct scatterlist
*dst
, struct scatterlist
*src
,
217 struct crypto_cts_ctx
*ctx
= crypto_blkcipher_ctx(desc
->tfm
);
218 int bsize
= crypto_blkcipher_blocksize(desc
->tfm
);
219 int tot_blocks
= (nbytes
+ bsize
- 1) / bsize
;
220 int cbc_blocks
= tot_blocks
> 2 ? tot_blocks
- 2 : 0;
221 struct blkcipher_desc lcldesc
;
224 lcldesc
.tfm
= ctx
->child
;
225 lcldesc
.info
= desc
->info
;
226 lcldesc
.flags
= desc
->flags
;
228 if (tot_blocks
== 1) {
229 err
= crypto_blkcipher_decrypt_iv(&lcldesc
, dst
, src
, bsize
);
230 } else if (nbytes
<= bsize
* 2) {
231 err
= cts_cbc_decrypt(ctx
, desc
, dst
, src
, 0, nbytes
);
233 /* do normal function for tot_blocks - 2 */
234 err
= crypto_blkcipher_decrypt_iv(&lcldesc
, dst
, src
,
237 /* do cts for final two blocks */
238 err
= cts_cbc_decrypt(ctx
, desc
, dst
, src
,
240 nbytes
- (cbc_blocks
* bsize
));
246 static int crypto_cts_init_tfm(struct crypto_tfm
*tfm
)
248 struct crypto_instance
*inst
= (void *)tfm
->__crt_alg
;
249 struct crypto_spawn
*spawn
= crypto_instance_ctx(inst
);
250 struct crypto_cts_ctx
*ctx
= crypto_tfm_ctx(tfm
);
251 struct crypto_blkcipher
*cipher
;
253 cipher
= crypto_spawn_blkcipher(spawn
);
255 return PTR_ERR(cipher
);
261 static void crypto_cts_exit_tfm(struct crypto_tfm
*tfm
)
263 struct crypto_cts_ctx
*ctx
= crypto_tfm_ctx(tfm
);
264 crypto_free_blkcipher(ctx
->child
);
267 static struct crypto_instance
*crypto_cts_alloc(struct rtattr
**tb
)
269 struct crypto_instance
*inst
;
270 struct crypto_alg
*alg
;
273 err
= crypto_check_attr_type(tb
, CRYPTO_ALG_TYPE_BLKCIPHER
);
277 alg
= crypto_attr_alg(tb
[1], CRYPTO_ALG_TYPE_BLKCIPHER
,
278 CRYPTO_ALG_TYPE_MASK
);
283 inst
= ERR_PTR(-EINVAL
);
284 if (!is_power_of_2(alg
->cra_blocksize
))
287 inst
= crypto_alloc_instance("cts", alg
);
291 inst
->alg
.cra_flags
= CRYPTO_ALG_TYPE_BLKCIPHER
;
292 inst
->alg
.cra_priority
= alg
->cra_priority
;
293 inst
->alg
.cra_blocksize
= alg
->cra_blocksize
;
294 inst
->alg
.cra_alignmask
= alg
->cra_alignmask
;
295 inst
->alg
.cra_type
= &crypto_blkcipher_type
;
297 /* We access the data as u32s when xoring. */
298 inst
->alg
.cra_alignmask
|= __alignof__(u32
) - 1;
300 inst
->alg
.cra_blkcipher
.ivsize
= alg
->cra_blocksize
;
301 inst
->alg
.cra_blkcipher
.min_keysize
= alg
->cra_blkcipher
.min_keysize
;
302 inst
->alg
.cra_blkcipher
.max_keysize
= alg
->cra_blkcipher
.max_keysize
;
304 inst
->alg
.cra_blkcipher
.geniv
= "seqiv";
306 inst
->alg
.cra_ctxsize
= sizeof(struct crypto_cts_ctx
);
308 inst
->alg
.cra_init
= crypto_cts_init_tfm
;
309 inst
->alg
.cra_exit
= crypto_cts_exit_tfm
;
311 inst
->alg
.cra_blkcipher
.setkey
= crypto_cts_setkey
;
312 inst
->alg
.cra_blkcipher
.encrypt
= crypto_cts_encrypt
;
313 inst
->alg
.cra_blkcipher
.decrypt
= crypto_cts_decrypt
;
320 static void crypto_cts_free(struct crypto_instance
*inst
)
322 crypto_drop_spawn(crypto_instance_ctx(inst
));
326 static struct crypto_template crypto_cts_tmpl
= {
328 .alloc
= crypto_cts_alloc
,
329 .free
= crypto_cts_free
,
330 .module
= THIS_MODULE
,
333 static int __init
crypto_cts_module_init(void)
335 return crypto_register_template(&crypto_cts_tmpl
);
338 static void __exit
crypto_cts_module_exit(void)
340 crypto_unregister_template(&crypto_cts_tmpl
);
343 module_init(crypto_cts_module_init
);
344 module_exit(crypto_cts_module_exit
);
346 MODULE_LICENSE("Dual BSD/GPL");
347 MODULE_DESCRIPTION("CTS-CBC CipherText Stealing for CBC");