LCOV - code coverage report
Current view: top level - test - test_hs_cell.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 109 109 100.0 %
Date: 2021-11-24 03:28:48 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2017-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file test_hs_cell.c
       6             :  * \brief Test hidden service cell functionality.
       7             :  */
       8             : 
       9             : #define HS_INTROPOINT_PRIVATE
      10             : #define HS_SERVICE_PRIVATE
      11             : 
      12             : #include "test/test.h"
      13             : #include "test/test_helpers.h"
      14             : #include "test/log_test_helpers.h"
      15             : 
      16             : #include "lib/crypt_ops/crypto_ed25519.h"
      17             : #include "lib/crypt_ops/crypto_rand.h"
      18             : #include "feature/hs/hs_cell.h"
      19             : #include "feature/hs/hs_intropoint.h"
      20             : #include "feature/hs/hs_service.h"
      21             : 
      22             : /* Trunnel. */
      23             : #include "trunnel/hs/cell_common.h"
      24             : #include "trunnel/hs/cell_establish_intro.h"
      25             : 
      26             : /** We simulate the creation of an outgoing ESTABLISH_INTRO cell, and then we
      27             :  *  parse it from the receiver side. */
      28             : static void
      29           1 : test_gen_establish_intro_cell(void *arg)
      30             : {
      31           1 :   (void) arg;
      32           1 :   ssize_t ret;
      33           1 :   char circ_nonce[DIGEST_LEN] = {0};
      34           1 :   uint8_t buf[RELAY_PAYLOAD_SIZE];
      35           1 :   trn_cell_establish_intro_t *cell_in = NULL;
      36             : 
      37           1 :   crypto_rand(circ_nonce, sizeof(circ_nonce));
      38             : 
      39             :   /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
      40             :      attempt to parse it. */
      41             :   {
      42           1 :     hs_service_config_t config;
      43           1 :     memset(&config, 0, sizeof(config));
      44             :     /* We only need the auth key pair here. */
      45           1 :     hs_service_intro_point_t *ip = service_intro_point_new(NULL);
      46             :     /* Auth key pair is generated in the constructor so we are all set for
      47             :      * using this IP object. */
      48           1 :     ret = hs_cell_build_establish_intro(circ_nonce, &config, ip, buf);
      49           1 :     service_intro_point_free(ip);
      50           1 :     tt_u64_op(ret, OP_GT, 0);
      51             :   }
      52             : 
      53             :   /* Check the contents of the cell */
      54             :   {
      55             :     /* First byte is the auth key type: make sure its correct */
      56           1 :     tt_int_op(buf[0], OP_EQ, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519);
      57             :     /* Next two bytes is auth key len */
      58           1 :     tt_int_op(ntohs(get_uint16(buf+1)), OP_EQ, ED25519_PUBKEY_LEN);
      59             :     /* Skip to the number of extensions: no extensions */
      60           1 :     tt_int_op(buf[35], OP_EQ, 0);
      61             :     /* Skip to the sig len. Make sure it's the size of an ed25519 sig */
      62           1 :     tt_int_op(ntohs(get_uint16(buf+35+1+32)), OP_EQ, ED25519_SIG_LEN);
      63             :   }
      64             : 
      65             :   /* Parse it as the receiver */
      66             :   {
      67           1 :     ret = trn_cell_establish_intro_parse(&cell_in, buf, sizeof(buf));
      68           1 :     tt_u64_op(ret, OP_GT, 0);
      69             : 
      70           1 :     ret = verify_establish_intro_cell(cell_in,
      71             :                                       (const uint8_t *) circ_nonce,
      72             :                                       sizeof(circ_nonce));
      73           1 :     tt_u64_op(ret, OP_EQ, 0);
      74             :   }
      75             : 
      76           1 :  done:
      77           1 :   trn_cell_establish_intro_free(cell_in);
      78           1 : }
      79             : 
      80             : /* Mocked ed25519_sign_prefixed() function that always fails :) */
      81             : static int
      82           1 : mock_ed25519_sign_prefixed(ed25519_signature_t *signature_out,
      83             :                            const uint8_t *msg, size_t msg_len,
      84             :                            const char *prefix_str,
      85             :                            const ed25519_keypair_t *keypair) {
      86           1 :   (void) signature_out;
      87           1 :   (void) msg;
      88           1 :   (void) msg_len;
      89           1 :   (void) prefix_str;
      90           1 :   (void) keypair;
      91           1 :   return -1;
      92             : }
      93             : 
      94             : /** We simulate a failure to create an ESTABLISH_INTRO cell */
      95             : static void
      96           1 : test_gen_establish_intro_cell_bad(void *arg)
      97             : {
      98           1 :   (void) arg;
      99           1 :   ssize_t cell_len = 0;
     100           1 :   trn_cell_establish_intro_t *cell = NULL;
     101           1 :   char circ_nonce[DIGEST_LEN] = {0};
     102           1 :   hs_service_intro_point_t *ip = NULL;
     103           1 :   hs_service_config_t config;
     104             : 
     105           1 :   memset(&config, 0, sizeof(config));
     106             : 
     107           1 :   MOCK(ed25519_sign_prefixed, mock_ed25519_sign_prefixed);
     108             : 
     109           1 :   crypto_rand(circ_nonce, sizeof(circ_nonce));
     110             : 
     111           1 :   setup_full_capture_of_logs(LOG_WARN);
     112             :   /* Easiest way to make that function fail is to mock the
     113             :      ed25519_sign_prefixed() function and make it fail. */
     114           1 :   cell = trn_cell_establish_intro_new();
     115           1 :   tt_assert(cell);
     116           1 :   ip = service_intro_point_new(NULL);
     117           1 :   cell_len = hs_cell_build_establish_intro(circ_nonce, &config, ip, NULL);
     118           1 :   service_intro_point_free(ip);
     119           1 :   expect_log_msg_containing("Unable to make signature for "
     120           1 :                             "ESTABLISH_INTRO cell.");
     121           1 :   teardown_capture_of_logs();
     122           1 :   tt_i64_op(cell_len, OP_EQ, -1);
     123             : 
     124           1 :  done:
     125           1 :   trn_cell_establish_intro_free(cell);
     126           1 :   UNMOCK(ed25519_sign_prefixed);
     127           1 : }
     128             : 
     129             : static void
     130           1 : test_gen_establish_intro_dos_ext(void *arg)
     131             : {
     132           1 :   ssize_t ret;
     133           1 :   hs_service_config_t config;
     134           1 :   hs_service_intro_point_t *ip = NULL;
     135           1 :   trn_cell_extension_t *extensions = NULL;
     136           1 :   trn_cell_extension_dos_t *dos = NULL;
     137             : 
     138           1 :   (void) arg;
     139             : 
     140           1 :   memset(&config, 0, sizeof(config));
     141           1 :   ip = service_intro_point_new(NULL);
     142           1 :   tt_assert(ip);
     143           1 :   ip->support_intro2_dos_defense = 1;
     144             : 
     145             :   /* Case 1: No DoS parameters so no extension to be built. */
     146           1 :   extensions = build_establish_intro_extensions(&config, ip);
     147           1 :   tt_int_op(trn_cell_extension_get_num(extensions), OP_EQ, 0);
     148           1 :   trn_cell_extension_free(extensions);
     149           1 :   extensions = NULL;
     150             : 
     151             :   /* Case 2: Enable the DoS extension. Parameter set to 0 should indicate to
     152             :    * disable the defense on the intro point but there should be an extension
     153             :    * nonetheless in the cell. */
     154           1 :   config.has_dos_defense_enabled = 1;
     155           1 :   extensions = build_establish_intro_extensions(&config, ip);
     156           1 :   tt_int_op(trn_cell_extension_get_num(extensions), OP_EQ, 1);
     157             :   /* Validate the extension. */
     158           1 :   const trn_cell_extension_field_t *field =
     159           1 :     trn_cell_extension_getconst_fields(extensions, 0);
     160           1 :   tt_int_op(trn_cell_extension_field_get_field_type(field), OP_EQ,
     161             :             TRUNNEL_CELL_EXTENSION_TYPE_DOS);
     162           1 :   ret = trn_cell_extension_dos_parse(&dos,
     163             :                  trn_cell_extension_field_getconstarray_field(field),
     164             :                  trn_cell_extension_field_getlen_field(field));
     165           1 :   tt_int_op(ret, OP_EQ, 19);
     166             :   /* Rate per sec param. */
     167           1 :   const trn_cell_extension_dos_param_t *param =
     168           1 :     trn_cell_extension_dos_getconst_params(dos, 0);
     169           1 :   tt_int_op(trn_cell_extension_dos_param_get_type(param), OP_EQ,
     170             :             TRUNNEL_DOS_PARAM_TYPE_INTRO2_RATE_PER_SEC);
     171           1 :   tt_u64_op(trn_cell_extension_dos_param_get_value(param), OP_EQ, 0);
     172             :   /* Burst per sec param. */
     173           1 :   param = trn_cell_extension_dos_getconst_params(dos, 1);
     174           1 :   tt_int_op(trn_cell_extension_dos_param_get_type(param), OP_EQ,
     175             :             TRUNNEL_DOS_PARAM_TYPE_INTRO2_BURST_PER_SEC);
     176           1 :   tt_u64_op(trn_cell_extension_dos_param_get_value(param), OP_EQ, 0);
     177           1 :   trn_cell_extension_dos_free(dos); dos = NULL;
     178           1 :   trn_cell_extension_free(extensions); extensions = NULL;
     179             : 
     180             :   /* Case 3: Enable the DoS extension. Parameter set to some normal values. */
     181           1 :   config.has_dos_defense_enabled = 1;
     182           1 :   config.intro_dos_rate_per_sec = 42;
     183           1 :   config.intro_dos_burst_per_sec = 250;
     184           1 :   extensions = build_establish_intro_extensions(&config, ip);
     185           1 :   tt_int_op(trn_cell_extension_get_num(extensions), OP_EQ, 1);
     186             :   /* Validate the extension. */
     187           1 :   field = trn_cell_extension_getconst_fields(extensions, 0);
     188           1 :   tt_int_op(trn_cell_extension_field_get_field_type(field), OP_EQ,
     189             :             TRUNNEL_CELL_EXTENSION_TYPE_DOS);
     190           1 :   ret = trn_cell_extension_dos_parse(&dos,
     191             :                  trn_cell_extension_field_getconstarray_field(field),
     192             :                  trn_cell_extension_field_getlen_field(field));
     193           1 :   tt_int_op(ret, OP_EQ, 19);
     194             :   /* Rate per sec param. */
     195           1 :   param = trn_cell_extension_dos_getconst_params(dos, 0);
     196           1 :   tt_int_op(trn_cell_extension_dos_param_get_type(param), OP_EQ,
     197             :             TRUNNEL_DOS_PARAM_TYPE_INTRO2_RATE_PER_SEC);
     198           1 :   tt_u64_op(trn_cell_extension_dos_param_get_value(param), OP_EQ, 42);
     199             :   /* Burst per sec param. */
     200           1 :   param = trn_cell_extension_dos_getconst_params(dos, 1);
     201           1 :   tt_int_op(trn_cell_extension_dos_param_get_type(param), OP_EQ,
     202             :             TRUNNEL_DOS_PARAM_TYPE_INTRO2_BURST_PER_SEC);
     203           1 :   tt_u64_op(trn_cell_extension_dos_param_get_value(param), OP_EQ, 250);
     204           1 :   trn_cell_extension_dos_free(dos); dos = NULL;
     205           1 :   trn_cell_extension_free(extensions); extensions = NULL;
     206             : 
     207           1 :  done:
     208           1 :   service_intro_point_free(ip);
     209           1 :   trn_cell_extension_dos_free(dos);
     210           1 :   trn_cell_extension_free(extensions);
     211           1 : }
     212             : 
     213             : struct testcase_t hs_cell_tests[] = {
     214             :   { "gen_establish_intro_cell", test_gen_establish_intro_cell, TT_FORK,
     215             :     NULL, NULL },
     216             :   { "gen_establish_intro_cell_bad", test_gen_establish_intro_cell_bad, TT_FORK,
     217             :     NULL, NULL },
     218             :   { "gen_establish_intro_dos_ext", test_gen_establish_intro_dos_ext, TT_FORK,
     219             :     NULL, NULL },
     220             : 
     221             :   END_OF_TESTCASES
     222             : };
     223             : 

Generated by: LCOV version 1.14