]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - sshdss.c
Merge branch 'pre-0.64'.
[PuTTY.git] / sshdss.c
index 3ea36952b503882a89c80a7a7a76775a55c54f78..3682ad69e8ce85e223945e1965d58fb7281ddbef 100644 (file)
--- a/sshdss.c
+++ b/sshdss.c
@@ -286,6 +286,11 @@ static int dss_verifysig(void *key, char *sig, int siglen,
      * Step 1. w <- s^-1 mod q.
      */
     w = modinv(s, dss->q);
+    if (!w) {
+        freebn(r);
+        freebn(s);
+        return 0;
+    }
 
     /*
      * Step 2. u1 <- SHA(message) * w mod q.
@@ -513,7 +518,8 @@ static int dss_pubkey_bits(void *blob, int len)
     return ret;
 }
 
-static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
+Bignum *dss_gen_k(const char *id_string, Bignum modulus, Bignum private_key,
+                  unsigned char *digest, int digest_len)
 {
     /*
      * The basic DSS signing algorithm is:
@@ -586,21 +592,16 @@ static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
      * Computer Security Group for helping to argue out all the
      * fine details.
      */
-    struct dss_key *dss = (struct dss_key *) key;
     SHA512_State ss;
-    unsigned char digest[20], digest512[64];
-    Bignum proto_k, k, gkp, hash, kinv, hxr, r, s;
-    unsigned char *bytes;
-    int nbytes, i;
-
-    SHA_Simple(data, datalen, digest);
+    unsigned char digest512[64];
+    Bignum proto_k, k;
 
     /*
      * Hash some identifying text plus x.
      */
     SHA512_Init(&ss);
-    SHA512_Bytes(&ss, "DSA deterministic k generator", 30);
-    sha512_mpint(&ss, dss->x);
+    SHA512_Bytes(&ss, id_string, strlen(id_string) + 1);
+    sha512_mpint(&ss, private_key);
     SHA512_Final(&ss, digest512);
 
     /*
@@ -608,19 +609,49 @@ static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
      */
     SHA512_Init(&ss);
     SHA512_Bytes(&ss, digest512, sizeof(digest512));
-    SHA512_Bytes(&ss, digest, sizeof(digest));
-    SHA512_Final(&ss, digest512);
+    SHA512_Bytes(&ss, digest, digest_len);
+
+    while (1) {
+        SHA512_State ss2 = ss;         /* structure copy */
+        SHA512_Final(&ss2, digest512);
+
+        smemclr(&ss2, sizeof(ss2));
+
+        /*
+         * Now convert the result into a bignum, and reduce it mod q.
+         */
+        proto_k = bignum_from_bytes(digest512, 64);
+        k = bigmod(proto_k, modulus);
+        freebn(proto_k);
+
+        if (bignum_cmp(k, One) != 0 && bignum_cmp(k, Zero) != 0) {
+            smemclr(&ss, sizeof(ss));
+            smemclr(digest512, sizeof(digest512));
+            return k;
+        }
+
+        /* Very unlikely we get here, but if so, k was unsuitable. */
+        freebn(k);
+        /* Perturb the hash to think of a different k. */
+        SHA512_Bytes(&ss, "x", 1);
+        /* Go round and try again. */
+    }
+}
 
-    smemclr(&ss, sizeof(ss));
+static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
+{
+    struct dss_key *dss = (struct dss_key *) key;
+    Bignum k, gkp, hash, kinv, hxr, r, s;
+    unsigned char digest[20];
+    unsigned char *bytes;
+    int nbytes, i;
 
-    /*
-     * Now convert the result into a bignum, and reduce it mod q.
-     */
-    proto_k = bignum_from_bytes(digest512, 64);
-    k = bigmod(proto_k, dss->q);
-    freebn(proto_k);
+    SHA_Simple(data, datalen, digest);
 
-    smemclr(digest512, sizeof(digest512));
+    k = dss_gen_k("DSA deterministic k generator", dss->q, dss->x,
+                  digest, sizeof(digest));
+    kinv = modinv(k, dss->q);         /* k^-1 mod q */
+    assert(kinv);
 
     /*
      * Now we have k, so just go ahead and compute the signature.
@@ -630,7 +661,6 @@ static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
     freebn(gkp);
 
     hash = bignum_from_bytes(digest, 20);
-    kinv = modinv(k, dss->q);         /* k^-1 mod q */
     hxr = bigmuladd(dss->x, r, hash);  /* hash + x*r */
     s = modmul(kinv, hxr, dss->q);     /* s = k^-1 * (hash + x*r) mod q */
     freebn(hxr);