upstream: factor out kex_dh_compute_key() - it's shared between

plain DH KEX and DH GEX in both the client and server implementations

from markus@ ok djm@

OpenBSD-Commit-ID: 12186e18791fffcd4642c82e7e0cfdd7ea37e2ec
diff --git a/kex.h b/kex.h
index 4394e10..a11bd5a 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.h,v 1.95 2019/01/21 10:00:23 djm Exp $ */
+/* $OpenBSD: kex.h,v 1.96 2019/01/21 10:03:37 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -203,15 +203,16 @@
 int	 kexc25519_server(struct ssh *);
 
 int	 kex_dh_keygen(struct kex *);
+int	 kex_dh_compute_key(struct kex *, BIGNUM *, struct sshbuf *);
 int	 kex_dh_hash(int, const struct sshbuf *, const struct sshbuf *,
     const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
-    const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *);
+    const BIGNUM *, const BIGNUM *, const u_char *, size_t, u_char *, size_t *);
 
 int	 kexgex_hash(int, const struct sshbuf *, const struct sshbuf *,
     const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
     int, int, int,
     const BIGNUM *, const BIGNUM *, const BIGNUM *,
-    const BIGNUM *, const BIGNUM *,
+    const BIGNUM *, const u_char *, size_t,
     u_char *, size_t *);
 
 int kex_ecdh_hash(int, const EC_GROUP *,
diff --git a/kexdh.c b/kexdh.c
index 9160369..5324857 100644
--- a/kexdh.c
+++ b/kexdh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexdh.c,v 1.28 2019/01/21 10:00:23 djm Exp $ */
+/* $OpenBSD: kexdh.c,v 1.29 2019/01/21 10:03:37 djm Exp $ */
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
  *
@@ -43,6 +43,7 @@
 #include "ssherr.h"
 #include "sshbuf.h"
 #include "digest.h"
+#include "dh.h"
 
 int
 kex_dh_keygen(struct kex *kex)
@@ -70,6 +71,48 @@
 }
 
 int
+kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out)
+{
+	BIGNUM *shared_secret = NULL;
+	u_char *kbuf = NULL;
+	size_t klen = 0;
+	int kout, r;
+
+#ifdef DEBUG_KEXDH
+	fprintf(stderr, "dh_pub= ");
+	BN_print_fp(stderr, dh_pub);
+	fprintf(stderr, "\n");
+	debug("bits %d", BN_num_bits(dh_pub));
+	DHparams_print_fp(stderr, kex->dh);
+	fprintf(stderr, "\n");
+#endif
+
+	if (!dh_pub_is_valid(kex->dh, dh_pub)) {
+		r = SSH_ERR_MESSAGE_INCOMPLETE;
+		goto out;
+	}
+	klen = DH_size(kex->dh);
+	if ((kbuf = malloc(klen)) == NULL ||
+	    (shared_secret = BN_new()) == NULL) {
+		r = SSH_ERR_ALLOC_FAIL;
+		goto out;
+	}
+	if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 ||
+	    BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
+		r = SSH_ERR_LIBCRYPTO_ERROR;
+		goto out;
+	}
+#ifdef DEBUG_KEXDH
+	dump_digest("shared secret", kbuf, kout);
+#endif
+	r = sshbuf_put_bignum2(out, shared_secret);
+ out:
+	freezero(kbuf, klen);
+	BN_clear_free(shared_secret);
+	return r;
+}
+
+int
 kex_dh_hash(
     int hash_alg,
     const struct sshbuf *client_version,
@@ -79,7 +122,7 @@
     const u_char *serverhostkeyblob, size_t sbloblen,
     const BIGNUM *client_dh_pub,
     const BIGNUM *server_dh_pub,
-    const BIGNUM *shared_secret,
+    const u_char *shared_secret, size_t secretlen,
     u_char *hash, size_t *hashlen)
 {
 	struct sshbuf *b;
@@ -101,7 +144,7 @@
 	    (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
 	    (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 ||
 	    (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 ||
-	    (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
+	    (r = sshbuf_put(b, shared_secret, secretlen)) != 0) {
 		sshbuf_free(b);
 		return r;
 	}
diff --git a/kexdhc.c b/kexdhc.c
index a7ea0ba..2e26f22 100644
--- a/kexdhc.c
+++ b/kexdhc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexdhc.c,v 1.27 2019/01/21 10:00:23 djm Exp $ */
+/* $OpenBSD: kexdhc.c,v 1.28 2019/01/21 10:03:37 djm Exp $ */
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
  *
@@ -86,13 +86,14 @@
 input_kex_dh(int type, u_int32_t seq, struct ssh *ssh)
 {
 	struct kex *kex = ssh->kex;
-	BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
+	BIGNUM *dh_server_pub = NULL;
 	const BIGNUM *pub_key;
 	struct sshkey *server_host_key = NULL;
-	u_char *kbuf = NULL, *server_host_key_blob = NULL, *signature = NULL;
+	struct sshbuf *shared_secret = NULL;
+	u_char *server_host_key_blob = NULL, *signature = NULL;
 	u_char hash[SSH_DIGEST_MAX_LENGTH];
-	size_t klen = 0, slen, sbloblen, hashlen;
-	int kout, r;
+	size_t slen, sbloblen, hashlen;
+	int r;
 
 	if (kex->verify_host_key == NULL) {
 		r = SSH_ERR_INVALID_ARGUMENT;
@@ -119,32 +120,12 @@
 	    (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
 	    (r = sshpkt_get_end(ssh)) != 0)
 		goto out;
-#ifdef DEBUG_KEXDH
-	fprintf(stderr, "dh_server_pub= ");
-	BN_print_fp(stderr, dh_server_pub);
-	fprintf(stderr, "\n");
-	debug("bits %d", BN_num_bits(dh_server_pub));
-#endif
-	if (!dh_pub_is_valid(kex->dh, dh_server_pub)) {
-		sshpkt_disconnect(ssh, "bad server public DH value");
-		r = SSH_ERR_MESSAGE_INCOMPLETE;
-		goto out;
-	}
-
-	klen = DH_size(kex->dh);
-	if ((kbuf = malloc(klen)) == NULL ||
-	    (shared_secret = BN_new()) == NULL) {
+	if ((shared_secret = sshbuf_new()) == NULL) {
 		r = SSH_ERR_ALLOC_FAIL;
 		goto out;
 	}
-	if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0 ||
-	    BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
-		r = SSH_ERR_LIBCRYPTO_ERROR;
+	if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0)
 		goto out;
-	}
-#ifdef DEBUG_KEXDH
-	dump_digest("shared secret", kbuf, kout);
-#endif
 
 	/* calc and verify H */
 	DH_get0_key(kex->dh, &pub_key, NULL);
@@ -158,7 +139,7 @@
 	    server_host_key_blob, sbloblen,
 	    pub_key,
 	    dh_server_pub,
-	    shared_secret,
+	    sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
 	    hash, &hashlen)) != 0)
 		goto out;
 
@@ -166,18 +147,14 @@
 	    kex->hostkey_alg, ssh->compat)) != 0)
 		goto out;
 
-	if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
+	if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
 		r = kex_send_newkeys(ssh);
  out:
 	explicit_bzero(hash, sizeof(hash));
 	DH_free(kex->dh);
 	kex->dh = NULL;
 	BN_clear_free(dh_server_pub);
-	if (kbuf) {
-		explicit_bzero(kbuf, klen);
-		free(kbuf);
-	}
-	BN_clear_free(shared_secret);
+	sshbuf_free(shared_secret);
 	sshkey_free(server_host_key);
 	free(server_host_key_blob);
 	free(signature);
diff --git a/kexdhs.c b/kexdhs.c
index cd2e52e..0f028aa 100644
--- a/kexdhs.c
+++ b/kexdhs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexdhs.c,v 1.33 2019/01/21 10:00:23 djm Exp $ */
+/* $OpenBSD: kexdhs.c,v 1.34 2019/01/21 10:03:37 djm Exp $ */
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
  *
