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) */