2 * Copyright (C)2006 USAGI/WIDE Project
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * Kazunori Miyazawa <miyazawa@linux-ipv6.org>
22 #include <linux/crypto.h>
23 #include <linux/err.h>
24 #include <linux/hardirq.h>
25 #include <linux/kernel.h>
27 #include <linux/rtnetlink.h>
28 #include <linux/slab.h>
29 #include <linux/scatterlist.h>
32 static u_int32_t ks
[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
33 0x02020202, 0x02020202, 0x02020202, 0x02020202,
34 0x03030303, 0x03030303, 0x03030303, 0x03030303};
36 * +------------------------
38 * +------------------------
40 * +------------------------
42 * +------------------------
44 * +------------------------
46 * +------------------------
47 * | consts (block size * 3)
48 * +------------------------
50 struct crypto_xcbc_ctx
{
51 struct crypto_tfm
*child
;
56 void (*xor)(u8
*a
, const u8
*b
, unsigned int bs
);
61 static void xor_128(u8
*a
, const u8
*b
, unsigned int bs
)
63 ((u32
*)a
)[0] ^= ((u32
*)b
)[0];
64 ((u32
*)a
)[1] ^= ((u32
*)b
)[1];
65 ((u32
*)a
)[2] ^= ((u32
*)b
)[2];
66 ((u32
*)a
)[3] ^= ((u32
*)b
)[3];
69 static int _crypto_xcbc_digest_setkey(struct crypto_hash
*parent
,
70 struct crypto_xcbc_ctx
*ctx
)
72 int bs
= crypto_hash_blocksize(parent
);
76 if ((err
= crypto_cipher_setkey(ctx
->child
, ctx
->key
, ctx
->keylen
)))
79 ctx
->child
->__crt_alg
->cra_cipher
.cia_encrypt(ctx
->child
, key1
,
82 return crypto_cipher_setkey(ctx
->child
, key1
, bs
);
85 static int crypto_xcbc_digest_setkey(struct crypto_hash
*parent
,
86 const u8
*inkey
, unsigned int keylen
)
88 struct crypto_xcbc_ctx
*ctx
= crypto_hash_ctx_aligned(parent
);
90 if (keylen
!= crypto_tfm_alg_blocksize(ctx
->child
))
94 memcpy(ctx
->key
, inkey
, keylen
);
95 ctx
->consts
= (u8
*)ks
;
97 return _crypto_xcbc_digest_setkey(parent
, ctx
);
100 static int crypto_xcbc_digest_init(struct hash_desc
*pdesc
)
102 struct crypto_xcbc_ctx
*ctx
= crypto_hash_ctx_aligned(pdesc
->tfm
);
103 int bs
= crypto_hash_blocksize(pdesc
->tfm
);
106 memset(ctx
->odds
, 0, bs
);
107 memset(ctx
->prev
, 0, bs
);
112 static int crypto_xcbc_digest_update2(struct hash_desc
*pdesc
,
113 struct scatterlist
*sg
,
116 struct crypto_hash
*parent
= pdesc
->tfm
;
117 struct crypto_xcbc_ctx
*ctx
= crypto_hash_ctx_aligned(parent
);
118 struct crypto_tfm
*tfm
= ctx
->child
;
119 int bs
= crypto_hash_blocksize(parent
);
124 struct page
*pg
= sg
[i
].page
;
125 unsigned int offset
= sg
[i
].offset
;
126 unsigned int slen
= sg
[i
].length
;
129 unsigned int len
= min(slen
, ((unsigned int)(PAGE_SIZE
)) - offset
);
130 char *p
= crypto_kmap(pg
, 0) + offset
;
132 /* checking the data can fill the block */
133 if ((ctx
->len
+ len
) <= bs
) {
134 memcpy(ctx
->odds
+ ctx
->len
, p
, len
);
138 /* checking the rest of the page */
139 if (len
+ offset
>= PAGE_SIZE
) {
146 crypto_yield(tfm
->crt_flags
);
150 /* filling odds with new data and encrypting it */
151 memcpy(ctx
->odds
+ ctx
->len
, p
, bs
- ctx
->len
);
152 len
-= bs
- ctx
->len
;
155 ctx
->xor(ctx
->prev
, ctx
->odds
, bs
);
156 tfm
->__crt_alg
->cra_cipher
.cia_encrypt(tfm
, ctx
->prev
, ctx
->prev
);
158 /* clearing the length */
161 /* encrypting the rest of data */
163 ctx
->xor(ctx
->prev
, p
, bs
);
164 tfm
->__crt_alg
->cra_cipher
.cia_encrypt(tfm
, ctx
->prev
, ctx
->prev
);
169 /* keeping the surplus of blocksize */
171 memcpy(ctx
->odds
, p
, len
);
175 crypto_yield(tfm
->crt_flags
);
176 slen
-= min(slen
, ((unsigned int)(PAGE_SIZE
)) - offset
);
180 nbytes
-=sg
[i
].length
;
187 static int crypto_xcbc_digest_update(struct hash_desc
*pdesc
,
188 struct scatterlist
*sg
,
191 if (WARN_ON_ONCE(in_irq()))
193 return crypto_xcbc_digest_update2(pdesc
, sg
, nbytes
);
196 static int crypto_xcbc_digest_final(struct hash_desc
*pdesc
, u8
*out
)
198 struct crypto_hash
*parent
= pdesc
->tfm
;
199 struct crypto_xcbc_ctx
*ctx
= crypto_hash_ctx_aligned(parent
);
200 struct crypto_tfm
*tfm
= ctx
->child
;
201 int bs
= crypto_hash_blocksize(parent
);
204 if (ctx
->len
== bs
) {
207 if ((err
= crypto_cipher_setkey(tfm
, ctx
->key
, ctx
->keylen
)) != 0)
210 tfm
->__crt_alg
->cra_cipher
.cia_encrypt(tfm
, key2
, (const u8
*)(ctx
->consts
+bs
));
212 ctx
->xor(ctx
->prev
, ctx
->odds
, bs
);
213 ctx
->xor(ctx
->prev
, key2
, bs
);
214 _crypto_xcbc_digest_setkey(parent
, ctx
);
216 tfm
->__crt_alg
->cra_cipher
.cia_encrypt(tfm
, out
, ctx
->prev
);
220 u8
*p
= ctx
->odds
+ ctx
->len
;
224 rlen
= bs
- ctx
->len
-1;
228 if ((err
= crypto_cipher_setkey(tfm
, ctx
->key
, ctx
->keylen
)) != 0)
231 tfm
->__crt_alg
->cra_cipher
.cia_encrypt(tfm
, key3
, (const u8
*)(ctx
->consts
+bs
*2));
233 ctx
->xor(ctx
->prev
, ctx
->odds
, bs
);
234 ctx
->xor(ctx
->prev
, key3
, bs
);
236 _crypto_xcbc_digest_setkey(parent
, ctx
);
238 tfm
->__crt_alg
->cra_cipher
.cia_encrypt(tfm
, out
, ctx
->prev
);
244 static int crypto_xcbc_digest(struct hash_desc
*pdesc
,
245 struct scatterlist
*sg
, unsigned int nbytes
, u8
*out
)
247 if (WARN_ON_ONCE(in_irq()))
250 crypto_xcbc_digest_init(pdesc
);
251 crypto_xcbc_digest_update2(pdesc
, sg
, nbytes
);
252 return crypto_xcbc_digest_final(pdesc
, out
);
255 static int xcbc_init_tfm(struct crypto_tfm
*tfm
)
257 struct crypto_instance
*inst
= (void *)tfm
->__crt_alg
;
258 struct crypto_spawn
*spawn
= crypto_instance_ctx(inst
);
259 struct crypto_xcbc_ctx
*ctx
= crypto_hash_ctx_aligned(__crypto_hash_cast(tfm
));
260 int bs
= crypto_hash_blocksize(__crypto_hash_cast(tfm
));
262 tfm
= crypto_spawn_tfm(spawn
);
274 ctx
->child
= crypto_cipher_cast(tfm
);
275 ctx
->odds
= (u8
*)(ctx
+1);
276 ctx
->prev
= ctx
->odds
+ bs
;
277 ctx
->key
= ctx
->prev
+ bs
;
282 static void xcbc_exit_tfm(struct crypto_tfm
*tfm
)
284 struct crypto_xcbc_ctx
*ctx
= crypto_hash_ctx_aligned(__crypto_hash_cast(tfm
));
285 crypto_free_cipher(ctx
->child
);
288 static struct crypto_instance
*xcbc_alloc(void *param
, unsigned int len
)
290 struct crypto_instance
*inst
;
291 struct crypto_alg
*alg
;
292 alg
= crypto_get_attr_alg(param
, len
, CRYPTO_ALG_TYPE_CIPHER
,
293 CRYPTO_ALG_TYPE_HASH_MASK
| CRYPTO_ALG_ASYNC
);
295 return ERR_PTR(PTR_ERR(alg
));
297 switch(alg
->cra_blocksize
) {
301 return ERR_PTR(PTR_ERR(alg
));
304 inst
= crypto_alloc_instance("xcbc", alg
);
308 inst
->alg
.cra_flags
= CRYPTO_ALG_TYPE_HASH
;
309 inst
->alg
.cra_priority
= alg
->cra_priority
;
310 inst
->alg
.cra_blocksize
= alg
->cra_blocksize
;
311 inst
->alg
.cra_alignmask
= alg
->cra_alignmask
;
312 inst
->alg
.cra_type
= &crypto_hash_type
;
314 inst
->alg
.cra_hash
.digestsize
=
315 (alg
->cra_flags
& CRYPTO_ALG_TYPE_MASK
) ==
316 CRYPTO_ALG_TYPE_HASH
? alg
->cra_hash
.digestsize
:
318 inst
->alg
.cra_ctxsize
= sizeof(struct crypto_xcbc_ctx
) +
319 ALIGN(inst
->alg
.cra_blocksize
* 3, sizeof(void *));
320 inst
->alg
.cra_init
= xcbc_init_tfm
;
321 inst
->alg
.cra_exit
= xcbc_exit_tfm
;
323 inst
->alg
.cra_hash
.init
= crypto_xcbc_digest_init
;
324 inst
->alg
.cra_hash
.update
= crypto_xcbc_digest_update
;
325 inst
->alg
.cra_hash
.final
= crypto_xcbc_digest_final
;
326 inst
->alg
.cra_hash
.digest
= crypto_xcbc_digest
;
327 inst
->alg
.cra_hash
.setkey
= crypto_xcbc_digest_setkey
;
334 static void xcbc_free(struct crypto_instance
*inst
)
336 crypto_drop_spawn(crypto_instance_ctx(inst
));
340 static struct crypto_template crypto_xcbc_tmpl
= {
344 .module
= THIS_MODULE
,
347 static int __init
crypto_xcbc_module_init(void)
349 return crypto_register_template(&crypto_xcbc_tmpl
);
352 static void __exit
crypto_xcbc_module_exit(void)
354 crypto_unregister_template(&crypto_xcbc_tmpl
);
357 module_init(crypto_xcbc_module_init
);
358 module_exit(crypto_xcbc_module_exit
);
360 MODULE_LICENSE("GPL");
361 MODULE_DESCRIPTION("XCBC keyed hash algorithm");