summaryrefslogtreecommitdiff
path: root/kex.c
diff options
context:
space:
mode:
Diffstat (limited to 'kex.c')
-rw-r--r--kex.c130
1 files changed, 80 insertions, 50 deletions
diff --git a/kex.c b/kex.c
index f9e7a9c09..1ec278245 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.c,v 1.88 2013/01/08 18:49:04 markus Exp $ */ 1/* $OpenBSD: kex.c,v 1.91 2013/05/17 00:13:13 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -66,6 +66,69 @@ extern const EVP_MD *evp_ssh_sha256(void);
66static void kex_kexinit_finish(Kex *); 66static void kex_kexinit_finish(Kex *);
67static void kex_choose_conf(Kex *); 67static void kex_choose_conf(Kex *);
68 68
69struct kexalg {
70 char *name;
71 int type;
72 int ec_nid;
73 const EVP_MD *(*mdfunc)(void);
74};
75static const struct kexalg kexalgs[] = {
76 { KEX_DH1, KEX_DH_GRP1_SHA1, 0, EVP_sha1 },
77 { KEX_DH14, KEX_DH_GRP14_SHA1, 0, EVP_sha1 },
78 { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, EVP_sha1 },
79#ifdef HAVE_EVP_SHA256
80 { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, EVP_sha256 },
81#endif
82#ifdef OPENSSL_HAS_ECC
83 { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, NID_X9_62_prime256v1, EVP_sha256 },
84 { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, EVP_sha384 },
85 { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, EVP_sha512 },
86#endif
87 { NULL, -1, -1, NULL},
88};
89static const struct kexalg kexalg_prefixes[] = {
90#ifdef GSSAPI
91 { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, EVP_sha1 },
92 { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, EVP_sha1 },
93 { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, EVP_sha1 },
94#endif
95 { NULL, -1, -1, NULL },
96};
97
98char *
99kex_alg_list(void)
100{
101 char *ret = NULL;
102 size_t nlen, rlen = 0;
103 const struct kexalg *k;
104
105 for (k = kexalgs; k->name != NULL; k++) {
106 if (ret != NULL)
107 ret[rlen++] = '\n';
108 nlen = strlen(k->name);
109 ret = xrealloc(ret, 1, rlen + nlen + 2);
110 memcpy(ret + rlen, k->name, nlen + 1);
111 rlen += nlen;
112 }
113 return ret;
114}
115
116static const struct kexalg *
117kex_alg_by_name(const char *name)
118{
119 const struct kexalg *k;
120
121 for (k = kexalgs; k->name != NULL; k++) {
122 if (strcmp(k->name, name) == 0)
123 return k;
124 }
125 for (k = kexalg_prefixes; k->name != NULL; k++) {
126 if (strncmp(k->name, name, strlen(k->name)) == 0)
127 return k;
128 }
129 return NULL;
130}
131
69/* Validate KEX method name list */ 132/* Validate KEX method name list */
70int 133int
71kex_names_valid(const char *names) 134kex_names_valid(const char *names)
@@ -77,20 +140,14 @@ kex_names_valid(const char *names)
77 s = cp = xstrdup(names); 140 s = cp = xstrdup(names);
78 for ((p = strsep(&cp, ",")); p && *p != '\0'; 141 for ((p = strsep(&cp, ",")); p && *p != '\0';
79 (p = strsep(&cp, ","))) { 142 (p = strsep(&cp, ","))) {
80 if (strcmp(p, KEX_DHGEX_SHA256) != 0 && 143 if (kex_alg_by_name(p) == NULL) {
81 strcmp(p, KEX_DHGEX_SHA1) != 0 &&
82 strcmp(p, KEX_DH14) != 0 &&
83 strcmp(p, KEX_DH1) != 0 &&
84 (strncmp(p, KEX_ECDH_SHA2_STEM,
85 sizeof(KEX_ECDH_SHA2_STEM) - 1) != 0 ||
86 kex_ecdh_name_to_nid(p) == -1)) {
87 error("Unsupported KEX algorithm \"%.100s\"", p); 144 error("Unsupported KEX algorithm \"%.100s\"", p);
88 xfree(s); 145 free(s);
89 return 0; 146 return 0;
90 } 147 }
91 } 148 }
92 debug3("kex names ok: [%s]", names); 149 debug3("kex names ok: [%s]", names);
93 xfree(s); 150 free(s);
94 return 1; 151 return 1;
95} 152}
96 153
@@ -150,8 +207,8 @@ kex_prop_free(char **proposal)
150 u_int i; 207 u_int i;
151 208
152 for (i = 0; i < PROPOSAL_MAX; i++) 209 for (i = 0; i < PROPOSAL_MAX; i++)
153 xfree(proposal[i]); 210 free(proposal[i]);
154 xfree(proposal); 211 free(proposal);
155} 212}
156 213
157/* ARGSUSED */ 214/* ARGSUSED */
@@ -188,7 +245,7 @@ kex_finish(Kex *kex)
188 buffer_clear(&kex->peer); 245 buffer_clear(&kex->peer);
189 /* buffer_clear(&kex->my); */ 246 /* buffer_clear(&kex->my); */
190 kex->flags &= ~KEX_INIT_SENT; 247 kex->flags &= ~KEX_INIT_SENT;
191 xfree(kex->name); 248 free(kex->name);
192 kex->name = NULL; 249 kex->name = NULL;
193} 250}
194 251
@@ -245,7 +302,7 @@ kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
245 for (i = 0; i < KEX_COOKIE_LEN; i++) 302 for (i = 0; i < KEX_COOKIE_LEN; i++)
246 packet_get_char(); 303 packet_get_char();
247 for (i = 0; i < PROPOSAL_MAX; i++) 304 for (i = 0; i < PROPOSAL_MAX; i++)
248 xfree(packet_get_string(NULL)); 305 free(packet_get_string(NULL));
249 /* 306 /*
250 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported 307 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
251 * KEX method has the server move first, but a server might be using 308 * KEX method has the server move first, but a server might be using
@@ -352,43 +409,16 @@ choose_comp(Comp *comp, char *client, char *server)
352static void 409static void
353choose_kex(Kex *k, char *client, char *server) 410choose_kex(Kex *k, char *client, char *server)
354{ 411{
412 const struct kexalg *kexalg;
413
355 k->name = match_list(client, server, NULL); 414 k->name = match_list(client, server, NULL);
356 if (k->name == NULL) 415 if (k->name == NULL)
357 fatal("Unable to negotiate a key exchange method"); 416 fatal("Unable to negotiate a key exchange method");
358 if (strcmp(k->name, KEX_DH1) == 0) { 417 if ((kexalg = kex_alg_by_name(k->name)) == NULL)
359 k->kex_type = KEX_DH_GRP1_SHA1; 418 fatal("unsupported kex alg %s", k->name);
360 k->evp_md = EVP_sha1(); 419 k->kex_type = kexalg->type;
361 } else if (strcmp(k->name, KEX_DH14) == 0) { 420 k->evp_md = kexalg->mdfunc();
362 k->kex_type = KEX_DH_GRP14_SHA1; 421 k->ec_nid = kexalg->ec_nid;
363 k->evp_md = EVP_sha1();
364 } else if (strcmp(k->name, KEX_DHGEX_SHA1) == 0) {
365 k->kex_type = KEX_DH_GEX_SHA1;
366 k->evp_md = EVP_sha1();
367#if OPENSSL_VERSION_NUMBER >= 0x00907000L
368 } else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) {
369 k->kex_type = KEX_DH_GEX_SHA256;
370 k->evp_md = evp_ssh_sha256();
371 } else if (strncmp(k->name, KEX_ECDH_SHA2_STEM,
372 sizeof(KEX_ECDH_SHA2_STEM) - 1) == 0) {
373 k->kex_type = KEX_ECDH_SHA2;
374 k->evp_md = kex_ecdh_name_to_evpmd(k->name);
375#endif
376#ifdef GSSAPI
377 } else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID,
378 sizeof(KEX_GSS_GEX_SHA1_ID) - 1) == 0) {
379 k->kex_type = KEX_GSS_GEX_SHA1;
380 k->evp_md = EVP_sha1();
381 } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID,
382 sizeof(KEX_GSS_GRP1_SHA1_ID) - 1) == 0) {
383 k->kex_type = KEX_GSS_GRP1_SHA1;
384 k->evp_md = EVP_sha1();
385 } else if (strncmp(k->name, KEX_GSS_GRP14_SHA1_ID,
386 sizeof(KEX_GSS_GRP14_SHA1_ID) - 1) == 0) {
387 k->kex_type = KEX_GSS_GRP14_SHA1;
388 k->evp_md = EVP_sha1();
389#endif
390 } else
391 fatal("bad kex alg %s", k->name);
392} 422}
393 423
394static void 424static void
@@ -400,7 +430,7 @@ choose_hostkeyalg(Kex *k, char *client, char *server)
400 k->hostkey_type = key_type_from_name(hostkeyalg); 430 k->hostkey_type = key_type_from_name(hostkeyalg);
401 if (k->hostkey_type == KEY_UNSPEC) 431 if (k->hostkey_type == KEY_UNSPEC)
402 fatal("bad hostkey alg '%s'", hostkeyalg); 432 fatal("bad hostkey alg '%s'", hostkeyalg);
403 xfree(hostkeyalg); 433 free(hostkeyalg);
404} 434}
405 435
406static int 436static int
@@ -454,7 +484,7 @@ kex_choose_conf(Kex *kex)
454 roaming = match_list(KEX_RESUME, peer[PROPOSAL_KEX_ALGS], NULL); 484 roaming = match_list(KEX_RESUME, peer[PROPOSAL_KEX_ALGS], NULL);
455 if (roaming) { 485 if (roaming) {
456 kex->roaming = 1; 486 kex->roaming = 1;
457 xfree(roaming); 487 free(roaming);
458 } 488 }
459 } 489 }
460 490