diff options
author | Damien Miller <djm@mindrot.org> | 2013-04-23 19:24:32 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2013-04-23 19:24:32 +1000 |
commit | ea11119eee3c5e2429b1f5f8688b25b028fa991a (patch) | |
tree | 5916295fcefb8665088f59a5431cb0c792fbf327 /kex.c | |
parent | a56086b9903b62c1c4fdedf01b68338fe4dc90e4 (diff) |
- djm@cvs.openbsd.org 2013/04/19 01:06:50
[authfile.c cipher.c cipher.h kex.c kex.h kexecdh.c kexecdhc.c kexecdhs.c]
[key.c key.h mac.c mac.h packet.c ssh.1 ssh.c]
add the ability to query supported ciphers, MACs, key type and KEX
algorithms to ssh. Includes some refactoring of KEX and key type handling
to be table-driven; ok markus@
Diffstat (limited to 'kex.c')
-rw-r--r-- | kex.c | 86 |
1 files changed, 58 insertions, 28 deletions
@@ -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.89 2013/04/19 01:06:50 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 | * |
@@ -62,6 +62,55 @@ extern const EVP_MD *evp_ssh_sha256(void); | |||
62 | static void kex_kexinit_finish(Kex *); | 62 | static void kex_kexinit_finish(Kex *); |
63 | static void kex_choose_conf(Kex *); | 63 | static void kex_choose_conf(Kex *); |
64 | 64 | ||
65 | struct kexalg { | ||
66 | char *name; | ||
67 | int type; | ||
68 | int ec_nid; | ||
69 | const EVP_MD *(*mdfunc)(void); | ||
70 | }; | ||
71 | static const struct kexalg kexalgs[] = { | ||
72 | { KEX_DH1, KEX_DH_GRP1_SHA1, 0, EVP_sha1 }, | ||
73 | { KEX_DH14, KEX_DH_GRP14_SHA1, 0, EVP_sha1 }, | ||
74 | { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, EVP_sha1 }, | ||
75 | #if OPENSSL_VERSION_NUMBER >= 0x00907000L | ||
76 | { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, EVP_sha256 }, | ||
77 | { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, NID_X9_62_prime256v1, EVP_sha256 }, | ||
78 | { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, EVP_sha384 }, | ||
79 | { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, EVP_sha512 }, | ||
80 | #endif | ||
81 | { NULL, -1, -1, NULL}, | ||
82 | }; | ||
83 | |||
84 | char * | ||
85 | kex_alg_list(void) | ||
86 | { | ||
87 | char *ret = NULL; | ||
88 | size_t nlen, rlen = 0; | ||
89 | const struct kexalg *k; | ||
90 | |||
91 | for (k = kexalgs; k->name != NULL; k++) { | ||
92 | if (ret != NULL) | ||
93 | ret[rlen++] = '\n'; | ||
94 | nlen = strlen(k->name); | ||
95 | ret = xrealloc(ret, 1, rlen + nlen + 2); | ||
96 | memcpy(ret + rlen, k->name, nlen + 1); | ||
97 | rlen += nlen; | ||
98 | } | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | static const struct kexalg * | ||
103 | kex_alg_by_name(const char *name) | ||
104 | { | ||
105 | const struct kexalg *k; | ||
106 | |||
107 | for (k = kexalgs; k->name != NULL; k++) { | ||
108 | if (strcmp(k->name, name) == 0) | ||
109 | return k; | ||
110 | } | ||
111 | return NULL; | ||
112 | } | ||
113 | |||
65 | /* Validate KEX method name list */ | 114 | /* Validate KEX method name list */ |
66 | int | 115 | int |
67 | kex_names_valid(const char *names) | 116 | kex_names_valid(const char *names) |
@@ -73,13 +122,7 @@ kex_names_valid(const char *names) | |||
73 | s = cp = xstrdup(names); | 122 | s = cp = xstrdup(names); |
74 | for ((p = strsep(&cp, ",")); p && *p != '\0'; | 123 | for ((p = strsep(&cp, ",")); p && *p != '\0'; |
75 | (p = strsep(&cp, ","))) { | 124 | (p = strsep(&cp, ","))) { |
76 | if (strcmp(p, KEX_DHGEX_SHA256) != 0 && | 125 | if (kex_alg_by_name(p) == NULL) { |
77 | strcmp(p, KEX_DHGEX_SHA1) != 0 && | ||
78 | strcmp(p, KEX_DH14) != 0 && | ||
79 | strcmp(p, KEX_DH1) != 0 && | ||
80 | (strncmp(p, KEX_ECDH_SHA2_STEM, | ||
81 | sizeof(KEX_ECDH_SHA2_STEM) - 1) != 0 || | ||
82 | kex_ecdh_name_to_nid(p) == -1)) { | ||
83 | error("Unsupported KEX algorithm \"%.100s\"", p); | 126 | error("Unsupported KEX algorithm \"%.100s\"", p); |
84 | xfree(s); | 127 | xfree(s); |
85 | return 0; | 128 | return 0; |
@@ -348,29 +391,16 @@ choose_comp(Comp *comp, char *client, char *server) | |||
348 | static void | 391 | static void |
349 | choose_kex(Kex *k, char *client, char *server) | 392 | choose_kex(Kex *k, char *client, char *server) |
350 | { | 393 | { |
394 | const struct kexalg *kexalg; | ||
395 | |||
351 | k->name = match_list(client, server, NULL); | 396 | k->name = match_list(client, server, NULL); |
352 | if (k->name == NULL) | 397 | if (k->name == NULL) |
353 | fatal("Unable to negotiate a key exchange method"); | 398 | fatal("Unable to negotiate a key exchange method"); |
354 | if (strcmp(k->name, KEX_DH1) == 0) { | 399 | if ((kexalg = kex_alg_by_name(k->name)) == NULL) |
355 | k->kex_type = KEX_DH_GRP1_SHA1; | 400 | fatal("unsupported kex alg %s", k->name); |
356 | k->evp_md = EVP_sha1(); | 401 | k->kex_type = kexalg->type; |
357 | } else if (strcmp(k->name, KEX_DH14) == 0) { | 402 | k->evp_md = kexalg->mdfunc(); |
358 | k->kex_type = KEX_DH_GRP14_SHA1; | 403 | k->ec_nid = kexalg->ec_nid; |
359 | k->evp_md = EVP_sha1(); | ||
360 | } else if (strcmp(k->name, KEX_DHGEX_SHA1) == 0) { | ||
361 | k->kex_type = KEX_DH_GEX_SHA1; | ||
362 | k->evp_md = EVP_sha1(); | ||
363 | #if OPENSSL_VERSION_NUMBER >= 0x00907000L | ||
364 | } else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) { | ||
365 | k->kex_type = KEX_DH_GEX_SHA256; | ||
366 | k->evp_md = evp_ssh_sha256(); | ||
367 | } else if (strncmp(k->name, KEX_ECDH_SHA2_STEM, | ||
368 | sizeof(KEX_ECDH_SHA2_STEM) - 1) == 0) { | ||
369 | k->kex_type = KEX_ECDH_SHA2; | ||
370 | k->evp_md = kex_ecdh_name_to_evpmd(k->name); | ||
371 | #endif | ||
372 | } else | ||
373 | fatal("bad kex alg %s", k->name); | ||
374 | } | 404 | } |
375 | 405 | ||
376 | static void | 406 | static void |