@@ -71,14 +71,15 @@
 input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh)
 {
 	struct kex *kex = ssh->kex;
-	BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
+	BIGNUM *dh_client_pub = NULL;
 	const BIGNUM *pub_key;
 	struct sshkey *server_host_public, *server_host_private;
-	u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL;
+	struct sshbuf *shared_secret = NULL;
+	u_char *signature = NULL, *server_host_key_blob = NULL;
 	u_char hash[SSH_DIGEST_MAX_LENGTH];
 	size_t sbloblen, slen;
-	size_t klen = 0, hashlen;
-	int kout, r;
+	size_t hashlen;
+	int r;
 
 	if (kex->load_host_public_key == NULL ||
 	    kex->load_host_private_key == NULL) {
@@ -98,42 +99,17 @@
 	if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 ||
 	    (r = sshpkt_get_end(ssh)) != 0)
 		goto out;
-	DH_get0_key(kex->dh, &pub_key, NULL);
-
-#ifdef DEBUG_KEXDH
-	fprintf(stderr, "dh_client_pub= ");
-	BN_print_fp(stderr, dh_client_pub);
-	fprintf(stderr, "\n");
-	debug("bits %d", BN_num_bits(dh_client_pub));
-	DHparams_print_fp(stderr, kex->dh);
-	fprintf(stderr, "pub= ");
-	BN_print_fp(stderr, pub_key);
-	fprintf(stderr, "\n");
-#endif
-	if (!dh_pub_is_valid(kex->dh, dh_client_pub)) {
-		sshpkt_disconnect(ssh, "bad client public DH value");
-		r = SSH_ERR_MESSAGE_INCOMPLETE;
-		goto out;
-	}
-
-	klen = DH_size(kex->dh);
-	if ((kbuf = malloc(klen)) == NULL ||
-	    (shared_secret = BN_new()) == NULL) {
+	if ((shared_secret = sshbuf_new()) == NULL) {
 		r = SSH_ERR_ALLOC_FAIL;
 		goto out;
 	}
-	if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 ||
-	    BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
-		r = SSH_ERR_LIBCRYPTO_ERROR;
+	if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0)
 		goto out;
-	}
-#ifdef DEBUG_KEXDH
-	dump_digest("shared secret", kbuf, kout);
-#endif
 	if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
 	    &sbloblen)) != 0)
 		goto out;
 	/* calc H */
+	DH_get0_key(kex->dh, &pub_key, NULL);
 	hashlen = sizeof(hash);
 	if ((r = kex_dh_hash(
 	    kex->hash_alg,
@@ -144,7 +120,7 @@
 	    server_host_key_blob, sbloblen,
 	    dh_client_pub,
 	    pub_key,
-	    shared_secret,
+	    sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
 	    hash, &hashlen)) != 0)
 		goto out;
 
@@ -153,8 +129,6 @@
 	    &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0)
 		goto out;
 
-	/* destroy_sensitive_data(); */
-
 	/* send server hostkey, DH pubkey 'f' and signed H */
 	if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 ||
 	    (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
@@ -163,18 +137,14 @@
 	    (r = sshpkt_send(ssh)) != 0)
 		goto out;
 
-	if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
+	if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
 		r = kex_send_newkeys(ssh);
  out:
 	explicit_bzero(hash, sizeof(hash));
 	DH_free(kex->dh);
 	kex->dh = NULL;
 	BN_clear_free(dh_client_pub);
-	if (kbuf) {
-		explicit_bzero(kbuf, klen);
-		free(kbuf);
-	}
-	BN_clear_free(shared_secret);
+	sshbuf_free(shared_secret);
 	free(server_host_key_blob);
 	free(signature);
 	return r;
