From 87fee462c0eeac9e1199bfb85dd7a3e93b3e1676 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Sat, 25 May 2013 00:54:19 +0800 Subject: have separate ecdsa keys for each size fix crash from the mp_alloc_init_multi change in RSA --- dropbearkey.c | 7 +++-- keyimport.c | 4 +-- rsa.c | 2 +- signkey.c | 97 +++++++++++++++++++++++++++++++++++++++++++---------------- signkey.h | 16 ++++++---- svr-runopts.c | 62 +++++++++++++++++++------------------- 6 files changed, 120 insertions(+), 68 deletions(-) diff --git a/dropbearkey.c b/dropbearkey.c index cf7048e..eecfbcc 100644 --- a/dropbearkey.c +++ b/dropbearkey.c @@ -266,8 +266,11 @@ int main(int argc, char ** argv) { #endif #ifdef DROPBEAR_ECDSA case DROPBEAR_SIGNKEY_ECDSA_KEYGEN: - key->ecckey = gen_ecdsa_priv_key(bits); - keytype = ecdsa_signkey_type(key->ecckey); + { + ecc_key *ecckey = gen_ecdsa_priv_key(bits); + keytype = ecdsa_signkey_type(ecckey); + *signkey_ecc_key_ptr(key, keytype) = ecckey; + } break; #endif default: diff --git a/keyimport.c b/keyimport.c index d0469de..05bf800 100644 --- a/keyimport.c +++ b/keyimport.c @@ -680,7 +680,7 @@ static sign_key *openssh_read(const char *filename, char *passphrase) int private_key_len = 0; unsigned char* public_key_bytes = NULL; int public_key_len = 0; - ecc_key *ecc; + ecc_key *ecc = NULL; const struct dropbear_ecc_curve *curve = NULL; // See SEC1 v2, Appendix C.4 @@ -774,7 +774,7 @@ static sign_key *openssh_read(const char *filename, char *passphrase) goto error; } - retkey->ecckey = ecc; + *signkey_ecc_key_ptr(retkey, retkey->type) = ecc; } #endif // DROPBEAR_ECDSA diff --git a/rsa.c b/rsa.c index 92adee4..e2abab1 100644 --- a/rsa.c +++ b/rsa.c @@ -96,7 +96,7 @@ int buf_get_rsa_priv_key(buffer* buf, dropbear_rsa_key *key) { key->p = NULL; key->q = NULL; - m_mp_alloc_init_multi(&key->d); + m_mp_alloc_init_multi(&key->d, NULL); if (buf_getmpint(buf, key->d) == DROPBEAR_FAILURE) { TRACE(("leave buf_get_rsa_priv_key: d: ret == DROPBEAR_FAILURE")) goto out; diff --git a/signkey.c b/signkey.c index 194c145..65c22c2 100644 --- a/signkey.c +++ b/signkey.c @@ -103,6 +103,22 @@ enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen) return DROPBEAR_SIGNKEY_NONE; } +#ifdef DROPBEAR_ECDSA +ecc_key ** +signkey_ecc_key_ptr(sign_key *key, enum signkey_type ecc_type) { + switch (ecc_type) { + case DROPBEAR_SIGNKEY_ECDSA_NISTP256: + return &key->ecckey256; + case DROPBEAR_SIGNKEY_ECDSA_NISTP384: + return &key->ecckey384; + case DROPBEAR_SIGNKEY_ECDSA_NISTP521: + return &key->ecckey521; + default: + return NULL; + } +} +#endif + /* returns DROPBEAR_SUCCESS on success, DROPBEAR_FAILURE on fail. * type should be set by the caller to specify the type to read, and * on return is set to the type read (useful when type = _ANY) */ @@ -152,13 +168,17 @@ int buf_get_pub_key(buffer *buf, sign_key *key, int *type) { } #endif #ifdef DROPBEAR_ECDSA - if (IS_ECDSA_KEY(keytype)) { - if (key->ecckey) { - ecc_free(key->ecckey); - } - key->ecckey = buf_get_ecdsa_pub_key(buf); - if (key->ecckey) { - ret = DROPBEAR_SUCCESS; + { + ecc_key **eck = signkey_ecc_key_ptr(key, keytype); + if (eck) { + if (*eck) { + ecc_free(*eck); + *eck = NULL; + } + *eck = buf_get_ecdsa_pub_key(buf); + if (*eck) { + ret = DROPBEAR_SUCCESS; + } } } #endif @@ -216,13 +236,17 @@ int buf_get_priv_key(buffer *buf, sign_key *key, int *type) { } #endif #ifdef DROPBEAR_ECDSA - if (IS_ECDSA_KEY(keytype)) { - if (key->ecckey) { - ecc_free(key->ecckey); - } - key->ecckey = buf_get_ecdsa_priv_key(buf); - if (key->ecckey) { - ret = DROPBEAR_SUCCESS; + { + ecc_key **eck = signkey_ecc_key_ptr(key, keytype); + if (eck) { + if (*eck) { + ecc_free(*eck); + *eck = NULL; + } + *eck = buf_get_ecdsa_priv_key(buf); + if (*eck) { + ret = DROPBEAR_SUCCESS; + } } } #endif @@ -252,8 +276,11 @@ void buf_put_pub_key(buffer* buf, sign_key *key, int type) { } #endif #ifdef DROPBEAR_ECDSA - if (IS_ECDSA_KEY(type)) { - buf_put_ecdsa_pub_key(pubkeys, key->ecckey); + { + ecc_key **eck = signkey_ecc_key_ptr(key, type); + if (eck) { + buf_put_ecdsa_pub_key(pubkeys, *eck); + } } #endif if (pubkeys->len == 0) { @@ -286,9 +313,13 @@ void buf_put_priv_key(buffer* buf, sign_key *key, int type) { } #endif #ifdef DROPBEAR_ECDSA - if (IS_ECDSA_KEY(type)) { - buf_put_ecdsa_priv_key(buf, key->ecckey); - return; + { + ecc_key **eck = signkey_ecc_key_ptr(key, type); + if (eck) { + buf_put_ecdsa_priv_key(buf, *eck); + TRACE(("leave buf_put_priv_key: ecdsa done")) + return; + } } #endif dropbear_exit("Bad key types in put pub key"); @@ -307,9 +338,17 @@ void sign_key_free(sign_key *key) { key->rsakey = NULL; #endif #ifdef DROPBEAR_ECDSA - if (key->ecckey) { - ecc_free(key->ecckey); - key->ecckey = NULL; + if (key->ecckey256) { + ecc_free(key->ecckey256); + key->ecckey256 = NULL; + } + if (key->ecckey384) { + ecc_free(key->ecckey384); + key->ecckey384 = NULL; + } + if (key->ecckey521) { + ecc_free(key->ecckey521); + key->ecckey521 = NULL; } #endif @@ -429,8 +468,11 @@ void buf_put_sign(buffer* buf, sign_key *key, int type, } #endif #ifdef DROPBEAR_ECDSA - if (IS_ECDSA_KEY(type)) { - buf_put_ecdsa_sign(sigblob, key->ecckey, data_buf); + { + ecc_key **eck = signkey_ecc_key_ptr(key, type); + if (eck) { + buf_put_ecdsa_sign(sigblob, *eck, data_buf); + } } #endif if (sigblob->len == 0) { @@ -477,8 +519,11 @@ int buf_verify(buffer * buf, sign_key *key, buffer *data_buf) { } #endif #ifdef DROPBEAR_ECDSA - if (IS_ECDSA_KEY(type)) { - return buf_ecdsa_verify(buf, key->ecckey, data_buf); + { + ecc_key **eck = signkey_ecc_key_ptr(key, type); + if (eck) { + return buf_ecdsa_verify(buf, *eck, data_buf); + } } #endif diff --git a/signkey.h b/signkey.h index 61095c7..6400d47 100644 --- a/signkey.h +++ b/signkey.h @@ -68,7 +68,15 @@ struct SIGN_key { dropbear_rsa_key * rsakey; #endif #ifdef DROPBEAR_ECDSA - ecc_key * ecckey; +#ifdef DROPBEAR_ECC_256 + ecc_key * ecckey256; +#endif +#ifdef DROPBEAR_ECC_384 + ecc_key * ecckey384; +#endif +#ifdef DROPBEAR_ECC_521 + ecc_key * ecckey521; +#endif #endif }; @@ -92,11 +100,7 @@ int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen, buffer * line, char ** fingerprint); #ifdef DROPBEAR_ECDSA -#define IS_ECDSA_KEY(type) \ - ((type) == DROPBEAR_SIGNKEY_ECDSA_NISTP256 \ - || (type) == DROPBEAR_SIGNKEY_ECDSA_NISTP384 \ - || (type) == DROPBEAR_SIGNKEY_ECDSA_NISTP521 \ - || (type) == DROPBEAR_SIGNKEY_ECDSA_KEYGEN) +ecc_key ** signkey_ecc_key_ptr(sign_key *key, enum signkey_type ecc_type); #endif #endif /* _SIGNKEY_H_ */ diff --git a/svr-runopts.c b/svr-runopts.c index 07da95c..2db88c2 100644 --- a/svr-runopts.c +++ b/svr-runopts.c @@ -375,6 +375,18 @@ static void disablekey(int type) { } } +static void loadhostkey_helper(const char *name, void** src, void** dst, int fatal_duplicate) { + if (*dst) { + if (fatal_duplicate) { + dropbear_exit("Only one %s key can be specified", name); + } + } else { + *dst = *src; + *src = NULL; + } + +} + /* Must be called after syslog/etc is working */ static void loadhostkey(const char *keyfile, int fatal_duplicate) { sign_key * read_key = new_sign_key(); @@ -385,42 +397,33 @@ static void loadhostkey(const char *keyfile, int fatal_duplicate) { #ifdef DROPBEAR_RSA if (type == DROPBEAR_SIGNKEY_RSA) { - if (svr_opts.hostkey->rsakey) { - if (fatal_duplicate) { - dropbear_exit("Only one RSA key can be specified"); - } - } else { - svr_opts.hostkey->rsakey = read_key->rsakey; - read_key->rsakey = NULL; - } + loadhostkey_helper("RSA", &read_key->rsakey, &svr_opts.hostkey->rsakey, fatal_duplicate); } #endif #ifdef DROPBEAR_DSS if (type == DROPBEAR_SIGNKEY_DSS) { - if (svr_opts.hostkey->dsskey) { - if (fatal_duplicate) { - dropbear_exit("Only one DSS key can be specified"); - } - } else { - svr_opts.hostkey->dsskey = read_key->dsskey; - read_key->dsskey = NULL; - } + loadhostkey_helper("DSS", &read_key->dsskey, &svr_opts.hostkey->dsskey, fatal_duplicate); } #endif #ifdef DROPBEAR_ECDSA - if (IS_ECDSA_KEY(type)) { - if (svr_opts.hostkey->ecckey) { - if (fatal_duplicate) { - dropbear_exit("Only one ECDSA key can be specified"); - } - } else { - svr_opts.hostkey->ecckey = read_key->ecckey; - read_key->ecckey = NULL; - } +#ifdef DROPBEAR_ECC_256 + if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP256) { + loadhostkey_helper("ECDSA256", &read_key->ecckey256, &svr_opts.hostkey->ecckey256, fatal_duplicate); + } +#endif +#ifdef DROPBEAR_ECC_384 + if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP384) { + loadhostkey_helper("ECDSA384", &read_key->ecckey384, &svr_opts.hostkey->ecckey384, fatal_duplicate); + } +#endif +#ifdef DROPBEAR_ECC_521 + if (type == DROPBEAR_SIGNKEY_ECDSA_NISTP521) { + loadhostkey_helper("ECDSA521", &read_key->ecckey521, &svr_opts.hostkey->ecckey521, fatal_duplicate); } #endif +#endif // DROPBEAR_ECDSA sign_key_free(read_key); TRACE(("leave loadhostkey")) } @@ -468,20 +471,17 @@ void load_all_hostkeys() { #endif #ifdef DROPBEAR_ECDSA #ifdef DROPBEAR_ECC_256 - if (!svr_opts.hostkey->ecckey - || ecdsa_signkey_type(svr_opts.hostkey->ecckey) != DROPBEAR_SIGNKEY_ECDSA_NISTP256) { + if (!svr_opts.hostkey->ecckey256) { disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP256); } #endif #ifdef DROPBEAR_ECC_384 - if (!svr_opts.hostkey->ecckey - || ecdsa_signkey_type(svr_opts.hostkey->ecckey) != DROPBEAR_SIGNKEY_ECDSA_NISTP384) { + if (!svr_opts.hostkey->ecckey384) { disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP384); } #endif #ifdef DROPBEAR_ECC_521 - if (!svr_opts.hostkey->ecckey - || ecdsa_signkey_type(svr_opts.hostkey->ecckey) != DROPBEAR_SIGNKEY_ECDSA_NISTP521) { + if (!svr_opts.hostkey->ecckey521) { disablekey(DROPBEAR_SIGNKEY_ECDSA_NISTP521); } #endif -- cgit v1.2.1