aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/aead.c
diff options
context:
space:
mode:
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)");