aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorStephan Mueller <smueller@chronox.de>2014-07-05 20:25:36 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2014-07-08 09:18:25 -0400
commit27e4de2bd1804c24e3e517dd54026c1f60e8fe27 (patch)
tree4f392026252cb1f1fb0a94a84204e424b0001b65 /crypto
parent4f150718797ffd539ace231d001eb41b09e13895 (diff)
crypto: drbg - Mix a time stamp into DRBG state
The current locking approach of the DRBG tries to keep the protected code paths very minimal. It is therefore possible that two threads query one DRBG instance at the same time. When thread A requests random numbers, a shadow copy of the DRBG state is created upon which the request for A is processed. After finishing the state for A's request is merged back into the DRBG state. If now thread B requests random numbers from the same DRBG after the request for thread A is received, but before A's shadow state is merged back, the random numbers for B will be identical to the ones for A. Please note that the time window is very small for this scenario. To prevent that there is even a theoretical chance for thread A and B having the same DRBG state, the current time stamp is provided as additional information string for each new request. The addition of the time stamp as additional information string implies that now all generate functions must be capable to process a linked list with additional information strings instead of a scalar. CC: Rafael Aquini <aquini@redhat.com> Signed-off-by: Stephan Mueller <smueller@chronox.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/drbg.c59
1 files changed, 35 insertions, 24 deletions
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 2a7860f73288..a76b3cb03cf4 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -646,7 +646,7 @@ out:
646/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */ 646/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
647static int drbg_ctr_generate(struct drbg_state *drbg, 647static int drbg_ctr_generate(struct drbg_state *drbg,
648 unsigned char *buf, unsigned int buflen, 648 unsigned char *buf, unsigned int buflen,
649 struct drbg_string *addtl) 649 struct list_head *addtl)
650{ 650{
651 int len = 0; 651 int len = 0;
652 int ret = 0; 652 int ret = 0;
@@ -656,11 +656,8 @@ static int drbg_ctr_generate(struct drbg_state *drbg,
656 memset(drbg->scratchpad, 0, drbg_blocklen(drbg)); 656 memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
657 657
658 /* 10.2.1.5.2 step 2 */ 658 /* 10.2.1.5.2 step 2 */
659 if (addtl && 0 < addtl->len) { 659 if (addtl && !list_empty(addtl)) {
660 LIST_HEAD(addtllist); 660 ret = drbg_ctr_update(drbg, addtl, 2);
661
662 list_add_tail(&addtl->list, &addtllist);
663 ret = drbg_ctr_update(drbg, &addtllist, 2);
664 if (ret) 661 if (ret)
665 return 0; 662 return 0;
666 } 663 }
@@ -777,7 +774,7 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
777static int drbg_hmac_generate(struct drbg_state *drbg, 774static int drbg_hmac_generate(struct drbg_state *drbg,
778 unsigned char *buf, 775 unsigned char *buf,
779 unsigned int buflen, 776 unsigned int buflen,
780 struct drbg_string *addtl) 777 struct list_head *addtl)
781{ 778{
782 int len = 0; 779 int len = 0;
783 int ret = 0; 780 int ret = 0;
@@ -785,11 +782,8 @@ static int drbg_hmac_generate(struct drbg_state *drbg,
785 LIST_HEAD(datalist); 782 LIST_HEAD(datalist);
786 783
787 /* 10.1.2.5 step 2 */ 784 /* 10.1.2.5 step 2 */
788 if (addtl && 0 < addtl->len) { 785 if (addtl && !list_empty(addtl)) {
789 LIST_HEAD(addtllist); 786 ret = drbg_hmac_update(drbg, addtl, 1);
790
791 list_add_tail(&addtl->list, &addtllist);
792 ret = drbg_hmac_update(drbg, &addtllist, 1);
793 if (ret) 787 if (ret)
794 return ret; 788 return ret;
795 } 789 }
@@ -813,14 +807,10 @@ static int drbg_hmac_generate(struct drbg_state *drbg,
813 } 807 }
814 808
815 /* 10.1.2.5 step 6 */ 809 /* 10.1.2.5 step 6 */
816 if (addtl && 0 < addtl->len) { 810 if (addtl && !list_empty(addtl))
817 LIST_HEAD(addtllist); 811 ret = drbg_hmac_update(drbg, addtl, 1);
818 812 else
819 list_add_tail(&addtl->list, &addtllist);
820 ret = drbg_hmac_update(drbg, &addtllist, 1);
821 } else {
822 ret = drbg_hmac_update(drbg, NULL, 1); 813 ret = drbg_hmac_update(drbg, NULL, 1);
823 }
824 if (ret) 814 if (ret)
825 return ret; 815 return ret;
826 816
@@ -944,7 +934,7 @@ out:
944 934
945/* processing of additional information string for Hash DRBG */ 935/* processing of additional information string for Hash DRBG */
946static int drbg_hash_process_addtl(struct drbg_state *drbg, 936static int drbg_hash_process_addtl(struct drbg_state *drbg,
947 struct drbg_string *addtl) 937 struct list_head *addtl)
948{ 938{
949 int ret = 0; 939 int ret = 0;
950 struct drbg_string data1, data2; 940 struct drbg_string data1, data2;
@@ -955,7 +945,7 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg,
955 memset(drbg->scratchpad, 0, drbg_blocklen(drbg)); 945 memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
956 946
957 /* 10.1.1.4 step 2 */ 947 /* 10.1.1.4 step 2 */
958 if (!addtl || 0 == addtl->len) 948 if (!addtl || list_empty(addtl))
959 return 0; 949 return 0;
960 950
961 /* 10.1.1.4 step 2a */ 951 /* 10.1.1.4 step 2a */
@@ -963,7 +953,7 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg,
963 drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg)); 953 drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
964 list_add_tail(&data1.list, &datalist); 954 list_add_tail(&data1.list, &datalist);
965 list_add_tail(&data2.list, &datalist); 955 list_add_tail(&data2.list, &datalist);
966 list_add_tail(&addtl->list, &datalist); 956 list_splice_tail(addtl, &datalist);
967 ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist); 957 ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
968 if (ret) 958 if (ret)
969 goto out; 959 goto out;
@@ -1029,7 +1019,7 @@ out:
1029/* generate function for Hash DRBG as defined in 10.1.1.4 */ 1019/* generate function for Hash DRBG as defined in 10.1.1.4 */
1030static int drbg_hash_generate(struct drbg_state *drbg, 1020static int drbg_hash_generate(struct drbg_state *drbg,
1031 unsigned char *buf, unsigned int buflen, 1021 unsigned char *buf, unsigned int buflen,
1032 struct drbg_string *addtl) 1022 struct list_head *addtl)
1033{ 1023{
1034 int len = 0; 1024 int len = 0;
1035 int ret = 0; 1025 int ret = 0;
@@ -1347,6 +1337,12 @@ static int drbg_generate(struct drbg_state *drbg,
1347{ 1337{
1348 int len = 0; 1338 int len = 0;
1349 struct drbg_state *shadow = NULL; 1339 struct drbg_state *shadow = NULL;
1340 LIST_HEAD(addtllist);
1341 struct drbg_string timestamp;
1342 union {
1343 cycles_t cycles;
1344 unsigned char char_cycles[sizeof(cycles_t)];
1345 } now;
1350 1346
1351 if (0 == buflen || !buf) { 1347 if (0 == buflen || !buf) {
1352 pr_devel("DRBG: no output buffer provided\n"); 1348 pr_devel("DRBG: no output buffer provided\n");
@@ -1407,8 +1403,23 @@ static int drbg_generate(struct drbg_state *drbg,
1407 /* 9.3.1 step 7.4 */ 1403 /* 9.3.1 step 7.4 */
1408 addtl = NULL; 1404 addtl = NULL;
1409 } 1405 }
1406
1407 /*
1408 * Mix the time stamp into the DRBG state if the DRBG is not in
1409 * test mode. If there are two callers invoking the DRBG at the same
1410 * time, i.e. before the first caller merges its shadow state back,
1411 * both callers would obtain the same random number stream without
1412 * changing the state here.
1413 */
1414 if (!drbg->test_data) {
1415 now.cycles = random_get_entropy();
1416 drbg_string_fill(&timestamp, now.char_cycles, sizeof(cycles_t));
1417 list_add_tail(&timestamp.list, &addtllist);
1418 }
1419 if (addtl && 0 < addtl->len)
1420 list_add_tail(&addtl->list, &addtllist);
1410 /* 9.3.1 step 8 and 10 */ 1421 /* 9.3.1 step 8 and 10 */
1411 len = shadow->d_ops->generate(shadow, buf, buflen, addtl); 1422 len = shadow->d_ops->generate(shadow, buf, buflen, &addtllist);
1412 1423
1413 /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */ 1424 /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
1414 shadow->reseed_ctr++; 1425 shadow->reseed_ctr++;