1a5ab499bSDamien Miller // libfuzzer driver for key exchange fuzzing.
2a5ab499bSDamien Miller 
3a5ab499bSDamien Miller 
4a5ab499bSDamien Miller #include <sys/types.h>
5a5ab499bSDamien Miller #include <sys/param.h>
6a5ab499bSDamien Miller #include <stdio.h>
7a5ab499bSDamien Miller #include <stdint.h>
8a5ab499bSDamien Miller #include <stdlib.h>
9a5ab499bSDamien Miller #include <string.h>
10a5ab499bSDamien Miller 
11a5ab499bSDamien Miller extern "C" {
12a5ab499bSDamien Miller 
13a5ab499bSDamien Miller #include "includes.h"
14a5ab499bSDamien Miller #include "ssherr.h"
15a5ab499bSDamien Miller #include "ssh_api.h"
16a5ab499bSDamien Miller #include "sshbuf.h"
17a5ab499bSDamien Miller #include "packet.h"
18a5ab499bSDamien Miller #include "myproposal.h"
19a5ab499bSDamien Miller #include "xmalloc.h"
20a5ab499bSDamien Miller #include "authfile.h"
21a5ab499bSDamien Miller #include "log.h"
22a5ab499bSDamien Miller 
23*7e96c877SDamien Miller #include "fixed-keys.h"
24*7e96c877SDamien Miller 
25a5ab499bSDamien Miller // Define if you want to generate traces.
26be5f0048SDamien Miller /* #define STANDALONE 1 */
27a5ab499bSDamien Miller 
28a5ab499bSDamien Miller static int prepare_key(struct shared_state *st, int keytype, int bits);
29a5ab499bSDamien Miller 
30a5ab499bSDamien Miller struct shared_state {
31a5ab499bSDamien Miller 	size_t nkeys;
32a5ab499bSDamien Miller 	struct sshkey **privkeys, **pubkeys;
33a5ab499bSDamien Miller };
34a5ab499bSDamien Miller 
35a5ab499bSDamien Miller struct test_state {
36a5ab499bSDamien Miller 	struct sshbuf *smsgs, *cmsgs; /* output, for standalone mode */
37a5ab499bSDamien Miller 	struct sshbuf *sin, *cin; /* input; setup per-test in do_kex_with_key */
38a5ab499bSDamien Miller 	struct sshbuf *s_template, *c_template; /* main copy of input */
39a5ab499bSDamien Miller };
40a5ab499bSDamien Miller 
41a5ab499bSDamien Miller static int
do_send_and_receive(struct ssh * from,struct ssh * to,struct sshbuf * store,int clobber,size_t * n)42a5ab499bSDamien Miller do_send_and_receive(struct ssh *from, struct ssh *to,
43a5ab499bSDamien Miller     struct sshbuf *store, int clobber, size_t *n)
44a5ab499bSDamien Miller {
45a5ab499bSDamien Miller 	u_char type;
46a5ab499bSDamien Miller 	size_t len;
47a5ab499bSDamien Miller 	const u_char *buf;
48a5ab499bSDamien Miller 	int r;
49a5ab499bSDamien Miller 
50a5ab499bSDamien Miller 	for (*n = 0;; (*n)++) {
51a5ab499bSDamien Miller 		if ((r = ssh_packet_next(from, &type)) != 0) {
52a5ab499bSDamien Miller 			debug_fr(r, "ssh_packet_next");
53a5ab499bSDamien Miller 			return r;
54a5ab499bSDamien Miller 		}
55a5ab499bSDamien Miller 		if (type != 0)
56a5ab499bSDamien Miller 			return 0;
57a5ab499bSDamien Miller 		buf = ssh_output_ptr(from, &len);
58a5ab499bSDamien Miller 		debug_f("%zu%s", len, clobber ? " ignore" : "");
59a5ab499bSDamien Miller 		if (len == 0)
60a5ab499bSDamien Miller 			return 0;
61a5ab499bSDamien Miller 		if ((r = ssh_output_consume(from, len)) != 0) {
62a5ab499bSDamien Miller 			debug_fr(r, "ssh_output_consume");
63a5ab499bSDamien Miller 			return r;
64a5ab499bSDamien Miller 		}
65a5ab499bSDamien Miller 		if (store != NULL && (r = sshbuf_put(store, buf, len)) != 0) {
66a5ab499bSDamien Miller 			debug_fr(r, "sshbuf_put");
67a5ab499bSDamien Miller 			return r;
68a5ab499bSDamien Miller 		}
69a5ab499bSDamien Miller 		if (!clobber && (r = ssh_input_append(to, buf, len)) != 0) {
70a5ab499bSDamien Miller 			debug_fr(r, "ssh_input_append");
71a5ab499bSDamien Miller 			return r;
72a5ab499bSDamien Miller 		}
73a5ab499bSDamien Miller 	}
74a5ab499bSDamien Miller }
75a5ab499bSDamien Miller 
76a5ab499bSDamien Miller static int
run_kex(struct test_state * ts,struct ssh * client,struct ssh * server)77a5ab499bSDamien Miller run_kex(struct test_state *ts, struct ssh *client, struct ssh *server)
78a5ab499bSDamien Miller {
79a5ab499bSDamien Miller 	int r = 0;
80a5ab499bSDamien Miller 	size_t cn, sn;
81a5ab499bSDamien Miller 
82a5ab499bSDamien Miller 	/* If fuzzing, replace server/client input */
83a5ab499bSDamien Miller 	if (ts->sin != NULL) {
84a5ab499bSDamien Miller 		if ((r = ssh_input_append(server, sshbuf_ptr(ts->sin),
85a5ab499bSDamien Miller 		    sshbuf_len(ts->sin))) != 0) {
86a5ab499bSDamien Miller 			error_fr(r, "ssh_input_append");
87a5ab499bSDamien Miller 			return r;
88a5ab499bSDamien Miller 		}
89a5ab499bSDamien Miller 		sshbuf_reset(ts->sin);
90a5ab499bSDamien Miller 	}
91a5ab499bSDamien Miller 	if (ts->cin != NULL) {
92a5ab499bSDamien Miller 		if ((r = ssh_input_append(client, sshbuf_ptr(ts->cin),
93a5ab499bSDamien Miller 		    sshbuf_len(ts->cin))) != 0) {
94a5ab499bSDamien Miller 			error_fr(r, "ssh_input_append");
95a5ab499bSDamien Miller 			return r;
96a5ab499bSDamien Miller 		}
97a5ab499bSDamien Miller 		sshbuf_reset(ts->cin);
98a5ab499bSDamien Miller 	}
99a5ab499bSDamien Miller 	while (!server->kex->done || !client->kex->done) {
100a5ab499bSDamien Miller 		cn = sn = 0;
101a5ab499bSDamien Miller 		debug_f("S:");
102a5ab499bSDamien Miller 		if ((r = do_send_and_receive(server, client,
103a5ab499bSDamien Miller 		    ts->smsgs, ts->cin != NULL, &sn)) != 0) {
104a5ab499bSDamien Miller 			debug_fr(r, "S->C");
105a5ab499bSDamien Miller 			break;
106a5ab499bSDamien Miller 		}
107a5ab499bSDamien Miller 		debug_f("C:");
108a5ab499bSDamien Miller 		if ((r = do_send_and_receive(client, server,
109a5ab499bSDamien Miller 		    ts->cmsgs, ts->sin != NULL, &cn)) != 0) {
110a5ab499bSDamien Miller 			debug_fr(r, "C->S");
111a5ab499bSDamien Miller 			break;
112a5ab499bSDamien Miller 		}
113a5ab499bSDamien Miller 		if (cn == 0 && sn == 0) {
114a5ab499bSDamien Miller 			debug_f("kex stalled");
115a5ab499bSDamien Miller 			r = SSH_ERR_PROTOCOL_ERROR;
116a5ab499bSDamien Miller 			break;
117a5ab499bSDamien Miller 		}
118a5ab499bSDamien Miller 	}
119a5ab499bSDamien Miller 	debug_fr(r, "done");
120a5ab499bSDamien Miller 	return r;
121a5ab499bSDamien Miller }
122a5ab499bSDamien Miller 
123a5ab499bSDamien Miller static void
store_key(struct shared_state * st,struct sshkey * pubkey,struct sshkey * privkey)124a5ab499bSDamien Miller store_key(struct shared_state *st, struct sshkey *pubkey,
125a5ab499bSDamien Miller     struct sshkey *privkey)
126a5ab499bSDamien Miller {
127a5ab499bSDamien Miller 	if (st == NULL || pubkey->type < 0 || pubkey->type > INT_MAX ||
128a5ab499bSDamien Miller 	    privkey->type != pubkey->type ||
129a5ab499bSDamien Miller 	    ((size_t)pubkey->type < st->nkeys &&
130a5ab499bSDamien Miller 	     st->pubkeys[pubkey->type] != NULL))
131a5ab499bSDamien Miller 		abort();
132a5ab499bSDamien Miller 	if ((size_t)pubkey->type >= st->nkeys) {
133a5ab499bSDamien Miller 		st->pubkeys = (struct sshkey **)xrecallocarray(st->pubkeys,
134a5ab499bSDamien Miller 		    st->nkeys, pubkey->type + 1, sizeof(*st->pubkeys));
135a5ab499bSDamien Miller 		st->privkeys = (struct sshkey **)xrecallocarray(st->privkeys,
136a5ab499bSDamien Miller 		    st->nkeys, privkey->type + 1, sizeof(*st->privkeys));
137a5ab499bSDamien Miller 		st->nkeys = privkey->type + 1;
138a5ab499bSDamien Miller 	}
139a5ab499bSDamien Miller 	debug_f("store %s at %d", sshkey_ssh_name(pubkey), pubkey->type);
140a5ab499bSDamien Miller 	st->pubkeys[pubkey->type] = pubkey;
141a5ab499bSDamien Miller 	st->privkeys[privkey->type] = privkey;
142a5ab499bSDamien Miller }
143a5ab499bSDamien Miller 
144a5ab499bSDamien Miller static int
prepare_keys(struct shared_state * st)145a5ab499bSDamien Miller prepare_keys(struct shared_state *st)
146a5ab499bSDamien Miller {
147a5ab499bSDamien Miller 	if (prepare_key(st, KEY_RSA, 2048) != 0 ||
148a5ab499bSDamien Miller 	    prepare_key(st, KEY_DSA, 1024) != 0 ||
149a5ab499bSDamien Miller 	    prepare_key(st, KEY_ECDSA, 256) != 0 ||
150a5ab499bSDamien Miller 	    prepare_key(st, KEY_ED25519, 256) != 0) {
151a5ab499bSDamien Miller 		error_f("key prepare failed");
152a5ab499bSDamien Miller 		return -1;
153a5ab499bSDamien Miller 	}
154a5ab499bSDamien Miller 	return 0;
155a5ab499bSDamien Miller }
156a5ab499bSDamien Miller 
157a5ab499bSDamien Miller static struct sshkey *
get_pubkey(struct shared_state * st,int keytype)158a5ab499bSDamien Miller get_pubkey(struct shared_state *st, int keytype)
159a5ab499bSDamien Miller {
160a5ab499bSDamien Miller 	if (st == NULL || keytype < 0 || (size_t)keytype >= st->nkeys ||
161a5ab499bSDamien Miller 	    st->pubkeys == NULL || st->pubkeys[keytype] == NULL)
162a5ab499bSDamien Miller 		abort();
163a5ab499bSDamien Miller 	return st->pubkeys[keytype];
164a5ab499bSDamien Miller }
165a5ab499bSDamien Miller 
166a5ab499bSDamien Miller static struct sshkey *
get_privkey(struct shared_state * st,int keytype)167a5ab499bSDamien Miller get_privkey(struct shared_state *st, int keytype)
168a5ab499bSDamien Miller {
169a5ab499bSDamien Miller 	if (st == NULL || keytype < 0 || (size_t)keytype >= st->nkeys ||
170a5ab499bSDamien Miller 	    st->privkeys == NULL || st->privkeys[keytype] == NULL)
171a5ab499bSDamien Miller 		abort();
172a5ab499bSDamien Miller 	return st->privkeys[keytype];
173a5ab499bSDamien Miller }
174a5ab499bSDamien Miller 
175a5ab499bSDamien Miller static int
do_kex_with_key(struct shared_state * st,struct test_state * ts,const char * kex,int keytype)176a5ab499bSDamien Miller do_kex_with_key(struct shared_state *st, struct test_state *ts,
177a5ab499bSDamien Miller     const char *kex, int keytype)
178a5ab499bSDamien Miller {
179a5ab499bSDamien Miller 	struct ssh *client = NULL, *server = NULL;
180a5ab499bSDamien Miller 	struct sshkey *privkey = NULL, *pubkey = NULL;
181a5ab499bSDamien Miller 	struct sshbuf *state = NULL;
182a5ab499bSDamien Miller 	struct kex_params kex_params;
183a5ab499bSDamien Miller 	const char *ccp, *proposal[PROPOSAL_MAX] = { KEX_CLIENT };
184a5ab499bSDamien Miller 	char *myproposal[PROPOSAL_MAX] = {0}, *keyname = NULL;
185a5ab499bSDamien Miller 	int i, r;
186a5ab499bSDamien Miller 
187a5ab499bSDamien Miller 	ts->cin = ts->sin = NULL;
188a5ab499bSDamien Miller 	if (ts->c_template != NULL &&
189a5ab499bSDamien Miller 	    (ts->cin = sshbuf_fromb(ts->c_template)) == NULL)
190a5ab499bSDamien Miller 		abort();
191a5ab499bSDamien Miller 	if (ts->s_template != NULL &&
192a5ab499bSDamien Miller 	    (ts->sin = sshbuf_fromb(ts->s_template)) == NULL)
193a5ab499bSDamien Miller 		abort();
194a5ab499bSDamien Miller 
195a5ab499bSDamien Miller 	pubkey = get_pubkey(st, keytype);
196a5ab499bSDamien Miller 	privkey = get_privkey(st, keytype);
197a5ab499bSDamien Miller 	keyname = xstrdup(sshkey_ssh_name(privkey));
198be5f0048SDamien Miller 	if (ts->cin != NULL) {
199be5f0048SDamien Miller 		debug_f("%s %s clobber client %zu", kex, keyname,
200be5f0048SDamien Miller 		    sshbuf_len(ts->cin));
201be5f0048SDamien Miller 	} else if (ts->sin != NULL) {
202be5f0048SDamien Miller 		debug_f("%s %s clobber server %zu", kex, keyname,
203be5f0048SDamien Miller 		    sshbuf_len(ts->sin));
204be5f0048SDamien Miller 	} else
205be5f0048SDamien Miller 		debug_f("%s %s noclobber", kex, keyname);
206be5f0048SDamien Miller 
207a5ab499bSDamien Miller 	for (i = 0; i < PROPOSAL_MAX; i++) {
208a5ab499bSDamien Miller 		ccp = proposal[i];
209be5f0048SDamien Miller #ifdef CIPHER_NONE_AVAIL
210be5f0048SDamien Miller 		if (i == PROPOSAL_ENC_ALGS_CTOS || i == PROPOSAL_ENC_ALGS_STOC)
211be5f0048SDamien Miller 			ccp = "none";
212be5f0048SDamien Miller #endif
213a5ab499bSDamien Miller 		if (i == PROPOSAL_SERVER_HOST_KEY_ALGS)
214a5ab499bSDamien Miller 			ccp = keyname;
215a5ab499bSDamien Miller 		else if (i == PROPOSAL_KEX_ALGS && kex != NULL)
216a5ab499bSDamien Miller 			ccp = kex;
217a5ab499bSDamien Miller 		if ((myproposal[i] = strdup(ccp)) == NULL) {
218a5ab499bSDamien Miller 			error_f("strdup prop %d", i);
219a5ab499bSDamien Miller 			goto fail;
220a5ab499bSDamien Miller 		}
221a5ab499bSDamien Miller 	}
222a5ab499bSDamien Miller 	memcpy(kex_params.proposal, myproposal, sizeof(myproposal));
223a5ab499bSDamien Miller 	if ((r = ssh_init(&client, 0, &kex_params)) != 0) {
224a5ab499bSDamien Miller 		error_fr(r, "init client");
225a5ab499bSDamien Miller 		goto fail;
226a5ab499bSDamien Miller 	}
227a5ab499bSDamien Miller 	if ((r = ssh_init(&server, 1, &kex_params)) != 0) {
228a5ab499bSDamien Miller 		error_fr(r, "init server");
229a5ab499bSDamien Miller 		goto fail;
230a5ab499bSDamien Miller 	}
231a5ab499bSDamien Miller 	if ((r = ssh_add_hostkey(server, privkey)) != 0 ||
232a5ab499bSDamien Miller 	    (r = ssh_add_hostkey(client, pubkey)) != 0) {
233a5ab499bSDamien Miller 		error_fr(r, "add hostkeys");
234a5ab499bSDamien Miller 		goto fail;
235a5ab499bSDamien Miller 	}
236a5ab499bSDamien Miller 	if ((r = run_kex(ts, client, server)) != 0) {
237a5ab499bSDamien Miller 		error_fr(r, "kex");
238a5ab499bSDamien Miller 		goto fail;
239a5ab499bSDamien Miller 	}
240a5ab499bSDamien Miller 	/* XXX rekex, set_state, etc */
241a5ab499bSDamien Miller  fail:
242a5ab499bSDamien Miller 	for (i = 0; i < PROPOSAL_MAX; i++)
243a5ab499bSDamien Miller 		free(myproposal[i]);
244a5ab499bSDamien Miller 	sshbuf_free(ts->sin);
245a5ab499bSDamien Miller 	sshbuf_free(ts->cin);
246a5ab499bSDamien Miller 	sshbuf_free(state);
247a5ab499bSDamien Miller 	ssh_free(client);
248a5ab499bSDamien Miller 	ssh_free(server);
249a5ab499bSDamien Miller 	free(keyname);
250a5ab499bSDamien Miller 	return r;
251a5ab499bSDamien Miller }
252a5ab499bSDamien Miller 
253a5ab499bSDamien Miller static int
prepare_key(struct shared_state * st,int kt,int bits)254a5ab499bSDamien Miller prepare_key(struct shared_state *st, int kt, int bits)
255a5ab499bSDamien Miller {
256a5ab499bSDamien Miller 	const char *pubstr = NULL;
257a5ab499bSDamien Miller 	const char *privstr = NULL;
258a5ab499bSDamien Miller 	char *tmp, *cp;
259a5ab499bSDamien Miller 	struct sshkey *privkey = NULL, *pubkey = NULL;
260a5ab499bSDamien Miller 	struct sshbuf *b = NULL;
261a5ab499bSDamien Miller 	int r;
262a5ab499bSDamien Miller 
263a5ab499bSDamien Miller 	switch (kt) {
264a5ab499bSDamien Miller 	case KEY_RSA:
265a5ab499bSDamien Miller 		pubstr = PUB_RSA;
266a5ab499bSDamien Miller 		privstr = PRIV_RSA;
267a5ab499bSDamien Miller 		break;
268a5ab499bSDamien Miller 	case KEY_DSA:
269a5ab499bSDamien Miller 		pubstr = PUB_DSA;
270a5ab499bSDamien Miller 		privstr = PRIV_DSA;
271a5ab499bSDamien Miller 		break;
272a5ab499bSDamien Miller 	case KEY_ECDSA:
273a5ab499bSDamien Miller 		pubstr = PUB_ECDSA;
274a5ab499bSDamien Miller 		privstr = PRIV_ECDSA;
275a5ab499bSDamien Miller 		break;
276a5ab499bSDamien Miller 	case KEY_ED25519:
277a5ab499bSDamien Miller 		pubstr = PUB_ED25519;
278a5ab499bSDamien Miller 		privstr = PRIV_ED25519;
279a5ab499bSDamien Miller 		break;
280a5ab499bSDamien Miller 	default:
281a5ab499bSDamien Miller 		abort();
282a5ab499bSDamien Miller 	}
283a5ab499bSDamien Miller 	if ((b = sshbuf_from(privstr, strlen(privstr))) == NULL)
284a5ab499bSDamien Miller 		abort();
285a5ab499bSDamien Miller 	if ((r = sshkey_parse_private_fileblob(b, "", &privkey, NULL)) != 0) {
286a5ab499bSDamien Miller 		error_fr(r, "priv %d", kt);
287a5ab499bSDamien Miller 		abort();
288a5ab499bSDamien Miller 	}
289a5ab499bSDamien Miller 	sshbuf_free(b);
290a5ab499bSDamien Miller 	tmp = cp = xstrdup(pubstr);
291a5ab499bSDamien Miller 	if ((pubkey = sshkey_new(KEY_UNSPEC)) == NULL)
292a5ab499bSDamien Miller 		abort();
293a5ab499bSDamien Miller 	if ((r = sshkey_read(pubkey, &cp)) != 0) {
294a5ab499bSDamien Miller 		error_fr(r, "pub %d", kt);
295a5ab499bSDamien Miller 		abort();
296a5ab499bSDamien Miller 	}
297a5ab499bSDamien Miller 	free(tmp);
298a5ab499bSDamien Miller 
299a5ab499bSDamien Miller 	store_key(st, pubkey, privkey);
300a5ab499bSDamien Miller 	return 0;
301a5ab499bSDamien Miller }
302a5ab499bSDamien Miller 
303a5ab499bSDamien Miller #if defined(STANDALONE)
304a5ab499bSDamien Miller 
305a5ab499bSDamien Miller #if 0 /* use this if generating new keys to embed above */
306a5ab499bSDamien Miller static int
307a5ab499bSDamien Miller prepare_key(struct shared_state *st, int keytype, int bits)
308a5ab499bSDamien Miller {
309a5ab499bSDamien Miller 	struct sshkey *privkey = NULL, *pubkey = NULL;
310a5ab499bSDamien Miller 	int r;
311a5ab499bSDamien Miller 
312a5ab499bSDamien Miller 	if ((r = sshkey_generate(keytype, bits, &privkey)) != 0) {
313a5ab499bSDamien Miller 		error_fr(r, "generate");
314a5ab499bSDamien Miller 		abort();
315a5ab499bSDamien Miller 	}
316a5ab499bSDamien Miller 	if ((r = sshkey_from_private(privkey, &pubkey)) != 0) {
317a5ab499bSDamien Miller 		error_fr(r, "make pubkey");
318a5ab499bSDamien Miller 		abort();
319a5ab499bSDamien Miller 	}
320a5ab499bSDamien Miller 	store_key(st, pubkey, privkey);
321a5ab499bSDamien Miller 	return 0;
322a5ab499bSDamien Miller }
323a5ab499bSDamien Miller #endif
324a5ab499bSDamien Miller 
main(void)325a5ab499bSDamien Miller int main(void)
326a5ab499bSDamien Miller {
327a5ab499bSDamien Miller 	static struct shared_state *st;
328a5ab499bSDamien Miller 	struct test_state *ts;
329a5ab499bSDamien Miller 	const int keytypes[] = { KEY_RSA, KEY_DSA, KEY_ECDSA, KEY_ED25519, -1 };
330a5ab499bSDamien Miller 	const char *kextypes[] = {
3311134a48cSDamien Miller 		"sntrup761x25519-sha512@openssh.com",
332a5ab499bSDamien Miller 		"curve25519-sha256@libssh.org",
333a5ab499bSDamien Miller 		"ecdh-sha2-nistp256",
334a5ab499bSDamien Miller 		"diffie-hellman-group1-sha1",
335be5f0048SDamien Miller 		"diffie-hellman-group-exchange-sha1",
336a5ab499bSDamien Miller 		NULL,
337a5ab499bSDamien Miller 	};
338a5ab499bSDamien Miller 	int i, j;
339a5ab499bSDamien Miller 	char *path;
340a5ab499bSDamien Miller 	FILE *f;
341a5ab499bSDamien Miller 
342be5f0048SDamien Miller 	log_init("kex_fuzz", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1);
343be5f0048SDamien Miller 
344a5ab499bSDamien Miller 	if (st == NULL) {
345a5ab499bSDamien Miller 		st = (struct shared_state *)xcalloc(1, sizeof(*st));
346a5ab499bSDamien Miller 		prepare_keys(st);
347a5ab499bSDamien Miller 	}
348a5ab499bSDamien Miller 	/* Run each kex method for each key and save client/server packets */
349a5ab499bSDamien Miller 	for (i = 0; keytypes[i] != -1; i++) {
350a5ab499bSDamien Miller 		for (j = 0; kextypes[j] != NULL; j++) {
351a5ab499bSDamien Miller 			ts = (struct test_state *)xcalloc(1, sizeof(*ts));
352a5ab499bSDamien Miller 			ts->smsgs = sshbuf_new();
353a5ab499bSDamien Miller 			ts->cmsgs = sshbuf_new();
354a5ab499bSDamien Miller 			do_kex_with_key(st, ts, kextypes[j], keytypes[i]);
355a5ab499bSDamien Miller 			xasprintf(&path, "S2C-%s-%s",
356a5ab499bSDamien Miller 			    kextypes[j], sshkey_type(st->pubkeys[keytypes[i]]));
357a5ab499bSDamien Miller 			debug_f("%s", path);
358a5ab499bSDamien Miller 			if ((f = fopen(path, "wb+")) == NULL)
359a5ab499bSDamien Miller 				abort();
360a5ab499bSDamien Miller 			if (fwrite(sshbuf_ptr(ts->smsgs), 1,
361a5ab499bSDamien Miller 			    sshbuf_len(ts->smsgs), f) != sshbuf_len(ts->smsgs))
362a5ab499bSDamien Miller 				abort();
363a5ab499bSDamien Miller 			fclose(f);
364a5ab499bSDamien Miller 			free(path);
365a5ab499bSDamien Miller 			//sshbuf_dump(ts->smsgs, stderr);
366a5ab499bSDamien Miller 			xasprintf(&path, "C2S-%s-%s",
367a5ab499bSDamien Miller 			    kextypes[j], sshkey_type(st->pubkeys[keytypes[i]]));
368a5ab499bSDamien Miller 			debug_f("%s", path);
369a5ab499bSDamien Miller 			if ((f = fopen(path, "wb+")) == NULL)
370a5ab499bSDamien Miller 				abort();
371a5ab499bSDamien Miller 			if (fwrite(sshbuf_ptr(ts->cmsgs), 1,
372a5ab499bSDamien Miller 			    sshbuf_len(ts->cmsgs), f) != sshbuf_len(ts->cmsgs))
373a5ab499bSDamien Miller 				abort();
374a5ab499bSDamien Miller 			fclose(f);
375a5ab499bSDamien Miller 			free(path);
376a5ab499bSDamien Miller 			//sshbuf_dump(ts->cmsgs, stderr);
377a5ab499bSDamien Miller 			sshbuf_free(ts->smsgs);
378a5ab499bSDamien Miller 			sshbuf_free(ts->cmsgs);
379a5ab499bSDamien Miller 			free(ts);
380a5ab499bSDamien Miller 		}
381a5ab499bSDamien Miller 	}
382a5ab499bSDamien Miller 	for (i = 0; keytypes[i] != -1; i++) {
383a5ab499bSDamien Miller 		xasprintf(&path, "%s.priv",
384a5ab499bSDamien Miller 		    sshkey_type(st->privkeys[keytypes[i]]));
385a5ab499bSDamien Miller 		debug_f("%s", path);
386a5ab499bSDamien Miller 		if (sshkey_save_private(st->privkeys[keytypes[i]], path,
387a5ab499bSDamien Miller 		    "", "", SSHKEY_PRIVATE_OPENSSH, NULL, 0) != 0)
388a5ab499bSDamien Miller 			abort();
389a5ab499bSDamien Miller 		free(path);
390a5ab499bSDamien Miller 		xasprintf(&path, "%s.pub",
391a5ab499bSDamien Miller 		    sshkey_type(st->pubkeys[keytypes[i]]));
392a5ab499bSDamien Miller 		debug_f("%s", path);
393a5ab499bSDamien Miller 		if (sshkey_save_public(st->pubkeys[keytypes[i]], path, "") != 0)
394a5ab499bSDamien Miller 			abort();
395a5ab499bSDamien Miller 		free(path);
396a5ab499bSDamien Miller 	}
397a5ab499bSDamien Miller }
398a5ab499bSDamien Miller #else /* !STANDALONE */
399a5ab499bSDamien Miller static void
do_kex(struct shared_state * st,struct test_state * ts,const char * kex)400a5ab499bSDamien Miller do_kex(struct shared_state *st, struct test_state *ts, const char *kex)
401a5ab499bSDamien Miller {
402a5ab499bSDamien Miller 	do_kex_with_key(st, ts, kex, KEY_RSA);
403a5ab499bSDamien Miller 	do_kex_with_key(st, ts, kex, KEY_DSA);
404a5ab499bSDamien Miller 	do_kex_with_key(st, ts, kex, KEY_ECDSA);
405a5ab499bSDamien Miller 	do_kex_with_key(st, ts, kex, KEY_ED25519);
406a5ab499bSDamien Miller }
407a5ab499bSDamien Miller 
408a5ab499bSDamien Miller static void
kex_tests(struct shared_state * st,struct test_state * ts)409a5ab499bSDamien Miller kex_tests(struct shared_state *st, struct test_state *ts)
410a5ab499bSDamien Miller {
4115c1953bfSDamien Miller 	do_kex(st, ts, "sntrup761x25519-sha512@openssh.com");
412a5ab499bSDamien Miller 	do_kex(st, ts, "curve25519-sha256@libssh.org");
413a5ab499bSDamien Miller 	do_kex(st, ts, "ecdh-sha2-nistp256");
414a5ab499bSDamien Miller 	do_kex(st, ts, "diffie-hellman-group1-sha1");
4151e660115SDamien Miller 	do_kex(st, ts, "diffie-hellman-group-exchange-sha1");
416a5ab499bSDamien Miller }
417a5ab499bSDamien Miller 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)418a5ab499bSDamien Miller int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
419a5ab499bSDamien Miller {
420a5ab499bSDamien Miller 	static struct shared_state *st;
421a5ab499bSDamien Miller 	struct test_state *ts;
422a5ab499bSDamien Miller 	u_char crbuf[SSH_MAX_PRE_BANNER_LINES * 4];
423a5ab499bSDamien Miller 	u_char zbuf[4096] = {0};
424a5ab499bSDamien Miller 	static LogLevel loglevel = SYSLOG_LEVEL_INFO;
425a5ab499bSDamien Miller 
426a5ab499bSDamien Miller 	if (st == NULL) {
427a5ab499bSDamien Miller 		if (getenv("DEBUG") != NULL || getenv("KEX_FUZZ_DEBUG") != NULL)
428a5ab499bSDamien Miller 			loglevel = SYSLOG_LEVEL_DEBUG3;
429a5ab499bSDamien Miller 		log_init("kex_fuzz",
430a5ab499bSDamien Miller 		    loglevel, SYSLOG_FACILITY_AUTH, 1);
431a5ab499bSDamien Miller 		st = (struct shared_state *)xcalloc(1, sizeof(*st));
432a5ab499bSDamien Miller 		prepare_keys(st);
433a5ab499bSDamien Miller 	}
434a5ab499bSDamien Miller 
435a5ab499bSDamien Miller 	/* Ensure that we can complete (fail) banner exchange at least */
436a5ab499bSDamien Miller 	memset(crbuf, '\n', sizeof(crbuf));
437a5ab499bSDamien Miller 
438a5ab499bSDamien Miller 	ts = (struct test_state *)xcalloc(1, sizeof(*ts));
439a5ab499bSDamien Miller 	if ((ts->s_template = sshbuf_new()) == NULL ||
440a5ab499bSDamien Miller 	    sshbuf_put(ts->s_template, data, size) != 0 ||
441a5ab499bSDamien Miller 	    sshbuf_put(ts->s_template, crbuf, sizeof(crbuf)) != 0 ||
442a5ab499bSDamien Miller 	    sshbuf_put(ts->s_template, zbuf, sizeof(zbuf)) != 0)
443a5ab499bSDamien Miller 		abort();
444a5ab499bSDamien Miller 	kex_tests(st, ts);
445a5ab499bSDamien Miller 	sshbuf_free(ts->s_template);
446a5ab499bSDamien Miller 	free(ts);
447a5ab499bSDamien Miller 
448a5ab499bSDamien Miller 	ts = (struct test_state *)xcalloc(1, sizeof(*ts));
449a5ab499bSDamien Miller 	if ((ts->c_template = sshbuf_new()) == NULL ||
450a5ab499bSDamien Miller 	    sshbuf_put(ts->c_template, data, size) != 0 ||
451a5ab499bSDamien Miller 	    sshbuf_put(ts->c_template, crbuf, sizeof(crbuf)) != 0 ||
452a5ab499bSDamien Miller 	    sshbuf_put(ts->c_template, zbuf, sizeof(zbuf)) != 0)
453a5ab499bSDamien Miller 		abort();
454a5ab499bSDamien Miller 	kex_tests(st, ts);
455a5ab499bSDamien Miller 	sshbuf_free(ts->c_template);
456a5ab499bSDamien Miller 	free(ts);
457a5ab499bSDamien Miller 
458a5ab499bSDamien Miller 	return 0;
459a5ab499bSDamien Miller }
460a5ab499bSDamien Miller #endif /* STANDALONE */
461a5ab499bSDamien Miller } /* extern "C" */
462