1659864feSdjm@openbsd.org /* 	$OpenBSD: test_kex.c,v 1.5 2020/12/29 01:02:15 djm Exp $ */
29e06a0fbSmarkus@openbsd.org /*
39e06a0fbSmarkus@openbsd.org  * Regress test KEX
49e06a0fbSmarkus@openbsd.org  *
59e06a0fbSmarkus@openbsd.org  * Placed in the public domain
69e06a0fbSmarkus@openbsd.org  */
79e06a0fbSmarkus@openbsd.org 
8cb030ce2SDamien Miller #include "includes.h"
9cb030ce2SDamien Miller 
109e06a0fbSmarkus@openbsd.org #include <sys/types.h>
119e06a0fbSmarkus@openbsd.org #include <sys/param.h>
129e06a0fbSmarkus@openbsd.org #include <stdio.h>
134c356308SDarren Tucker #ifdef HAVE_STDINT_H
149e06a0fbSmarkus@openbsd.org #include <stdint.h>
154c356308SDarren Tucker #endif
169e06a0fbSmarkus@openbsd.org #include <stdlib.h>
179e06a0fbSmarkus@openbsd.org #include <string.h>
189e06a0fbSmarkus@openbsd.org 
191ca3e215SDamien Miller #include "../test_helper/test_helper.h"
209e06a0fbSmarkus@openbsd.org 
219e06a0fbSmarkus@openbsd.org #include "ssherr.h"
229e06a0fbSmarkus@openbsd.org #include "ssh_api.h"
239e06a0fbSmarkus@openbsd.org #include "sshbuf.h"
249e06a0fbSmarkus@openbsd.org #include "packet.h"
259e06a0fbSmarkus@openbsd.org #include "myproposal.h"
269e06a0fbSmarkus@openbsd.org 
279e06a0fbSmarkus@openbsd.org void kex_tests(void);
289e06a0fbSmarkus@openbsd.org static int do_debug = 0;
299e06a0fbSmarkus@openbsd.org 
309e06a0fbSmarkus@openbsd.org static int
do_send_and_receive(struct ssh * from,struct ssh * to)319e06a0fbSmarkus@openbsd.org do_send_and_receive(struct ssh *from, struct ssh *to)
329e06a0fbSmarkus@openbsd.org {
339e06a0fbSmarkus@openbsd.org 	u_char type;
349e06a0fbSmarkus@openbsd.org 	size_t len;
359e06a0fbSmarkus@openbsd.org 	const u_char *buf;
369e06a0fbSmarkus@openbsd.org 	int r;
379e06a0fbSmarkus@openbsd.org 
389e06a0fbSmarkus@openbsd.org 	for (;;) {
399e06a0fbSmarkus@openbsd.org 		if ((r = ssh_packet_next(from, &type)) != 0) {
409e06a0fbSmarkus@openbsd.org 			fprintf(stderr, "ssh_packet_next: %s\n", ssh_err(r));
419e06a0fbSmarkus@openbsd.org 			return r;
429e06a0fbSmarkus@openbsd.org 		}
439e06a0fbSmarkus@openbsd.org 		if (type != 0)
449e06a0fbSmarkus@openbsd.org 			return 0;
459e06a0fbSmarkus@openbsd.org 		buf = ssh_output_ptr(from, &len);
469e06a0fbSmarkus@openbsd.org 		if (do_debug)
479e06a0fbSmarkus@openbsd.org 			printf("%zu", len);
489e06a0fbSmarkus@openbsd.org 		if (len == 0)
499e06a0fbSmarkus@openbsd.org 			return 0;
509e06a0fbSmarkus@openbsd.org 		if ((r = ssh_output_consume(from, len)) != 0 ||
519e06a0fbSmarkus@openbsd.org 		    (r = ssh_input_append(to, buf, len)) != 0)
529e06a0fbSmarkus@openbsd.org 			return r;
539e06a0fbSmarkus@openbsd.org 	}
549e06a0fbSmarkus@openbsd.org }
559e06a0fbSmarkus@openbsd.org 
569e06a0fbSmarkus@openbsd.org static void
run_kex(struct ssh * client,struct ssh * server)579e06a0fbSmarkus@openbsd.org run_kex(struct ssh *client, struct ssh *server)
589e06a0fbSmarkus@openbsd.org {
599e06a0fbSmarkus@openbsd.org 	int r = 0;
609e06a0fbSmarkus@openbsd.org 
619e06a0fbSmarkus@openbsd.org 	while (!server->kex->done || !client->kex->done) {
629e06a0fbSmarkus@openbsd.org 		if (do_debug)
639e06a0fbSmarkus@openbsd.org 			printf(" S:");
649e06a0fbSmarkus@openbsd.org 		if ((r = do_send_and_receive(server, client)))
659e06a0fbSmarkus@openbsd.org 			break;
669e06a0fbSmarkus@openbsd.org 		if (do_debug)
679e06a0fbSmarkus@openbsd.org 			printf(" C:");
689e06a0fbSmarkus@openbsd.org 		if ((r = do_send_and_receive(client, server)))
699e06a0fbSmarkus@openbsd.org 			break;
709e06a0fbSmarkus@openbsd.org 	}
719e06a0fbSmarkus@openbsd.org 	if (do_debug)
729e06a0fbSmarkus@openbsd.org 		printf("done: %s\n", ssh_err(r));
739e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(r, 0);
749e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(server->kex->done, 1);
759e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(client->kex->done, 1);
769e06a0fbSmarkus@openbsd.org }
779e06a0fbSmarkus@openbsd.org 
789e06a0fbSmarkus@openbsd.org static void
do_kex_with_key(char * kex,int keytype,int bits)799e06a0fbSmarkus@openbsd.org do_kex_with_key(char *kex, int keytype, int bits)
809e06a0fbSmarkus@openbsd.org {
819e06a0fbSmarkus@openbsd.org 	struct ssh *client = NULL, *server = NULL, *server2 = NULL;
829e06a0fbSmarkus@openbsd.org 	struct sshkey *private, *public;
839e06a0fbSmarkus@openbsd.org 	struct sshbuf *state;
849e06a0fbSmarkus@openbsd.org 	struct kex_params kex_params;
859e06a0fbSmarkus@openbsd.org 	char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
865bf09331Smarkus@openbsd.org 	char *keyname = NULL;
879e06a0fbSmarkus@openbsd.org 
889e06a0fbSmarkus@openbsd.org 	TEST_START("sshkey_generate");
899e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(sshkey_generate(keytype, bits, &private), 0);
909e06a0fbSmarkus@openbsd.org 	TEST_DONE();
919e06a0fbSmarkus@openbsd.org 
929e06a0fbSmarkus@openbsd.org 	TEST_START("sshkey_from_private");
939e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(sshkey_from_private(private, &public), 0);
949e06a0fbSmarkus@openbsd.org 	TEST_DONE();
959e06a0fbSmarkus@openbsd.org 
969e06a0fbSmarkus@openbsd.org 	TEST_START("ssh_init");
979e06a0fbSmarkus@openbsd.org 	memcpy(kex_params.proposal, myproposal, sizeof(myproposal));
989e06a0fbSmarkus@openbsd.org 	if (kex != NULL)
999e06a0fbSmarkus@openbsd.org 		kex_params.proposal[PROPOSAL_KEX_ALGS] = kex;
1005bf09331Smarkus@openbsd.org 	keyname = strdup(sshkey_ssh_name(private));
1015bf09331Smarkus@openbsd.org 	ASSERT_PTR_NE(keyname, NULL);
1025bf09331Smarkus@openbsd.org 	kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname;
1039e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0);
1049e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(ssh_init(&server, 1, &kex_params), 0);
1059e06a0fbSmarkus@openbsd.org 	ASSERT_PTR_NE(client, NULL);
1069e06a0fbSmarkus@openbsd.org 	ASSERT_PTR_NE(server, NULL);
1079e06a0fbSmarkus@openbsd.org 	TEST_DONE();
1089e06a0fbSmarkus@openbsd.org 
1099e06a0fbSmarkus@openbsd.org 	TEST_START("ssh_add_hostkey");
1109e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(ssh_add_hostkey(server, private), 0);
1119e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(ssh_add_hostkey(client, public), 0);
1129e06a0fbSmarkus@openbsd.org 	TEST_DONE();
1139e06a0fbSmarkus@openbsd.org 
1149e06a0fbSmarkus@openbsd.org 	TEST_START("kex");
1159e06a0fbSmarkus@openbsd.org 	run_kex(client, server);
1169e06a0fbSmarkus@openbsd.org 	TEST_DONE();
1179e06a0fbSmarkus@openbsd.org 
1189e06a0fbSmarkus@openbsd.org 	TEST_START("rekeying client");
1199e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(kex_send_kexinit(client), 0);
1209e06a0fbSmarkus@openbsd.org 	run_kex(client, server);
1219e06a0fbSmarkus@openbsd.org 	TEST_DONE();
1229e06a0fbSmarkus@openbsd.org 
1239e06a0fbSmarkus@openbsd.org 	TEST_START("rekeying server");
1249e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(kex_send_kexinit(server), 0);
1259e06a0fbSmarkus@openbsd.org 	run_kex(client, server);
1269e06a0fbSmarkus@openbsd.org 	TEST_DONE();
1279e06a0fbSmarkus@openbsd.org 
1289e06a0fbSmarkus@openbsd.org 	TEST_START("ssh_packet_get_state");
1299e06a0fbSmarkus@openbsd.org 	state = sshbuf_new();
1309e06a0fbSmarkus@openbsd.org 	ASSERT_PTR_NE(state, NULL);
1319e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(ssh_packet_get_state(server, state), 0);
1329e06a0fbSmarkus@openbsd.org 	ASSERT_INT_GE(sshbuf_len(state), 1);
1339e06a0fbSmarkus@openbsd.org 	TEST_DONE();
1349e06a0fbSmarkus@openbsd.org 
1359e06a0fbSmarkus@openbsd.org 	TEST_START("ssh_packet_set_state");
1369e06a0fbSmarkus@openbsd.org 	server2 = NULL;
1379e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(ssh_init(&server2, 1, NULL), 0);
1389e06a0fbSmarkus@openbsd.org 	ASSERT_PTR_NE(server2, NULL);
1399e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(ssh_add_hostkey(server2, private), 0);
1409e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(ssh_packet_set_state(server2, state), 0);
1419e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(sshbuf_len(state), 0);
1429e06a0fbSmarkus@openbsd.org 	sshbuf_free(state);
1439e06a0fbSmarkus@openbsd.org 	ASSERT_PTR_NE(server2->kex, NULL);
1449e06a0fbSmarkus@openbsd.org 	/* XXX we need to set the callbacks */
145f61f29afSDamien Miller #ifdef WITH_OPENSSL
14635ecc53aSdjm@openbsd.org 	server2->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
14735ecc53aSdjm@openbsd.org 	server2->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
1489e06a0fbSmarkus@openbsd.org 	server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
1499e06a0fbSmarkus@openbsd.org 	server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
1505d5ec165SDarren Tucker #ifdef OPENSSL_HAS_ECC
15135ecc53aSdjm@openbsd.org 	server2->kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
152f61f29afSDamien Miller #endif /* OPENSSL_HAS_ECC */
153f61f29afSDamien Miller #endif /* WITH_OPENSSL */
15435ecc53aSdjm@openbsd.org 	server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server;
155659864feSdjm@openbsd.org 	server2->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server;
1569e06a0fbSmarkus@openbsd.org 	server2->kex->load_host_public_key = server->kex->load_host_public_key;
1579e06a0fbSmarkus@openbsd.org 	server2->kex->load_host_private_key = server->kex->load_host_private_key;
1589e06a0fbSmarkus@openbsd.org 	server2->kex->sign = server->kex->sign;
1599e06a0fbSmarkus@openbsd.org 	TEST_DONE();
1609e06a0fbSmarkus@openbsd.org 
1619e06a0fbSmarkus@openbsd.org 	TEST_START("rekeying server2");
1629e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(kex_send_kexinit(server2), 0);
1639e06a0fbSmarkus@openbsd.org 	run_kex(client, server2);
1649e06a0fbSmarkus@openbsd.org 	ASSERT_INT_EQ(kex_send_kexinit(client), 0);
1659e06a0fbSmarkus@openbsd.org 	run_kex(client, server2);
1669e06a0fbSmarkus@openbsd.org 	TEST_DONE();
1679e06a0fbSmarkus@openbsd.org 
1689e06a0fbSmarkus@openbsd.org 	TEST_START("cleanup");
1699e06a0fbSmarkus@openbsd.org 	sshkey_free(private);
1709e06a0fbSmarkus@openbsd.org 	sshkey_free(public);
1719e06a0fbSmarkus@openbsd.org 	ssh_free(client);
1729e06a0fbSmarkus@openbsd.org 	ssh_free(server);
1739e06a0fbSmarkus@openbsd.org 	ssh_free(server2);
1745bf09331Smarkus@openbsd.org 	free(keyname);
1759e06a0fbSmarkus@openbsd.org 	TEST_DONE();
1769e06a0fbSmarkus@openbsd.org }
1779e06a0fbSmarkus@openbsd.org 
1789e06a0fbSmarkus@openbsd.org static void
do_kex(char * kex)1799e06a0fbSmarkus@openbsd.org do_kex(char *kex)
1809e06a0fbSmarkus@openbsd.org {
181f61f29afSDamien Miller #ifdef WITH_OPENSSL
1829e06a0fbSmarkus@openbsd.org 	do_kex_with_key(kex, KEY_RSA, 2048);
1839e06a0fbSmarkus@openbsd.org 	do_kex_with_key(kex, KEY_DSA, 1024);
1845d5ec165SDarren Tucker #ifdef OPENSSL_HAS_ECC
1859e06a0fbSmarkus@openbsd.org 	do_kex_with_key(kex, KEY_ECDSA, 256);
186f61f29afSDamien Miller #endif /* OPENSSL_HAS_ECC */
187f61f29afSDamien Miller #endif /* WITH_OPENSSL */
1889e06a0fbSmarkus@openbsd.org 	do_kex_with_key(kex, KEY_ED25519, 256);
1899e06a0fbSmarkus@openbsd.org }
1909e06a0fbSmarkus@openbsd.org 
1919e06a0fbSmarkus@openbsd.org void
kex_tests(void)1929e06a0fbSmarkus@openbsd.org kex_tests(void)
1939e06a0fbSmarkus@openbsd.org {
1949e06a0fbSmarkus@openbsd.org 	do_kex("curve25519-sha256@libssh.org");
195f61f29afSDamien Miller #ifdef WITH_OPENSSL
1965d5ec165SDarren Tucker #ifdef OPENSSL_HAS_ECC
1979e06a0fbSmarkus@openbsd.org 	do_kex("ecdh-sha2-nistp256");
1989e06a0fbSmarkus@openbsd.org 	do_kex("ecdh-sha2-nistp384");
1999e06a0fbSmarkus@openbsd.org 	do_kex("ecdh-sha2-nistp521");
200f61f29afSDamien Miller #endif /* OPENSSL_HAS_ECC */
2019e06a0fbSmarkus@openbsd.org 	do_kex("diffie-hellman-group-exchange-sha256");
2029e06a0fbSmarkus@openbsd.org 	do_kex("diffie-hellman-group-exchange-sha1");
2039e06a0fbSmarkus@openbsd.org 	do_kex("diffie-hellman-group14-sha1");
2049e06a0fbSmarkus@openbsd.org 	do_kex("diffie-hellman-group1-sha1");
205*ae5f9b0dSDarren Tucker # ifdef USE_SNTRUP761X25519
206659864feSdjm@openbsd.org 	do_kex("sntrup761x25519-sha512@openssh.com");
207*ae5f9b0dSDarren Tucker # endif /* USE_SNTRUP761X25519 */
208f61f29afSDamien Miller #endif /* WITH_OPENSSL */
2099e06a0fbSmarkus@openbsd.org }
210