LCOV - code coverage report
Current view: top level - core/or - crypt_path.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 63 88 71.6 %
Date: 2021-11-24 03:28:48 Functions: 11 13 84.6 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2019-2021, The Tor Project, Inc. */
       3             : /* See LICENSE for licensing information */
       4             : 
       5             : /**
       6             :  * \file crypt_path.c
       7             :  *
       8             :  * \brief Functions dealing with layered circuit encryption. This file aims to
       9             :  *   provide an API around the crypt_path_t structure which holds crypto
      10             :  *   information about a specific hop of a circuit.
      11             :  *
      12             :  * TODO: We should eventually move all functions dealing and manipulating
      13             :  *   crypt_path_t to this file, so that eventually we encapsulate more and more
      14             :  *   of crypt_path_t. Here are some more functions that can be moved here with
      15             :  *   some more effort:
      16             :  *
      17             :  *   - circuit_list_path_impl()
      18             :  **/
      19             : 
      20             : #define CRYPT_PATH_PRIVATE
      21             : 
      22             : #include "core/or/or.h"
      23             : #include "core/or/crypt_path.h"
      24             : 
      25             : #include "core/crypto/relay_crypto.h"
      26             : #include "core/crypto/onion_crypto.h"
      27             : #include "core/or/circuitbuild.h"
      28             : #include "core/or/circuitlist.h"
      29             : #include "core/or/extendinfo.h"
      30             : 
      31             : #include "lib/crypt_ops/crypto_dh.h"
      32             : #include "lib/crypt_ops/crypto_util.h"
      33             : 
      34             : #include "core/or/crypt_path_st.h"
      35             : #include "core/or/cell_st.h"
      36             : 
      37             : /** Add <b>new_hop</b> to the end of the doubly-linked-list <b>head_ptr</b>.
      38             :  * This function is used to extend cpath by another hop.
      39             :  */
      40             : void
      41          95 : cpath_extend_linked_list(crypt_path_t **head_ptr, crypt_path_t *new_hop)
      42             : {
      43          95 :   if (*head_ptr) {
      44          63 :     new_hop->next = (*head_ptr);
      45          63 :     new_hop->prev = (*head_ptr)->prev;
      46          63 :     (*head_ptr)->prev->next = new_hop;
      47          63 :     (*head_ptr)->prev = new_hop;
      48             :   } else {
      49          32 :     *head_ptr = new_hop;
      50          32 :     new_hop->prev = new_hop->next = new_hop;
      51             :   }
      52          95 : }
      53             : 
      54             : /** Create a new hop, annotate it with information about its
      55             :  * corresponding router <b>choice</b>, and append it to the
      56             :  * end of the cpath <b>head_ptr</b>. */
      57             : int
      58          56 : cpath_append_hop(crypt_path_t **head_ptr, extend_info_t *choice)
      59             : {
      60          56 :   crypt_path_t *hop = tor_malloc_zero(sizeof(crypt_path_t));
      61             : 
      62             :   /* link hop into the cpath, at the end. */
      63          56 :   cpath_extend_linked_list(head_ptr, hop);
      64             : 
      65          56 :   hop->magic = CRYPT_PATH_MAGIC;
      66          56 :   hop->state = CPATH_STATE_CLOSED;
      67             : 
      68          56 :   hop->extend_info = extend_info_dup(choice);
      69             : 
      70          56 :   hop->package_window = circuit_initial_package_window();
      71          56 :   hop->deliver_window = CIRCWINDOW_START;
      72             : 
      73          56 :   return 0;
      74             : }
      75             : 
      76             : /** Verify that cpath <b>cp</b> has all of its invariants
      77             :  * correct. Trigger an assert if anything is invalid.
      78             :  */
      79             : void
      80           0 : cpath_assert_ok(const crypt_path_t *cp)
      81             : {
      82           0 :   const crypt_path_t *start = cp;
      83             : 
      84           0 :   do {
      85           0 :     cpath_assert_layer_ok(cp);
      86             :     /* layers must be in sequence of: "open* awaiting? closed*" */
      87           0 :     if (cp != start) {
      88           0 :       if (cp->state == CPATH_STATE_AWAITING_KEYS) {
      89           0 :         tor_assert(cp->prev->state == CPATH_STATE_OPEN);
      90           0 :       } else if (cp->state == CPATH_STATE_OPEN) {
      91           0 :         tor_assert(cp->prev->state == CPATH_STATE_OPEN);
      92             :       }
      93             :     }
      94           0 :     cp = cp->next;
      95           0 :     tor_assert(cp);
      96           0 :   } while (cp != start);
      97           0 : }
      98             : 
      99             : /** Verify that cpath layer <b>cp</b> has all of its invariants
     100             :  * correct. Trigger an assert if anything is invalid.
     101             :  */
     102             : void
     103           2 : cpath_assert_layer_ok(const crypt_path_t *cp)
     104             : {
     105             : //  tor_assert(cp->addr); /* these are zero for rendezvous extra-hops */
     106             : //  tor_assert(cp->port);
     107           2 :   tor_assert(cp);
     108           2 :   tor_assert(cp->magic == CRYPT_PATH_MAGIC);
     109           2 :   switch (cp->state)
     110             :     {
     111           0 :     case CPATH_STATE_OPEN:
     112           0 :       relay_crypto_assert_ok(&cp->pvt_crypto);
     113           0 :       FALLTHROUGH;
     114           0 :     case CPATH_STATE_CLOSED:
     115             :       /*XXXX Assert that there's no handshake_state either. */
     116           0 :       tor_assert(!cp->rend_dh_handshake_state);
     117             :       break;
     118             :     case CPATH_STATE_AWAITING_KEYS:
     119             :       /* tor_assert(cp->dh_handshake_state); */
     120             :       break;
     121           0 :     default:
     122           0 :       log_fn(LOG_ERR, LD_BUG, "Unexpected state %d", cp->state);
     123           0 :       tor_assert(0);
     124             :     }
     125           2 :   tor_assert(cp->package_window >= 0);
     126           2 :   tor_assert(cp->deliver_window >= 0);
     127           2 : }
     128             : 
     129             : /** Initialize cpath-\>{f|b}_{crypto|digest} from the key material in key_data.
     130             :  *
     131             :  * If <b>is_hs_v3</b> is set, this cpath will be used for next gen hidden
     132             :  * service circuits and <b>key_data</b> must be at least
     133             :  * HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN bytes in length.
     134             :  *
     135             :  * If <b>is_hs_v3</b> is not set, key_data must contain CPATH_KEY_MATERIAL_LEN
     136             :  * bytes, which are used as follows:
     137             :  *   - 20 to initialize f_digest
     138             :  *   - 20 to initialize b_digest
     139             :  *   - 16 to key f_crypto
     140             :  *   - 16 to key b_crypto
     141             :  *
     142             :  * (If 'reverse' is true, then f_XX and b_XX are swapped.)
     143             :  *
     144             :  * Return 0 if init was successful, else -1 if it failed.
     145             :  */
     146             : int
     147          52 : cpath_init_circuit_crypto(crypt_path_t *cpath,
     148             :                           const char *key_data, size_t key_data_len,
     149             :                           int reverse, int is_hs_v3)
     150             : {
     151             : 
     152          52 :   tor_assert(cpath);
     153          52 :   return relay_crypto_init(&cpath->pvt_crypto, key_data, key_data_len,
     154             :                            reverse, is_hs_v3);
     155             : }
     156             : 
     157             : /** Deallocate space associated with the cpath node <b>victim</b>. */
     158             : void
     159          77 : cpath_free(crypt_path_t *victim)
     160             : {
     161          77 :   if (!victim)
     162             :     return;
     163             : 
     164          77 :   relay_crypto_clear(&victim->pvt_crypto);
     165          77 :   onion_handshake_state_release(&victim->handshake_state);
     166          77 :   crypto_dh_free(victim->rend_dh_handshake_state);
     167          77 :   extend_info_free(victim->extend_info);
     168             : 
     169          77 :   memwipe(victim, 0xBB, sizeof(crypt_path_t)); /* poison memory */
     170          77 :   tor_free(victim);
     171             : }
     172             : 
     173             : /********************** cpath crypto API *******************************/
     174             : 
     175             : /** Encrypt or decrypt <b>payload</b> using the crypto of <b>cpath</b>. Actual
     176             :  *  operation decided by <b>is_decrypt</b>.  */
     177             : void
     178         300 : cpath_crypt_cell(const crypt_path_t *cpath, uint8_t *payload, bool is_decrypt)
     179             : {
     180         300 :   if (is_decrypt) {
     181         150 :     relay_crypt_one_payload(cpath->pvt_crypto.b_crypto, payload);
     182             :   } else {
     183         150 :     relay_crypt_one_payload(cpath->pvt_crypto.f_crypto, payload);
     184             :   }
     185         300 : }
     186             : 
     187             : /** Getter for the incoming digest of <b>cpath</b>. */
     188             : struct crypto_digest_t *
     189          50 : cpath_get_incoming_digest(const crypt_path_t *cpath)
     190             : {
     191          50 :   return cpath->pvt_crypto.b_digest;
     192             : }
     193             : 
     194             : /** Set the right integrity digest on the outgoing <b>cell</b> based on the
     195             :  *  cell payload and update the forward digest of <b>cpath</b>. */
     196             : void
     197          50 : cpath_set_cell_forward_digest(crypt_path_t *cpath, cell_t *cell)
     198             : {
     199          50 :   relay_set_digest(cpath->pvt_crypto.f_digest, cell);
     200          50 : }
     201             : 
     202             : /************ cpath sendme API ***************************/
     203             : 
     204             : /** Return the sendme_digest of this <b>cpath</b>. */
     205             : uint8_t *
     206           6 : cpath_get_sendme_digest(crypt_path_t *cpath)
     207             : {
     208           6 :   return relay_crypto_get_sendme_digest(&cpath->pvt_crypto);
     209             : }
     210             : 
     211             : /** Record the cell digest, indicated by is_foward_digest or not, as the
     212             :  * SENDME cell digest. */
     213             : void
     214           0 : cpath_sendme_record_cell_digest(crypt_path_t *cpath, bool is_foward_digest)
     215             : {
     216           0 :   tor_assert(cpath);
     217           0 :   relay_crypto_record_sendme_digest(&cpath->pvt_crypto, is_foward_digest);
     218           0 : }
     219             : 
     220             : /************ other cpath functions ***************************/
     221             : 
     222             : /** Return the first non-open hop in cpath, or return NULL if all
     223             :  * hops are open. */
     224             : crypt_path_t *
     225           6 : cpath_get_next_non_open_hop(crypt_path_t *cpath)
     226             : {
     227           6 :   crypt_path_t *hop = cpath;
     228          12 :   do {
     229          12 :     if (hop->state != CPATH_STATE_OPEN)
     230           6 :       return hop;
     231           6 :     hop = hop->next;
     232           6 :   } while (hop != cpath);
     233             :   return NULL;
     234             : }
     235             : 
     236             : #ifdef TOR_UNIT_TESTS
     237             : 
     238             : /** Unittest helper function: Count number of hops in cpath linked list. */
     239             : unsigned int
     240           4 : cpath_get_n_hops(crypt_path_t **head_ptr)
     241             : {
     242           4 :   unsigned int n_hops = 0;
     243           4 :   crypt_path_t *tmp;
     244             : 
     245           4 :   if (!*head_ptr) {
     246             :     return 0;
     247             :   }
     248             : 
     249             :   tmp = *head_ptr;
     250           2 :   do {
     251           2 :     n_hops++;
     252           2 :     tmp = tmp->next;
     253           2 :   } while (tmp != *head_ptr);
     254             : 
     255             :   return n_hops;
     256             : }
     257             : 
     258             : #endif /* defined(TOR_UNIT_TESTS) */

Generated by: LCOV version 1.14