crypto: hash - Add crypto_clone_ahash/shash

This patch adds the helpers crypto_clone_ahash and crypto_clone_shash.
They are the hash-specific counterparts of crypto_clone_tfm.

This allows code paths that cannot otherwise allocate a hash tfm
object to do so.  Once a new tfm has been obtained its key could
then be changed without impacting other users.

Note that only algorithms that implement clone_tfm can be cloned.
However, all keyless hashes can be cloned by simply reusing the
tfm object.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Herbert Xu
2023-04-13 14:24:19 +08:00
parent 3c3a24cb0a
commit ed3630b83e
5 changed files with 115 additions and 2 deletions

View File

@@ -445,6 +445,24 @@ int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
return 0;
}
struct crypto_ahash *crypto_clone_shash_ops_async(struct crypto_ahash *nhash,
struct crypto_ahash *hash)
{
struct crypto_shash **nctx = crypto_ahash_ctx(nhash);
struct crypto_shash **ctx = crypto_ahash_ctx(hash);
struct crypto_shash *shash;
shash = crypto_clone_shash(*ctx);
if (IS_ERR(shash)) {
crypto_free_ahash(nhash);
return ERR_CAST(shash);
}
*nctx = shash;
return nhash;
}
static void crypto_shash_exit_tfm(struct crypto_tfm *tfm)
{
struct crypto_shash *hash = __crypto_shash_cast(tfm);
@@ -564,6 +582,40 @@ int crypto_has_shash(const char *alg_name, u32 type, u32 mask)
}
EXPORT_SYMBOL_GPL(crypto_has_shash);
struct crypto_shash *crypto_clone_shash(struct crypto_shash *hash)
{
struct crypto_tfm *tfm = crypto_shash_tfm(hash);
struct shash_alg *alg = crypto_shash_alg(hash);
struct crypto_shash *nhash;
int err;
if (!crypto_shash_alg_has_setkey(alg)) {
tfm = crypto_tfm_get(tfm);
if (IS_ERR(tfm))
return ERR_CAST(tfm);
return hash;
}
if (!alg->clone_tfm)
return ERR_PTR(-ENOSYS);
nhash = crypto_clone_tfm(&crypto_shash_type, tfm);
if (IS_ERR(nhash))
return nhash;
nhash->descsize = hash->descsize;
err = alg->clone_tfm(nhash, hash);
if (err) {
crypto_free_shash(nhash);
return ERR_PTR(err);
}
return nhash;
}
EXPORT_SYMBOL_GPL(crypto_clone_shash);
int hash_prepare_alg(struct hash_alg_common *alg)
{
struct crypto_istat_hash *istat = hash_get_stat(alg);