diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2023-04-13 08:24:19 +0200 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2023-04-20 12:20:04 +0200 |
commit | ed3630b83e9394acef27041de7a2223f1e875e9a (patch) | |
tree | 9f18ad66b747c4a5a9698a61444f2509eefd1756 /crypto/ahash.c | |
parent | crypto: api - Add crypto_clone_tfm (diff) | |
download | linux-ed3630b83e9394acef27041de7a2223f1e875e9a.tar.xz linux-ed3630b83e9394acef27041de7a2223f1e875e9a.zip |
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>
Diffstat (limited to 'crypto/ahash.c')
-rw-r--r-- | crypto/ahash.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/crypto/ahash.c b/crypto/ahash.c index 2d858d7fd1bb..b8a607928e72 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -543,6 +543,57 @@ int crypto_has_ahash(const char *alg_name, u32 type, u32 mask) } EXPORT_SYMBOL_GPL(crypto_has_ahash); +struct crypto_ahash *crypto_clone_ahash(struct crypto_ahash *hash) +{ + struct hash_alg_common *halg = crypto_hash_alg_common(hash); + struct crypto_tfm *tfm = crypto_ahash_tfm(hash); + struct crypto_ahash *nhash; + struct ahash_alg *alg; + int err; + + if (!crypto_hash_alg_has_setkey(halg)) { + tfm = crypto_tfm_get(tfm); + if (IS_ERR(tfm)) + return ERR_CAST(tfm); + + return hash; + } + + nhash = crypto_clone_tfm(&crypto_ahash_type, tfm); + + if (IS_ERR(nhash)) + return nhash; + + nhash->init = hash->init; + nhash->update = hash->update; + nhash->final = hash->final; + nhash->finup = hash->finup; + nhash->digest = hash->digest; + nhash->export = hash->export; + nhash->import = hash->import; + nhash->setkey = hash->setkey; + nhash->reqsize = hash->reqsize; + + if (tfm->__crt_alg->cra_type != &crypto_ahash_type) + return crypto_clone_shash_ops_async(nhash, hash); + + err = -ENOSYS; + alg = crypto_ahash_alg(hash); + if (!alg->clone_tfm) + goto out_free_nhash; + + err = alg->clone_tfm(nhash, hash); + if (err) + goto out_free_nhash; + + return nhash; + +out_free_nhash: + crypto_free_ahash(nhash); + return ERR_PTR(err); +} +EXPORT_SYMBOL_GPL(crypto_clone_ahash); + static int ahash_prepare_alg(struct ahash_alg *alg) { struct crypto_alg *base = &alg->halg.base; |