Commit 7b0bac64cd5b74d6f1147524c26216de13a501fd
1 parent
4a7794860b
Exists in
master
and in
39 other branches
crypto: api - Rebirth of crypto_alloc_tfm
This patch reintroduces a completely revamped crypto_alloc_tfm. The biggest change is that we now take two crypto_type objects when allocating a tfm, a frontend and a backend. In fact this simply formalises what we've been doing behind the API's back. For example, as it stands crypto_alloc_ahash may use an actual ahash algorithm or a crypto_hash algorithm. Putting this in the API allows us to do this much more cleanly. The existing types will be converted across gradually. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Showing 4 changed files with 123 additions and 1 deletions Side-by-side Diff
crypto/api.c
... | ... | @@ -403,6 +403,9 @@ |
403 | 403 | * @type: Type of algorithm |
404 | 404 | * @mask: Mask for type comparison |
405 | 405 | * |
406 | + * This function should not be used by new algorithm types. | |
407 | + * Plesae use crypto_alloc_tfm instead. | |
408 | + * | |
406 | 409 | * crypto_alloc_base() will first attempt to locate an already loaded |
407 | 410 | * algorithm. If that fails and the kernel supports dynamically loadable |
408 | 411 | * modules, it will then attempt to load a module of the same name or |
... | ... | @@ -449,6 +452,111 @@ |
449 | 452 | return ERR_PTR(err); |
450 | 453 | } |
451 | 454 | EXPORT_SYMBOL_GPL(crypto_alloc_base); |
455 | + | |
456 | +struct crypto_tfm *crypto_create_tfm(struct crypto_alg *alg, | |
457 | + const struct crypto_type *frontend) | |
458 | +{ | |
459 | + char *mem; | |
460 | + struct crypto_tfm *tfm = NULL; | |
461 | + unsigned int tfmsize; | |
462 | + unsigned int total; | |
463 | + int err = -ENOMEM; | |
464 | + | |
465 | + tfmsize = frontend->tfmsize; | |
466 | + total = tfmsize + sizeof(*tfm) + frontend->extsize(alg, frontend); | |
467 | + | |
468 | + mem = kzalloc(total, GFP_KERNEL); | |
469 | + if (mem == NULL) | |
470 | + goto out_err; | |
471 | + | |
472 | + tfm = (struct crypto_tfm *)(mem + tfmsize); | |
473 | + tfm->__crt_alg = alg; | |
474 | + | |
475 | + err = frontend->init_tfm(tfm, frontend); | |
476 | + if (err) | |
477 | + goto out_free_tfm; | |
478 | + | |
479 | + if (!tfm->exit && alg->cra_init && (err = alg->cra_init(tfm))) | |
480 | + goto cra_init_failed; | |
481 | + | |
482 | + goto out; | |
483 | + | |
484 | +cra_init_failed: | |
485 | + crypto_exit_ops(tfm); | |
486 | +out_free_tfm: | |
487 | + if (err == -EAGAIN) | |
488 | + crypto_shoot_alg(alg); | |
489 | + kfree(mem); | |
490 | +out_err: | |
491 | + tfm = ERR_PTR(err); | |
492 | +out: | |
493 | + return tfm; | |
494 | +} | |
495 | +EXPORT_SYMBOL_GPL(crypto_create_tfm); | |
496 | + | |
497 | +/* | |
498 | + * crypto_alloc_tfm - Locate algorithm and allocate transform | |
499 | + * @alg_name: Name of algorithm | |
500 | + * @frontend: Frontend algorithm type | |
501 | + * @type: Type of algorithm | |
502 | + * @mask: Mask for type comparison | |
503 | + * | |
504 | + * crypto_alloc_tfm() will first attempt to locate an already loaded | |
505 | + * algorithm. If that fails and the kernel supports dynamically loadable | |
506 | + * modules, it will then attempt to load a module of the same name or | |
507 | + * alias. If that fails it will send a query to any loaded crypto manager | |
508 | + * to construct an algorithm on the fly. A refcount is grabbed on the | |
509 | + * algorithm which is then associated with the new transform. | |
510 | + * | |
511 | + * The returned transform is of a non-determinate type. Most people | |
512 | + * should use one of the more specific allocation functions such as | |
513 | + * crypto_alloc_blkcipher. | |
514 | + * | |
515 | + * In case of error the return value is an error pointer. | |
516 | + */ | |
517 | +struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, | |
518 | + const struct crypto_type *frontend, | |
519 | + u32 type, u32 mask) | |
520 | +{ | |
521 | + struct crypto_alg *(*lookup)(const char *name, u32 type, u32 mask); | |
522 | + struct crypto_tfm *tfm; | |
523 | + int err; | |
524 | + | |
525 | + type &= frontend->maskclear; | |
526 | + mask &= frontend->maskclear; | |
527 | + type |= frontend->type; | |
528 | + mask |= frontend->maskset; | |
529 | + | |
530 | + lookup = frontend->lookup ?: crypto_alg_mod_lookup; | |
531 | + | |
532 | + for (;;) { | |
533 | + struct crypto_alg *alg; | |
534 | + | |
535 | + alg = lookup(alg_name, type, mask); | |
536 | + if (IS_ERR(alg)) { | |
537 | + err = PTR_ERR(alg); | |
538 | + goto err; | |
539 | + } | |
540 | + | |
541 | + tfm = crypto_create_tfm(alg, frontend); | |
542 | + if (!IS_ERR(tfm)) | |
543 | + return tfm; | |
544 | + | |
545 | + crypto_mod_put(alg); | |
546 | + err = PTR_ERR(tfm); | |
547 | + | |
548 | +err: | |
549 | + if (err != -EAGAIN) | |
550 | + break; | |
551 | + if (signal_pending(current)) { | |
552 | + err = -EINTR; | |
553 | + break; | |
554 | + } | |
555 | + } | |
556 | + | |
557 | + return ERR_PTR(err); | |
558 | +} | |
559 | +EXPORT_SYMBOL_GPL(crypto_alloc_tfm); | |
452 | 560 | |
453 | 561 | /* |
454 | 562 | * crypto_free_tfm - Free crypto transform |
crypto/internal.h
... | ... | @@ -109,6 +109,8 @@ |
109 | 109 | void crypto_shoot_alg(struct crypto_alg *alg); |
110 | 110 | struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type, |
111 | 111 | u32 mask); |
112 | +struct crypto_tfm *crypto_create_tfm(struct crypto_alg *alg, | |
113 | + const struct crypto_type *frontend); | |
112 | 114 | |
113 | 115 | int crypto_register_instance(struct crypto_template *tmpl, |
114 | 116 | struct crypto_instance *inst); |
include/crypto/algapi.h
... | ... | @@ -22,8 +22,18 @@ |
22 | 22 | |
23 | 23 | struct crypto_type { |
24 | 24 | unsigned int (*ctxsize)(struct crypto_alg *alg, u32 type, u32 mask); |
25 | + unsigned int (*extsize)(struct crypto_alg *alg, | |
26 | + const struct crypto_type *frontend); | |
25 | 27 | int (*init)(struct crypto_tfm *tfm, u32 type, u32 mask); |
28 | + int (*init_tfm)(struct crypto_tfm *tfm, | |
29 | + const struct crypto_type *frontend); | |
26 | 30 | void (*show)(struct seq_file *m, struct crypto_alg *alg); |
31 | + struct crypto_alg *(*lookup)(const char *name, u32 type, u32 mask); | |
32 | + | |
33 | + unsigned int type; | |
34 | + unsigned int maskclear; | |
35 | + unsigned int maskset; | |
36 | + unsigned int tfmsize; | |
27 | 37 | }; |
28 | 38 | |
29 | 39 | struct crypto_instance { |
include/linux/crypto.h
... | ... | @@ -546,7 +546,9 @@ |
546 | 546 | * Transform user interface. |
547 | 547 | */ |
548 | 548 | |
549 | -struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags); | |
549 | +struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, | |
550 | + const struct crypto_type *frontend, | |
551 | + u32 type, u32 mask); | |
550 | 552 | struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask); |
551 | 553 | void crypto_free_tfm(struct crypto_tfm *tfm); |
552 | 554 |