diff options
Diffstat (limited to 'kex.c')
-rw-r--r-- | kex.c | 40 |
1 files changed, 24 insertions, 16 deletions
@@ -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 | ||
@@ -298,21 +298,27 @@ choose_kex(Kex *k, char *client, char *server) | |||
298 | fatal("no kex alg"); | 298 | fatal("no kex alg"); |
299 | if (strcmp(k->name, KEX_DH1) == 0) { | 299 | if (strcmp(k->name, KEX_DH1) == 0) { |
300 | k->kex_type = KEX_DH_GRP1_SHA1; | 300 | k->kex_type = KEX_DH_GRP1_SHA1; |
301 | k->evp_md = EVP_sha1(); | ||
301 | } else if (strcmp(k->name, KEX_DH14) == 0) { | 302 | } else if (strcmp(k->name, KEX_DH14) == 0) { |
302 | k->kex_type = KEX_DH_GRP14_SHA1; | 303 | k->kex_type = KEX_DH_GRP14_SHA1; |
303 | } else if (strcmp(k->name, KEX_DHGEX) == 0) { | 304 | k->evp_md = EVP_sha1(); |
305 | } else if (strcmp(k->name, KEX_DHGEX_SHA1) == 0) { | ||
304 | k->kex_type = KEX_DH_GEX_SHA1; | 306 | k->kex_type = KEX_DH_GEX_SHA1; |
307 | k->evp_md = EVP_sha1(); | ||
305 | #ifdef GSSAPI | 308 | #ifdef GSSAPI |
306 | } else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID, | 309 | } else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID, |
307 | sizeof(KEX_GSS_GEX_SHA1_ID)-1) == 0) { | 310 | sizeof(KEX_GSS_GEX_SHA1_ID)-1) == 0) { |
308 | k->kex_type = KEX_GSS_GEX_SHA1; | 311 | k->kex_type = KEX_GSS_GEX_SHA1; |
309 | } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID, | 312 | k->evp_md = EVP_sha1(); |
313 | } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID, | ||
310 | sizeof(KEX_GSS_GRP1_SHA1_ID)-1) == 0) { | 314 | sizeof(KEX_GSS_GRP1_SHA1_ID)-1) == 0) { |
311 | k->kex_type = KEX_GSS_GRP1_SHA1; | 315 | k->kex_type = KEX_GSS_GRP1_SHA1; |
316 | k->evp_md = EVP_sha1(); | ||
312 | #endif | 317 | #endif |
313 | } else | 318 | } else |
314 | fatal("bad kex alg %s", k->name); | 319 | fatal("bad kex alg %s", k->name); |
315 | } | 320 | } |
321 | |||
316 | static void | 322 | static void |
317 | choose_hostkeyalg(Kex *k, char *client, char *server) | 323 | choose_hostkeyalg(Kex *k, char *client, char *server) |
318 | { | 324 | { |
@@ -416,28 +422,28 @@ kex_choose_conf(Kex *kex) | |||
416 | } | 422 | } |
417 | 423 | ||
418 | static u_char * | 424 | static u_char * |
419 | derive_key(Kex *kex, int id, u_int need, u_char *hash, BIGNUM *shared_secret) | 425 | derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, |
426 | BIGNUM *shared_secret) | ||
420 | { | 427 | { |
421 | Buffer b; | 428 | Buffer b; |
422 | const EVP_MD *evp_md = EVP_sha1(); | ||
423 | EVP_MD_CTX md; | 429 | EVP_MD_CTX md; |
424 | char c = id; | 430 | char c = id; |
425 | u_int have; | 431 | u_int have; |
426 | int mdsz = EVP_MD_size(evp_md); | 432 | int mdsz; |
427 | u_char *digest; | 433 | u_char *digest; |
428 | 434 | ||
429 | if (mdsz < 0) | 435 | if ((mdsz = EVP_MD_size(kex->evp_md)) <= 0) |
430 | fatal("derive_key: mdsz < 0"); | 436 | fatal("bad kex md size %d", mdsz); |
431 | digest = xmalloc(roundup(need, mdsz)); | 437 | digest = xmalloc(roundup(need, mdsz)); |
432 | 438 | ||
433 | buffer_init(&b); | 439 | buffer_init(&b); |
434 | buffer_put_bignum2(&b, shared_secret); | 440 | buffer_put_bignum2(&b, shared_secret); |
435 | 441 | ||
436 | /* K1 = HASH(K || H || "A" || session_id) */ | 442 | /* K1 = HASH(K || H || "A" || session_id) */ |
437 | EVP_DigestInit(&md, evp_md); | 443 | EVP_DigestInit(&md, kex->evp_md); |
438 | if (!(datafellows & SSH_BUG_DERIVEKEY)) | 444 | if (!(datafellows & SSH_BUG_DERIVEKEY)) |
439 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); | 445 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); |
440 | EVP_DigestUpdate(&md, hash, mdsz); | 446 | EVP_DigestUpdate(&md, hash, hashlen); |
441 | EVP_DigestUpdate(&md, &c, 1); | 447 | EVP_DigestUpdate(&md, &c, 1); |
442 | EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); | 448 | EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); |
443 | EVP_DigestFinal(&md, digest, NULL); | 449 | EVP_DigestFinal(&md, digest, NULL); |
@@ -448,10 +454,10 @@ derive_key(Kex *kex, int id, u_int need, u_char *hash, BIGNUM *shared_secret) | |||
448 | * Key = K1 || K2 || ... || Kn | 454 | * Key = K1 || K2 || ... || Kn |
449 | */ | 455 | */ |
450 | for (have = mdsz; need > have; have += mdsz) { | 456 | for (have = mdsz; need > have; have += mdsz) { |
451 | EVP_DigestInit(&md, evp_md); | 457 | EVP_DigestInit(&md, kex->evp_md); |
452 | if (!(datafellows & SSH_BUG_DERIVEKEY)) | 458 | if (!(datafellows & SSH_BUG_DERIVEKEY)) |
453 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); | 459 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); |
454 | EVP_DigestUpdate(&md, hash, mdsz); | 460 | EVP_DigestUpdate(&md, hash, hashlen); |
455 | EVP_DigestUpdate(&md, digest, have); | 461 | EVP_DigestUpdate(&md, digest, have); |
456 | EVP_DigestFinal(&md, digest + have, NULL); | 462 | EVP_DigestFinal(&md, digest + have, NULL); |
457 | } | 463 | } |
@@ -467,13 +473,15 @@ Newkeys *current_keys[MODE_MAX]; | |||
467 | 473 | ||
468 | #define NKEYS 6 | 474 | #define NKEYS 6 |
469 | void | 475 | void |
470 | kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret) | 476 | kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, BIGNUM *shared_secret) |
471 | { | 477 | { |
472 | u_char *keys[NKEYS]; | 478 | u_char *keys[NKEYS]; |
473 | u_int i, mode, ctos; | 479 | u_int i, mode, ctos; |
474 | 480 | ||
475 | for (i = 0; i < NKEYS; i++) | 481 | for (i = 0; i < NKEYS; i++) { |
476 | keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, shared_secret); | 482 | keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, hashlen, |
483 | shared_secret); | ||
484 | } | ||
477 | 485 | ||
478 | debug2("kex_derive_keys"); | 486 | debug2("kex_derive_keys"); |
479 | for (mode = 0; mode < MODE_MAX; mode++) { | 487 | for (mode = 0; mode < MODE_MAX; mode++) { |