|
@@ -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(×tamp, now.char_cycles, sizeof(cycles_t));
|
|
|
+ list_add_tail(×tamp.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++;
|