summaryrefslogtreecommitdiffstats
path: root/kex.c
diff options
context:
space:
mode:
Diffstat (limited to 'kex.c')
-rw-r--r--kex.c104
1 files changed, 68 insertions, 36 deletions
diff --git a/kex.c b/kex.c
index 57a79dd..54bd1a4 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.c,v 1.88 2013/01/08 18:49:04 markus Exp $ */
+/* $OpenBSD: kex.c,v 1.91 2013/05/17 00:13:13 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
@@ -62,6 +62,57 @@ 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 },
+#ifdef HAVE_EVP_SHA256
+ { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, EVP_sha256 },
+#endif
+#ifdef OPENSSL_HAS_ECC
+ { 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,20 +124,14 @@ 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);
+ free(s);
return 0;
}
}
debug3("kex names ok: [%s]", names);
- xfree(s);
+ free(s);
return 1;
}
@@ -146,8 +191,8 @@ kex_prop_free(char **proposal)
u_int i;
for (i = 0; i < PROPOSAL_MAX; i++)
- xfree(proposal[i]);
- xfree(proposal);
+ free(proposal[i]);
+ free(proposal);
}
/* ARGSUSED */
@@ -184,7 +229,7 @@ kex_finish(Kex *kex)
buffer_clear(&kex->peer);
/* buffer_clear(&kex->my); */
kex->flags &= ~KEX_INIT_SENT;
- xfree(kex->name);
+ free(kex->name);
kex->name = NULL;
}
@@ -241,7 +286,7 @@ kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
for (i = 0; i < KEX_COOKIE_LEN; i++)
packet_get_char();
for (i = 0; i < PROPOSAL_MAX; i++)
- xfree(packet_get_string(NULL));
+ free(packet_get_string(NULL));
/*
* XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
* KEX method has the server move first, but a server might be using
@@ -348,29 +393,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
@@ -382,7 +414,7 @@ choose_hostkeyalg(Kex *k, char *client, char *server)
k->hostkey_type = key_type_from_name(hostkeyalg);
if (k->hostkey_type == KEY_UNSPEC)
fatal("bad hostkey alg '%s'", hostkeyalg);
- xfree(hostkeyalg);
+ free(hostkeyalg);
}
static int
@@ -436,7 +468,7 @@ kex_choose_conf(Kex *kex)
roaming = match_list(KEX_RESUME, peer[PROPOSAL_KEX_ALGS], NULL);
if (roaming) {
kex->roaming = 1;
- xfree(roaming);
+ free(roaming);
}
}
OpenPOWER on IntegriCloud