diff options
author | Stephan Mueller <smueller@chronox.de> | 2016-03-28 10:47:55 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2016-04-05 08:35:53 -0400 |
commit | 4218ebe8cab421c72f134cca1374e0985303f34a (patch) | |
tree | 813c3ec09204f4cd35998aaca752c22ae88beecd /crypto/drbg.c | |
parent | bdb6cf9f6fe6d9af905ea34b7c4bb78ea601329e (diff) |
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>
Diffstat (limited to 'crypto/drbg.c')
-rw-r--r-- | crypto/drbg.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/crypto/drbg.c b/crypto/drbg.c index 1b86310db7b1..0a3538f6cf22 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c | |||
@@ -592,8 +592,10 @@ static const struct drbg_state_ops drbg_ctr_ops = { | |||
592 | ******************************************************************/ | 592 | ******************************************************************/ |
593 | 593 | ||
594 | #if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC) | 594 | #if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC) |
595 | static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key, | 595 | static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval, |
596 | unsigned char *outval, const struct list_head *in); | 596 | const struct list_head *in); |
597 | static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg, | ||
598 | const unsigned char *key); | ||
597 | static int drbg_init_hash_kernel(struct drbg_state *drbg); | 599 | static int drbg_init_hash_kernel(struct drbg_state *drbg); |
598 | static int drbg_fini_hash_kernel(struct drbg_state *drbg); | 600 | static int drbg_fini_hash_kernel(struct drbg_state *drbg); |
599 | #endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */ | 601 | #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, | |||
619 | LIST_HEAD(seedlist); | 621 | LIST_HEAD(seedlist); |
620 | LIST_HEAD(vdatalist); | 622 | LIST_HEAD(vdatalist); |
621 | 623 | ||
622 | if (!reseed) | 624 | if (!reseed) { |
623 | /* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */ | 625 | /* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */ |
624 | memset(drbg->V, 1, drbg_statelen(drbg)); | 626 | memset(drbg->V, 1, drbg_statelen(drbg)); |
627 | drbg_kcapi_hmacsetkey(drbg, drbg->C); | ||
628 | } | ||
625 | 629 | ||
626 | drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg)); | 630 | drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg)); |
627 | list_add_tail(&seed1.list, &seedlist); | 631 | list_add_tail(&seed1.list, &seedlist); |
@@ -641,12 +645,13 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed, | |||
641 | prefix = DRBG_PREFIX1; | 645 | prefix = DRBG_PREFIX1; |
642 | /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */ | 646 | /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */ |
643 | seed2.buf = &prefix; | 647 | seed2.buf = &prefix; |
644 | ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seedlist); | 648 | ret = drbg_kcapi_hash(drbg, drbg->C, &seedlist); |
645 | if (ret) | 649 | if (ret) |
646 | return ret; | 650 | return ret; |
651 | drbg_kcapi_hmacsetkey(drbg, drbg->C); | ||
647 | 652 | ||
648 | /* 10.1.2.2 step 2 and 5 -- HMAC for V */ | 653 | /* 10.1.2.2 step 2 and 5 -- HMAC for V */ |
649 | ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &vdatalist); | 654 | ret = drbg_kcapi_hash(drbg, drbg->V, &vdatalist); |
650 | if (ret) | 655 | if (ret) |
651 | return ret; | 656 | return ret; |
652 | 657 | ||
@@ -681,7 +686,7 @@ static int drbg_hmac_generate(struct drbg_state *drbg, | |||
681 | while (len < buflen) { | 686 | while (len < buflen) { |
682 | unsigned int outlen = 0; | 687 | unsigned int outlen = 0; |
683 | /* 10.1.2.5 step 4.1 */ | 688 | /* 10.1.2.5 step 4.1 */ |
684 | ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &datalist); | 689 | ret = drbg_kcapi_hash(drbg, drbg->V, &datalist); |
685 | if (ret) | 690 | if (ret) |
686 | return ret; | 691 | return ret; |
687 | outlen = (drbg_blocklen(drbg) < (buflen - len)) ? | 692 | outlen = (drbg_blocklen(drbg) < (buflen - len)) ? |
@@ -796,7 +801,7 @@ static int drbg_hash_df(struct drbg_state *drbg, | |||
796 | while (len < outlen) { | 801 | while (len < outlen) { |
797 | short blocklen = 0; | 802 | short blocklen = 0; |
798 | /* 10.4.1 step 4.1 */ | 803 | /* 10.4.1 step 4.1 */ |
799 | ret = drbg_kcapi_hash(drbg, NULL, tmp, entropylist); | 804 | ret = drbg_kcapi_hash(drbg, tmp, entropylist); |
800 | if (ret) | 805 | if (ret) |
801 | goto out; | 806 | goto out; |
802 | /* 10.4.1 step 4.2 */ | 807 | /* 10.4.1 step 4.2 */ |
@@ -874,7 +879,7 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg, | |||
874 | list_add_tail(&data1.list, &datalist); | 879 | list_add_tail(&data1.list, &datalist); |
875 | list_add_tail(&data2.list, &datalist); | 880 | list_add_tail(&data2.list, &datalist); |
876 | list_splice_tail(addtl, &datalist); | 881 | list_splice_tail(addtl, &datalist); |
877 | ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist); | 882 | ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist); |
878 | if (ret) | 883 | if (ret) |
879 | goto out; | 884 | goto out; |
880 | 885 | ||
@@ -907,7 +912,7 @@ static int drbg_hash_hashgen(struct drbg_state *drbg, | |||
907 | while (len < buflen) { | 912 | while (len < buflen) { |
908 | unsigned int outlen = 0; | 913 | unsigned int outlen = 0; |
909 | /* 10.1.1.4 step hashgen 4.1 */ | 914 | /* 10.1.1.4 step hashgen 4.1 */ |
910 | ret = drbg_kcapi_hash(drbg, NULL, dst, &datalist); | 915 | ret = drbg_kcapi_hash(drbg, dst, &datalist); |
911 | if (ret) { | 916 | if (ret) { |
912 | len = ret; | 917 | len = ret; |
913 | goto out; | 918 | goto out; |
@@ -956,7 +961,7 @@ static int drbg_hash_generate(struct drbg_state *drbg, | |||
956 | list_add_tail(&data1.list, &datalist); | 961 | list_add_tail(&data1.list, &datalist); |
957 | drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg)); | 962 | drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg)); |
958 | list_add_tail(&data2.list, &datalist); | 963 | list_add_tail(&data2.list, &datalist); |
959 | ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist); | 964 | ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist); |
960 | if (ret) { | 965 | if (ret) { |
961 | len = ret; | 966 | len = ret; |
962 | goto out; | 967 | goto out; |
@@ -1600,14 +1605,20 @@ static int drbg_fini_hash_kernel(struct drbg_state *drbg) | |||
1600 | return 0; | 1605 | return 0; |
1601 | } | 1606 | } |
1602 | 1607 | ||
1603 | static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key, | 1608 | static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg, |
1604 | unsigned char *outval, const struct list_head *in) | 1609 | const unsigned char *key) |
1610 | { | ||
1611 | struct sdesc *sdesc = (struct sdesc *)drbg->priv_data; | ||
1612 | |||
1613 | crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg)); | ||
1614 | } | ||
1615 | |||
1616 | static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval, | ||
1617 | const struct list_head *in) | ||
1605 | { | 1618 | { |
1606 | struct sdesc *sdesc = (struct sdesc *)drbg->priv_data; | 1619 | struct sdesc *sdesc = (struct sdesc *)drbg->priv_data; |
1607 | struct drbg_string *input = NULL; | 1620 | struct drbg_string *input = NULL; |
1608 | 1621 | ||
1609 | if (key) | ||
1610 | crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg)); | ||
1611 | crypto_shash_init(&sdesc->shash); | 1622 | crypto_shash_init(&sdesc->shash); |
1612 | list_for_each_entry(input, in, list) | 1623 | list_for_each_entry(input, in, list) |
1613 | crypto_shash_update(&sdesc->shash, input->buf, input->len); | 1624 | crypto_shash_update(&sdesc->shash, input->buf, input->len); |