test_hs_intropoint.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  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 "log_test_helpers.h"
  14. #include "or.h"
  15. #include "ht.h"
  16. /* Trunnel. */
  17. #include "hs/cell_establish_intro.h"
  18. #include "hs/cell_introduce1.h"
  19. #include "hs/cell_common.h"
  20. #include "hs_service.h"
  21. #include "hs_circuitmap.h"
  22. #include "hs_intropoint.h"
  23. #include "circuitlist.h"
  24. #include "circuituse.h"
  25. #include "rendservice.h"
  26. #include "relay.h"
  27. /* Mock function to avoid networking in unittests */
  28. static int
  29. mock_send_intro_established_cell(or_circuit_t *circ)
  30. {
  31. (void) circ;
  32. return 0;
  33. }
  34. static int
  35. mock_relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ,
  36. uint8_t relay_command, const char *payload,
  37. size_t payload_len, crypt_path_t *cpath_layer,
  38. const char *filename, int lineno)
  39. {
  40. (void) stream_id;
  41. (void) circ;
  42. (void) relay_command;
  43. (void) payload;
  44. (void) payload_len;
  45. (void) cpath_layer;
  46. (void) filename;
  47. (void) lineno;
  48. return 0;
  49. }
  50. static or_circuit_t *
  51. helper_create_intro_circuit(void)
  52. {
  53. or_circuit_t *circ = or_circuit_new(0, NULL);
  54. tt_assert(circ);
  55. circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_OR);
  56. done:
  57. return circ;
  58. }
  59. static hs_cell_introduce1_t *
  60. helper_create_introduce1_cell(void)
  61. {
  62. hs_cell_introduce1_t *cell = NULL;
  63. ed25519_keypair_t auth_key_kp;
  64. /* Generate the auth_key of the cell. */
  65. if (ed25519_keypair_generate(&auth_key_kp, 0) < 0) {
  66. goto err;
  67. }
  68. cell = hs_cell_introduce1_new();
  69. tt_assert(cell);
  70. /* Set the auth key. */
  71. {
  72. size_t auth_key_len = sizeof(auth_key_kp.pubkey);
  73. hs_cell_introduce1_set_auth_key_type(cell,
  74. HS_INTRO_AUTH_KEY_TYPE_ED25519);
  75. hs_cell_introduce1_set_auth_key_len(cell, auth_key_len);
  76. hs_cell_introduce1_setlen_auth_key(cell, auth_key_len);
  77. uint8_t *auth_key_ptr = hs_cell_introduce1_getarray_auth_key(cell);
  78. memcpy(auth_key_ptr, auth_key_kp.pubkey.pubkey, auth_key_len);
  79. }
  80. /* Set the cell extentions to none. */
  81. {
  82. cell_extension_t *ext = cell_extension_new();
  83. cell_extension_set_num(ext, 0);
  84. hs_cell_introduce1_set_extensions(cell, ext);
  85. }
  86. /* Set the encrypted section to some data. */
  87. {
  88. size_t enc_len = 128;
  89. hs_cell_introduce1_setlen_encrypted(cell, enc_len);
  90. uint8_t *enc_ptr = hs_cell_introduce1_getarray_encrypted(cell);
  91. memset(enc_ptr, 'a', enc_len);
  92. }
  93. return cell;
  94. err:
  95. done:
  96. hs_cell_introduce1_free(cell);
  97. return NULL;
  98. }
  99. /* Try sending an ESTABLISH_INTRO cell on a circuit that is already an intro
  100. * point. Should fail. */
  101. static void
  102. test_establish_intro_wrong_purpose(void *arg)
  103. {
  104. int retval;
  105. hs_cell_establish_intro_t *establish_intro_cell = NULL;
  106. or_circuit_t *intro_circ = or_circuit_new(0,NULL);;
  107. uint8_t cell_body[RELAY_PAYLOAD_SIZE];
  108. ssize_t cell_len = 0;
  109. uint8_t circuit_key_material[DIGEST_LEN] = {0};
  110. (void)arg;
  111. /* Get the auth key of the intro point */
  112. crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material));
  113. memcpy(intro_circ->rend_circ_nonce, circuit_key_material, DIGEST_LEN);
  114. /* Set a bad circuit purpose!! :) */
  115. circuit_change_purpose(TO_CIRCUIT(intro_circ), CIRCUIT_PURPOSE_INTRO_POINT);
  116. /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
  117. attempt to parse it. */
  118. establish_intro_cell = generate_establish_intro_cell(circuit_key_material,
  119. sizeof(circuit_key_material));
  120. tt_assert(establish_intro_cell);
  121. cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body),
  122. establish_intro_cell);
  123. tt_int_op(cell_len, >, 0);
  124. /* Receive the cell */
  125. retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len);
  126. tt_int_op(retval, ==, -1);
  127. done:
  128. hs_cell_establish_intro_free(establish_intro_cell);
  129. circuit_free(TO_CIRCUIT(intro_circ));
  130. }
  131. /* Prepare a circuit for accepting an ESTABLISH_INTRO cell */
  132. static void
  133. helper_prepare_circ_for_intro(or_circuit_t *circ,
  134. uint8_t *circuit_key_material)
  135. {
  136. /* Prepare the circuit for the incoming ESTABLISH_INTRO */
  137. circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_OR);
  138. memcpy(circ->rend_circ_nonce, circuit_key_material, DIGEST_LEN);
  139. }
  140. /* Send an empty ESTABLISH_INTRO cell. Should fail. */
  141. static void
  142. test_establish_intro_wrong_keytype(void *arg)
  143. {
  144. int retval;
  145. or_circuit_t *intro_circ = or_circuit_new(0,NULL);;
  146. uint8_t circuit_key_material[DIGEST_LEN] = {0};
  147. (void)arg;
  148. /* Get the auth key of the intro point */
  149. crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material));
  150. helper_prepare_circ_for_intro(intro_circ, circuit_key_material);
  151. /* Receive the cell. Should fail. */
  152. retval = hs_intro_received_establish_intro(intro_circ, (uint8_t*)"", 0);
  153. tt_int_op(retval, ==, -1);
  154. done:
  155. circuit_free(TO_CIRCUIT(intro_circ));
  156. }
  157. /* Send an ESTABLISH_INTRO cell with an unknown auth key type. Should fail. */
  158. static void
  159. test_establish_intro_wrong_keytype2(void *arg)
  160. {
  161. int retval;
  162. hs_cell_establish_intro_t *establish_intro_cell = NULL;
  163. or_circuit_t *intro_circ = or_circuit_new(0,NULL);;
  164. uint8_t cell_body[RELAY_PAYLOAD_SIZE];
  165. ssize_t cell_len = 0;
  166. uint8_t circuit_key_material[DIGEST_LEN] = {0};
  167. (void)arg;
  168. /* Get the auth key of the intro point */
  169. crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material));
  170. helper_prepare_circ_for_intro(intro_circ, circuit_key_material);
  171. /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
  172. attempt to parse it. */
  173. establish_intro_cell = generate_establish_intro_cell(circuit_key_material,
  174. sizeof(circuit_key_material));
  175. tt_assert(establish_intro_cell);
  176. cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body),
  177. establish_intro_cell);
  178. tt_int_op(cell_len, >, 0);
  179. /* Mutate the auth key type! :) */
  180. cell_body[0] = 42;
  181. /* Receive the cell. Should fail. */
  182. retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len);
  183. tt_int_op(retval, ==, -1);
  184. done:
  185. hs_cell_establish_intro_free(establish_intro_cell);
  186. circuit_free(TO_CIRCUIT(intro_circ));
  187. }
  188. /* Send a legit ESTABLISH_INTRO cell but slightly change the signature. Should
  189. * fail. */
  190. static void
  191. test_establish_intro_wrong_sig(void *arg)
  192. {
  193. int retval;
  194. hs_cell_establish_intro_t *establish_intro_cell = NULL;
  195. or_circuit_t *intro_circ = or_circuit_new(0,NULL);;
  196. uint8_t cell_body[RELAY_PAYLOAD_SIZE];
  197. ssize_t cell_len = 0;
  198. uint8_t circuit_key_material[DIGEST_LEN] = {0};
  199. (void)arg;
  200. /* Get the auth key of the intro point */
  201. crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material));
  202. helper_prepare_circ_for_intro(intro_circ, circuit_key_material);
  203. /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
  204. attempt to parse it. */
  205. establish_intro_cell = generate_establish_intro_cell(circuit_key_material,
  206. sizeof(circuit_key_material));
  207. tt_assert(establish_intro_cell);
  208. cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body),
  209. establish_intro_cell);
  210. tt_int_op(cell_len, >, 0);
  211. /* Mutate the last byte (signature)! :) */
  212. cell_body[cell_len-1]++;
  213. /* Receive the cell. Should fail. */
  214. retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len);
  215. tt_int_op(retval, ==, -1);
  216. done:
  217. hs_cell_establish_intro_free(establish_intro_cell);
  218. circuit_free(TO_CIRCUIT(intro_circ));
  219. }
  220. /* Helper function: Send a well-formed v3 ESTABLISH_INTRO cell to
  221. * <b>intro_circ</b>. Return the cell. */
  222. static hs_cell_establish_intro_t *
  223. helper_establish_intro_v3(or_circuit_t *intro_circ)
  224. {
  225. int retval;
  226. hs_cell_establish_intro_t *establish_intro_cell = NULL;
  227. uint8_t cell_body[RELAY_PAYLOAD_SIZE];
  228. ssize_t cell_len = 0;
  229. uint8_t circuit_key_material[DIGEST_LEN] = {0};
  230. tt_assert(intro_circ);
  231. /* Prepare the circuit for the incoming ESTABLISH_INTRO */
  232. crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material));
  233. helper_prepare_circ_for_intro(intro_circ, circuit_key_material);
  234. /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
  235. attempt to parse it. */
  236. establish_intro_cell = generate_establish_intro_cell(circuit_key_material,
  237. sizeof(circuit_key_material));
  238. tt_assert(establish_intro_cell);
  239. cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body),
  240. establish_intro_cell);
  241. tt_int_op(cell_len, >, 0);
  242. /* Receive the cell */
  243. retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len);
  244. tt_int_op(retval, ==, 0);
  245. done:
  246. return establish_intro_cell;
  247. }
  248. /* Helper function: Send a well-formed v2 ESTABLISH_INTRO cell to
  249. * <b>intro_circ</b>. Return the public key advertised in the cell. */
  250. static crypto_pk_t *
  251. helper_establish_intro_v2(or_circuit_t *intro_circ)
  252. {
  253. crypto_pk_t *key1 = NULL;
  254. int retval;
  255. uint8_t cell_body[RELAY_PAYLOAD_SIZE];
  256. ssize_t cell_len = 0;
  257. uint8_t circuit_key_material[DIGEST_LEN] = {0};
  258. tt_assert(intro_circ);
  259. /* Prepare the circuit for the incoming ESTABLISH_INTRO */
  260. crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material));
  261. helper_prepare_circ_for_intro(intro_circ, circuit_key_material);
  262. /* Send legacy establish_intro */
  263. key1 = pk_generate(0);
  264. /* Use old circuit_key_material why not */
  265. cell_len = encode_establish_intro_cell_legacy((char*)cell_body,
  266. key1,
  267. (char *) circuit_key_material);
  268. tt_int_op(cell_len, >, 0);
  269. /* Receive legacy establish_intro */
  270. retval = hs_intro_received_establish_intro(intro_circ,
  271. cell_body, cell_len);
  272. tt_int_op(retval, ==, 0);
  273. done:
  274. return key1;
  275. }
  276. /** Successfuly register a v2 intro point and a v3 intro point. Ensure that HS
  277. * circuitmap is maintained properly. */
  278. static void
  279. test_intro_point_registration(void *arg)
  280. {
  281. int retval;
  282. hs_circuitmap_ht *the_hs_circuitmap = NULL;
  283. or_circuit_t *intro_circ = NULL;
  284. hs_cell_establish_intro_t *establish_intro_cell = NULL;
  285. ed25519_public_key_t auth_key;
  286. crypto_pk_t *legacy_auth_key = NULL;
  287. or_circuit_t *legacy_intro_circ = NULL;
  288. or_circuit_t *returned_intro_circ = NULL;
  289. (void) arg;
  290. MOCK(hs_intro_send_intro_established_cell, mock_send_intro_established_cell);
  291. hs_circuitmap_init();
  292. /* Check that the circuitmap is currently empty */
  293. {
  294. the_hs_circuitmap = get_hs_circuitmap();
  295. tt_assert(the_hs_circuitmap);
  296. tt_int_op(0, ==, HT_SIZE(the_hs_circuitmap));
  297. /* Do a circuitmap query in any case */
  298. returned_intro_circ = hs_circuitmap_get_intro_circ_v3(&auth_key);
  299. tt_ptr_op(returned_intro_circ, ==, NULL);
  300. }
  301. /* Create a v3 intro point */
  302. {
  303. intro_circ = or_circuit_new(0, NULL);
  304. tt_assert(intro_circ);
  305. establish_intro_cell = helper_establish_intro_v3(intro_circ);
  306. /* Check that the intro point was registered on the HS circuitmap */
  307. the_hs_circuitmap = get_hs_circuitmap();
  308. tt_assert(the_hs_circuitmap);
  309. tt_int_op(1, ==, HT_SIZE(the_hs_circuitmap));
  310. get_auth_key_from_cell(&auth_key, RELAY_COMMAND_ESTABLISH_INTRO,
  311. establish_intro_cell);
  312. returned_intro_circ = hs_circuitmap_get_intro_circ_v3(&auth_key);
  313. tt_ptr_op(intro_circ, ==, returned_intro_circ);
  314. }
  315. /* Create a v2 intro point */
  316. {
  317. char key_digest[DIGEST_LEN];
  318. legacy_intro_circ = or_circuit_new(1, NULL);
  319. tt_assert(legacy_intro_circ);
  320. legacy_auth_key = helper_establish_intro_v2(legacy_intro_circ);
  321. tt_assert(legacy_auth_key);
  322. /* Check that the circuitmap now has two elements */
  323. the_hs_circuitmap = get_hs_circuitmap();
  324. tt_assert(the_hs_circuitmap);
  325. tt_int_op(2, ==, HT_SIZE(the_hs_circuitmap));
  326. /* Check that the new element is our legacy intro circuit. */
  327. retval = crypto_pk_get_digest(legacy_auth_key, key_digest);
  328. tt_int_op(retval, ==, 0);
  329. returned_intro_circ= hs_circuitmap_get_intro_circ_v2((uint8_t*)key_digest);
  330. tt_ptr_op(legacy_intro_circ, ==, returned_intro_circ);
  331. }
  332. /* XXX Continue test and try to register a second v3 intro point with the
  333. * same auth key. Make sure that old intro circuit gets closed. */
  334. done:
  335. crypto_pk_free(legacy_auth_key);
  336. circuit_free(TO_CIRCUIT(intro_circ));
  337. circuit_free(TO_CIRCUIT(legacy_intro_circ));
  338. hs_cell_establish_intro_free(establish_intro_cell);
  339. { /* Test circuitmap free_all function. */
  340. the_hs_circuitmap = get_hs_circuitmap();
  341. tt_assert(the_hs_circuitmap);
  342. hs_circuitmap_free_all();
  343. the_hs_circuitmap = get_hs_circuitmap();
  344. tt_assert(!the_hs_circuitmap);
  345. }
  346. UNMOCK(hs_intro_send_intro_established_cell);
  347. }
  348. static void
  349. test_introduce1_suitable_circuit(void *arg)
  350. {
  351. int ret;
  352. or_circuit_t *circ = NULL;
  353. (void) arg;
  354. /* Valid suitable circuit. */
  355. {
  356. circ = or_circuit_new(0, NULL);
  357. circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_OR);
  358. ret = circuit_is_suitable_for_introduce1(circ);
  359. circuit_free(TO_CIRCUIT(circ));
  360. tt_int_op(ret, OP_EQ, 1);
  361. }
  362. /* Test if the circuit purpose safeguard works correctly. */
  363. {
  364. circ = or_circuit_new(0, NULL);
  365. circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_INTRO_POINT);
  366. ret = circuit_is_suitable_for_introduce1(circ);
  367. circuit_free(TO_CIRCUIT(circ));
  368. tt_int_op(ret, OP_EQ, 0);
  369. }
  370. /* Test the non-edge circuit safeguard works correctly. */
  371. {
  372. circ = or_circuit_new(0, NULL);
  373. circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_OR);
  374. /* Bogus pointer, the check is against NULL on n_chan. */
  375. circ->base_.n_chan = (channel_t *) circ;
  376. ret = circuit_is_suitable_for_introduce1(circ);
  377. circuit_free(TO_CIRCUIT(circ));
  378. tt_int_op(ret, OP_EQ, 0);
  379. }
  380. /* Mangle the circuit a bit more so see if our only one INTRODUCE1 cell
  381. * limit works correctly. */
  382. {
  383. circ = or_circuit_new(0, NULL);
  384. circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_OR);
  385. circ->already_received_introduce1 = 1;
  386. ret = circuit_is_suitable_for_introduce1(circ);
  387. circuit_free(TO_CIRCUIT(circ));
  388. tt_int_op(ret, OP_EQ, 0);
  389. }
  390. done:
  391. ;
  392. }
  393. static void
  394. test_introduce1_is_legacy(void *arg)
  395. {
  396. int ret;
  397. uint8_t request[256];
  398. (void) arg;
  399. /* For a cell to be considered legacy, according to the specification, the
  400. * first 20 bytes MUST BE non-zero else it's a v3 cell. */
  401. memset(request, 'a', DIGEST_LEN);
  402. memset(request + DIGEST_LEN, 0, sizeof(request) - DIGEST_LEN);
  403. ret = introduce1_cell_is_legacy(request);
  404. tt_int_op(ret, OP_EQ, 1);
  405. /* This is a NON legacy cell. */
  406. memset(request, 0, DIGEST_LEN);
  407. memset(request + DIGEST_LEN, 'a', sizeof(request) - DIGEST_LEN);
  408. ret = introduce1_cell_is_legacy(request);
  409. tt_int_op(ret, OP_EQ, 0);
  410. done:
  411. ;
  412. }
  413. static void
  414. test_introduce1_validation(void *arg)
  415. {
  416. int ret;
  417. hs_cell_introduce1_t *cell = NULL;
  418. (void) arg;
  419. /* Create our decoy cell that we'll modify as we go to test the validation
  420. * function of that parsed cell. */
  421. cell = helper_create_introduce1_cell();
  422. /* It should NOT be a legacy cell which will trigger a BUG(). */
  423. memset(cell->legacy_key_id, 'a', sizeof(cell->legacy_key_id));
  424. tor_capture_bugs_(1);
  425. ret = validate_introduce1_parsed_cell(cell);
  426. tor_end_capture_bugs_();
  427. tt_int_op(ret, OP_EQ, -1);
  428. /* Reset legacy ID and make sure it's correct. */
  429. memset(cell->legacy_key_id, 0, sizeof(cell->legacy_key_id));
  430. ret = validate_introduce1_parsed_cell(cell);
  431. tt_int_op(ret, OP_EQ, 0);
  432. /* Non existing auth key type. */
  433. cell->auth_key_type = 42;
  434. ret = validate_introduce1_parsed_cell(cell);
  435. tt_int_op(ret, OP_EQ, -1);
  436. /* Reset is to correct value and make sure it's correct. */
  437. cell->auth_key_type = HS_INTRO_AUTH_KEY_TYPE_ED25519;
  438. ret = validate_introduce1_parsed_cell(cell);
  439. tt_int_op(ret, OP_EQ, 0);
  440. /* Really bad key length. */
  441. cell->auth_key_len = 0;
  442. ret = validate_introduce1_parsed_cell(cell);
  443. tt_int_op(ret, OP_EQ, -1);
  444. cell->auth_key_len = UINT16_MAX;
  445. ret = validate_introduce1_parsed_cell(cell);
  446. tt_int_op(ret, OP_EQ, -1);
  447. /* Correct size, let's try that. */
  448. cell->auth_key_len = sizeof(ed25519_public_key_t);
  449. ret = validate_introduce1_parsed_cell(cell);
  450. tt_int_op(ret, OP_EQ, 0);
  451. /* Set an invalid size of the auth key buffer. */
  452. hs_cell_introduce1_setlen_auth_key(cell, 3);
  453. ret = validate_introduce1_parsed_cell(cell);
  454. tt_int_op(ret, OP_EQ, -1);
  455. /* Reset auth key buffer and make sure it works. */
  456. hs_cell_introduce1_setlen_auth_key(cell, sizeof(ed25519_public_key_t));
  457. ret = validate_introduce1_parsed_cell(cell);
  458. tt_int_op(ret, OP_EQ, 0);
  459. /* Empty encrypted section. */
  460. hs_cell_introduce1_setlen_encrypted(cell, 0);
  461. ret = validate_introduce1_parsed_cell(cell);
  462. tt_int_op(ret, OP_EQ, -1);
  463. /* Reset it to some non zero bytes and validate. */
  464. hs_cell_introduce1_setlen_encrypted(cell, 1);
  465. ret = validate_introduce1_parsed_cell(cell);
  466. tt_int_op(ret, OP_EQ, 0);
  467. done:
  468. hs_cell_introduce1_free(cell);
  469. }
  470. static void
  471. test_received_introduce1_handling(void *arg)
  472. {
  473. int ret;
  474. uint8_t *request = NULL, buf[128];
  475. hs_cell_introduce1_t *cell = NULL;
  476. or_circuit_t *circ = NULL;
  477. (void) arg;
  478. MOCK(relay_send_command_from_edge_, mock_relay_send_command_from_edge);
  479. hs_circuitmap_init();
  480. /* Too small request length. An INTRODUCE1 expect at the very least a
  481. * DIGEST_LEN size. */
  482. {
  483. circ = helper_create_intro_circuit();
  484. ret = hs_intro_received_introduce1(circ, buf, DIGEST_LEN - 1);
  485. tt_int_op(ret, OP_EQ, -1);
  486. circuit_free(TO_CIRCUIT(circ));
  487. }
  488. /* We have a unit test only for the suitability of a circuit to receive an
  489. * INTRODUCE1 cell so from now on we'll only test the handling of a cell. */
  490. /* Bad request. */
  491. {
  492. circ = helper_create_intro_circuit();
  493. uint8_t test[2]; /* Too small request. */
  494. ret = handle_introduce1(circ, test, sizeof(test));
  495. tor_free(circ->p_chan);
  496. circuit_free(TO_CIRCUIT(circ));
  497. tt_int_op(ret, OP_EQ, -1);
  498. }
  499. /* Valid case. */
  500. {
  501. cell = helper_create_introduce1_cell();
  502. size_t request_len = hs_cell_introduce1_encoded_len(cell);
  503. tt_size_op(request_len, OP_GT, 0);
  504. request = tor_malloc_zero(request_len);
  505. ssize_t encoded_len = hs_cell_introduce1_encode(request, request_len, cell);
  506. tt_size_op(encoded_len, OP_GT, 0);
  507. circ = helper_create_intro_circuit();
  508. or_circuit_t *service_circ = helper_create_intro_circuit();
  509. circuit_change_purpose(TO_CIRCUIT(service_circ), CIRCUIT_PURPOSE_INTRO_POINT);
  510. /* Register the circuit in the map for the auth key of the cell. */
  511. ed25519_public_key_t auth_key;
  512. const uint8_t *cell_auth_key =
  513. hs_cell_introduce1_getconstarray_auth_key(cell);
  514. memcpy(auth_key.pubkey, cell_auth_key, ED25519_PUBKEY_LEN);
  515. hs_circuitmap_register_intro_circ_v3(service_circ, &auth_key);
  516. ret = hs_intro_received_introduce1(circ, request, request_len);
  517. circuit_free(TO_CIRCUIT(circ));
  518. circuit_free(TO_CIRCUIT(service_circ));
  519. tt_int_op(ret, OP_EQ, 0);
  520. }
  521. /* Valid legacy cell. */
  522. {
  523. tor_free(request);
  524. hs_cell_introduce1_free(cell);
  525. cell = helper_create_introduce1_cell();
  526. uint8_t *legacy_key_id = hs_cell_introduce1_getarray_legacy_key_id(cell);
  527. memset(legacy_key_id, 'a', DIGEST_LEN);
  528. /* Add an arbitrary amount of data for the payload of a v2 cell. */
  529. size_t request_len = hs_cell_introduce1_encoded_len(cell) + 256;
  530. tt_size_op(request_len, OP_GT, 0);
  531. request = tor_malloc_zero(request_len + 256);
  532. ssize_t encoded_len = hs_cell_introduce1_encode(request, request_len, cell);
  533. tt_size_op(encoded_len, OP_GT, 0);
  534. circ = helper_create_intro_circuit();
  535. or_circuit_t *service_circ = helper_create_intro_circuit();
  536. circuit_change_purpose(TO_CIRCUIT(service_circ), CIRCUIT_PURPOSE_INTRO_POINT);
  537. /* Register the circuit in the map for the auth key of the cell. */
  538. uint8_t token[REND_TOKEN_LEN];
  539. memcpy(token, legacy_key_id, sizeof(token));
  540. hs_circuitmap_register_intro_circ_v2(service_circ, token);
  541. ret = hs_intro_received_introduce1(circ, request, request_len);
  542. circuit_free(TO_CIRCUIT(circ));
  543. circuit_free(TO_CIRCUIT(service_circ));
  544. tt_int_op(ret, OP_EQ, 0);
  545. }
  546. done:
  547. hs_cell_introduce1_free(cell);
  548. tor_free(request);
  549. hs_circuitmap_free_all();
  550. UNMOCK(relay_send_command_from_edge_);
  551. }
  552. struct testcase_t hs_intropoint_tests[] = {
  553. { "intro_point_registration",
  554. test_intro_point_registration, TT_FORK, NULL, NULL },
  555. { "receive_establish_intro_wrong_keytype",
  556. test_establish_intro_wrong_keytype, TT_FORK, NULL, NULL },
  557. { "receive_establish_intro_wrong_keytype2",
  558. test_establish_intro_wrong_keytype2, TT_FORK, NULL, NULL },
  559. { "receive_establish_intro_wrong_purpose",
  560. test_establish_intro_wrong_purpose, TT_FORK, NULL, NULL },
  561. { "receive_establish_intro_wrong_sig",
  562. test_establish_intro_wrong_sig, TT_FORK, NULL, NULL },
  563. { "introduce1_suitable_circuit",
  564. test_introduce1_suitable_circuit, TT_FORK, NULL, NULL },
  565. { "introduce1_is_legacy",
  566. test_introduce1_is_legacy, TT_FORK, NULL, NULL },
  567. { "introduce1_validation",
  568. test_introduce1_validation, TT_FORK, NULL, NULL },
  569. { "received_introduce1_handling",
  570. test_received_introduce1_handling, TT_FORK, NULL, NULL },
  571. END_OF_TESTCASES
  572. };