test_kex.c 5.2 KB

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