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_init(struct crypto_tfm
*tfm
)
151 struct crypto_ablkcipher
*geniv
= __crypto_ablkcipher_cast(tfm
);
152 struct eseqiv_ctx
*ctx
= crypto_ablkcipher_ctx(geniv
);
153 unsigned long alignmask
;
154 unsigned int reqsize
;
157 spin_lock_init(&ctx
->lock
);
159 alignmask
= crypto_tfm_ctx_alignment() - 1;
160 reqsize
= sizeof(struct eseqiv_request_ctx
);
162 if (alignmask
& reqsize
) {
163 alignmask
&= reqsize
;
167 alignmask
= ~alignmask
;
168 alignmask
&= crypto_ablkcipher_alignmask(geniv
);
170 reqsize
+= alignmask
;
171 reqsize
+= crypto_ablkcipher_ivsize(geniv
);
172 reqsize
= ALIGN(reqsize
, crypto_tfm_ctx_alignment());
174 ctx
->reqoff
= reqsize
- sizeof(struct eseqiv_request_ctx
);
176 tfm
->crt_ablkcipher
.reqsize
= reqsize
+
177 sizeof(struct ablkcipher_request
);
180 if (!crypto_get_default_rng()) {
181 crypto_ablkcipher_crt(geniv
)->givencrypt
= eseqiv_givencrypt
;
182 err
= crypto_rng_get_bytes(crypto_default_rng
, ctx
->salt
,
183 crypto_ablkcipher_ivsize(geniv
));
184 crypto_put_default_rng();
187 return err
?: skcipher_geniv_init(tfm
);
190 static struct crypto_template eseqiv_tmpl
;
192 static struct crypto_instance
*eseqiv_alloc(struct rtattr
**tb
)
194 struct crypto_instance
*inst
;
197 inst
= skcipher_geniv_alloc(&eseqiv_tmpl
, tb
, 0, 0);
202 if (inst
->alg
.cra_ablkcipher
.ivsize
!= inst
->alg
.cra_blocksize
)
205 inst
->alg
.cra_init
= eseqiv_init
;
206 inst
->alg
.cra_exit
= skcipher_geniv_exit
;
208 inst
->alg
.cra_ctxsize
= sizeof(struct eseqiv_ctx
);
209 inst
->alg
.cra_ctxsize
+= inst
->alg
.cra_ablkcipher
.ivsize
;
215 skcipher_geniv_free(inst
);
220 static struct crypto_template eseqiv_tmpl
= {
222 .alloc
= eseqiv_alloc
,
223 .free
= skcipher_geniv_free
,
224 .module
= THIS_MODULE
,
227 static int __init
eseqiv_module_init(void)
229 return crypto_register_template(&eseqiv_tmpl
);
232 static void __exit
eseqiv_module_exit(void)
234 crypto_unregister_template(&eseqiv_tmpl
);
237 module_init(eseqiv_module_init
);
238 module_exit(eseqiv_module_exit
);
240 MODULE_LICENSE("GPL");
241 MODULE_DESCRIPTION("Encrypted Sequence Number IV Generator");
242 MODULE_ALIAS_CRYPTO("eseqiv");