crypto: hash - Add crypto_clone_ahash/shash

JIRA: https://redhat.atlassian.net/browse/RHEL-142637
Upstream Status: net.git commit ed3630b83e9394acef27041de7a2223f1e875e9a
Conflicts:
 - crypto/hash.h we don't have it, use extern declarations in ahash.c
 - crypto/shash.c context mismatch

commit ed3630b83e9394acef27041de7a2223f1e875e9a
Author: Herbert Xu <herbert@gondor.apana.org.au>
Date:   Thu Apr 13 14:24:19 2023 +0800

    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>

Signed-off-by: Davide Caratti <dcaratti@redhat.com>
This commit is contained in:
Davide Caratti
2026-07-06 23:21:03 +02:00
parent dbfb9df7ab
commit 30a8824857
4 changed files with 115 additions and 2 deletions
+55
View File
@@ -32,6 +32,10 @@ struct ahash_request_priv {
void *ubuf[] CRYPTO_MINALIGN_ATTR;
};
extern int crypto_init_shash_ops_async(struct crypto_tfm *tfm);
extern struct crypto_ahash *crypto_clone_shash_ops_async(struct crypto_ahash *nhash,
struct crypto_ahash *hash);
static inline struct ahash_alg *crypto_ahash_alg(struct crypto_ahash *hash)
{
return container_of(crypto_hash_alg_common(hash), struct ahash_alg,
@@ -567,6 +571,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;
+52
View File
@@ -413,6 +413,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);
@@ -527,6 +545,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);
static int shash_prepare_alg(struct shash_alg *alg)
{
struct crypto_alg *base = &alg->base;
+8
View File
@@ -129,6 +129,7 @@ struct ahash_request {
* @exit_tfm: Deinitialize the cryptographic transformation object.
* This is a counterpart to @init_tfm, used to remove
* various changes set in @init_tfm.
* @clone_tfm: Copy transform into new object, may allocate memory.
* @halg: see struct hash_alg_common
*/
struct ahash_alg {
@@ -143,6 +144,7 @@ struct ahash_alg {
unsigned int keylen);
int (*init_tfm)(struct crypto_ahash *tfm);
void (*exit_tfm)(struct crypto_ahash *tfm);
int (*clone_tfm)(struct crypto_ahash *dst, struct crypto_ahash *src);
struct hash_alg_common halg;
};
@@ -188,6 +190,7 @@ struct shash_desc {
* @exit_tfm: Deinitialize the cryptographic transformation object.
* This is a counterpart to @init_tfm, used to remove
* various changes set in @init_tfm.
* @clone_tfm: Copy transform into new object, may allocate memory.
* @digestsize: see struct ahash_alg
* @statesize: see struct ahash_alg
* @descsize: Size of the operational state for the message digest. This state
@@ -210,6 +213,7 @@ struct shash_alg {
unsigned int keylen);
int (*init_tfm)(struct crypto_shash *tfm);
void (*exit_tfm)(struct crypto_shash *tfm);
int (*clone_tfm)(struct crypto_shash *dst, struct crypto_shash *src);
unsigned int descsize;
@@ -274,6 +278,8 @@ static inline struct crypto_ahash *__crypto_ahash_cast(struct crypto_tfm *tfm)
struct crypto_ahash *crypto_alloc_ahash(const char *alg_name, u32 type,
u32 mask);
struct crypto_ahash *crypto_clone_ahash(struct crypto_ahash *tfm);
static inline struct crypto_tfm *crypto_ahash_tfm(struct crypto_ahash *tfm)
{
return &tfm->base;
@@ -719,6 +725,8 @@ static inline void ahash_request_set_crypt(struct ahash_request *req,
struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
u32 mask);
struct crypto_shash *crypto_clone_shash(struct crypto_shash *tfm);
int crypto_has_shash(const char *alg_name, u32 type, u32 mask);
static inline struct crypto_tfm *crypto_shash_tfm(struct crypto_shash *tfm)
-2
View File
@@ -127,8 +127,6 @@ int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc);
int shash_ahash_finup(struct ahash_request *req, struct shash_desc *desc);
int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc);
int crypto_init_shash_ops_async(struct crypto_tfm *tfm);
static inline void *crypto_ahash_ctx(struct crypto_ahash *tfm)
{
return crypto_tfm_ctx(crypto_ahash_tfm(tfm));