diff options
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/aead.c | 153 |
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 | } |
329 | EXPORT_SYMBOL_GPL(aead_geniv_exit); | 330 | EXPORT_SYMBOL_GPL(aead_geniv_exit); |
330 | 331 | ||
332 | static 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 | |||
395 | put_tmpl: | ||
396 | crypto_tmpl_put(tmpl); | ||
397 | kill_larval: | ||
398 | crypto_larval_kill(larval); | ||
399 | drop_larval: | ||
400 | crypto_mod_put(larval); | ||
401 | out: | ||
402 | crypto_mod_put(alg); | ||
403 | return err; | ||
404 | } | ||
405 | |||
406 | static 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 | |||
424 | int 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 | } | ||
443 | EXPORT_SYMBOL_GPL(crypto_grab_aead); | ||
444 | |||
445 | struct 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 | |||
471 | err: | ||
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 | } | ||
482 | EXPORT_SYMBOL_GPL(crypto_alloc_aead); | ||
483 | |||
331 | MODULE_LICENSE("GPL"); | 484 | MODULE_LICENSE("GPL"); |
332 | MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)"); | 485 | MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)"); |