Commit 08debaa5 authored by Eric Biggers's avatar Eric Biggers Committed by Herbert Xu

crypto: shash - eliminate indirect call for default import and export

Most shash algorithms don't have custom ->import and ->export functions,
resulting in the memcpy() based default being used.  Yet,
crypto_shash_import() and crypto_shash_export() still make an indirect
call, which is expensive.  Therefore, change how the default import and
export are called to make it so that crypto_shash_import() and
crypto_shash_export() don't do an indirect call in this case.
Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent a411f6de
...@@ -277,17 +277,34 @@ int crypto_shash_tfm_digest(struct crypto_shash *tfm, const u8 *data, ...@@ -277,17 +277,34 @@ int crypto_shash_tfm_digest(struct crypto_shash *tfm, const u8 *data,
} }
EXPORT_SYMBOL_GPL(crypto_shash_tfm_digest); EXPORT_SYMBOL_GPL(crypto_shash_tfm_digest);
static int shash_default_export(struct shash_desc *desc, void *out) int crypto_shash_export(struct shash_desc *desc, void *out)
{ {
memcpy(out, shash_desc_ctx(desc), crypto_shash_descsize(desc->tfm)); struct crypto_shash *tfm = desc->tfm;
struct shash_alg *shash = crypto_shash_alg(tfm);
if (shash->export)
return shash->export(desc, out);
memcpy(out, shash_desc_ctx(desc), crypto_shash_descsize(tfm));
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(crypto_shash_export);
static int shash_default_import(struct shash_desc *desc, const void *in) int crypto_shash_import(struct shash_desc *desc, const void *in)
{ {
memcpy(shash_desc_ctx(desc), in, crypto_shash_descsize(desc->tfm)); struct crypto_shash *tfm = desc->tfm;
struct shash_alg *shash = crypto_shash_alg(tfm);
if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
return -ENOKEY;
if (shash->import)
return shash->import(desc, in);
memcpy(shash_desc_ctx(desc), in, crypto_shash_descsize(tfm));
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(crypto_shash_import);
static int shash_async_setkey(struct crypto_ahash *tfm, const u8 *key, static int shash_async_setkey(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen) unsigned int keylen)
...@@ -666,15 +683,23 @@ static int shash_prepare_alg(struct shash_alg *alg) ...@@ -666,15 +683,23 @@ static int shash_prepare_alg(struct shash_alg *alg)
base->cra_type = &crypto_shash_type; base->cra_type = &crypto_shash_type;
base->cra_flags |= CRYPTO_ALG_TYPE_SHASH; base->cra_flags |= CRYPTO_ALG_TYPE_SHASH;
/*
* Handle missing optional functions. For each one we can either
* install a default here, or we can leave the pointer as NULL and check
* the pointer for NULL in crypto_shash_*(), avoiding an indirect call
* when the default behavior is desired. For ->finup and ->digest we
* install defaults, since for optimal performance algorithms should
* implement these anyway. On the other hand, for ->import and
* ->export the common case and best performance comes from the simple
* memcpy of the shash_desc_ctx, so when those pointers are NULL we
* leave them NULL and provide the memcpy with no indirect call.
*/
if (!alg->finup) if (!alg->finup)
alg->finup = shash_default_finup; alg->finup = shash_default_finup;
if (!alg->digest) if (!alg->digest)
alg->digest = shash_default_digest; alg->digest = shash_default_digest;
if (!alg->export) { if (!alg->export)
alg->export = shash_default_export;
alg->import = shash_default_import;
alg->halg.statesize = alg->descsize; alg->halg.statesize = alg->descsize;
}
if (!alg->setkey) if (!alg->setkey)
alg->setkey = shash_no_setkey; alg->setkey = shash_no_setkey;
......
...@@ -952,10 +952,7 @@ int crypto_shash_tfm_digest(struct crypto_shash *tfm, const u8 *data, ...@@ -952,10 +952,7 @@ int crypto_shash_tfm_digest(struct crypto_shash *tfm, const u8 *data,
* Context: Any context. * Context: Any context.
* Return: 0 if the export creation was successful; < 0 if an error occurred * Return: 0 if the export creation was successful; < 0 if an error occurred
*/ */
static inline int crypto_shash_export(struct shash_desc *desc, void *out) int crypto_shash_export(struct shash_desc *desc, void *out);
{
return crypto_shash_alg(desc->tfm)->export(desc, out);
}
/** /**
* crypto_shash_import() - import operational state * crypto_shash_import() - import operational state
...@@ -969,15 +966,7 @@ static inline int crypto_shash_export(struct shash_desc *desc, void *out) ...@@ -969,15 +966,7 @@ static inline int crypto_shash_export(struct shash_desc *desc, void *out)
* Context: Any context. * Context: Any context.
* Return: 0 if the import was successful; < 0 if an error occurred * Return: 0 if the import was successful; < 0 if an error occurred
*/ */
static inline int crypto_shash_import(struct shash_desc *desc, const void *in) int crypto_shash_import(struct shash_desc *desc, const void *in);
{
struct crypto_shash *tfm = desc->tfm;
if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
return -ENOKEY;
return crypto_shash_alg(tfm)->import(desc, in);
}
/** /**
* crypto_shash_init() - (re)initialize message digest * crypto_shash_init() - (re)initialize message digest
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment