]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - crypto/drbg.c
x86, msr: Convert printk to pr_foo()
[karo-tx-linux.git] / crypto / drbg.c
index 2a7860f73288b4fbf2ad343a45ee146da505a666..7894db9ca90b1e13c742841e41b309b39584e622 100644 (file)
@@ -184,7 +184,7 @@ static const struct drbg_core drbg_cores[] = {
 #endif /* CONFIG_CRYPTO_DRBG_HASH */
 #ifdef CONFIG_CRYPTO_DRBG_HMAC
        {
-               .flags = DRBG_HMAC | DRBG_STRENGTH256,
+               .flags = DRBG_HMAC | DRBG_STRENGTH128,
                .statelen = 20, /* block length of cipher */
                .max_addtllen = 35,
                .max_bits = 19,
@@ -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++;
@@ -1489,7 +1500,7 @@ static int drbg_generate_long(struct drbg_state *drbg,
                if (0 >= tmplen)
                        return tmplen;
                len += tmplen;
-       } while (slice > 0);
+       } while (slice > 0 && (len < buflen));
        return len;
 }
 
@@ -2008,7 +2019,7 @@ static int __init drbg_init(void)
        return crypto_register_algs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
 }
 
-void __exit drbg_exit(void)
+static void __exit drbg_exit(void)
 {
        crypto_unregister_algs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
 }