LCOV - code coverage report
Current view: top level - core/or - onion.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 324 336 96.4 %
Date: 2021-11-24 03:28:48 Functions: 20 20 100.0 %

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

Generated by: LCOV version 1.14