xref: /freebsd-src/crypto/openssh/regress/misc/fuzz-harness/kex_fuzz.cc (revision 1323ec571215a77ddd21294f0871979d5ad6b992)
119261079SEd Maste // libfuzzer driver for key exchange fuzzing.
219261079SEd Maste 
319261079SEd Maste 
419261079SEd Maste #include <sys/types.h>
519261079SEd Maste #include <stdio.h>
619261079SEd Maste #include <stdint.h>
719261079SEd Maste #include <stdlib.h>
819261079SEd Maste #include <string.h>
919261079SEd Maste 
1019261079SEd Maste extern "C" {
1119261079SEd Maste 
1219261079SEd Maste #include "includes.h"
1319261079SEd Maste #include "ssherr.h"
1419261079SEd Maste #include "ssh_api.h"
1519261079SEd Maste #include "sshbuf.h"
1619261079SEd Maste #include "packet.h"
1719261079SEd Maste #include "myproposal.h"
1819261079SEd Maste #include "xmalloc.h"
1919261079SEd Maste #include "authfile.h"
2019261079SEd Maste #include "log.h"
2119261079SEd Maste 
2219261079SEd Maste #include "fixed-keys.h"
2319261079SEd Maste 
2419261079SEd Maste // Define if you want to generate traces.
2519261079SEd Maste /* #define STANDALONE 1 */
2619261079SEd Maste 
2719261079SEd Maste static int prepare_key(struct shared_state *st, int keytype, int bits);
2819261079SEd Maste 
2919261079SEd Maste struct shared_state {
3019261079SEd Maste 	size_t nkeys;
3119261079SEd Maste 	struct sshkey **privkeys, **pubkeys;
3219261079SEd Maste };
3319261079SEd Maste 
3419261079SEd Maste struct test_state {
3519261079SEd Maste 	struct sshbuf *smsgs, *cmsgs; /* output, for standalone mode */
3619261079SEd Maste 	struct sshbuf *sin, *cin; /* input; setup per-test in do_kex_with_key */
3719261079SEd Maste 	struct sshbuf *s_template, *c_template; /* main copy of input */
3819261079SEd Maste };
3919261079SEd Maste 
4019261079SEd Maste static int
do_send_and_receive(struct ssh * from,struct ssh * to,struct sshbuf * store,int clobber,size_t * n)4119261079SEd Maste do_send_and_receive(struct ssh *from, struct ssh *to,
4219261079SEd Maste     struct sshbuf *store, int clobber, size_t *n)
4319261079SEd Maste {
4419261079SEd Maste 	u_char type;
4519261079SEd Maste 	size_t len;
4619261079SEd Maste 	const u_char *buf;
4719261079SEd Maste 	int r;
4819261079SEd Maste 
4919261079SEd Maste 	for (*n = 0;; (*n)++) {
5019261079SEd Maste 		if ((r = ssh_packet_next(from, &type)) != 0) {
5119261079SEd Maste 			debug_fr(r, "ssh_packet_next");
5219261079SEd Maste 			return r;
5319261079SEd Maste 		}
5419261079SEd Maste 		if (type != 0)
5519261079SEd Maste 			return 0;
5619261079SEd Maste 		buf = ssh_output_ptr(from, &len);
5719261079SEd Maste 		debug_f("%zu%s", len, clobber ? " ignore" : "");
5819261079SEd Maste 		if (len == 0)
5919261079SEd Maste 			return 0;
6019261079SEd Maste 		if ((r = ssh_output_consume(from, len)) != 0) {
6119261079SEd Maste 			debug_fr(r, "ssh_output_consume");
6219261079SEd Maste 			return r;
6319261079SEd Maste 		}
6419261079SEd Maste 		if (store != NULL && (r = sshbuf_put(store, buf, len)) != 0) {
6519261079SEd Maste 			debug_fr(r, "sshbuf_put");
6619261079SEd Maste 			return r;
6719261079SEd Maste 		}
6819261079SEd Maste 		if (!clobber && (r = ssh_input_append(to, buf, len)) != 0) {
6919261079SEd Maste 			debug_fr(r, "ssh_input_append");
7019261079SEd Maste 			return r;
7119261079SEd Maste 		}
7219261079SEd Maste 	}
7319261079SEd Maste }
7419261079SEd Maste 
7519261079SEd Maste static int
run_kex(struct test_state * ts,struct ssh * client,struct ssh * server)7619261079SEd Maste run_kex(struct test_state *ts, struct ssh *client, struct ssh *server)
7719261079SEd Maste {
7819261079SEd Maste 	int r = 0;
7919261079SEd Maste 	size_t cn, sn;
8019261079SEd Maste 
8119261079SEd Maste 	/* If fuzzing, replace server/client input */
8219261079SEd Maste 	if (ts->sin != NULL) {
8319261079SEd Maste 		if ((r = ssh_input_append(server, sshbuf_ptr(ts->sin),
8419261079SEd Maste 		    sshbuf_len(ts->sin))) != 0) {
8519261079SEd Maste 			error_fr(r, "ssh_input_append");
8619261079SEd Maste 			return r;
8719261079SEd Maste 		}
8819261079SEd Maste 		sshbuf_reset(ts->sin);
8919261079SEd Maste 	}
9019261079SEd Maste 	if (ts->cin != NULL) {
9119261079SEd Maste 		if ((r = ssh_input_append(client, sshbuf_ptr(ts->cin),
9219261079SEd Maste 		    sshbuf_len(ts->cin))) != 0) {
9319261079SEd Maste 			error_fr(r, "ssh_input_append");
9419261079SEd Maste 			return r;
9519261079SEd Maste 		}
9619261079SEd Maste 		sshbuf_reset(ts->cin);
9719261079SEd Maste 	}
9819261079SEd Maste 	while (!server->kex->done || !client->kex->done) {
9919261079SEd Maste 		cn = sn = 0;
10019261079SEd Maste 		debug_f("S:");
10119261079SEd Maste 		if ((r = do_send_and_receive(server, client,
10219261079SEd Maste 		    ts->smsgs, ts->cin != NULL, &sn)) != 0) {
10319261079SEd Maste 			debug_fr(r, "S->C");
10419261079SEd Maste 			break;
10519261079SEd Maste 		}
10619261079SEd Maste 		debug_f("C:");
10719261079SEd Maste 		if ((r = do_send_and_receive(client, server,
10819261079SEd Maste 		    ts->cmsgs, ts->sin != NULL, &cn)) != 0) {
10919261079SEd Maste 			debug_fr(r, "C->S");
11019261079SEd Maste 			break;
11119261079SEd Maste 		}
11219261079SEd Maste 		if (cn == 0 && sn == 0) {
11319261079SEd Maste 			debug_f("kex stalled");
11419261079SEd Maste 			r = SSH_ERR_PROTOCOL_ERROR;
11519261079SEd Maste 			break;
11619261079SEd Maste 		}
11719261079SEd Maste 	}
11819261079SEd Maste 	debug_fr(r, "done");
11919261079SEd Maste 	return r;
12019261079SEd Maste }
12119261079SEd Maste 
12219261079SEd Maste static void
store_key(struct shared_state * st,struct sshkey * pubkey,struct sshkey * privkey)12319261079SEd Maste store_key(struct shared_state *st, struct sshkey *pubkey,
12419261079SEd Maste     struct sshkey *privkey)
12519261079SEd Maste {
12619261079SEd Maste 	if (st == NULL || pubkey->type < 0 || pubkey->type > INT_MAX ||
12719261079SEd Maste 	    privkey->type != pubkey->type ||
12819261079SEd Maste 	    ((size_t)pubkey->type < st->nkeys &&
12919261079SEd Maste 	     st->pubkeys[pubkey->type] != NULL))
13019261079SEd Maste 		abort();
13119261079SEd Maste 	if ((size_t)pubkey->type >= st->nkeys) {
13219261079SEd Maste 		st->pubkeys = (struct sshkey **)xrecallocarray(st->pubkeys,
13319261079SEd Maste 		    st->nkeys, pubkey->type + 1, sizeof(*st->pubkeys));
13419261079SEd Maste 		st->privkeys = (struct sshkey **)xrecallocarray(st->privkeys,
13519261079SEd Maste 		    st->nkeys, privkey->type + 1, sizeof(*st->privkeys));
13619261079SEd Maste 		st->nkeys = privkey->type + 1;
13719261079SEd Maste 	}
13819261079SEd Maste 	debug_f("store %s at %d", sshkey_ssh_name(pubkey), pubkey->type);
13919261079SEd Maste 	st->pubkeys[pubkey->type] = pubkey;
14019261079SEd Maste 	st->privkeys[privkey->type] = privkey;
14119261079SEd Maste }
14219261079SEd Maste 
14319261079SEd Maste static int
prepare_keys(struct shared_state * st)14419261079SEd Maste prepare_keys(struct shared_state *st)
14519261079SEd Maste {
14619261079SEd Maste 	if (prepare_key(st, KEY_RSA, 2048) != 0 ||
14719261079SEd Maste 	    prepare_key(st, KEY_DSA, 1024) != 0 ||
14819261079SEd Maste 	    prepare_key(st, KEY_ECDSA, 256) != 0 ||
14919261079SEd Maste 	    prepare_key(st, KEY_ED25519, 256) != 0) {
15019261079SEd Maste 		error_f("key prepare failed");
15119261079SEd Maste 		return -1;
15219261079SEd Maste 	}
15319261079SEd Maste 	return 0;
15419261079SEd Maste }
15519261079SEd Maste 
15619261079SEd Maste static struct sshkey *
get_pubkey(struct shared_state * st,int keytype)15719261079SEd Maste get_pubkey(struct shared_state *st, int keytype)
15819261079SEd Maste {
15919261079SEd Maste 	if (st == NULL || keytype < 0 || (size_t)keytype >= st->nkeys ||
16019261079SEd Maste 	    st->pubkeys == NULL || st->pubkeys[keytype] == NULL)
16119261079SEd Maste 		abort();
16219261079SEd Maste 	return st->pubkeys[keytype];
16319261079SEd Maste }
16419261079SEd Maste 
16519261079SEd Maste static struct sshkey *
get_privkey(struct shared_state * st,int keytype)16619261079SEd Maste get_privkey(struct shared_state *st, int keytype)
16719261079SEd Maste {
16819261079SEd Maste 	if (st == NULL || keytype < 0 || (size_t)keytype >= st->nkeys ||
16919261079SEd Maste 	    st->privkeys == NULL || st->privkeys[keytype] == NULL)
17019261079SEd Maste 		abort();
17119261079SEd Maste 	return st->privkeys[keytype];
17219261079SEd Maste }
17319261079SEd Maste 
17419261079SEd Maste static int
do_kex_with_key(struct shared_state * st,struct test_state * ts,const char * kex,int keytype)17519261079SEd Maste do_kex_with_key(struct shared_state *st, struct test_state *ts,
17619261079SEd Maste     const char *kex, int keytype)
17719261079SEd Maste {
17819261079SEd Maste 	struct ssh *client = NULL, *server = NULL;
17919261079SEd Maste 	struct sshkey *privkey = NULL, *pubkey = NULL;
18019261079SEd Maste 	struct sshbuf *state = NULL;
18119261079SEd Maste 	struct kex_params kex_params;
18219261079SEd Maste 	const char *ccp, *proposal[PROPOSAL_MAX] = { KEX_CLIENT };
18319261079SEd Maste 	char *myproposal[PROPOSAL_MAX] = {0}, *keyname = NULL;
18419261079SEd Maste 	int i, r;
18519261079SEd Maste 
18619261079SEd Maste 	ts->cin = ts->sin = NULL;
18719261079SEd Maste 	if (ts->c_template != NULL &&
18819261079SEd Maste 	    (ts->cin = sshbuf_fromb(ts->c_template)) == NULL)
18919261079SEd Maste 		abort();
19019261079SEd Maste 	if (ts->s_template != NULL &&
19119261079SEd Maste 	    (ts->sin = sshbuf_fromb(ts->s_template)) == NULL)
19219261079SEd Maste 		abort();
19319261079SEd Maste 
19419261079SEd Maste 	pubkey = get_pubkey(st, keytype);
19519261079SEd Maste 	privkey = get_privkey(st, keytype);
19619261079SEd Maste 	keyname = xstrdup(sshkey_ssh_name(privkey));
19719261079SEd Maste 	if (ts->cin != NULL) {
19819261079SEd Maste 		debug_f("%s %s clobber client %zu", kex, keyname,
19919261079SEd Maste 		    sshbuf_len(ts->cin));
20019261079SEd Maste 	} else if (ts->sin != NULL) {
20119261079SEd Maste 		debug_f("%s %s clobber server %zu", kex, keyname,
20219261079SEd Maste 		    sshbuf_len(ts->sin));
20319261079SEd Maste 	} else
20419261079SEd Maste 		debug_f("%s %s noclobber", kex, keyname);
20519261079SEd Maste 
20619261079SEd Maste 	for (i = 0; i < PROPOSAL_MAX; i++) {
20719261079SEd Maste 		ccp = proposal[i];
20819261079SEd Maste #ifdef CIPHER_NONE_AVAIL
20919261079SEd Maste 		if (i == PROPOSAL_ENC_ALGS_CTOS || i == PROPOSAL_ENC_ALGS_STOC)
21019261079SEd Maste 			ccp = "none";
21119261079SEd Maste #endif
21219261079SEd Maste 		if (i == PROPOSAL_SERVER_HOST_KEY_ALGS)
21319261079SEd Maste 			ccp = keyname;
21419261079SEd Maste 		else if (i == PROPOSAL_KEX_ALGS && kex != NULL)
21519261079SEd Maste 			ccp = kex;
21619261079SEd Maste 		if ((myproposal[i] = strdup(ccp)) == NULL) {
21719261079SEd Maste 			error_f("strdup prop %d", i);
21819261079SEd Maste 			goto fail;
21919261079SEd Maste 		}
22019261079SEd Maste 	}
22119261079SEd Maste 	memcpy(kex_params.proposal, myproposal, sizeof(myproposal));
22219261079SEd Maste 	if ((r = ssh_init(&client, 0, &kex_params)) != 0) {
22319261079SEd Maste 		error_fr(r, "init client");
22419261079SEd Maste 		goto fail;
22519261079SEd Maste 	}
22619261079SEd Maste 	if ((r = ssh_init(&server, 1, &kex_params)) != 0) {
22719261079SEd Maste 		error_fr(r, "init server");
22819261079SEd Maste 		goto fail;
22919261079SEd Maste 	}
23019261079SEd Maste 	if ((r = ssh_add_hostkey(server, privkey)) != 0 ||
23119261079SEd Maste 	    (r = ssh_add_hostkey(client, pubkey)) != 0) {
23219261079SEd Maste 		error_fr(r, "add hostkeys");
23319261079SEd Maste 		goto fail;
23419261079SEd Maste 	}
23519261079SEd Maste 	if ((r = run_kex(ts, client, server)) != 0) {
23619261079SEd Maste 		error_fr(r, "kex");
23719261079SEd Maste 		goto fail;
23819261079SEd Maste 	}
23919261079SEd Maste 	/* XXX rekex, set_state, etc */
24019261079SEd Maste  fail:
24119261079SEd Maste 	for (i = 0; i < PROPOSAL_MAX; i++)
24219261079SEd Maste 		free(myproposal[i]);
24319261079SEd Maste 	sshbuf_free(ts->sin);
24419261079SEd Maste 	sshbuf_free(ts->cin);
24519261079SEd Maste 	sshbuf_free(state);
24619261079SEd Maste 	ssh_free(client);
24719261079SEd Maste 	ssh_free(server);
24819261079SEd Maste 	free(keyname);
24919261079SEd Maste 	return r;
25019261079SEd Maste }
25119261079SEd Maste 
25219261079SEd Maste static int
prepare_key(struct shared_state * st,int kt,int bits)25319261079SEd Maste prepare_key(struct shared_state *st, int kt, int bits)
25419261079SEd Maste {
25519261079SEd Maste 	const char *pubstr = NULL;
25619261079SEd Maste 	const char *privstr = NULL;
25719261079SEd Maste 	char *tmp, *cp;
25819261079SEd Maste 	struct sshkey *privkey = NULL, *pubkey = NULL;
25919261079SEd Maste 	struct sshbuf *b = NULL;
26019261079SEd Maste 	int r;
26119261079SEd Maste 
26219261079SEd Maste 	switch (kt) {
26319261079SEd Maste 	case KEY_RSA:
26419261079SEd Maste 		pubstr = PUB_RSA;
26519261079SEd Maste 		privstr = PRIV_RSA;
26619261079SEd Maste 		break;
26719261079SEd Maste 	case KEY_DSA:
26819261079SEd Maste 		pubstr = PUB_DSA;
26919261079SEd Maste 		privstr = PRIV_DSA;
27019261079SEd Maste 		break;
27119261079SEd Maste 	case KEY_ECDSA:
27219261079SEd Maste 		pubstr = PUB_ECDSA;
27319261079SEd Maste 		privstr = PRIV_ECDSA;
27419261079SEd Maste 		break;
27519261079SEd Maste 	case KEY_ED25519:
27619261079SEd Maste 		pubstr = PUB_ED25519;
27719261079SEd Maste 		privstr = PRIV_ED25519;
27819261079SEd Maste 		break;
27919261079SEd Maste 	default:
28019261079SEd Maste 		abort();
28119261079SEd Maste 	}
28219261079SEd Maste 	if ((b = sshbuf_from(privstr, strlen(privstr))) == NULL)
28319261079SEd Maste 		abort();
28419261079SEd Maste 	if ((r = sshkey_parse_private_fileblob(b, "", &privkey, NULL)) != 0) {
28519261079SEd Maste 		error_fr(r, "priv %d", kt);
28619261079SEd Maste 		abort();
28719261079SEd Maste 	}
28819261079SEd Maste 	sshbuf_free(b);
28919261079SEd Maste 	tmp = cp = xstrdup(pubstr);
29019261079SEd Maste 	if ((pubkey = sshkey_new(KEY_UNSPEC)) == NULL)
29119261079SEd Maste 		abort();
29219261079SEd Maste 	if ((r = sshkey_read(pubkey, &cp)) != 0) {
29319261079SEd Maste 		error_fr(r, "pub %d", kt);
29419261079SEd Maste 		abort();
29519261079SEd Maste 	}
29619261079SEd Maste 	free(tmp);
29719261079SEd Maste 
29819261079SEd Maste 	store_key(st, pubkey, privkey);
29919261079SEd Maste 	return 0;
30019261079SEd Maste }
30119261079SEd Maste 
30219261079SEd Maste #if defined(STANDALONE)
30319261079SEd Maste 
30419261079SEd Maste #if 0 /* use this if generating new keys to embed above */
30519261079SEd Maste static int
30619261079SEd Maste prepare_key(struct shared_state *st, int keytype, int bits)
30719261079SEd Maste {
30819261079SEd Maste 	struct sshkey *privkey = NULL, *pubkey = NULL;
30919261079SEd Maste 	int r;
31019261079SEd Maste 
31119261079SEd Maste 	if ((r = sshkey_generate(keytype, bits, &privkey)) != 0) {
31219261079SEd Maste 		error_fr(r, "generate");
31319261079SEd Maste 		abort();
31419261079SEd Maste 	}
31519261079SEd Maste 	if ((r = sshkey_from_private(privkey, &pubkey)) != 0) {
31619261079SEd Maste 		error_fr(r, "make pubkey");
31719261079SEd Maste 		abort();
31819261079SEd Maste 	}
31919261079SEd Maste 	store_key(st, pubkey, privkey);
32019261079SEd Maste 	return 0;
32119261079SEd Maste }
32219261079SEd Maste #endif
32319261079SEd Maste 
main(void)32419261079SEd Maste int main(void)
32519261079SEd Maste {
32619261079SEd Maste 	static struct shared_state *st;
32719261079SEd Maste 	struct test_state *ts;
32819261079SEd Maste 	const int keytypes[] = { KEY_RSA, KEY_DSA, KEY_ECDSA, KEY_ED25519, -1 };
329*1323ec57SEd Maste 	static const char * const kextypes[] = {
33019261079SEd Maste 		"sntrup761x25519-sha512@openssh.com",
33119261079SEd Maste 		"curve25519-sha256@libssh.org",
33219261079SEd Maste 		"ecdh-sha2-nistp256",
33319261079SEd Maste 		"diffie-hellman-group1-sha1",
33419261079SEd Maste 		"diffie-hellman-group-exchange-sha1",
33519261079SEd Maste 		NULL,
33619261079SEd Maste 	};
33719261079SEd Maste 	int i, j;
33819261079SEd Maste 	char *path;
33919261079SEd Maste 	FILE *f;
34019261079SEd Maste 
34119261079SEd Maste 	log_init("kex_fuzz", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1);
34219261079SEd Maste 
34319261079SEd Maste 	if (st == NULL) {
34419261079SEd Maste 		st = (struct shared_state *)xcalloc(1, sizeof(*st));
34519261079SEd Maste 		prepare_keys(st);
34619261079SEd Maste 	}
34719261079SEd Maste 	/* Run each kex method for each key and save client/server packets */
34819261079SEd Maste 	for (i = 0; keytypes[i] != -1; i++) {
34919261079SEd Maste 		for (j = 0; kextypes[j] != NULL; j++) {
35019261079SEd Maste 			ts = (struct test_state *)xcalloc(1, sizeof(*ts));
35119261079SEd Maste 			ts->smsgs = sshbuf_new();
35219261079SEd Maste 			ts->cmsgs = sshbuf_new();
35319261079SEd Maste 			do_kex_with_key(st, ts, kextypes[j], keytypes[i]);
35419261079SEd Maste 			xasprintf(&path, "S2C-%s-%s",
35519261079SEd Maste 			    kextypes[j], sshkey_type(st->pubkeys[keytypes[i]]));
35619261079SEd Maste 			debug_f("%s", path);
35719261079SEd Maste 			if ((f = fopen(path, "wb+")) == NULL)
35819261079SEd Maste 				abort();
35919261079SEd Maste 			if (fwrite(sshbuf_ptr(ts->smsgs), 1,
36019261079SEd Maste 			    sshbuf_len(ts->smsgs), f) != sshbuf_len(ts->smsgs))
36119261079SEd Maste 				abort();
36219261079SEd Maste 			fclose(f);
36319261079SEd Maste 			free(path);
36419261079SEd Maste 			//sshbuf_dump(ts->smsgs, stderr);
36519261079SEd Maste 			xasprintf(&path, "C2S-%s-%s",
36619261079SEd Maste 			    kextypes[j], sshkey_type(st->pubkeys[keytypes[i]]));
36719261079SEd Maste 			debug_f("%s", path);
36819261079SEd Maste 			if ((f = fopen(path, "wb+")) == NULL)
36919261079SEd Maste 				abort();
37019261079SEd Maste 			if (fwrite(sshbuf_ptr(ts->cmsgs), 1,
37119261079SEd Maste 			    sshbuf_len(ts->cmsgs), f) != sshbuf_len(ts->cmsgs))
37219261079SEd Maste 				abort();
37319261079SEd Maste 			fclose(f);
37419261079SEd Maste 			free(path);
37519261079SEd Maste 			//sshbuf_dump(ts->cmsgs, stderr);
37619261079SEd Maste 			sshbuf_free(ts->smsgs);
37719261079SEd Maste 			sshbuf_free(ts->cmsgs);
37819261079SEd Maste 			free(ts);
37919261079SEd Maste 		}
38019261079SEd Maste 	}
38119261079SEd Maste 	for (i = 0; keytypes[i] != -1; i++) {
38219261079SEd Maste 		xasprintf(&path, "%s.priv",
38319261079SEd Maste 		    sshkey_type(st->privkeys[keytypes[i]]));
38419261079SEd Maste 		debug_f("%s", path);
38519261079SEd Maste 		if (sshkey_save_private(st->privkeys[keytypes[i]], path,
38619261079SEd Maste 		    "", "", SSHKEY_PRIVATE_OPENSSH, NULL, 0) != 0)
38719261079SEd Maste 			abort();
38819261079SEd Maste 		free(path);
38919261079SEd Maste 		xasprintf(&path, "%s.pub",
39019261079SEd Maste 		    sshkey_type(st->pubkeys[keytypes[i]]));
39119261079SEd Maste 		debug_f("%s", path);
39219261079SEd Maste 		if (sshkey_save_public(st->pubkeys[keytypes[i]], path, "") != 0)
39319261079SEd Maste 			abort();
39419261079SEd Maste 		free(path);
39519261079SEd Maste 	}
39619261079SEd Maste }
39719261079SEd Maste #else /* !STANDALONE */
39819261079SEd Maste static void
do_kex(struct shared_state * st,struct test_state * ts,const char * kex)39919261079SEd Maste do_kex(struct shared_state *st, struct test_state *ts, const char *kex)
40019261079SEd Maste {
40119261079SEd Maste 	do_kex_with_key(st, ts, kex, KEY_RSA);
40219261079SEd Maste 	do_kex_with_key(st, ts, kex, KEY_DSA);
40319261079SEd Maste 	do_kex_with_key(st, ts, kex, KEY_ECDSA);
40419261079SEd Maste 	do_kex_with_key(st, ts, kex, KEY_ED25519);
40519261079SEd Maste }
40619261079SEd Maste 
40719261079SEd Maste static void
kex_tests(struct shared_state * st,struct test_state * ts)40819261079SEd Maste kex_tests(struct shared_state *st, struct test_state *ts)
40919261079SEd Maste {
41019261079SEd Maste 	do_kex(st, ts, "sntrup761x25519-sha512@openssh.com");
41119261079SEd Maste 	do_kex(st, ts, "curve25519-sha256@libssh.org");
41219261079SEd Maste 	do_kex(st, ts, "ecdh-sha2-nistp256");
41319261079SEd Maste 	do_kex(st, ts, "diffie-hellman-group1-sha1");
41419261079SEd Maste 	do_kex(st, ts, "diffie-hellman-group-exchange-sha1");
41519261079SEd Maste }
41619261079SEd Maste 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)41719261079SEd Maste int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
41819261079SEd Maste {
41919261079SEd Maste 	static struct shared_state *st;
42019261079SEd Maste 	struct test_state *ts;
42119261079SEd Maste 	u_char crbuf[SSH_MAX_PRE_BANNER_LINES * 4];
42219261079SEd Maste 	u_char zbuf[4096] = {0};
42319261079SEd Maste 	static LogLevel loglevel = SYSLOG_LEVEL_INFO;
42419261079SEd Maste 
42519261079SEd Maste 	if (st == NULL) {
42619261079SEd Maste 		if (getenv("DEBUG") != NULL || getenv("KEX_FUZZ_DEBUG") != NULL)
42719261079SEd Maste 			loglevel = SYSLOG_LEVEL_DEBUG3;
42819261079SEd Maste 		log_init("kex_fuzz",
42919261079SEd Maste 		    loglevel, SYSLOG_FACILITY_AUTH, 1);
43019261079SEd Maste 		st = (struct shared_state *)xcalloc(1, sizeof(*st));
43119261079SEd Maste 		prepare_keys(st);
43219261079SEd Maste 	}
43319261079SEd Maste 
43419261079SEd Maste 	/* Ensure that we can complete (fail) banner exchange at least */
43519261079SEd Maste 	memset(crbuf, '\n', sizeof(crbuf));
43619261079SEd Maste 
43719261079SEd Maste 	ts = (struct test_state *)xcalloc(1, sizeof(*ts));
43819261079SEd Maste 	if ((ts->s_template = sshbuf_new()) == NULL ||
43919261079SEd Maste 	    sshbuf_put(ts->s_template, data, size) != 0 ||
44019261079SEd Maste 	    sshbuf_put(ts->s_template, crbuf, sizeof(crbuf)) != 0 ||
44119261079SEd Maste 	    sshbuf_put(ts->s_template, zbuf, sizeof(zbuf)) != 0)
44219261079SEd Maste 		abort();
44319261079SEd Maste 	kex_tests(st, ts);
44419261079SEd Maste 	sshbuf_free(ts->s_template);
44519261079SEd Maste 	free(ts);
44619261079SEd Maste 
44719261079SEd Maste 	ts = (struct test_state *)xcalloc(1, sizeof(*ts));
44819261079SEd Maste 	if ((ts->c_template = sshbuf_new()) == NULL ||
44919261079SEd Maste 	    sshbuf_put(ts->c_template, data, size) != 0 ||
45019261079SEd Maste 	    sshbuf_put(ts->c_template, crbuf, sizeof(crbuf)) != 0 ||
45119261079SEd Maste 	    sshbuf_put(ts->c_template, zbuf, sizeof(zbuf)) != 0)
45219261079SEd Maste 		abort();
45319261079SEd Maste 	kex_tests(st, ts);
45419261079SEd Maste 	sshbuf_free(ts->c_template);
45519261079SEd Maste 	free(ts);
45619261079SEd Maste 
45719261079SEd Maste 	return 0;
45819261079SEd Maste }
45919261079SEd Maste #endif /* STANDALONE */
46019261079SEd Maste } /* extern "C" */
461