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 };