crypto: drbg - set HMAC key only when altered
The HMAC implementation allows setting the HMAC key independently from the hashing operation. Therefore, the key only needs to be set when a new key is generated. This patch increases the speed of the HMAC DRBG by at least 35% depending on the use case. The patch is fully CAVS tested. Signed-off-by: Stephan Mueller <smueller@chronox.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
bdb6cf9f6f
commit
4218ebe8ca
1 changed files with 25 additions and 14 deletions
|
@ -592,8 +592,10 @@ static const struct drbg_state_ops drbg_ctr_ops = {
|
||||||
******************************************************************/
|
******************************************************************/
|
||||||
|
|
||||||
#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
|
#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
|
||||||
static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
|
static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
|
||||||
unsigned char *outval, const struct list_head *in);
|
const struct list_head *in);
|
||||||
|
static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
|
||||||
|
const unsigned char *key);
|
||||||
static int drbg_init_hash_kernel(struct drbg_state *drbg);
|
static int drbg_init_hash_kernel(struct drbg_state *drbg);
|
||||||
static int drbg_fini_hash_kernel(struct drbg_state *drbg);
|
static int drbg_fini_hash_kernel(struct drbg_state *drbg);
|
||||||
#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
|
#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
|
||||||
|
@ -619,9 +621,11 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
|
||||||
LIST_HEAD(seedlist);
|
LIST_HEAD(seedlist);
|
||||||
LIST_HEAD(vdatalist);
|
LIST_HEAD(vdatalist);
|
||||||
|
|
||||||
if (!reseed)
|
if (!reseed) {
|
||||||
/* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */
|
/* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */
|
||||||
memset(drbg->V, 1, drbg_statelen(drbg));
|
memset(drbg->V, 1, drbg_statelen(drbg));
|
||||||
|
drbg_kcapi_hmacsetkey(drbg, drbg->C);
|
||||||
|
}
|
||||||
|
|
||||||
drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
|
drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
|
||||||
list_add_tail(&seed1.list, &seedlist);
|
list_add_tail(&seed1.list, &seedlist);
|
||||||
|
@ -641,12 +645,13 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
|
||||||
prefix = DRBG_PREFIX1;
|
prefix = DRBG_PREFIX1;
|
||||||
/* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
|
/* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
|
||||||
seed2.buf = &prefix;
|
seed2.buf = &prefix;
|
||||||
ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seedlist);
|
ret = drbg_kcapi_hash(drbg, drbg->C, &seedlist);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
drbg_kcapi_hmacsetkey(drbg, drbg->C);
|
||||||
|
|
||||||
/* 10.1.2.2 step 2 and 5 -- HMAC for V */
|
/* 10.1.2.2 step 2 and 5 -- HMAC for V */
|
||||||
ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &vdatalist);
|
ret = drbg_kcapi_hash(drbg, drbg->V, &vdatalist);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -681,7 +686,7 @@ static int drbg_hmac_generate(struct drbg_state *drbg,
|
||||||
while (len < buflen) {
|
while (len < buflen) {
|
||||||
unsigned int outlen = 0;
|
unsigned int outlen = 0;
|
||||||
/* 10.1.2.5 step 4.1 */
|
/* 10.1.2.5 step 4.1 */
|
||||||
ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &datalist);
|
ret = drbg_kcapi_hash(drbg, drbg->V, &datalist);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
|
outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
|
||||||
|
@ -796,7 +801,7 @@ static int drbg_hash_df(struct drbg_state *drbg,
|
||||||
while (len < outlen) {
|
while (len < outlen) {
|
||||||
short blocklen = 0;
|
short blocklen = 0;
|
||||||
/* 10.4.1 step 4.1 */
|
/* 10.4.1 step 4.1 */
|
||||||
ret = drbg_kcapi_hash(drbg, NULL, tmp, entropylist);
|
ret = drbg_kcapi_hash(drbg, tmp, entropylist);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
/* 10.4.1 step 4.2 */
|
/* 10.4.1 step 4.2 */
|
||||||
|
@ -874,7 +879,7 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg,
|
||||||
list_add_tail(&data1.list, &datalist);
|
list_add_tail(&data1.list, &datalist);
|
||||||
list_add_tail(&data2.list, &datalist);
|
list_add_tail(&data2.list, &datalist);
|
||||||
list_splice_tail(addtl, &datalist);
|
list_splice_tail(addtl, &datalist);
|
||||||
ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
|
ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -907,7 +912,7 @@ static int drbg_hash_hashgen(struct drbg_state *drbg,
|
||||||
while (len < buflen) {
|
while (len < buflen) {
|
||||||
unsigned int outlen = 0;
|
unsigned int outlen = 0;
|
||||||
/* 10.1.1.4 step hashgen 4.1 */
|
/* 10.1.1.4 step hashgen 4.1 */
|
||||||
ret = drbg_kcapi_hash(drbg, NULL, dst, &datalist);
|
ret = drbg_kcapi_hash(drbg, dst, &datalist);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
len = ret;
|
len = ret;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -956,7 +961,7 @@ static int drbg_hash_generate(struct drbg_state *drbg,
|
||||||
list_add_tail(&data1.list, &datalist);
|
list_add_tail(&data1.list, &datalist);
|
||||||
drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
|
drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
|
||||||
list_add_tail(&data2.list, &datalist);
|
list_add_tail(&data2.list, &datalist);
|
||||||
ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
|
ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
len = ret;
|
len = ret;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1600,14 +1605,20 @@ static int drbg_fini_hash_kernel(struct drbg_state *drbg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
|
static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
|
||||||
unsigned char *outval, const struct list_head *in)
|
const unsigned char *key)
|
||||||
|
{
|
||||||
|
struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
|
||||||
|
|
||||||
|
crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
|
||||||
|
const struct list_head *in)
|
||||||
{
|
{
|
||||||
struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
|
struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
|
||||||
struct drbg_string *input = NULL;
|
struct drbg_string *input = NULL;
|
||||||
|
|
||||||
if (key)
|
|
||||||
crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
|
|
||||||
crypto_shash_init(&sdesc->shash);
|
crypto_shash_init(&sdesc->shash);
|
||||||
list_for_each_entry(input, in, list)
|
list_for_each_entry(input, in, list)
|
||||||
crypto_shash_update(&sdesc->shash, input->buf, input->len);
|
crypto_shash_update(&sdesc->shash, input->buf, input->len);
|
||||||
|
|
Loading…
Reference in a new issue