aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/aead.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-12-12 06:24:27 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2008-01-10 16:16:52 -0500
commitd29ce988aeb459203c74f14747f4f77e1829ef78 (patch)
tree886ec0a429c3b1b5b79f290be6b0d8383b89c30b /crypto/aead.c
parent14df4d80433b8413f901e80880c39e8759b8418f (diff)
[CRYPTO] aead: Create default givcipher instances
This patch makes crypto_alloc_aead always return algorithms that is capable of generating their own IVs through givencrypt and givdecrypt. All existing AEAD algorithms already do. New ones must either supply their own or specify a generic IV generator with the geniv field. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/aead.c')
-rw-r--r--crypto/aead.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/crypto/aead.c b/crypto/aead.c
index 9f7aca891926..f5b1add31976 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -17,6 +17,7 @@
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/rtnetlink.h>
20#include <linux/slab.h> 21#include <linux/slab.h>
21#include <linux/seq_file.h> 22#include <linux/seq_file.h>
22 23
@@ -328,5 +329,157 @@ void aead_geniv_exit(struct crypto_tfm *tfm)
328} 329}
329EXPORT_SYMBOL_GPL(aead_geniv_exit); 330EXPORT_SYMBOL_GPL(aead_geniv_exit);
330 331
332static int crypto_nivaead_default(struct crypto_alg *alg, u32 type, u32 mask)
333{
334 struct rtattr *tb[3];
335 struct {
336 struct rtattr attr;
337 struct crypto_attr_type data;
338 } ptype;
339 struct {
340 struct rtattr attr;
341 struct crypto_attr_alg data;
342 } palg;
343 struct crypto_template *tmpl;
344 struct crypto_instance *inst;
345 struct crypto_alg *larval;
346 const char *geniv;
347 int err;
348
349 larval = crypto_larval_lookup(alg->cra_driver_name,
350 CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV,
351 CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
352 err = PTR_ERR(larval);
353 if (IS_ERR(larval))
354 goto out;
355
356 err = -EAGAIN;
357 if (!crypto_is_larval(larval))
358 goto drop_larval;
359
360 ptype.attr.rta_len = sizeof(ptype);
361 ptype.attr.rta_type = CRYPTOA_TYPE;
362 ptype.data.type = type | CRYPTO_ALG_GENIV;
363 /* GENIV tells the template that we're making a default geniv. */
364 ptype.data.mask = mask | CRYPTO_ALG_GENIV;
365 tb[0] = &ptype.attr;
366
367 palg.attr.rta_len = sizeof(palg);
368 palg.attr.rta_type = CRYPTOA_ALG;
369 /* Must use the exact name to locate ourselves. */
370 memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME);
371 tb[1] = &palg.attr;
372
373 tb[2] = NULL;
374
375 geniv = alg->cra_aead.geniv;
376
377 tmpl = crypto_lookup_template(geniv);
378 err = -ENOENT;
379 if (!tmpl)
380 goto kill_larval;
381
382 inst = tmpl->alloc(tb);
383 err = PTR_ERR(inst);
384 if (IS_ERR(inst))
385 goto put_tmpl;
386
387 if ((err = crypto_register_instance(tmpl, inst))) {
388 tmpl->free(inst);
389 goto put_tmpl;
390 }
391
392 /* Redo the lookup to use the instance we just registered. */
393 err = -EAGAIN;
394
395put_tmpl:
396 crypto_tmpl_put(tmpl);
397kill_larval:
398 crypto_larval_kill(larval);
399drop_larval:
400 crypto_mod_put(larval);
401out:
402 crypto_mod_put(alg);
403 return err;
404}
405
406static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type,
407 u32 mask)
408{
409 struct crypto_alg *alg;
410
411 alg = crypto_alg_mod_lookup(name, type, mask);
412 if (IS_ERR(alg))
413 return alg;
414
415 if (alg->cra_type == &crypto_aead_type)
416 return alg;
417
418 if (!alg->cra_aead.ivsize)
419 return alg;
420
421 return ERR_PTR(crypto_nivaead_default(alg, type, mask));
422}
423
424int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
425 u32 type, u32 mask)
426{
427 struct crypto_alg *alg;
428 int err;
429
430 type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
431 type |= CRYPTO_ALG_TYPE_AEAD;
432 mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
433 mask |= CRYPTO_ALG_TYPE_MASK;
434
435 alg = crypto_lookup_aead(name, type, mask);
436 if (IS_ERR(alg))
437 return PTR_ERR(alg);
438
439 err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
440 crypto_mod_put(alg);
441 return err;
442}
443EXPORT_SYMBOL_GPL(crypto_grab_aead);
444
445struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask)
446{
447 struct crypto_tfm *tfm;
448 int err;
449
450 type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
451 type |= CRYPTO_ALG_TYPE_AEAD;
452 mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
453 mask |= CRYPTO_ALG_TYPE_MASK;
454
455 for (;;) {
456 struct crypto_alg *alg;
457
458 alg = crypto_lookup_aead(alg_name, type, mask);
459 if (IS_ERR(alg)) {
460 err = PTR_ERR(alg);
461 goto err;
462 }
463
464 tfm = __crypto_alloc_tfm(alg, type, mask);
465 if (!IS_ERR(tfm))
466 return __crypto_aead_cast(tfm);
467
468 crypto_mod_put(alg);
469 err = PTR_ERR(tfm);
470
471err:
472 if (err != -EAGAIN)
473 break;
474 if (signal_pending(current)) {
475 err = -EINTR;
476 break;
477 }
478 }
479
480 return ERR_PTR(err);
481}
482EXPORT_SYMBOL_GPL(crypto_alloc_aead);
483
331MODULE_LICENSE("GPL"); 484MODULE_LICENSE("GPL");
332MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)"); 485MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)");