]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - sshpubk.c
Sort out the mess with OpenSSH key file formats.
[PuTTY.git] / sshpubk.c
index cd35afd5ad2a15265324b03fa22bdedfeb4779f5..6aba82fc80630d19f2cac5bbfbf296c7d8d6752d 100644 (file)
--- a/sshpubk.c
+++ b/sshpubk.c
@@ -67,7 +67,7 @@ static int loadrsakey_main(FILE * fp, struct RSAKey *key, int pub_only,
     i += 4;
 
     /* Now the serious stuff. An ordinary SSH-1 public key. */
-    j = makekey(buf + i, len, key, NULL, 1);
+    j = makekey(buf + i, len - i, key, NULL, 1);
     if (j < 0)
        goto end;                      /* overran */
     i += j;
@@ -557,22 +557,29 @@ struct ssh2_userkey ssh2_wrong_passphrase = {
     NULL, NULL, NULL
 };
 
-const struct ssh_signkey *find_pubkey_alg(const char *name)
+const struct ssh_signkey *find_pubkey_alg_len(int namelen, const char *name)
 {
-    if (!strcmp(name, "ssh-rsa"))
+    if (match_ssh_id(namelen, name, "ssh-rsa"))
        return &ssh_rsa;
-    else if (!strcmp(name, "ssh-dss"))
+    else if (match_ssh_id(namelen, name, "ssh-dss"))
        return &ssh_dss;
-    else if (!strcmp(name, "ecdsa-sha2-nistp256"))
+    else if (match_ssh_id(namelen, name, "ecdsa-sha2-nistp256"))
         return &ssh_ecdsa_nistp256;
-    else if (!strcmp(name, "ecdsa-sha2-nistp384"))
+    else if (match_ssh_id(namelen, name, "ecdsa-sha2-nistp384"))
         return &ssh_ecdsa_nistp384;
-    else if (!strcmp(name, "ecdsa-sha2-nistp521"))
+    else if (match_ssh_id(namelen, name, "ecdsa-sha2-nistp521"))
         return &ssh_ecdsa_nistp521;
+    else if (match_ssh_id(namelen, name, "ssh-ed25519"))
+        return &ssh_ecdsa_ed25519;
     else
        return NULL;
 }
 
+const struct ssh_signkey *find_pubkey_alg(const char *name)
+{
+    return find_pubkey_alg_len(strlen(name), name);
+}
+
 struct ssh2_userkey *ssh2_load_userkey(const Filename *filename,
                                       char *passphrase, const char **errorstr)
 {
@@ -802,6 +809,7 @@ struct ssh2_userkey *ssh2_load_userkey(const Filename *filename,
        goto error;
     }
     sfree(public_blob);
+    smemclr(private_blob, private_blob_len);
     sfree(private_blob);
     sfree(encryption);
     if (errorstr)
@@ -822,8 +830,10 @@ struct ssh2_userkey *ssh2_load_userkey(const Filename *filename,
        sfree(mac);
     if (public_blob)
        sfree(public_blob);
-    if (private_blob)
-       sfree(private_blob);
+    if (private_blob) {
+        smemclr(private_blob, private_blob_len);
+        sfree(private_blob);
+    }
     if (errorstr)
        *errorstr = error;
     return ret;
@@ -840,7 +850,7 @@ unsigned char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm,
     int public_blob_len;
     int i;
     const char *error = NULL;
-    char *comment;
+    char *comment = NULL;
 
     public_blob = NULL;
 
@@ -865,11 +875,10 @@ unsigned char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm,
        goto error;
     /* Select key algorithm structure. */
     alg = find_pubkey_alg(b);
+    sfree(b);
     if (!alg) {
-       sfree(b);
        goto error;
     }
-    sfree(b);
 
     /* Read the Encryption header line. */
     if (!read_header(fp, header) || 0 != strcmp(header, "Encryption"))
@@ -916,6 +925,10 @@ unsigned char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm,
        sfree(public_blob);
     if (errorstr)
        *errorstr = error;
+    if (comment && commentptr) {
+        sfree(comment);
+        *commentptr = NULL;
+    }
     return NULL;
 }
 
@@ -1112,8 +1125,14 @@ int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key,
     }
 
     fp = f_open(filename, "w", TRUE);
-    if (!fp)
-       return 0;
+    if (!fp) {
+        sfree(pub_blob);
+        smemclr(priv_blob, priv_blob_len);
+        sfree(priv_blob);
+        smemclr(priv_blob_encrypted, priv_blob_len);
+        sfree(priv_blob_encrypted);
+        return 0;
+    }
     fprintf(fp, "PuTTY-User-Key-File-2: %s\n", key->alg->name);
     fprintf(fp, "Encryption: %s\n", cipherstr);
     fprintf(fp, "Comment: %s\n", key->comment);
@@ -1130,6 +1149,7 @@ int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key,
     sfree(pub_blob);
     smemclr(priv_blob, priv_blob_len);
     sfree(priv_blob);
+    smemclr(priv_blob_encrypted, priv_blob_len);
     sfree(priv_blob_encrypted);
     return 1;
 }
@@ -1144,6 +1164,7 @@ int key_type(const Filename *filename)
     char buf[32];
     const char putty2_sig[] = "PuTTY-User-Key-File-";
     const char sshcom_sig[] = "---- BEGIN SSH2 ENCRYPTED PRIVAT";
+    const char openssh_new_sig[] = "-----BEGIN OPENSSH PRIVATE KEY";
     const char openssh_sig[] = "-----BEGIN ";
     int i;
 
@@ -1160,8 +1181,10 @@ int key_type(const Filename *filename)
        return SSH_KEYTYPE_SSH1;
     if (!memcmp(buf, putty2_sig, sizeof(putty2_sig)-1))
        return SSH_KEYTYPE_SSH2;
+    if (!memcmp(buf, openssh_new_sig, sizeof(openssh_new_sig)-1))
+       return SSH_KEYTYPE_OPENSSH_NEW;
     if (!memcmp(buf, openssh_sig, sizeof(openssh_sig)-1))
-       return SSH_KEYTYPE_OPENSSH;
+       return SSH_KEYTYPE_OPENSSH_PEM;
     if (!memcmp(buf, sshcom_sig, sizeof(sshcom_sig)-1))
        return SSH_KEYTYPE_SSHCOM;
     return SSH_KEYTYPE_UNKNOWN;               /* unrecognised or EOF */
@@ -1178,8 +1201,16 @@ char *key_type_to_str(int type)
       case SSH_KEYTYPE_UNKNOWN: return "not a private key"; break;
       case SSH_KEYTYPE_SSH1: return "SSH-1 private key"; break;
       case SSH_KEYTYPE_SSH2: return "PuTTY SSH-2 private key"; break;
-      case SSH_KEYTYPE_OPENSSH: return "OpenSSH SSH-2 private key"; break;
+      case SSH_KEYTYPE_OPENSSH_PEM: return "OpenSSH SSH-2 private key (old PEM format)"; break;
+      case SSH_KEYTYPE_OPENSSH_NEW: return "OpenSSH SSH-2 private key (new format)"; break;
       case SSH_KEYTYPE_SSHCOM: return "ssh.com SSH-2 private key"; break;
+        /*
+         * This function is called with a key type derived from
+         * looking at an actual key file, so the output-only type
+         * OPENSSH_AUTO should never get here, and is much an INTERNAL
+         * ERROR as a code we don't even understand.
+         */
+      case SSH_KEYTYPE_OPENSSH_AUTO: return "INTERNAL ERROR (OPENSSH_AUTO)"; break;
       default: return "INTERNAL ERROR"; break;
     }
 }