/* 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;
        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;
        }
 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;
        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;
        }
        }
 
        /* 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;
 
 
 /* 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;
        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 */
        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;
 /* 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;
 {
        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");
                /* 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++;