lib/crypto: Introduce new HMAC functions to reuse buffers
To enable more efficient buffer reuse for HMAC operations three new
functions have been introduced. This change prevents the need to
reallocate memory for each HMAC operation:
- grub_crypto_hmac_reset(): reinitializes the hash contexts in the HMAC handle,
- grub_crypto_hmac_final(): provides the final HMAC result without freeing the
handle allowing it to be reused immediately,
- grub_crypto_hmac_free(): deallocates the HMAC handle and its associated memory.
To further facilitate buffer reuse ctx2 is now included within the HMAC handle
struct and the initialization of ctx2 is moved to grub_crypto_hmac_init().
The intermediate hash states, ctx and ctx2, for the inner and outer padded
keys are now cached. The grub_crypto_hmac_reset() restores these cached
states for new operations which avoids redundant hashing of the keys.
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This commit is contained in:
parent
59304a7b51
commit
961e38b2b0
@ -464,9 +464,7 @@ geli_recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_ar
|
||||
grub_crypto_hmac_write (hnd, header.salt, sizeof (header.salt));
|
||||
grub_crypto_hmac_write (hnd, cargs->key_data, cargs->key_len);
|
||||
|
||||
gcry_err = grub_crypto_hmac_fini (hnd, geomkey);
|
||||
if (gcry_err)
|
||||
return grub_crypto_gcry_error (gcry_err);
|
||||
grub_crypto_hmac_fini (hnd, geomkey);
|
||||
}
|
||||
|
||||
gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey,
|
||||
|
||||
@ -31,7 +31,9 @@ struct grub_crypto_hmac_handle
|
||||
{
|
||||
const struct gcry_md_spec *md;
|
||||
void *ctx;
|
||||
void *opad;
|
||||
void *ctx2;
|
||||
void *ctx_cache;
|
||||
void *ctx2_cache;
|
||||
};
|
||||
|
||||
static gcry_cipher_spec_t *grub_ciphers = NULL;
|
||||
@ -443,7 +445,8 @@ grub_crypto_hmac_init (const struct gcry_md_spec *md,
|
||||
{
|
||||
grub_uint8_t *helpkey = NULL;
|
||||
grub_uint8_t *ipad = NULL, *opad = NULL;
|
||||
void *ctx = NULL;
|
||||
void *ctx = NULL, *ctx2 = NULL;
|
||||
void *ctx_cache = NULL, *ctx2_cache = NULL;
|
||||
struct grub_crypto_hmac_handle *ret = NULL;
|
||||
unsigned i;
|
||||
|
||||
@ -454,6 +457,18 @@ grub_crypto_hmac_init (const struct gcry_md_spec *md,
|
||||
if (!ctx)
|
||||
goto err;
|
||||
|
||||
ctx2 = grub_malloc (md->contextsize);
|
||||
if (!ctx2)
|
||||
goto err;
|
||||
|
||||
ctx_cache = grub_malloc (md->contextsize);
|
||||
if (!ctx_cache)
|
||||
goto err;
|
||||
|
||||
ctx2_cache = grub_malloc (md->contextsize);
|
||||
if (!ctx2_cache)
|
||||
goto err;
|
||||
|
||||
if ( keylen > md->blocksize )
|
||||
{
|
||||
helpkey = grub_malloc (md->mdlen);
|
||||
@ -483,26 +498,40 @@ grub_crypto_hmac_init (const struct gcry_md_spec *md,
|
||||
grub_free (helpkey);
|
||||
helpkey = NULL;
|
||||
|
||||
/* inner pad */
|
||||
md->init (ctx, 0);
|
||||
|
||||
md->write (ctx, ipad, md->blocksize); /* inner pad */
|
||||
md->write (ctx, ipad, md->blocksize);
|
||||
grub_memcpy (ctx_cache, ctx, md->contextsize);
|
||||
grub_memset (ipad, 0, md->blocksize);
|
||||
grub_free (ipad);
|
||||
ipad = NULL;
|
||||
|
||||
/* outer pad */
|
||||
md->init (ctx2, 0);
|
||||
md->write (ctx2, opad, md->blocksize);
|
||||
grub_memcpy (ctx2_cache, ctx2, md->contextsize);
|
||||
grub_memset (opad, 0, md->blocksize);
|
||||
grub_free (opad);
|
||||
opad = NULL;
|
||||
|
||||
ret = grub_malloc (sizeof (*ret));
|
||||
if (!ret)
|
||||
goto err;
|
||||
|
||||
ret->md = md;
|
||||
ret->ctx = ctx;
|
||||
ret->opad = opad;
|
||||
ret->ctx2 = ctx2;
|
||||
ret->ctx_cache = ctx_cache;
|
||||
ret->ctx2_cache = ctx2_cache;
|
||||
|
||||
return ret;
|
||||
|
||||
err:
|
||||
grub_free (helpkey);
|
||||
grub_free (ctx);
|
||||
grub_free (ctx2);
|
||||
grub_free (ctx_cache);
|
||||
grub_free (ctx2_cache);
|
||||
grub_free (ipad);
|
||||
grub_free (opad);
|
||||
return NULL;
|
||||
@ -516,37 +545,48 @@ grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd,
|
||||
hnd->md->write (hnd->ctx, data, datalen);
|
||||
}
|
||||
|
||||
gcry_err_code_t
|
||||
void
|
||||
grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out)
|
||||
{
|
||||
grub_uint8_t *p;
|
||||
grub_uint8_t *ctx2;
|
||||
grub_crypto_hmac_final (hnd, out);
|
||||
grub_crypto_hmac_free (hnd);
|
||||
}
|
||||
|
||||
ctx2 = grub_malloc (hnd->md->contextsize);
|
||||
if (!ctx2)
|
||||
return GPG_ERR_OUT_OF_MEMORY;
|
||||
void
|
||||
grub_crypto_hmac_reset (struct grub_crypto_hmac_handle *hnd)
|
||||
{
|
||||
grub_memcpy (hnd->ctx, hnd->ctx_cache, hnd->md->contextsize);
|
||||
grub_memcpy (hnd->ctx2, hnd->ctx2_cache, hnd->md->contextsize);
|
||||
}
|
||||
|
||||
void
|
||||
grub_crypto_hmac_final (struct grub_crypto_hmac_handle *hnd, void *out)
|
||||
{
|
||||
grub_uint8_t *p;
|
||||
|
||||
hnd->md->final (hnd->ctx);
|
||||
hnd->md->read (hnd->ctx);
|
||||
p = hnd->md->read (hnd->ctx);
|
||||
|
||||
hnd->md->init (ctx2, 0);
|
||||
hnd->md->write (ctx2, hnd->opad, hnd->md->blocksize);
|
||||
hnd->md->write (ctx2, p, hnd->md->mdlen);
|
||||
hnd->md->final (ctx2);
|
||||
grub_memset (hnd->opad, 0, hnd->md->blocksize);
|
||||
grub_free (hnd->opad);
|
||||
hnd->md->write (hnd->ctx2, p, hnd->md->mdlen);
|
||||
hnd->md->final (hnd->ctx2);
|
||||
|
||||
grub_memcpy (out, hnd->md->read (hnd->ctx2), hnd->md->mdlen);
|
||||
}
|
||||
|
||||
void
|
||||
grub_crypto_hmac_free (struct grub_crypto_hmac_handle *hnd)
|
||||
{
|
||||
grub_memset (hnd->ctx, 0, hnd->md->contextsize);
|
||||
grub_free (hnd->ctx);
|
||||
|
||||
grub_memcpy (out, hnd->md->read (ctx2), hnd->md->mdlen);
|
||||
grub_memset (ctx2, 0, hnd->md->contextsize);
|
||||
grub_free (ctx2);
|
||||
|
||||
grub_memset (hnd->ctx2, 0, hnd->md->contextsize);
|
||||
grub_free (hnd->ctx2);
|
||||
grub_memset (hnd->ctx_cache, 0, hnd->md->contextsize);
|
||||
grub_free (hnd->ctx_cache);
|
||||
grub_memset (hnd->ctx2_cache, 0, hnd->md->contextsize);
|
||||
grub_free (hnd->ctx2_cache);
|
||||
grub_memset (hnd, 0, sizeof (*hnd));
|
||||
grub_free (hnd);
|
||||
|
||||
return GPG_ERR_NO_ERROR;
|
||||
}
|
||||
|
||||
gcry_err_code_t
|
||||
@ -561,7 +601,8 @@ grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
|
||||
return GPG_ERR_OUT_OF_MEMORY;
|
||||
|
||||
grub_crypto_hmac_write (hnd, data, datalen);
|
||||
return grub_crypto_hmac_fini (hnd, out);
|
||||
grub_crypto_hmac_fini (hnd, out);
|
||||
return GPG_ERR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -511,8 +511,14 @@ void
|
||||
grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd,
|
||||
const void *data,
|
||||
grub_size_t datalen);
|
||||
gcry_err_code_t
|
||||
void
|
||||
grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out);
|
||||
void
|
||||
grub_crypto_hmac_reset (struct grub_crypto_hmac_handle *hnd);
|
||||
void
|
||||
grub_crypto_hmac_final (struct grub_crypto_hmac_handle *hnd, void *out);
|
||||
void
|
||||
grub_crypto_hmac_free (struct grub_crypto_hmac_handle *hnd);
|
||||
|
||||
gcry_err_code_t
|
||||
grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user