diff options
author | Damien Miller <djm@mindrot.org> | 2014-01-10 10:58:53 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2014-01-10 10:58:53 +1100 |
commit | b3051d01e505c9c2dc00faab472a0d06fa6b0e65 (patch) | |
tree | c0ca49b5fc4e5e1a066157b4dbd9c68cfcd41d63 /kex.c | |
parent | e00e413dd16eb747fb2c15a099971d91c13cf70f (diff) | |
download | openssh-git-b3051d01e505c9c2dc00faab472a0d06fa6b0e65.tar.gz |
- djm@cvs.openbsd.org 2014/01/09 23:20:00
[digest.c digest.h hostfile.c kex.c kex.h kexc25519.c kexc25519c.c]
[kexc25519s.c kexdh.c kexecdh.c kexecdhc.c kexecdhs.c kexgex.c kexgexc.c]
[kexgexs.c key.c key.h roaming_client.c roaming_common.c schnorr.c]
[schnorr.h ssh-dss.c ssh-ecdsa.c ssh-rsa.c sshconnect2.c]
Introduce digest API and use it to perform all hashing operations
rather than calling OpenSSL EVP_Digest* directly. Will make it easier
to build a reduced-feature OpenSSH without OpenSSL in future;
feedback, ok markus@
Diffstat (limited to 'kex.c')
-rw-r--r-- | kex.c | 94 |
1 files changed, 53 insertions, 41 deletions
@@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.93 2013/11/07 11:58:27 dtucker Exp $ */ +/* $OpenBSD: kex.c,v 1.94 2014/01/09 23:20:00 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -49,6 +49,7 @@ #include "dispatch.h" #include "monitor.h" #include "roaming.h" +#include "digest.h" #if OPENSSL_VERSION_NUMBER >= 0x00907000L # if defined(HAVE_EVP_SHA256) @@ -66,26 +67,30 @@ struct kexalg { char *name; int type; int ec_nid; - const EVP_MD *(*mdfunc)(void); + int hash_alg; }; static const struct kexalg kexalgs[] = { - { KEX_DH1, KEX_DH_GRP1_SHA1, 0, EVP_sha1 }, - { KEX_DH14, KEX_DH_GRP14_SHA1, 0, EVP_sha1 }, - { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, EVP_sha1 }, + { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, + { KEX_DH14, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, + { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, #ifdef HAVE_EVP_SHA256 - { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, EVP_sha256 }, + { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, #endif #ifdef OPENSSL_HAS_ECC - { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, NID_X9_62_prime256v1, EVP_sha256 }, - { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, EVP_sha384 }, + { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, + NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, + { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, + SSH_DIGEST_SHA384 }, # ifdef OPENSSL_HAS_NISTP521 - { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, EVP_sha512 }, + { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, + SSH_DIGEST_SHA512 }, # endif #endif + { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, #ifdef HAVE_EVP_SHA256 - { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, EVP_sha256 }, + { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, #endif - { NULL, -1, -1, NULL}, + { NULL, -1, -1, -1}, }; char * @@ -406,7 +411,7 @@ choose_kex(Kex *k, char *client, char *server) if ((kexalg = kex_alg_by_name(k->name)) == NULL) fatal("unsupported kex alg %s", k->name); k->kex_type = kexalg->type; - k->evp_md = kexalg->mdfunc(); + k->hash_alg = kexalg->hash_alg; k->ec_nid = kexalg->ec_nid; } @@ -532,27 +537,31 @@ derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, BIGNUM *shared_secret) { Buffer b; - EVP_MD_CTX md; + struct ssh_digest_ctx *hashctx; char c = id; u_int have; - int mdsz; + size_t mdsz; u_char *digest; - if ((mdsz = EVP_MD_size(kex->evp_md)) <= 0) - fatal("bad kex md size %d", mdsz); + if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0) + fatal("bad kex md size %zu", mdsz); digest = xmalloc(roundup(need, mdsz)); buffer_init(&b); buffer_put_bignum2(&b, shared_secret); /* K1 = HASH(K || H || "A" || session_id) */ - EVP_DigestInit(&md, kex->evp_md); - if (!(datafellows & SSH_BUG_DERIVEKEY)) - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); - EVP_DigestUpdate(&md, hash, hashlen); - EVP_DigestUpdate(&md, &c, 1); - EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len); - EVP_DigestFinal(&md, digest, NULL); + if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) + fatal("%s: ssh_digest_start failed", __func__); + if (ssh_digest_update_buffer(hashctx, &b) != 0 || + ssh_digest_update(hashctx, hash, hashlen) != 0 || + ssh_digest_update(hashctx, &c, 1) != 0 || + ssh_digest_update(hashctx, kex->session_id, + kex->session_id_len) != 0) + fatal("%s: ssh_digest_update failed", __func__); + if (ssh_digest_final(hashctx, digest, mdsz) != 0) + fatal("%s: ssh_digest_final failed", __func__); + ssh_digest_free(hashctx); /* * expand key: @@ -560,12 +569,15 @@ derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, * Key = K1 || K2 || ... || Kn */ for (have = mdsz; need > have; have += mdsz) { - EVP_DigestInit(&md, kex->evp_md); - if (!(datafellows & SSH_BUG_DERIVEKEY)) - EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); - EVP_DigestUpdate(&md, hash, hashlen); - EVP_DigestUpdate(&md, digest, have); - EVP_DigestFinal(&md, digest + have, NULL); + if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) + fatal("%s: ssh_digest_start failed", __func__); + if (ssh_digest_update_buffer(hashctx, &b) != 0 || + ssh_digest_update(hashctx, hash, hashlen) != 0 || + ssh_digest_update(hashctx, digest, have) != 0) + fatal("%s: ssh_digest_update failed", __func__); + if (ssh_digest_final(hashctx, digest + have, mdsz) != 0) + fatal("%s: ssh_digest_final failed", __func__); + ssh_digest_free(hashctx); } buffer_free(&b); #ifdef DEBUG_KEX @@ -615,33 +627,33 @@ void derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, u_int8_t cookie[8], u_int8_t id[16]) { - const EVP_MD *evp_md = EVP_md5(); - EVP_MD_CTX md; - u_int8_t nbuf[2048], obuf[EVP_MAX_MD_SIZE]; + u_int8_t nbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH]; int len; + struct ssh_digest_ctx *hashctx; - EVP_DigestInit(&md, evp_md); + if ((hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL) + fatal("%s: ssh_digest_start", __func__); len = BN_num_bytes(host_modulus); if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) fatal("%s: bad host modulus (len %d)", __func__, len); BN_bn2bin(host_modulus, nbuf); - EVP_DigestUpdate(&md, nbuf, len); + if (ssh_digest_update(hashctx, nbuf, len) != 0) + fatal("%s: ssh_digest_update failed", __func__); len = BN_num_bytes(server_modulus); if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) fatal("%s: bad server modulus (len %d)", __func__, len); BN_bn2bin(server_modulus, nbuf); - EVP_DigestUpdate(&md, nbuf, len); - - EVP_DigestUpdate(&md, cookie, 8); - - EVP_DigestFinal(&md, obuf, NULL); - memcpy(id, obuf, 16); + if (ssh_digest_update(hashctx, nbuf, len) != 0 || + ssh_digest_update(hashctx, cookie, 8) != 0) + fatal("%s: ssh_digest_update failed", __func__); + if (ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0) + fatal("%s: ssh_digest_final failed", __func__); + memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5)); memset(nbuf, 0, sizeof(nbuf)); memset(obuf, 0, sizeof(obuf)); - memset(&md, 0, sizeof(md)); } #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) |