Modify the new rsa_verify routine. We now also check the integrity of
[u/mdw/putty] / sshrsa.c
index aeafec3..fa5bfa2 100644 (file)
--- a/sshrsa.c
+++ b/sshrsa.c
@@ -151,6 +151,57 @@ void rsa_fingerprint(char *str, int len, struct RSAKey *key) {
     }
 }
 
+/*
+ * Verify that the public data in an RSA key matches the private
+ * data. We also check the private data itself: we ensure that p >
+ * q and that iqmp really is the inverse of q mod p.
+ */
+int rsa_verify(struct RSAKey *key) {
+    Bignum n, ed, pm1, qm1;
+    int cmp;
+
+    /* n must equal pq. */
+    n = bigmul(key->p, key->q);
+    cmp = bignum_cmp(n, key->modulus);
+    freebn(n);
+    if (cmp != 0)
+       return 0;
+
+    /* e * d must be congruent to 1, modulo (p-1) and modulo (q-1). */
+    pm1 = copybn(key->p);
+    decbn(pm1);
+    ed = modmul(key->exponent, key->private_exponent, pm1);
+    cmp = bignum_cmp(ed, One);
+    sfree(ed);
+    if (cmp != 0)
+       return 0;
+
+    qm1 = copybn(key->q);
+    decbn(qm1);
+    ed = modmul(key->exponent, key->private_exponent, qm1);
+    cmp = bignum_cmp(ed, One);
+    sfree(ed);
+    if (cmp != 0)
+       return 0;
+
+    /*
+     * Ensure p > q.
+     */
+    if (bignum_cmp(key->p, key->q) <= 0)
+        return 0;
+
+    /*
+     * Ensure iqmp * q is congruent to 1, modulo p.
+     */
+    n = modmul(key->iqmp, key->q, key->p);
+    cmp = bignum_cmp(n, One);
+    sfree(n);
+    if (cmp != 0)
+        return 0;
+
+    return 1;
+}
+
 void freersakey(struct RSAKey *key) {
     if (key->modulus) freebn(key->modulus);
     if (key->exponent) freebn(key->exponent);
@@ -231,7 +282,7 @@ static char *rsa2_fmtkey(void *key) {
     
     len = rsastr_len(rsa);
     p = smalloc(len);
-    rsastr_fmt(p, rsa);
+     rsastr_fmt(p, rsa);
     return p;
 }
 
@@ -304,6 +355,11 @@ static void *rsa2_createkey(unsigned char *pub_blob, int pub_len,
     rsa->q = getmp(&pb, &priv_len);
     rsa->iqmp = getmp(&pb, &priv_len);
 
+    if (!rsa_verify(rsa)) {
+       rsa2_freekey(rsa);
+       return NULL;
+    }
+
     return rsa;
 }