Sebastian Kuschel reports that pfd_closing can be called for a socket
[u/mdw/putty] / sshrsa.c
index c4a469e..4ec95f2 100644 (file)
--- a/sshrsa.c
+++ b/sshrsa.c
@@ -273,9 +273,18 @@ static Bignum rsa_privkey_op(Bignum input, struct RSAKey *key)
            bignum_cmp(random, key->modulus) >= 0) {
            freebn(random);
            continue;
-       } else {
-           break;
        }
+
+        /*
+         * Also, make sure it has an inverse mod modulus.
+         */
+        random_inverse = modinv(random, key->modulus);
+        if (!random_inverse) {
+           freebn(random);
+           continue;
+        }
+
+        break;
     }
 
     /*
@@ -294,7 +303,6 @@ static Bignum rsa_privkey_op(Bignum input, struct RSAKey *key)
      */
     random_encrypted = crt_modpow(random, key->exponent,
                                   key->modulus, key->p, key->q, key->iqmp);
-    random_inverse = modinv(random, key->modulus);
     input_blinded = modmul(input, random_encrypted, key->modulus);
     ret_blinded = crt_modpow(input_blinded, key->private_exponent,
                              key->modulus, key->p, key->q, key->iqmp);
@@ -415,7 +423,7 @@ int rsa_verify(struct RSAKey *key)
     ed = modmul(key->exponent, key->private_exponent, pm1);
     freebn(pm1);
     cmp = bignum_cmp(ed, One);
-    sfree(ed);
+    freebn(ed);
     if (cmp != 0)
        return 0;
 
@@ -424,7 +432,7 @@ int rsa_verify(struct RSAKey *key)
     ed = modmul(key->exponent, key->private_exponent, qm1);
     freebn(qm1);
     cmp = bignum_cmp(ed, One);
-    sfree(ed);
+    freebn(ed);
     if (cmp != 0)
        return 0;
 
@@ -443,6 +451,8 @@ int rsa_verify(struct RSAKey *key)
 
        freebn(key->iqmp);
        key->iqmp = modinv(key->q, key->p);
+        if (!key->iqmp)
+            return 0;
     }
 
     /*
@@ -450,7 +460,7 @@ int rsa_verify(struct RSAKey *key)
      */
     n = modmul(key->iqmp, key->q, key->p);
     cmp = bignum_cmp(n, One);
-    sfree(n);
+    freebn(n);
     if (cmp != 0)
        return 0;
 
@@ -551,6 +561,8 @@ static Bignum getmp(char **data, int *datalen)
     return b;
 }
 
+static void rsa2_freekey(void *key);   /* forward reference */
+
 static void *rsa2_newkey(char *data, int len)
 {
     char *p;
@@ -558,8 +570,6 @@ static void *rsa2_newkey(char *data, int len)
     struct RSAKey *rsa;
 
     rsa = snew(struct RSAKey);
-    if (!rsa)
-       return NULL;
     getstring(&data, &len, &p, &slen);
 
     if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) {
@@ -572,6 +582,11 @@ static void *rsa2_newkey(char *data, int len)
     rsa->p = rsa->q = rsa->iqmp = NULL;
     rsa->comment = NULL;
 
+    if (!rsa->exponent || !rsa->modulus) {
+        rsa2_freekey(rsa);
+        return NULL;
+    }
+
     return rsa;
 }
 
@@ -694,8 +709,6 @@ static void *rsa2_openssh_createkey(unsigned char **blob, int *len)
     struct RSAKey *rsa;
 
     rsa = snew(struct RSAKey);
-    if (!rsa)
-       return NULL;
     rsa->comment = NULL;
 
     rsa->modulus = getmp(b, len);
@@ -707,13 +720,12 @@ static void *rsa2_openssh_createkey(unsigned char **blob, int *len)
 
     if (!rsa->modulus || !rsa->exponent || !rsa->private_exponent ||
        !rsa->iqmp || !rsa->p || !rsa->q) {
-       sfree(rsa->modulus);
-       sfree(rsa->exponent);
-       sfree(rsa->private_exponent);
-       sfree(rsa->iqmp);
-       sfree(rsa->p);
-       sfree(rsa->q);
-       sfree(rsa);
+        rsa2_freekey(rsa);
+       return NULL;
+    }
+
+    if (!rsa_verify(rsa)) {
+       rsa2_freekey(rsa);
        return NULL;
     }