hs_cell.c (48030B)
1 /* Copyright (c) 2017-2021, The Tor Project, Inc. */ 2 /* See LICENSE for licensing information */ 3 4 /** 5 * \file hs_cell.c 6 * \brief Hidden service API for cell creation and handling. 7 **/ 8 9 #include "core/or/or.h" 10 #include "app/config/config.h" 11 #include "lib/crypt_ops/crypto_util.h" 12 #include "feature/hs_common/replaycache.h" 13 14 #include "feature/hs/hs_cell.h" 15 #include "feature/hs/hs_ob.h" 16 #include "core/crypto/hs_ntor.h" 17 #include "core/or/congestion_control_common.h" 18 19 #include "core/or/origin_circuit_st.h" 20 21 /* Trunnel. */ 22 #include "trunnel/congestion_control.h" 23 #include "trunnel/ed25519_cert.h" 24 #include "trunnel/extension.h" 25 #include "trunnel/hs/cell_establish_intro.h" 26 #include "trunnel/hs/cell_introduce1.h" 27 #include "trunnel/hs/cell_rendezvous.h" 28 29 /** Compute the MAC of an INTRODUCE cell in mac_out. The encoded_cell param is 30 * the cell content up to the ENCRYPTED section of length encoded_cell_len. 31 * The encrypted param is the start of the ENCRYPTED section of length 32 * encrypted_len. The mac_key is the key needed for the computation of the MAC 33 * derived from the ntor handshake of length mac_key_len. 34 * 35 * The length mac_out_len must be at least DIGEST256_LEN. */ 36 static void 37 compute_introduce_mac(const uint8_t *encoded_cell, size_t encoded_cell_len, 38 const uint8_t *encrypted, size_t encrypted_len, 39 const uint8_t *mac_key, size_t mac_key_len, 40 uint8_t *mac_out, size_t mac_out_len) 41 { 42 size_t offset = 0; 43 size_t mac_msg_len; 44 uint8_t mac_msg[RELAY_PAYLOAD_SIZE_MAX] = {0}; 45 46 tor_assert(encoded_cell); 47 tor_assert(encrypted); 48 tor_assert(mac_key); 49 tor_assert(mac_out); 50 tor_assert(mac_out_len >= DIGEST256_LEN); 51 52 /* Compute the size of the message which is basically the entire cell until 53 * the MAC field of course. */ 54 mac_msg_len = encoded_cell_len + (encrypted_len - DIGEST256_LEN); 55 tor_assert(mac_msg_len <= sizeof(mac_msg)); 56 57 /* First, put the encoded cell in the msg. */ 58 memcpy(mac_msg, encoded_cell, encoded_cell_len); 59 offset += encoded_cell_len; 60 /* Second, put the CLIENT_PK + ENCRYPTED_DATA but omit the MAC field (which 61 * is junk at this point). */ 62 memcpy(mac_msg + offset, encrypted, (encrypted_len - DIGEST256_LEN)); 63 offset += (encrypted_len - DIGEST256_LEN); 64 tor_assert(offset == mac_msg_len); 65 66 crypto_mac_sha3_256(mac_out, mac_out_len, 67 mac_key, mac_key_len, 68 mac_msg, mac_msg_len); 69 memwipe(mac_msg, 0, sizeof(mac_msg)); 70 } 71 72 /** 73 * From a set of keys, a list of subcredentials, and the ENCRYPTED section of 74 * an INTRODUCE2 cell, return an array of newly allocated intro cell keys 75 * structures. Finally, the client public key is copied in client_pk. On 76 * error, return NULL. 77 **/ 78 static hs_ntor_intro_cell_keys_t * 79 get_introduce2_key_material(const ed25519_public_key_t *auth_key, 80 const curve25519_keypair_t *enc_key, 81 size_t n_subcredentials, 82 const hs_subcredential_t *subcredentials, 83 const uint8_t *encrypted_section, 84 curve25519_public_key_t *client_pk) 85 { 86 hs_ntor_intro_cell_keys_t *keys; 87 88 tor_assert(auth_key); 89 tor_assert(enc_key); 90 tor_assert(n_subcredentials > 0); 91 tor_assert(subcredentials); 92 tor_assert(encrypted_section); 93 tor_assert(client_pk); 94 95 keys = tor_calloc(n_subcredentials, sizeof(hs_ntor_intro_cell_keys_t)); 96 97 /* First bytes of the ENCRYPTED section are the client public key. */ 98 memcpy(client_pk->public_key, encrypted_section, CURVE25519_PUBKEY_LEN); 99 100 if (hs_ntor_service_get_introduce1_keys_multi(auth_key, enc_key, client_pk, 101 n_subcredentials, 102 subcredentials, keys) < 0) { 103 /* Don't rely on the caller to wipe this on error. */ 104 memwipe(client_pk, 0, sizeof(curve25519_public_key_t)); 105 tor_free(keys); 106 keys = NULL; 107 } 108 return keys; 109 } 110 111 /** Using the given encryption key, decrypt the encrypted_section of length 112 * encrypted_section_len of an INTRODUCE2 cell and return a newly allocated 113 * buffer containing the decrypted data. On decryption failure, NULL is 114 * returned. */ 115 static uint8_t * 116 decrypt_introduce2(const uint8_t *enc_key, const uint8_t *encrypted_section, 117 size_t encrypted_section_len) 118 { 119 uint8_t *decrypted = NULL; 120 crypto_cipher_t *cipher = NULL; 121 122 tor_assert(enc_key); 123 tor_assert(encrypted_section); 124 125 /* Decrypt ENCRYPTED section. */ 126 cipher = crypto_cipher_new_with_bits((char *) enc_key, 127 CURVE25519_PUBKEY_LEN * 8); 128 tor_assert(cipher); 129 130 /* This is symmetric encryption so can't be bigger than the encrypted 131 * section length. */ 132 decrypted = tor_malloc_zero(encrypted_section_len); 133 if (crypto_cipher_decrypt(cipher, (char *) decrypted, 134 (const char *) encrypted_section, 135 encrypted_section_len) < 0) { 136 tor_free(decrypted); 137 decrypted = NULL; 138 goto done; 139 } 140 141 done: 142 crypto_cipher_free(cipher); 143 return decrypted; 144 } 145 146 /** Given a pointer to the decrypted data of the ENCRYPTED section of an 147 * INTRODUCE2 cell of length decrypted_len, parse and validate the cell 148 * content. Return a newly allocated cell structure or NULL on error. The 149 * circuit and service object are only used for logging purposes. */ 150 static trn_cell_introduce_encrypted_t * 151 parse_introduce2_encrypted(const uint8_t *decrypted_data, 152 size_t decrypted_len, const origin_circuit_t *circ, 153 const hs_service_t *service) 154 { 155 trn_cell_introduce_encrypted_t *enc_cell = NULL; 156 157 tor_assert(decrypted_data); 158 tor_assert(circ); 159 tor_assert(service); 160 161 if (trn_cell_introduce_encrypted_parse(&enc_cell, decrypted_data, 162 decrypted_len) < 0) { 163 log_info(LD_REND, "Unable to parse the decrypted ENCRYPTED section of " 164 "the INTRODUCE2 cell on circuit %u for service %s", 165 TO_CIRCUIT(circ)->n_circ_id, 166 safe_str_client(service->onion_address)); 167 goto err; 168 } 169 170 if (trn_cell_introduce_encrypted_get_onion_key_type(enc_cell) != 171 TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR) { 172 log_info(LD_REND, "INTRODUCE2 onion key type is invalid. Got %u but " 173 "expected %u on circuit %u for service %s", 174 trn_cell_introduce_encrypted_get_onion_key_type(enc_cell), 175 TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR, 176 TO_CIRCUIT(circ)->n_circ_id, 177 safe_str_client(service->onion_address)); 178 goto err; 179 } 180 181 if (trn_cell_introduce_encrypted_getlen_onion_key(enc_cell) != 182 CURVE25519_PUBKEY_LEN) { 183 log_info(LD_REND, "INTRODUCE2 onion key length is invalid. Got %u but " 184 "expected %d on circuit %u for service %s", 185 (unsigned)trn_cell_introduce_encrypted_getlen_onion_key(enc_cell), 186 CURVE25519_PUBKEY_LEN, TO_CIRCUIT(circ)->n_circ_id, 187 safe_str_client(service->onion_address)); 188 goto err; 189 } 190 /* XXX: Validate NSPEC field as well. */ 191 192 return enc_cell; 193 err: 194 trn_cell_introduce_encrypted_free(enc_cell); 195 return NULL; 196 } 197 198 /** Parse an INTRODUCE2 cell from payload of size payload_len for the given 199 * service and circuit which are used only for logging purposes. The resulting 200 * parsed cell is put in cell_ptr_out. 201 * 202 * Return 0 on success else a negative value and cell_ptr_out is untouched. */ 203 static int 204 parse_introduce2_cell(const hs_service_t *service, 205 const origin_circuit_t *circ, const uint8_t *payload, 206 size_t payload_len, 207 trn_cell_introduce1_t **cell_ptr_out) 208 { 209 trn_cell_introduce1_t *cell = NULL; 210 211 tor_assert(service); 212 tor_assert(circ); 213 tor_assert(payload); 214 tor_assert(cell_ptr_out); 215 216 /* Parse the cell so we can start cell validation. */ 217 if (trn_cell_introduce1_parse(&cell, payload, payload_len) < 0) { 218 log_info(LD_PROTOCOL, "Unable to parse INTRODUCE2 cell on circuit %u " 219 "for service %s", 220 TO_CIRCUIT(circ)->n_circ_id, 221 safe_str_client(service->onion_address)); 222 goto err; 223 } 224 225 /* Success. */ 226 *cell_ptr_out = cell; 227 return 0; 228 err: 229 return -1; 230 } 231 232 /** Set the onion public key onion_pk in cell, the encrypted section of an 233 * INTRODUCE1 cell. */ 234 static void 235 introduce1_set_encrypted_onion_key(trn_cell_introduce_encrypted_t *cell, 236 const uint8_t *onion_pk) 237 { 238 tor_assert(cell); 239 tor_assert(onion_pk); 240 /* There is only one possible key type for a non legacy cell. */ 241 trn_cell_introduce_encrypted_set_onion_key_type(cell, 242 TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR); 243 trn_cell_introduce_encrypted_set_onion_key_len(cell, CURVE25519_PUBKEY_LEN); 244 trn_cell_introduce_encrypted_setlen_onion_key(cell, CURVE25519_PUBKEY_LEN); 245 memcpy(trn_cell_introduce_encrypted_getarray_onion_key(cell), onion_pk, 246 trn_cell_introduce_encrypted_getlen_onion_key(cell)); 247 } 248 249 /** Set the link specifiers in lspecs in cell, the encrypted section of an 250 * INTRODUCE1 cell. */ 251 static void 252 introduce1_set_encrypted_link_spec(trn_cell_introduce_encrypted_t *cell, 253 const smartlist_t *lspecs) 254 { 255 tor_assert(cell); 256 tor_assert(lspecs); 257 tor_assert(smartlist_len(lspecs) > 0); 258 tor_assert(smartlist_len(lspecs) <= UINT8_MAX); 259 260 uint8_t lspecs_num = (uint8_t) smartlist_len(lspecs); 261 trn_cell_introduce_encrypted_set_nspec(cell, lspecs_num); 262 /* We aren't duplicating the link specifiers object here which means that 263 * the ownership goes to the trn_cell_introduce_encrypted_t cell and those 264 * object will be freed when the cell is. */ 265 SMARTLIST_FOREACH(lspecs, link_specifier_t *, ls, 266 trn_cell_introduce_encrypted_add_nspecs(cell, ls)); 267 } 268 269 /** Set padding in the enc_cell only if needed that is the total length of both 270 * sections are below the minimum required for an INTRODUCE1 cell. */ 271 static void 272 introduce1_set_encrypted_padding(const trn_cell_introduce1_t *cell, 273 trn_cell_introduce_encrypted_t *enc_cell) 274 { 275 tor_assert(cell); 276 tor_assert(enc_cell); 277 /* This is the length we expect to have once encoded of the whole cell. */ 278 ssize_t full_len = trn_cell_introduce1_encoded_len(cell) + 279 trn_cell_introduce_encrypted_encoded_len(enc_cell); 280 tor_assert(full_len > 0); 281 if (full_len < HS_CELL_INTRODUCE1_MIN_SIZE) { 282 size_t padding = HS_CELL_INTRODUCE1_MIN_SIZE - full_len; 283 trn_cell_introduce_encrypted_setlen_pad(enc_cell, padding); 284 memset(trn_cell_introduce_encrypted_getarray_pad(enc_cell), 0, 285 trn_cell_introduce_encrypted_getlen_pad(enc_cell)); 286 } 287 } 288 289 /** Encrypt the ENCRYPTED payload and encode it in the cell using the enc_cell 290 * and the INTRODUCE1 data. 291 * 292 * This can't fail but it is very important that the caller sets every field 293 * in data so the computation of the INTRODUCE1 keys doesn't fail. */ 294 static void 295 introduce1_encrypt_and_encode(trn_cell_introduce1_t *cell, 296 const trn_cell_introduce_encrypted_t *enc_cell, 297 const hs_cell_introduce1_data_t *data) 298 { 299 size_t offset = 0; 300 ssize_t encrypted_len; 301 ssize_t encoded_cell_len, encoded_enc_cell_len; 302 uint8_t encoded_cell[RELAY_PAYLOAD_SIZE_MAX] = {0}; 303 uint8_t encoded_enc_cell[RELAY_PAYLOAD_SIZE_MAX] = {0}; 304 uint8_t *encrypted = NULL; 305 uint8_t mac[DIGEST256_LEN]; 306 crypto_cipher_t *cipher = NULL; 307 hs_ntor_intro_cell_keys_t keys; 308 309 tor_assert(cell); 310 tor_assert(enc_cell); 311 tor_assert(data); 312 313 /* Encode the cells up to now of what we have to we can perform the MAC 314 * computation on it. */ 315 encoded_cell_len = trn_cell_introduce1_encode(encoded_cell, 316 sizeof(encoded_cell), cell); 317 /* We have a much more serious issue if this isn't true. */ 318 tor_assert(encoded_cell_len > 0); 319 320 encoded_enc_cell_len = 321 trn_cell_introduce_encrypted_encode(encoded_enc_cell, 322 sizeof(encoded_enc_cell), enc_cell); 323 /* We have a much more serious issue if this isn't true. */ 324 tor_assert(encoded_enc_cell_len > 0); 325 326 /* Get the key material for the encryption. */ 327 if (hs_ntor_client_get_introduce1_keys(data->auth_pk, data->enc_pk, 328 data->client_kp, 329 data->subcredential, &keys) < 0) { 330 tor_assert_unreached(); 331 } 332 333 /* Prepare cipher with the encryption key just computed. */ 334 cipher = crypto_cipher_new_with_bits((const char *) keys.enc_key, 335 sizeof(keys.enc_key) * 8); 336 tor_assert(cipher); 337 338 /* Compute the length of the ENCRYPTED section which is the CLIENT_PK, 339 * ENCRYPTED_DATA and MAC length. */ 340 encrypted_len = sizeof(data->client_kp->pubkey) + encoded_enc_cell_len + 341 sizeof(mac); 342 tor_assert(encrypted_len < RELAY_PAYLOAD_SIZE_MAX); 343 encrypted = tor_malloc_zero(encrypted_len); 344 345 /* Put the CLIENT_PK first. */ 346 memcpy(encrypted, data->client_kp->pubkey.public_key, 347 sizeof(data->client_kp->pubkey.public_key)); 348 offset += sizeof(data->client_kp->pubkey.public_key); 349 /* Then encrypt and set the ENCRYPTED_DATA. This can't fail. */ 350 crypto_cipher_encrypt(cipher, (char *) encrypted + offset, 351 (const char *) encoded_enc_cell, encoded_enc_cell_len); 352 crypto_cipher_free(cipher); 353 offset += encoded_enc_cell_len; 354 /* Compute MAC from the above and put it in the buffer. This function will 355 * make the adjustment to the encrypted_len to omit the MAC length. */ 356 compute_introduce_mac(encoded_cell, encoded_cell_len, 357 encrypted, encrypted_len, 358 keys.mac_key, sizeof(keys.mac_key), 359 mac, sizeof(mac)); 360 memcpy(encrypted + offset, mac, sizeof(mac)); 361 offset += sizeof(mac); 362 tor_assert(offset == (size_t) encrypted_len); 363 364 /* Set the ENCRYPTED section in the cell. */ 365 trn_cell_introduce1_setlen_encrypted(cell, encrypted_len); 366 memcpy(trn_cell_introduce1_getarray_encrypted(cell), 367 encrypted, encrypted_len); 368 369 /* Cleanup. */ 370 memwipe(&keys, 0, sizeof(keys)); 371 memwipe(mac, 0, sizeof(mac)); 372 memwipe(encrypted, 0, sizeof(encrypted_len)); 373 memwipe(encoded_enc_cell, 0, sizeof(encoded_enc_cell)); 374 tor_free(encrypted); 375 } 376 377 /** Build the PoW cell extension and put it in the given extensions object. 378 * Return 0 on success, -1 on failure. */ 379 static int 380 build_introduce_pow_extension(const hs_pow_solution_t *pow_solution, 381 trn_extension_t *extensions) 382 { 383 ssize_t ret; 384 size_t pow_ext_encoded_len; 385 uint8_t *field_array; 386 trn_extension_field_t *field = NULL; 387 trn_cell_extension_pow_t *pow_ext = NULL; 388 389 tor_assert(pow_solution); 390 tor_assert(extensions); 391 392 /* We are creating a cell extension field of type PoW solution. */ 393 field = trn_extension_field_new(); 394 trn_extension_field_set_field_type(field, TRUNNEL_EXT_TYPE_POW); 395 396 /* Build PoW extension field. */ 397 pow_ext = trn_cell_extension_pow_new(); 398 399 /* Copy PoW solution values into PoW extension cell. */ 400 401 /* Equi-X base scheme */ 402 trn_cell_extension_pow_set_pow_version(pow_ext, TRUNNEL_POW_VERSION_EQUIX); 403 404 memcpy(trn_cell_extension_pow_getarray_pow_nonce(pow_ext), 405 &pow_solution->nonce, TRUNNEL_POW_NONCE_LEN); 406 407 trn_cell_extension_pow_set_pow_effort(pow_ext, pow_solution->effort); 408 409 memcpy(trn_cell_extension_pow_getarray_pow_seed(pow_ext), 410 pow_solution->seed_head, TRUNNEL_POW_SEED_HEAD_LEN); 411 memcpy(trn_cell_extension_pow_getarray_pow_solution(pow_ext), 412 pow_solution->equix_solution, TRUNNEL_POW_SOLUTION_LEN); 413 414 /* Set the field with the encoded PoW extension. */ 415 ret = trn_cell_extension_pow_encoded_len(pow_ext); 416 if (BUG(ret <= 0)) { 417 goto err; 418 } 419 pow_ext_encoded_len = ret; 420 421 /* Set length field and the field array size length. */ 422 trn_extension_field_set_field_len(field, pow_ext_encoded_len); 423 trn_extension_field_setlen_field(field, pow_ext_encoded_len); 424 /* Encode the PoW extension into the cell extension field. */ 425 field_array = trn_extension_field_getarray_field(field); 426 ret = trn_cell_extension_pow_encode(field_array, 427 trn_extension_field_getlen_field(field), pow_ext); 428 if (BUG(ret <= 0)) { 429 goto err; 430 } 431 tor_assert(ret == (ssize_t)pow_ext_encoded_len); 432 433 /* Finally, encode field into the cell extension. */ 434 trn_extension_add_fields(extensions, field); 435 436 /* We've just add an extension field to the cell extensions so increment the 437 * total number. */ 438 trn_extension_set_num(extensions, trn_extension_get_num(extensions) + 1); 439 440 /* Cleanup. PoW extension has been encoded at this point. */ 441 trn_cell_extension_pow_free(pow_ext); 442 443 return 0; 444 445 err: 446 trn_extension_field_free(field); 447 trn_cell_extension_pow_free(pow_ext); 448 return -1; 449 } 450 451 /** Build and set the INTRODUCE congestion control extension in the given 452 * extensions. */ 453 static void 454 build_introduce_cc_extension(trn_extension_t *extensions) 455 { 456 trn_extension_field_t *field = NULL; 457 458 /* Build CC request extension. */ 459 field = trn_extension_field_new(); 460 trn_extension_field_set_field_type(field, 461 TRUNNEL_EXT_TYPE_CC_REQUEST); 462 463 /* No payload indicating a request to use congestion control. */ 464 trn_extension_field_set_field_len(field, 0); 465 466 /* Build final extension. */ 467 trn_extension_add_fields(extensions, field); 468 trn_extension_set_num(extensions, trn_extension_get_num(extensions) + 1); 469 } 470 471 /** Using the INTRODUCE1 data, setup the ENCRYPTED section in cell. This means 472 * set it, encrypt it and encode it. */ 473 static void 474 introduce1_set_encrypted(trn_cell_introduce1_t *cell, 475 const hs_cell_introduce1_data_t *data) 476 { 477 trn_cell_introduce_encrypted_t *enc_cell; 478 trn_extension_t *ext; 479 480 tor_assert(cell); 481 tor_assert(data); 482 483 enc_cell = trn_cell_introduce_encrypted_new(); 484 tor_assert(enc_cell); 485 486 /* Setup extension(s) if any. */ 487 ext = trn_extension_new(); 488 tor_assert(ext); 489 /* Build congestion control extension if enabled. */ 490 if (data->cc_enabled) { 491 build_introduce_cc_extension(ext); 492 } 493 /* Build PoW extension if present. */ 494 if (data->pow_solution) { 495 build_introduce_pow_extension(data->pow_solution, ext); 496 } 497 trn_cell_introduce_encrypted_set_extensions(enc_cell, ext); 498 499 /* Set the rendezvous cookie. */ 500 memcpy(trn_cell_introduce_encrypted_getarray_rend_cookie(enc_cell), 501 data->rendezvous_cookie, REND_COOKIE_LEN); 502 503 /* Set the onion public key. */ 504 introduce1_set_encrypted_onion_key(enc_cell, data->onion_pk->public_key); 505 506 /* Set the link specifiers. */ 507 introduce1_set_encrypted_link_spec(enc_cell, data->link_specifiers); 508 509 /* Set padding. */ 510 introduce1_set_encrypted_padding(cell, enc_cell); 511 512 /* Encrypt and encode it in the cell. */ 513 introduce1_encrypt_and_encode(cell, enc_cell, data); 514 515 /* Cleanup. */ 516 trn_cell_introduce_encrypted_free(enc_cell); 517 } 518 519 /** Set the authentication key in the INTRODUCE1 cell from the given data. */ 520 static void 521 introduce1_set_auth_key(trn_cell_introduce1_t *cell, 522 const hs_cell_introduce1_data_t *data) 523 { 524 tor_assert(cell); 525 tor_assert(data); 526 /* There is only one possible type for a non legacy cell. */ 527 trn_cell_introduce1_set_auth_key_type(cell, 528 TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519); 529 trn_cell_introduce1_set_auth_key_len(cell, ED25519_PUBKEY_LEN); 530 trn_cell_introduce1_setlen_auth_key(cell, ED25519_PUBKEY_LEN); 531 memcpy(trn_cell_introduce1_getarray_auth_key(cell), 532 data->auth_pk->pubkey, trn_cell_introduce1_getlen_auth_key(cell)); 533 } 534 535 /** Build and add to the given DoS cell extension the given parameter type and 536 * value. */ 537 static void 538 build_establish_intro_dos_param(trn_cell_extension_dos_t *dos_ext, 539 uint8_t param_type, uint64_t param_value) 540 { 541 trn_cell_extension_dos_param_t *dos_param = 542 trn_cell_extension_dos_param_new(); 543 544 /* Extra safety. We should never send an unknown parameter type. */ 545 tor_assert(param_type == TRUNNEL_DOS_PARAM_TYPE_INTRO2_RATE_PER_SEC || 546 param_type == TRUNNEL_DOS_PARAM_TYPE_INTRO2_BURST_PER_SEC); 547 548 trn_cell_extension_dos_param_set_type(dos_param, param_type); 549 trn_cell_extension_dos_param_set_value(dos_param, param_value); 550 trn_cell_extension_dos_add_params(dos_ext, dos_param); 551 552 /* Not freeing the trunnel object because it is now owned by dos_ext. */ 553 } 554 555 /** Build the DoS defense cell extension and put it in the given extensions 556 * object. Return 0 on success, -1 on failure. (Right now, failure is only 557 * possible if there is a bug.) */ 558 static int 559 build_establish_intro_dos_extension(const hs_service_config_t *service_config, 560 trn_extension_t *extensions) 561 { 562 ssize_t ret; 563 size_t dos_ext_encoded_len; 564 uint8_t *field_array; 565 trn_extension_field_t *field = NULL; 566 trn_cell_extension_dos_t *dos_ext = NULL; 567 568 tor_assert(service_config); 569 tor_assert(extensions); 570 571 /* We are creating a cell extension field of the type DoS. */ 572 field = trn_extension_field_new(); 573 trn_extension_field_set_field_type(field, 574 TRUNNEL_CELL_EXTENSION_TYPE_DOS); 575 576 /* Build DoS extension field. We will put in two parameters. */ 577 dos_ext = trn_cell_extension_dos_new(); 578 trn_cell_extension_dos_set_n_params(dos_ext, 2); 579 580 /* Build DoS parameter INTRO2 rate per second. */ 581 build_establish_intro_dos_param(dos_ext, 582 TRUNNEL_DOS_PARAM_TYPE_INTRO2_RATE_PER_SEC, 583 service_config->intro_dos_rate_per_sec); 584 /* Build DoS parameter INTRO2 burst per second. */ 585 build_establish_intro_dos_param(dos_ext, 586 TRUNNEL_DOS_PARAM_TYPE_INTRO2_BURST_PER_SEC, 587 service_config->intro_dos_burst_per_sec); 588 589 /* Set the field with the encoded DoS extension. */ 590 ret = trn_cell_extension_dos_encoded_len(dos_ext); 591 if (BUG(ret <= 0)) { 592 goto err; 593 } 594 dos_ext_encoded_len = ret; 595 /* Set length field and the field array size length. */ 596 trn_extension_field_set_field_len(field, dos_ext_encoded_len); 597 trn_extension_field_setlen_field(field, dos_ext_encoded_len); 598 /* Encode the DoS extension into the cell extension field. */ 599 field_array = trn_extension_field_getarray_field(field); 600 ret = trn_cell_extension_dos_encode(field_array, 601 trn_extension_field_getlen_field(field), dos_ext); 602 if (BUG(ret <= 0)) { 603 goto err; 604 } 605 tor_assert(ret == (ssize_t) dos_ext_encoded_len); 606 607 /* Finally, encode field into the cell extension. */ 608 trn_extension_add_fields(extensions, field); 609 610 /* We've just add an extension field to the cell extensions so increment the 611 * total number. */ 612 trn_extension_set_num(extensions, trn_extension_get_num(extensions) + 1); 613 614 /* Cleanup. DoS extension has been encoded at this point. */ 615 trn_cell_extension_dos_free(dos_ext); 616 617 return 0; 618 619 err: 620 trn_extension_field_free(field); 621 trn_cell_extension_dos_free(dos_ext); 622 return -1; 623 } 624 625 /* ========== */ 626 /* Public API */ 627 /* ========== */ 628 629 /** Allocate and build all the ESTABLISH_INTRO cell extension. The given 630 * extensions pointer is always set to a valid cell extension object. */ 631 STATIC trn_extension_t * 632 build_establish_intro_extensions(const hs_service_config_t *service_config, 633 const hs_service_intro_point_t *ip) 634 { 635 int ret; 636 trn_extension_t *extensions; 637 638 tor_assert(service_config); 639 tor_assert(ip); 640 641 extensions = trn_extension_new(); 642 trn_extension_set_num(extensions, 0); 643 644 /* If the defense has been enabled service side (by the operator with a 645 * torrc option) and the intro point does support it. */ 646 if (service_config->has_dos_defense_enabled && 647 ip->support_intro2_dos_defense) { 648 /* This function takes care to increment the number of extensions. */ 649 ret = build_establish_intro_dos_extension(service_config, extensions); 650 if (ret < 0) { 651 /* Return no extensions on error. */ 652 goto end; 653 } 654 } 655 656 end: 657 return extensions; 658 } 659 660 /** Build an ESTABLISH_INTRO cell with the given circuit nonce and intro point 661 * object. The encoded cell is put in cell_out that MUST at least be of the 662 * size of RELAY_PAYLOAD_SIZE. Return the encoded cell length on success else 663 * a negative value and cell_out is untouched. */ 664 ssize_t 665 hs_cell_build_establish_intro(const char *circ_nonce, 666 const hs_service_config_t *service_config, 667 const hs_service_intro_point_t *ip, 668 uint8_t *cell_out) 669 { 670 ssize_t cell_len = -1; 671 uint16_t sig_len = ED25519_SIG_LEN; 672 trn_cell_establish_intro_t *cell = NULL; 673 trn_extension_t *extensions; 674 675 tor_assert(circ_nonce); 676 tor_assert(service_config); 677 tor_assert(ip); 678 679 /* Build the extensions, if any. */ 680 extensions = build_establish_intro_extensions(service_config, ip); 681 682 /* Set extension data. None used here. */ 683 cell = trn_cell_establish_intro_new(); 684 trn_cell_establish_intro_set_extensions(cell, extensions); 685 /* Set signature size. Array is then allocated in the cell. We need to do 686 * this early so we can use trunnel API to get the signature length. */ 687 trn_cell_establish_intro_set_sig_len(cell, sig_len); 688 trn_cell_establish_intro_setlen_sig(cell, sig_len); 689 690 /* Set AUTH_KEY_TYPE: 2 means ed25519 */ 691 trn_cell_establish_intro_set_auth_key_type(cell, 692 TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519); 693 694 /* Set AUTH_KEY and AUTH_KEY_LEN field. Must also set byte-length of 695 * AUTH_KEY to match */ 696 { 697 uint16_t auth_key_len = ED25519_PUBKEY_LEN; 698 trn_cell_establish_intro_set_auth_key_len(cell, auth_key_len); 699 trn_cell_establish_intro_setlen_auth_key(cell, auth_key_len); 700 /* We do this call _after_ setting the length because it's reallocated at 701 * that point only. */ 702 uint8_t *auth_key_ptr = trn_cell_establish_intro_getarray_auth_key(cell); 703 memcpy(auth_key_ptr, ip->auth_key_kp.pubkey.pubkey, auth_key_len); 704 } 705 706 /* Calculate HANDSHAKE_AUTH field (MAC). */ 707 { 708 ssize_t tmp_cell_enc_len = 0; 709 ssize_t tmp_cell_mac_offset = 710 sig_len + sizeof(cell->sig_len) + 711 trn_cell_establish_intro_getlen_handshake_mac(cell); 712 uint8_t tmp_cell_enc[RELAY_PAYLOAD_SIZE_MAX] = {0}; 713 uint8_t mac[TRUNNEL_SHA3_256_LEN], *handshake_ptr; 714 715 /* We first encode the current fields we have in the cell so we can 716 * compute the MAC using the raw bytes. */ 717 tmp_cell_enc_len = trn_cell_establish_intro_encode(tmp_cell_enc, 718 sizeof(tmp_cell_enc), 719 cell); 720 if (BUG(tmp_cell_enc_len < 0)) { 721 goto done; 722 } 723 /* Sanity check. */ 724 tor_assert(tmp_cell_enc_len > tmp_cell_mac_offset); 725 726 /* Circuit nonce is always DIGEST_LEN according to tor-spec.txt. */ 727 crypto_mac_sha3_256(mac, sizeof(mac), 728 (uint8_t *) circ_nonce, DIGEST_LEN, 729 tmp_cell_enc, tmp_cell_enc_len - tmp_cell_mac_offset); 730 handshake_ptr = trn_cell_establish_intro_getarray_handshake_mac(cell); 731 memcpy(handshake_ptr, mac, sizeof(mac)); 732 733 memwipe(mac, 0, sizeof(mac)); 734 memwipe(tmp_cell_enc, 0, sizeof(tmp_cell_enc)); 735 } 736 737 /* Calculate the cell signature SIG. */ 738 { 739 ssize_t tmp_cell_enc_len = 0; 740 ssize_t tmp_cell_sig_offset = (sig_len + sizeof(cell->sig_len)); 741 uint8_t tmp_cell_enc[RELAY_PAYLOAD_SIZE_MAX] = {0}, *sig_ptr; 742 ed25519_signature_t sig; 743 744 /* We first encode the current fields we have in the cell so we can 745 * compute the signature from the raw bytes of the cell. */ 746 tmp_cell_enc_len = trn_cell_establish_intro_encode(tmp_cell_enc, 747 sizeof(tmp_cell_enc), 748 cell); 749 if (BUG(tmp_cell_enc_len < 0)) { 750 goto done; 751 } 752 753 if (ed25519_sign_prefixed(&sig, tmp_cell_enc, 754 tmp_cell_enc_len - tmp_cell_sig_offset, 755 ESTABLISH_INTRO_SIG_PREFIX, &ip->auth_key_kp)) { 756 log_warn(LD_BUG, "Unable to make signature for ESTABLISH_INTRO cell."); 757 goto done; 758 } 759 /* Copy the signature into the cell. */ 760 sig_ptr = trn_cell_establish_intro_getarray_sig(cell); 761 memcpy(sig_ptr, sig.sig, sig_len); 762 763 memwipe(tmp_cell_enc, 0, sizeof(tmp_cell_enc)); 764 } 765 766 /* Encode the cell. Can't be bigger than a standard cell. */ 767 cell_len = trn_cell_establish_intro_encode(cell_out, 768 RELAY_PAYLOAD_SIZE_MAX, 769 cell); 770 771 done: 772 trn_cell_establish_intro_free(cell); 773 return cell_len; 774 } 775 776 /** Parse the INTRO_ESTABLISHED cell in the payload of size payload_len. If we 777 * are successful at parsing it, return the length of the parsed cell else a 778 * negative value on error. */ 779 ssize_t 780 hs_cell_parse_intro_established(const uint8_t *payload, size_t payload_len) 781 { 782 ssize_t ret; 783 trn_cell_intro_established_t *cell = NULL; 784 785 tor_assert(payload); 786 787 /* Try to parse the payload into a cell making sure we do actually have a 788 * valid cell. */ 789 ret = trn_cell_intro_established_parse(&cell, payload, payload_len); 790 if (ret >= 0) { 791 /* On success, we do not keep the cell, we just notify the caller that it 792 * was successfully parsed. */ 793 trn_cell_intro_established_free(cell); 794 } 795 return ret; 796 } 797 798 /** Parse the cell PoW solution extension. Return 0 on success and data 799 * structure is updated with the PoW effort. Return -1 on any kind of error 800 * including if PoW couldn't be verified. */ 801 static int 802 handle_introduce2_encrypted_cell_pow_extension(const hs_service_t *service, 803 const hs_service_intro_point_t *ip, 804 const trn_extension_field_t *field, 805 hs_cell_introduce2_data_t *data) 806 { 807 int ret = -1; 808 trn_cell_extension_pow_t *pow = NULL; 809 hs_pow_solution_t sol; 810 811 tor_assert(field); 812 tor_assert(ip); 813 814 if (!service->state.pow_state) { 815 log_info(LD_REND, "Unsolicited PoW solution in INTRODUCE2 request."); 816 goto end; 817 } 818 819 if (trn_cell_extension_pow_parse(&pow, 820 trn_extension_field_getconstarray_field(field), 821 trn_extension_field_getlen_field(field)) < 0) { 822 goto end; 823 } 824 825 /* There is only one version supported at the moment so validate we at least 826 * have that. */ 827 if (trn_cell_extension_pow_get_pow_version(pow) != 828 TRUNNEL_POW_VERSION_EQUIX) { 829 log_debug(LD_REND, "Unsupported PoW version. Malformed INTRODUCE2"); 830 goto end; 831 } 832 833 /* Effort E */ 834 sol.effort = trn_cell_extension_pow_get_pow_effort(pow); 835 /* Seed C */ 836 memcpy(sol.seed_head, trn_cell_extension_pow_getconstarray_pow_seed(pow), 837 HS_POW_SEED_HEAD_LEN); 838 /* Nonce N */ 839 memcpy(sol.nonce, trn_cell_extension_pow_getconstarray_pow_nonce(pow), 840 HS_POW_NONCE_LEN); 841 /* Solution S */ 842 memcpy(sol.equix_solution, 843 trn_cell_extension_pow_getconstarray_pow_solution(pow), 844 HS_POW_EQX_SOL_LEN); 845 846 if (hs_pow_verify(&ip->blinded_id, service->state.pow_state, &sol)) { 847 log_info(LD_REND, "PoW INTRODUCE2 request failed to verify."); 848 goto end; 849 } 850 851 log_info(LD_REND, "PoW INTRODUCE2 request successfully verified."); 852 data->rdv_data.pow_effort = sol.effort; 853 854 /* Successfully parsed and verified the PoW solution */ 855 ret = 0; 856 857 end: 858 trn_cell_extension_pow_free(pow); 859 return ret; 860 } 861 862 /** For the encrypted INTRO2 cell in <b>encrypted_section</b>, use the crypto 863 * material in <b>data</b> to compute the right ntor keys. Also validate the 864 * INTRO2 MAC to ensure that the keys are the right ones. 865 * 866 * Return NULL on failure to either produce the key material or on MAC 867 * validation. Else return a newly allocated intro keys object. */ 868 static hs_ntor_intro_cell_keys_t * 869 get_introduce2_keys_and_verify_mac(hs_cell_introduce2_data_t *data, 870 const uint8_t *encrypted_section, 871 size_t encrypted_section_len) 872 { 873 hs_ntor_intro_cell_keys_t *intro_keys = NULL; 874 hs_ntor_intro_cell_keys_t *intro_keys_result = NULL; 875 876 /* Build the key material out of the key material found in the cell. */ 877 intro_keys = get_introduce2_key_material(data->auth_pk, data->enc_kp, 878 data->n_subcredentials, 879 data->subcredentials, 880 encrypted_section, 881 &data->rdv_data.client_pk); 882 if (intro_keys == NULL) { 883 log_info(LD_REND, "Invalid INTRODUCE2 encrypted data. Unable to " 884 "compute key material"); 885 return NULL; 886 } 887 888 /* Make sure we are not about to underflow. */ 889 if (BUG(encrypted_section_len < DIGEST256_LEN)) { 890 return NULL; 891 } 892 893 /* Validate MAC from the cell and our computed key material. The MAC field 894 * in the cell is at the end of the encrypted section. */ 895 intro_keys_result = tor_malloc_zero(sizeof(*intro_keys_result)); 896 for (unsigned i = 0; i < data->n_subcredentials; ++i) { 897 uint8_t mac[DIGEST256_LEN]; 898 899 /* The MAC field is at the very end of the ENCRYPTED section. */ 900 size_t mac_offset = encrypted_section_len - sizeof(mac); 901 /* Compute the MAC. Use the entire encoded payload with a length up to the 902 * ENCRYPTED section. */ 903 compute_introduce_mac(data->payload, 904 data->payload_len - encrypted_section_len, 905 encrypted_section, encrypted_section_len, 906 intro_keys[i].mac_key, 907 sizeof(intro_keys[i].mac_key), 908 mac, sizeof(mac)); 909 /* Time-invariant conditional copy: if the MAC is what we expected, then 910 * set intro_keys_result to intro_keys[i]. Otherwise, don't: but don't 911 * leak which one it was! */ 912 bool equal = tor_memeq(mac, encrypted_section + mac_offset, sizeof(mac)); 913 memcpy_if_true_timei(equal, intro_keys_result, &intro_keys[i], 914 sizeof(*intro_keys_result)); 915 } 916 917 /* We no longer need intro_keys. */ 918 memwipe(intro_keys, 0, 919 sizeof(hs_ntor_intro_cell_keys_t) * data->n_subcredentials); 920 tor_free(intro_keys); 921 922 if (safe_mem_is_zero(intro_keys_result, sizeof(*intro_keys_result))) { 923 log_info(LD_REND, "Invalid MAC validation for INTRODUCE2 cell"); 924 tor_free(intro_keys_result); /* sets intro_keys_result to NULL */ 925 } 926 927 return intro_keys_result; 928 } 929 930 /** Parse the given INTRODUCE cell extension. Update the data object 931 * accordingly depending on the extension. Return 0 if it validated 932 * correctly, or return -1 if it is malformed (for example because it 933 * includes a PoW that doesn't verify). */ 934 static int 935 parse_introduce_cell_extension(const hs_service_t *service, 936 const hs_service_intro_point_t *ip, 937 hs_cell_introduce2_data_t *data, 938 const trn_extension_field_t *field) 939 { 940 int ret = 0; 941 trn_extension_field_cc_t *cc_field = NULL; 942 943 tor_assert(data); 944 tor_assert(field); 945 946 switch (trn_extension_field_get_field_type(field)) { 947 case TRUNNEL_EXT_TYPE_CC_REQUEST: 948 /* CC requests, enable it. */ 949 data->rdv_data.cc_enabled = 1; 950 data->pv.protocols_known = 1; 951 data->pv.supports_congestion_control = data->rdv_data.cc_enabled; 952 break; 953 case TRUNNEL_EXT_TYPE_POW: 954 /* PoW request. If successful, the effort is put in the data. */ 955 if (handle_introduce2_encrypted_cell_pow_extension(service, ip, 956 field, data) < 0) { 957 log_fn(LOG_PROTOCOL_WARN, LD_REND, "Invalid PoW cell extension."); 958 ret = -1; 959 } 960 break; 961 default: 962 break; 963 } 964 965 trn_extension_field_cc_free(cc_field); 966 return ret; 967 } 968 969 /** Parse the INTRODUCE2 cell using data which contains everything we need to 970 * do so and contains the destination buffers of information we extract and 971 * compute from the cell. Return 0 on success else a negative value. The 972 * service and circ are only used for logging purposes. */ 973 ssize_t 974 hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data, 975 const origin_circuit_t *circ, 976 const hs_service_t *service, 977 const hs_service_intro_point_t *ip) 978 { 979 int ret = -1; 980 time_t elapsed; 981 uint8_t *decrypted = NULL; 982 size_t encrypted_section_len; 983 const uint8_t *encrypted_section; 984 trn_cell_introduce1_t *cell = NULL; 985 trn_cell_introduce_encrypted_t *enc_cell = NULL; 986 hs_ntor_intro_cell_keys_t *intro_keys = NULL; 987 988 tor_assert(data); 989 tor_assert(circ); 990 tor_assert(service); 991 992 /* Parse the cell into a decoded data structure pointed by cell_ptr. */ 993 if (parse_introduce2_cell(service, circ, data->payload, data->payload_len, 994 &cell) < 0) { 995 goto done; 996 } 997 998 log_info(LD_REND, "Received a decodable INTRODUCE2 cell on circuit %u " 999 "for service %s. Decoding encrypted section...", 1000 TO_CIRCUIT(circ)->n_circ_id, 1001 safe_str_client(service->onion_address)); 1002 1003 encrypted_section = trn_cell_introduce1_getconstarray_encrypted(cell); 1004 encrypted_section_len = trn_cell_introduce1_getlen_encrypted(cell); 1005 1006 /* Encrypted section must at least contain the CLIENT_PK and MAC which is 1007 * defined in section 3.3.2 of the specification. */ 1008 if (encrypted_section_len < (CURVE25519_PUBKEY_LEN + DIGEST256_LEN)) { 1009 log_info(LD_REND, "Invalid INTRODUCE2 encrypted section length " 1010 "for service %s. Dropping cell.", 1011 safe_str_client(service->onion_address)); 1012 goto done; 1013 } 1014 1015 /* Check our replay cache for this introduction point. */ 1016 if (replaycache_add_test_and_elapsed(data->replay_cache, encrypted_section, 1017 encrypted_section_len, &elapsed)) { 1018 log_warn(LD_REND, "Possible replay detected! An INTRODUCE2 cell with the " 1019 "same ENCRYPTED section was seen %ld seconds ago. " 1020 "Dropping cell.", (long int) elapsed); 1021 goto done; 1022 } 1023 1024 /* First bytes of the ENCRYPTED section are the client public key (they are 1025 * guaranteed to exist because of the length check above). We are gonna use 1026 * the client public key to compute the ntor keys and decrypt the payload: 1027 */ 1028 memcpy(&data->rdv_data.client_pk.public_key, encrypted_section, 1029 CURVE25519_PUBKEY_LEN); 1030 1031 /* Get the right INTRODUCE2 ntor keys and verify the cell MAC */ 1032 intro_keys = get_introduce2_keys_and_verify_mac(data, encrypted_section, 1033 encrypted_section_len); 1034 if (!intro_keys) { 1035 log_warn(LD_REND, "Could not get valid INTRO2 keys on circuit %u " 1036 "for service %s", TO_CIRCUIT(circ)->n_circ_id, 1037 safe_str_client(service->onion_address)); 1038 goto done; 1039 } 1040 1041 { 1042 /* The ENCRYPTED_DATA section starts just after the CLIENT_PK. */ 1043 const uint8_t *encrypted_data = 1044 encrypted_section + sizeof(data->rdv_data.client_pk); 1045 /* It's symmetric encryption so it's correct to use the ENCRYPTED length 1046 * for decryption. Computes the length of ENCRYPTED_DATA meaning removing 1047 * the CLIENT_PK and MAC length. */ 1048 size_t encrypted_data_len = 1049 encrypted_section_len - 1050 (sizeof(data->rdv_data.client_pk) + DIGEST256_LEN); 1051 1052 /* This decrypts the ENCRYPTED_DATA section of the cell. */ 1053 decrypted = decrypt_introduce2(intro_keys->enc_key, 1054 encrypted_data, encrypted_data_len); 1055 if (decrypted == NULL) { 1056 log_info(LD_REND, "Unable to decrypt the ENCRYPTED section of an " 1057 "INTRODUCE2 cell on circuit %u for service %s", 1058 TO_CIRCUIT(circ)->n_circ_id, 1059 safe_str_client(service->onion_address)); 1060 goto done; 1061 } 1062 1063 /* Parse this blob into an encrypted cell structure so we can then extract 1064 * the data we need out of it. */ 1065 enc_cell = parse_introduce2_encrypted(decrypted, encrypted_data_len, 1066 circ, service); 1067 memwipe(decrypted, 0, encrypted_data_len); 1068 if (enc_cell == NULL) { 1069 goto done; 1070 } 1071 } 1072 1073 /* XXX: Implement client authorization checks. */ 1074 1075 /* Extract onion key and rendezvous cookie from the cell used for the 1076 * rendezvous point circuit e2e encryption. */ 1077 memcpy(data->rdv_data.onion_pk.public_key, 1078 trn_cell_introduce_encrypted_getconstarray_onion_key(enc_cell), 1079 CURVE25519_PUBKEY_LEN); 1080 memcpy(data->rdv_data.rendezvous_cookie, 1081 trn_cell_introduce_encrypted_getconstarray_rend_cookie(enc_cell), 1082 sizeof(data->rdv_data.rendezvous_cookie)); 1083 1084 /* Extract rendezvous link specifiers. */ 1085 for (size_t idx = 0; 1086 idx < trn_cell_introduce_encrypted_get_nspec(enc_cell); idx++) { 1087 link_specifier_t *lspec = 1088 trn_cell_introduce_encrypted_get_nspecs(enc_cell, idx); 1089 if (BUG(!lspec)) { 1090 goto done; 1091 } 1092 link_specifier_t *lspec_dup = link_specifier_dup(lspec); 1093 if (BUG(!lspec_dup)) { 1094 goto done; 1095 } 1096 smartlist_add(data->rdv_data.link_specifiers, lspec_dup); 1097 } 1098 1099 /* Extract any extensions. */ 1100 const trn_extension_t *extensions = 1101 trn_cell_introduce_encrypted_get_extensions(enc_cell); 1102 if (extensions != NULL) { 1103 for (size_t idx = 0; idx < trn_extension_get_num(extensions); idx++) { 1104 const trn_extension_field_t *field = 1105 trn_extension_getconst_fields(extensions, idx); 1106 if (BUG(field == NULL)) { 1107 /* The number of extensions should match the number of fields. */ 1108 break; 1109 } 1110 if (parse_introduce_cell_extension(service, ip, data, field) < 0) { 1111 goto done; 1112 } 1113 } 1114 } 1115 1116 /* If the client asked for congestion control, but we don't support it, 1117 * that's a failure. It should not have asked, based on our descriptor. */ 1118 if (data->rdv_data.cc_enabled && !congestion_control_enabled()) { 1119 goto done; 1120 } 1121 1122 /* Success. */ 1123 ret = 0; 1124 log_info(LD_REND, 1125 "Valid INTRODUCE2 cell. Willing to launch rendezvous circuit."); 1126 1127 done: 1128 if (intro_keys) { 1129 memwipe(intro_keys, 0, sizeof(hs_ntor_intro_cell_keys_t)); 1130 tor_free(intro_keys); 1131 } 1132 tor_free(decrypted); 1133 trn_cell_introduce_encrypted_free(enc_cell); 1134 trn_cell_introduce1_free(cell); 1135 return ret; 1136 } 1137 1138 /** Build a RENDEZVOUS1 cell with the given rendezvous cookie and handshake 1139 * info. The encoded cell is put in cell_out and the length of the data is 1140 * returned. This can't fail. */ 1141 ssize_t 1142 hs_cell_build_rendezvous1(const uint8_t *rendezvous_cookie, 1143 size_t rendezvous_cookie_len, 1144 const uint8_t *rendezvous_handshake_info, 1145 size_t rendezvous_handshake_info_len, 1146 uint8_t *cell_out) 1147 { 1148 ssize_t cell_len; 1149 trn_cell_rendezvous1_t *cell; 1150 1151 tor_assert(rendezvous_cookie); 1152 tor_assert(rendezvous_handshake_info); 1153 tor_assert(cell_out); 1154 1155 cell = trn_cell_rendezvous1_new(); 1156 /* Set the RENDEZVOUS_COOKIE. */ 1157 memcpy(trn_cell_rendezvous1_getarray_rendezvous_cookie(cell), 1158 rendezvous_cookie, rendezvous_cookie_len); 1159 /* Set the HANDSHAKE_INFO. */ 1160 trn_cell_rendezvous1_setlen_handshake_info(cell, 1161 rendezvous_handshake_info_len); 1162 memcpy(trn_cell_rendezvous1_getarray_handshake_info(cell), 1163 rendezvous_handshake_info, rendezvous_handshake_info_len); 1164 /* Encoding. */ 1165 cell_len = trn_cell_rendezvous1_encode(cell_out, 1166 RELAY_PAYLOAD_SIZE_MAX, cell); 1167 tor_assert(cell_len > 0); 1168 1169 trn_cell_rendezvous1_free(cell); 1170 return cell_len; 1171 } 1172 1173 /** Build an INTRODUCE1 cell from the given data. The encoded cell is put in 1174 * cell_out which must be of at least size RELAY_PAYLOAD_SIZE. On success, the 1175 * encoded length is returned else a negative value and the content of 1176 * cell_out should be ignored. */ 1177 ssize_t 1178 hs_cell_build_introduce1(const hs_cell_introduce1_data_t *data, 1179 uint8_t *cell_out) 1180 { 1181 ssize_t cell_len; 1182 trn_cell_introduce1_t *cell; 1183 trn_extension_t *ext; 1184 1185 tor_assert(data); 1186 tor_assert(cell_out); 1187 1188 cell = trn_cell_introduce1_new(); 1189 tor_assert(cell); 1190 1191 /* Set extension data. None are used. */ 1192 ext = trn_extension_new(); 1193 tor_assert(ext); 1194 trn_extension_set_num(ext, 0); 1195 trn_cell_introduce1_set_extensions(cell, ext); 1196 1197 /* Set the authentication key. */ 1198 introduce1_set_auth_key(cell, data); 1199 1200 /* Set the encrypted section. This will set, encrypt and encode the 1201 * ENCRYPTED section in the cell. After this, we'll be ready to encode. */ 1202 introduce1_set_encrypted(cell, data); 1203 1204 /* Final encoding. */ 1205 cell_len = trn_cell_introduce1_encode(cell_out, 1206 RELAY_PAYLOAD_SIZE_MAX, cell); 1207 1208 trn_cell_introduce1_free(cell); 1209 return cell_len; 1210 } 1211 1212 /** Build an ESTABLISH_RENDEZVOUS cell from the given rendezvous_cookie. The 1213 * encoded cell is put in cell_out which must be of at least 1214 * RELAY_PAYLOAD_SIZE. On success, the encoded length is returned and the 1215 * caller should clear up the content of the cell. 1216 * 1217 * This function can't fail. */ 1218 ssize_t 1219 hs_cell_build_establish_rendezvous(const uint8_t *rendezvous_cookie, 1220 uint8_t *cell_out) 1221 { 1222 tor_assert(rendezvous_cookie); 1223 tor_assert(cell_out); 1224 1225 memcpy(cell_out, rendezvous_cookie, HS_REND_COOKIE_LEN); 1226 return HS_REND_COOKIE_LEN; 1227 } 1228 1229 /** Handle an INTRODUCE_ACK cell encoded in payload of length payload_len. 1230 * Return the status code on success else a negative value if the cell as not 1231 * decodable. */ 1232 int 1233 hs_cell_parse_introduce_ack(const uint8_t *payload, size_t payload_len) 1234 { 1235 int ret = -1; 1236 trn_cell_introduce_ack_t *cell = NULL; 1237 1238 tor_assert(payload); 1239 1240 if (trn_cell_introduce_ack_parse(&cell, payload, payload_len) < 0) { 1241 log_info(LD_REND, "Invalid INTRODUCE_ACK cell. Unable to parse it."); 1242 goto end; 1243 } 1244 1245 ret = trn_cell_introduce_ack_get_status(cell); 1246 1247 end: 1248 trn_cell_introduce_ack_free(cell); 1249 return ret; 1250 } 1251 1252 /** Handle a RENDEZVOUS2 cell encoded in payload of length payload_len. On 1253 * success, handshake_info contains the data in the HANDSHAKE_INFO field, and 1254 * 0 is returned. On error, a negative value is returned. */ 1255 int 1256 hs_cell_parse_rendezvous2(const uint8_t *payload, size_t payload_len, 1257 uint8_t *handshake_info, size_t handshake_info_len) 1258 { 1259 int ret = -1; 1260 trn_cell_rendezvous2_t *cell = NULL; 1261 1262 tor_assert(payload); 1263 tor_assert(handshake_info); 1264 1265 if (trn_cell_rendezvous2_parse(&cell, payload, payload_len) < 0) { 1266 log_info(LD_REND, "Invalid RENDEZVOUS2 cell. Unable to parse it."); 1267 goto end; 1268 } 1269 1270 /* Static size, we should never have an issue with this else we messed up 1271 * our code flow. */ 1272 tor_assert(trn_cell_rendezvous2_getlen_handshake_info(cell) == 1273 handshake_info_len); 1274 memcpy(handshake_info, 1275 trn_cell_rendezvous2_getconstarray_handshake_info(cell), 1276 handshake_info_len); 1277 ret = 0; 1278 1279 end: 1280 trn_cell_rendezvous2_free(cell); 1281 return ret; 1282 } 1283 1284 /** Clear the given INTRODUCE1 data structure data. */ 1285 void 1286 hs_cell_introduce1_data_clear(hs_cell_introduce1_data_t *data) 1287 { 1288 if (data == NULL) { 1289 return; 1290 } 1291 /* Object in this list have been moved to the cell object when building it 1292 * so they've been freed earlier. We do that in order to avoid duplicating 1293 * them leading to more memory and CPU time being used for nothing. */ 1294 smartlist_free(data->link_specifiers); 1295 /* The data object has no ownership of any members. */ 1296 memwipe(data, 0, sizeof(hs_cell_introduce1_data_t)); 1297 }