diff options
Diffstat (limited to 'kex.c')
-rw-r--r-- | kex.c | 94 |
1 files changed, 53 insertions, 41 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.c,v 1.93 2013/11/07 11:58:27 dtucker Exp $ */ | 1 | /* $OpenBSD: kex.c,v 1.94 2014/01/09 23:20:00 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 | * |
@@ -49,6 +49,7 @@ | |||
49 | #include "dispatch.h" | 49 | #include "dispatch.h" |
50 | #include "monitor.h" | 50 | #include "monitor.h" |
51 | #include "roaming.h" | 51 | #include "roaming.h" |
52 | #include "digest.h" | ||
52 | 53 | ||
53 | #if OPENSSL_VERSION_NUMBER >= 0x00907000L | 54 | #if OPENSSL_VERSION_NUMBER >= 0x00907000L |
54 | # if defined(HAVE_EVP_SHA256) | 55 | # if defined(HAVE_EVP_SHA256) |
@@ -66,26 +67,30 @@ struct kexalg { | |||
66 | char *name; | 67 | char *name; |
67 | int type; | 68 | int type; |
68 | int ec_nid; | 69 | int ec_nid; |
69 | const EVP_MD *(*mdfunc)(void); | 70 | int hash_alg; |
70 | }; | 71 | }; |
71 | static const struct kexalg kexalgs[] = { | 72 | static const struct kexalg kexalgs[] = { |
72 | { KEX_DH1, KEX_DH_GRP1_SHA1, 0, EVP_sha1 }, | 73 | { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, |
73 | { KEX_DH14, KEX_DH_GRP14_SHA1, 0, EVP_sha1 }, | 74 | { KEX_DH14, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, |
74 | { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, EVP_sha1 }, | 75 | { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, |
75 | #ifdef HAVE_EVP_SHA256 | 76 | #ifdef HAVE_EVP_SHA256 |
76 | { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, EVP_sha256 }, | 77 | { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, |
77 | #endif | 78 | #endif |
78 | #ifdef OPENSSL_HAS_ECC | 79 | #ifdef OPENSSL_HAS_ECC |
79 | { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, NID_X9_62_prime256v1, EVP_sha256 }, | 80 | { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, |
80 | { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, EVP_sha384 }, | 81 | NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, |
82 | { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, | ||
83 | SSH_DIGEST_SHA384 }, | ||
81 | # ifdef OPENSSL_HAS_NISTP521 | 84 | # ifdef OPENSSL_HAS_NISTP521 |
82 | { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, EVP_sha512 }, | 85 | { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, |
86 | SSH_DIGEST_SHA512 }, | ||
83 | # endif | 87 | # endif |
84 | #endif | 88 | #endif |
89 | { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, | ||
85 | #ifdef HAVE_EVP_SHA256 | 90 | #ifdef HAVE_EVP_SHA256 |
86 | { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, EVP_sha256 }, | 91 | { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, |
87 | #endif | 92 | #endif |
88 | { NULL, -1, -1, NULL}, | 93 | { NULL, -1, -1, -1}, |
89 | }; | 94 | }; |
90 | 95 | ||
91 | char * | 96 | char * |
@@ -406,7 +411,7 @@ choose_kex(Kex *k, char *client, char *server) | |||
406 | if ((kexalg = kex_alg_by_name(k->name)) == NULL) | 411 | if ((kexalg = kex_alg_by_name(k->name)) == NULL) |
407 | fatal("unsupported kex alg %s", k->name); | 412 | fatal("unsupported kex alg %s", k->name); |
408 | k->kex_type = kexalg->type; | 413 | k->kex_type = kexalg->type; |
409 | k->evp_md = kexalg->mdfunc(); | 414 | k->hash_alg = kexalg->hash_alg; |
410 | k->ec_nid = kexalg->ec_nid; | 415 | k->ec_nid = kexalg->ec_nid; |
411 | } | 416 | } |
412 | 417 | ||
@@ -532,27 +537,31 @@ derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, | |||
532 | BIGNUM *shared_secret) | 537 | BIGNUM *shared_secret) |
533 | { | 538 | { |
534 | Buffer b; | 539 | Buffer b; |
535 | EVP_MD_CTX md; | 540 | struct ssh_digest_ctx *hashctx; |
536 | char c = id; | 541 | char c = id; |
537 | u_int have; | 542 | u_int have; |
538 | int mdsz; | 543 | size_t mdsz; |
539 | u_char *digest; | 544 | u_char *digest; |
540 | 545 | ||
541 | if ((mdsz = EVP_MD_size(kex->evp_md)) <= 0) | 546 | if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0) |
542 | fatal("bad kex md size %d", mdsz); | 547 | fatal("bad kex md size %zu", mdsz); |
543 | digest = xmalloc(roundup(need, mdsz)); | 548 | digest = xmalloc(roundup(need, mdsz)); |
544 | 549 | ||
545 | buffer_init(&b); | 550 | buffer_init(&b); |
546 | buffer_put_bignum2(&b, shared_secret); | 551 | buffer_put_bignum2(&b, shared_secret); |
547 | 552 | ||
548 | /* K1 = HASH(K || H || "A" || session_id) */ | 553 | /* K1 = HASH(K || H || "A" || session_id) */ |
549 | EVP_DigestInit(&md, kex->evp_md); | 554 | if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) |
550 | if (!(datafellows & SSH_BUG_DERIVEKEY)) | 555 | fatal("%s: ssh_digest_start failed", __func__); |
551 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); | 556 | if (ssh_digest_update_buffer(hashctx, &b) != 0 || |
552 | EVP_DigestUpdate(&md, hash, hashlen); | 557 | ssh_digest_update(hashctx, hash, hashlen) != 0 || |
553 | EVP_DigestUpdate(&md, &c, 1); | 558 | ssh_digest_update(hashctx, &c, 1) != 0 || |
554 | EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); | 559 | ssh_digest_update(hashctx, kex->session_id, |
555 | EVP_DigestFinal(&md, digest, NULL); | 560 | kex->session_id_len) != 0) |
561 | fatal("%s: ssh_digest_update failed", __func__); | ||
562 | if (ssh_digest_final(hashctx, digest, mdsz) != 0) | ||
563 | fatal("%s: ssh_digest_final failed", __func__); | ||
564 | ssh_digest_free(hashctx); | ||
556 | 565 | ||
557 | /* | 566 | /* |
558 | * expand key: | 567 | * expand key: |
@@ -560,12 +569,15 @@ derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, | |||
560 | * Key = K1 || K2 || ... || Kn | 569 | * Key = K1 || K2 || ... || Kn |
561 | */ | 570 | */ |
562 | for (have = mdsz; need > have; have += mdsz) { | 571 | for (have = mdsz; need > have; have += mdsz) { |
563 | EVP_DigestInit(&md, kex->evp_md); | 572 | if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) |
564 | if (!(datafellows & SSH_BUG_DERIVEKEY)) | 573 | fatal("%s: ssh_digest_start failed", __func__); |
565 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); | 574 | if (ssh_digest_update_buffer(hashctx, &b) != 0 || |
566 | EVP_DigestUpdate(&md, hash, hashlen); | 575 | ssh_digest_update(hashctx, hash, hashlen) != 0 || |
567 | EVP_DigestUpdate(&md, digest, have); | 576 | ssh_digest_update(hashctx, digest, have) != 0) |
568 | EVP_DigestFinal(&md, digest + have, NULL); | 577 | fatal("%s: ssh_digest_update failed", __func__); |
578 | if (ssh_digest_final(hashctx, digest + have, mdsz) != 0) | ||
579 | fatal("%s: ssh_digest_final failed", __func__); | ||
580 | ssh_digest_free(hashctx); | ||
569 | } | 581 | } |
570 | buffer_free(&b); | 582 | buffer_free(&b); |
571 | #ifdef DEBUG_KEX | 583 | #ifdef DEBUG_KEX |
@@ -615,33 +627,33 @@ void | |||
615 | derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, | 627 | derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, |
616 | u_int8_t cookie[8], u_int8_t id[16]) | 628 | u_int8_t cookie[8], u_int8_t id[16]) |
617 | { | 629 | { |
618 | const EVP_MD *evp_md = EVP_md5(); | 630 | u_int8_t nbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH]; |
619 | EVP_MD_CTX md; | ||
620 | u_int8_t nbuf[2048], obuf[EVP_MAX_MD_SIZE]; | ||
621 | int len; | 631 | int len; |
632 | struct ssh_digest_ctx *hashctx; | ||
622 | 633 | ||
623 | EVP_DigestInit(&md, evp_md); | 634 | if ((hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL) |
635 | fatal("%s: ssh_digest_start", __func__); | ||
624 | 636 | ||
625 | len = BN_num_bytes(host_modulus); | 637 | len = BN_num_bytes(host_modulus); |
626 | if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) | 638 | if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) |
627 | fatal("%s: bad host modulus (len %d)", __func__, len); | 639 | fatal("%s: bad host modulus (len %d)", __func__, len); |
628 | BN_bn2bin(host_modulus, nbuf); | 640 | BN_bn2bin(host_modulus, nbuf); |
629 | EVP_DigestUpdate(&md, nbuf, len); | 641 | if (ssh_digest_update(hashctx, nbuf, len) != 0) |
642 | fatal("%s: ssh_digest_update failed", __func__); | ||
630 | 643 | ||
631 | len = BN_num_bytes(server_modulus); | 644 | len = BN_num_bytes(server_modulus); |
632 | if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) | 645 | if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) |
633 | fatal("%s: bad server modulus (len %d)", __func__, len); | 646 | fatal("%s: bad server modulus (len %d)", __func__, len); |
634 | BN_bn2bin(server_modulus, nbuf); | 647 | BN_bn2bin(server_modulus, nbuf); |
635 | EVP_DigestUpdate(&md, nbuf, len); | 648 | if (ssh_digest_update(hashctx, nbuf, len) != 0 || |
636 | 649 | ssh_digest_update(hashctx, cookie, 8) != 0) | |
637 | EVP_DigestUpdate(&md, cookie, 8); | 650 | fatal("%s: ssh_digest_update failed", __func__); |
638 | 651 | if (ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0) | |
639 | EVP_DigestFinal(&md, obuf, NULL); | 652 | fatal("%s: ssh_digest_final failed", __func__); |
640 | memcpy(id, obuf, 16); | 653 | memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5)); |
641 | 654 | ||
642 | memset(nbuf, 0, sizeof(nbuf)); | 655 | memset(nbuf, 0, sizeof(nbuf)); |
643 | memset(obuf, 0, sizeof(obuf)); | 656 | memset(obuf, 0, sizeof(obuf)); |
644 | memset(&md, 0, sizeof(md)); | ||
645 | } | 657 | } |
646 | 658 | ||
647 | #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) | 659 | #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) |