2 * eseqiv: Encrypted Sequence Number IV Generator
4 * This generator generates an IV based on a sequence number by xoring it
5 * with a salt and then encrypting it with the same key as used to encrypt
6 * the plain text. This algorithm requires that the block size be equal
7 * to the IV size. It is mainly useful for CBC.
9 * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the Free
13 * Software Foundation; either version 2 of the License, or (at your option)
18 #include <crypto/internal/skcipher.h>
19 #include <crypto/rng.h>
20 #include <crypto/scatterwalk.h>
21 #include <linux/err.h>
22 #include <linux/init.h>
23 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/scatterlist.h>
27 #include <linux/spinlock.h>
28 #include <linux/string.h>
30 struct eseqiv_request_ctx
{
31 struct scatterlist src
[2];
32 struct scatterlist dst
[2];
42 static void eseqiv_complete2(struct skcipher_givcrypt_request
*req
)
44 struct crypto_ablkcipher
*geniv
= skcipher_givcrypt_reqtfm(req
);
45 struct eseqiv_request_ctx
*reqctx
= skcipher_givcrypt_reqctx(req
);
47 memcpy(req
->giv
, PTR_ALIGN((u8
*)reqctx
->tail
,
48 crypto_ablkcipher_alignmask(geniv
) + 1),
49 crypto_ablkcipher_ivsize(geniv
));
52 static void eseqiv_complete(struct crypto_async_request
*base
, int err
)
54 struct skcipher_givcrypt_request
*req
= base
->data
;
59 eseqiv_complete2(req
);
62 skcipher_givcrypt_complete(req
, err
);
65 static int eseqiv_givencrypt(struct skcipher_givcrypt_request
*req
)
67 struct crypto_ablkcipher
*geniv
= skcipher_givcrypt_reqtfm(req
);
68 struct eseqiv_ctx
*ctx
= crypto_ablkcipher_ctx(geniv
);
69 struct eseqiv_request_ctx
*reqctx
= skcipher_givcrypt_reqctx(req
);
70 struct ablkcipher_request
*subreq
;
71 crypto_completion_t
compl;
73 struct scatterlist
*osrc
, *odst
;
74 struct scatterlist
*dst
;
85 subreq
= (void *)(reqctx
->tail
+ ctx
->reqoff
);
86 ablkcipher_request_set_tfm(subreq
, skcipher_geniv_cipher(geniv
));
89 compl = req
->creq
.base
.complete
;
90 data
= req
->creq
.base
.data
;
96 vsrc
= PageHighMem(srcp
) ? NULL
: page_address(srcp
) + osrc
->offset
;
97 vdst
= PageHighMem(dstp
) ? NULL
: page_address(dstp
) + odst
->offset
;
99 ivsize
= crypto_ablkcipher_ivsize(geniv
);
101 if (vsrc
!= giv
+ ivsize
&& vdst
!= giv
+ ivsize
) {
102 giv
= PTR_ALIGN((u8
*)reqctx
->tail
,
103 crypto_ablkcipher_alignmask(geniv
) + 1);
104 compl = eseqiv_complete
;
108 ablkcipher_request_set_callback(subreq
, req
->creq
.base
.flags
, compl,
111 sg_init_table(reqctx
->src
, 2);
112 sg_set_buf(reqctx
->src
, giv
, ivsize
);
113 scatterwalk_crypto_chain(reqctx
->src
, osrc
, vsrc
== giv
+ ivsize
, 2);
117 sg_init_table(reqctx
->dst
, 2);
118 sg_set_buf(reqctx
->dst
, giv
, ivsize
);
119 scatterwalk_crypto_chain(reqctx
->dst
, odst
, vdst
== giv
+ ivsize
, 2);
124 ablkcipher_request_set_crypt(subreq
, reqctx
->src
, dst
,
125 req
->creq
.nbytes
+ ivsize
,
128 memcpy(req
->creq
.info
, ctx
->salt
, ivsize
);
131 if (ivsize
> sizeof(u64
)) {
132 memset(req
->giv
, 0, ivsize
- sizeof(u64
));
135 seq
= cpu_to_be64(req
->seq
);
136 memcpy(req
->giv
+ ivsize
- len
, &seq
, len
);
138 err
= crypto_ablkcipher_encrypt(subreq
);
143 eseqiv_complete2(req
);
149 static int eseqiv_givencrypt_first(struct skcipher_givcrypt_request
*req
)
151 struct crypto_ablkcipher
*geniv
= skcipher_givcrypt_reqtfm(req
);
152 struct eseqiv_ctx
*ctx
= crypto_ablkcipher_ctx(geniv
);
155 spin_lock_bh(&ctx
->lock
);
156 if (crypto_ablkcipher_crt(geniv
)->givencrypt
!= eseqiv_givencrypt_first
)
159 crypto_ablkcipher_crt(geniv
)->givencrypt
= eseqiv_givencrypt
;
160 err
= crypto_rng_get_bytes(crypto_default_rng
, ctx
->salt
,
161 crypto_ablkcipher_ivsize(geniv
));
164 spin_unlock_bh(&ctx
->lock
);
169 return eseqiv_givencrypt(req
);
172 static int eseqiv_init(struct crypto_tfm
*tfm
)
174 struct crypto_ablkcipher
*geniv
= __crypto_ablkcipher_cast(tfm
);
175 struct eseqiv_ctx
*ctx
= crypto_ablkcipher_ctx(geniv
);
176 unsigned long alignmask
;
177 unsigned int reqsize
;
179 spin_lock_init(&ctx
->lock
);
181 alignmask
= crypto_tfm_ctx_alignment() - 1;
182 reqsize
= sizeof(struct eseqiv_request_ctx
);
184 if (alignmask
& reqsize
) {
185 alignmask
&= reqsize
;
189 alignmask
= ~alignmask
;
190 alignmask
&= crypto_ablkcipher_alignmask(geniv
);
192 reqsize
+= alignmask
;
193 reqsize
+= crypto_ablkcipher_ivsize(geniv
);
194 reqsize
= ALIGN(reqsize
, crypto_tfm_ctx_alignment());
196 ctx
->reqoff
= reqsize
- sizeof(struct eseqiv_request_ctx
);
198 tfm
->crt_ablkcipher
.reqsize
= reqsize
+
199 sizeof(struct ablkcipher_request
);
201 return skcipher_geniv_init(tfm
);
204 static struct crypto_template eseqiv_tmpl
;
206 static struct crypto_instance
*eseqiv_alloc(struct rtattr
**tb
)
208 struct crypto_instance
*inst
;
211 err
= crypto_get_default_rng();
215 inst
= skcipher_geniv_alloc(&eseqiv_tmpl
, tb
, 0, 0);
220 if (inst
->alg
.cra_ablkcipher
.ivsize
!= inst
->alg
.cra_blocksize
)
223 inst
->alg
.cra_ablkcipher
.givencrypt
= eseqiv_givencrypt_first
;
225 inst
->alg
.cra_init
= eseqiv_init
;
226 inst
->alg
.cra_exit
= skcipher_geniv_exit
;
228 inst
->alg
.cra_ctxsize
= sizeof(struct eseqiv_ctx
);
229 inst
->alg
.cra_ctxsize
+= inst
->alg
.cra_ablkcipher
.ivsize
;
235 skcipher_geniv_free(inst
);
238 crypto_put_default_rng();
242 static void eseqiv_free(struct crypto_instance
*inst
)
244 skcipher_geniv_free(inst
);
245 crypto_put_default_rng();
248 static struct crypto_template eseqiv_tmpl
= {
250 .alloc
= eseqiv_alloc
,
252 .module
= THIS_MODULE
,
255 static int __init
eseqiv_module_init(void)
257 return crypto_register_template(&eseqiv_tmpl
);
260 static void __exit
eseqiv_module_exit(void)
262 crypto_unregister_template(&eseqiv_tmpl
);
265 module_init(eseqiv_module_init
);
266 module_exit(eseqiv_module_exit
);
268 MODULE_LICENSE("GPL");
269 MODULE_DESCRIPTION("Encrypted Sequence Number IV Generator");