diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | kex.c | 36 | ||||
-rw-r--r-- | kex.h | 22 | ||||
-rw-r--r-- | kexdh.c | 10 | ||||
-rw-r--r-- | kexdhc.c | 15 | ||||
-rw-r--r-- | kexdhs.c | 17 | ||||
-rw-r--r-- | kexgex.c | 16 | ||||
-rw-r--r-- | kexgexc.c | 17 | ||||
-rw-r--r-- | kexgexs.c | 20 |
9 files changed, 90 insertions, 70 deletions
@@ -93,6 +93,11 @@ | |||
93 | - dtucker@cvs.openbsd.org 2005/11/03 13:38:29 | 93 | - dtucker@cvs.openbsd.org 2005/11/03 13:38:29 |
94 | [canohost.c] | 94 | [canohost.c] |
95 | Cache reverse lookups with and without DNS separately; ok markus@ | 95 | Cache reverse lookups with and without DNS separately; ok markus@ |
96 | - djm@cvs.openbsd.org 2005/11/04 05:15:59 | ||
97 | [kex.c kex.h kexdh.c kexdhc.c kexdhs.c kexgex.c kexgexc.c kexgexs.c] | ||
98 | remove hardcoded hash lengths in key exchange code, allowing | ||
99 | implementation of KEX methods with different hashes (e.g. SHA-256); | ||
100 | ok markus@ dtucker@ stevesk@ | ||
96 | 101 | ||
97 | 20051102 | 102 | 20051102 |
98 | - (dtucker) [openbsd-compat/bsd-misc.c] Bug #1108: fix broken strdup(). | 103 | - (dtucker) [openbsd-compat/bsd-misc.c] Bug #1108: fix broken strdup(). |
@@ -3226,4 +3231,4 @@ | |||
3226 | - (djm) Trim deprecated options from INSTALL. Mention UsePAM | 3231 | - (djm) Trim deprecated options from INSTALL. Mention UsePAM |
3227 | - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu | 3232 | - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu |
3228 | 3233 | ||
3229 | $Id: ChangeLog,v 1.3950 2005/11/05 04:16:52 djm Exp $ | 3234 | $Id: ChangeLog,v 1.3951 2005/11/05 04:19:35 djm Exp $ |
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: kex.c,v 1.64 2005/07/25 11:59:39 markus Exp $"); | 26 | RCSID("$OpenBSD: kex.c,v 1.65 2005/11/04 05:15:59 djm Exp $"); |
27 | 27 | ||
28 | #include <openssl/crypto.h> | 28 | #include <openssl/crypto.h> |
29 | 29 | ||
@@ -294,13 +294,17 @@ choose_kex(Kex *k, char *client, char *server) | |||
294 | fatal("no kex alg"); | 294 | fatal("no kex alg"); |
295 | if (strcmp(k->name, KEX_DH1) == 0) { | 295 | if (strcmp(k->name, KEX_DH1) == 0) { |
296 | k->kex_type = KEX_DH_GRP1_SHA1; | 296 | k->kex_type = KEX_DH_GRP1_SHA1; |
297 | k->evp_md = EVP_sha1(); | ||
297 | } else if (strcmp(k->name, KEX_DH14) == 0) { | 298 | } else if (strcmp(k->name, KEX_DH14) == 0) { |
298 | k->kex_type = KEX_DH_GRP14_SHA1; | 299 | k->kex_type = KEX_DH_GRP14_SHA1; |
299 | } else if (strcmp(k->name, KEX_DHGEX) == 0) { | 300 | k->evp_md = EVP_sha1(); |
301 | } else if (strcmp(k->name, KEX_DHGEX_SHA1) == 0) { | ||
300 | k->kex_type = KEX_DH_GEX_SHA1; | 302 | k->kex_type = KEX_DH_GEX_SHA1; |
303 | k->evp_md = EVP_sha1(); | ||
301 | } else | 304 | } else |
302 | fatal("bad kex alg %s", k->name); | 305 | fatal("bad kex alg %s", k->name); |
303 | } | 306 | } |
307 | |||
304 | static void | 308 | static void |
305 | choose_hostkeyalg(Kex *k, char *client, char *server) | 309 | choose_hostkeyalg(Kex *k, char *client, char *server) |
306 | { | 310 | { |
@@ -404,28 +408,28 @@ kex_choose_conf(Kex *kex) | |||
404 | } | 408 | } |
405 | 409 | ||
406 | static u_char * | 410 | static u_char * |
407 | derive_key(Kex *kex, int id, u_int need, u_char *hash, BIGNUM *shared_secret) | 411 | derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, |
412 | BIGNUM *shared_secret) | ||
408 | { | 413 | { |
409 | Buffer b; | 414 | Buffer b; |
410 | const EVP_MD *evp_md = EVP_sha1(); | ||
411 | EVP_MD_CTX md; | 415 | EVP_MD_CTX md; |
412 | char c = id; | 416 | char c = id; |
413 | u_int have; | 417 | u_int have; |
414 | int mdsz = EVP_MD_size(evp_md); | 418 | int mdsz; |
415 | u_char *digest; | 419 | u_char *digest; |
416 | 420 | ||
417 | if (mdsz < 0) | 421 | if ((mdsz = EVP_MD_size(kex->evp_md)) <= 0) |
418 | fatal("derive_key: mdsz < 0"); | 422 | fatal("bad kex md size %d", mdsz); |
419 | digest = xmalloc(roundup(need, mdsz)); | 423 | digest = xmalloc(roundup(need, mdsz)); |
420 | 424 | ||
421 | buffer_init(&b); | 425 | buffer_init(&b); |
422 | buffer_put_bignum2(&b, shared_secret); | 426 | buffer_put_bignum2(&b, shared_secret); |
423 | 427 | ||
424 | /* K1 = HASH(K || H || "A" || session_id) */ | 428 | /* K1 = HASH(K || H || "A" || session_id) */ |
425 | EVP_DigestInit(&md, evp_md); | 429 | EVP_DigestInit(&md, kex->evp_md); |
426 | if (!(datafellows & SSH_BUG_DERIVEKEY)) | 430 | if (!(datafellows & SSH_BUG_DERIVEKEY)) |
427 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); | 431 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); |
428 | EVP_DigestUpdate(&md, hash, mdsz); | 432 | EVP_DigestUpdate(&md, hash, hashlen); |
429 | EVP_DigestUpdate(&md, &c, 1); | 433 | EVP_DigestUpdate(&md, &c, 1); |
430 | EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); | 434 | EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); |
431 | EVP_DigestFinal(&md, digest, NULL); | 435 | EVP_DigestFinal(&md, digest, NULL); |
@@ -436,10 +440,10 @@ derive_key(Kex *kex, int id, u_int need, u_char *hash, BIGNUM *shared_secret) | |||
436 | * Key = K1 || K2 || ... || Kn | 440 | * Key = K1 || K2 || ... || Kn |
437 | */ | 441 | */ |
438 | for (have = mdsz; need > have; have += mdsz) { | 442 | for (have = mdsz; need > have; have += mdsz) { |
439 | EVP_DigestInit(&md, evp_md); | 443 | EVP_DigestInit(&md, kex->evp_md); |
440 | if (!(datafellows & SSH_BUG_DERIVEKEY)) | 444 | if (!(datafellows & SSH_BUG_DERIVEKEY)) |
441 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); | 445 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); |
442 | EVP_DigestUpdate(&md, hash, mdsz); | 446 | EVP_DigestUpdate(&md, hash, hashlen); |
443 | EVP_DigestUpdate(&md, digest, have); | 447 | EVP_DigestUpdate(&md, digest, have); |
444 | EVP_DigestFinal(&md, digest + have, NULL); | 448 | EVP_DigestFinal(&md, digest + have, NULL); |
445 | } | 449 | } |
@@ -455,13 +459,15 @@ Newkeys *current_keys[MODE_MAX]; | |||
455 | 459 | ||
456 | #define NKEYS 6 | 460 | #define NKEYS 6 |
457 | void | 461 | void |
458 | kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret) | 462 | kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, BIGNUM *shared_secret) |
459 | { | 463 | { |
460 | u_char *keys[NKEYS]; | 464 | u_char *keys[NKEYS]; |
461 | u_int i, mode, ctos; | 465 | u_int i, mode, ctos; |
462 | 466 | ||
463 | for (i = 0; i < NKEYS; i++) | 467 | for (i = 0; i < NKEYS; i++) { |
464 | keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, shared_secret); | 468 | keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, hashlen, |
469 | shared_secret); | ||
470 | } | ||
465 | 471 | ||
466 | debug2("kex_derive_keys"); | 472 | debug2("kex_derive_keys"); |
467 | for (mode = 0; mode < MODE_MAX; mode++) { | 473 | for (mode = 0; mode < MODE_MAX; mode++) { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.h,v 1.37 2005/07/25 11:59:39 markus Exp $ */ | 1 | /* $OpenBSD: kex.h,v 1.38 2005/11/04 05:15:59 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. |
@@ -31,9 +31,9 @@ | |||
31 | #include "cipher.h" | 31 | #include "cipher.h" |
32 | #include "key.h" | 32 | #include "key.h" |
33 | 33 | ||
34 | #define KEX_DH1 "diffie-hellman-group1-sha1" | 34 | #define KEX_DH1 "diffie-hellman-group1-sha1" |
35 | #define KEX_DH14 "diffie-hellman-group14-sha1" | 35 | #define KEX_DH14 "diffie-hellman-group14-sha1" |
36 | #define KEX_DHGEX "diffie-hellman-group-exchange-sha1" | 36 | #define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1" |
37 | 37 | ||
38 | #define COMP_NONE 0 | 38 | #define COMP_NONE 0 |
39 | #define COMP_ZLIB 1 | 39 | #define COMP_ZLIB 1 |
@@ -114,6 +114,7 @@ struct Kex { | |||
114 | Buffer peer; | 114 | Buffer peer; |
115 | int done; | 115 | int done; |
116 | int flags; | 116 | int flags; |
117 | const EVP_MD *evp_md; | ||
117 | char *client_version_string; | 118 | char *client_version_string; |
118 | char *server_version_string; | 119 | char *server_version_string; |
119 | int (*verify_host_key)(Key *); | 120 | int (*verify_host_key)(Key *); |
@@ -127,7 +128,7 @@ void kex_finish(Kex *); | |||
127 | 128 | ||
128 | void kex_send_kexinit(Kex *); | 129 | void kex_send_kexinit(Kex *); |
129 | void kex_input_kexinit(int, u_int32_t, void *); | 130 | void kex_input_kexinit(int, u_int32_t, void *); |
130 | void kex_derive_keys(Kex *, u_char *, BIGNUM *); | 131 | void kex_derive_keys(Kex *, u_char *, u_int, BIGNUM *); |
131 | 132 | ||
132 | Newkeys *kex_get_newkeys(int); | 133 | Newkeys *kex_get_newkeys(int); |
133 | 134 | ||
@@ -136,12 +137,13 @@ void kexdh_server(Kex *); | |||
136 | void kexgex_client(Kex *); | 137 | void kexgex_client(Kex *); |
137 | void kexgex_server(Kex *); | 138 | void kexgex_server(Kex *); |
138 | 139 | ||
139 | u_char * | 140 | void |
140 | kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, | 141 | kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, |
141 | BIGNUM *, BIGNUM *, BIGNUM *); | 142 | BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *); |
142 | u_char * | 143 | void |
143 | kexgex_hash(char *, char *, char *, int, char *, int, u_char *, int, | 144 | kexgex_hash(const EVP_MD *, char *, char *, char *, int, char *, |
144 | int, int, int, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *); | 145 | int, u_char *, int, int, int, int, BIGNUM *, BIGNUM *, BIGNUM *, |
146 | BIGNUM *, BIGNUM *, u_char **, u_int *); | ||
145 | 147 | ||
146 | void | 148 | void |
147 | derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]); | 149 | derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]); |
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: kexdh.c,v 1.19 2003/02/16 17:09:57 markus Exp $"); | 26 | RCSID("$OpenBSD: kexdh.c,v 1.20 2005/11/04 05:15:59 djm Exp $"); |
27 | 27 | ||
28 | #include <openssl/evp.h> | 28 | #include <openssl/evp.h> |
29 | 29 | ||
@@ -32,7 +32,7 @@ RCSID("$OpenBSD: kexdh.c,v 1.19 2003/02/16 17:09:57 markus Exp $"); | |||
32 | #include "ssh2.h" | 32 | #include "ssh2.h" |
33 | #include "kex.h" | 33 | #include "kex.h" |
34 | 34 | ||
35 | u_char * | 35 | void |
36 | kex_dh_hash( | 36 | kex_dh_hash( |
37 | char *client_version_string, | 37 | char *client_version_string, |
38 | char *server_version_string, | 38 | char *server_version_string, |
@@ -41,7 +41,8 @@ kex_dh_hash( | |||
41 | u_char *serverhostkeyblob, int sbloblen, | 41 | u_char *serverhostkeyblob, int sbloblen, |
42 | BIGNUM *client_dh_pub, | 42 | BIGNUM *client_dh_pub, |
43 | BIGNUM *server_dh_pub, | 43 | BIGNUM *server_dh_pub, |
44 | BIGNUM *shared_secret) | 44 | BIGNUM *shared_secret, |
45 | u_char **hash, u_int *hashlen) | ||
45 | { | 46 | { |
46 | Buffer b; | 47 | Buffer b; |
47 | static u_char digest[EVP_MAX_MD_SIZE]; | 48 | static u_char digest[EVP_MAX_MD_SIZE]; |
@@ -77,5 +78,6 @@ kex_dh_hash( | |||
77 | #ifdef DEBUG_KEX | 78 | #ifdef DEBUG_KEX |
78 | dump_digest("hash", digest, EVP_MD_size(evp_md)); | 79 | dump_digest("hash", digest, EVP_MD_size(evp_md)); |
79 | #endif | 80 | #endif |
80 | return digest; | 81 | *hash = digest; |
82 | *hashlen = EVP_MD_size(evp_md); | ||
81 | } | 83 | } |
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: kexdhc.c,v 1.2 2004/06/13 12:53:24 djm Exp $"); | 26 | RCSID("$OpenBSD: kexdhc.c,v 1.3 2005/11/04 05:15:59 djm Exp $"); |
27 | 27 | ||
28 | #include "xmalloc.h" | 28 | #include "xmalloc.h" |
29 | #include "key.h" | 29 | #include "key.h" |
@@ -41,7 +41,7 @@ kexdh_client(Kex *kex) | |||
41 | Key *server_host_key; | 41 | Key *server_host_key; |
42 | u_char *server_host_key_blob = NULL, *signature = NULL; | 42 | u_char *server_host_key_blob = NULL, *signature = NULL; |
43 | u_char *kbuf, *hash; | 43 | u_char *kbuf, *hash; |
44 | u_int klen, kout, slen, sbloblen; | 44 | u_int klen, kout, slen, sbloblen, hashlen; |
45 | 45 | ||
46 | /* generate and send 'e', client DH public key */ | 46 | /* generate and send 'e', client DH public key */ |
47 | switch (kex->kex_type) { | 47 | switch (kex->kex_type) { |
@@ -114,7 +114,7 @@ kexdh_client(Kex *kex) | |||
114 | xfree(kbuf); | 114 | xfree(kbuf); |
115 | 115 | ||
116 | /* calc and verify H */ | 116 | /* calc and verify H */ |
117 | hash = kex_dh_hash( | 117 | kex_dh_hash( |
118 | kex->client_version_string, | 118 | kex->client_version_string, |
119 | kex->server_version_string, | 119 | kex->server_version_string, |
120 | buffer_ptr(&kex->my), buffer_len(&kex->my), | 120 | buffer_ptr(&kex->my), buffer_len(&kex->my), |
@@ -122,25 +122,26 @@ kexdh_client(Kex *kex) | |||
122 | server_host_key_blob, sbloblen, | 122 | server_host_key_blob, sbloblen, |
123 | dh->pub_key, | 123 | dh->pub_key, |
124 | dh_server_pub, | 124 | dh_server_pub, |
125 | shared_secret | 125 | shared_secret, |
126 | &hash, &hashlen | ||
126 | ); | 127 | ); |
127 | xfree(server_host_key_blob); | 128 | xfree(server_host_key_blob); |
128 | BN_clear_free(dh_server_pub); | 129 | BN_clear_free(dh_server_pub); |
129 | DH_free(dh); | 130 | DH_free(dh); |
130 | 131 | ||
131 | if (key_verify(server_host_key, signature, slen, hash, 20) != 1) | 132 | if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1) |
132 | fatal("key_verify failed for server_host_key"); | 133 | fatal("key_verify failed for server_host_key"); |
133 | key_free(server_host_key); | 134 | key_free(server_host_key); |
134 | xfree(signature); | 135 | xfree(signature); |
135 | 136 | ||
136 | /* save session id */ | 137 | /* save session id */ |
137 | if (kex->session_id == NULL) { | 138 | if (kex->session_id == NULL) { |
138 | kex->session_id_len = 20; | 139 | kex->session_id_len = hashlen; |
139 | kex->session_id = xmalloc(kex->session_id_len); | 140 | kex->session_id = xmalloc(kex->session_id_len); |
140 | memcpy(kex->session_id, hash, kex->session_id_len); | 141 | memcpy(kex->session_id, hash, kex->session_id_len); |
141 | } | 142 | } |
142 | 143 | ||
143 | kex_derive_keys(kex, hash, shared_secret); | 144 | kex_derive_keys(kex, hash, hashlen, shared_secret); |
144 | BN_clear_free(shared_secret); | 145 | BN_clear_free(shared_secret); |
145 | kex_finish(kex); | 146 | kex_finish(kex); |
146 | } | 147 | } |
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: kexdhs.c,v 1.2 2004/06/13 12:53:24 djm Exp $"); | 26 | RCSID("$OpenBSD: kexdhs.c,v 1.3 2005/11/04 05:15:59 djm Exp $"); |
27 | 27 | ||
28 | #include "xmalloc.h" | 28 | #include "xmalloc.h" |
29 | #include "key.h" | 29 | #include "key.h" |
@@ -41,7 +41,7 @@ kexdh_server(Kex *kex) | |||
41 | DH *dh; | 41 | DH *dh; |
42 | Key *server_host_key; | 42 | Key *server_host_key; |
43 | u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; | 43 | u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; |
44 | u_int sbloblen, klen, kout; | 44 | u_int sbloblen, klen, kout, hashlen; |
45 | u_int slen; | 45 | u_int slen; |
46 | 46 | ||
47 | /* generate server DH public key */ | 47 | /* generate server DH public key */ |
@@ -103,7 +103,7 @@ kexdh_server(Kex *kex) | |||
103 | key_to_blob(server_host_key, &server_host_key_blob, &sbloblen); | 103 | key_to_blob(server_host_key, &server_host_key_blob, &sbloblen); |
104 | 104 | ||
105 | /* calc H */ | 105 | /* calc H */ |
106 | hash = kex_dh_hash( | 106 | kex_dh_hash( |
107 | kex->client_version_string, | 107 | kex->client_version_string, |
108 | kex->server_version_string, | 108 | kex->server_version_string, |
109 | buffer_ptr(&kex->peer), buffer_len(&kex->peer), | 109 | buffer_ptr(&kex->peer), buffer_len(&kex->peer), |
@@ -111,21 +111,20 @@ kexdh_server(Kex *kex) | |||
111 | server_host_key_blob, sbloblen, | 111 | server_host_key_blob, sbloblen, |
112 | dh_client_pub, | 112 | dh_client_pub, |
113 | dh->pub_key, | 113 | dh->pub_key, |
114 | shared_secret | 114 | shared_secret, |
115 | &hash, &hashlen | ||
115 | ); | 116 | ); |
116 | BN_clear_free(dh_client_pub); | 117 | BN_clear_free(dh_client_pub); |
117 | 118 | ||
118 | /* save session id := H */ | 119 | /* save session id := H */ |
119 | /* XXX hashlen depends on KEX */ | ||
120 | if (kex->session_id == NULL) { | 120 | if (kex->session_id == NULL) { |
121 | kex->session_id_len = 20; | 121 | kex->session_id_len = hashlen; |
122 | kex->session_id = xmalloc(kex->session_id_len); | 122 | kex->session_id = xmalloc(kex->session_id_len); |
123 | memcpy(kex->session_id, hash, kex->session_id_len); | 123 | memcpy(kex->session_id, hash, kex->session_id_len); |
124 | } | 124 | } |
125 | 125 | ||
126 | /* sign H */ | 126 | /* sign H */ |
127 | /* XXX hashlen depends on KEX */ | 127 | PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, hashlen)); |
128 | PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20)); | ||
129 | 128 | ||
130 | /* destroy_sensitive_data(); */ | 129 | /* destroy_sensitive_data(); */ |
131 | 130 | ||
@@ -141,7 +140,7 @@ kexdh_server(Kex *kex) | |||
141 | /* have keys, free DH */ | 140 | /* have keys, free DH */ |
142 | DH_free(dh); | 141 | DH_free(dh); |
143 | 142 | ||
144 | kex_derive_keys(kex, hash, shared_secret); | 143 | kex_derive_keys(kex, hash, hashlen, shared_secret); |
145 | BN_clear_free(shared_secret); | 144 | BN_clear_free(shared_secret); |
146 | kex_finish(kex); | 145 | kex_finish(kex); |
147 | } | 146 | } |
@@ -24,7 +24,7 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include "includes.h" | 26 | #include "includes.h" |
27 | RCSID("$OpenBSD: kexgex.c,v 1.23 2003/02/16 17:09:57 markus Exp $"); | 27 | RCSID("$OpenBSD: kexgex.c,v 1.24 2005/11/04 05:15:59 djm Exp $"); |
28 | 28 | ||
29 | #include <openssl/evp.h> | 29 | #include <openssl/evp.h> |
30 | 30 | ||
@@ -33,8 +33,9 @@ RCSID("$OpenBSD: kexgex.c,v 1.23 2003/02/16 17:09:57 markus Exp $"); | |||
33 | #include "kex.h" | 33 | #include "kex.h" |
34 | #include "ssh2.h" | 34 | #include "ssh2.h" |
35 | 35 | ||
36 | u_char * | 36 | void |
37 | kexgex_hash( | 37 | kexgex_hash( |
38 | const EVP_MD *evp_md, | ||
38 | char *client_version_string, | 39 | char *client_version_string, |
39 | char *server_version_string, | 40 | char *server_version_string, |
40 | char *ckexinit, int ckexinitlen, | 41 | char *ckexinit, int ckexinitlen, |
@@ -43,11 +44,11 @@ kexgex_hash( | |||
43 | int min, int wantbits, int max, BIGNUM *prime, BIGNUM *gen, | 44 | int min, int wantbits, int max, BIGNUM *prime, BIGNUM *gen, |
44 | BIGNUM *client_dh_pub, | 45 | BIGNUM *client_dh_pub, |
45 | BIGNUM *server_dh_pub, | 46 | BIGNUM *server_dh_pub, |
46 | BIGNUM *shared_secret) | 47 | BIGNUM *shared_secret, |
48 | u_char **hash, u_int *hashlen) | ||
47 | { | 49 | { |
48 | Buffer b; | 50 | Buffer b; |
49 | static u_char digest[EVP_MAX_MD_SIZE]; | 51 | static u_char digest[EVP_MAX_MD_SIZE]; |
50 | const EVP_MD *evp_md = EVP_sha1(); | ||
51 | EVP_MD_CTX md; | 52 | EVP_MD_CTX md; |
52 | 53 | ||
53 | buffer_init(&b); | 54 | buffer_init(&b); |
@@ -79,14 +80,15 @@ kexgex_hash( | |||
79 | #ifdef DEBUG_KEXDH | 80 | #ifdef DEBUG_KEXDH |
80 | buffer_dump(&b); | 81 | buffer_dump(&b); |
81 | #endif | 82 | #endif |
83 | |||
82 | EVP_DigestInit(&md, evp_md); | 84 | EVP_DigestInit(&md, evp_md); |
83 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); | 85 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); |
84 | EVP_DigestFinal(&md, digest, NULL); | 86 | EVP_DigestFinal(&md, digest, NULL); |
85 | 87 | ||
86 | buffer_free(&b); | 88 | buffer_free(&b); |
87 | 89 | *hash = digest; | |
90 | *hashlen = EVP_MD_size(evp_md); | ||
88 | #ifdef DEBUG_KEXDH | 91 | #ifdef DEBUG_KEXDH |
89 | dump_digest("hash", digest, EVP_MD_size(evp_md)); | 92 | dump_digest("hash", digest, *hashlen); |
90 | #endif | 93 | #endif |
91 | return digest; | ||
92 | } | 94 | } |
@@ -24,7 +24,7 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include "includes.h" | 26 | #include "includes.h" |
27 | RCSID("$OpenBSD: kexgexc.c,v 1.2 2003/12/08 11:00:47 markus Exp $"); | 27 | RCSID("$OpenBSD: kexgexc.c,v 1.3 2005/11/04 05:15:59 djm Exp $"); |
28 | 28 | ||
29 | #include "xmalloc.h" | 29 | #include "xmalloc.h" |
30 | #include "key.h" | 30 | #include "key.h" |
@@ -42,7 +42,7 @@ kexgex_client(Kex *kex) | |||
42 | BIGNUM *p = NULL, *g = NULL; | 42 | BIGNUM *p = NULL, *g = NULL; |
43 | Key *server_host_key; | 43 | Key *server_host_key; |
44 | u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; | 44 | u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; |
45 | u_int klen, kout, slen, sbloblen; | 45 | u_int klen, kout, slen, sbloblen, hashlen; |
46 | int min, max, nbits; | 46 | int min, max, nbits; |
47 | DH *dh; | 47 | DH *dh; |
48 | 48 | ||
@@ -155,7 +155,8 @@ kexgex_client(Kex *kex) | |||
155 | min = max = -1; | 155 | min = max = -1; |
156 | 156 | ||
157 | /* calc and verify H */ | 157 | /* calc and verify H */ |
158 | hash = kexgex_hash( | 158 | kexgex_hash( |
159 | kex->evp_md, | ||
159 | kex->client_version_string, | 160 | kex->client_version_string, |
160 | kex->server_version_string, | 161 | kex->server_version_string, |
161 | buffer_ptr(&kex->my), buffer_len(&kex->my), | 162 | buffer_ptr(&kex->my), buffer_len(&kex->my), |
@@ -165,25 +166,27 @@ kexgex_client(Kex *kex) | |||
165 | dh->p, dh->g, | 166 | dh->p, dh->g, |
166 | dh->pub_key, | 167 | dh->pub_key, |
167 | dh_server_pub, | 168 | dh_server_pub, |
168 | shared_secret | 169 | shared_secret, |
170 | &hash, &hashlen | ||
169 | ); | 171 | ); |
172 | |||
170 | /* have keys, free DH */ | 173 | /* have keys, free DH */ |
171 | DH_free(dh); | 174 | DH_free(dh); |
172 | xfree(server_host_key_blob); | 175 | xfree(server_host_key_blob); |
173 | BN_clear_free(dh_server_pub); | 176 | BN_clear_free(dh_server_pub); |
174 | 177 | ||
175 | if (key_verify(server_host_key, signature, slen, hash, 20) != 1) | 178 | if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1) |
176 | fatal("key_verify failed for server_host_key"); | 179 | fatal("key_verify failed for server_host_key"); |
177 | key_free(server_host_key); | 180 | key_free(server_host_key); |
178 | xfree(signature); | 181 | xfree(signature); |
179 | 182 | ||
180 | /* save session id */ | 183 | /* save session id */ |
181 | if (kex->session_id == NULL) { | 184 | if (kex->session_id == NULL) { |
182 | kex->session_id_len = 20; | 185 | kex->session_id_len = hashlen; |
183 | kex->session_id = xmalloc(kex->session_id_len); | 186 | kex->session_id = xmalloc(kex->session_id_len); |
184 | memcpy(kex->session_id, hash, kex->session_id_len); | 187 | memcpy(kex->session_id, hash, kex->session_id_len); |
185 | } | 188 | } |
186 | kex_derive_keys(kex, hash, shared_secret); | 189 | kex_derive_keys(kex, hash, hashlen, shared_secret); |
187 | BN_clear_free(shared_secret); | 190 | BN_clear_free(shared_secret); |
188 | 191 | ||
189 | kex_finish(kex); | 192 | kex_finish(kex); |
@@ -24,7 +24,7 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include "includes.h" | 26 | #include "includes.h" |
27 | RCSID("$OpenBSD: kexgexs.c,v 1.1 2003/02/16 17:09:57 markus Exp $"); | 27 | RCSID("$OpenBSD: kexgexs.c,v 1.2 2005/11/04 05:15:59 djm Exp $"); |
28 | 28 | ||
29 | #include "xmalloc.h" | 29 | #include "xmalloc.h" |
30 | #include "key.h" | 30 | #include "key.h" |
@@ -43,7 +43,7 @@ kexgex_server(Kex *kex) | |||
43 | Key *server_host_key; | 43 | Key *server_host_key; |
44 | DH *dh; | 44 | DH *dh; |
45 | u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; | 45 | u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; |
46 | u_int sbloblen, klen, kout, slen; | 46 | u_int sbloblen, klen, kout, slen, hashlen; |
47 | int min = -1, max = -1, nbits = -1, type; | 47 | int min = -1, max = -1, nbits = -1, type; |
48 | 48 | ||
49 | if (kex->load_host_key == NULL) | 49 | if (kex->load_host_key == NULL) |
@@ -137,8 +137,9 @@ kexgex_server(Kex *kex) | |||
137 | if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD) | 137 | if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD) |
138 | min = max = -1; | 138 | min = max = -1; |
139 | 139 | ||
140 | /* calc H */ /* XXX depends on 'kex' */ | 140 | /* calc H */ |
141 | hash = kexgex_hash( | 141 | kexgex_hash( |
142 | kex->evp_md, | ||
142 | kex->client_version_string, | 143 | kex->client_version_string, |
143 | kex->server_version_string, | 144 | kex->server_version_string, |
144 | buffer_ptr(&kex->peer), buffer_len(&kex->peer), | 145 | buffer_ptr(&kex->peer), buffer_len(&kex->peer), |
@@ -148,21 +149,20 @@ kexgex_server(Kex *kex) | |||
148 | dh->p, dh->g, | 149 | dh->p, dh->g, |
149 | dh_client_pub, | 150 | dh_client_pub, |
150 | dh->pub_key, | 151 | dh->pub_key, |
151 | shared_secret | 152 | shared_secret, |
153 | &hash, &hashlen | ||
152 | ); | 154 | ); |
153 | BN_clear_free(dh_client_pub); | 155 | BN_clear_free(dh_client_pub); |
154 | 156 | ||
155 | /* save session id := H */ | 157 | /* save session id := H */ |
156 | /* XXX hashlen depends on KEX */ | ||
157 | if (kex->session_id == NULL) { | 158 | if (kex->session_id == NULL) { |
158 | kex->session_id_len = 20; | 159 | kex->session_id_len = hashlen; |
159 | kex->session_id = xmalloc(kex->session_id_len); | 160 | kex->session_id = xmalloc(kex->session_id_len); |
160 | memcpy(kex->session_id, hash, kex->session_id_len); | 161 | memcpy(kex->session_id, hash, kex->session_id_len); |
161 | } | 162 | } |
162 | 163 | ||
163 | /* sign H */ | 164 | /* sign H */ |
164 | /* XXX hashlen depends on KEX */ | 165 | PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, hashlen)); |
165 | PRIVSEP(key_sign(server_host_key, &signature, &slen, hash, 20)); | ||
166 | 166 | ||
167 | /* destroy_sensitive_data(); */ | 167 | /* destroy_sensitive_data(); */ |
168 | 168 | ||
@@ -179,7 +179,7 @@ kexgex_server(Kex *kex) | |||
179 | /* have keys, free DH */ | 179 | /* have keys, free DH */ |
180 | DH_free(dh); | 180 | DH_free(dh); |
181 | 181 | ||
182 | kex_derive_keys(kex, hash, shared_secret); | 182 | kex_derive_keys(kex, hash, hashlen, shared_secret); |
183 | BN_clear_free(shared_secret); | 183 | BN_clear_free(shared_secret); |
184 | 184 | ||
185 | kex_finish(kex); | 185 | kex_finish(kex); |