Fix dsa keygen for too-short seed

If the seed value for dsa key generation is too short (< qsize),
return an error.

(Imported from upstream's 1d7df236dcb4f7c95707110753e5e77b19b9a0aa and
df1565ed9cebb6933ee7c6e762abcfefd1cd3846.)

This switches the trigger for random seed from seed_len = 0 to seed_in =
NULL.

Change-Id: I2e07abed754c57ef9d96b02a52ba6d260c3f5fb9
Reviewed-on: https://boringssl-review.googlesource.com/5781
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/dsa/dsa_impl.c b/crypto/dsa/dsa_impl.c
index e4984b4..b10610d 100644
--- a/crypto/dsa/dsa_impl.c
+++ b/crypto/dsa/dsa_impl.c
@@ -487,16 +487,14 @@
 
   bits = (bits + 63) / 64 * 64;
 
-  /* NB: seed_len == 0 is special case: copy generated seed to
-   * seed_in if it is not NULL. */
-  if (seed_len && (seed_len < (size_t)qsize)) {
-    seed_in = NULL; /* seed buffer too small -- ignore */
-  }
-  if (seed_len > (size_t)qsize) {
-    seed_len = qsize; /* App. 2.2 of FIPS PUB 186 allows larger SEED,
-                       * but our internal buffers are restricted to 160 bits*/
-  }
   if (seed_in != NULL) {
+    if (seed_len < (size_t)qsize) {
+      return 0;
+    }
+    if (seed_len > (size_t)qsize) {
+      /* Only consume as much seed as is expected. */
+      seed_len = qsize;
+    }
     memcpy(seed, seed_in, seed_len);
   }
 
@@ -527,21 +525,19 @@
   for (;;) {
     /* Find q. */
     for (;;) {
-      int seed_is_random;
-
       /* step 1 */
       if (!BN_GENCB_call(cb, 0, m++)) {
         goto err;
       }
 
-      if (!seed_len) {
+      int use_random_seed = (seed_in == NULL);
+      if (use_random_seed) {
         if (!RAND_bytes(seed, qsize)) {
           goto err;
         }
-        seed_is_random = 1;
       } else {
-        seed_is_random = 0;
-        seed_len = 0; /* use random seed if 'seed_in' turns out to be bad*/
+        /* If we come back through, use random seed next time. */
+        seed_in = NULL;
       }
       memcpy(buf, seed, qsize);
       memcpy(buf2, seed, qsize);
@@ -570,7 +566,7 @@
       }
 
       /* step 4 */
-      r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx, seed_is_random, cb);
+      r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx, use_random_seed, cb);
       if (r > 0) {
         break;
       }