diff options
Diffstat (limited to 'kex.c')
-rw-r--r-- | kex.c | 86 |
1 files changed, 58 insertions, 28 deletions
@@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.88 2013/01/08 18:49:04 markus Exp $ */ +/* $OpenBSD: kex.c,v 1.89 2013/04/19 01:06:50 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -62,6 +62,55 @@ extern const EVP_MD *evp_ssh_sha256(void); static void kex_kexinit_finish(Kex *); static void kex_choose_conf(Kex *); +struct kexalg { + char *name; + int type; + int ec_nid; + const EVP_MD *(*mdfunc)(void); +}; +static const struct kexalg kexalgs[] = { + { KEX_DH1, KEX_DH_GRP1_SHA1, 0, EVP_sha1 }, + { KEX_DH14, KEX_DH_GRP14_SHA1, 0, EVP_sha1 }, + { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, EVP_sha1 }, +#if OPENSSL_VERSION_NUMBER >= 0x00907000L + { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, EVP_sha256 }, + { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, NID_X9_62_prime256v1, EVP_sha256 }, + { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, EVP_sha384 }, + { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, EVP_sha512 }, +#endif + { NULL, -1, -1, NULL}, +}; + +char * +kex_alg_list(void) +{ + char *ret = NULL; + size_t nlen, rlen = 0; + const struct kexalg *k; + + for (k = kexalgs; k->name != NULL; k++) { + if (ret != NULL) + ret[rlen++] = '\n'; + nlen = strlen(k->name); + ret = xrealloc(ret, 1, rlen + nlen + 2); + memcpy(ret + rlen, k->name, nlen + 1); + rlen += nlen; + } + return ret; +} + +static const struct kexalg * +kex_alg_by_name(const char *name) +{ + const struct kexalg *k; + + for (k = kexalgs; k->name != NULL; k++) { + if (strcmp(k->name, name) == 0) + return k; + } + return NULL; +} + /* Validate KEX method name list */ int kex_names_valid(const char *names) @@ -73,13 +122,7 @@ kex_names_valid(const char *names) s = cp = xstrdup(names); for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { - if (strcmp(p, KEX_DHGEX_SHA256) != 0 && - strcmp(p, KEX_DHGEX_SHA1) != 0 && - strcmp(p, KEX_DH14) != 0 && - strcmp(p, KEX_DH1) != 0 && - (strncmp(p, KEX_ECDH_SHA2_STEM, - sizeof(KEX_ECDH_SHA2_STEM) - 1) != 0 || - kex_ecdh_name_to_nid(p) == -1)) { + if (kex_alg_by_name(p) == NULL) { error("Unsupported KEX algorithm \"%.100s\"", p); xfree(s); return 0; @@ -348,29 +391,16 @@ choose_comp(Comp *comp, char *client, char *server) static void choose_kex(Kex *k, char *client, char *server) { + const struct kexalg *kexalg; + k->name = match_list(client, server, NULL); if (k->name == NULL) fatal("Unable to negotiate a key exchange method"); - if (strcmp(k->name, KEX_DH1) == 0) { - k->kex_type = KEX_DH_GRP1_SHA1; - k->evp_md = EVP_sha1(); - } else if (strcmp(k->name, KEX_DH14) == 0) { - k->kex_type = KEX_DH_GRP14_SHA1; - k->evp_md = EVP_sha1(); - } else if (strcmp(k->name, KEX_DHGEX_SHA1) == 0) { - k->kex_type = KEX_DH_GEX_SHA1; - k->evp_md = EVP_sha1(); -#if OPENSSL_VERSION_NUMBER >= 0x00907000L - } else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) { - k->kex_type = KEX_DH_GEX_SHA256; - k->evp_md = evp_ssh_sha256(); - } else if (strncmp(k->name, KEX_ECDH_SHA2_STEM, - sizeof(KEX_ECDH_SHA2_STEM) - 1) == 0) { - k->kex_type = KEX_ECDH_SHA2; - k->evp_md = kex_ecdh_name_to_evpmd(k->name); -#endif - } else - fatal("bad kex alg %s", k->name); + if ((kexalg = kex_alg_by_name(k->name)) == NULL) + fatal("unsupported kex alg %s", k->name); + k->kex_type = kexalg->type; + k->evp_md = kexalg->mdfunc(); + k->ec_nid = kexalg->ec_nid; } static void |