Skip to content

Commit 27e4de2

Browse files
smuellerDDherbertx
authored andcommitted
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>
1 parent 4f15071 commit 27e4de2

File tree

2 files changed

+36
-25
lines changed

2 files changed

+36
-25
lines changed

crypto/drbg.c

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
646646
/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
647647
static int drbg_ctr_generate(struct drbg_state *drbg,
648648
unsigned char *buf, unsigned int buflen,
649-
struct drbg_string *addtl)
649+
struct list_head *addtl)
650650
{
651651
int len = 0;
652652
int ret = 0;
@@ -656,11 +656,8 @@ static int drbg_ctr_generate(struct drbg_state *drbg,
656656
memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
657657

658658
/* 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);
664661
if (ret)
665662
return 0;
666663
}
@@ -777,19 +774,16 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
777774
static int drbg_hmac_generate(struct drbg_state *drbg,
778775
unsigned char *buf,
779776
unsigned int buflen,
780-
struct drbg_string *addtl)
777+
struct list_head *addtl)
781778
{
782779
int len = 0;
783780
int ret = 0;
784781
struct drbg_string data;
785782
LIST_HEAD(datalist);
786783

787784
/* 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);
793787
if (ret)
794788
return ret;
795789
}
@@ -813,14 +807,10 @@ static int drbg_hmac_generate(struct drbg_state *drbg,
813807
}
814808

815809
/* 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
822813
ret = drbg_hmac_update(drbg, NULL, 1);
823-
}
824814
if (ret)
825815
return ret;
826816

@@ -944,7 +934,7 @@ static int drbg_hash_update(struct drbg_state *drbg, struct list_head *seed,
944934

945935
/* processing of additional information string for Hash DRBG */
946936
static int drbg_hash_process_addtl(struct drbg_state *drbg,
947-
struct drbg_string *addtl)
937+
struct list_head *addtl)
948938
{
949939
int ret = 0;
950940
struct drbg_string data1, data2;
@@ -955,15 +945,15 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg,
955945
memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
956946

957947
/* 10.1.1.4 step 2 */
958-
if (!addtl || 0 == addtl->len)
948+
if (!addtl || list_empty(addtl))
959949
return 0;
960950

961951
/* 10.1.1.4 step 2a */
962952
drbg_string_fill(&data1, &prefix, 1);
963953
drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
964954
list_add_tail(&data1.list, &datalist);
965955
list_add_tail(&data2.list, &datalist);
966-
list_add_tail(&addtl->list, &datalist);
956+
list_splice_tail(addtl, &datalist);
967957
ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
968958
if (ret)
969959
goto out;
@@ -1029,7 +1019,7 @@ static int drbg_hash_hashgen(struct drbg_state *drbg,
10291019
/* generate function for Hash DRBG as defined in 10.1.1.4 */
10301020
static int drbg_hash_generate(struct drbg_state *drbg,
10311021
unsigned char *buf, unsigned int buflen,
1032-
struct drbg_string *addtl)
1022+
struct list_head *addtl)
10331023
{
10341024
int len = 0;
10351025
int ret = 0;
@@ -1347,6 +1337,12 @@ static int drbg_generate(struct drbg_state *drbg,
13471337
{
13481338
int len = 0;
13491339
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;
13501346

13511347
if (0 == buflen || !buf) {
13521348
pr_devel("DRBG: no output buffer provided\n");
@@ -1407,8 +1403,23 @@ static int drbg_generate(struct drbg_state *drbg,
14071403
/* 9.3.1 step 7.4 */
14081404
addtl = NULL;
14091405
}
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);
14101421
/* 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);
14121423

14131424
/* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
14141425
shadow->reseed_ctr++;

include/crypto/drbg.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ struct drbg_state_ops {
102102
int reseed);
103103
int (*generate)(struct drbg_state *drbg,
104104
unsigned char *buf, unsigned int buflen,
105-
struct drbg_string *addtl);
105+
struct list_head *addtl);
106106
int (*crypto_init)(struct drbg_state *drbg);
107107
int (*crypto_fini)(struct drbg_state *drbg);
108108

0 commit comments

Comments
 (0)