Commit 7b0bac64cd5b74d6f1147524c26216de13a501fd

Authored by Herbert Xu
1 parent 4a7794860b

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

... ... @@ -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
... ... @@ -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