tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

test_hs_pow_slow.c (11158B)


      1 /* Copyright (c) 2020-2023, The Tor Project, Inc. */
      2 /* See LICENSE for licensing information */
      3 
      4 /**
      5 * \file test_hs_pow_slow.c
      6 * \brief Slower (solve + verify) tests for service proof-of-work defenses.
      7 */
      8 
      9 #define HS_SERVICE_PRIVATE
     10 
     11 #include "lib/cc/compat_compiler.h"
     12 #include "lib/cc/torint.h"
     13 
     14 #include "test/test.h"
     15 #include "test/test_helpers.h"
     16 #include "test/log_test_helpers.h"
     17 #include "test/rng_test_helpers.h"
     18 
     19 #include "app/config/config.h"
     20 #include "feature/hs/hs_pow.h"
     21 
     22 static int
     23 testing_one_hs_pow_solution(const hs_pow_solution_t *ref_solution,
     24                            const ed25519_public_key_t *service_blinded_id,
     25                            const uint8_t *seed)
     26 {
     27  int retval = -1;
     28  hs_pow_solution_t sol_buffer;
     29  hs_pow_service_state_t *s = tor_malloc_zero(sizeof(hs_pow_service_state_t));
     30  s->rend_request_pqueue = smartlist_new();
     31 
     32  memcpy(s->seed_previous, seed, HS_POW_SEED_LEN);
     33 
     34  const unsigned num_variants = 10;
     35  const unsigned num_attempts = 3;
     36 
     37  for (unsigned variant = 0; variant < num_variants; variant++) {
     38    hs_pow_remove_seed_from_cache(seed);
     39 
     40    for (unsigned attempt = 0; attempt < num_attempts; attempt++) {
     41      int expected = -1;
     42      memcpy(&sol_buffer, ref_solution, sizeof sol_buffer);
     43 
     44      /* One positive test, and a few negative tests of corrupted solutions */
     45      if (variant == 0) {
     46        if (attempt == 0) {
     47          /* Only the first attempt should succeed (nonce replay) */
     48          expected = 0;
     49        }
     50      } else if (variant & 1) {
     51        sol_buffer.nonce[variant / 2 % HS_POW_NONCE_LEN]++;
     52      } else {
     53        sol_buffer.equix_solution[variant / 2 % HS_POW_EQX_SOL_LEN]++;
     54      }
     55 
     56      tt_int_op(expected, OP_EQ,
     57                hs_pow_verify(service_blinded_id, s, &sol_buffer));
     58    }
     59  }
     60 
     61  retval = 0;
     62 done:
     63  hs_pow_free_service_state(s);
     64  return retval;
     65 }
     66 
     67 static void
     68 test_hs_pow_vectors(void *arg)
     69 {
     70  (void)arg;
     71 
     72  /* All test vectors include a solve, verify, and fail-verify phase
     73   * as well as a test of the nonce replay cache. The initial nonce for the
     74   * solution search is set via the solver's RNG data. The amount of solve
     75   * time during test execution can be tuned based on how far away from the
     76   * winning nonce our solve_rng value is set.
     77   */
     78  static const struct {
     79    uint32_t effort;
     80    const char *solve_rng_hex;
     81    const char *seed_hex;
     82    const char *service_blinded_id_hex;
     83    const char *nonce_hex;
     84    const char *sol_hex;
     85  } vectors[] = {
     86    {
     87      0, "55555555555555555555555555555555",
     88      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
     89      "1111111111111111111111111111111111111111111111111111111111111111",
     90      "55555555555555555555555555555555", "4312f87ceab844c78e1c793a913812d7"
     91    },
     92    {
     93      1, "55555555555555555555555555555555",
     94      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
     95      "1111111111111111111111111111111111111111111111111111111111111111",
     96      "55555555555555555555555555555555", "84355542ab2b3f79532ef055144ac5ab"
     97    },
     98    {
     99      1, "55555555555555555555555555555555",
    100      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    101      "1111111111111111111111111111111111111111111111111111111111111110",
    102      "55555555555555555555555555555555", "115e4b70da858792fc205030b8c83af9"
    103    },
    104    {
    105      2, "55555555555555555555555555555555",
    106      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    107      "1111111111111111111111111111111111111111111111111111111111111111",
    108      "55555555555555555555555555555555", "4600a93a535ed76dc746c99942ab7de2"
    109    },
    110    {
    111      10, "55555555555555555555555555555555",
    112      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    113      "1111111111111111111111111111111111111111111111111111111111111111",
    114      "56555555555555555555555555555555", "128bbda5df2929c3be086de2aad34aed"
    115    },
    116    {
    117      10, "ffffffffffffffffffffffffffffffff",
    118      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    119      "1111111111111111111111111111111111111111111111111111111111111111",
    120      "01000000000000000000000000000000", "203af985537fadb23f3ed5873b4c81ce"
    121    },
    122    {
    123      1337, "7fffffffffffffffffffffffffffffff",
    124      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    125      "4111111111111111111111111111111111111111111111111111111111111111",
    126      "01000000000000000000000000000000", "31c377cb72796ed80ae77df6ac1d6bfd"
    127    },
    128    {
    129      31337, "34a20000000000000000000000000000",
    130      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    131      "1111111111111111111111111111111111111111111111111111111111111111",
    132      "36a20000000000000000000000000000", "ca6899b91113aaf7536f28db42526bff"
    133    },
    134    {
    135      100, "55555555555555555555555555555555",
    136      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    137      "1111111111111111111111111111111111111111111111111111111111111111",
    138      "56555555555555555555555555555555", "3a4122a240bd7abfc922ab3cbb9479ed"
    139    },
    140    {
    141      1000, "d3555555555555555555555555555555",
    142      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    143      "1111111111111111111111111111111111111111111111111111111111111111",
    144      "d4555555555555555555555555555555", "338cc08f57697ce8ac2e4b453057d6e9"
    145    },
    146    {
    147      10000, "c5715555555555555555555555555555",
    148      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    149      "1111111111111111111111111111111111111111111111111111111111111111",
    150      "c8715555555555555555555555555555", "9f2d3d4ed831ac96ad34c25fb59ff3e2"
    151    },
    152    {
    153      100000, "418d5655555555555555555555555555",
    154      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    155      "1111111111111111111111111111111111111111111111111111111111111111",
    156      "428d5655555555555555555555555555", "9863f3acd2d15adfd244a7ca61d4c6ff"
    157    },
    158    {
    159      1000000, "58217255555555555555555555555555",
    160      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    161      "1111111111111111111111111111111111111111111111111111111111111111",
    162      "59217255555555555555555555555555", "0f3db97b9cac20c1771680a1a34848d3"
    163    },
    164    {
    165      1, "d0aec1669384bfe5ed39cd724d6c7954",
    166      "c52be1f8a5e6cc3b8fb71cfdbe272cbc91d4d035400f2f94fb0d0074794e0a07",
    167      "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed",
    168      "d1aec1669384bfe5ed39cd724d6c7954", "462606e5f8c2f3f844127b8bfdd6b4ff"
    169    },
    170    {
    171      1, "b4d0e611e6935750fcf9406aae131f62",
    172      "86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f",
    173      "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed",
    174      "b4d0e611e6935750fcf9406aae131f62", "9f3fbd50b1a83fb63284bde44318c0fd"
    175    },
    176    {
    177      1, "b4d0e611e6935750fcf9406aae131f62",
    178      "9dfbd06d86fed8e12de3ab214e1a63ea61f46253fe08346a20378da70c4a327d",
    179      "bec632eb76123956f99a06d394fcbee8f135b8ed01f2e90aabe404cb0346744a",
    180      "b4d0e611e6935750fcf9406aae131f62", "161baa7490356292d020065fdbe55ffc"
    181    },
    182    {
    183      1, "40559fdbc34326d9d2f18ed277469c63",
    184      "86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f",
    185      "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed",
    186      "40559fdbc34326d9d2f18ed277469c63", "fa649c6a2c5c0bb6a3511b9ea4b448d1"
    187    },
    188    {
    189      10000, "34569fdbc34326d9d2f18ed277469c63",
    190      "86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f",
    191      "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed",
    192      "36569fdbc34326d9d2f18ed277469c63", "2802951e623c74adc443ab93e99633ee"
    193    },
    194    {
    195      100000, "2cff9fdbc34326d9d2f18ed277469c63",
    196      "86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f",
    197      "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed",
    198      "2eff9fdbc34326d9d2f18ed277469c63", "400cb091139f86b352119f6e131802d6"
    199    },
    200    {
    201      1000000, "5243b3dbc34326d9d2f18ed277469c63",
    202      "86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f",
    203      "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed",
    204      "5543b3dbc34326d9d2f18ed277469c63", "b47c718b56315e9697173a6bac1feaa4"
    205    },
    206  };
    207 
    208  const unsigned num_vectors = sizeof vectors / sizeof vectors[0];
    209  for (unsigned vec_i = 0; vec_i < num_vectors; vec_i++) {
    210    const char *seed_hex = vectors[vec_i].seed_hex;
    211    const char *service_blinded_id_hex = vectors[vec_i].service_blinded_id_hex;
    212    const char *solve_rng_hex = vectors[vec_i].solve_rng_hex;
    213    const char *nonce_hex = vectors[vec_i].nonce_hex;
    214    const char *sol_hex = vectors[vec_i].sol_hex;
    215 
    216    uint8_t rng_bytes[HS_POW_NONCE_LEN];
    217    hs_pow_solution_t output;
    218    hs_pow_solution_t solution = { 0 };
    219    hs_pow_solver_inputs_t input = {
    220      .effort = vectors[vec_i].effort,
    221      .CompiledProofOfWorkHash = -1
    222    };
    223 
    224    tt_int_op(strlen(service_blinded_id_hex), OP_EQ, 2 * HS_POW_ID_LEN);
    225    tt_int_op(strlen(seed_hex), OP_EQ, 2 * sizeof input.seed);
    226    tt_int_op(strlen(solve_rng_hex), OP_EQ, 2 * sizeof rng_bytes);
    227    tt_int_op(strlen(nonce_hex), OP_EQ, 2 * sizeof solution.nonce);
    228    tt_int_op(strlen(sol_hex), OP_EQ, 2 * sizeof solution.equix_solution);
    229 
    230    tt_int_op(base16_decode((char*)input.service_blinded_id.pubkey,
    231                            HS_POW_ID_LEN, service_blinded_id_hex,
    232                            2 * HS_POW_ID_LEN),
    233                            OP_EQ, HS_POW_ID_LEN);
    234    tt_int_op(base16_decode((char*)input.seed, HS_POW_SEED_LEN,
    235                            seed_hex, 2 * HS_POW_SEED_LEN),
    236                            OP_EQ, HS_POW_SEED_LEN);
    237    tt_int_op(base16_decode((char*)rng_bytes, sizeof rng_bytes,
    238                            solve_rng_hex, 2 * sizeof rng_bytes),
    239                            OP_EQ, HS_POW_NONCE_LEN);
    240    tt_int_op(base16_decode((char*)&solution.nonce, sizeof solution.nonce,
    241                            nonce_hex, 2 * sizeof solution.nonce),
    242                            OP_EQ, HS_POW_NONCE_LEN);
    243    tt_int_op(base16_decode((char*)&solution.equix_solution,
    244                            sizeof solution.equix_solution,
    245                            sol_hex, 2 * sizeof solution.equix_solution),
    246                            OP_EQ, HS_POW_EQX_SOL_LEN);
    247    memcpy(solution.seed_head, input.seed, HS_POW_SEED_HEAD_LEN);
    248 
    249    memset(&output, 0xaa, sizeof output);
    250    testing_enable_prefilled_rng(rng_bytes, HS_POW_NONCE_LEN);
    251    tt_int_op(0, OP_EQ, hs_pow_solve(&input, &output));
    252    testing_disable_prefilled_rng();
    253 
    254    tt_mem_op(solution.seed_head, OP_EQ, output.seed_head,
    255              sizeof output.seed_head);
    256    tt_mem_op(solution.nonce, OP_EQ, output.nonce,
    257              sizeof output.nonce);
    258    tt_mem_op(&solution.equix_solution, OP_EQ, &output.equix_solution,
    259              sizeof output.equix_solution);
    260 
    261    tt_int_op(testing_one_hs_pow_solution(&output, &input.service_blinded_id,
    262                                          input.seed), OP_EQ, 0);
    263  }
    264 
    265 done:
    266  testing_disable_prefilled_rng();
    267  hs_pow_remove_seed_from_cache(NULL);
    268 }
    269 
    270 struct testcase_t slow_hs_pow_tests[] = {
    271  { "vectors", test_hs_pow_vectors, 0, NULL, NULL },
    272  END_OF_TESTCASES
    273 };