onion.c (20843B)
1 /* Copyright (c) 2001 Matej Pfajfar. 2 * Copyright (c) 2001-2004, Roger Dingledine. 3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. 4 * Copyright (c) 2007-2021, The Tor Project, Inc. */ 5 /* See LICENSE for licensing information */ 6 7 /** 8 * \file onion.c 9 * \brief Functions to queue create cells, 10 * and parse and create the CREATE cell and its allies. 11 * 12 * This module has a few functions, all related to the CREATE/CREATED 13 * handshake that we use on links in order to create a circuit, and the 14 * related EXTEND/EXTENDED handshake that we use over circuits in order to 15 * extend them an additional hop. 16 * 17 * Clients invoke these functions when creating or extending a circuit, 18 * from circuitbuild.c. 19 * 20 * Relays invoke these functions when they receive a CREATE or EXTEND 21 * cell in command.c or relay.c, in order to queue the pending request. 22 * They also invoke them from cpuworker.c, which handles dispatching 23 * onionskin requests to different worker threads. 24 * 25 * <br> 26 * 27 * This module also handles: 28 * <ul> 29 * <li> Queueing incoming onionskins on the relay side before passing 30 * them to worker threads. 31 * <li>Expiring onionskins on the relay side if they have waited for 32 * too long. 33 * <li>Packaging private keys on the server side in order to pass 34 * them to worker threads. 35 * <li>Encoding and decoding CREATE, CREATED, CREATE2, and CREATED2 cells. 36 * <li>Encoding and decodign EXTEND, EXTENDED, EXTEND2, and EXTENDED2 37 * relay cells. 38 * </ul> 39 **/ 40 41 #include "core/or/or.h" 42 43 #include "app/config/config.h" 44 #include "core/crypto/onion_crypto.h" 45 #include "core/crypto/onion_fast.h" 46 #include "core/crypto/onion_ntor.h" 47 #include "core/or/onion.h" 48 #include "feature/nodelist/networkstatus.h" 49 50 #include "core/or/cell_st.h" 51 52 // trunnel 53 #include "trunnel/ed25519_cert.h" 54 55 /** Helper: return 0 if <b>cell</b> appears valid, -1 otherwise. If 56 * <b>unknown_ok</b> is true, allow cells with handshake types we don't 57 * recognize. */ 58 static int 59 check_create_cell(const create_cell_t *cell, int unknown_ok) 60 { 61 switch (cell->cell_type) { 62 case CELL_CREATE: 63 return -1; 64 case CELL_CREATE_FAST: 65 if (cell->handshake_type != ONION_HANDSHAKE_TYPE_FAST) 66 return -1; 67 break; 68 case CELL_CREATE2: 69 break; 70 default: 71 return -1; 72 } 73 74 switch (cell->handshake_type) { 75 case ONION_HANDSHAKE_TYPE_TAP: 76 return -1; 77 case ONION_HANDSHAKE_TYPE_FAST: 78 if (cell->handshake_len != CREATE_FAST_LEN) 79 return -1; 80 break; 81 case ONION_HANDSHAKE_TYPE_NTOR: 82 if (cell->handshake_len != NTOR_ONIONSKIN_LEN) 83 return -1; 84 break; 85 case ONION_HANDSHAKE_TYPE_NTOR_V3: 86 /* ntor v3 has variable length fields that are checked 87 * elsewhere. Fall through to always valid here. */ 88 break; 89 default: 90 if (! unknown_ok) 91 return -1; 92 } 93 94 return 0; 95 } 96 97 /** Write the various parameters into the create cell. Separate from 98 * create_cell_parse() to make unit testing easier. 99 */ 100 void 101 create_cell_init(create_cell_t *cell_out, uint8_t cell_type, 102 uint16_t handshake_type, uint16_t handshake_len, 103 const uint8_t *onionskin) 104 { 105 memset(cell_out, 0, sizeof(*cell_out)); 106 107 cell_out->cell_type = cell_type; 108 cell_out->handshake_type = handshake_type; 109 cell_out->handshake_len = handshake_len; 110 memcpy(cell_out->onionskin, onionskin, handshake_len); 111 } 112 113 /** Helper: parse the CREATE2 payload at <b>p</b>, which could be up to 114 * <b>p_len</b> bytes long, and use it to fill the fields of 115 * <b>cell_out</b>. Return 0 on success and -1 on failure. 116 * 117 * Note that part of the body of an EXTEND2 cell is a CREATE2 payload, so 118 * this function is also used for parsing those. 119 */ 120 static int 121 parse_create2_payload(create_cell_t *cell_out, const uint8_t *p, size_t p_len) 122 { 123 uint16_t handshake_type, handshake_len; 124 125 if (p_len < 4) 126 return -1; 127 128 handshake_type = ntohs(get_uint16(p)); 129 handshake_len = ntohs(get_uint16(p+2)); 130 131 if (handshake_len > MAX_CREATE_LEN || handshake_len > p_len - 4) 132 return -1; 133 if (handshake_type == ONION_HANDSHAKE_TYPE_FAST) 134 return -1; 135 136 create_cell_init(cell_out, CELL_CREATE2, handshake_type, handshake_len, 137 p+4); 138 return 0; 139 } 140 141 /** Magic string which, in a CREATE or EXTEND cell, indicates that a seeming 142 * TAP payload is really an ntor payload. We'd do away with this if every 143 * relay supported EXTEND2, but we want to be able to extend from A to B with 144 * ntor even when A doesn't understand EXTEND2 and so can't generate a 145 * CREATE2 cell. 146 **/ 147 #define NTOR_CREATE_MAGIC "ntorNTORntorNTOR" 148 149 /** Parse a CREATE, CREATE_FAST, or CREATE2 cell from <b>cell_in</b> into 150 * <b>cell_out</b>. Return 0 on success, -1 on failure. (We reject some 151 * syntactically valid CREATE2 cells that we can't generate or react to.) */ 152 int 153 create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in) 154 { 155 switch (cell_in->command) { 156 case CELL_CREATE: 157 return -1; 158 case CELL_CREATE_FAST: 159 create_cell_init(cell_out, CELL_CREATE_FAST, ONION_HANDSHAKE_TYPE_FAST, 160 CREATE_FAST_LEN, cell_in->payload); 161 break; 162 case CELL_CREATE2: 163 if (parse_create2_payload(cell_out, cell_in->payload, 164 CELL_PAYLOAD_SIZE) < 0) 165 return -1; 166 break; 167 default: 168 return -1; 169 } 170 171 return check_create_cell(cell_out, 0); 172 } 173 174 /** Helper: return 0 if <b>cell</b> appears valid, -1 otherwise. */ 175 static int 176 check_created_cell(const created_cell_t *cell) 177 { 178 switch (cell->cell_type) { 179 case CELL_CREATED: 180 return -1; 181 case CELL_CREATED_FAST: 182 if (cell->handshake_len != CREATED_FAST_LEN) 183 return -1; 184 break; 185 case CELL_CREATED2: 186 if (cell->handshake_len > MAX_CREATED_LEN) 187 return -1; 188 break; 189 } 190 191 return 0; 192 } 193 194 /** Parse a CREATED, CREATED_FAST, or CREATED2 cell from <b>cell_in</b> into 195 * <b>cell_out</b>. Return 0 on success, -1 on failure. */ 196 int 197 created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in) 198 { 199 memset(cell_out, 0, sizeof(*cell_out)); 200 201 switch (cell_in->command) { 202 case CELL_CREATED: 203 return -1; 204 case CELL_CREATED_FAST: 205 cell_out->cell_type = CELL_CREATED_FAST; 206 cell_out->handshake_len = CREATED_FAST_LEN; 207 memcpy(cell_out->reply, cell_in->payload, CREATED_FAST_LEN); 208 break; 209 case CELL_CREATED2: 210 { 211 const uint8_t *p = cell_in->payload; 212 cell_out->cell_type = CELL_CREATED2; 213 cell_out->handshake_len = ntohs(get_uint16(p)); 214 if (cell_out->handshake_len > MAX_CREATED_LEN) 215 return -1; 216 memcpy(cell_out->reply, p+2, cell_out->handshake_len); 217 break; 218 } 219 } 220 221 return check_created_cell(cell_out); 222 } 223 224 /** Helper: return 0 if <b>cell</b> appears valid, -1 otherwise. */ 225 static int 226 check_extend_cell(const extend_cell_t *cell) 227 { 228 const bool is_extend2 = (cell->cell_type == RELAY_COMMAND_EXTEND2); 229 230 if (tor_digest_is_zero((const char*)cell->node_id)) 231 return -1; 232 if (!tor_addr_port_is_valid_ap(&cell->orport_ipv4, 0)) { 233 /* EXTEND cells must have an IPv4 address. */ 234 if (!is_extend2) { 235 return -1; 236 } 237 /* EXTEND2 cells must have at least one IP address. 238 * It can be IPv4 or IPv6. */ 239 if (!tor_addr_port_is_valid_ap(&cell->orport_ipv6, 0)) { 240 return -1; 241 } 242 } 243 if (cell->create_cell.cell_type == CELL_CREATE) { 244 return -1; 245 } else if (cell->create_cell.cell_type == CELL_CREATE2) { 246 if (cell->cell_type != RELAY_COMMAND_EXTEND2) 247 return -1; 248 } else { 249 /* In particular, no CREATE_FAST cells are allowed */ 250 return -1; 251 } 252 if (cell->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_FAST || 253 cell->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_TAP) 254 return -1; 255 256 return check_create_cell(&cell->create_cell, 1); 257 } 258 259 static int 260 create_cell_from_create2_cell_body(create_cell_t *cell_out, 261 const create2_cell_body_t *cell) 262 { 263 tor_assert(cell_out); 264 tor_assert(cell); 265 memset(cell_out, 0, sizeof(create_cell_t)); 266 if (BUG(cell->handshake_len > sizeof(cell_out->onionskin))) { 267 /* This should be impossible because there just isn't enough room in the 268 * input cell to make the handshake_len this large and provide a 269 * handshake_data to match. */ 270 return -1; 271 } 272 273 cell_out->cell_type = CELL_CREATE2; 274 cell_out->handshake_type = cell->handshake_type; 275 cell_out->handshake_len = cell->handshake_len; 276 memcpy(cell_out->onionskin, 277 create2_cell_body_getconstarray_handshake_data(cell), 278 cell->handshake_len); 279 return 0; 280 } 281 282 static int 283 extend_cell_from_extend2_cell_body(extend_cell_t *cell_out, 284 const extend2_cell_body_t *cell) 285 { 286 tor_assert(cell_out); 287 tor_assert(cell); 288 int found_ipv4 = 0, found_ipv6 = 0, found_rsa_id = 0, found_ed_id = 0; 289 memset(cell_out, 0, sizeof(*cell_out)); 290 tor_addr_make_unspec(&cell_out->orport_ipv4.addr); 291 tor_addr_make_unspec(&cell_out->orport_ipv6.addr); 292 cell_out->cell_type = RELAY_COMMAND_EXTEND2; 293 294 unsigned i; 295 for (i = 0; i < cell->n_spec; ++i) { 296 const link_specifier_t *ls = extend2_cell_body_getconst_ls(cell, i); 297 switch (ls->ls_type) { 298 case LS_IPV4: 299 if (found_ipv4) 300 continue; 301 found_ipv4 = 1; 302 tor_addr_from_ipv4h(&cell_out->orport_ipv4.addr, ls->un_ipv4_addr); 303 cell_out->orport_ipv4.port = ls->un_ipv4_port; 304 break; 305 case LS_IPV6: 306 if (found_ipv6) 307 continue; 308 found_ipv6 = 1; 309 tor_addr_from_ipv6_bytes(&cell_out->orport_ipv6.addr, 310 ls->un_ipv6_addr); 311 cell_out->orport_ipv6.port = ls->un_ipv6_port; 312 break; 313 case LS_LEGACY_ID: 314 if (found_rsa_id) 315 return -1; 316 found_rsa_id = 1; 317 memcpy(cell_out->node_id, ls->un_legacy_id, 20); 318 break; 319 case LS_ED25519_ID: 320 if (found_ed_id) 321 return -1; 322 found_ed_id = 1; 323 memcpy(cell_out->ed_pubkey.pubkey, ls->un_ed25519_id, 32); 324 break; 325 default: 326 /* Ignore this, whatever it is. */ 327 break; 328 } 329 } 330 331 /* EXTEND2 cells must have an RSA ID */ 332 if (!found_rsa_id) 333 return -1; 334 335 /* EXTEND2 cells must have at least one IP address */ 336 if (!found_ipv4 && !found_ipv6) 337 return -1; 338 339 return create_cell_from_create2_cell_body(&cell_out->create_cell, 340 cell->create2); 341 } 342 343 /** Parse an EXTEND or EXTEND2 cell (according to <b>command</b>) from the 344 * <b>payload_length</b> bytes of <b>payload</b> into <b>cell_out</b>. Return 345 * 0 on success, -1 on failure. */ 346 MOCK_IMPL(int, 347 extend_cell_parse,(extend_cell_t *cell_out, 348 const uint8_t command, 349 const uint8_t *payload, 350 size_t payload_length)) 351 { 352 353 tor_assert(cell_out); 354 tor_assert(payload); 355 356 if (payload_length > RELAY_PAYLOAD_SIZE_MAX) 357 return -1; 358 359 switch (command) { 360 case RELAY_COMMAND_EXTEND: 361 return -1; 362 break; 363 case RELAY_COMMAND_EXTEND2: 364 { 365 extend2_cell_body_t *cell = NULL; 366 if (extend2_cell_body_parse(&cell, payload, payload_length) < 0 || 367 cell == NULL) { 368 if (cell) 369 extend2_cell_body_free(cell); 370 return -1; 371 } 372 int r = extend_cell_from_extend2_cell_body(cell_out, cell); 373 extend2_cell_body_free(cell); 374 if (r < 0) 375 return r; 376 } 377 break; 378 default: 379 return -1; 380 } 381 382 return check_extend_cell(cell_out); 383 } 384 385 /** Helper: return 0 if <b>cell</b> appears valid, -1 otherwise. */ 386 static int 387 check_extended_cell(const extended_cell_t *cell) 388 { 389 tor_assert(cell); 390 if (cell->created_cell.cell_type == CELL_CREATED) { 391 if (cell->cell_type != RELAY_COMMAND_EXTENDED) 392 return -1; 393 } else if (cell->created_cell.cell_type == CELL_CREATED2) { 394 if (cell->cell_type != RELAY_COMMAND_EXTENDED2) 395 return -1; 396 } else { 397 return -1; 398 } 399 400 return check_created_cell(&cell->created_cell); 401 } 402 403 /** Parse an EXTENDED or EXTENDED2 cell (according to <b>command</b>) from the 404 * <b>payload_len</b> bytes of <b>payload</b> into <b>cell_out</b>. Return 405 * 0 on success, -1 on failure. */ 406 int 407 extended_cell_parse(extended_cell_t *cell_out, 408 const uint8_t command, const uint8_t *payload, 409 size_t payload_len) 410 { 411 tor_assert(cell_out); 412 tor_assert(payload); 413 414 memset(cell_out, 0, sizeof(*cell_out)); 415 if (payload_len > RELAY_PAYLOAD_SIZE_MAX) 416 return -1; 417 418 switch (command) { 419 case RELAY_COMMAND_EXTENDED: 420 return -1; 421 case RELAY_COMMAND_EXTENDED2: 422 { 423 if (payload_len < 2) { 424 // Prevent underflow below. 425 return -1; 426 } 427 cell_out->cell_type = RELAY_COMMAND_EXTENDED2; 428 cell_out->created_cell.cell_type = CELL_CREATED2; 429 cell_out->created_cell.handshake_len = ntohs(get_uint16(payload)); 430 if (cell_out->created_cell.handshake_len > RELAY_PAYLOAD_SIZE_MAX - 2 || 431 cell_out->created_cell.handshake_len > payload_len - 2) 432 return -1; 433 memcpy(cell_out->created_cell.reply, payload+2, 434 cell_out->created_cell.handshake_len); 435 } 436 break; 437 default: 438 return -1; 439 } 440 441 return check_extended_cell(cell_out); 442 } 443 444 /** Fill <b>cell_out</b> with a correctly formatted version of the 445 * CREATE{,_FAST,2} cell in <b>cell_in</b>. Return 0 on success, -1 on 446 * failure. This is a cell we didn't originate if <b>relayed</b> is true. */ 447 static int 448 create_cell_format_impl(cell_t *cell_out, const create_cell_t *cell_in, 449 int relayed) 450 { 451 uint8_t *p; 452 size_t space; 453 if (check_create_cell(cell_in, relayed) < 0) 454 return -1; 455 456 memset(cell_out->payload, 0, sizeof(cell_out->payload)); 457 cell_out->command = cell_in->cell_type; 458 459 p = cell_out->payload; 460 space = sizeof(cell_out->payload); 461 462 switch (cell_in->cell_type) { 463 case CELL_CREATE: 464 if (BUG(cell_in->handshake_type == ONION_HANDSHAKE_TYPE_NTOR_V3)) { 465 log_warn(LD_BUG, "Create cells cannot contain ntorv3."); 466 return -1; 467 } 468 469 if (cell_in->handshake_type == ONION_HANDSHAKE_TYPE_NTOR) { 470 memcpy(p, NTOR_CREATE_MAGIC, 16); 471 p += 16; 472 space -= 16; 473 } 474 FALLTHROUGH; 475 case CELL_CREATE_FAST: 476 tor_assert(cell_in->handshake_len <= space); 477 memcpy(p, cell_in->onionskin, cell_in->handshake_len); 478 break; 479 case CELL_CREATE2: 480 tor_assert(cell_in->handshake_len <= sizeof(cell_out->payload)-4); 481 set_uint16(cell_out->payload, htons(cell_in->handshake_type)); 482 set_uint16(cell_out->payload+2, htons(cell_in->handshake_len)); 483 memcpy(cell_out->payload + 4, cell_in->onionskin, cell_in->handshake_len); 484 break; 485 default: 486 return -1; 487 } 488 489 return 0; 490 } 491 492 int 493 create_cell_format(cell_t *cell_out, const create_cell_t *cell_in) 494 { 495 return create_cell_format_impl(cell_out, cell_in, 0); 496 } 497 498 int 499 create_cell_format_relayed(cell_t *cell_out, const create_cell_t *cell_in) 500 { 501 return create_cell_format_impl(cell_out, cell_in, 1); 502 } 503 504 /** Fill <b>cell_out</b> with a correctly formatted version of the 505 * CREATED{,_FAST,2} cell in <b>cell_in</b>. Return 0 on success, -1 on 506 * failure. */ 507 int 508 created_cell_format(cell_t *cell_out, const created_cell_t *cell_in) 509 { 510 if (check_created_cell(cell_in) < 0) 511 return -1; 512 513 memset(cell_out->payload, 0, sizeof(cell_out->payload)); 514 cell_out->command = cell_in->cell_type; 515 516 switch (cell_in->cell_type) { 517 case CELL_CREATED: 518 case CELL_CREATED_FAST: 519 tor_assert(cell_in->handshake_len <= sizeof(cell_out->payload)); 520 memcpy(cell_out->payload, cell_in->reply, cell_in->handshake_len); 521 break; 522 case CELL_CREATED2: 523 tor_assert(cell_in->handshake_len <= sizeof(cell_out->payload)-2); 524 set_uint16(cell_out->payload, htons(cell_in->handshake_len)); 525 memcpy(cell_out->payload + 2, cell_in->reply, cell_in->handshake_len); 526 break; 527 default: 528 return -1; 529 } 530 return 0; 531 } 532 533 /** Return true iff we are configured (by torrc or by the networkstatus 534 * parameters) to use Ed25519 identities in our Extend2 cells. */ 535 static int 536 should_include_ed25519_id_extend_cells(const networkstatus_t *ns, 537 const or_options_t *options) 538 { 539 if (options->ExtendByEd25519ID != -1) 540 return options->ExtendByEd25519ID; /* The user has an opinion. */ 541 542 return (int) networkstatus_get_param(ns, "ExtendByEd25519ID", 543 0 /* default */, 544 0 /* min */, 545 1 /*max*/); 546 } 547 548 /** Format the EXTEND{,2} cell in <b>cell_in</b>, storing its relay payload in 549 * <b>payload_out</b>, the number of bytes used in *<b>len_out</b>, and the 550 * relay command in *<b>command_out</b>. The <b>payload_out</b> must have 551 * RELAY_PAYLOAD_SIZE_MAX bytes available. 552 * 553 * Return 0 on success, -1 on failure. */ 554 int 555 extend_cell_format(uint8_t *command_out, uint16_t *len_out, 556 uint8_t *payload_out, const extend_cell_t *cell_in) 557 { 558 uint8_t *p; 559 if (check_extend_cell(cell_in) < 0) 560 return -1; 561 562 p = payload_out; 563 564 memset(p, 0, RELAY_PAYLOAD_SIZE_MAX); 565 566 switch (cell_in->cell_type) { 567 case RELAY_COMMAND_EXTEND: 568 return -1; 569 case RELAY_COMMAND_EXTEND2: 570 { 571 uint8_t n_specifiers = 1; 572 *command_out = RELAY_COMMAND_EXTEND2; 573 extend2_cell_body_t *cell = extend2_cell_body_new(); 574 link_specifier_t *ls; 575 if (tor_addr_port_is_valid_ap(&cell_in->orport_ipv4, 0)) { 576 /* Maybe IPv4 specifier first. */ 577 ++n_specifiers; 578 ls = link_specifier_new(); 579 extend2_cell_body_add_ls(cell, ls); 580 ls->ls_type = LS_IPV4; 581 ls->ls_len = 6; 582 ls->un_ipv4_addr = tor_addr_to_ipv4h(&cell_in->orport_ipv4.addr); 583 ls->un_ipv4_port = cell_in->orport_ipv4.port; 584 } 585 { 586 /* Then RSA id */ 587 ls = link_specifier_new(); 588 extend2_cell_body_add_ls(cell, ls); 589 ls->ls_type = LS_LEGACY_ID; 590 ls->ls_len = DIGEST_LEN; 591 memcpy(ls->un_legacy_id, cell_in->node_id, DIGEST_LEN); 592 } 593 if (should_include_ed25519_id_extend_cells(NULL, get_options()) && 594 !ed25519_public_key_is_zero(&cell_in->ed_pubkey)) { 595 /* Then, maybe, the ed25519 id! */ 596 ++n_specifiers; 597 ls = link_specifier_new(); 598 extend2_cell_body_add_ls(cell, ls); 599 ls->ls_type = LS_ED25519_ID; 600 ls->ls_len = 32; 601 memcpy(ls->un_ed25519_id, cell_in->ed_pubkey.pubkey, 32); 602 } 603 if (tor_addr_port_is_valid_ap(&cell_in->orport_ipv6, 0)) { 604 /* Then maybe IPv6 specifier. */ 605 ++n_specifiers; 606 ls = link_specifier_new(); 607 extend2_cell_body_add_ls(cell, ls); 608 ls->ls_type = LS_IPV6; 609 ls->ls_len = 18; 610 tor_addr_copy_ipv6_bytes(ls->un_ipv6_addr, 611 &cell_in->orport_ipv6.addr); 612 ls->un_ipv6_port = cell_in->orport_ipv6.port; 613 } 614 cell->n_spec = n_specifiers; 615 616 /* Now, the handshake */ 617 cell->create2 = create2_cell_body_new(); 618 cell->create2->handshake_type = cell_in->create_cell.handshake_type; 619 cell->create2->handshake_len = cell_in->create_cell.handshake_len; 620 create2_cell_body_setlen_handshake_data(cell->create2, 621 cell_in->create_cell.handshake_len); 622 memcpy(create2_cell_body_getarray_handshake_data(cell->create2), 623 cell_in->create_cell.onionskin, 624 cell_in->create_cell.handshake_len); 625 626 ssize_t len_encoded = extend2_cell_body_encode( 627 payload_out, RELAY_PAYLOAD_SIZE_MAX, 628 cell); 629 extend2_cell_body_free(cell); 630 if (len_encoded < 0 || len_encoded > UINT16_MAX) 631 return -1; 632 *len_out = (uint16_t) len_encoded; 633 } 634 break; 635 default: 636 return -1; 637 } 638 639 return 0; 640 } 641 642 /** Format the EXTENDED{,2} cell in <b>cell_in</b>, storing its relay payload 643 * in <b>payload_out</b>, the number of bytes used in *<b>len_out</b>, and the 644 * relay command in *<b>command_out</b>. The <b>payload_out</b> must have 645 * RELAY_PAYLOAD_SIZE_MAX bytes available. 646 * 647 * Return 0 on success, -1 on failure. */ 648 int 649 extended_cell_format(uint8_t *command_out, uint16_t *len_out, 650 uint8_t *payload_out, const extended_cell_t *cell_in) 651 { 652 uint8_t *p; 653 if (check_extended_cell(cell_in) < 0) 654 return -1; 655 656 p = payload_out; 657 memset(p, 0, RELAY_PAYLOAD_SIZE_MAX); 658 659 switch (cell_in->cell_type) { 660 case RELAY_COMMAND_EXTENDED: 661 return -1; 662 case RELAY_COMMAND_EXTENDED2: 663 { 664 *command_out = RELAY_COMMAND_EXTENDED2; 665 *len_out = 2 + cell_in->created_cell.handshake_len; 666 set_uint16(payload_out, htons(cell_in->created_cell.handshake_len)); 667 if (cell_in->created_cell.handshake_len > MAX_CREATED_LEN) 668 return -1; 669 memcpy(payload_out+2, cell_in->created_cell.reply, 670 cell_in->created_cell.handshake_len); 671 } 672 break; 673 default: 674 return -1; 675 } 676 677 return 0; 678 }