diff --git a/kexgex.c b/kexgex.c
index a5d591b..f828f2b 100644
--- a/kexgex.c
+++ b/kexgex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgex.c,v 1.30 2018/12/27 03:25:25 djm Exp $ */
+/* $OpenBSD: kexgex.c,v 1.31 2019/01/21 10:03:37 djm Exp $ */
 /*
  * Copyright (c) 2000 Niels Provos.  All rights reserved.
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -56,7 +56,7 @@
     const BIGNUM *gen,
     const BIGNUM *client_dh_pub,
     const BIGNUM *server_dh_pub,
-    const BIGNUM *shared_secret,
+    const u_char *shared_secret, size_t secretlen,
     u_char *hash, size_t *hashlen)
 {
 	struct sshbuf *b;
@@ -83,7 +83,7 @@
 	    (r = sshbuf_put_bignum2(b, gen)) != 0 ||
 	    (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 ||
 	    (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 ||
-	    (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
+	    (r = sshbuf_put(b, shared_secret, secretlen)) != 0) {
 		sshbuf_free(b);
 		return r;
 	}
diff --git a/kexgexc.c b/kexgexc.c
index 0425309..600d91a 100644
--- a/kexgexc.c
+++ b/kexgexc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgexc.c,v 1.31 2019/01/21 09:55:52 djm Exp $ */
+/* $OpenBSD: kexgexc.c,v 1.32 2019/01/21 10:03:37 djm Exp $ */
 /*
  * Copyright (c) 2000 Niels Provos.  All rights reserved.
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -143,13 +143,14 @@
 input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
 {
 	struct kex *kex = ssh->kex;
-	BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
+	BIGNUM *dh_server_pub = NULL;
 	const BIGNUM *pub_key, *dh_p, *dh_g;
+	struct sshbuf *shared_secret = NULL;
 	struct sshkey *server_host_key = NULL;
-	u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL;
+	u_char *signature = NULL, *server_host_key_blob = NULL;
 	u_char hash[SSH_DIGEST_MAX_LENGTH];
-	size_t klen = 0, slen, sbloblen, hashlen;
-	int kout, r;
+	size_t slen, sbloblen, hashlen;
+	int r;
 
 	debug("got SSH2_MSG_KEX_DH_GEX_REPLY");
 	if (kex->verify_host_key == NULL) {
@@ -177,32 +178,12 @@
 	    (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
 	    (r = sshpkt_get_end(ssh)) != 0)
 		goto out;
-#ifdef DEBUG_KEXDH
-	fprintf(stderr, "dh_server_pub= ");
-	BN_print_fp(stderr, dh_server_pub);
-	fprintf(stderr, "\n");
-	debug("bits %d", BN_num_bits(dh_server_pub));
-#endif
-	if (!dh_pub_is_valid(kex->dh, dh_server_pub)) {
-		sshpkt_disconnect(ssh, "bad server public DH value");
-		r = SSH_ERR_MESSAGE_INCOMPLETE;
-		goto out;
-	}
-
-	klen = DH_size(kex->dh);
-	if ((kbuf = malloc(klen)) == NULL ||
-	    (shared_secret = BN_new()) == NULL) {
+	if ((shared_secret = sshbuf_new()) == NULL) {
 		r = SSH_ERR_ALLOC_FAIL;
 		goto out;
 	}
-	if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0 ||
-	    BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
-		r = SSH_ERR_LIBCRYPTO_ERROR;
+	if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0)
 		goto out;
-	}
-#ifdef DEBUG_KEXDH
-	dump_digest("shared secret", kbuf, kout);
-#endif
 	if (ssh->compat & SSH_OLD_DHGEX)
 		kex->min = kex->max = -1;
 
@@ -221,7 +202,7 @@
 	    dh_p, dh_g,
 	    pub_key,
 	    dh_server_pub,
-	    shared_secret,
+	    sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
 	    hash, &hashlen)) != 0)
 		goto out;
 
@@ -229,18 +210,14 @@
 	    hashlen, kex->hostkey_alg, ssh->compat)) != 0)
 		goto out;
 
-	if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
+	if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
 		r = kex_send_newkeys(ssh);
  out:
 	explicit_bzero(hash, sizeof(hash));
 	DH_free(kex->dh);
 	kex->dh = NULL;
 	BN_clear_free(dh_server_pub);
-	if (kbuf) {
-		explicit_bzero(kbuf, klen);
-		free(kbuf);
-	}
-	BN_clear_free(shared_secret);
+	sshbuf_free(shared_secret);
 	sshkey_free(server_host_key);
 	free(server_host_key_blob);
 	free(signature);
diff --git a/kexgexs.c b/kexgexs.c
index 4ffbb19..f8eb365 100644
--- a/kexgexs.c
+++ b/kexgexs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgexs.c,v 1.39 2019/01/21 09:55:52 djm Exp $ */
+/* $OpenBSD: kexgexs.c,v 1.40 2019/01/21 10:03:37 djm Exp $ */
 /*
  * Copyright (c) 2000 Niels Provos.  All rights reserved.
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -126,14 +126,15 @@
 input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
 {
 	struct kex *kex = ssh->kex;
-	BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
+	BIGNUM *dh_client_pub = NULL;
 	const BIGNUM *pub_key, *dh_p, *dh_g;
+	struct sshbuf *shared_secret = NULL;
 	struct sshkey *server_host_public, *server_host_private;
-	u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL;
+	u_char *signature = NULL, *server_host_key_blob = NULL;
 	u_char hash[SSH_DIGEST_MAX_LENGTH];
 	size_t sbloblen, slen;
-	size_t klen = 0, hashlen;
-	int kout, r;
+	size_t hashlen;
+	int r;
 
 	if (kex->load_host_public_key == NULL ||
 	    kex->load_host_private_key == NULL) {
@@ -153,44 +154,19 @@
 	if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 ||
 	    (r = sshpkt_get_end(ssh)) != 0)
 		goto out;
-
-	DH_get0_key(kex->dh, &pub_key, NULL);
-	DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
-
-#ifdef DEBUG_KEXDH
-	fprintf(stderr, "dh_client_pub= ");
-	BN_print_fp(stderr, dh_client_pub);
-	fprintf(stderr, "\n");
-	debug("bits %d", BN_num_bits(dh_client_pub));
-	DHparams_print_fp(stderr, kex->dh);
-	fprintf(stderr, "pub= ");
-	BN_print_fp(stderr, pub_key);
-	fprintf(stderr, "\n");
-#endif
-	if (!dh_pub_is_valid(kex->dh, dh_client_pub)) {
-		sshpkt_disconnect(ssh, "bad client public DH value");
-		r = SSH_ERR_MESSAGE_INCOMPLETE;
-		goto out;
-	}
-
-	klen = DH_size(kex->dh);
-	if ((kbuf = malloc(klen)) == NULL ||
-	    (shared_secret = BN_new()) == NULL) {
+	if ((shared_secret = sshbuf_new()) == NULL) {
 		r = SSH_ERR_ALLOC_FAIL;
 		goto out;
 	}
-	if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 ||
-	    BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
-		r = SSH_ERR_LIBCRYPTO_ERROR;
+	if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0)
 		goto out;
-	}
-#ifdef DEBUG_KEXDH
-	dump_digest("shared secret", kbuf, kout);
-#endif
 	if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
 	    &sbloblen)) != 0)
 		goto out;
+
 	/* calc H */
