2 * chainiv: Chain IV Generator
4 * Generate IVs simply be using the last block of the previous encryption.
5 * This is mainly useful for CBC with a synchronous algorithm.
7 * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
16 #include <crypto/internal/skcipher.h>
17 #include <crypto/rng.h>
18 #include <linux/err.h>
19 #include <linux/init.h>
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/spinlock.h>
23 #include <linux/string.h>
24 #include <linux/workqueue.h>
27 CHAINIV_STATE_INUSE
= 0,
35 struct async_chainiv_ctx
{
41 struct crypto_queue queue
;
42 struct work_struct postponed
;
47 static int chainiv_givencrypt(struct skcipher_givcrypt_request
*req
)
49 struct crypto_ablkcipher
*geniv
= skcipher_givcrypt_reqtfm(req
);
50 struct chainiv_ctx
*ctx
= crypto_ablkcipher_ctx(geniv
);
51 struct ablkcipher_request
*subreq
= skcipher_givcrypt_reqctx(req
);
55 ablkcipher_request_set_tfm(subreq
, skcipher_geniv_cipher(geniv
));
56 ablkcipher_request_set_callback(subreq
, req
->creq
.base
.flags
&
57 ~CRYPTO_TFM_REQ_MAY_SLEEP
,
58 req
->creq
.base
.complete
,
60 ablkcipher_request_set_crypt(subreq
, req
->creq
.src
, req
->creq
.dst
,
61 req
->creq
.nbytes
, req
->creq
.info
);
63 spin_lock_bh(&ctx
->lock
);
65 ivsize
= crypto_ablkcipher_ivsize(geniv
);
67 memcpy(req
->giv
, ctx
->iv
, ivsize
);
68 memcpy(subreq
->info
, ctx
->iv
, ivsize
);
70 err
= crypto_ablkcipher_encrypt(subreq
);
74 memcpy(ctx
->iv
, subreq
->info
, ivsize
);
77 spin_unlock_bh(&ctx
->lock
);
82 static int chainiv_givencrypt_first(struct skcipher_givcrypt_request
*req
)
84 struct crypto_ablkcipher
*geniv
= skcipher_givcrypt_reqtfm(req
);
85 struct chainiv_ctx
*ctx
= crypto_ablkcipher_ctx(geniv
);
88 spin_lock_bh(&ctx
->lock
);
89 if (crypto_ablkcipher_crt(geniv
)->givencrypt
!=
90 chainiv_givencrypt_first
)
93 crypto_ablkcipher_crt(geniv
)->givencrypt
= chainiv_givencrypt
;
94 err
= crypto_rng_get_bytes(crypto_default_rng
, ctx
->iv
,
95 crypto_ablkcipher_ivsize(geniv
));
98 spin_unlock_bh(&ctx
->lock
);
103 return chainiv_givencrypt(req
);
106 static int chainiv_init_common(struct crypto_tfm
*tfm
)
108 tfm
->crt_ablkcipher
.reqsize
= sizeof(struct ablkcipher_request
);
110 return skcipher_geniv_init(tfm
);
113 static int chainiv_init(struct crypto_tfm
*tfm
)
115 struct chainiv_ctx
*ctx
= crypto_tfm_ctx(tfm
);
117 spin_lock_init(&ctx
->lock
);
119 return chainiv_init_common(tfm
);
122 static int async_chainiv_schedule_work(struct async_chainiv_ctx
*ctx
)
127 if (!ctx
->queue
.qlen
) {
128 smp_mb__before_clear_bit();
129 clear_bit(CHAINIV_STATE_INUSE
, &ctx
->state
);
131 if (!ctx
->queue
.qlen
||
132 test_and_set_bit(CHAINIV_STATE_INUSE
, &ctx
->state
))
136 queued
= schedule_work(&ctx
->postponed
);
143 static int async_chainiv_postpone_request(struct skcipher_givcrypt_request
*req
)
145 struct crypto_ablkcipher
*geniv
= skcipher_givcrypt_reqtfm(req
);
146 struct async_chainiv_ctx
*ctx
= crypto_ablkcipher_ctx(geniv
);
149 spin_lock_bh(&ctx
->lock
);
150 err
= skcipher_enqueue_givcrypt(&ctx
->queue
, req
);
151 spin_unlock_bh(&ctx
->lock
);
153 if (test_and_set_bit(CHAINIV_STATE_INUSE
, &ctx
->state
))
157 return async_chainiv_schedule_work(ctx
);
160 static int async_chainiv_givencrypt_tail(struct skcipher_givcrypt_request
*req
)
162 struct crypto_ablkcipher
*geniv
= skcipher_givcrypt_reqtfm(req
);
163 struct async_chainiv_ctx
*ctx
= crypto_ablkcipher_ctx(geniv
);
164 struct ablkcipher_request
*subreq
= skcipher_givcrypt_reqctx(req
);
165 unsigned int ivsize
= crypto_ablkcipher_ivsize(geniv
);
167 memcpy(req
->giv
, ctx
->iv
, ivsize
);
168 memcpy(subreq
->info
, ctx
->iv
, ivsize
);
170 ctx
->err
= crypto_ablkcipher_encrypt(subreq
);
174 memcpy(ctx
->iv
, subreq
->info
, ivsize
);
177 return async_chainiv_schedule_work(ctx
);
180 static int async_chainiv_givencrypt(struct skcipher_givcrypt_request
*req
)
182 struct crypto_ablkcipher
*geniv
= skcipher_givcrypt_reqtfm(req
);
183 struct async_chainiv_ctx
*ctx
= crypto_ablkcipher_ctx(geniv
);
184 struct ablkcipher_request
*subreq
= skcipher_givcrypt_reqctx(req
);
186 ablkcipher_request_set_tfm(subreq
, skcipher_geniv_cipher(geniv
));
187 ablkcipher_request_set_callback(subreq
, req
->creq
.base
.flags
,
188 req
->creq
.base
.complete
,
189 req
->creq
.base
.data
);
190 ablkcipher_request_set_crypt(subreq
, req
->creq
.src
, req
->creq
.dst
,
191 req
->creq
.nbytes
, req
->creq
.info
);
193 if (test_and_set_bit(CHAINIV_STATE_INUSE
, &ctx
->state
))
196 if (ctx
->queue
.qlen
) {
197 clear_bit(CHAINIV_STATE_INUSE
, &ctx
->state
);
201 return async_chainiv_givencrypt_tail(req
);
204 return async_chainiv_postpone_request(req
);
207 static int async_chainiv_givencrypt_first(struct skcipher_givcrypt_request
*req
)
209 struct crypto_ablkcipher
*geniv
= skcipher_givcrypt_reqtfm(req
);
210 struct async_chainiv_ctx
*ctx
= crypto_ablkcipher_ctx(geniv
);
213 if (test_and_set_bit(CHAINIV_STATE_INUSE
, &ctx
->state
))
216 if (crypto_ablkcipher_crt(geniv
)->givencrypt
!=
217 async_chainiv_givencrypt_first
)
220 crypto_ablkcipher_crt(geniv
)->givencrypt
= async_chainiv_givencrypt
;
221 err
= crypto_rng_get_bytes(crypto_default_rng
, ctx
->iv
,
222 crypto_ablkcipher_ivsize(geniv
));
225 clear_bit(CHAINIV_STATE_INUSE
, &ctx
->state
);
231 return async_chainiv_givencrypt(req
);
234 static void async_chainiv_do_postponed(struct work_struct
*work
)
236 struct async_chainiv_ctx
*ctx
= container_of(work
,
237 struct async_chainiv_ctx
,
239 struct skcipher_givcrypt_request
*req
;
240 struct ablkcipher_request
*subreq
;
243 /* Only handle one request at a time to avoid hogging keventd. */
244 spin_lock_bh(&ctx
->lock
);
245 req
= skcipher_dequeue_givcrypt(&ctx
->queue
);
246 spin_unlock_bh(&ctx
->lock
);
249 async_chainiv_schedule_work(ctx
);
253 subreq
= skcipher_givcrypt_reqctx(req
);
254 subreq
->base
.flags
|= CRYPTO_TFM_REQ_MAY_SLEEP
;
256 err
= async_chainiv_givencrypt_tail(req
);
259 skcipher_givcrypt_complete(req
, err
);
263 static int async_chainiv_init(struct crypto_tfm
*tfm
)
265 struct async_chainiv_ctx
*ctx
= crypto_tfm_ctx(tfm
);
267 spin_lock_init(&ctx
->lock
);
269 crypto_init_queue(&ctx
->queue
, 100);
270 INIT_WORK(&ctx
->postponed
, async_chainiv_do_postponed
);
272 return chainiv_init_common(tfm
);
275 static void async_chainiv_exit(struct crypto_tfm
*tfm
)
277 struct async_chainiv_ctx
*ctx
= crypto_tfm_ctx(tfm
);
279 BUG_ON(test_bit(CHAINIV_STATE_INUSE
, &ctx
->state
) || ctx
->queue
.qlen
);
281 skcipher_geniv_exit(tfm
);
284 static struct crypto_template chainiv_tmpl
;
286 static struct crypto_instance
*chainiv_alloc(struct rtattr
**tb
)
288 struct crypto_attr_type
*algt
;
289 struct crypto_instance
*inst
;
292 algt
= crypto_get_attr_type(tb
);
297 err
= crypto_get_default_rng();
301 inst
= skcipher_geniv_alloc(&chainiv_tmpl
, tb
, 0, 0);
305 inst
->alg
.cra_ablkcipher
.givencrypt
= chainiv_givencrypt_first
;
307 inst
->alg
.cra_init
= chainiv_init
;
308 inst
->alg
.cra_exit
= skcipher_geniv_exit
;
310 inst
->alg
.cra_ctxsize
= sizeof(struct chainiv_ctx
);
312 if (!crypto_requires_sync(algt
->type
, algt
->mask
)) {
313 inst
->alg
.cra_flags
|= CRYPTO_ALG_ASYNC
;
315 inst
->alg
.cra_ablkcipher
.givencrypt
=
316 async_chainiv_givencrypt_first
;
318 inst
->alg
.cra_init
= async_chainiv_init
;
319 inst
->alg
.cra_exit
= async_chainiv_exit
;
321 inst
->alg
.cra_ctxsize
= sizeof(struct async_chainiv_ctx
);
324 inst
->alg
.cra_ctxsize
+= inst
->alg
.cra_ablkcipher
.ivsize
;
330 crypto_put_default_rng();
334 static void chainiv_free(struct crypto_instance
*inst
)
336 skcipher_geniv_free(inst
);
337 crypto_put_default_rng();
340 static struct crypto_template chainiv_tmpl
= {
342 .alloc
= chainiv_alloc
,
343 .free
= chainiv_free
,
344 .module
= THIS_MODULE
,
347 static int __init
chainiv_module_init(void)
349 return crypto_register_template(&chainiv_tmpl
);
352 static void chainiv_module_exit(void)
354 crypto_unregister_template(&chainiv_tmpl
);
357 module_init(chainiv_module_init
);
358 module_exit(chainiv_module_exit
);
360 MODULE_LICENSE("GPL");
361 MODULE_DESCRIPTION("Chain IV Generator");