test_ntor_v3.c (11856B)
1 /* Copyright (c) 2001-2004, Roger Dingledine. 2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. 3 * Copyright (c) 2007-2021, The Tor Project, Inc. */ 4 /* See LICENSE for licensing information */ 5 6 #include "orconfig.h" 7 #define ONION_NTOR_V3_PRIVATE 8 #include "core/or/or.h" 9 #include "test/test.h" 10 #include "lib/crypt_ops/crypto_curve25519.h" 11 #include "lib/crypt_ops/crypto_ed25519.h" 12 #include "core/crypto/onion_ntor_v3.h" 13 #include "core/crypto/onion_crypto.h" 14 #include "core/or/extend_info_st.h" 15 #include "core/or/crypt_path_st.h" 16 #define TOR_CONGESTION_CONTROL_PRIVATE 17 #define TOR_CONGESTION_CONTROL_COMMON_PRIVATE 18 #include "core/or/congestion_control_st.h" 19 #include "core/or/congestion_control_common.h" 20 #include "app/config/config.h" 21 22 #define unhex(arry, s) \ 23 { tt_int_op(sizeof(arry), OP_EQ, \ 24 base16_decode((char*)arry, sizeof(arry), s, strlen(s))); \ 25 } 26 27 static void 28 test_ntor3_testvecs(void *arg) 29 { 30 (void)arg; 31 char *mem_op_hex_tmp = NULL; // temp val to make test_memeq_hex work. 32 33 ntor3_server_handshake_state_t *relay_state = NULL; 34 uint8_t *onion_skin = NULL; 35 size_t onion_skin_len; 36 ntor3_handshake_state_t *client_state = NULL; 37 uint8_t *cm = NULL, *sm = NULL; 38 size_t cm_len, sm_len; 39 di_digest256_map_t *private_keys = NULL; 40 uint8_t *server_handshake = NULL; 41 size_t server_handshake_len; 42 43 // Test vectors from python implementation, confirmed with rust 44 // implementation. 45 curve25519_keypair_t relay_keypair_b; 46 curve25519_keypair_t client_keypair_x; 47 curve25519_keypair_t relay_keypair_y; 48 ed25519_public_key_t relay_id; 49 50 unhex(relay_keypair_b.seckey.secret_key, 51 "4051daa5921cfa2a1c27b08451324919538e79e788a81b38cbed097a5dff454a"); 52 unhex(relay_keypair_b.pubkey.public_key, 53 "f8307a2bc1870b00b828bb74dbb8fd88e632a6375ab3bcd1ae706aaa8b6cdd1d"); 54 unhex(relay_id.pubkey, 55 "9fad2af287ef942632833d21f946c6260c33fae6172b60006e86e4a6911753a2"); 56 unhex(client_keypair_x.seckey.secret_key, 57 "b825a3719147bcbe5fb1d0b0fcb9c09e51948048e2e3283d2ab7b45b5ef38b49"); 58 unhex(client_keypair_x.pubkey.public_key, 59 "252fe9ae91264c91d4ecb8501f79d0387e34ad8ca0f7c995184f7d11d5da4f46"); 60 unhex(relay_keypair_y.seckey.secret_key, 61 "4865a5b7689dafd978f529291c7171bc159be076b92186405d13220b80e2a053"); 62 unhex(relay_keypair_y.pubkey.public_key, 63 "4bf4814326fdab45ad5184f5518bd7fae25dc59374062698201a50a22954246d"); 64 65 uint8_t client_message[11]; 66 uint8_t verification[5]; 67 unhex(client_message, "68656c6c6f20776f726c64"); 68 unhex(verification, "78797a7a79"); 69 70 // ========= Client handshake 1. 71 72 onion_skin_ntor3_create_nokeygen( 73 &client_keypair_x, 74 &relay_id, 75 &relay_keypair_b.pubkey, 76 verification, 77 sizeof(verification), 78 client_message, 79 sizeof(client_message), 80 &client_state, 81 &onion_skin, 82 &onion_skin_len); 83 84 const char expect_client_handshake[] = "9fad2af287ef942632833d21f946c6260c" 85 "33fae6172b60006e86e4a6911753a2f8307a2bc1870b00b828bb74dbb8fd88e632a6375" 86 "ab3bcd1ae706aaa8b6cdd1d252fe9ae91264c91d4ecb8501f79d0387e34ad8ca0f7c995" 87 "184f7d11d5da4f463bebd9151fd3b47c180abc9e044d53565f04d82bbb3bebed3d06cea" 88 "65db8be9c72b68cd461942088502f67"; 89 90 tt_int_op(onion_skin_len, OP_EQ, strlen(expect_client_handshake)/2); 91 test_memeq_hex(onion_skin, expect_client_handshake); 92 93 // ========= Relay handshake. 94 95 dimap_add_entry(&private_keys, 96 relay_keypair_b.pubkey.public_key, 97 &relay_keypair_b); 98 99 int r = onion_skin_ntor3_server_handshake_part1( 100 private_keys, 101 &client_keypair_x, 102 &relay_id, 103 onion_skin, 104 onion_skin_len, 105 verification, 106 sizeof(verification), 107 &cm, 108 &cm_len, 109 &relay_state); 110 tt_int_op(r, OP_EQ, 0); 111 tt_int_op(cm_len, OP_EQ, sizeof(client_message)); 112 tt_mem_op(cm, OP_EQ, client_message, cm_len); 113 114 uint8_t server_message[10]; 115 unhex(server_message, "486f6c61204d756e646f"); 116 117 uint8_t server_keys[256]; 118 onion_skin_ntor3_server_handshake_part2_nokeygen( 119 &relay_keypair_y, 120 relay_state, 121 verification, 122 sizeof(verification), 123 server_message, 124 sizeof(server_message), 125 &server_handshake, 126 &server_handshake_len, 127 server_keys, 128 sizeof(server_keys)); 129 130 const char expect_server_handshake[] = "4bf4814326fdab45ad5184f5518bd7fae25" 131 "dc59374062698201a50a22954246d2fc5f8773ca824542bc6cf6f57c7c29bbf4e5476461" 132 "ab130c5b18ab0a91276651202c3e1e87c0d32054c"; 133 tt_int_op(server_handshake_len, OP_EQ, strlen(expect_server_handshake)/2); 134 test_memeq_hex(server_handshake, expect_server_handshake); 135 136 uint8_t expect_keys[256]; 137 unhex(expect_keys, "9c19b631fd94ed86a817e01f6c80b0743a43f5faebd39cfaa8b00f" 138 "a8bcc65c3bfeaa403d91acbd68a821bf6ee8504602b094a254392a07737d5662768" 139 "c7a9fb1b2814bb34780eaee6e867c773e28c212ead563e98a1cd5d5b4576f5ee61c" 140 "59bde025ff2851bb19b721421694f263818e3531e43a9e4e3e2c661e2ad547d8984" 141 "caa28ebecd3e4525452299be26b9185a20a90ce1eac20a91f2832d731b54502b097" 142 "49b5a2a2949292f8cfcbeffb790c7790ed935a9d251e7e336148ea83b063a5618fc" 143 "ff674a44581585fd22077ca0e52c59a24347a38d1a1ceebddbf238541f226b8f88d" 144 "0fb9c07a1bcd2ea764bbbb5dacdaf5312a14c0b9e4f06309b0333b4a"); 145 tt_mem_op(server_keys, OP_EQ, expect_keys, 256); 146 147 // ===== Client handshake 2 148 149 uint8_t client_keys[256]; 150 r = onion_ntor3_client_handshake( 151 client_state, 152 server_handshake, 153 server_handshake_len, 154 verification, 155 sizeof(verification), 156 client_keys, 157 sizeof(client_keys), 158 &sm, 159 &sm_len); 160 161 tt_int_op(r, OP_EQ, 0); 162 tt_int_op(sm_len, OP_EQ, sizeof(server_message)); 163 tt_mem_op(sm, OP_EQ, server_message, sizeof(server_message)); 164 tt_mem_op(client_keys, OP_EQ, server_keys, 256); 165 166 done: 167 tor_free(onion_skin); 168 tor_free(server_handshake); 169 tor_free(mem_op_hex_tmp); 170 ntor3_handshake_state_free(client_state); 171 ntor3_server_handshake_state_free(relay_state); 172 tor_free(cm); 173 tor_free(sm); 174 dimap_free(private_keys, NULL); 175 } 176 177 static void 178 run_full_handshake(circuit_params_t *serv_params_in, 179 circuit_params_t *client_params_out, 180 circuit_params_t *serv_params_out) 181 { 182 extend_info_t info = {0}; 183 uint8_t onionskin[CELL_PAYLOAD_SIZE]; 184 int onionskin_len = 0; 185 int reply_len = 0; 186 onion_handshake_state_t handshake_state = {0}; 187 server_onion_keys_t server_keys = {0}; 188 curve25519_keypair_t relay_onion_key; 189 uint8_t serv_reply[CELL_PAYLOAD_SIZE]; 190 uint8_t serv_keys[100]; 191 uint8_t rend_nonce[DIGEST_LEN]; 192 uint8_t client_keys[CELL_PAYLOAD_SIZE]; 193 uint8_t rend_auth[DIGEST_LEN]; 194 195 info.supports_ntor_v3 = true; 196 info.exit_supports_congestion_control = 1; 197 198 unhex(relay_onion_key.seckey.secret_key, 199 "4051daa5921cfa2a1c27b08451324919538e79e788a81b38cbed097a5dff454a"); 200 unhex(relay_onion_key.pubkey.public_key, 201 "f8307a2bc1870b00b828bb74dbb8fd88e632a6375ab3bcd1ae706aaa8b6cdd1d"); 202 203 memcpy(&info.curve25519_onion_key, 204 &relay_onion_key.pubkey, sizeof(info.curve25519_onion_key)); 205 unhex(info.ed_identity.pubkey, 206 "9fad2af287ef942632833d21f946c6260c33fae6172b60006e86e4a6911753a2"); 207 208 memcpy(&server_keys.my_ed_identity, &info.ed_identity, 209 sizeof(server_keys.my_ed_identity)); 210 211 dimap_add_entry(&server_keys.curve25519_key_map, 212 relay_onion_key.pubkey.public_key, 213 &relay_onion_key); 214 215 onionskin_len = onion_skin_create(ONION_HANDSHAKE_TYPE_NTOR_V3, &info, 216 &handshake_state, onionskin, 217 sizeof(onionskin)); 218 tt_int_op(onionskin_len, OP_NE, -1); 219 220 server_keys.junk_keypair = &handshake_state.u.ntor3->client_keypair; 221 222 size_t serv_keylen = sizeof(serv_keys); 223 size_t client_keylen = sizeof(serv_keys); 224 reply_len = onion_skin_server_handshake(ONION_HANDSHAKE_TYPE_NTOR_V3, 225 onionskin, onionskin_len, 226 &server_keys, serv_params_in, 227 serv_reply, sizeof(serv_reply), 228 serv_keys, &serv_keylen, 229 rend_nonce, serv_params_out); 230 tt_int_op(reply_len, OP_NE, -1); 231 232 tt_int_op(onion_skin_client_handshake(ONION_HANDSHAKE_TYPE_NTOR_V3, 233 &handshake_state, 234 serv_reply, reply_len, 235 client_keys, &client_keylen, 236 rend_auth, client_params_out, 237 NULL), OP_EQ, 0); 238 239 done: 240 dimap_free(server_keys.curve25519_key_map, NULL); 241 ntor3_handshake_state_free(handshake_state.u.ntor3); 242 243 return; 244 } 245 246 /** 247 * Test congestion control negotiation logic. 248 * 249 * This tests that congestion control is only enabled when both 250 * client and server agree, via consensus param or torrc. 251 * 252 * It also tests that when they agree, they agree on the server's 253 * version of sendme_inc. 254 */ 255 static void 256 test_ntor3_handshake(void *arg) 257 { 258 (void)arg; 259 circuit_params_t client_params, serv_params, serv_ns_params; 260 261 serv_ns_params.sendme_inc_cells = congestion_control_sendme_inc(); 262 263 /* client off, serv off -> off */ 264 serv_ns_params.cc_enabled = 0; 265 run_full_handshake(&serv_ns_params, &client_params, &serv_params); 266 tt_int_op(client_params.cc_enabled, OP_EQ, 0); 267 tt_int_op(serv_params.cc_enabled, OP_EQ, 0); 268 269 /* client off, serv on -> off */ 270 congestion_control_set_cc_disabled(); 271 serv_ns_params.cc_enabled = 1; 272 run_full_handshake(&serv_ns_params, &client_params, &serv_params); 273 tt_int_op(client_params.cc_enabled, OP_EQ, 0); 274 tt_int_op(serv_params.cc_enabled, OP_EQ, 0); 275 276 /* client off + param, serv on -> on */ 277 serv_ns_params.cc_enabled = 1; 278 get_options_mutable()->AlwaysCongestionControl = 1; 279 run_full_handshake(&serv_ns_params, &client_params, &serv_params); 280 tt_int_op(client_params.cc_enabled, OP_EQ, 1); 281 tt_int_op(serv_params.cc_enabled, OP_EQ, 1); 282 283 /* client on, serv off -> off */ 284 serv_ns_params.cc_enabled = 0; 285 congestion_control_set_cc_enabled(); 286 run_full_handshake(&serv_ns_params, &client_params, &serv_params); 287 tt_int_op(client_params.cc_enabled, OP_EQ, 0); 288 tt_int_op(serv_params.cc_enabled, OP_EQ, 0); 289 290 /* client on, serv on -> on */ 291 serv_ns_params.cc_enabled = 1; 292 run_full_handshake(&serv_ns_params, &client_params, &serv_params); 293 tt_int_op(client_params.cc_enabled, OP_EQ, 1); 294 tt_int_op(serv_params.cc_enabled, OP_EQ, 1); 295 296 /* client on, serv on, sendme_inc diff -> serv sendme_inc */ 297 serv_ns_params.cc_enabled = 1; 298 serv_ns_params.sendme_inc_cells += 1; 299 run_full_handshake(&serv_ns_params, &client_params, &serv_params); 300 tt_int_op(client_params.cc_enabled, OP_EQ, 1); 301 tt_int_op(serv_params.cc_enabled, OP_EQ, 1); 302 tt_int_op(serv_params.sendme_inc_cells, OP_EQ, 303 client_params.sendme_inc_cells); 304 tt_int_op(client_params.sendme_inc_cells, OP_EQ, 305 serv_ns_params.sendme_inc_cells); 306 tt_int_op(client_params.sendme_inc_cells, OP_NE, 307 congestion_control_sendme_inc()); 308 309 done: 310 return; 311 } 312 313 struct testcase_t ntor_v3_tests[] = { 314 { "testvecs", test_ntor3_testvecs, 0, NULL, NULL, }, 315 { "handshake_negtotiation", test_ntor3_handshake, 0, NULL, NULL, }, 316 END_OF_TESTCASES, 317 };