Tor 0.4.9.3-alpha-dev
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
relay_crypto.c
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 relay_crypto.h
9 * @brief Header for relay_crypto.c
10 **/
11
12// For access to cpath pvt_crypto field.
13#define CRYPT_PATH_PRIVATE
14
15#include "core/or/or.h"
16#include "core/or/circuitlist.h"
17#include "core/or/crypt_path.h"
18#include "app/config/config.h"
22#include "core/crypto/relay_crypto_tor1.h"
23#include "core/or/sendme.h"
24
25#include "core/or/or_circuit_st.h"
27
28#define CGO_AES_BITS 128
29
30/** Return the sendme tag within the <b>crypto</b> object,
31 * along with its length.
32 *
33 * This is the digest from the most recent cell that we originated
34 * or recognized, _in either direction_.
35 * Calls to any encryption function on `crypto` may invalidate
36 * this digest.
37 */
38const uint8_t *
39relay_crypto_get_sendme_tag(relay_crypto_t *crypto,
40 size_t *len_out)
41{
42 tor_assert(crypto);
43 switch (crypto->kind) {
44 case RCK_TOR1:
45 *len_out = SENDME_TAG_LEN_TOR1;
46 return crypto->c.tor1.sendme_digest;
47 case RCK_CGO:
48 *len_out = SENDME_TAG_LEN_CGO;
49 return crypto->c.cgo.last_tag;
50 }
51 tor_assert_unreached();
52}
53
54/** Return the length of SENDME tags generated by `crypto`. */
55size_t
56relay_crypto_sendme_tag_len(const relay_crypto_t *crypto)
57{
58 tor_assert(crypto);
59 switch (crypto->kind) {
60 case RCK_TOR1:
62 case RCK_CGO:
63 return SENDME_TAG_LEN_CGO;
64 }
65 tor_assert_unreached();
66}
67
68/**
69 * Handle a single layer of client-side backward encryption
70 * with crypto of an arbitary type.
71 */
72static inline bool
73relay_crypt_client_backward(relay_crypto_t *crypto, cell_t *cell)
74{
75 switch (crypto->kind) {
76 case RCK_TOR1:
77 return tor1_crypt_client_backward(&crypto->c.tor1, cell);
78 case RCK_CGO: {
79 const uint8_t *tag = NULL;
80 cgo_crypt_client_backward(crypto->c.cgo.back, cell, &tag);
81 if (tag != NULL) {
82 memcpy(crypto->c.cgo.last_tag, tag, SENDME_TAG_LEN_CGO);
83 return true;
84 } else {
85 return false;
86 }
87 }
88 }
89 tor_assert_unreached();
90}
91
92/**
93 * Handle a relay-side forward encryption
94 * with crypto of an arbitary type.
95 */
96static inline bool
97relay_crypt_relay_forward(relay_crypto_t *crypto, cell_t *cell)
98{
99 switch (crypto->kind) {
100 case RCK_TOR1:
101 return tor1_crypt_relay_forward(&crypto->c.tor1, cell);
102 case RCK_CGO: {
103 const uint8_t *tag = NULL;
104 cgo_crypt_relay_forward(crypto->c.cgo.fwd, cell, &tag);
105 if (tag != NULL) {
106 memcpy(crypto->c.cgo.last_tag, tag, SENDME_TAG_LEN_CGO);
107 return true;
108 } else {
109 return false;
110 }
111 }
112 }
113 tor_assert_unreached();
114}
115
116/**
117 * Handle relay-side backward encryption with crypto of an arbitary type.
118 */
119static inline void
120relay_crypt_relay_backward(relay_crypto_t *crypto, cell_t *cell)
121{
122 switch (crypto->kind) {
123 case RCK_TOR1:
124 tor1_crypt_relay_backward(&crypto->c.tor1, cell);
125 break;
126 case RCK_CGO: {
127 cgo_crypt_relay_backward(crypto->c.cgo.back, cell);
128 break;
129 }
130 }
131}
132
133/** Do the appropriate en/decryptions for <b>cell</b> arriving on
134 * <b>circ</b> in direction <b>cell_direction</b>.
135 *
136 * If cell_direction == CELL_DIRECTION_IN:
137 * - If we're at the origin (we're the OP), for hops 1..N,
138 * decrypt cell. If recognized, stop.
139 * - Else (we're not the OP), encrypt one hop. Cell is not recognized.
140 *
141 * If cell_direction == CELL_DIRECTION_OUT:
142 * - decrypt one hop. Check if recognized.
143 *
144 * If cell is recognized, set *recognized to 1, and set
145 * *layer_hint to the hop that recognized it.
146 *
147 * Return -1 to indicate that we should mark the circuit for close,
148 * else return 0.
149 */
150int
151relay_decrypt_cell(circuit_t *circ, cell_t *cell,
152 cell_direction_t cell_direction,
153 crypt_path_t **layer_hint, char *recognized)
154{
155 tor_assert(circ);
156 tor_assert(cell);
157 tor_assert(recognized);
158 tor_assert(cell_direction == CELL_DIRECTION_IN ||
159 cell_direction == CELL_DIRECTION_OUT);
160
161 if (cell_direction == CELL_DIRECTION_IN) {
162 if (CIRCUIT_IS_ORIGIN(circ)) { /* We're at the beginning of the circuit.
163 * We'll want to do layered decrypts. */
164 crypt_path_t *thishop, *cpath = TO_ORIGIN_CIRCUIT(circ)->cpath;
165 thishop = cpath;
166 if (thishop->state != CPATH_STATE_OPEN) {
167 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
168 "Relay cell before first created cell? Closing.");
169 return -1;
170 }
171 do { /* Remember: cpath is in forward order, that is, first hop first. */
172 tor_assert(thishop);
173
174 bool rec = relay_crypt_client_backward(&thishop->pvt_crypto, cell);
175 if (rec) {
176 *recognized = 1;
177 *layer_hint = thishop;
178 return 0;
179 }
180 thishop = thishop->next;
181 } while (thishop != cpath && thishop->state == CPATH_STATE_OPEN);
182 log_fn(LOG_PROTOCOL_WARN, LD_OR,
183 "Incoming cell at client not recognized. Closing.");
184 return -1;
185 } else {
186 /* We're in the middle. Encrypt one layer. */
187 relay_crypto_t *crypto = &TO_OR_CIRCUIT(circ)->crypto;
188 relay_crypt_relay_backward(crypto, cell);
189 }
190 } else /* cell_direction == CELL_DIRECTION_OUT */ {
191 /* We're in the middle. Decrypt one layer. */
192 relay_crypto_t *crypto = &TO_OR_CIRCUIT(circ)->crypto;
193
194 bool rec = relay_crypt_relay_forward(crypto, cell);
195 if (rec) {
196 *recognized = 1;
197 return 0;
198 }
199 }
200 return 0;
201}
202
203/** Originate a client cell with a relay_crypt_t of arbitrary type. */
204static inline void
205relay_crypt_client_originate(relay_crypto_t *crypto, cell_t *cell)
206{
207 switch (crypto->kind) {
208 case RCK_TOR1:
209 tor1_crypt_client_originate(&crypto->c.tor1, cell);
210 break;
211 case RCK_CGO: {
212 const uint8_t *tag = NULL;
213 cgo_crypt_client_originate(crypto->c.cgo.fwd, cell, &tag);
214 tor_assert(tag);
215 memcpy(crypto->c.cgo.last_tag, tag, SENDME_TAG_LEN_CGO);
216 break;
217 }
218 }
219}
220
221/** Perform forward-direction client encryption with a relay_crypt_t
222 * of arbitrary type. */
223static inline void
224relay_crypt_client_forward(relay_crypto_t *crypto, cell_t *cell)
225{
226 switch (crypto->kind) {
227 case RCK_TOR1:
228 tor1_crypt_client_forward(&crypto->c.tor1, cell);
229 break;
230 case RCK_CGO:
231 cgo_crypt_client_forward(crypto->c.cgo.fwd, cell);
232 break;
233 }
234}
235
236/**
237 * Encrypt a cell <b>cell</b> that we are creating, and sending outbound on
238 * <b>circ</b> until the hop corresponding to <b>layer_hint</b>.
239 *
240 * The integrity field and recognized field of <b>cell</b>'s relay headers
241 * must be set to zero.
242 */
243void
244relay_encrypt_cell_outbound(cell_t *cell,
245 origin_circuit_t *circ,
246 crypt_path_t *layer_hint)
247{
248 crypt_path_t *thishop = layer_hint;
249
250 relay_crypt_client_originate(&thishop->pvt_crypto, cell);
251 thishop = thishop->prev;
252
253 while (thishop != circ->cpath->prev) {
254 relay_crypt_client_forward(&thishop->pvt_crypto, cell);
255 thishop = thishop->prev;
256 }
257}
258
259/**
260 * Encrypt a cell <b>cell</b> that we are creating, and sending on
261 * <b>circuit</b> to the origin.
262 *
263 * The integrity field and recognized field of <b>cell</b>'s relay headers
264 * must be set to zero.
265 */
266void
267relay_encrypt_cell_inbound(cell_t *cell,
268 or_circuit_t *or_circ)
269{
270 relay_crypto_t *crypto = &or_circ->crypto;
271 switch (crypto->kind) {
272 case RCK_TOR1:
273 tor1_crypt_relay_originate(&crypto->c.tor1, cell);
274 break;
275 case RCK_CGO: {
276 const uint8_t *tag = NULL;
277 cgo_crypt_relay_originate(crypto->c.cgo.back, cell, &tag);
278 tor_assert(tag);
279 memcpy(&crypto->c.cgo.last_tag, tag, SENDME_TAG_LEN_CGO);
280 break;
281 }
282 }
283}
284
285/**
286 * Release all storage held inside <b>crypto</b>, but do not free
287 * <b>crypto</b> itself: it lives inside another object.
288 */
289void
290relay_crypto_clear(relay_crypto_t *crypto)
291{
292 switch (crypto->kind) {
293 case RCK_TOR1:
294 tor1_crypt_clear(&crypto->c.tor1);
295 break;
296 case RCK_CGO:
297 cgo_crypt_free(crypto->c.cgo.fwd);
298 cgo_crypt_free(crypto->c.cgo.back);
299 break;
300 }
301}
302
303static int
304cgo_pair_init(cgo_pair_t *pair, bool is_relay,
305 const uint8_t *key_material, size_t key_data_len)
306{
307 memset(pair, 0, sizeof(*pair));
308 const int aes_bits = CGO_AES_BITS;
309 const size_t single_cgo_len = cgo_key_material_len(aes_bits);
310 if (BUG(key_data_len != single_cgo_len * 2)) {
311 return -1;
312 }
313
314 cgo_mode_t fwd_mode, back_mode;
315 if (is_relay) {
316 fwd_mode = CGO_MODE_RELAY_FORWARD;
317 back_mode = CGO_MODE_RELAY_BACKWARD;
318 } else {
319 fwd_mode = CGO_MODE_CLIENT_FORWARD;
320 back_mode = CGO_MODE_CLIENT_BACKWARD;
321 }
322
323 pair->fwd = cgo_crypt_new(fwd_mode, aes_bits,
324 key_material, single_cgo_len);
325 pair->back = cgo_crypt_new(back_mode, aes_bits,
326 key_material + single_cgo_len, single_cgo_len);
327
328 return 0;
329}
330
331/** Initialize <b>crypto</b> from the key material in key_data.
332 *
333 * If <b>is_hs_v3</b> is set, this cpath will be used for next gen hidden
334 * service circuits and <b>key_data</b> must be at least
335 * HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN bytes in length.
336 *
337 * If <b>is_hs_v3</b> is not set, key_data must contain CPATH_KEY_MATERIAL_LEN
338 * bytes, which are used as follows:
339 * - 20 to initialize f_digest
340 * - 20 to initialize b_digest
341 * - 16 to key f_crypto
342 * - 16 to key b_crypto
343 *
344 * (If 'reverse' is true, then f_XX and b_XX are swapped.)
345 *
346 * Return 0 if init was successful, else -1 if it failed.
347 */
348int
349relay_crypto_init(relay_crypto_alg_t alg,
350 relay_crypto_t *crypto,
351 const char *key_data, size_t key_data_len)
352{
353 switch (alg) {
354 /* Tor1 cases: the booleans are "reverse" and "is_hs_v3". */
356 crypto->kind = RCK_TOR1;
357 return tor1_crypt_init(&crypto->c.tor1, key_data, key_data_len,
358 false, false);
360 crypto->kind = RCK_TOR1;
361 return tor1_crypt_init(&crypto->c.tor1, key_data, key_data_len,
362 false, true);
364 crypto->kind = RCK_TOR1;
365 return tor1_crypt_init(&crypto->c.tor1, key_data, key_data_len,
366 true, true);
368 crypto->kind = RCK_CGO;
369 return cgo_pair_init(&crypto->c.cgo, false,
370 (const uint8_t *)key_data, key_data_len);
372 crypto->kind = RCK_CGO;
373 return cgo_pair_init(&crypto->c.cgo, true,
374 (const uint8_t *)key_data, key_data_len);
375 }
376 tor_assert_unreached();
377}
378
379/** Return the amount of key material we need to initialize
380 * the given relay crypto algorithm.
381 *
382 * Return -1 if the algorithm is unrecognized.
383 */
384ssize_t
385relay_crypto_key_material_len(relay_crypto_alg_t alg)
386{
387 switch (alg) {
389 return tor1_key_material_len(false);
392 return tor1_key_material_len(true);
395 return cgo_key_material_len(CGO_AES_BITS) * 2;
396 }
397 return -1;
398}
399
400/** Assert that <b>crypto</b> is valid and set. */
401void
402relay_crypto_assert_ok(const relay_crypto_t *crypto)
403{
404 switch (crypto->kind) {
405 case RCK_TOR1:
406 tor1_crypt_assert_ok(&crypto->c.tor1);
407 break;
408 case RCK_CGO:
409 break;
410 }
411}
origin_circuit_t * TO_ORIGIN_CIRCUIT(circuit_t *x)
or_circuit_t * TO_OR_CIRCUIT(circuit_t *x)
Header file for circuitlist.c.
#define CIRCUIT_IS_ORIGIN(c)
Header file for config.c.
Header file for crypt_path.c.
Headers for crypto_cipher.c.
Common functions for cryptographic routines.
#define log_fn(severity, domain, args,...)
Definition log.h:283
#define LD_PROTOCOL
Definition log.h:72
#define LD_OR
Definition log.h:92
Master header file for Tor-specific functionality.
#define SENDME_TAG_LEN_TOR1
Definition or.h:455
#define SENDME_TAG_LEN_CGO
Definition or.h:457
cell_direction_t
Definition or.h:423
@ CELL_DIRECTION_OUT
Definition or.h:425
@ CELL_DIRECTION_IN
Definition or.h:424
Origin circuit structure.
Header for relay_crypto.c.
relay_crypto_alg_t
@ RELAY_CRYPTO_ALG_TOR1_HSS
@ RELAY_CRYPTO_ALG_TOR1_HSC
@ RELAY_CRYPTO_ALG_TOR1
@ RELAY_CRYPTO_ALG_CGO_RELAY
@ RELAY_CRYPTO_ALG_CGO_CLIENT
void cgo_crypt_relay_originate(cgo_crypt_t *cgo, cell_t *cell, const uint8_t **tag_out)
void cgo_crypt_client_forward(cgo_crypt_t *cgo, cell_t *cell)
void cgo_crypt_relay_backward(cgo_crypt_t *cgo, cell_t *cell)
size_t cgo_key_material_len(int aesbits)
void cgo_crypt_relay_forward(cgo_crypt_t *cgo, cell_t *cell, const uint8_t **recognized_tag_out)
cgo_crypt_t * cgo_crypt_new(cgo_mode_t mode, int aesbits, const uint8_t *keys, size_t keylen)
void cgo_crypt_client_originate(cgo_crypt_t *cgo, cell_t *cell, const uint8_t **tag_out)
void cgo_crypt_client_backward(cgo_crypt_t *cgo, cell_t *cell, const uint8_t **recognized_tag_out)
void tor1_crypt_client_forward(tor1_crypt_t *tor1, cell_t *cell)
void tor1_crypt_assert_ok(const tor1_crypt_t *crypto)
void tor1_crypt_relay_backward(tor1_crypt_t *tor1, cell_t *cell)
void tor1_crypt_relay_originate(tor1_crypt_t *tor1, cell_t *cell)
int tor1_crypt_init(tor1_crypt_t *crypto, const char *key_data, size_t key_data_len, int reverse, int is_hs_v3)
void tor1_crypt_client_originate(tor1_crypt_t *tor1, cell_t *cell)
bool tor1_crypt_client_backward(tor1_crypt_t *tor1, cell_t *cell)
size_t tor1_key_material_len(bool is_hs)
bool tor1_crypt_relay_forward(tor1_crypt_t *tor1, cell_t *cell)
Header file for sendme.c.
struct crypt_path_t * prev
struct crypt_path_t * next
relay_crypto_t crypto
crypt_path_t * cpath
uint8_t sendme_digest[DIGEST_LEN]
#define tor_assert(expr)
Definition util_bug.h:103