aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/drbg.c
diff options
context:
space:
mode:
authorStephan Mueller <smueller@chronox.de>2016-03-28 10:47:55 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2016-04-05 08:35:53 -0400
commit4218ebe8cab421c72f134cca1374e0985303f34a (patch)
tree813c3ec09204f4cd35998aaca752c22ae88beecd /crypto/drbg.c
parentbdb6cf9f6fe6d9af905ea34b7c4bb78ea601329e (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.c39
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)
595static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key, 595static 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);
597static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
598 const unsigned char *key);
597static int drbg_init_hash_kernel(struct drbg_state *drbg); 599static int drbg_init_hash_kernel(struct drbg_state *drbg);
598static int drbg_fini_hash_kernel(struct drbg_state *drbg); 600static 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
1603static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key, 1608static 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
1616static 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);