+	DH_get0_key(kex->dh, &pub_key, NULL);
+	DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
 	hashlen = sizeof(hash);
 	if ((r = kexgex_hash(
 	    kex->hash_alg,
@@ -203,7 +179,7 @@
 	    dh_p, dh_g,
 	    dh_client_pub,
 	    pub_key,
-	    shared_secret,
+	    sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
 	    hash, &hashlen)) != 0)
 		goto out;
 
@@ -212,8 +188,6 @@
 	    &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0)
 		goto out;
 
-	/* destroy_sensitive_data(); */
-
 	/* send server hostkey, DH pubkey 'f' and signed H */
 	if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 ||
 	    (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
@@ -222,18 +196,14 @@
 	    (r = sshpkt_send(ssh)) != 0)
 		goto out;
 
-	if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
+	if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
 		r = kex_send_newkeys(ssh);
  out:
 	explicit_bzero(hash, sizeof(hash));
 	DH_free(kex->dh);
 	kex->dh = NULL;
 	BN_clear_free(dh_client_pub);
-	if (kbuf) {
-		explicit_bzero(kbuf, klen);
-		free(kbuf);
-	}
-	BN_clear_free(shared_secret);
+	sshbuf_free(shared_secret);
 	free(server_host_key_blob);
 	free(signature);
 	return r;