From 6b303169225f9e3ce62dd90445be61865af9b104 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 2 May 2015 15:11:41 +0100 Subject: [PATCH] Use find_pubkey_alg in openssh_read_new(). This is better than listing all the algorithm names in yet another place that will then need updating when a new key format is added. However, that also means I need to find a new place to put the 'npieces' value I was previously setting up differently per key type; since that's a fundamental property of the key format, I've moved it to a constant field in the ssh_signkey structure, and filled that field in for all the existing key types with the values from the replaced code in openssh_read_new(). --- import.c | 34 ++++++++++++---------------------- ssh.h | 9 +++++++++ sshdss.c | 1 + sshecc.c | 3 +++ sshrsa.c | 1 + 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/import.c b/import.c index 6206fdb1..92141d3a 100644 --- a/import.c +++ b/import.c @@ -1629,7 +1629,7 @@ struct ssh2_userkey *openssh_new_read(const Filename *filename, retkey = NULL; for (key_index = 0; key_index < key->nkeys; key_index++) { unsigned char *thiskey; - int thiskeylen, npieces; + int thiskeylen; /* * Read the key type, which will tell us how to scan over @@ -1647,26 +1647,16 @@ struct ssh2_userkey *openssh_new_read(const Filename *filename, * of strings, so we just need to know how many of them to * skip over. (The numbers below exclude the key comment.) */ - if (match_ssh_id(stringlen, string, "ssh-rsa")) { - alg = &ssh_rsa; - npieces = 6; /* n,e,d,iqmp,q,p */ - } else if (match_ssh_id(stringlen, string, "ssh-dss")) { - alg = &ssh_dss; - npieces = 5; /* p,q,g,y,x */ - } else if (match_ssh_id(stringlen, string, - "ecdsa-sha2-nistp256")) { - alg = &ssh_ecdsa_nistp256; - npieces = 3; /* curve name, point, private exponent */ - } else if (match_ssh_id(stringlen, string, - "ecdsa-sha2-nistp384")) { - alg = &ssh_ecdsa_nistp384; - npieces = 3; /* curve name, point, private exponent */ - } else if (match_ssh_id(stringlen, string, - "ecdsa-sha2-nistp521")) { - alg = &ssh_ecdsa_nistp521; - npieces = 3; /* curve name, point, private exponent */ - } else { - errmsg = "private key did not start with type string\n"; + { + /* find_pubkey_alg needs a zero-terminated copy of the + * algorithm name */ + char *name_zt = dupprintf("%.*s", stringlen, (char *)string); + alg = find_pubkey_alg(name_zt); + sfree(name_zt); + } + + if (!alg) { + errmsg = "private key type not recognised\n"; goto error; } @@ -1675,7 +1665,7 @@ struct ssh2_userkey *openssh_new_read(const Filename *filename, /* * Skip over the pieces of key. */ - for (i = 0; i < npieces; i++) { + for (i = 0; i < alg->openssh_private_npieces; i++) { if (!(string = get_ssh_string(&privlen, &priv, &stringlen))) { errmsg = "ran out of data in mid-private-key"; goto error; diff --git a/ssh.h b/ssh.h index f81d95c5..b733ffa0 100644 --- a/ssh.h +++ b/ssh.h @@ -333,6 +333,15 @@ struct ssh_signkey { unsigned char *priv_blob, int priv_len); void *(*openssh_createkey) (unsigned char **blob, int *len); int (*openssh_fmtkey) (void *key, unsigned char *blob, int len); + /* OpenSSH private key blobs, as created by openssh_fmtkey and + * consumed by openssh_createkey, always (at least so far...) take + * the form of a number of SSH-2 strings / mpints concatenated + * end-to-end. Because the new-style OpenSSH private key format + * stores those blobs without a containing string wrapper, we need + * to know how many strings each one consists of, so that we can + * skip over the right number to find the next key in the file. + * openssh_private_npieces gives that information. */ + int openssh_private_npieces; int (*pubkey_bits) (void *blob, int len); char *(*fingerprint) (void *key); int (*verifysig) (void *key, char *sig, int siglen, diff --git a/sshdss.c b/sshdss.c index 3682ad69..40285a02 100644 --- a/sshdss.c +++ b/sshdss.c @@ -701,6 +701,7 @@ const struct ssh_signkey ssh_dss = { dss_createkey, dss_openssh_createkey, dss_openssh_fmtkey, + 5 /* p,q,g,y,x */, dss_pubkey_bits, dss_fingerprint, dss_verifysig, diff --git a/sshecc.c b/sshecc.c index 10c4fc11..9b2e5020 100644 --- a/sshecc.c +++ b/sshecc.c @@ -1966,6 +1966,7 @@ const struct ssh_signkey ssh_ecdsa_nistp256 = { ecdsa_createkey, ecdsa_openssh_createkey, ecdsa_openssh_fmtkey, + 3 /* curve name, point, private exponent */, ecdsa_pubkey_bits, ecdsa_fingerprint, ecdsa_verifysig, @@ -1983,6 +1984,7 @@ const struct ssh_signkey ssh_ecdsa_nistp384 = { ecdsa_createkey, ecdsa_openssh_createkey, ecdsa_openssh_fmtkey, + 3 /* curve name, point, private exponent */, ecdsa_pubkey_bits, ecdsa_fingerprint, ecdsa_verifysig, @@ -2000,6 +2002,7 @@ const struct ssh_signkey ssh_ecdsa_nistp521 = { ecdsa_createkey, ecdsa_openssh_createkey, ecdsa_openssh_fmtkey, + 3 /* curve name, point, private exponent */, ecdsa_pubkey_bits, ecdsa_fingerprint, ecdsa_verifysig, diff --git a/sshrsa.c b/sshrsa.c index 25f9cf7e..058200f4 100644 --- a/sshrsa.c +++ b/sshrsa.c @@ -942,6 +942,7 @@ const struct ssh_signkey ssh_rsa = { rsa2_createkey, rsa2_openssh_createkey, rsa2_openssh_fmtkey, + 6 /* n,e,d,iqmp,q,p */, rsa2_pubkey_bits, rsa2_fingerprint, rsa2_verifysig,