1 /* $OpenBSD: test_kex.c,v 1.1 2015/01/15 23:41:29 markus Exp $ */ 2 /* 3 * Regress test KEX 4 * 5 * Placed in the public domain 6 */ 7 8 #include "includes.h" 9 10 #include <sys/types.h> 11 #include <sys/param.h> 12 #include <stdio.h> 13 #ifdef HAVE_STDINT_H 14 #include <stdint.h> 15 #endif 16 #include <stdlib.h> 17 #include <string.h> 18 19 #include "../test_helper/test_helper.h" 20 21 #include "ssherr.h" 22 #include "ssh_api.h" 23 #include "sshbuf.h" 24 #include "packet.h" 25 #include "myproposal.h" 26 27 struct ssh *active_state = NULL; /* XXX - needed for linking */ 28 29 void kex_tests(void); 30 static int do_debug = 0; 31 32 static int 33 do_send_and_receive(struct ssh *from, struct ssh *to) 34 { 35 u_char type; 36 size_t len; 37 const u_char *buf; 38 int r; 39 40 for (;;) { 41 if ((r = ssh_packet_next(from, &type)) != 0) { 42 fprintf(stderr, "ssh_packet_next: %s\n", ssh_err(r)); 43 return r; 44 } 45 if (type != 0) 46 return 0; 47 buf = ssh_output_ptr(from, &len); 48 if (do_debug) 49 printf("%zu", len); 50 if (len == 0) 51 return 0; 52 if ((r = ssh_output_consume(from, len)) != 0 || 53 (r = ssh_input_append(to, buf, len)) != 0) 54 return r; 55 } 56 } 57 58 static void 59 run_kex(struct ssh *client, struct ssh *server) 60 { 61 int r = 0; 62 63 while (!server->kex->done || !client->kex->done) { 64 if (do_debug) 65 printf(" S:"); 66 if ((r = do_send_and_receive(server, client))) 67 break; 68 if (do_debug) 69 printf(" C:"); 70 if ((r = do_send_and_receive(client, server))) 71 break; 72 } 73 if (do_debug) 74 printf("done: %s\n", ssh_err(r)); 75 ASSERT_INT_EQ(r, 0); 76 ASSERT_INT_EQ(server->kex->done, 1); 77 ASSERT_INT_EQ(client->kex->done, 1); 78 } 79 80 static void 81 do_kex_with_key(char *kex, int keytype, int bits) 82 { 83 struct ssh *client = NULL, *server = NULL, *server2 = NULL; 84 struct sshkey *private, *public; 85 struct sshbuf *state; 86 struct kex_params kex_params; 87 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; 88 89 TEST_START("sshkey_generate"); 90 ASSERT_INT_EQ(sshkey_generate(keytype, bits, &private), 0); 91 TEST_DONE(); 92 93 TEST_START("sshkey_from_private"); 94 ASSERT_INT_EQ(sshkey_from_private(private, &public), 0); 95 TEST_DONE(); 96 97 TEST_START("ssh_init"); 98 memcpy(kex_params.proposal, myproposal, sizeof(myproposal)); 99 if (kex != NULL) 100 kex_params.proposal[PROPOSAL_KEX_ALGS] = kex; 101 ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0); 102 ASSERT_INT_EQ(ssh_init(&server, 1, &kex_params), 0); 103 ASSERT_PTR_NE(client, NULL); 104 ASSERT_PTR_NE(server, NULL); 105 TEST_DONE(); 106 107 TEST_START("ssh_add_hostkey"); 108 ASSERT_INT_EQ(ssh_add_hostkey(server, private), 0); 109 ASSERT_INT_EQ(ssh_add_hostkey(client, public), 0); 110 TEST_DONE(); 111 112 TEST_START("kex"); 113 run_kex(client, server); 114 TEST_DONE(); 115 116 TEST_START("rekeying client"); 117 ASSERT_INT_EQ(kex_send_kexinit(client), 0); 118 run_kex(client, server); 119 TEST_DONE(); 120 121 TEST_START("rekeying server"); 122 ASSERT_INT_EQ(kex_send_kexinit(server), 0); 123 run_kex(client, server); 124 TEST_DONE(); 125 126 TEST_START("ssh_packet_get_state"); 127 state = sshbuf_new(); 128 ASSERT_PTR_NE(state, NULL); 129 ASSERT_INT_EQ(ssh_packet_get_state(server, state), 0); 130 ASSERT_INT_GE(sshbuf_len(state), 1); 131 TEST_DONE(); 132 133 TEST_START("ssh_packet_set_state"); 134 server2 = NULL; 135 ASSERT_INT_EQ(ssh_init(&server2, 1, NULL), 0); 136 ASSERT_PTR_NE(server2, NULL); 137 ASSERT_INT_EQ(ssh_add_hostkey(server2, private), 0); 138 kex_free(server2->kex); /* XXX or should ssh_packet_set_state()? */ 139 ASSERT_INT_EQ(ssh_packet_set_state(server2, state), 0); 140 ASSERT_INT_EQ(sshbuf_len(state), 0); 141 sshbuf_free(state); 142 ASSERT_PTR_NE(server2->kex, NULL); 143 /* XXX we need to set the callbacks */ 144 server2->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; 145 server2->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; 146 server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 147 server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 148 #ifdef OPENSSL_HAS_ECC 149 server2->kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 150 #endif 151 server2->kex->kex[KEX_C25519_SHA256] = kexc25519_server; 152 server2->kex->load_host_public_key = server->kex->load_host_public_key; 153 server2->kex->load_host_private_key = server->kex->load_host_private_key; 154 server2->kex->sign = server->kex->sign; 155 TEST_DONE(); 156 157 TEST_START("rekeying server2"); 158 ASSERT_INT_EQ(kex_send_kexinit(server2), 0); 159 run_kex(client, server2); 160 ASSERT_INT_EQ(kex_send_kexinit(client), 0); 161 run_kex(client, server2); 162 TEST_DONE(); 163 164 TEST_START("cleanup"); 165 sshkey_free(private); 166 sshkey_free(public); 167 ssh_free(client); 168 ssh_free(server); 169 ssh_free(server2); 170 TEST_DONE(); 171 } 172 173 static void 174 do_kex(char *kex) 175 { 176 do_kex_with_key(kex, KEY_RSA, 2048); 177 do_kex_with_key(kex, KEY_DSA, 1024); 178 #ifdef OPENSSL_HAS_ECC 179 do_kex_with_key(kex, KEY_ECDSA, 256); 180 #endif 181 do_kex_with_key(kex, KEY_ED25519, 256); 182 } 183 184 void 185 kex_tests(void) 186 { 187 do_kex("curve25519-sha256@libssh.org"); 188 #ifdef OPENSSL_HAS_ECC 189 do_kex("ecdh-sha2-nistp256"); 190 do_kex("ecdh-sha2-nistp384"); 191 do_kex("ecdh-sha2-nistp521"); 192 #endif 193 do_kex("diffie-hellman-group-exchange-sha256"); 194 do_kex("diffie-hellman-group-exchange-sha1"); 195 do_kex("diffie-hellman-group14-sha1"); 196 do_kex("diffie-hellman-group1-sha1"); 197 } 198