]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Fix mpint signedness bug in importing PEM ECDSA keys.
authorSimon Tatham <anakin@pobox.com>
Fri, 15 May 2015 13:01:35 +0000 (14:01 +0100)
committerSimon Tatham <anakin@pobox.com>
Fri, 15 May 2015 13:01:35 +0000 (14:01 +0100)
The OpenSSH PEM format contains a big integer with the top bit
potentially set, which we handle by copying the data into a faked up
instance of our own private key format, and passing that to
ecdsa_createkey(). But our own private key format expects an SSH-2
standard mpint, i.e. with the top bit reliably clear, so this might
fail for no good reason.

Fixed by prefixing a zero byte unconditionally when constructing the
fake private blob.

import.c

index 1e91f82adeefa230c3f7df59cadf32a4d70165e0..51b236a0517b29e92c0cb8c901ea18ab0386cc34 100644 (file)
--- a/import.c
+++ b/import.c
@@ -753,7 +753,7 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename,
             goto error;
         }
         retkey->alg = alg;
-        blob = snewn((4+19 + 4+8 + 4+len) + (4+privlen), unsigned char);
+        blob = snewn((4+19 + 4+8 + 4+len) + (4+1+privlen), unsigned char);
         if (!blob) {
             sfree(retkey);
             errmsg = "out of memory";
@@ -773,12 +773,20 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename,
         PUT_32BIT(q, len); q += 4;
         memcpy(q, p, len); q += len;
 
-        PUT_32BIT(q, privlen);
-        memcpy(q+4, priv, privlen);
+        /*
+         * To be acceptable to our createkey(), the private blob must
+         * contain a valid mpint, i.e. without the top bit set. But
+         * the input private string may have the top bit set, so we
+         * prefix a zero byte to ensure createkey() doesn't fail for
+         * that reason.
+         */
+        PUT_32BIT(q, privlen+1);
+        q[4] = 0;
+        memcpy(q+5, priv, privlen);
 
         retkey->data = retkey->alg->createkey(retkey->alg,
                                               blob, q-blob,
-                                              q, 4+privlen);
+                                              q, 5+privlen);
 
         if (!retkey->data) {
             sfree(retkey);