xref: /freebsd-src/crypto/openssh/kexgen.c (revision 1323ec571215a77ddd21294f0871979d5ad6b992)
1*1323ec57SEd Maste /* $OpenBSD: kexgen.c,v 1.8 2021/12/19 22:08:06 djm Exp $ */
219261079SEd Maste /*
319261079SEd Maste  * Copyright (c) 2019 Markus Friedl.  All rights reserved.
419261079SEd Maste  *
519261079SEd Maste  * Redistribution and use in source and binary forms, with or without
619261079SEd Maste  * modification, are permitted provided that the following conditions
719261079SEd Maste  * are met:
819261079SEd Maste  * 1. Redistributions of source code must retain the above copyright
919261079SEd Maste  *    notice, this list of conditions and the following disclaimer.
1019261079SEd Maste  * 2. Redistributions in binary form must reproduce the above copyright
1119261079SEd Maste  *    notice, this list of conditions and the following disclaimer in the
1219261079SEd Maste  *    documentation and/or other materials provided with the distribution.
1319261079SEd Maste  *
1419261079SEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1519261079SEd Maste  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1619261079SEd Maste  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1719261079SEd Maste  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1819261079SEd Maste  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1919261079SEd Maste  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2019261079SEd Maste  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2119261079SEd Maste  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2219261079SEd Maste  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2319261079SEd Maste  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2419261079SEd Maste  */
2519261079SEd Maste 
2619261079SEd Maste #include "includes.h"
2719261079SEd Maste 
2819261079SEd Maste #include <sys/types.h>
2919261079SEd Maste 
3019261079SEd Maste #include <stdarg.h>
3119261079SEd Maste #include <stdio.h>
3219261079SEd Maste #include <string.h>
3319261079SEd Maste #include <signal.h>
3419261079SEd Maste 
3519261079SEd Maste #include "sshkey.h"
3619261079SEd Maste #include "kex.h"
3719261079SEd Maste #include "log.h"
3819261079SEd Maste #include "packet.h"
3919261079SEd Maste #include "ssh2.h"
4019261079SEd Maste #include "sshbuf.h"
4119261079SEd Maste #include "digest.h"
4219261079SEd Maste #include "ssherr.h"
4319261079SEd Maste 
4419261079SEd Maste static int input_kex_gen_init(int, u_int32_t, struct ssh *);
4519261079SEd Maste static int input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh);
4619261079SEd Maste 
4719261079SEd Maste static int
kex_gen_hash(int hash_alg,const struct sshbuf * client_version,const struct sshbuf * server_version,const struct sshbuf * client_kexinit,const struct sshbuf * server_kexinit,const struct sshbuf * server_host_key_blob,const struct sshbuf * client_pub,const struct sshbuf * server_pub,const struct sshbuf * shared_secret,u_char * hash,size_t * hashlen)4819261079SEd Maste kex_gen_hash(
4919261079SEd Maste     int hash_alg,
5019261079SEd Maste     const struct sshbuf *client_version,
5119261079SEd Maste     const struct sshbuf *server_version,
5219261079SEd Maste     const struct sshbuf *client_kexinit,
5319261079SEd Maste     const struct sshbuf *server_kexinit,
5419261079SEd Maste     const struct sshbuf *server_host_key_blob,
5519261079SEd Maste     const struct sshbuf *client_pub,
5619261079SEd Maste     const struct sshbuf *server_pub,
5719261079SEd Maste     const struct sshbuf *shared_secret,
5819261079SEd Maste     u_char *hash, size_t *hashlen)
5919261079SEd Maste {
6019261079SEd Maste 	struct sshbuf *b;
6119261079SEd Maste 	int r;
6219261079SEd Maste 
6319261079SEd Maste 	if (*hashlen < ssh_digest_bytes(hash_alg))
6419261079SEd Maste 		return SSH_ERR_INVALID_ARGUMENT;
6519261079SEd Maste 	if ((b = sshbuf_new()) == NULL)
6619261079SEd Maste 		return SSH_ERR_ALLOC_FAIL;
6719261079SEd Maste 	if ((r = sshbuf_put_stringb(b, client_version)) != 0 ||
6819261079SEd Maste 	    (r = sshbuf_put_stringb(b, server_version)) != 0 ||
6919261079SEd Maste 	    /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
7019261079SEd Maste 	    (r = sshbuf_put_u32(b, sshbuf_len(client_kexinit) + 1)) != 0 ||
7119261079SEd Maste 	    (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
7219261079SEd Maste 	    (r = sshbuf_putb(b, client_kexinit)) != 0 ||
7319261079SEd Maste 	    (r = sshbuf_put_u32(b, sshbuf_len(server_kexinit) + 1)) != 0 ||
7419261079SEd Maste 	    (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
7519261079SEd Maste 	    (r = sshbuf_putb(b, server_kexinit)) != 0 ||
7619261079SEd Maste 	    (r = sshbuf_put_stringb(b, server_host_key_blob)) != 0 ||
7719261079SEd Maste 	    (r = sshbuf_put_stringb(b, client_pub)) != 0 ||
7819261079SEd Maste 	    (r = sshbuf_put_stringb(b, server_pub)) != 0 ||
7919261079SEd Maste 	    (r = sshbuf_putb(b, shared_secret)) != 0) {
8019261079SEd Maste 		sshbuf_free(b);
8119261079SEd Maste 		return r;
8219261079SEd Maste 	}
8319261079SEd Maste #ifdef DEBUG_KEX
8419261079SEd Maste 	sshbuf_dump(b, stderr);
8519261079SEd Maste #endif
8619261079SEd Maste 	if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) {
8719261079SEd Maste 		sshbuf_free(b);
8819261079SEd Maste 		return SSH_ERR_LIBCRYPTO_ERROR;
8919261079SEd Maste 	}
9019261079SEd Maste 	sshbuf_free(b);
9119261079SEd Maste 	*hashlen = ssh_digest_bytes(hash_alg);
9219261079SEd Maste #ifdef DEBUG_KEX
9319261079SEd Maste 	dump_digest("hash", hash, *hashlen);
9419261079SEd Maste #endif
9519261079SEd Maste 	return 0;
9619261079SEd Maste }
9719261079SEd Maste 
9819261079SEd Maste int
kex_gen_client(struct ssh * ssh)9919261079SEd Maste kex_gen_client(struct ssh *ssh)
10019261079SEd Maste {
10119261079SEd Maste 	struct kex *kex = ssh->kex;
10219261079SEd Maste 	int r;
10319261079SEd Maste 
10419261079SEd Maste 	switch (kex->kex_type) {
10519261079SEd Maste #ifdef WITH_OPENSSL
10619261079SEd Maste 	case KEX_DH_GRP1_SHA1:
10719261079SEd Maste 	case KEX_DH_GRP14_SHA1:
10819261079SEd Maste 	case KEX_DH_GRP14_SHA256:
10919261079SEd Maste 	case KEX_DH_GRP16_SHA512:
11019261079SEd Maste 	case KEX_DH_GRP18_SHA512:
11119261079SEd Maste 		r = kex_dh_keypair(kex);
11219261079SEd Maste 		break;
11319261079SEd Maste 	case KEX_ECDH_SHA2:
11419261079SEd Maste 		r = kex_ecdh_keypair(kex);
11519261079SEd Maste 		break;
11619261079SEd Maste #endif
11719261079SEd Maste 	case KEX_C25519_SHA256:
11819261079SEd Maste 		r = kex_c25519_keypair(kex);
11919261079SEd Maste 		break;
12019261079SEd Maste 	case KEX_KEM_SNTRUP761X25519_SHA512:
12119261079SEd Maste 		r = kex_kem_sntrup761x25519_keypair(kex);
12219261079SEd Maste 		break;
12319261079SEd Maste 	default:
12419261079SEd Maste 		r = SSH_ERR_INVALID_ARGUMENT;
12519261079SEd Maste 		break;
12619261079SEd Maste 	}
12719261079SEd Maste 	if (r != 0)
12819261079SEd Maste 		return r;
12919261079SEd Maste 	if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 ||
13019261079SEd Maste 	    (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0 ||
13119261079SEd Maste 	    (r = sshpkt_send(ssh)) != 0)
13219261079SEd Maste 		return r;
13319261079SEd Maste 	debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
13419261079SEd Maste 	ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_gen_reply);
13519261079SEd Maste 	return 0;
13619261079SEd Maste }
13719261079SEd Maste 
13819261079SEd Maste static int
input_kex_gen_reply(int type,u_int32_t seq,struct ssh * ssh)13919261079SEd Maste input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh)
14019261079SEd Maste {
14119261079SEd Maste 	struct kex *kex = ssh->kex;
14219261079SEd Maste 	struct sshkey *server_host_key = NULL;
14319261079SEd Maste 	struct sshbuf *shared_secret = NULL;
14419261079SEd Maste 	struct sshbuf *server_blob = NULL;
14519261079SEd Maste 	struct sshbuf *tmp = NULL, *server_host_key_blob = NULL;
14619261079SEd Maste 	u_char *signature = NULL;
14719261079SEd Maste 	u_char hash[SSH_DIGEST_MAX_LENGTH];
14819261079SEd Maste 	size_t slen, hashlen;
14919261079SEd Maste 	int r;
15019261079SEd Maste 
15119261079SEd Maste 	debug("SSH2_MSG_KEX_ECDH_REPLY received");
15219261079SEd Maste 	ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &kex_protocol_error);
15319261079SEd Maste 
15419261079SEd Maste 	/* hostkey */
15519261079SEd Maste 	if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
15619261079SEd Maste 		goto out;
15719261079SEd Maste 	/* sshkey_fromb() consumes its buffer, so make a copy */
15819261079SEd Maste 	if ((tmp = sshbuf_fromb(server_host_key_blob)) == NULL) {
15919261079SEd Maste 		r = SSH_ERR_ALLOC_FAIL;
16019261079SEd Maste 		goto out;
16119261079SEd Maste 	}
16219261079SEd Maste 	if ((r = sshkey_fromb(tmp, &server_host_key)) != 0)
16319261079SEd Maste 		goto out;
16419261079SEd Maste 	if ((r = kex_verify_host_key(ssh, server_host_key)) != 0)
16519261079SEd Maste 		goto out;
16619261079SEd Maste 
16719261079SEd Maste 	/* Q_S, server public key */
16819261079SEd Maste 	/* signed H */
16919261079SEd Maste 	if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 ||
17019261079SEd Maste 	    (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
17119261079SEd Maste 	    (r = sshpkt_get_end(ssh)) != 0)
17219261079SEd Maste 		goto out;
17319261079SEd Maste 
17419261079SEd Maste 	/* compute shared secret */
17519261079SEd Maste 	switch (kex->kex_type) {
17619261079SEd Maste #ifdef WITH_OPENSSL
17719261079SEd Maste 	case KEX_DH_GRP1_SHA1:
17819261079SEd Maste 	case KEX_DH_GRP14_SHA1:
17919261079SEd Maste 	case KEX_DH_GRP14_SHA256:
18019261079SEd Maste 	case KEX_DH_GRP16_SHA512:
18119261079SEd Maste 	case KEX_DH_GRP18_SHA512:
18219261079SEd Maste 		r = kex_dh_dec(kex, server_blob, &shared_secret);
18319261079SEd Maste 		break;
18419261079SEd Maste 	case KEX_ECDH_SHA2:
18519261079SEd Maste 		r = kex_ecdh_dec(kex, server_blob, &shared_secret);
18619261079SEd Maste 		break;
18719261079SEd Maste #endif
18819261079SEd Maste 	case KEX_C25519_SHA256:
18919261079SEd Maste 		r = kex_c25519_dec(kex, server_blob, &shared_secret);
19019261079SEd Maste 		break;
19119261079SEd Maste 	case KEX_KEM_SNTRUP761X25519_SHA512:
19219261079SEd Maste 		r = kex_kem_sntrup761x25519_dec(kex, server_blob,
19319261079SEd Maste 		    &shared_secret);
19419261079SEd Maste 		break;
19519261079SEd Maste 	default:
19619261079SEd Maste 		r = SSH_ERR_INVALID_ARGUMENT;
19719261079SEd Maste 		break;
19819261079SEd Maste 	}
19919261079SEd Maste 	if (r !=0 )
20019261079SEd Maste 		goto out;
20119261079SEd Maste 
20219261079SEd Maste 	/* calc and verify H */
20319261079SEd Maste 	hashlen = sizeof(hash);
20419261079SEd Maste 	if ((r = kex_gen_hash(
20519261079SEd Maste 	    kex->hash_alg,
20619261079SEd Maste 	    kex->client_version,
20719261079SEd Maste 	    kex->server_version,
20819261079SEd Maste 	    kex->my,
20919261079SEd Maste 	    kex->peer,
21019261079SEd Maste 	    server_host_key_blob,
21119261079SEd Maste 	    kex->client_pub,
21219261079SEd Maste 	    server_blob,
21319261079SEd Maste 	    shared_secret,
21419261079SEd Maste 	    hash, &hashlen)) != 0)
21519261079SEd Maste 		goto out;
21619261079SEd Maste 
21719261079SEd Maste 	if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
21819261079SEd Maste 	    kex->hostkey_alg, ssh->compat, NULL)) != 0)
21919261079SEd Maste 		goto out;
22019261079SEd Maste 
221*1323ec57SEd Maste 	if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) != 0 ||
222*1323ec57SEd Maste 	    (r = kex_send_newkeys(ssh)) != 0)
223*1323ec57SEd Maste 		goto out;
224*1323ec57SEd Maste 
225*1323ec57SEd Maste 	/* save initial signature and hostkey */
226*1323ec57SEd Maste 	if ((kex->flags & KEX_INITIAL) != 0) {
227*1323ec57SEd Maste 		if (kex->initial_hostkey != NULL || kex->initial_sig != NULL) {
228*1323ec57SEd Maste 			r = SSH_ERR_INTERNAL_ERROR;
229*1323ec57SEd Maste 			goto out;
230*1323ec57SEd Maste 		}
231*1323ec57SEd Maste 		if ((kex->initial_sig = sshbuf_new()) == NULL) {
232*1323ec57SEd Maste 			r = SSH_ERR_ALLOC_FAIL;
233*1323ec57SEd Maste 			goto out;
234*1323ec57SEd Maste 		}
235*1323ec57SEd Maste 		if ((r = sshbuf_put(kex->initial_sig, signature, slen)) != 0)
236*1323ec57SEd Maste 			goto out;
237*1323ec57SEd Maste 		kex->initial_hostkey = server_host_key;
238*1323ec57SEd Maste 		server_host_key = NULL;
239*1323ec57SEd Maste 	}
240*1323ec57SEd Maste 	/* success */
24119261079SEd Maste out:
24219261079SEd Maste 	explicit_bzero(hash, sizeof(hash));
24319261079SEd Maste 	explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));
24419261079SEd Maste 	explicit_bzero(kex->sntrup761_client_key,
24519261079SEd Maste 	    sizeof(kex->sntrup761_client_key));
24619261079SEd Maste 	sshbuf_free(server_host_key_blob);
24719261079SEd Maste 	free(signature);
24819261079SEd Maste 	sshbuf_free(tmp);
24919261079SEd Maste 	sshkey_free(server_host_key);
25019261079SEd Maste 	sshbuf_free(server_blob);
25119261079SEd Maste 	sshbuf_free(shared_secret);
25219261079SEd Maste 	sshbuf_free(kex->client_pub);
25319261079SEd Maste 	kex->client_pub = NULL;
25419261079SEd Maste 	return r;
25519261079SEd Maste }
25619261079SEd Maste 
25719261079SEd Maste int
kex_gen_server(struct ssh * ssh)25819261079SEd Maste kex_gen_server(struct ssh *ssh)
25919261079SEd Maste {
26019261079SEd Maste 	debug("expecting SSH2_MSG_KEX_ECDH_INIT");
26119261079SEd Maste 	ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_gen_init);
26219261079SEd Maste 	return 0;
26319261079SEd Maste }
26419261079SEd Maste 
26519261079SEd Maste static int
input_kex_gen_init(int type,u_int32_t seq,struct ssh * ssh)26619261079SEd Maste input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh)
26719261079SEd Maste {
26819261079SEd Maste 	struct kex *kex = ssh->kex;
26919261079SEd Maste 	struct sshkey *server_host_private, *server_host_public;
27019261079SEd Maste 	struct sshbuf *shared_secret = NULL;
27119261079SEd Maste 	struct sshbuf *server_pubkey = NULL;
27219261079SEd Maste 	struct sshbuf *client_pubkey = NULL;
27319261079SEd Maste 	struct sshbuf *server_host_key_blob = NULL;
27419261079SEd Maste 	u_char *signature = NULL, hash[SSH_DIGEST_MAX_LENGTH];
27519261079SEd Maste 	size_t slen, hashlen;
27619261079SEd Maste 	int r;
27719261079SEd Maste 
27819261079SEd Maste 	debug("SSH2_MSG_KEX_ECDH_INIT received");
27919261079SEd Maste 	ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &kex_protocol_error);
28019261079SEd Maste 
28119261079SEd Maste 	if ((r = kex_load_hostkey(ssh, &server_host_private,
28219261079SEd Maste 	    &server_host_public)) != 0)
28319261079SEd Maste 		goto out;
28419261079SEd Maste 
28519261079SEd Maste 	if ((r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 ||
28619261079SEd Maste 	    (r = sshpkt_get_end(ssh)) != 0)
28719261079SEd Maste 		goto out;
28819261079SEd Maste 
28919261079SEd Maste 	/* compute shared secret */
29019261079SEd Maste 	switch (kex->kex_type) {
29119261079SEd Maste #ifdef WITH_OPENSSL
29219261079SEd Maste 	case KEX_DH_GRP1_SHA1:
29319261079SEd Maste 	case KEX_DH_GRP14_SHA1:
29419261079SEd Maste 	case KEX_DH_GRP14_SHA256:
29519261079SEd Maste 	case KEX_DH_GRP16_SHA512:
29619261079SEd Maste 	case KEX_DH_GRP18_SHA512:
29719261079SEd Maste 		r = kex_dh_enc(kex, client_pubkey, &server_pubkey,
29819261079SEd Maste 		    &shared_secret);
29919261079SEd Maste 		break;
30019261079SEd Maste 	case KEX_ECDH_SHA2:
30119261079SEd Maste 		r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey,
30219261079SEd Maste 		    &shared_secret);
30319261079SEd Maste 		break;
30419261079SEd Maste #endif
30519261079SEd Maste 	case KEX_C25519_SHA256:
30619261079SEd Maste 		r = kex_c25519_enc(kex, client_pubkey, &server_pubkey,
30719261079SEd Maste 		    &shared_secret);
30819261079SEd Maste 		break;
30919261079SEd Maste 	case KEX_KEM_SNTRUP761X25519_SHA512:
31019261079SEd Maste 		r = kex_kem_sntrup761x25519_enc(kex, client_pubkey,
31119261079SEd Maste 		    &server_pubkey, &shared_secret);
31219261079SEd Maste 		break;
31319261079SEd Maste 	default:
31419261079SEd Maste 		r = SSH_ERR_INVALID_ARGUMENT;
31519261079SEd Maste 		break;
31619261079SEd Maste 	}
31719261079SEd Maste 	if (r !=0 )
31819261079SEd Maste 		goto out;
31919261079SEd Maste 
32019261079SEd Maste 	/* calc H */
32119261079SEd Maste 	if ((server_host_key_blob = sshbuf_new()) == NULL) {
32219261079SEd Maste 		r = SSH_ERR_ALLOC_FAIL;
32319261079SEd Maste 		goto out;
32419261079SEd Maste 	}
32519261079SEd Maste 	if ((r = sshkey_putb(server_host_public, server_host_key_blob)) != 0)
32619261079SEd Maste 		goto out;
32719261079SEd Maste 	hashlen = sizeof(hash);
32819261079SEd Maste 	if ((r = kex_gen_hash(
32919261079SEd Maste 	    kex->hash_alg,
33019261079SEd Maste 	    kex->client_version,
33119261079SEd Maste 	    kex->server_version,
33219261079SEd Maste 	    kex->peer,
33319261079SEd Maste 	    kex->my,
33419261079SEd Maste 	    server_host_key_blob,
33519261079SEd Maste 	    client_pubkey,
33619261079SEd Maste 	    server_pubkey,
33719261079SEd Maste 	    shared_secret,
33819261079SEd Maste 	    hash, &hashlen)) != 0)
33919261079SEd Maste 		goto out;
34019261079SEd Maste 
34119261079SEd Maste 	/* sign H */
34219261079SEd Maste 	if ((r = kex->sign(ssh, server_host_private, server_host_public,
34319261079SEd Maste 	    &signature, &slen, hash, hashlen, kex->hostkey_alg)) != 0)
34419261079SEd Maste 		goto out;
34519261079SEd Maste 
34619261079SEd Maste 	/* send server hostkey, ECDH pubkey 'Q_S' and signed H */
34719261079SEd Maste 	if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 ||
34819261079SEd Maste 	    (r = sshpkt_put_stringb(ssh, server_host_key_blob)) != 0 ||
34919261079SEd Maste 	    (r = sshpkt_put_stringb(ssh, server_pubkey)) != 0 ||
35019261079SEd Maste 	    (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
35119261079SEd Maste 	    (r = sshpkt_send(ssh)) != 0)
35219261079SEd Maste 		goto out;
35319261079SEd Maste 
354*1323ec57SEd Maste 	if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) != 0 ||
355*1323ec57SEd Maste 	    (r = kex_send_newkeys(ssh)) != 0)
356*1323ec57SEd Maste 		goto out;
357*1323ec57SEd Maste 	/* retain copy of hostkey used at initial KEX */
358*1323ec57SEd Maste 	if (kex->initial_hostkey == NULL &&
359*1323ec57SEd Maste 	    (r = sshkey_from_private(server_host_public,
360*1323ec57SEd Maste 	    &kex->initial_hostkey)) != 0)
361*1323ec57SEd Maste 		goto out;
362*1323ec57SEd Maste 	/* success */
36319261079SEd Maste out:
36419261079SEd Maste 	explicit_bzero(hash, sizeof(hash));
36519261079SEd Maste 	sshbuf_free(server_host_key_blob);
36619261079SEd Maste 	free(signature);
36719261079SEd Maste 	sshbuf_free(shared_secret);
36819261079SEd Maste 	sshbuf_free(client_pubkey);
36919261079SEd Maste 	sshbuf_free(server_pubkey);
37019261079SEd Maste 	return r;
37119261079SEd Maste }
372