From 870ad6ab0780c68e0e71d1a14d394aa543a8b89e Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 15 May 2015 10:12:07 +0100 Subject: [PATCH] Pass the ssh_signkey structure itself to public key methods. Not all of them, but the ones that don't get a 'void *key' parameter. This means I can share methods between multiple ssh_signkey structures, and still give those methods an easy way to find out which public key method they're dealing with, by loading parameters from a larger structure in which the ssh_signkey is the first element. (In OO terms, I'm arranging that all static methods of my public key classes get a pointer to the class vtable, to make up for not having a pointer to the class instance.) I haven't actually done anything with the new facility in this commit, but it will shortly allow me to clean up the constant lookups by curve name in the ECDSA code. --- cmdgen.c | 3 ++- import.c | 9 +++++---- pageant.c | 2 +- ssh.c | 9 ++++++--- ssh.h | 12 ++++++++---- sshdss.c | 16 ++++++++++------ sshecc.c | 19 ++++++++++++------- sshpubk.c | 4 ++-- sshrsa.c | 18 +++++++++++------- 9 files changed, 57 insertions(+), 35 deletions(-) diff --git a/cmdgen.c b/cmdgen.c index 3d51347b..c1f3a8cb 100644 --- a/cmdgen.c +++ b/cmdgen.c @@ -786,7 +786,8 @@ int main(int argc, char **argv) if (ssh2blob) { ssh2algf = find_pubkey_alg(ssh2alg); if (ssh2algf) - bits = ssh2algf->pubkey_bits(ssh2blob, ssh2bloblen); + bits = ssh2algf->pubkey_bits(ssh2algf, + ssh2blob, ssh2bloblen); else bits = -1; } diff --git a/import.c b/import.c index 34f29acf..95386a0a 100644 --- a/import.c +++ b/import.c @@ -777,7 +777,8 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, memcpy(blob+4+19+4+8+4, p, len); PUT_32BIT(blob+4+19+4+8+4+len, privlen); memcpy(blob+4+19+4+8+4+len+4, priv, privlen); - retkey->data = retkey->alg->createkey(blob, 4+19+4+8+4+len, + retkey->data = retkey->alg->createkey(retkey->alg, + blob, 4+19+4+8+4+len, blob+4+19+4+8+4+len, 4+privlen); if (!retkey->data) { @@ -867,7 +868,7 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, assert(privptr > 0); /* should have bombed by now if not */ retkey = snew(struct ssh2_userkey); retkey->alg = (key->keytype == OP_RSA ? &ssh_rsa : &ssh_dss); - retkey->data = retkey->alg->createkey(blob, privptr, + retkey->data = retkey->alg->createkey(retkey->alg, blob, privptr, blob+privptr, blobptr-privptr); if (!retkey->data) { @@ -1679,7 +1680,7 @@ struct ssh2_userkey *openssh_new_read(const Filename *filename, if (key_index == key->key_wanted) { retkey = snew(struct ssh2_userkey); retkey->alg = alg; - retkey->data = alg->openssh_createkey(&thiskey, &thiskeylen); + retkey->data = alg->openssh_createkey(alg, &thiskey, &thiskeylen); if (!retkey->data) { sfree(retkey); errmsg = "unable to create key data structure"; @@ -2457,7 +2458,7 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase, retkey = snew(struct ssh2_userkey); retkey->alg = alg; - retkey->data = alg->createkey(blob, publen, blob+publen, privlen); + retkey->data = alg->createkey(alg, blob, publen, blob+publen, privlen); if (!retkey->data) { sfree(retkey); errmsg = "unable to create key data structure"; diff --git a/pageant.c b/pageant.c index da320681..d1db8623 100644 --- a/pageant.c +++ b/pageant.c @@ -674,7 +674,7 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen, } bloblen = msgend - p; - key->data = key->alg->openssh_createkey(&p, &bloblen); + key->data = key->alg->openssh_createkey(key->alg, &p, &bloblen); if (!key->data) { sfree(key); fail_reason = "key setup failed"; diff --git a/ssh.c b/ssh.c index db820050..bd7471fa 100644 --- a/ssh.c +++ b/ssh.c @@ -6805,7 +6805,8 @@ static void do_ssh2_transport(Ssh ssh, void *vin, int inlen, } set_busy_status(ssh->frontend, BUSY_CPU); /* cogitate */ ssh_pkt_getstring(pktin, &s->hostkeydata, &s->hostkeylen); - s->hkey = ssh->hostkey->newkey(s->hostkeydata, s->hostkeylen); + s->hkey = ssh->hostkey->newkey(ssh->hostkey, + s->hostkeydata, s->hostkeylen); s->f = ssh2_pkt_getmp(pktin); if (!s->f) { bombout(("unable to parse key exchange reply packet")); @@ -6883,7 +6884,8 @@ static void do_ssh2_transport(Ssh ssh, void *vin, int inlen, ssh_pkt_getstring(pktin, &s->hostkeydata, &s->hostkeylen); hash_string(ssh->kex->hash, ssh->exhash, s->hostkeydata, s->hostkeylen); - s->hkey = ssh->hostkey->newkey(s->hostkeydata, s->hostkeylen); + s->hkey = ssh->hostkey->newkey(ssh->hostkey, + s->hostkeydata, s->hostkeylen); { char *publicPoint; @@ -6932,7 +6934,8 @@ static void do_ssh2_transport(Ssh ssh, void *vin, int inlen, ssh_pkt_getstring(pktin, &s->hostkeydata, &s->hostkeylen); hash_string(ssh->kex->hash, ssh->exhash, s->hostkeydata, s->hostkeylen); - s->hkey = ssh->hostkey->newkey(s->hostkeydata, s->hostkeylen); + s->hkey = ssh->hostkey->newkey(ssh->hostkey, + s->hostkeydata, s->hostkeylen); { char *keydata; diff --git a/ssh.h b/ssh.h index ffa88665..f23972f0 100644 --- a/ssh.h +++ b/ssh.h @@ -356,14 +356,17 @@ struct ssh_kexes { }; struct ssh_signkey { - void *(*newkey) (const char *data, int len); + void *(*newkey) (const struct ssh_signkey *self, + const char *data, int len); void (*freekey) (void *key); char *(*fmtkey) (void *key); unsigned char *(*public_blob) (void *key, int *len); unsigned char *(*private_blob) (void *key, int *len); - void *(*createkey) (const unsigned char *pub_blob, int pub_len, + void *(*createkey) (const struct ssh_signkey *self, + const unsigned char *pub_blob, int pub_len, const unsigned char *priv_blob, int priv_len); - void *(*openssh_createkey) (const unsigned char **blob, int *len); + void *(*openssh_createkey) (const struct ssh_signkey *self, + const 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 @@ -374,7 +377,8 @@ struct ssh_signkey { * 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) (const void *blob, int len); + int (*pubkey_bits) (const struct ssh_signkey *self, + const void *blob, int len); int (*verifysig) (void *key, const char *sig, int siglen, const char *data, int datalen); unsigned char *(*sign) (void *key, const char *data, int datalen, diff --git a/sshdss.c b/sshdss.c index 80056266..bd7e0887 100644 --- a/sshdss.c +++ b/sshdss.c @@ -85,7 +85,8 @@ static Bignum get160(const char **data, int *datalen) static void dss_freekey(void *key); /* forward reference */ -static void *dss_newkey(const char *data, int len) +static void *dss_newkey(const struct ssh_signkey *self, + const char *data, int len) { const char *p; int slen; @@ -366,7 +367,8 @@ static unsigned char *dss_private_blob(void *key, int *len) return blob; } -static void *dss_createkey(const unsigned char *pub_blob, int pub_len, +static void *dss_createkey(const struct ssh_signkey *self, + const unsigned char *pub_blob, int pub_len, const unsigned char *priv_blob, int priv_len) { struct dss_key *dss; @@ -377,7 +379,7 @@ static void *dss_createkey(const unsigned char *pub_blob, int pub_len, unsigned char digest[20]; Bignum ytest; - dss = dss_newkey((char *) pub_blob, pub_len); + dss = dss_newkey(self, (char *) pub_blob, pub_len); if (!dss) return NULL; dss->x = getmp(&pb, &priv_len); @@ -417,7 +419,8 @@ static void *dss_createkey(const unsigned char *pub_blob, int pub_len, return dss; } -static void *dss_openssh_createkey(const unsigned char **blob, int *len) +static void *dss_openssh_createkey(const struct ssh_signkey *self, + const unsigned char **blob, int *len) { const char **b = (const char **) blob; struct dss_key *dss; @@ -468,12 +471,13 @@ static int dss_openssh_fmtkey(void *key, unsigned char *blob, int len) return bloblen; } -static int dss_pubkey_bits(const void *blob, int len) +static int dss_pubkey_bits(const struct ssh_signkey *self, + const void *blob, int len) { struct dss_key *dss; int ret; - dss = dss_newkey((const char *) blob, len); + dss = dss_newkey(self, (const char *) blob, len); if (!dss) return -1; ret = bignum_bitcount(dss->p); diff --git a/sshecc.c b/sshecc.c index 6915eaf0..84ab2477 100644 --- a/sshecc.c +++ b/sshecc.c @@ -2585,7 +2585,8 @@ static void ecdsa_freekey(void *key) sfree(ec); } -static void *ecdsa_newkey(const char *data, int len) +static void *ecdsa_newkey(const struct ssh_signkey *self, + const char *data, int len) { const char *p; int slen; @@ -2788,14 +2789,15 @@ static unsigned char *ecdsa_private_blob(void *key, int *len) return blob; } -static void *ecdsa_createkey(const unsigned char *pub_blob, int pub_len, +static void *ecdsa_createkey(const struct ssh_signkey *self, + const unsigned char *pub_blob, int pub_len, const unsigned char *priv_blob, int priv_len) { struct ec_key *ec; struct ec_point *publicKey; const char *pb = (const char *) priv_blob; - ec = (struct ec_key*)ecdsa_newkey((const char *) pub_blob, pub_len); + ec = (struct ec_key*)ecdsa_newkey(self, (const char *) pub_blob, pub_len); if (!ec) { return NULL; } @@ -2831,7 +2833,8 @@ static void *ecdsa_createkey(const unsigned char *pub_blob, int pub_len, return ec; } -static void *ed25519_openssh_createkey(const unsigned char **blob, int *len) +static void *ed25519_openssh_createkey(const struct ssh_signkey *self, + const unsigned char **blob, int *len) { struct ec_key *ec; struct ec_point *publicKey; @@ -2950,7 +2953,8 @@ static int ed25519_openssh_fmtkey(void *key, unsigned char *blob, int len) return bloblen; } -static void *ecdsa_openssh_createkey(const unsigned char **blob, int *len) +static void *ecdsa_openssh_createkey(const struct ssh_signkey *self, + const unsigned char **blob, int *len) { const char **b = (const char **) blob; const char *p; @@ -3068,12 +3072,13 @@ static int ecdsa_openssh_fmtkey(void *key, unsigned char *blob, int len) return bloblen; } -static int ecdsa_pubkey_bits(const void *blob, int len) +static int ecdsa_pubkey_bits(const struct ssh_signkey *self, + const void *blob, int len) { struct ec_key *ec; int ret; - ec = (struct ec_key*)ecdsa_newkey((const char *) blob, len); + ec = (struct ec_key*)ecdsa_newkey(self, (const char *) blob, len); if (!ec) return -1; ret = ec->publicKey.curve->fieldBits; diff --git a/sshpubk.c b/sshpubk.c index 2070fe41..30f9e4b3 100644 --- a/sshpubk.c +++ b/sshpubk.c @@ -853,7 +853,7 @@ struct ssh2_userkey *ssh2_load_userkey(const Filename *filename, ret = snew(struct ssh2_userkey); ret->alg = alg; ret->comment = comment; - ret->data = alg->createkey(public_blob, public_blob_len, + ret->data = alg->createkey(alg, public_blob, public_blob_len, private_blob, private_blob_len); if (!ret->data) { sfree(ret); @@ -1600,7 +1600,7 @@ char *ssh2_fingerprint_blob(const void *blob, int bloblen) */ alg = find_pubkey_alg_len(alglen, algstr); if (alg) { - int bits = alg->pubkey_bits(blob, bloblen); + int bits = alg->pubkey_bits(alg, blob, bloblen); return dupprintf("%.*s %d %s", alglen, algstr, bits, fingerprint_str); } else { diff --git a/sshrsa.c b/sshrsa.c index 9042c43a..32694456 100644 --- a/sshrsa.c +++ b/sshrsa.c @@ -565,7 +565,8 @@ static Bignum getmp(const char **data, int *datalen) static void rsa2_freekey(void *key); /* forward reference */ -static void *rsa2_newkey(const char *data, int len) +static void *rsa2_newkey(const struct ssh_signkey *self, + const char *data, int len) { const char *p; int slen; @@ -685,13 +686,14 @@ static unsigned char *rsa2_private_blob(void *key, int *len) return blob; } -static void *rsa2_createkey(const unsigned char *pub_blob, int pub_len, +static void *rsa2_createkey(const struct ssh_signkey *self, + const unsigned char *pub_blob, int pub_len, const unsigned char *priv_blob, int priv_len) { struct RSAKey *rsa; const char *pb = (const char *) priv_blob; - rsa = rsa2_newkey((char *) pub_blob, pub_len); + rsa = rsa2_newkey(self, (char *) pub_blob, pub_len); rsa->private_exponent = getmp(&pb, &priv_len); rsa->p = getmp(&pb, &priv_len); rsa->q = getmp(&pb, &priv_len); @@ -705,7 +707,8 @@ static void *rsa2_createkey(const unsigned char *pub_blob, int pub_len, return rsa; } -static void *rsa2_openssh_createkey(const unsigned char **blob, int *len) +static void *rsa2_openssh_createkey(const struct ssh_signkey *self, + const unsigned char **blob, int *len) { const char **b = (const char **) blob; struct RSAKey *rsa; @@ -763,12 +766,13 @@ static int rsa2_openssh_fmtkey(void *key, unsigned char *blob, int len) return bloblen; } -static int rsa2_pubkey_bits(const void *blob, int len) +static int rsa2_pubkey_bits(const struct ssh_signkey *self, + const void *blob, int len) { struct RSAKey *rsa; int ret; - rsa = rsa2_newkey((const char *) blob, len); + rsa = rsa2_newkey(self, (const char *) blob, len); ret = bignum_bitcount(rsa->modulus); rsa2_freekey(rsa); @@ -918,7 +922,7 @@ const struct ssh_signkey ssh_rsa = { void *ssh_rsakex_newkey(char *data, int len) { - return rsa2_newkey(data, len); + return rsa2_newkey(&ssh_rsa, data, len); } void ssh_rsakex_freekey(void *key) -- 2.45.2