test_hs_intropoint.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /* Copyright (c) 2016, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file test_hs_service.c
  5. * \brief Test hidden service functionality.
  6. */
  7. #define HS_SERVICE_PRIVATE
  8. #define HS_INTROPOINT_PRIVATE
  9. #define RENDSERVICE_PRIVATE
  10. #define CIRCUITLIST_PRIVATE
  11. #include "test.h"
  12. #include "crypto.h"
  13. #include "or.h"
  14. #include "ht.h"
  15. #include "hs/cell_establish_intro.h"
  16. #include "hs_service.h"
  17. #include "hs_circuitmap.h"
  18. #include "hs_intropoint.h"
  19. #include "circuitlist.h"
  20. #include "circuituse.h"
  21. #include "rendservice.h"
  22. /* Mock function to avoid networking in unittests */
  23. static int
  24. mock_send_intro_established_cell(or_circuit_t *circ)
  25. {
  26. (void) circ;
  27. return 0;
  28. }
  29. /* Try sending an ESTABLISH_INTRO cell on a circuit that is already an intro
  30. * point. Should fail. */
  31. static void
  32. test_establish_intro_wrong_purpose(void *arg)
  33. {
  34. int retval;
  35. hs_cell_establish_intro_t *establish_intro_cell = NULL;
  36. or_circuit_t *intro_circ = or_circuit_new(0,NULL);;
  37. uint8_t cell_body[RELAY_PAYLOAD_SIZE];
  38. ssize_t cell_len = 0;
  39. char circuit_key_material[DIGEST_LEN] = {0};
  40. (void)arg;
  41. /* Get the auth key of the intro point */
  42. crypto_rand(circuit_key_material, sizeof(circuit_key_material));
  43. memcpy(intro_circ->rend_circ_nonce, circuit_key_material, DIGEST_LEN);
  44. /* Set a bad circuit purpose!! :) */
  45. circuit_change_purpose(TO_CIRCUIT(intro_circ), CIRCUIT_PURPOSE_INTRO_POINT);
  46. /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
  47. attempt to parse it. */
  48. establish_intro_cell = generate_establish_intro_cell(circuit_key_material,
  49. sizeof(circuit_key_material));
  50. tt_assert(establish_intro_cell);
  51. cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body),
  52. establish_intro_cell);
  53. tt_int_op(cell_len, >, 0);
  54. /* Receive the cell */
  55. retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len);
  56. tt_int_op(retval, ==, -1);
  57. done:
  58. hs_cell_establish_intro_free(establish_intro_cell);
  59. circuit_free(TO_CIRCUIT(intro_circ));
  60. }
  61. /* Prepare a circuit for accepting an ESTABLISH_INTRO cell */
  62. static void
  63. helper_prepare_circ_for_intro(or_circuit_t *circ, char *circuit_key_material)
  64. {
  65. /* Prepare the circuit for the incoming ESTABLISH_INTRO */
  66. circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_OR);
  67. memcpy(circ->rend_circ_nonce, circuit_key_material, DIGEST_LEN);
  68. }
  69. /* Send an empty ESTABLISH_INTRO cell. Should fail. */
  70. static void
  71. test_establish_intro_wrong_keytype(void *arg)
  72. {
  73. int retval;
  74. or_circuit_t *intro_circ = or_circuit_new(0,NULL);;
  75. char circuit_key_material[DIGEST_LEN] = {0};
  76. (void)arg;
  77. /* Get the auth key of the intro point */
  78. crypto_rand(circuit_key_material, sizeof(circuit_key_material));
  79. helper_prepare_circ_for_intro(intro_circ, circuit_key_material);
  80. /* Receive the cell. Should fail. */
  81. retval = hs_intro_received_establish_intro(intro_circ, (uint8_t*)"", 0);
  82. tt_int_op(retval, ==, -1);
  83. done:
  84. circuit_free(TO_CIRCUIT(intro_circ));
  85. }
  86. /* Send an ESTABLISH_INTRO cell with an unknown auth key type. Should fail. */
  87. static void
  88. test_establish_intro_wrong_keytype2(void *arg)
  89. {
  90. int retval;
  91. hs_cell_establish_intro_t *establish_intro_cell = NULL;
  92. or_circuit_t *intro_circ = or_circuit_new(0,NULL);;
  93. uint8_t cell_body[RELAY_PAYLOAD_SIZE];
  94. ssize_t cell_len = 0;
  95. char circuit_key_material[DIGEST_LEN] = {0};
  96. (void)arg;
  97. /* Get the auth key of the intro point */
  98. crypto_rand(circuit_key_material, sizeof(circuit_key_material));
  99. helper_prepare_circ_for_intro(intro_circ, circuit_key_material);
  100. /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
  101. attempt to parse it. */
  102. establish_intro_cell = generate_establish_intro_cell(circuit_key_material,
  103. sizeof(circuit_key_material));
  104. tt_assert(establish_intro_cell);
  105. cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body),
  106. establish_intro_cell);
  107. tt_int_op(cell_len, >, 0);
  108. /* Mutate the auth key type! :) */
  109. cell_body[0] = 42;
  110. /* Receive the cell. Should fail. */
  111. retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len);
  112. tt_int_op(retval, ==, -1);
  113. done:
  114. hs_cell_establish_intro_free(establish_intro_cell);
  115. circuit_free(TO_CIRCUIT(intro_circ));
  116. }
  117. /* Send a legit ESTABLISH_INTRO cell but slightly change the signature. Should
  118. * fail. */
  119. static void
  120. test_establish_intro_wrong_sig(void *arg)
  121. {
  122. int retval;
  123. hs_cell_establish_intro_t *establish_intro_cell = NULL;
  124. or_circuit_t *intro_circ = or_circuit_new(0,NULL);;
  125. uint8_t cell_body[RELAY_PAYLOAD_SIZE];
  126. ssize_t cell_len = 0;
  127. char circuit_key_material[DIGEST_LEN] = {0};
  128. (void)arg;
  129. /* Get the auth key of the intro point */
  130. crypto_rand(circuit_key_material, sizeof(circuit_key_material));
  131. helper_prepare_circ_for_intro(intro_circ, circuit_key_material);
  132. /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
  133. attempt to parse it. */
  134. establish_intro_cell = generate_establish_intro_cell(circuit_key_material,
  135. sizeof(circuit_key_material));
  136. tt_assert(establish_intro_cell);
  137. cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body),
  138. establish_intro_cell);
  139. tt_int_op(cell_len, >, 0);
  140. /* Mutate the last byte (signature)! :) */
  141. cell_body[cell_len-1]++;
  142. /* Receive the cell. Should fail. */
  143. retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len);
  144. tt_int_op(retval, ==, -1);
  145. done:
  146. hs_cell_establish_intro_free(establish_intro_cell);
  147. circuit_free(TO_CIRCUIT(intro_circ));
  148. }
  149. /* Helper function: Send a well-formed v3 ESTABLISH_INTRO cell to
  150. * <b>intro_circ</b>. Return the cell. */
  151. static hs_cell_establish_intro_t *
  152. helper_establish_intro_v3(or_circuit_t *intro_circ)
  153. {
  154. int retval;
  155. hs_cell_establish_intro_t *establish_intro_cell = NULL;
  156. uint8_t cell_body[RELAY_PAYLOAD_SIZE];
  157. ssize_t cell_len = 0;
  158. char circuit_key_material[DIGEST_LEN] = {0};
  159. tt_assert(intro_circ);
  160. /* Prepare the circuit for the incoming ESTABLISH_INTRO */
  161. crypto_rand(circuit_key_material, sizeof(circuit_key_material));
  162. helper_prepare_circ_for_intro(intro_circ, circuit_key_material);
  163. /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
  164. attempt to parse it. */
  165. establish_intro_cell = generate_establish_intro_cell(circuit_key_material,
  166. sizeof(circuit_key_material));
  167. tt_assert(establish_intro_cell);
  168. cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body),
  169. establish_intro_cell);
  170. tt_int_op(cell_len, >, 0);
  171. /* Receive the cell */
  172. retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len);
  173. tt_int_op(retval, ==, 0);
  174. done:
  175. return establish_intro_cell;
  176. }
  177. /* Helper function: Send a well-formed v2 ESTABLISH_INTRO cell to
  178. * <b>intro_circ</b>. Return the public key advertised in the cell. */
  179. static crypto_pk_t *
  180. helper_establish_intro_v2(or_circuit_t *intro_circ)
  181. {
  182. crypto_pk_t *key1 = NULL;
  183. int retval;
  184. uint8_t cell_body[RELAY_PAYLOAD_SIZE];
  185. ssize_t cell_len = 0;
  186. char circuit_key_material[DIGEST_LEN] = {0};
  187. tt_assert(intro_circ);
  188. /* Prepare the circuit for the incoming ESTABLISH_INTRO */
  189. crypto_rand(circuit_key_material, sizeof(circuit_key_material));
  190. helper_prepare_circ_for_intro(intro_circ, circuit_key_material);
  191. /* Send legacy establish_intro */
  192. key1 = pk_generate(0);
  193. /* Use old circuit_key_material why not */
  194. cell_len = encode_establish_intro_cell_legacy((char*)cell_body,
  195. key1,
  196. circuit_key_material);
  197. tt_int_op(cell_len, >, 0);
  198. /* Receive legacy establish_intro */
  199. retval = hs_intro_received_establish_intro(intro_circ,
  200. cell_body, cell_len);
  201. tt_int_op(retval, ==, 0);
  202. done:
  203. return key1;
  204. }
  205. /** Successfuly register a v2 intro point and a v3 intro point. Ensure that HS
  206. * circuitmap is maintained properly. */
  207. static void
  208. test_intro_point_registration(void *arg)
  209. {
  210. int retval;
  211. hs_circuitmap_ht *the_hs_circuitmap = NULL;
  212. or_circuit_t *intro_circ = NULL;
  213. hs_cell_establish_intro_t *establish_intro_cell = NULL;
  214. ed25519_public_key_t auth_key;
  215. crypto_pk_t *legacy_auth_key = NULL;
  216. or_circuit_t *legacy_intro_circ = NULL;
  217. or_circuit_t *returned_intro_circ = NULL;
  218. (void) arg;
  219. MOCK(hs_intro_send_intro_established_cell, mock_send_intro_established_cell);
  220. hs_circuitmap_init();
  221. /* Check that the circuitmap is currently empty */
  222. {
  223. the_hs_circuitmap = get_hs_circuitmap();
  224. tt_assert(the_hs_circuitmap);
  225. tt_int_op(0, ==, HT_SIZE(the_hs_circuitmap));
  226. /* Do a circuitmap query in any case */
  227. returned_intro_circ = hs_circuitmap_get_intro_circ_v3(&auth_key);
  228. tt_ptr_op(returned_intro_circ, ==, NULL);
  229. }
  230. /* Create a v3 intro point */
  231. {
  232. intro_circ = or_circuit_new(0, NULL);
  233. tt_assert(intro_circ);
  234. establish_intro_cell = helper_establish_intro_v3(intro_circ);
  235. /* Check that the intro point was registered on the HS circuitmap */
  236. the_hs_circuitmap = get_hs_circuitmap();
  237. tt_assert(the_hs_circuitmap);
  238. tt_int_op(1, ==, HT_SIZE(the_hs_circuitmap));
  239. get_auth_key_from_establish_intro_cell(&auth_key, establish_intro_cell);
  240. returned_intro_circ = hs_circuitmap_get_intro_circ_v3(&auth_key);
  241. tt_ptr_op(intro_circ, ==, returned_intro_circ);
  242. }
  243. /* Create a v2 intro point */
  244. {
  245. char key_digest[DIGEST_LEN];
  246. legacy_intro_circ = or_circuit_new(1, NULL);
  247. tt_assert(legacy_intro_circ);
  248. legacy_auth_key = helper_establish_intro_v2(legacy_intro_circ);
  249. tt_assert(legacy_auth_key);
  250. /* Check that the circuitmap now has two elements */
  251. the_hs_circuitmap = get_hs_circuitmap();
  252. tt_assert(the_hs_circuitmap);
  253. tt_int_op(2, ==, HT_SIZE(the_hs_circuitmap));
  254. /* Check that the new element is our legacy intro circuit. */
  255. retval = crypto_pk_get_digest(legacy_auth_key, key_digest);
  256. tt_int_op(retval, ==, 0);
  257. returned_intro_circ= hs_circuitmap_get_intro_circ_v2((uint8_t*)key_digest);
  258. tt_ptr_op(legacy_intro_circ, ==, returned_intro_circ);
  259. }
  260. /* XXX Continue test and try to register a second v3 intro point with the
  261. * same auth key. Make sure that old intro circuit gets closed. */
  262. done:
  263. crypto_pk_free(legacy_auth_key);
  264. circuit_free(TO_CIRCUIT(intro_circ));
  265. circuit_free(TO_CIRCUIT(legacy_intro_circ));
  266. hs_cell_establish_intro_free(establish_intro_cell);
  267. { /* Test circuitmap free_all function. */
  268. the_hs_circuitmap = get_hs_circuitmap();
  269. tt_assert(the_hs_circuitmap);
  270. hs_circuitmap_free_all();
  271. the_hs_circuitmap = get_hs_circuitmap();
  272. tt_assert(!the_hs_circuitmap);
  273. }
  274. UNMOCK(hs_intro_send_intro_established_cell);
  275. }
  276. struct testcase_t hs_intropoint_tests[] = {
  277. { "intro_point_registration",
  278. test_intro_point_registration, TT_FORK, NULL, NULL },
  279. { "receive_establish_intro_wrong_keytype",
  280. test_establish_intro_wrong_keytype, TT_FORK, NULL, NULL },
  281. { "receive_establish_intro_wrong_keytype2",
  282. test_establish_intro_wrong_keytype2, TT_FORK, NULL, NULL },
  283. { "receive_establish_intro_wrong_purpose",
  284. test_establish_intro_wrong_purpose, TT_FORK, NULL, NULL },
  285. { "receive_establish_intro_wrong_sig",
  286. test_establish_intro_wrong_sig, TT_FORK, NULL, NULL },
  287. END_OF_TESTCASES
  288. };