Commit 27e4de2bd1804c24e3e517dd54026c1f60e8fe27

Authored by Stephan Mueller
Committed by Herbert Xu
1 parent 4f15071879

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>

Showing 2 changed files with 36 additions and 25 deletions Side-by-side Diff

... ... @@ -646,7 +646,7 @@
646 646 /* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
647 647 static int drbg_ctr_generate(struct drbg_state *drbg,
648 648 unsigned char *buf, unsigned int buflen,
649   - struct drbg_string *addtl)
  649 + struct list_head *addtl)
650 650 {
651 651 int len = 0;
652 652 int ret = 0;
... ... @@ -656,11 +656,8 @@
656 656 memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
657 657  
658 658 /* 10.2.1.5.2 step 2 */
659   - if (addtl && 0 < addtl->len) {
660   - LIST_HEAD(addtllist);
661   -
662   - list_add_tail(&addtl->list, &addtllist);
663   - ret = drbg_ctr_update(drbg, &addtllist, 2);
  659 + if (addtl && !list_empty(addtl)) {
  660 + ret = drbg_ctr_update(drbg, addtl, 2);
664 661 if (ret)
665 662 return 0;
666 663 }
... ... @@ -777,7 +774,7 @@
777 774 static int drbg_hmac_generate(struct drbg_state *drbg,
778 775 unsigned char *buf,
779 776 unsigned int buflen,
780   - struct drbg_string *addtl)
  777 + struct list_head *addtl)
781 778 {
782 779 int len = 0;
783 780 int ret = 0;
... ... @@ -785,11 +782,8 @@
785 782 LIST_HEAD(datalist);
786 783  
787 784 /* 10.1.2.5 step 2 */
788   - if (addtl && 0 < addtl->len) {
789   - LIST_HEAD(addtllist);
790   -
791   - list_add_tail(&addtl->list, &addtllist);
792   - ret = drbg_hmac_update(drbg, &addtllist, 1);
  785 + if (addtl && !list_empty(addtl)) {
  786 + ret = drbg_hmac_update(drbg, addtl, 1);
793 787 if (ret)
794 788 return ret;
795 789 }
796 790  
... ... @@ -813,14 +807,10 @@
813 807 }
814 808  
815 809 /* 10.1.2.5 step 6 */
816   - if (addtl && 0 < addtl->len) {
817   - LIST_HEAD(addtllist);
818   -
819   - list_add_tail(&addtl->list, &addtllist);
820   - ret = drbg_hmac_update(drbg, &addtllist, 1);
821   - } else {
  810 + if (addtl && !list_empty(addtl))
  811 + ret = drbg_hmac_update(drbg, addtl, 1);
  812 + else
822 813 ret = drbg_hmac_update(drbg, NULL, 1);
823   - }
824 814 if (ret)
825 815 return ret;
826 816  
... ... @@ -944,7 +934,7 @@
944 934  
945 935 /* processing of additional information string for Hash DRBG */
946 936 static int drbg_hash_process_addtl(struct drbg_state *drbg,
947   - struct drbg_string *addtl)
  937 + struct list_head *addtl)
948 938 {
949 939 int ret = 0;
950 940 struct drbg_string data1, data2;
... ... @@ -955,7 +945,7 @@
955 945 memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
956 946  
957 947 /* 10.1.1.4 step 2 */
958   - if (!addtl || 0 == addtl->len)
  948 + if (!addtl || list_empty(addtl))
959 949 return 0;
960 950  
961 951 /* 10.1.1.4 step 2a */
... ... @@ -963,7 +953,7 @@
963 953 drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
964 954 list_add_tail(&data1.list, &datalist);
965 955 list_add_tail(&data2.list, &datalist);
966   - list_add_tail(&addtl->list, &datalist);
  956 + list_splice_tail(addtl, &datalist);
967 957 ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
968 958 if (ret)
969 959 goto out;
... ... @@ -1029,7 +1019,7 @@
1029 1019 /* generate function for Hash DRBG as defined in 10.1.1.4 */
1030 1020 static int drbg_hash_generate(struct drbg_state *drbg,
1031 1021 unsigned char *buf, unsigned int buflen,
1032   - struct drbg_string *addtl)
  1022 + struct list_head *addtl)
1033 1023 {
1034 1024 int len = 0;
1035 1025 int ret = 0;
... ... @@ -1347,6 +1337,12 @@
1347 1337 {
1348 1338 int len = 0;
1349 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 1347 if (0 == buflen || !buf) {
1352 1348 pr_devel("DRBG: no output buffer provided\n");
1353 1349  
... ... @@ -1407,8 +1403,23 @@
1407 1403 /* 9.3.1 step 7.4 */
1408 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 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 1424 /* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
1414 1425 shadow->reseed_ctr++;
include/crypto/drbg.h
... ... @@ -102,7 +102,7 @@
102 102 int reseed);
103 103 int (*generate)(struct drbg_state *drbg,
104 104 unsigned char *buf, unsigned int buflen,
105   - struct drbg_string *addtl);
  105 + struct list_head *addtl);
106 106 int (*crypto_init)(struct drbg_state *drbg);
107 107 int (*crypto_fini)(struct drbg_state *drbg);
108 108