diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | authfile.c | 6 | ||||
-rw-r--r-- | cipher.c | 55 | ||||
-rw-r--r-- | cipher.h | 13 | ||||
-rw-r--r-- | kex.c | 86 | ||||
-rw-r--r-- | kex.h | 16 | ||||
-rw-r--r-- | kexecdh.c | 20 | ||||
-rw-r--r-- | kexecdhc.c | 7 | ||||
-rw-r--r-- | kexecdhs.c | 7 | ||||
-rw-r--r-- | key.c | 230 | ||||
-rw-r--r-- | key.h | 7 | ||||
-rw-r--r-- | mac.c | 62 | ||||
-rw-r--r-- | mac.h | 3 | ||||
-rw-r--r-- | packet.c | 6 | ||||
-rw-r--r-- | ssh.1 | 21 | ||||
-rw-r--r-- | ssh.c | 20 |
16 files changed, 314 insertions, 251 deletions
@@ -69,6 +69,12 @@ | |||
69 | reintroduce 1.262 without the connection-killing bug: | 69 | reintroduce 1.262 without the connection-killing bug: |
70 | fatal() when ChrootDirectory specified by running without root privileges; | 70 | fatal() when ChrootDirectory specified by running without root privileges; |
71 | ok markus@ | 71 | ok markus@ |
72 | - djm@cvs.openbsd.org 2013/04/19 01:06:50 | ||
73 | [authfile.c cipher.c cipher.h kex.c kex.h kexecdh.c kexecdhc.c kexecdhs.c] | ||
74 | [key.c key.h mac.c mac.h packet.c ssh.1 ssh.c] | ||
75 | add the ability to query supported ciphers, MACs, key type and KEX | ||
76 | algorithms to ssh. Includes some refactoring of KEX and key type handling | ||
77 | to be table-driven; ok markus@ | ||
72 | 78 | ||
73 | 20130418 | 79 | 20130418 |
74 | - (djm) [config.guess config.sub] Update to last versions before they switch | 80 | - (djm) [config.guess config.sub] Update to last versions before they switch |
diff --git a/authfile.c b/authfile.c index 3544d170b..91812bf87 100644 --- a/authfile.c +++ b/authfile.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfile.c,v 1.95 2013/01/08 18:49:04 markus Exp $ */ | 1 | /* $OpenBSD: authfile.c,v 1.96 2013/04/19 01:06:50 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -89,7 +89,7 @@ key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase, | |||
89 | u_char buf[100], *cp; | 89 | u_char buf[100], *cp; |
90 | int i, cipher_num; | 90 | int i, cipher_num; |
91 | CipherContext ciphercontext; | 91 | CipherContext ciphercontext; |
92 | Cipher *cipher; | 92 | const Cipher *cipher; |
93 | u_int32_t rnd; | 93 | u_int32_t rnd; |
94 | 94 | ||
95 | /* | 95 | /* |
@@ -421,7 +421,7 @@ key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp) | |||
421 | Buffer decrypted; | 421 | Buffer decrypted; |
422 | u_char *cp; | 422 | u_char *cp; |
423 | CipherContext ciphercontext; | 423 | CipherContext ciphercontext; |
424 | Cipher *cipher; | 424 | const Cipher *cipher; |
425 | Key *prv = NULL; | 425 | Key *prv = NULL; |
426 | Buffer copy; | 426 | Buffer copy; |
427 | 427 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: cipher.c,v 1.87 2013/01/26 06:11:05 djm Exp $ */ | 1 | /* $OpenBSD: cipher.c,v 1.88 2013/04/19 01:06:50 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -65,7 +65,9 @@ struct Cipher { | |||
65 | u_int discard_len; | 65 | u_int discard_len; |
66 | u_int cbc_mode; | 66 | u_int cbc_mode; |
67 | const EVP_CIPHER *(*evptype)(void); | 67 | const EVP_CIPHER *(*evptype)(void); |
68 | } ciphers[] = { | 68 | }; |
69 | |||
70 | static const struct Cipher ciphers[] = { | ||
69 | { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, | 71 | { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, |
70 | { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, | 72 | { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, |
71 | { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, | 73 | { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, |
@@ -98,6 +100,27 @@ struct Cipher { | |||
98 | 100 | ||
99 | /*--*/ | 101 | /*--*/ |
100 | 102 | ||
103 | /* Returns a comma-separated list of supported ciphers. */ | ||
104 | char * | ||
105 | cipher_alg_list(void) | ||
106 | { | ||
107 | char *ret = NULL; | ||
108 | size_t nlen, rlen = 0; | ||
109 | const Cipher *c; | ||
110 | |||
111 | for (c = ciphers; c->name != NULL; c++) { | ||
112 | if (c->number != SSH_CIPHER_SSH2) | ||
113 | continue; | ||
114 | if (ret != NULL) | ||
115 | ret[rlen++] = '\n'; | ||
116 | nlen = strlen(c->name); | ||
117 | ret = xrealloc(ret, 1, rlen + nlen + 2); | ||
118 | memcpy(ret + rlen, c->name, nlen + 1); | ||
119 | rlen += nlen; | ||
120 | } | ||
121 | return ret; | ||
122 | } | ||
123 | |||
101 | u_int | 124 | u_int |
102 | cipher_blocksize(const Cipher *c) | 125 | cipher_blocksize(const Cipher *c) |
103 | { | 126 | { |
@@ -146,20 +169,20 @@ cipher_mask_ssh1(int client) | |||
146 | return mask; | 169 | return mask; |
147 | } | 170 | } |
148 | 171 | ||
149 | Cipher * | 172 | const Cipher * |
150 | cipher_by_name(const char *name) | 173 | cipher_by_name(const char *name) |
151 | { | 174 | { |
152 | Cipher *c; | 175 | const Cipher *c; |
153 | for (c = ciphers; c->name != NULL; c++) | 176 | for (c = ciphers; c->name != NULL; c++) |
154 | if (strcmp(c->name, name) == 0) | 177 | if (strcmp(c->name, name) == 0) |
155 | return c; | 178 | return c; |
156 | return NULL; | 179 | return NULL; |
157 | } | 180 | } |
158 | 181 | ||
159 | Cipher * | 182 | const Cipher * |
160 | cipher_by_number(int id) | 183 | cipher_by_number(int id) |
161 | { | 184 | { |
162 | Cipher *c; | 185 | const Cipher *c; |
163 | for (c = ciphers; c->name != NULL; c++) | 186 | for (c = ciphers; c->name != NULL; c++) |
164 | if (c->number == id) | 187 | if (c->number == id) |
165 | return c; | 188 | return c; |
@@ -170,7 +193,7 @@ cipher_by_number(int id) | |||
170 | int | 193 | int |
171 | ciphers_valid(const char *names) | 194 | ciphers_valid(const char *names) |
172 | { | 195 | { |
173 | Cipher *c; | 196 | const Cipher *c; |
174 | char *cipher_list, *cp; | 197 | char *cipher_list, *cp; |
175 | char *p; | 198 | char *p; |
176 | 199 | ||
@@ -201,7 +224,7 @@ ciphers_valid(const char *names) | |||
201 | int | 224 | int |
202 | cipher_number(const char *name) | 225 | cipher_number(const char *name) |
203 | { | 226 | { |
204 | Cipher *c; | 227 | const Cipher *c; |
205 | if (name == NULL) | 228 | if (name == NULL) |
206 | return -1; | 229 | return -1; |
207 | for (c = ciphers; c->name != NULL; c++) | 230 | for (c = ciphers; c->name != NULL; c++) |
@@ -213,12 +236,12 @@ cipher_number(const char *name) | |||
213 | char * | 236 | char * |
214 | cipher_name(int id) | 237 | cipher_name(int id) |
215 | { | 238 | { |
216 | Cipher *c = cipher_by_number(id); | 239 | const Cipher *c = cipher_by_number(id); |
217 | return (c==NULL) ? "<unknown>" : c->name; | 240 | return (c==NULL) ? "<unknown>" : c->name; |
218 | } | 241 | } |
219 | 242 | ||
220 | void | 243 | void |
221 | cipher_init(CipherContext *cc, Cipher *cipher, | 244 | cipher_init(CipherContext *cc, const Cipher *cipher, |
222 | const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, | 245 | const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, |
223 | int do_encrypt) | 246 | int do_encrypt) |
224 | { | 247 | { |
@@ -364,7 +387,7 @@ cipher_cleanup(CipherContext *cc) | |||
364 | */ | 387 | */ |
365 | 388 | ||
366 | void | 389 | void |
367 | cipher_set_key_string(CipherContext *cc, Cipher *cipher, | 390 | cipher_set_key_string(CipherContext *cc, const Cipher *cipher, |
368 | const char *passphrase, int do_encrypt) | 391 | const char *passphrase, int do_encrypt) |
369 | { | 392 | { |
370 | MD5_CTX md; | 393 | MD5_CTX md; |
@@ -389,7 +412,7 @@ cipher_set_key_string(CipherContext *cc, Cipher *cipher, | |||
389 | int | 412 | int |
390 | cipher_get_keyiv_len(const CipherContext *cc) | 413 | cipher_get_keyiv_len(const CipherContext *cc) |
391 | { | 414 | { |
392 | Cipher *c = cc->cipher; | 415 | const Cipher *c = cc->cipher; |
393 | int ivlen; | 416 | int ivlen; |
394 | 417 | ||
395 | if (c->number == SSH_CIPHER_3DES) | 418 | if (c->number == SSH_CIPHER_3DES) |
@@ -402,7 +425,7 @@ cipher_get_keyiv_len(const CipherContext *cc) | |||
402 | void | 425 | void |
403 | cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) | 426 | cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) |
404 | { | 427 | { |
405 | Cipher *c = cc->cipher; | 428 | const Cipher *c = cc->cipher; |
406 | int evplen; | 429 | int evplen; |
407 | 430 | ||
408 | switch (c->number) { | 431 | switch (c->number) { |
@@ -438,7 +461,7 @@ cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) | |||
438 | void | 461 | void |
439 | cipher_set_keyiv(CipherContext *cc, u_char *iv) | 462 | cipher_set_keyiv(CipherContext *cc, u_char *iv) |
440 | { | 463 | { |
441 | Cipher *c = cc->cipher; | 464 | const Cipher *c = cc->cipher; |
442 | int evplen = 0; | 465 | int evplen = 0; |
443 | 466 | ||
444 | switch (c->number) { | 467 | switch (c->number) { |
@@ -471,7 +494,7 @@ cipher_set_keyiv(CipherContext *cc, u_char *iv) | |||
471 | int | 494 | int |
472 | cipher_get_keycontext(const CipherContext *cc, u_char *dat) | 495 | cipher_get_keycontext(const CipherContext *cc, u_char *dat) |
473 | { | 496 | { |
474 | Cipher *c = cc->cipher; | 497 | const Cipher *c = cc->cipher; |
475 | int plen = 0; | 498 | int plen = 0; |
476 | 499 | ||
477 | if (c->evptype == EVP_rc4) { | 500 | if (c->evptype == EVP_rc4) { |
@@ -486,7 +509,7 @@ cipher_get_keycontext(const CipherContext *cc, u_char *dat) | |||
486 | void | 509 | void |
487 | cipher_set_keycontext(CipherContext *cc, u_char *dat) | 510 | cipher_set_keycontext(CipherContext *cc, u_char *dat) |
488 | { | 511 | { |
489 | Cipher *c = cc->cipher; | 512 | const Cipher *c = cc->cipher; |
490 | int plen; | 513 | int plen; |
491 | 514 | ||
492 | if (c->evptype == EVP_rc4) { | 515 | if (c->evptype == EVP_rc4) { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: cipher.h,v 1.39 2013/01/08 18:49:04 markus Exp $ */ | 1 | /* $OpenBSD: cipher.h,v 1.40 2013/04/19 01:06:50 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -66,21 +66,22 @@ struct CipherContext { | |||
66 | int plaintext; | 66 | int plaintext; |
67 | int encrypt; | 67 | int encrypt; |
68 | EVP_CIPHER_CTX evp; | 68 | EVP_CIPHER_CTX evp; |
69 | Cipher *cipher; | 69 | const Cipher *cipher; |
70 | }; | 70 | }; |
71 | 71 | ||
72 | u_int cipher_mask_ssh1(int); | 72 | u_int cipher_mask_ssh1(int); |
73 | Cipher *cipher_by_name(const char *); | 73 | const Cipher *cipher_by_name(const char *); |
74 | Cipher *cipher_by_number(int); | 74 | const Cipher *cipher_by_number(int); |
75 | int cipher_number(const char *); | 75 | int cipher_number(const char *); |
76 | char *cipher_name(int); | 76 | char *cipher_name(int); |
77 | int ciphers_valid(const char *); | 77 | int ciphers_valid(const char *); |
78 | void cipher_init(CipherContext *, Cipher *, const u_char *, u_int, | 78 | char *cipher_alg_list(void); |
79 | void cipher_init(CipherContext *, const Cipher *, const u_char *, u_int, | ||
79 | const u_char *, u_int, int); | 80 | const u_char *, u_int, int); |
80 | void cipher_crypt(CipherContext *, u_char *, const u_char *, | 81 | void cipher_crypt(CipherContext *, u_char *, const u_char *, |
81 | u_int, u_int, u_int); | 82 | u_int, u_int, u_int); |
82 | void cipher_cleanup(CipherContext *); | 83 | void cipher_cleanup(CipherContext *); |
83 | void cipher_set_key_string(CipherContext *, Cipher *, const char *, int); | 84 | void cipher_set_key_string(CipherContext *, const Cipher *, const char *, int); |
84 | u_int cipher_blocksize(const Cipher *); | 85 | u_int cipher_blocksize(const Cipher *); |
85 | u_int cipher_keylen(const Cipher *); | 86 | u_int cipher_keylen(const Cipher *); |
86 | u_int cipher_authlen(const Cipher *); | 87 | u_int cipher_authlen(const Cipher *); |
@@ -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 |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.h,v 1.54 2013/01/08 18:49:04 markus Exp $ */ | 1 | /* $OpenBSD: kex.h,v 1.55 2013/04/19 01:06:50 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
@@ -40,8 +40,9 @@ | |||
40 | #define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1" | 40 | #define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1" |
41 | #define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256" | 41 | #define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256" |
42 | #define KEX_RESUME "resume@appgate.com" | 42 | #define KEX_RESUME "resume@appgate.com" |
43 | /* The following represents the family of ECDH methods */ | 43 | #define KEX_ECDH_SHA2_NISTP256 "ecdh-sha2-nistp256" |
44 | #define KEX_ECDH_SHA2_STEM "ecdh-sha2-" | 44 | #define KEX_ECDH_SHA2_NISTP384 "ecdh-sha2-nistp384" |
45 | #define KEX_ECDH_SHA2_NISTP521 "ecdh-sha2-nistp521" | ||
45 | 46 | ||
46 | #define COMP_NONE 0 | 47 | #define COMP_NONE 0 |
47 | #define COMP_ZLIB 1 | 48 | #define COMP_ZLIB 1 |
@@ -86,7 +87,7 @@ typedef struct Newkeys Newkeys; | |||
86 | 87 | ||
87 | struct Enc { | 88 | struct Enc { |
88 | char *name; | 89 | char *name; |
89 | Cipher *cipher; | 90 | const Cipher *cipher; |
90 | int enabled; | 91 | int enabled; |
91 | u_int key_len; | 92 | u_int key_len; |
92 | u_int iv_len; | 93 | u_int iv_len; |
@@ -131,6 +132,7 @@ struct Kex { | |||
131 | sig_atomic_t done; | 132 | sig_atomic_t done; |
132 | int flags; | 133 | int flags; |
133 | const EVP_MD *evp_md; | 134 | const EVP_MD *evp_md; |
135 | int ec_nid; | ||
134 | char *client_version_string; | 136 | char *client_version_string; |
135 | char *server_version_string; | 137 | char *server_version_string; |
136 | int (*verify_host_key)(Key *); | 138 | int (*verify_host_key)(Key *); |
@@ -141,6 +143,7 @@ struct Kex { | |||
141 | }; | 143 | }; |
142 | 144 | ||
143 | int kex_names_valid(const char *); | 145 | int kex_names_valid(const char *); |
146 | char *kex_alg_list(void); | ||
144 | 147 | ||
145 | Kex *kex_setup(char *[PROPOSAL_MAX]); | 148 | Kex *kex_setup(char *[PROPOSAL_MAX]); |
146 | void kex_finish(Kex *); | 149 | void kex_finish(Kex *); |
@@ -170,11 +173,6 @@ void | |||
170 | kex_ecdh_hash(const EVP_MD *, const EC_GROUP *, char *, char *, char *, int, | 173 | kex_ecdh_hash(const EVP_MD *, const EC_GROUP *, char *, char *, char *, int, |
171 | char *, int, u_char *, int, const EC_POINT *, const EC_POINT *, | 174 | char *, int, u_char *, int, const EC_POINT *, const EC_POINT *, |
172 | const BIGNUM *, u_char **, u_int *); | 175 | const BIGNUM *, u_char **, u_int *); |
173 | int kex_ecdh_name_to_nid(const char *); | ||
174 | const EVP_MD *kex_ecdh_name_to_evpmd(const char *); | ||
175 | #else | ||
176 | # define kex_ecdh_name_to_nid(x) (-1) | ||
177 | # define kex_ecdh_name_to_evpmd(x) (NULL) | ||
178 | #endif | 176 | #endif |
179 | 177 | ||
180 | void | 178 | void |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kexecdh.c,v 1.3 2010/09/22 05:01:29 djm Exp $ */ | 1 | /* $OpenBSD: kexecdh.c,v 1.4 2013/04/19 01:06:50 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2010 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2010 Damien Miller. All rights reserved. |
@@ -45,24 +45,6 @@ | |||
45 | #include "kex.h" | 45 | #include "kex.h" |
46 | #include "log.h" | 46 | #include "log.h" |
47 | 47 | ||
48 | int | ||
49 | kex_ecdh_name_to_nid(const char *kexname) | ||
50 | { | ||
51 | if (strlen(kexname) < sizeof(KEX_ECDH_SHA2_STEM) - 1) | ||
52 | fatal("%s: kexname too short \"%s\"", __func__, kexname); | ||
53 | return key_curve_name_to_nid(kexname + sizeof(KEX_ECDH_SHA2_STEM) - 1); | ||
54 | } | ||
55 | |||
56 | const EVP_MD * | ||
57 | kex_ecdh_name_to_evpmd(const char *kexname) | ||
58 | { | ||
59 | int nid = kex_ecdh_name_to_nid(kexname); | ||
60 | |||
61 | if (nid == -1) | ||
62 | fatal("%s: unsupported ECDH curve \"%s\"", __func__, kexname); | ||
63 | return key_ec_nid_to_evpmd(nid); | ||
64 | } | ||
65 | |||
66 | void | 48 | void |
67 | kex_ecdh_hash( | 49 | kex_ecdh_hash( |
68 | const EVP_MD *evp_md, | 50 | const EVP_MD *evp_md, |
diff --git a/kexecdhc.c b/kexecdhc.c index 115d4bf83..04239a471 100644 --- a/kexecdhc.c +++ b/kexecdhc.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kexecdhc.c,v 1.2 2010/09/22 05:01:29 djm Exp $ */ | 1 | /* $OpenBSD: kexecdhc.c,v 1.3 2013/04/19 01:06:50 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2010 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2010 Damien Miller. All rights reserved. |
@@ -57,11 +57,8 @@ kexecdh_client(Kex *kex) | |||
57 | u_char *server_host_key_blob = NULL, *signature = NULL; | 57 | u_char *server_host_key_blob = NULL, *signature = NULL; |
58 | u_char *kbuf, *hash; | 58 | u_char *kbuf, *hash; |
59 | u_int klen, slen, sbloblen, hashlen; | 59 | u_int klen, slen, sbloblen, hashlen; |
60 | int curve_nid; | ||
61 | 60 | ||
62 | if ((curve_nid = kex_ecdh_name_to_nid(kex->name)) == -1) | 61 | if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) |
63 | fatal("%s: unsupported ECDH curve \"%s\"", __func__, kex->name); | ||
64 | if ((client_key = EC_KEY_new_by_curve_name(curve_nid)) == NULL) | ||
65 | fatal("%s: EC_KEY_new_by_curve_name failed", __func__); | 62 | fatal("%s: EC_KEY_new_by_curve_name failed", __func__); |
66 | if (EC_KEY_generate_key(client_key) != 1) | 63 | if (EC_KEY_generate_key(client_key) != 1) |
67 | fatal("%s: EC_KEY_generate_key failed", __func__); | 64 | fatal("%s: EC_KEY_generate_key failed", __func__); |
diff --git a/kexecdhs.c b/kexecdhs.c index 8c515dfa6..6519abbef 100644 --- a/kexecdhs.c +++ b/kexecdhs.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kexecdhs.c,v 1.2 2010/09/22 05:01:29 djm Exp $ */ | 1 | /* $OpenBSD: kexecdhs.c,v 1.3 2013/04/19 01:06:50 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2010 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2010 Damien Miller. All rights reserved. |
@@ -59,11 +59,8 @@ kexecdh_server(Kex *kex) | |||
59 | u_char *server_host_key_blob = NULL, *signature = NULL; | 59 | u_char *server_host_key_blob = NULL, *signature = NULL; |
60 | u_char *kbuf, *hash; | 60 | u_char *kbuf, *hash; |
61 | u_int klen, slen, sbloblen, hashlen; | 61 | u_int klen, slen, sbloblen, hashlen; |
62 | int curve_nid; | ||
63 | 62 | ||
64 | if ((curve_nid = kex_ecdh_name_to_nid(kex->name)) == -1) | 63 | if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) |
65 | fatal("%s: unsupported ECDH curve \"%s\"", __func__, kex->name); | ||
66 | if ((server_key = EC_KEY_new_by_curve_name(curve_nid)) == NULL) | ||
67 | fatal("%s: EC_KEY_new_by_curve_name failed", __func__); | 64 | fatal("%s: EC_KEY_new_by_curve_name failed", __func__); |
68 | if (EC_KEY_generate_key(server_key) != 1) | 65 | if (EC_KEY_generate_key(server_key) != 1) |
69 | fatal("%s: EC_KEY_generate_key failed", __func__); | 66 | fatal("%s: EC_KEY_generate_key failed", __func__); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: key.c,v 1.100 2013/01/17 23:00:01 djm Exp $ */ | 1 | /* $OpenBSD: key.c,v 1.101 2013/04/19 01:06:50 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * read_bignum(): | 3 | * read_bignum(): |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -892,36 +892,6 @@ key_write(const Key *key, FILE *f) | |||
892 | } | 892 | } |
893 | 893 | ||
894 | const char * | 894 | const char * |
895 | key_type(const Key *k) | ||
896 | { | ||
897 | switch (k->type) { | ||
898 | case KEY_RSA1: | ||
899 | return "RSA1"; | ||
900 | case KEY_RSA: | ||
901 | return "RSA"; | ||
902 | case KEY_DSA: | ||
903 | return "DSA"; | ||
904 | #ifdef OPENSSL_HAS_ECC | ||
905 | case KEY_ECDSA: | ||
906 | return "ECDSA"; | ||
907 | #endif | ||
908 | case KEY_RSA_CERT_V00: | ||
909 | return "RSA-CERT-V00"; | ||
910 | case KEY_DSA_CERT_V00: | ||
911 | return "DSA-CERT-V00"; | ||
912 | case KEY_RSA_CERT: | ||
913 | return "RSA-CERT"; | ||
914 | case KEY_DSA_CERT: | ||
915 | return "DSA-CERT"; | ||
916 | #ifdef OPENSSL_HAS_ECC | ||
917 | case KEY_ECDSA_CERT: | ||
918 | return "ECDSA-CERT"; | ||
919 | #endif | ||
920 | } | ||
921 | return "unknown"; | ||
922 | } | ||
923 | |||
924 | const char * | ||
925 | key_cert_type(const Key *k) | 895 | key_cert_type(const Key *k) |
926 | { | 896 | { |
927 | switch (k->cert->type) { | 897 | switch (k->cert->type) { |
@@ -934,48 +904,59 @@ key_cert_type(const Key *k) | |||
934 | } | 904 | } |
935 | } | 905 | } |
936 | 906 | ||
907 | struct keytype { | ||
908 | char *name; | ||
909 | char *shortname; | ||
910 | int type; | ||
911 | int nid; | ||
912 | int cert; | ||
913 | }; | ||
914 | static const struct keytype keytypes[] = { | ||
915 | { NULL, "RSA1", KEY_RSA1, 0, 0 }, | ||
916 | { "ssh-rsa", "RSA", KEY_RSA, 0, 0 }, | ||
917 | { "ssh-dss", "DSA", KEY_DSA, 0, 0 }, | ||
918 | #ifdef OPENSSL_HAS_ECC | ||
919 | { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 }, | ||
920 | { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 }, | ||
921 | { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 }, | ||
922 | #endif /* OPENSSL_HAS_ECC */ | ||
923 | { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 }, | ||
924 | { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 }, | ||
925 | #ifdef OPENSSL_HAS_ECC | ||
926 | { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", | ||
927 | KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 }, | ||
928 | { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", | ||
929 | KEY_ECDSA_CERT, NID_secp384r1, 1 }, | ||
930 | { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", | ||
931 | KEY_ECDSA_CERT, NID_secp521r1, 1 }, | ||
932 | #endif /* OPENSSL_HAS_ECC */ | ||
933 | { "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00", | ||
934 | KEY_RSA_CERT_V00, 0, 1 }, | ||
935 | { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00", | ||
936 | KEY_DSA_CERT_V00, 0, 1 }, | ||
937 | { NULL, NULL, -1, -1, 0 } | ||
938 | }; | ||
939 | |||
940 | const char * | ||
941 | key_type(const Key *k) | ||
942 | { | ||
943 | const struct keytype *kt; | ||
944 | |||
945 | for (kt = keytypes; kt->type != -1; kt++) { | ||
946 | if (kt->type == k->type) | ||
947 | return kt->shortname; | ||
948 | } | ||
949 | return "unknown"; | ||
950 | } | ||
951 | |||
937 | static const char * | 952 | static const char * |
938 | key_ssh_name_from_type_nid(int type, int nid) | 953 | key_ssh_name_from_type_nid(int type, int nid) |
939 | { | 954 | { |
940 | switch (type) { | 955 | const struct keytype *kt; |
941 | case KEY_RSA: | 956 | |
942 | return "ssh-rsa"; | 957 | for (kt = keytypes; kt->type != -1; kt++) { |
943 | case KEY_DSA: | 958 | if (kt->type == type && (kt->nid == 0 || kt->nid == nid)) |
944 | return "ssh-dss"; | 959 | return kt->name; |
945 | case KEY_RSA_CERT_V00: | ||
946 | return "ssh-rsa-cert-v00@openssh.com"; | ||
947 | case KEY_DSA_CERT_V00: | ||
948 | return "ssh-dss-cert-v00@openssh.com"; | ||
949 | case KEY_RSA_CERT: | ||
950 | return "ssh-rsa-cert-v01@openssh.com"; | ||
951 | case KEY_DSA_CERT: | ||
952 | return "ssh-dss-cert-v01@openssh.com"; | ||
953 | #ifdef OPENSSL_HAS_ECC | ||
954 | case KEY_ECDSA: | ||
955 | switch (nid) { | ||
956 | case NID_X9_62_prime256v1: | ||
957 | return "ecdsa-sha2-nistp256"; | ||
958 | case NID_secp384r1: | ||
959 | return "ecdsa-sha2-nistp384"; | ||
960 | case NID_secp521r1: | ||
961 | return "ecdsa-sha2-nistp521"; | ||
962 | default: | ||
963 | break; | ||
964 | } | ||
965 | break; | ||
966 | case KEY_ECDSA_CERT: | ||
967 | switch (nid) { | ||
968 | case NID_X9_62_prime256v1: | ||
969 | return "ecdsa-sha2-nistp256-cert-v01@openssh.com"; | ||
970 | case NID_secp384r1: | ||
971 | return "ecdsa-sha2-nistp384-cert-v01@openssh.com"; | ||
972 | case NID_secp521r1: | ||
973 | return "ecdsa-sha2-nistp521-cert-v01@openssh.com"; | ||
974 | default: | ||
975 | break; | ||
976 | } | ||
977 | break; | ||
978 | #endif /* OPENSSL_HAS_ECC */ | ||
979 | } | 960 | } |
980 | return "ssh-unknown"; | 961 | return "ssh-unknown"; |
981 | } | 962 | } |
@@ -993,6 +974,56 @@ key_ssh_name_plain(const Key *k) | |||
993 | k->ecdsa_nid); | 974 | k->ecdsa_nid); |
994 | } | 975 | } |
995 | 976 | ||
977 | int | ||
978 | key_type_from_name(char *name) | ||
979 | { | ||
980 | const struct keytype *kt; | ||
981 | |||
982 | for (kt = keytypes; kt->type != -1; kt++) { | ||
983 | /* Only allow shortname matches for plain key types */ | ||
984 | if ((kt->name != NULL && strcmp(name, kt->name) == 0) || | ||
985 | (!kt->cert && strcasecmp(kt->shortname, name) == 0)) | ||
986 | return kt->type; | ||
987 | } | ||
988 | debug2("key_type_from_name: unknown key type '%s'", name); | ||
989 | return KEY_UNSPEC; | ||
990 | } | ||
991 | |||
992 | int | ||
993 | key_ecdsa_nid_from_name(const char *name) | ||
994 | { | ||
995 | const struct keytype *kt; | ||
996 | |||
997 | for (kt = keytypes; kt->type != -1; kt++) { | ||
998 | if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT) | ||
999 | continue; | ||
1000 | if (kt->name != NULL && strcmp(name, kt->name) == 0) | ||
1001 | return kt->nid; | ||
1002 | } | ||
1003 | debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name); | ||
1004 | return -1; | ||
1005 | } | ||
1006 | |||
1007 | char * | ||
1008 | key_alg_list(void) | ||
1009 | { | ||
1010 | char *ret = NULL; | ||
1011 | size_t nlen, rlen = 0; | ||
1012 | const struct keytype *kt; | ||
1013 | |||
1014 | for (kt = keytypes; kt->type != -1; kt++) { | ||
1015 | if (kt->name == NULL) | ||
1016 | continue; | ||
1017 | if (ret != NULL) | ||
1018 | ret[rlen++] = '\n'; | ||
1019 | nlen = strlen(kt->name); | ||
1020 | ret = xrealloc(ret, 1, rlen + nlen + 2); | ||
1021 | memcpy(ret + rlen, kt->name, nlen + 1); | ||
1022 | rlen += nlen; | ||
1023 | } | ||
1024 | return ret; | ||
1025 | } | ||
1026 | |||
996 | u_int | 1027 | u_int |
997 | key_size(const Key *k) | 1028 | key_size(const Key *k) |
998 | { | 1029 | { |
@@ -1248,65 +1279,6 @@ key_from_private(const Key *k) | |||
1248 | } | 1279 | } |
1249 | 1280 | ||
1250 | int | 1281 | int |
1251 | key_type_from_name(char *name) | ||
1252 | { | ||
1253 | if (strcmp(name, "rsa1") == 0) { | ||
1254 | return KEY_RSA1; | ||
1255 | } else if (strcmp(name, "rsa") == 0) { | ||
1256 | return KEY_RSA; | ||
1257 | } else if (strcmp(name, "dsa") == 0) { | ||
1258 | return KEY_DSA; | ||
1259 | } else if (strcmp(name, "ssh-rsa") == 0) { | ||
1260 | return KEY_RSA; | ||
1261 | } else if (strcmp(name, "ssh-dss") == 0) { | ||
1262 | return KEY_DSA; | ||
1263 | #ifdef OPENSSL_HAS_ECC | ||
1264 | } else if (strcmp(name, "ecdsa") == 0 || | ||
1265 | strcmp(name, "ecdsa-sha2-nistp256") == 0 || | ||
1266 | strcmp(name, "ecdsa-sha2-nistp384") == 0 || | ||
1267 | strcmp(name, "ecdsa-sha2-nistp521") == 0) { | ||
1268 | return KEY_ECDSA; | ||
1269 | #endif | ||
1270 | } else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) { | ||
1271 | return KEY_RSA_CERT_V00; | ||
1272 | } else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) { | ||
1273 | return KEY_DSA_CERT_V00; | ||
1274 | } else if (strcmp(name, "ssh-rsa-cert-v01@openssh.com") == 0) { | ||
1275 | return KEY_RSA_CERT; | ||
1276 | } else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) { | ||
1277 | return KEY_DSA_CERT; | ||
1278 | #ifdef OPENSSL_HAS_ECC | ||
1279 | } else if (strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0 || | ||
1280 | strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0 || | ||
1281 | strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) { | ||
1282 | return KEY_ECDSA_CERT; | ||
1283 | #endif | ||
1284 | } | ||
1285 | |||
1286 | debug2("key_type_from_name: unknown key type '%s'", name); | ||
1287 | return KEY_UNSPEC; | ||
1288 | } | ||
1289 | |||
1290 | int | ||
1291 | key_ecdsa_nid_from_name(const char *name) | ||
1292 | { | ||
1293 | #ifdef OPENSSL_HAS_ECC | ||
1294 | if (strcmp(name, "ecdsa-sha2-nistp256") == 0 || | ||
1295 | strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0) | ||
1296 | return NID_X9_62_prime256v1; | ||
1297 | if (strcmp(name, "ecdsa-sha2-nistp384") == 0 || | ||
1298 | strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0) | ||
1299 | return NID_secp384r1; | ||
1300 | if (strcmp(name, "ecdsa-sha2-nistp521") == 0 || | ||
1301 | strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) | ||
1302 | return NID_secp521r1; | ||
1303 | #endif /* OPENSSL_HAS_ECC */ | ||
1304 | |||
1305 | debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name); | ||
1306 | return -1; | ||
1307 | } | ||
1308 | |||
1309 | int | ||
1310 | key_names_valid2(const char *names) | 1282 | key_names_valid2(const char *names) |
1311 | { | 1283 | { |
1312 | char *s, *cp, *p; | 1284 | char *s, *cp, *p; |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: key.h,v 1.35 2013/01/17 23:00:01 djm Exp $ */ | 1 | /* $OpenBSD: key.h,v 1.36 2013/04/19 01:06:50 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
@@ -118,15 +118,16 @@ int key_cert_is_legacy(const Key *); | |||
118 | 118 | ||
119 | int key_ecdsa_nid_from_name(const char *); | 119 | int key_ecdsa_nid_from_name(const char *); |
120 | int key_curve_name_to_nid(const char *); | 120 | int key_curve_name_to_nid(const char *); |
121 | const char * key_curve_nid_to_name(int); | 121 | const char *key_curve_nid_to_name(int); |
122 | u_int key_curve_nid_to_bits(int); | 122 | u_int key_curve_nid_to_bits(int); |
123 | int key_ecdsa_bits_to_nid(int); | 123 | int key_ecdsa_bits_to_nid(int); |
124 | #ifdef OPENSSL_HAS_ECC | 124 | #ifdef OPENSSL_HAS_ECC |
125 | int key_ecdsa_key_to_nid(EC_KEY *); | 125 | int key_ecdsa_key_to_nid(EC_KEY *); |
126 | const EVP_MD * key_ec_nid_to_evpmd(int nid); | 126 | const EVP_MD *key_ec_nid_to_evpmd(int nid); |
127 | int key_ec_validate_public(const EC_GROUP *, const EC_POINT *); | 127 | int key_ec_validate_public(const EC_GROUP *, const EC_POINT *); |
128 | int key_ec_validate_private(const EC_KEY *); | 128 | int key_ec_validate_private(const EC_KEY *); |
129 | #endif | 129 | #endif |
130 | char *key_alg_list(void); | ||
130 | 131 | ||
131 | Key *key_from_blob(const u_char *, u_int); | 132 | Key *key_from_blob(const u_char *, u_int); |
132 | int key_to_blob(const Key *, u_char **, u_int *); | 133 | int key_to_blob(const Key *, u_char **, u_int *); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mac.c,v 1.21 2012/12/11 22:51:45 sthen Exp $ */ | 1 | /* $OpenBSD: mac.c,v 1.22 2013/04/19 01:06:50 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -50,7 +50,7 @@ | |||
50 | #define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ | 50 | #define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ |
51 | #define SSH_UMAC128 3 | 51 | #define SSH_UMAC128 3 |
52 | 52 | ||
53 | struct { | 53 | struct macalg { |
54 | char *name; | 54 | char *name; |
55 | int type; | 55 | int type; |
56 | const EVP_MD * (*mdfunc)(void); | 56 | const EVP_MD * (*mdfunc)(void); |
@@ -58,7 +58,9 @@ struct { | |||
58 | int key_len; /* just for UMAC */ | 58 | int key_len; /* just for UMAC */ |
59 | int len; /* just for UMAC */ | 59 | int len; /* just for UMAC */ |
60 | int etm; /* Encrypt-then-MAC */ | 60 | int etm; /* Encrypt-then-MAC */ |
61 | } macs[] = { | 61 | }; |
62 | |||
63 | static const struct macalg macs[] = { | ||
62 | /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ | 64 | /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ |
63 | { "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 }, | 65 | { "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 }, |
64 | { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 }, | 66 | { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 }, |
@@ -89,38 +91,58 @@ struct { | |||
89 | { NULL, 0, NULL, 0, 0, 0, 0 } | 91 | { NULL, 0, NULL, 0, 0, 0, 0 } |
90 | }; | 92 | }; |
91 | 93 | ||
94 | /* Returns a comma-separated list of supported MACs. */ | ||
95 | char * | ||
96 | mac_alg_list(void) | ||
97 | { | ||
98 | char *ret = NULL; | ||
99 | size_t nlen, rlen = 0; | ||
100 | const struct macalg *m; | ||
101 | |||
102 | for (m = macs; m->name != NULL; m++) { | ||
103 | if (ret != NULL) | ||
104 | ret[rlen++] = '\n'; | ||
105 | nlen = strlen(m->name); | ||
106 | ret = xrealloc(ret, 1, rlen + nlen + 2); | ||
107 | memcpy(ret + rlen, m->name, nlen + 1); | ||
108 | rlen += nlen; | ||
109 | } | ||
110 | return ret; | ||
111 | } | ||
112 | |||
92 | static void | 113 | static void |
93 | mac_setup_by_id(Mac *mac, int which) | 114 | mac_setup_by_alg(Mac *mac, const struct macalg *macalg) |
94 | { | 115 | { |
95 | int evp_len; | 116 | int evp_len; |
96 | mac->type = macs[which].type; | 117 | |
118 | mac->type = macalg->type; | ||
97 | if (mac->type == SSH_EVP) { | 119 | if (mac->type == SSH_EVP) { |
98 | mac->evp_md = (*macs[which].mdfunc)(); | 120 | mac->evp_md = macalg->mdfunc(); |
99 | if ((evp_len = EVP_MD_size(mac->evp_md)) <= 0) | 121 | if ((evp_len = EVP_MD_size(mac->evp_md)) <= 0) |
100 | fatal("mac %s len %d", mac->name, evp_len); | 122 | fatal("mac %s len %d", mac->name, evp_len); |
101 | mac->key_len = mac->mac_len = (u_int)evp_len; | 123 | mac->key_len = mac->mac_len = (u_int)evp_len; |
102 | } else { | 124 | } else { |
103 | mac->mac_len = macs[which].len / 8; | 125 | mac->mac_len = macalg->len / 8; |
104 | mac->key_len = macs[which].key_len / 8; | 126 | mac->key_len = macalg->key_len / 8; |
105 | mac->umac_ctx = NULL; | 127 | mac->umac_ctx = NULL; |
106 | } | 128 | } |
107 | if (macs[which].truncatebits != 0) | 129 | if (macalg->truncatebits != 0) |
108 | mac->mac_len = macs[which].truncatebits / 8; | 130 | mac->mac_len = macalg->truncatebits / 8; |
109 | mac->etm = macs[which].etm; | 131 | mac->etm = macalg->etm; |
110 | } | 132 | } |
111 | 133 | ||
112 | int | 134 | int |
113 | mac_setup(Mac *mac, char *name) | 135 | mac_setup(Mac *mac, char *name) |
114 | { | 136 | { |
115 | int i; | 137 | const struct macalg *m; |
116 | 138 | ||
117 | for (i = 0; macs[i].name; i++) { | 139 | for (m = macs; m->name != NULL; m++) { |
118 | if (strcmp(name, macs[i].name) == 0) { | 140 | if (strcmp(name, m->name) != 0) |
119 | if (mac != NULL) | 141 | continue; |
120 | mac_setup_by_id(mac, i); | 142 | if (mac != NULL) |
121 | debug2("mac_setup: found %s", name); | 143 | mac_setup_by_alg(mac, m); |
122 | return (0); | 144 | debug2("mac_setup: found %s", name); |
123 | } | 145 | return (0); |
124 | } | 146 | } |
125 | debug2("mac_setup: unknown %s", name); | 147 | debug2("mac_setup: unknown %s", name); |
126 | return (-1); | 148 | return (-1); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mac.h,v 1.6 2007/06/07 19:37:34 pvalchev Exp $ */ | 1 | /* $OpenBSD: mac.h,v 1.7 2013/04/19 01:06:50 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -24,6 +24,7 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | int mac_valid(const char *); | 26 | int mac_valid(const char *); |
27 | char *mac_alg_list(void); | ||
27 | int mac_setup(Mac *, char *); | 28 | int mac_setup(Mac *, char *); |
28 | int mac_init(Mac *); | 29 | int mac_init(Mac *); |
29 | u_char *mac_compute(Mac *, u_int32_t, u_char *, int); | 30 | u_char *mac_compute(Mac *, u_int32_t, u_char *, int); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.c,v 1.182 2013/04/11 02:27:50 djm Exp $ */ | 1 | /* $OpenBSD: packet.c,v 1.183 2013/04/19 01:06:50 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -215,7 +215,7 @@ alloc_session_state(void) | |||
215 | void | 215 | void |
216 | packet_set_connection(int fd_in, int fd_out) | 216 | packet_set_connection(int fd_in, int fd_out) |
217 | { | 217 | { |
218 | Cipher *none = cipher_by_name("none"); | 218 | const Cipher *none = cipher_by_name("none"); |
219 | 219 | ||
220 | if (none == NULL) | 220 | if (none == NULL) |
221 | fatal("packet_set_connection: cannot load cipher 'none'"); | 221 | fatal("packet_set_connection: cannot load cipher 'none'"); |
@@ -545,7 +545,7 @@ packet_start_compression(int level) | |||
545 | void | 545 | void |
546 | packet_set_encryption_key(const u_char *key, u_int keylen, int number) | 546 | packet_set_encryption_key(const u_char *key, u_int keylen, int number) |
547 | { | 547 | { |
548 | Cipher *cipher = cipher_by_number(number); | 548 | const Cipher *cipher = cipher_by_number(number); |
549 | 549 | ||
550 | if (cipher == NULL) | 550 | if (cipher == NULL) |
551 | fatal("packet_set_encryption_key: unknown cipher number %d", number); | 551 | fatal("packet_set_encryption_key: unknown cipher number %d", number); |
@@ -33,8 +33,8 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: ssh.1,v 1.331 2013/04/07 02:10:33 dtucker Exp $ | 36 | .\" $OpenBSD: ssh.1,v 1.332 2013/04/19 01:06:50 djm Exp $ |
37 | .Dd $Mdocdate: April 7 2013 $ | 37 | .Dd $Mdocdate: April 19 2013 $ |
38 | .Dt SSH 1 | 38 | .Dt SSH 1 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -65,6 +65,8 @@ | |||
65 | .Oo Ar user Ns @ Oc Ns Ar hostname | 65 | .Oo Ar user Ns @ Oc Ns Ar hostname |
66 | .Op Ar command | 66 | .Op Ar command |
67 | .Ek | 67 | .Ek |
68 | .Nm | ||
69 | .Fl Q Ar protocol_feature | ||
68 | .Sh DESCRIPTION | 70 | .Sh DESCRIPTION |
69 | .Nm | 71 | .Nm |
70 | (SSH client) is a program for logging into a remote machine and for | 72 | (SSH client) is a program for logging into a remote machine and for |
@@ -487,6 +489,21 @@ For full details of the options listed below, and their possible values, see | |||
487 | Port to connect to on the remote host. | 489 | Port to connect to on the remote host. |
488 | This can be specified on a | 490 | This can be specified on a |
489 | per-host basis in the configuration file. | 491 | per-host basis in the configuration file. |
492 | .It Fl Q Ar protocol_feature | ||
493 | Queries | ||
494 | .Nm | ||
495 | for the algorithms supported for the specified version 2 | ||
496 | .Ar protocol_feature . | ||
497 | The queriable features are: | ||
498 | .Dq cipher | ||
499 | (supported symmetric ciphers), | ||
500 | .Dq MAC | ||
501 | (supported message integrity codes), | ||
502 | .Dq KEX | ||
503 | (key exchange algorithms), | ||
504 | .Dq key | ||
505 | (key types). | ||
506 | Protocol features are treated case-insensitively. | ||
490 | .It Fl q | 507 | .It Fl q |
491 | Quiet mode. | 508 | Quiet mode. |
492 | Causes most warning and diagnostic messages to be suppressed. | 509 | Causes most warning and diagnostic messages to be suppressed. |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.375 2013/04/07 02:10:33 dtucker Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.376 2013/04/19 01:06:50 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -327,7 +327,7 @@ main(int ac, char **av) | |||
327 | 327 | ||
328 | again: | 328 | again: |
329 | while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" | 329 | while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" |
330 | "ACD:E:F:I:KL:MNO:PR:S:TVw:W:XYy")) != -1) { | 330 | "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { |
331 | switch (opt) { | 331 | switch (opt) { |
332 | case '1': | 332 | case '1': |
333 | options.protocol = SSH_PROTO_1; | 333 | options.protocol = SSH_PROTO_1; |
@@ -389,6 +389,22 @@ main(int ac, char **av) | |||
389 | case 'P': /* deprecated */ | 389 | case 'P': /* deprecated */ |
390 | options.use_privileged_port = 0; | 390 | options.use_privileged_port = 0; |
391 | break; | 391 | break; |
392 | case 'Q': /* deprecated */ | ||
393 | cp = NULL; | ||
394 | if (strcasecmp(optarg, "cipher") == 0) | ||
395 | cp = cipher_alg_list(); | ||
396 | else if (strcasecmp(optarg, "mac") == 0) | ||
397 | cp = mac_alg_list(); | ||
398 | else if (strcasecmp(optarg, "kex") == 0) | ||
399 | cp = kex_alg_list(); | ||
400 | else if (strcasecmp(optarg, "key") == 0) | ||
401 | cp = key_alg_list(); | ||
402 | if (cp == NULL) | ||
403 | fatal("Unsupported query \"%s\"", optarg); | ||
404 | printf("%s\n", cp); | ||
405 | free(cp); | ||
406 | exit(0); | ||
407 | break; | ||
392 | case 'a': | 408 | case 'a': |
393 | options.forward_agent = 0; | 409 | options.forward_agent = 0; |
394 | break; | 410 | break; |