Mercurial > dropbear
changeset 1675:ae41624c2198
split signkey_type and signature_type for RSA sha1 vs sha256
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 17 May 2020 23:58:31 +0800 |
parents | ba6fc7afe1c5 |
children | d5cdc60db08e |
files | cli-authpubkey.c common-algo.c fuzzer-verify.c rsa.c rsa.h session.h signkey.c signkey.h ssh.h svr-authpubkey.c |
diffstat | 10 files changed, 148 insertions(+), 68 deletions(-) [+] |
line wrap: on
line diff
--- a/cli-authpubkey.c Mon Apr 06 23:18:26 2020 +0800 +++ b/cli-authpubkey.c Sun May 17 23:58:31 2020 +0800 @@ -33,7 +33,7 @@ #include "agentfwd.h" #if DROPBEAR_CLI_PUBKEY_AUTH -static void send_msg_userauth_pubkey(sign_key *key, enum signkey_type sigtype, int realsign); +static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype, int realsign); /* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request. * We use it to remove the key we tried from the list */ @@ -58,7 +58,8 @@ buffer* keybuf = NULL; char* algotype = NULL; unsigned int algolen; - enum signkey_type sigtype, keytype; + enum signkey_type keytype; + enum signature_type sigtype; unsigned int remotelen; TRACE(("enter recv_msg_userauth_pk_ok")) @@ -113,7 +114,7 @@ TRACE(("matching key")) /* XXX TODO: if it's an encrypted key, here we ask for their * password */ - send_msg_userauth_pubkey((sign_key*)iter->item, keytype, 1); + send_msg_userauth_pubkey((sign_key*)iter->item, sigtype, 1); } else { TRACE(("That was whacky. We got told that a key was valid, but it didn't match our list. Sounds like dodgy code on Dropbear's part")) } @@ -121,7 +122,7 @@ TRACE(("leave recv_msg_userauth_pk_ok")) } -static void cli_buf_put_sign(buffer* buf, sign_key *key, enum signkey_type sigtype, +static void cli_buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype, const buffer *data_buf) { #if DROPBEAR_CLI_AGENTFWD // TODO: rsa-sha256 agent @@ -139,14 +140,14 @@ } } -static void send_msg_userauth_pubkey(sign_key *key, enum signkey_type sigtype, int realsign) { +static void send_msg_userauth_pubkey(sign_key *key, enum signature_type sigtype, int realsign) { const char *algoname = NULL; unsigned int algolen; buffer* sigbuf = NULL; enum signkey_type keytype = signkey_type_from_signature(sigtype); - TRACE(("enter send_msg_userauth_pubkey")) + TRACE(("enter send_msg_userauth_pubkey sigtype %d", sigtype)) CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); @@ -183,7 +184,6 @@ /* Returns 1 if a key was tried */ int cli_auth_pubkey() { - TRACE(("enter cli_auth_pubkey")) #if DROPBEAR_CLI_AGENTFWD @@ -194,16 +194,26 @@ } #endif + /* TODO iterate through privkeys to skip ones not in server-sig-algs */ + + /* TODO: testing */ +#if DROPBEAR_RSA_SHA256 + cli_ses.preferred_rsa_sigtype = DROPBEAR_SIGNATURE_RSA_SHA256; +#elif DROPBEAR_RSA_SHA1 + cli_ses.preferred_rsa_sigtype = DROPBEAR_SIGNATURE_RSA_SHA1; +#endif + if (cli_opts.privkeys->first) { sign_key * key = (sign_key*)cli_opts.privkeys->first->item; - enum signkey_type sigtype = key->type; - /* Send a trial request */ -#if DROPBEAR_RSA && DROPBEAR_RSA_SHA256 - // TODO: use ext-info to choose rsa kind - if (sigtype == DROPBEAR_SIGNKEY_RSA) { - sigtype = DROPBEAR_SIGNKEY_RSA_SHA256; + /* Determine the signature type to use */ + enum signature_type sigtype = (enum signature_type)key->type; +#if DROPBEAR_RSA + if (key->type == DROPBEAR_SIGNKEY_RSA) { + sigtype = cli_ses.preferred_rsa_sigtype; } #endif + + /* Send a trial request */ send_msg_userauth_pubkey(key, sigtype, 0); cli_ses.lastprivkey = key; TRACE(("leave cli_auth_pubkey-success"))
--- a/common-algo.c Mon Apr 06 23:18:26 2020 +0800 +++ b/common-algo.c Sun May 17 23:58:31 2020 +0800 @@ -223,29 +223,29 @@ algo_type sshhostkey[] = { #if DROPBEAR_ED25519 - {"ssh-ed25519", DROPBEAR_SIGNKEY_ED25519, NULL, 1, NULL}, + {"ssh-ed25519", DROPBEAR_SIGNATURE_ED25519, NULL, 1, NULL}, #endif #if DROPBEAR_ECDSA #if DROPBEAR_ECC_256 - {"ecdsa-sha2-nistp256", DROPBEAR_SIGNKEY_ECDSA_NISTP256, NULL, 1, NULL}, + {"ecdsa-sha2-nistp256", DROPBEAR_SIGNATURE_ECDSA_NISTP256, NULL, 1, NULL}, #endif #if DROPBEAR_ECC_384 - {"ecdsa-sha2-nistp384", DROPBEAR_SIGNKEY_ECDSA_NISTP384, NULL, 1, NULL}, + {"ecdsa-sha2-nistp384", DROPBEAR_SIGNATURE_ECDSA_NISTP384, NULL, 1, NULL}, #endif #if DROPBEAR_ECC_521 - {"ecdsa-sha2-nistp521", DROPBEAR_SIGNKEY_ECDSA_NISTP521, NULL, 1, NULL}, + {"ecdsa-sha2-nistp521", DROPBEAR_SIGNATURE_ECDSA_NISTP521, NULL, 1, NULL}, #endif #endif #if DROPBEAR_RSA #if DROPBEAR_RSA_SHA256 - {"rsa-sha2-256", DROPBEAR_SIGNKEY_RSA_SHA256, NULL, 1, NULL}, + {"rsa-sha2-256", DROPBEAR_SIGNATURE_RSA_SHA256, NULL, 1, NULL}, #endif #if DROPBEAR_RSA_SHA1 - {"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1, NULL}, + {"ssh-rsa", DROPBEAR_SIGNATURE_RSA_SHA1, NULL, 1, NULL}, #endif #endif #if DROPBEAR_DSS - {"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1, NULL}, + {"ssh-dss", DROPBEAR_SIGNATURE_DSS, NULL, 1, NULL}, #endif {NULL, 0, NULL, 0, NULL} }; @@ -263,8 +263,6 @@ static const struct dropbear_kex kex_dh_group16_sha512 = {DROPBEAR_KEX_NORMAL_DH, dh_p_16, DH_P_16_LEN, NULL, &sha512_desc }; #endif -/* These can't be const since dropbear_ecc_fill_dp() fills out - ecc_curve at runtime */ #if DROPBEAR_ECDH #if DROPBEAR_ECC_256 static const struct dropbear_kex kex_ecdh_nistp256 = {DROPBEAR_KEX_ECDH, NULL, 0, &ecc_curve_nistp256, &sha256_desc };
--- a/fuzzer-verify.c Mon Apr 06 23:18:26 2020 +0800 +++ b/fuzzer-verify.c Sun May 17 23:58:31 2020 +0800 @@ -27,15 +27,25 @@ if (setjmp(fuzz.jmp) == 0) { sign_key *key = new_sign_key(); - enum signkey_type type = DROPBEAR_SIGNKEY_ANY; - if (buf_get_pub_key(fuzz.input, key, &type) == DROPBEAR_SUCCESS) { - if (buf_verify(fuzz.input, key, verifydata) == DROPBEAR_SUCCESS) { + enum signkey_type keytype = DROPBEAR_SIGNKEY_ANY; + if (buf_get_pub_key(fuzz.input, key, &keytype) == DROPBEAR_SUCCESS) { + enum signature_type sigtype = (enum signature_type)keytype; + if (keytype == DROPBEAR_SIGNKEY_RSA) { + /* Flip a coin to decide rsa signature type */ + int flag = buf_getbyte(fuzz_input); + if (flag & 0x01) { + sigtype = DROPBEAR_SIGNATURE_RSA_SHA256; + } else { + sigtype = DROPBEAR_SIGNATURE_RSA_SHA1; + } + } + if (buf_verify(fuzz.input, key, sigtype, verifydata) == DROPBEAR_SUCCESS) { /* The fuzzer is capable of generating keys with a signature to match. We don't want false positives if the key is bogus, since a client/server wouldn't be trusting a bogus key anyway */ int boguskey = 0; - if (type == DROPBEAR_SIGNKEY_DSS) { + if (keytype == DROPBEAR_SIGNKEY_DSS) { /* So far have seen dss keys with bad p/q/g domain parameters */ int pprime, qprime, trials; trials = mp_prime_rabin_miller_trials(mp_count_bits(key->dsskey->p));
--- a/rsa.c Mon Apr 06 23:18:26 2020 +0800 +++ b/rsa.c Sun May 17 23:58:31 2020 +0800 @@ -44,7 +44,7 @@ #endif static void rsa_pad_em(const dropbear_rsa_key * key, - const buffer *data_buf, mp_int * rsa_em, enum signkey_type sigtype); + const buffer *data_buf, mp_int * rsa_em, enum signature_type sigtype); /* Load a public rsa key from a buffer, initialising the values. * The key will have the same format as buf_put_rsa_key. @@ -197,7 +197,7 @@ /* Verify a signature in buf, made on data by the key given. * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ int buf_rsa_verify(buffer * buf, const dropbear_rsa_key *key, - enum signkey_type sigtype, const buffer *data_buf) { + enum signature_type sigtype, const buffer *data_buf) { unsigned int slen; DEF_MP_INT(rsa_s); DEF_MP_INT(rsa_mdash); @@ -253,7 +253,7 @@ /* Sign the data presented with key, writing the signature contents * to the buffer */ void buf_put_rsa_sign(buffer* buf, const dropbear_rsa_key *key, - enum signkey_type sigtype, const buffer *data_buf) { + enum signature_type sigtype, const buffer *data_buf) { const char *name = NULL; unsigned int nsize, ssize, namelen = 0; unsigned int i; @@ -352,7 +352,7 @@ /* Creates the message value as expected by PKCS, see rfc8017 section 9.2 */ static void rsa_pad_em(const dropbear_rsa_key * key, - const buffer *data_buf, mp_int * rsa_em, enum signkey_type sigtype) { + const buffer *data_buf, mp_int * rsa_em, enum signature_type sigtype) { /* EM = 0x00 || 0x01 || PS || 0x00 || T PS is padding of 0xff to make EM the size of key->n @@ -380,14 +380,14 @@ switch (sigtype) { #if DROPBEAR_RSA_SHA1 - case DROPBEAR_SIGNKEY_RSA: + case DROPBEAR_SIGNATURE_RSA_SHA1: Tlen = sizeof(T_sha1); T = T_sha1; hash_desc = &sha1_desc; break; #endif #if DROPBEAR_RSA_SHA256 - case DROPBEAR_SIGNKEY_RSA_SHA256: + case DROPBEAR_SIGNATURE_RSA_SHA256: Tlen = sizeof(T_sha256); T = T_sha256; hash_desc = &sha256_desc;
--- a/rsa.h Mon Apr 06 23:18:26 2020 +0800 +++ b/rsa.h Sun May 17 23:58:31 2020 +0800 @@ -43,10 +43,10 @@ } dropbear_rsa_key; void buf_put_rsa_sign(buffer* buf, const dropbear_rsa_key *key, - enum signkey_type sigtype, const buffer *data_buf); + enum signature_type sigtype, const buffer *data_buf); #if DROPBEAR_SIGNKEY_VERIFY int buf_rsa_verify(buffer * buf, const dropbear_rsa_key *key, - enum signkey_type sigtype, const buffer *data_buf); + enum signature_type sigtype, const buffer *data_buf); #endif int buf_get_rsa_pub_key(buffer* buf, dropbear_rsa_key *key); int buf_get_rsa_priv_key(buffer* buf, dropbear_rsa_key *key);
--- a/session.h Mon Apr 06 23:18:26 2020 +0800 +++ b/session.h Sun May 17 23:58:31 2020 +0800 @@ -92,8 +92,8 @@ struct key_context_directional trans; const struct dropbear_kex *algo_kex; - int algo_hostkey; /* server key type */ - int algo_signature; /* server signature type */ + enum signkey_type algo_hostkey; /* server key type */ + enum signature_type algo_signature; /* server signature type */ int allow_compress; /* whether compression has started (useful in [email protected] delayed compression case) */ @@ -313,6 +313,14 @@ #endif sign_key *lastprivkey; + enum signature_type server_sig_algs[DROPBEAR_SIGNKEY_NUM_NAMED+1]; + int server_sig_algs_count; +#if DROPBEAR_RSA + /* Set to DROPBEAR_SIGNATURE_RSA_SHA256 or DROPBEAR_SIGNATURE_RSA_SHA1 + if depending which the server accepts */ + enum signature_type preferred_rsa_sigtype; +#endif + int retval; /* What the command exit status was - we emulate it */ #if 0 TODO
--- a/signkey.c Mon Apr 06 23:18:26 2020 +0800 +++ b/signkey.c Sun May 17 23:58:31 2020 +0800 @@ -111,34 +111,52 @@ /* Special case for rsa-sha2-256. This could be generalised if more signature names are added that aren't 1-1 with public key names */ -const char* signature_name_from_type(enum signkey_type type, unsigned int *namelen) { +const char* signature_name_from_type(enum signature_type type, unsigned int *namelen) { #if DROPBEAR_RSA_SHA256 - if (type == DROPBEAR_SIGNKEY_RSA_SHA256) { - *namelen = strlen(SSH_SIGNKEY_RSA_SHA256); - return SSH_SIGNKEY_RSA_SHA256; + if (type == DROPBEAR_SIGNATURE_RSA_SHA256) { + *namelen = strlen(SSH_SIGNATURE_RSA_SHA256); + return SSH_SIGNATURE_RSA_SHA256; } #endif - return signkey_name_from_type(type, namelen); +#if DROPBEAR_RSA_SHA1 + if (type == DROPBEAR_SIGNATURE_RSA_SHA1) { + *namelen = strlen(SSH_SIGNKEY_RSA); + return SSH_SIGNKEY_RSA; + } +#endif + return signkey_name_from_type((enum signkey_type)type, namelen); } -enum signkey_type signature_type_from_name(const char* name, unsigned int namelen) { +/* Returns DROPBEAR_SIGNATURE_NONE if none match */ +enum signature_type signature_type_from_name(const char* name, unsigned int namelen) { #if DROPBEAR_RSA_SHA256 - if (namelen == strlen(SSH_SIGNKEY_RSA_SHA256) - && memcmp(name, SSH_SIGNKEY_RSA_SHA256, namelen) == 0) { - return DROPBEAR_SIGNKEY_RSA_SHA256; + if (namelen == strlen(SSH_SIGNATURE_RSA_SHA256) + && memcmp(name, SSH_SIGNATURE_RSA_SHA256, namelen) == 0) { + return DROPBEAR_SIGNATURE_RSA_SHA256; } #endif - return signkey_type_from_name(name, namelen); +#if DROPBEAR_RSA_SHA256 + if (namelen == strlen(SSH_SIGNKEY_RSA) + && memcmp(name, SSH_SIGNKEY_RSA, namelen) == 0) { + return DROPBEAR_SIGNATURE_RSA_SHA1; + } +#endif + return (enum signature_type)signkey_type_from_name(name, namelen); } -enum signkey_type signkey_type_from_signature(enum signkey_type sigtype) { +enum signkey_type signkey_type_from_signature(enum signature_type sigtype) { #if DROPBEAR_RSA_SHA256 - if (sigtype == DROPBEAR_SIGNKEY_RSA_SHA256) { + if (sigtype == DROPBEAR_SIGNATURE_RSA_SHA256) { + return DROPBEAR_SIGNKEY_RSA; + } +#endif +#if DROPBEAR_RSA_SHA1 + if (sigtype == DROPBEAR_SIGNATURE_RSA_SHA1) { return DROPBEAR_SIGNKEY_RSA; } #endif assert(sigtype < DROPBEAR_SIGNKEY_NUM_NAMED); - return sigtype; + return (enum signkey_type)sigtype; } /* Returns a pointer to the key part specific to "type". @@ -562,11 +580,20 @@ #endif } -void buf_put_sign(buffer* buf, sign_key *key, enum signkey_type sigtype, +void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype, const buffer *data_buf) { buffer *sigblob = buf_new(MAX_PUBKEY_SIZE); enum signkey_type keytype = signkey_type_from_signature(sigtype); +#if DEBUG_TRACE + { + int namelen; + const char* signame = signature_name_from_type(sigtype, &namelen); + TRACE(("buf_put_sign type %d %s", sigtype, signame)); + } +#endif + + #if DROPBEAR_DSS if (keytype == DROPBEAR_SIGNKEY_DSS) { buf_put_dss_sign(sigblob, key->dsskey, data_buf); @@ -603,11 +630,12 @@ * If FAILURE is returned, the position of * buf is undefined. If SUCCESS is returned, buf will be positioned after the * signature blob */ -int buf_verify(buffer * buf, sign_key *key, enum signkey_type expect_sigtype, const buffer *data_buf) { +int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf) { char *type_name = NULL; unsigned int type_name_len = 0; - enum signkey_type sigtype, keytype; + enum signature_type sigtype; + enum signkey_type keytype; TRACE(("enter buf_verify")) @@ -616,8 +644,7 @@ sigtype = signature_type_from_name(type_name, type_name_len); m_free(type_name); - if (expect_sigtype != DROPBEAR_SIGNKEY_ANY - && expect_sigtype != sigtype) { + if (expect_sigtype != sigtype) { dropbear_exit("Non-matching signing type"); }
--- a/signkey.h Mon Apr 06 23:18:26 2020 +0800 +++ b/signkey.h Sun May 17 23:58:31 2020 +0800 @@ -32,6 +32,7 @@ struct dropbear_RSA_Key; struct dropbear_ED25519_Key; +/* Must match with signature_type below */ enum signkey_type { #if DROPBEAR_RSA DROPBEAR_SIGNKEY_RSA, @@ -49,13 +50,32 @@ #endif DROPBEAR_SIGNKEY_NUM_NAMED, DROPBEAR_SIGNKEY_ECDSA_KEYGEN = 70, /* just "ecdsa" for keygen */ -#if DROPBEAR_RSA_SHA256 - DROPBEAR_SIGNKEY_RSA_SHA256, /* rsa-sha2-256 signature. has a ssh-rsa key */ -#endif DROPBEAR_SIGNKEY_ANY = 80, DROPBEAR_SIGNKEY_NONE = 90, }; +/* Must match with signkey_type above, apart from rsa */ +enum signature_type { +#if DROPBEAR_DSS + DROPBEAR_SIGNATURE_DSS = DROPBEAR_SIGNKEY_DSS, +#endif +#if DROPBEAR_ECDSA + DROPBEAR_SIGNATURE_ECDSA_NISTP256 = DROPBEAR_SIGNKEY_ECDSA_NISTP256, + DROPBEAR_SIGNATURE_ECDSA_NISTP384 = DROPBEAR_SIGNKEY_ECDSA_NISTP384, + DROPBEAR_SIGNATURE_ECDSA_NISTP521 = DROPBEAR_SIGNKEY_ECDSA_NISTP521, +#endif /* DROPBEAR_ECDSA */ +#if DROPBEAR_ED25519 + DROPBEAR_SIGNATURE_ED25519 = DROPBEAR_SIGNKEY_ED25519, +#endif +#if DROPBEAR_RSA_SHA1 + DROPBEAR_SIGNATURE_RSA_SHA1 = 100, /* ssh-rsa signature (sha1) */ +#endif +#if DROPBEAR_RSA_SHA256 + DROPBEAR_SIGNATURE_RSA_SHA256 = 101, /* rsa-sha2-256 signature. has a ssh-rsa key */ +#endif + DROPBEAR_SIGNATURE_NONE = DROPBEAR_SIGNKEY_NONE, +}; + /* Sources for signing keys */ typedef enum { @@ -97,17 +117,17 @@ sign_key * new_sign_key(void); const char* signkey_name_from_type(enum signkey_type type, unsigned int *namelen); enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen); -const char* signature_name_from_type(enum signkey_type type, unsigned int *namelen); -enum signkey_type signature_type_from_name(const char* name, unsigned int namelen); -enum signkey_type signkey_type_from_signature(enum signkey_type sigtype); +const char* signature_name_from_type(enum signature_type type, unsigned int *namelen); +enum signature_type signature_type_from_name(const char* name, unsigned int namelen); +enum signkey_type signkey_type_from_signature(enum signature_type sigtype); int buf_get_pub_key(buffer *buf, sign_key *key, enum signkey_type *type); int buf_get_priv_key(buffer* buf, sign_key *key, enum signkey_type *type); void buf_put_pub_key(buffer* buf, sign_key *key, enum signkey_type type); void buf_put_priv_key(buffer* buf, sign_key *key, enum signkey_type type); void sign_key_free(sign_key *key); -void buf_put_sign(buffer* buf, sign_key *key, enum signkey_type sigtype, const buffer *data_buf); +void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype, const buffer *data_buf); #if DROPBEAR_SIGNKEY_VERIFY -int buf_verify(buffer * buf, sign_key *key, enum signkey_type type, const buffer *data_buf); +int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf); char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloblen); #endif int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen,
--- a/ssh.h Mon Apr 06 23:18:26 2020 +0800 +++ b/ssh.h Sun May 17 23:58:31 2020 +0800 @@ -108,7 +108,7 @@ #define SSH_SIGNKEY_ED25519 "ssh-ed25519" #define SSH_SIGNKEY_ED25519_LEN 11 /* signature type */ -#define SSH_SIGNKEY_RSA_SHA256 "rsa-sha2-256" +#define SSH_SIGNATURE_RSA_SHA256 "rsa-sha2-256" /* Agent commands. These aren't part of the spec, and are defined * only on the openssh implementation. */
--- a/svr-authpubkey.c Mon Apr 06 23:18:26 2020 +0800 +++ b/svr-authpubkey.c Sun May 17 23:58:31 2020 +0800 @@ -92,7 +92,8 @@ buffer * signbuf = NULL; sign_key * key = NULL; char* fp = NULL; - enum signkey_type sigtype, keytype; + enum signature_type sigtype; + enum signkey_type keytype; int auth_failure = 1; TRACE(("enter pubkeyauth")) @@ -102,10 +103,6 @@ testkey = (buf_getbool(ses.payload) == 0); sigalgo = buf_getstring(ses.payload, &sigalgolen); - sigtype = signature_type_from_name(sigalgo, sigalgolen); - keytype = signkey_type_from_signature(sigtype); - keyalgo = signkey_name_from_type(keytype, &keyalgolen); - keybloblen = buf_getint(ses.payload); keyblob = buf_getptr(ses.payload, keybloblen); @@ -117,6 +114,16 @@ send_msg_userauth_failure(0, 0); goto out; } + + sigtype = signature_type_from_name(sigalgo, sigalgolen); + if (sigtype == DROPBEAR_SIGNATURE_NONE) { + send_msg_userauth_failure(0, 0); + goto out; + } + + keytype = signkey_type_from_signature(sigtype); + keyalgo = signkey_name_from_type(keytype, &keyalgolen); + #if DROPBEAR_PLUGIN if (svr_ses.plugin_instance != NULL) { char *options_buf;