|
@@ -403,6 +403,9 @@ EXPORT_SYMBOL_GPL(__crypto_alloc_tfm);
|
|
* @type: Type of algorithm
|
|
* @type: Type of algorithm
|
|
* @mask: Mask for type comparison
|
|
* @mask: Mask for type comparison
|
|
*
|
|
*
|
|
|
|
+ * This function should not be used by new algorithm types.
|
|
|
|
+ * Plesae use crypto_alloc_tfm instead.
|
|
|
|
+ *
|
|
* crypto_alloc_base() will first attempt to locate an already loaded
|
|
* crypto_alloc_base() will first attempt to locate an already loaded
|
|
* algorithm. If that fails and the kernel supports dynamically loadable
|
|
* algorithm. If that fails and the kernel supports dynamically loadable
|
|
* modules, it will then attempt to load a module of the same name or
|
|
* modules, it will then attempt to load a module of the same name or
|
|
@@ -449,6 +452,111 @@ err:
|
|
return ERR_PTR(err);
|
|
return ERR_PTR(err);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(crypto_alloc_base);
|
|
EXPORT_SYMBOL_GPL(crypto_alloc_base);
|
|
|
|
+
|
|
|
|
+struct crypto_tfm *crypto_create_tfm(struct crypto_alg *alg,
|
|
|
|
+ const struct crypto_type *frontend)
|
|
|
|
+{
|
|
|
|
+ char *mem;
|
|
|
|
+ struct crypto_tfm *tfm = NULL;
|
|
|
|
+ unsigned int tfmsize;
|
|
|
|
+ unsigned int total;
|
|
|
|
+ int err = -ENOMEM;
|
|
|
|
+
|
|
|
|
+ tfmsize = frontend->tfmsize;
|
|
|
|
+ total = tfmsize + sizeof(*tfm) + frontend->extsize(alg, frontend);
|
|
|
|
+
|
|
|
|
+ mem = kzalloc(total, GFP_KERNEL);
|
|
|
|
+ if (mem == NULL)
|
|
|
|
+ goto out_err;
|
|
|
|
+
|
|
|
|
+ tfm = (struct crypto_tfm *)(mem + tfmsize);
|
|
|
|
+ tfm->__crt_alg = alg;
|
|
|
|
+
|
|
|
|
+ err = frontend->init_tfm(tfm, frontend);
|
|
|
|
+ if (err)
|
|
|
|
+ goto out_free_tfm;
|
|
|
|
+
|
|
|
|
+ if (!tfm->exit && alg->cra_init && (err = alg->cra_init(tfm)))
|
|
|
|
+ goto cra_init_failed;
|
|
|
|
+
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+cra_init_failed:
|
|
|
|
+ crypto_exit_ops(tfm);
|
|
|
|
+out_free_tfm:
|
|
|
|
+ if (err == -EAGAIN)
|
|
|
|
+ crypto_shoot_alg(alg);
|
|
|
|
+ kfree(mem);
|
|
|
|
+out_err:
|
|
|
|
+ tfm = ERR_PTR(err);
|
|
|
|
+out:
|
|
|
|
+ return tfm;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(crypto_create_tfm);
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * crypto_alloc_tfm - Locate algorithm and allocate transform
|
|
|
|
+ * @alg_name: Name of algorithm
|
|
|
|
+ * @frontend: Frontend algorithm type
|
|
|
|
+ * @type: Type of algorithm
|
|
|
|
+ * @mask: Mask for type comparison
|
|
|
|
+ *
|
|
|
|
+ * crypto_alloc_tfm() will first attempt to locate an already loaded
|
|
|
|
+ * algorithm. If that fails and the kernel supports dynamically loadable
|
|
|
|
+ * modules, it will then attempt to load a module of the same name or
|
|
|
|
+ * alias. If that fails it will send a query to any loaded crypto manager
|
|
|
|
+ * to construct an algorithm on the fly. A refcount is grabbed on the
|
|
|
|
+ * algorithm which is then associated with the new transform.
|
|
|
|
+ *
|
|
|
|
+ * The returned transform is of a non-determinate type. Most people
|
|
|
|
+ * should use one of the more specific allocation functions such as
|
|
|
|
+ * crypto_alloc_blkcipher.
|
|
|
|
+ *
|
|
|
|
+ * In case of error the return value is an error pointer.
|
|
|
|
+ */
|
|
|
|
+struct crypto_tfm *crypto_alloc_tfm(const char *alg_name,
|
|
|
|
+ const struct crypto_type *frontend,
|
|
|
|
+ u32 type, u32 mask)
|
|
|
|
+{
|
|
|
|
+ struct crypto_alg *(*lookup)(const char *name, u32 type, u32 mask);
|
|
|
|
+ struct crypto_tfm *tfm;
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ type &= frontend->maskclear;
|
|
|
|
+ mask &= frontend->maskclear;
|
|
|
|
+ type |= frontend->type;
|
|
|
|
+ mask |= frontend->maskset;
|
|
|
|
+
|
|
|
|
+ lookup = frontend->lookup ?: crypto_alg_mod_lookup;
|
|
|
|
+
|
|
|
|
+ for (;;) {
|
|
|
|
+ struct crypto_alg *alg;
|
|
|
|
+
|
|
|
|
+ alg = lookup(alg_name, type, mask);
|
|
|
|
+ if (IS_ERR(alg)) {
|
|
|
|
+ err = PTR_ERR(alg);
|
|
|
|
+ goto err;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ tfm = crypto_create_tfm(alg, frontend);
|
|
|
|
+ if (!IS_ERR(tfm))
|
|
|
|
+ return tfm;
|
|
|
|
+
|
|
|
|
+ crypto_mod_put(alg);
|
|
|
|
+ err = PTR_ERR(tfm);
|
|
|
|
+
|
|
|
|
+err:
|
|
|
|
+ if (err != -EAGAIN)
|
|
|
|
+ break;
|
|
|
|
+ if (signal_pending(current)) {
|
|
|
|
+ err = -EINTR;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ERR_PTR(err);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
|
|
|
|
|
|
/*
|
|
/*
|
|
* crypto_free_tfm - Free crypto transform
|
|
* crypto_free_tfm - Free crypto transform
|