summaryrefslogtreecommitdiff
path: root/crypto/drbg.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/drbg.c')
-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:
/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
static int drbg_ctr_generate(struct drbg_state *drbg,
unsigned char *buf, unsigned int buflen,
- struct drbg_string *addtl)
+ struct list_head *addtl)
{
int len = 0;
int ret = 0;
@@ -656,11 +656,8 @@ static int drbg_ctr_generate(struct drbg_state *drbg,
memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
/* 10.2.1.5.2 step 2 */
- if (addtl && 0 < addtl->len) {
- LIST_HEAD(addtllist);
-
- list_add_tail(&addtl->list, &addtllist);
- ret = drbg_ctr_update(drbg, &addtllist, 2);
+ if (addtl && !list_empty(addtl)) {
+ ret = drbg_ctr_update(drbg, addtl, 2);
if (ret)
return 0;
}
@@ -777,7 +774,7 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
static int drbg_hmac_generate(struct drbg_state *drbg,
unsigned char *buf,
unsigned int buflen,
- struct drbg_string *addtl)
+ struct list_head *addtl)
{
int len = 0;
int ret = 0;
@@ -785,11 +782,8 @@ static int drbg_hmac_generate(struct drbg_state *drbg,
LIST_HEAD(datalist);
/* 10.1.2.5 step 2 */
- if (addtl && 0 < addtl->len) {
- LIST_HEAD(addtllist);
-
- list_add_tail(&addtl->list, &addtllist);
- ret = drbg_hmac_update(drbg, &addtllist, 1);
+ if (addtl && !list_empty(addtl)) {
+ ret = drbg_hmac_update(drbg, addtl, 1);
if (ret)
return ret;
}
@@ -813,14 +807,10 @@ static int drbg_hmac_generate(struct drbg_state *drbg,
}
/* 10.1.2.5 step 6 */
- if (addtl && 0 < addtl->len) {
- LIST_HEAD(addtllist);
-
- list_add_tail(&addtl->list, &addtllist);
- ret = drbg_hmac_update(drbg, &addtllist, 1);
- } else {
+ if (addtl && !list_empty(addtl))
+ ret = drbg_hmac_update(drbg, addtl, 1);
+ else
ret = drbg_hmac_update(drbg, NULL, 1);
- }
if (ret)
return ret;
@@ -944,7 +934,7 @@ out:
/* processing of additional information string for Hash DRBG */
static int drbg_hash_process_addtl(struct drbg_state *drbg,
- struct drbg_string *addtl)
+ struct list_head *addtl)
{
int ret = 0;
struct drbg_string data1, data2;
@@ -955,7 +945,7 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg,
memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
/* 10.1.1.4 step 2 */
- if (!addtl || 0 == addtl->len)
+ if (!addtl || list_empty(addtl))
return 0;
/* 10.1.1.4 step 2a */
@@ -963,7 +953,7 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg,
drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
list_add_tail(&data1.list, &datalist);
list_add_tail(&data2.list, &datalist);
- list_add_tail(&addtl->list, &datalist);
+ list_splice_tail(addtl, &datalist);
ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
if (ret)
goto out;
@@ -1029,7 +1019,7 @@ out:
/* generate function for Hash DRBG as defined in 10.1.1.4 */
static int drbg_hash_generate(struct drbg_state *drbg,
unsigned char *buf, unsigned int buflen,
- struct drbg_string *addtl)
+ struct list_head *addtl)
{
int len = 0;
int ret = 0;
@@ -1347,6 +1337,12 @@ static int drbg_generate(struct drbg_state *drbg,
{
int len = 0;
struct drbg_state *shadow = NULL;
+ LIST_HEAD(addtllist);
+ struct drbg_string timestamp;
+ union {
+ cycles_t cycles;
+ unsigned char char_cycles[sizeof(cycles_t)];
+ } now;
if (0 == buflen || !buf) {
pr_devel("DRBG: no output buffer provided\n");
@@ -1407,8 +1403,23 @@ static int drbg_generate(struct drbg_state *drbg,
/* 9.3.1 step 7.4 */
addtl = NULL;
}
+
+ /*
+ * Mix the time stamp into the DRBG state if the DRBG is not in
+ * test mode. If there are two callers invoking the DRBG at the same
+ * time, i.e. before the first caller merges its shadow state back,
+ * both callers would obtain the same random number stream without
+ * changing the state here.
+ */
+ if (!drbg->test_data) {
+ now.cycles = random_get_entropy();
+ drbg_string_fill(&timestamp, now.char_cycles, sizeof(cycles_t));
+ list_add_tail(&timestamp.list, &addtllist);
+ }
+ if (addtl && 0 < addtl->len)
+ list_add_tail(&addtl->list, &addtllist);
/* 9.3.1 step 8 and 10 */
- len = shadow->d_ops->generate(shadow, buf, buflen, addtl);
+ len = shadow->d_ops->generate(shadow, buf, buflen, &addtllist);
/* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
shadow->reseed_ctr++;