aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/tcrypt.c
diff options
context:
space:
mode:
authorMikko Herranen <mh1@iki.fi>2007-11-26 09:12:07 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2008-01-10 16:16:23 -0500
commite3a4ea4fd2e5f154ae9233f1ce30e7564e5cbcfc (patch)
tree8564aa42c333db6170cdc5dfc93e7a82bc315b27 /crypto/tcrypt.c
parentff85a8082f0665fe6f79d50eb79bdccb98cabfa2 (diff)
[CRYPTO] tcrypt: Add aead support
Add AEAD support to tcrypt, needed by GCM. Signed-off-by: Mikko Herranen <mh1@iki.fi> Reviewed-by: Mika Kukkonen <mika.kukkonen@nsn.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/tcrypt.c')
-rw-r--r--crypto/tcrypt.c258
1 files changed, 249 insertions, 9 deletions
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index b8cb1d1420ae..b343d81d20c9 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -6,12 +6,14 @@
6 * 6 *
7 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> 7 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
8 * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org> 8 * Copyright (c) 2002 Jean-Francois Dive <jef@linuxbe.org>
9 * Copyright (c) 2007 Nokia Siemens Networks
9 * 10 *
10 * This program is free software; you can redistribute it and/or modify it 11 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free 12 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option) 13 * Software Foundation; either version 2 of the License, or (at your option)
13 * any later version. 14 * any later version.
14 * 15 *
16 * 2007-11-13 Added AEAD support
15 * 2007-11-06 Added SHA-224 and SHA-224-HMAC tests 17 * 2007-11-06 Added SHA-224 and SHA-224-HMAC tests
16 * 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests 18 * 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests
17 * 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk@vantronix.net>) 19 * 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk@vantronix.net>)
@@ -72,6 +74,7 @@ static unsigned int sec;
72 74
73static int mode; 75static int mode;
74static char *xbuf; 76static char *xbuf;
77static char *axbuf;
75static char *tvmem; 78static char *tvmem;
76 79
77static char *check[] = { 80static char *check[] = {
@@ -169,6 +172,7 @@ static void test_hash(char *algo, struct hash_testvec *template,
169 172
170 /* setup the dummy buffer first */ 173 /* setup the dummy buffer first */
171 memset(xbuf, 0, XBUFSIZE); 174 memset(xbuf, 0, XBUFSIZE);
175 memset(axbuf, 0, XBUFSIZE);
172 176
173 j = 0; 177 j = 0;
174 for (i = 0; i < tcount; i++) { 178 for (i = 0; i < tcount; i++) {
@@ -217,6 +221,233 @@ out:
217 crypto_free_hash(tfm); 221 crypto_free_hash(tfm);
218} 222}
219 223
224static void test_aead(char *algo, int enc, struct aead_testvec *template,
225 unsigned int tcount)
226{
227 unsigned int ret, i, j, k, temp;
228 unsigned int tsize;
229 char *q;
230 struct crypto_aead *tfm;
231 char *key;
232 struct aead_testvec *aead_tv;
233 struct aead_request *req;
234 struct scatterlist sg[8];
235 struct scatterlist asg[8];
236 const char *e;
237 struct tcrypt_result result;
238
239 if (enc == ENCRYPT)
240 e = "encryption";
241 else
242 e = "decryption";
243
244 printk(KERN_INFO "\ntesting %s %s\n", algo, e);
245
246 tsize = sizeof(struct aead_testvec);
247 tsize *= tcount;
248
249 if (tsize > TVMEMSIZE) {
250 printk(KERN_INFO "template (%u) too big for tvmem (%u)\n",
251 tsize, TVMEMSIZE);
252 return;
253 }
254
255 memcpy(tvmem, template, tsize);
256 aead_tv = (void *)tvmem;
257
258 init_completion(&result.completion);
259
260 tfm = crypto_alloc_aead(algo, 0, 0);
261
262 if (IS_ERR(tfm)) {
263 printk(KERN_INFO "failed to load transform for %s: %ld\n",
264 algo, PTR_ERR(tfm));
265 return;
266 }
267
268 req = aead_request_alloc(tfm, GFP_KERNEL);
269 if (!req) {
270 printk(KERN_INFO "failed to allocate request for %s\n", algo);
271 goto out;
272 }
273
274 aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
275 tcrypt_complete, &result);
276
277 for (i = 0, j = 0; i < tcount; i++) {
278 if (!aead_tv[i].np) {
279 printk(KERN_INFO "test %u (%d bit key):\n",
280 ++j, aead_tv[i].klen * 8);
281
282 crypto_aead_clear_flags(tfm, ~0);
283 if (aead_tv[i].wk)
284 crypto_aead_set_flags(
285 tfm, CRYPTO_TFM_REQ_WEAK_KEY);
286 key = aead_tv[i].key;
287
288 ret = crypto_aead_setkey(tfm, key,
289 aead_tv[i].klen);
290 if (ret) {
291 printk(KERN_INFO "setkey() failed flags=%x\n",
292 crypto_aead_get_flags(tfm));
293
294 if (!aead_tv[i].fail)
295 goto out;
296 }
297
298 sg_init_one(&sg[0], aead_tv[i].input,
299 aead_tv[i].ilen);
300
301 sg_init_one(&asg[0], aead_tv[i].assoc,
302 aead_tv[i].alen);
303
304 aead_request_set_crypt(req, sg, sg,
305 aead_tv[i].ilen,
306 aead_tv[i].iv);
307
308 aead_request_set_assoc(req, asg, aead_tv[i].alen);
309
310 if (enc) {
311 ret = crypto_aead_encrypt(req);
312 } else {
313 memcpy(req->__ctx, aead_tv[i].tag,
314 aead_tv[i].tlen);
315 ret = crypto_aead_decrypt(req);
316 }
317
318 switch (ret) {
319 case 0:
320 break;
321 case -EINPROGRESS:
322 case -EBUSY:
323 ret = wait_for_completion_interruptible(
324 &result.completion);
325 if (!ret && !(ret = result.err)) {
326 INIT_COMPLETION(result.completion);
327 break;
328 }
329 /* fall through */
330 default:
331 printk(KERN_INFO "%s () failed err=%d\n",
332 e, -ret);
333 goto out;
334 }
335
336 q = kmap(sg_page(&sg[0])) + sg[0].offset;
337 hexdump(q, aead_tv[i].rlen);
338 printk(KERN_INFO "auth tag: ");
339 hexdump((unsigned char *)req->__ctx, aead_tv[i].tlen);
340
341 printk(KERN_INFO "enc/dec: %s\n",
342 memcmp(q, aead_tv[i].result,
343 aead_tv[i].rlen) ? "fail" : "pass");
344
345 printk(KERN_INFO "auth tag: %s\n",
346 memcmp(req->__ctx, aead_tv[i].tag,
347 aead_tv[i].tlen) ? "fail" : "pass");
348 }
349 }
350
351 printk(KERN_INFO "\ntesting %s %s across pages (chunking)\n", algo, e);
352 memset(xbuf, 0, XBUFSIZE);
353
354 for (i = 0, j = 0; i < tcount; i++) {
355 if (aead_tv[i].np) {
356 printk(KERN_INFO "test %u (%d bit key):\n",
357 ++j, aead_tv[i].klen * 8);
358
359 crypto_aead_clear_flags(tfm, ~0);
360 if (aead_tv[i].wk)
361 crypto_aead_set_flags(
362 tfm, CRYPTO_TFM_REQ_WEAK_KEY);
363 key = aead_tv[i].key;
364
365 ret = crypto_aead_setkey(tfm, key, aead_tv[i].klen);
366 if (ret) {
367 printk(KERN_INFO "setkey() failed flags=%x\n",
368 crypto_aead_get_flags(tfm));
369
370 if (!aead_tv[i].fail)
371 goto out;
372 }
373
374 sg_init_table(sg, aead_tv[i].np);
375 for (k = 0, temp = 0; k < aead_tv[i].np; k++) {
376 memcpy(&xbuf[IDX[k]],
377 aead_tv[i].input + temp,
378 aead_tv[i].tap[k]);
379 temp += aead_tv[i].tap[k];
380 sg_set_buf(&sg[k], &xbuf[IDX[k]],
381 aead_tv[i].tap[k]);
382 }
383
384 sg_init_table(asg, aead_tv[i].anp);
385 for (k = 0, temp = 0; k < aead_tv[i].anp; k++) {
386 memcpy(&axbuf[IDX[k]],
387 aead_tv[i].assoc + temp,
388 aead_tv[i].atap[k]);
389 temp += aead_tv[i].atap[k];
390 sg_set_buf(&asg[k], &axbuf[IDX[k]],
391 aead_tv[i].atap[k]);
392 }
393
394 aead_request_set_crypt(req, sg, sg,
395 aead_tv[i].ilen,
396 aead_tv[i].iv);
397
398 aead_request_set_assoc(req, asg, aead_tv[i].alen);
399
400 if (enc) {
401 ret = crypto_aead_encrypt(req);
402 } else {
403 memcpy(req->__ctx, aead_tv[i].tag,
404 aead_tv[i].tlen);
405 ret = crypto_aead_decrypt(req);
406 }
407
408 switch (ret) {
409 case 0:
410 break;
411 case -EINPROGRESS:
412 case -EBUSY:
413 ret = wait_for_completion_interruptible(
414 &result.completion);
415 if (!ret && !(ret = result.err)) {
416 INIT_COMPLETION(result.completion);
417 break;
418 }
419 /* fall through */
420 default:
421 printk(KERN_INFO "%s () failed err=%d\n",
422 e, -ret);
423 goto out;
424 }
425
426 for (k = 0, temp = 0; k < aead_tv[i].np; k++) {
427 printk(KERN_INFO "page %u\n", k);
428 q = kmap(sg_page(&sg[k])) + sg[k].offset;
429 hexdump(q, aead_tv[i].tap[k]);
430 printk(KERN_INFO "%s\n",
431 memcmp(q, aead_tv[i].result + temp,
432 aead_tv[i].tap[k]) ?
433 "fail" : "pass");
434
435 temp += aead_tv[i].tap[k];
436 }
437 printk(KERN_INFO "auth tag: ");
438 hexdump((unsigned char *)req->__ctx, aead_tv[i].tlen);
439
440 printk(KERN_INFO "auth tag: %s\n",
441 memcmp(req->__ctx, aead_tv[i].tag,
442 aead_tv[i].tlen) ? "fail" : "pass");
443 }
444 }
445
446out:
447 crypto_free_aead(tfm);
448 aead_request_free(req);
449}
450
220static void test_cipher(char *algo, int enc, 451static void test_cipher(char *algo, int enc,
221 struct cipher_testvec *template, unsigned int tcount) 452 struct cipher_testvec *template, unsigned int tcount)
222{ 453{
@@ -1497,20 +1728,21 @@ static void do_test(void)
1497 1728
1498static int __init init(void) 1729static int __init init(void)
1499{ 1730{
1731 int err = -ENOMEM;
1732
1500 tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL); 1733 tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL);
1501 if (tvmem == NULL) 1734 if (tvmem == NULL)
1502 return -ENOMEM; 1735 return err;
1503 1736
1504 xbuf = kmalloc(XBUFSIZE, GFP_KERNEL); 1737 xbuf = kmalloc(XBUFSIZE, GFP_KERNEL);
1505 if (xbuf == NULL) { 1738 if (xbuf == NULL)
1506 kfree(tvmem); 1739 goto err_free_tv;
1507 return -ENOMEM;
1508 }
1509 1740
1510 do_test(); 1741 axbuf = kmalloc(XBUFSIZE, GFP_KERNEL);
1742 if (axbuf == NULL)
1743 goto err_free_xbuf;
1511 1744
1512 kfree(xbuf); 1745 do_test();
1513 kfree(tvmem);
1514 1746
1515 /* We intentionaly return -EAGAIN to prevent keeping 1747 /* We intentionaly return -EAGAIN to prevent keeping
1516 * the module. It does all its work from init() 1748 * the module. It does all its work from init()
@@ -1518,7 +1750,15 @@ static int __init init(void)
1518 * => we don't need it in the memory, do we? 1750 * => we don't need it in the memory, do we?
1519 * -- mludvig 1751 * -- mludvig
1520 */ 1752 */
1521 return -EAGAIN; 1753 err = -EAGAIN;
1754
1755 kfree(axbuf);
1756 err_free_xbuf:
1757 kfree(xbuf);
1758 err_free_tv:
1759 kfree(tvmem);
1760
1761 return err;
1522} 1762}
1523 1763
1524/* 1764/*