Home | History | Annotate | Line # | Download | only in dist
      1  1.10       rin /*	$NetBSD: kexgen.c,v 1.10 2026/07/29 08:24:09 rin Exp $	*/
      2   1.9  christos /* $OpenBSD: kexgen.c,v 1.12 2026/03/03 09:57:25 dtucker Exp $ */
      3   1.8  christos 
      4   1.1  christos /*
      5   1.1  christos  * Copyright (c) 2019 Markus Friedl.  All rights reserved.
      6   1.1  christos  *
      7   1.1  christos  * Redistribution and use in source and binary forms, with or without
      8   1.1  christos  * modification, are permitted provided that the following conditions
      9   1.1  christos  * are met:
     10   1.1  christos  * 1. Redistributions of source code must retain the above copyright
     11   1.1  christos  *    notice, this list of conditions and the following disclaimer.
     12   1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     14   1.1  christos  *    documentation and/or other materials provided with the distribution.
     15   1.1  christos  *
     16   1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17   1.1  christos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18   1.1  christos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19   1.1  christos  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20   1.1  christos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21   1.1  christos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22   1.1  christos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23   1.1  christos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24   1.1  christos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25   1.1  christos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26   1.1  christos  */
     27   1.2  christos #include "includes.h"
     28  1.10       rin __RCSID("$NetBSD: kexgen.c,v 1.10 2026/07/29 08:24:09 rin Exp $");
     29   1.1  christos 
     30   1.1  christos #include <sys/types.h>
     31   1.1  christos 
     32   1.9  christos #include <stdarg.h>
     33   1.1  christos #include <stdio.h>
     34   1.1  christos #include <string.h>
     35   1.1  christos #include <signal.h>
     36   1.1  christos 
     37   1.1  christos #include "sshkey.h"
     38   1.1  christos #include "kex.h"
     39   1.1  christos #include "log.h"
     40   1.1  christos #include "packet.h"
     41   1.1  christos #include "ssh2.h"
     42   1.1  christos #include "sshbuf.h"
     43   1.1  christos #include "digest.h"
     44   1.1  christos #include "ssherr.h"
     45   1.1  christos 
     46   1.9  christos static int input_kex_gen_init(int, uint32_t, struct ssh *);
     47   1.9  christos static int input_kex_gen_reply(int type, uint32_t seq, struct ssh *ssh);
     48   1.1  christos 
     49   1.1  christos static int
     50   1.1  christos kex_gen_hash(
     51   1.1  christos     int hash_alg,
     52   1.1  christos     const struct sshbuf *client_version,
     53   1.1  christos     const struct sshbuf *server_version,
     54   1.1  christos     const struct sshbuf *client_kexinit,
     55   1.1  christos     const struct sshbuf *server_kexinit,
     56   1.1  christos     const struct sshbuf *server_host_key_blob,
     57   1.1  christos     const struct sshbuf *client_pub,
     58   1.1  christos     const struct sshbuf *server_pub,
     59   1.1  christos     const struct sshbuf *shared_secret,
     60   1.1  christos     u_char *hash, size_t *hashlen)
     61   1.1  christos {
     62   1.1  christos 	struct sshbuf *b;
     63   1.1  christos 	int r;
     64   1.1  christos 
     65   1.1  christos 	if (*hashlen < ssh_digest_bytes(hash_alg))
     66   1.1  christos 		return SSH_ERR_INVALID_ARGUMENT;
     67   1.1  christos 	if ((b = sshbuf_new()) == NULL)
     68   1.1  christos 		return SSH_ERR_ALLOC_FAIL;
     69   1.1  christos 	if ((r = sshbuf_put_stringb(b, client_version)) != 0 ||
     70   1.1  christos 	    (r = sshbuf_put_stringb(b, server_version)) != 0 ||
     71   1.1  christos 	    /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
     72   1.1  christos 	    (r = sshbuf_put_u32(b, sshbuf_len(client_kexinit) + 1)) != 0 ||
     73   1.1  christos 	    (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
     74   1.1  christos 	    (r = sshbuf_putb(b, client_kexinit)) != 0 ||
     75   1.1  christos 	    (r = sshbuf_put_u32(b, sshbuf_len(server_kexinit) + 1)) != 0 ||
     76   1.1  christos 	    (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
     77   1.1  christos 	    (r = sshbuf_putb(b, server_kexinit)) != 0 ||
     78   1.1  christos 	    (r = sshbuf_put_stringb(b, server_host_key_blob)) != 0 ||
     79   1.1  christos 	    (r = sshbuf_put_stringb(b, client_pub)) != 0 ||
     80   1.1  christos 	    (r = sshbuf_put_stringb(b, server_pub)) != 0 ||
     81   1.1  christos 	    (r = sshbuf_putb(b, shared_secret)) != 0) {
     82   1.1  christos 		sshbuf_free(b);
     83   1.1  christos 		return r;
     84   1.1  christos 	}
     85   1.1  christos #ifdef DEBUG_KEX
     86   1.1  christos 	sshbuf_dump(b, stderr);
     87   1.1  christos #endif
     88   1.1  christos 	if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) {
     89   1.1  christos 		sshbuf_free(b);
     90   1.1  christos 		return SSH_ERR_LIBCRYPTO_ERROR;
     91   1.1  christos 	}
     92   1.1  christos 	sshbuf_free(b);
     93   1.1  christos 	*hashlen = ssh_digest_bytes(hash_alg);
     94   1.1  christos #ifdef DEBUG_KEX
     95   1.1  christos 	dump_digest("hash", hash, *hashlen);
     96   1.1  christos #endif
     97   1.1  christos 	return 0;
     98   1.1  christos }
     99   1.1  christos 
    100   1.1  christos int
    101   1.1  christos kex_gen_client(struct ssh *ssh)
    102   1.1  christos {
    103   1.1  christos 	struct kex *kex = ssh->kex;
    104   1.1  christos 	int r;
    105   1.1  christos 
    106   1.1  christos 	switch (kex->kex_type) {
    107   1.3  christos #ifdef WITH_OPENSSL
    108   1.1  christos 	case KEX_DH_GRP1_SHA1:
    109   1.1  christos 	case KEX_DH_GRP14_SHA1:
    110   1.1  christos 	case KEX_DH_GRP14_SHA256:
    111   1.1  christos 	case KEX_DH_GRP16_SHA512:
    112   1.1  christos 	case KEX_DH_GRP18_SHA512:
    113   1.1  christos 		r = kex_dh_keypair(kex);
    114   1.1  christos 		break;
    115   1.1  christos 	case KEX_ECDH_SHA2:
    116   1.1  christos 		r = kex_ecdh_keypair(kex);
    117   1.1  christos 		break;
    118   1.3  christos #endif /* WITH_OPENSSL */
    119   1.1  christos 	case KEX_C25519_SHA256:
    120   1.1  christos 		r = kex_c25519_keypair(kex);
    121   1.1  christos 		break;
    122   1.5  christos 	case KEX_KEM_SNTRUP761X25519_SHA512:
    123   1.5  christos 		r = kex_kem_sntrup761x25519_keypair(kex);
    124   1.1  christos 		break;
    125   1.8  christos 	case KEX_KEM_MLKEM768X25519_SHA256:
    126   1.8  christos 		r = kex_kem_mlkem768x25519_keypair(kex);
    127   1.8  christos 		break;
    128   1.1  christos 	default:
    129   1.1  christos 		r = SSH_ERR_INVALID_ARGUMENT;
    130   1.1  christos 		break;
    131   1.1  christos 	}
    132   1.1  christos 	if (r != 0)
    133   1.1  christos 		return r;
    134   1.1  christos 	if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 ||
    135   1.1  christos 	    (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0 ||
    136   1.1  christos 	    (r = sshpkt_send(ssh)) != 0)
    137   1.1  christos 		return r;
    138   1.1  christos 	debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
    139   1.1  christos 	ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_gen_reply);
    140   1.1  christos 	return 0;
    141   1.1  christos }
    142   1.1  christos 
    143   1.1  christos static int
    144   1.9  christos input_kex_gen_reply(int type, uint32_t seq, struct ssh *ssh)
    145   1.1  christos {
    146   1.1  christos 	struct kex *kex = ssh->kex;
    147   1.1  christos 	struct sshkey *server_host_key = NULL;
    148   1.1  christos 	struct sshbuf *shared_secret = NULL;
    149   1.1  christos 	struct sshbuf *server_blob = NULL;
    150   1.1  christos 	struct sshbuf *tmp = NULL, *server_host_key_blob = NULL;
    151   1.1  christos 	u_char *signature = NULL;
    152   1.1  christos 	u_char hash[SSH_DIGEST_MAX_LENGTH];
    153   1.1  christos 	size_t slen, hashlen;
    154   1.1  christos 	int r;
    155   1.1  christos 
    156   1.5  christos 	debug("SSH2_MSG_KEX_ECDH_REPLY received");
    157   1.5  christos 	ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &kex_protocol_error);
    158   1.5  christos 
    159   1.1  christos 	/* hostkey */
    160   1.1  christos 	if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
    161   1.1  christos 		goto out;
    162   1.1  christos 	/* sshkey_fromb() consumes its buffer, so make a copy */
    163   1.1  christos 	if ((tmp = sshbuf_fromb(server_host_key_blob)) == NULL) {
    164   1.1  christos 		r = SSH_ERR_ALLOC_FAIL;
    165   1.1  christos 		goto out;
    166   1.1  christos 	}
    167   1.1  christos 	if ((r = sshkey_fromb(tmp, &server_host_key)) != 0)
    168   1.1  christos 		goto out;
    169   1.1  christos 	if ((r = kex_verify_host_key(ssh, server_host_key)) != 0)
    170   1.1  christos 		goto out;
    171   1.1  christos 
    172   1.1  christos 	/* Q_S, server public key */
    173   1.1  christos 	/* signed H */
    174   1.1  christos 	if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 ||
    175   1.1  christos 	    (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
    176   1.1  christos 	    (r = sshpkt_get_end(ssh)) != 0)
    177   1.1  christos 		goto out;
    178   1.1  christos 
    179   1.1  christos 	/* compute shared secret */
    180   1.1  christos 	switch (kex->kex_type) {
    181   1.3  christos #ifdef WITH_OPENSSL
    182   1.1  christos 	case KEX_DH_GRP1_SHA1:
    183   1.1  christos 	case KEX_DH_GRP14_SHA1:
    184   1.1  christos 	case KEX_DH_GRP14_SHA256:
    185   1.1  christos 	case KEX_DH_GRP16_SHA512:
    186   1.1  christos 	case KEX_DH_GRP18_SHA512:
    187   1.1  christos 		r = kex_dh_dec(kex, server_blob, &shared_secret);
    188   1.1  christos 		break;
    189   1.1  christos 	case KEX_ECDH_SHA2:
    190   1.1  christos 		r = kex_ecdh_dec(kex, server_blob, &shared_secret);
    191   1.1  christos 		break;
    192   1.3  christos #endif /* WITH_OPENSSL */
    193   1.1  christos 	case KEX_C25519_SHA256:
    194   1.1  christos 		r = kex_c25519_dec(kex, server_blob, &shared_secret);
    195   1.1  christos 		break;
    196   1.5  christos 	case KEX_KEM_SNTRUP761X25519_SHA512:
    197   1.5  christos 		r = kex_kem_sntrup761x25519_dec(kex, server_blob,
    198   1.1  christos 		    &shared_secret);
    199   1.1  christos 		break;
    200   1.8  christos 	case KEX_KEM_MLKEM768X25519_SHA256:
    201   1.8  christos 		r = kex_kem_mlkem768x25519_dec(kex, server_blob,
    202   1.8  christos 		    &shared_secret);
    203   1.8  christos 		break;
    204   1.1  christos 	default:
    205   1.1  christos 		r = SSH_ERR_INVALID_ARGUMENT;
    206   1.1  christos 		break;
    207   1.1  christos 	}
    208   1.1  christos 	if (r !=0 )
    209   1.1  christos 		goto out;
    210   1.1  christos 
    211   1.1  christos 	/* calc and verify H */
    212   1.1  christos 	hashlen = sizeof(hash);
    213   1.1  christos 	if ((r = kex_gen_hash(
    214   1.1  christos 	    kex->hash_alg,
    215   1.1  christos 	    kex->client_version,
    216   1.1  christos 	    kex->server_version,
    217   1.1  christos 	    kex->my,
    218   1.1  christos 	    kex->peer,
    219   1.1  christos 	    server_host_key_blob,
    220   1.1  christos 	    kex->client_pub,
    221   1.1  christos 	    server_blob,
    222   1.1  christos 	    shared_secret,
    223   1.1  christos 	    hash, &hashlen)) != 0)
    224   1.1  christos 		goto out;
    225   1.1  christos 
    226   1.1  christos 	if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
    227   1.4  christos 	    kex->hostkey_alg, ssh->compat, NULL)) != 0)
    228   1.1  christos 		goto out;
    229   1.1  christos 
    230   1.7  christos 	if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) != 0 ||
    231   1.7  christos 	    (r = kex_send_newkeys(ssh)) != 0)
    232   1.7  christos 		goto out;
    233   1.7  christos 
    234   1.7  christos 	/* save initial signature and hostkey */
    235   1.7  christos 	if ((kex->flags & KEX_INITIAL) != 0) {
    236   1.7  christos 		if (kex->initial_hostkey != NULL || kex->initial_sig != NULL) {
    237   1.7  christos 			r = SSH_ERR_INTERNAL_ERROR;
    238   1.7  christos 			goto out;
    239   1.7  christos 		}
    240   1.7  christos 		if ((kex->initial_sig = sshbuf_new()) == NULL) {
    241   1.7  christos 			r = SSH_ERR_ALLOC_FAIL;
    242   1.7  christos 			goto out;
    243   1.7  christos 		}
    244   1.7  christos 		if ((r = sshbuf_put(kex->initial_sig, signature, slen)) != 0)
    245   1.7  christos 			goto out;
    246   1.7  christos 		kex->initial_hostkey = server_host_key;
    247   1.7  christos 		server_host_key = NULL;
    248   1.7  christos 	}
    249   1.7  christos 	/* success */
    250   1.1  christos out:
    251   1.1  christos 	explicit_bzero(hash, sizeof(hash));
    252   1.1  christos 	explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));
    253   1.5  christos 	explicit_bzero(kex->sntrup761_client_key,
    254   1.5  christos 	    sizeof(kex->sntrup761_client_key));
    255   1.8  christos 	explicit_bzero(kex->mlkem768_client_key,
    256   1.8  christos 	    sizeof(kex->mlkem768_client_key));
    257   1.1  christos 	sshbuf_free(server_host_key_blob);
    258   1.1  christos 	free(signature);
    259   1.1  christos 	sshbuf_free(tmp);
    260   1.1  christos 	sshkey_free(server_host_key);
    261   1.1  christos 	sshbuf_free(server_blob);
    262   1.1  christos 	sshbuf_free(shared_secret);
    263   1.1  christos 	sshbuf_free(kex->client_pub);
    264   1.1  christos 	kex->client_pub = NULL;
    265   1.1  christos 	return r;
    266   1.1  christos }
    267   1.1  christos 
    268   1.1  christos int
    269   1.1  christos kex_gen_server(struct ssh *ssh)
    270   1.1  christos {
    271   1.1  christos 	debug("expecting SSH2_MSG_KEX_ECDH_INIT");
    272   1.1  christos 	ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_gen_init);
    273   1.1  christos 	return 0;
    274   1.1  christos }
    275   1.1  christos 
    276   1.1  christos static int
    277   1.9  christos input_kex_gen_init(int type, uint32_t seq, struct ssh *ssh)
    278   1.1  christos {
    279   1.1  christos 	struct kex *kex = ssh->kex;
    280   1.1  christos 	struct sshkey *server_host_private, *server_host_public;
    281   1.1  christos 	struct sshbuf *shared_secret = NULL;
    282   1.1  christos 	struct sshbuf *server_pubkey = NULL;
    283   1.1  christos 	struct sshbuf *client_pubkey = NULL;
    284   1.1  christos 	struct sshbuf *server_host_key_blob = NULL;
    285   1.1  christos 	u_char *signature = NULL, hash[SSH_DIGEST_MAX_LENGTH];
    286   1.1  christos 	size_t slen, hashlen;
    287   1.1  christos 	int r;
    288   1.1  christos 
    289   1.5  christos 	debug("SSH2_MSG_KEX_ECDH_INIT received");
    290   1.5  christos 	ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &kex_protocol_error);
    291   1.5  christos 
    292   1.1  christos 	if ((r = kex_load_hostkey(ssh, &server_host_private,
    293   1.1  christos 	    &server_host_public)) != 0)
    294   1.1  christos 		goto out;
    295   1.1  christos 
    296   1.1  christos 	if ((r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 ||
    297   1.1  christos 	    (r = sshpkt_get_end(ssh)) != 0)
    298   1.1  christos 		goto out;
    299   1.1  christos 
    300   1.1  christos 	/* compute shared secret */
    301   1.1  christos 	switch (kex->kex_type) {
    302   1.3  christos #ifdef WITH_OPENSSL
    303   1.1  christos 	case KEX_DH_GRP1_SHA1:
    304   1.1  christos 	case KEX_DH_GRP14_SHA1:
    305   1.1  christos 	case KEX_DH_GRP14_SHA256:
    306   1.1  christos 	case KEX_DH_GRP16_SHA512:
    307   1.1  christos 	case KEX_DH_GRP18_SHA512:
    308   1.1  christos 		r = kex_dh_enc(kex, client_pubkey, &server_pubkey,
    309   1.1  christos 		    &shared_secret);
    310   1.1  christos 		break;
    311   1.1  christos 	case KEX_ECDH_SHA2:
    312   1.1  christos 		r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey,
    313   1.1  christos 		    &shared_secret);
    314   1.1  christos 		break;
    315   1.3  christos #endif /* WITH_OPENSSL */
    316   1.1  christos 	case KEX_C25519_SHA256:
    317   1.1  christos 		r = kex_c25519_enc(kex, client_pubkey, &server_pubkey,
    318   1.1  christos 		    &shared_secret);
    319   1.1  christos 		break;
    320   1.5  christos 	case KEX_KEM_SNTRUP761X25519_SHA512:
    321   1.5  christos 		r = kex_kem_sntrup761x25519_enc(kex, client_pubkey,
    322   1.1  christos 		    &server_pubkey, &shared_secret);
    323   1.1  christos 		break;
    324   1.8  christos 	case KEX_KEM_MLKEM768X25519_SHA256:
    325   1.8  christos 		r = kex_kem_mlkem768x25519_enc(kex, client_pubkey,
    326   1.8  christos 		    &server_pubkey, &shared_secret);
    327   1.8  christos 		break;
    328   1.1  christos 	default:
    329   1.1  christos 		r = SSH_ERR_INVALID_ARGUMENT;
    330   1.1  christos 		break;
    331   1.1  christos 	}
    332   1.1  christos 	if (r !=0 )
    333   1.1  christos 		goto out;
    334   1.1  christos 
    335   1.1  christos 	/* calc H */
    336   1.1  christos 	if ((server_host_key_blob = sshbuf_new()) == NULL) {
    337   1.1  christos 		r = SSH_ERR_ALLOC_FAIL;
    338   1.1  christos 		goto out;
    339   1.1  christos 	}
    340   1.1  christos 	if ((r = sshkey_putb(server_host_public, server_host_key_blob)) != 0)
    341   1.1  christos 		goto out;
    342   1.1  christos 	hashlen = sizeof(hash);
    343   1.1  christos 	if ((r = kex_gen_hash(
    344   1.1  christos 	    kex->hash_alg,
    345   1.1  christos 	    kex->client_version,
    346   1.1  christos 	    kex->server_version,
    347   1.1  christos 	    kex->peer,
    348   1.1  christos 	    kex->my,
    349   1.1  christos 	    server_host_key_blob,
    350   1.1  christos 	    client_pubkey,
    351   1.1  christos 	    server_pubkey,
    352   1.1  christos 	    shared_secret,
    353   1.1  christos 	    hash, &hashlen)) != 0)
    354   1.1  christos 		goto out;
    355   1.1  christos 
    356   1.1  christos 	/* sign H */
    357   1.1  christos 	if ((r = kex->sign(ssh, server_host_private, server_host_public,
    358   1.6  christos 	    &signature, &slen, hash, hashlen, kex->hostkey_alg)) != 0)
    359   1.1  christos 		goto out;
    360   1.1  christos 
    361   1.1  christos 	/* send server hostkey, ECDH pubkey 'Q_S' and signed H */
    362   1.1  christos 	if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 ||
    363   1.1  christos 	    (r = sshpkt_put_stringb(ssh, server_host_key_blob)) != 0 ||
    364   1.1  christos 	    (r = sshpkt_put_stringb(ssh, server_pubkey)) != 0 ||
    365   1.1  christos 	    (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
    366   1.1  christos 	    (r = sshpkt_send(ssh)) != 0)
    367   1.1  christos 		goto out;
    368   1.1  christos 
    369   1.7  christos 	if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) != 0 ||
    370   1.7  christos 	    (r = kex_send_newkeys(ssh)) != 0)
    371   1.7  christos 		goto out;
    372   1.7  christos 	/* retain copy of hostkey used at initial KEX */
    373   1.7  christos 	if (kex->initial_hostkey == NULL &&
    374   1.7  christos 	    (r = sshkey_from_private(server_host_public,
    375   1.7  christos 	    &kex->initial_hostkey)) != 0)
    376   1.7  christos 		goto out;
    377   1.7  christos 	/* success */
    378   1.1  christos out:
    379   1.1  christos 	explicit_bzero(hash, sizeof(hash));
    380   1.1  christos 	sshbuf_free(server_host_key_blob);
    381   1.1  christos 	free(signature);
    382   1.1  christos 	sshbuf_free(shared_secret);
    383   1.1  christos 	sshbuf_free(client_pubkey);
    384   1.1  christos 	sshbuf_free(server_pubkey);
    385   1.1  christos 	return r;
    386   1.1  christos }
    387