1 /* Copyright 2001,2002,2003 Roger Dingledine, Matej Pfajfar. */
2 /* See LICENSE for licensing information */
7 /* prototypes for smartlist operations from routerlist.h
8 * they're here to prevent precedence issues with the .h files
10 void router_add_running_routers_to_smartlist(smartlist_t
*sl
);
11 void add_nickname_list_to_smartlist(smartlist_t
*sl
, char *list
);
13 extern or_options_t options
; /* command-line and config-file options */
15 static int count_acceptable_routers(smartlist_t
*routers
);
17 int decide_circ_id_type(char *local_nick
, char *remote_nick
) {
22 return CIRC_ID_TYPE_LOWER
;
23 result
= strcmp(local_nick
, remote_nick
);
26 return CIRC_ID_TYPE_LOWER
;
27 return CIRC_ID_TYPE_HIGHER
;
30 struct onion_queue_t
{
32 struct onion_queue_t
*next
;
35 /* global (within this file) variables used by the next few functions */
36 static struct onion_queue_t
*ol_list
=NULL
;
37 static struct onion_queue_t
*ol_tail
=NULL
;
38 static int ol_length
=0;
40 int onion_pending_add(circuit_t
*circ
) {
41 struct onion_queue_t
*tmp
;
43 tmp
= tor_malloc(sizeof(struct onion_queue_t
));
57 assert(!ol_tail
->next
);
59 if(ol_length
>= options
.MaxOnionsPending
) {
60 log_fn(LOG_WARN
,"Already have %d onions queued. Closing.", ol_length
);
72 circuit_t
*onion_next_task(void) {
76 return NULL
; /* no onions pending, we're done */
78 assert(ol_list
->circ
);
79 assert(ol_list
->circ
->p_conn
); /* make sure it's still valid */
80 assert(ol_length
> 0);
82 onion_pending_remove(ol_list
->circ
);
86 /* go through ol_list, find the onion_queue_t element which points to
87 * circ, remove and free that element. leave circ itself alone.
89 void onion_pending_remove(circuit_t
*circ
) {
90 struct onion_queue_t
*tmpo
, *victim
;
93 return; /* nothing here. */
95 /* first check to see if it's the first entry */
97 if(tmpo
->circ
== circ
) {
98 /* it's the first one. remove it from the list. */
104 } else { /* we need to hunt through the rest of the list */
105 for( ;tmpo
->next
&& tmpo
->next
->circ
!= circ
; tmpo
=tmpo
->next
) ;
107 log_fn(LOG_DEBUG
,"circ (p_circ_id %d) not in list, probably at cpuworker.",circ
->p_circ_id
);
110 /* now we know tmpo->next->circ == circ */
112 tmpo
->next
= victim
->next
;
113 if(ol_tail
== victim
)
118 /* now victim points to the element that needs to be removed */
123 /* given a response payload and keys, initialize, then send a created cell back */
124 int onionskin_answer(circuit_t
*circ
, unsigned char *payload
, unsigned char *keys
) {
126 crypt_path_t
*tmp_cpath
;
128 tmp_cpath
= tor_malloc_zero(sizeof(crypt_path_t
));
130 memset(&cell
, 0, sizeof(cell_t
));
131 cell
.command
= CELL_CREATED
;
132 cell
.circ_id
= circ
->p_circ_id
;
134 circ
->state
= CIRCUIT_STATE_OPEN
;
136 log_fn(LOG_DEBUG
,"Entering.");
138 memcpy(cell
.payload
, payload
, ONIONSKIN_REPLY_LEN
);
140 log_fn(LOG_INFO
,"init digest forward 0x%.8x, backward 0x%.8x.",
141 (unsigned int)*(uint32_t*)(keys
), (unsigned int)*(uint32_t*)(keys
+20));
142 if (circuit_init_cpath_crypto(tmp_cpath
, keys
, 0)<0) {
143 log_fn(LOG_WARN
,"Circuit initialization failed");
147 circ
->n_digest
= tmp_cpath
->f_digest
;
148 circ
->n_crypto
= tmp_cpath
->f_crypto
;
149 circ
->p_digest
= tmp_cpath
->b_digest
;
150 circ
->p_crypto
= tmp_cpath
->b_crypto
;
153 memcpy(circ
->handshake_digest
, cell
.payload
+DH_KEY_LEN
, DIGEST_LEN
);
155 connection_or_write_cell_to_buf(&cell
, circ
->p_conn
);
156 log_fn(LOG_DEBUG
,"Finished sending 'created' cell.");
161 extern int has_fetched_directory
;
163 static int new_route_len(double cw
, uint8_t purpose
, smartlist_t
*routers
) {
164 int num_acceptable_routers
;
167 assert((cw
>= 0) && (cw
< 1) && routers
); /* valid parameters */
172 if(purpose
== CIRCUIT_PURPOSE_C_GENERAL
)
174 else if(purpose
== CIRCUIT_PURPOSE_C_INTRODUCING
)
176 else if(purpose
== CIRCUIT_PURPOSE_C_ESTABLISH_REND
)
178 else if(purpose
== CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
)
180 else if(purpose
== CIRCUIT_PURPOSE_S_CONNECT_REND
)
183 log_fn(LOG_WARN
,"Unhandled purpose %d", purpose
);
188 for(routelen
= 3; ; routelen
++) { /* 3, increment until coinflip says we're done */
189 if (crypto_pseudo_rand_int(255) >= cw
*255) /* don't extend */
193 log_fn(LOG_DEBUG
,"Chosen route length %d (%d routers available).",routelen
,
194 smartlist_len(routers
));
196 num_acceptable_routers
= count_acceptable_routers(routers
);
198 if(num_acceptable_routers
< 2) {
199 log_fn(LOG_INFO
,"Not enough acceptable routers (%d). Discarding this circuit.",
200 num_acceptable_routers
);
204 if(num_acceptable_routers
< routelen
) {
205 log_fn(LOG_INFO
,"Not enough routers: cutting routelen from %d to %d.",
206 routelen
, num_acceptable_routers
);
207 routelen
= num_acceptable_routers
;
213 static routerinfo_t
*choose_good_exit_server_general(routerlist_t
*dir
)
217 int n_pending_connections
= 0;
218 connection_t
**carray
;
220 int best_support
= -1;
221 int n_best_support
=0;
222 smartlist_t
*sl
, *preferredexits
, *excludedexits
;
223 routerinfo_t
*router
;
225 get_connection_array(&carray
, &n_connections
);
227 /* Count how many connections are waiting for a circuit to be built.
228 * We use this for log messages now, but in the future we may depend on it.
230 for (i
= 0; i
< n_connections
; ++i
) {
231 if (carray
[i
]->type
== CONN_TYPE_AP
&&
232 carray
[i
]->state
== AP_CONN_STATE_CIRCUIT_WAIT
&&
233 !carray
[i
]->marked_for_close
&&
234 !circuit_stream_is_being_handled(carray
[i
]))
235 ++n_pending_connections
;
237 log_fn(LOG_DEBUG
, "Choosing exit node; %d connections are pending",
238 n_pending_connections
);
239 /* Now we count, for each of the routers in the directory, how many
240 * of the pending connections could possibly exit from that
241 * router (n_supported[i]). (We can't be sure about cases where we
242 * don't know the IP address of the pending connection.)
244 n_supported
= tor_malloc(sizeof(int)*smartlist_len(dir
->routers
));
245 for (i
= 0; i
< smartlist_len(dir
->routers
); ++i
) { /* iterate over routers */
246 router
= smartlist_get(dir
->routers
, i
);
247 if(router_is_me(router
)) {
249 log_fn(LOG_DEBUG
,"Skipping node %s -- it's me.", router
->nickname
);
250 /* XXX there's probably a reverse predecessor attack here, but
251 * it's slow. should we take this out? -RD
255 if(!router
->is_running
) {
257 log_fn(LOG_DEBUG
,"Skipping node %s (index %d) -- directory says it's not running.",
258 router
->nickname
, i
);
259 continue; /* skip routers that are known to be down */
261 if(router_exit_policy_rejects_all(router
)) {
263 log_fn(LOG_DEBUG
,"Skipping node %s (index %d) -- it rejects all.",
264 router
->nickname
, i
);
265 continue; /* skip routers that reject all */
268 for (j
= 0; j
< n_connections
; ++j
) { /* iterate over connections */
269 if (carray
[j
]->type
!= CONN_TYPE_AP
||
270 carray
[j
]->state
!= AP_CONN_STATE_CIRCUIT_WAIT
||
271 carray
[j
]->marked_for_close
||
272 circuit_stream_is_being_handled(carray
[j
]))
273 continue; /* Skip everything but APs in CIRCUIT_WAIT */
274 switch (connection_ap_can_use_exit(carray
[j
], router
))
276 case ADDR_POLICY_REJECTED
:
277 log_fn(LOG_DEBUG
,"%s (index %d) would reject this stream.",
278 router
->nickname
, i
);
279 break; /* would be rejected; try next connection */
280 case ADDR_POLICY_ACCEPTED
:
281 case ADDR_POLICY_UNKNOWN
:
283 log_fn(LOG_DEBUG
,"%s is supported. n_supported[%d] now %d.",
284 router
->nickname
, i
, n_supported
[i
]);
286 } /* End looping over connections. */
287 if (n_supported
[i
] > best_support
) {
288 /* If this router is better than previous ones, remember its index
289 * and goodness, and start counting how many routers are this good. */
290 best_support
= n_supported
[i
]; n_best_support
=1;
291 log_fn(LOG_DEBUG
,"%s is new best supported option so far.",
293 } else if (n_supported
[i
] == best_support
) {
294 /* If this router is _as good_ as the best one, just increment the
295 * count of equally good routers.*/
299 log_fn(LOG_INFO
, "Found %d servers that might support %d/%d pending connections.",
300 n_best_support
, best_support
, n_pending_connections
);
302 preferredexits
= smartlist_create();
303 add_nickname_list_to_smartlist(preferredexits
,options
.ExitNodes
);
305 excludedexits
= smartlist_create();
306 add_nickname_list_to_smartlist(excludedexits
,options
.ExcludeNodes
);
308 sl
= smartlist_create();
310 /* If any routers definitely support any pending connections, choose one
312 if (best_support
> 0) {
313 for (i
= 0; i
< smartlist_len(dir
->routers
); i
++)
314 if (n_supported
[i
] == best_support
)
315 smartlist_add(sl
, smartlist_get(dir
->routers
, i
));
317 smartlist_subtract(sl
,excludedexits
);
318 if (smartlist_overlap(sl
,preferredexits
))
319 smartlist_intersect(sl
,preferredexits
);
320 router
= smartlist_choose(sl
);
322 /* Either there are no pending connections, or no routers even seem to
323 * possibly support any of them. Choose a router at random. */
324 if (best_support
== -1) {
325 log(LOG_WARN
, "All routers are down or middleman -- choosing a doomed exit at random.");
327 for(i
= 0; i
< smartlist_len(dir
->routers
); i
++)
328 if(n_supported
[i
] != -1)
329 smartlist_add(sl
, smartlist_get(dir
->routers
, i
));
331 smartlist_subtract(sl
,excludedexits
);
332 if (smartlist_overlap(sl
,preferredexits
))
333 smartlist_intersect(sl
,preferredexits
);
334 router
= smartlist_choose(sl
);
337 smartlist_free(preferredexits
);
338 smartlist_free(excludedexits
);
340 tor_free(n_supported
);
342 log_fn(LOG_INFO
, "Chose exit server '%s'", router
->nickname
);
345 log_fn(LOG_WARN
, "No exit routers seem to be running; can't choose an exit.");
349 static routerinfo_t
*choose_good_exit_server(uint8_t purpose
, routerlist_t
*dir
)
351 smartlist_t
*obsolete_routers
;
354 case CIRCUIT_PURPOSE_C_GENERAL
:
355 return choose_good_exit_server_general(dir
);
356 case CIRCUIT_PURPOSE_C_ESTABLISH_REND
:
357 obsolete_routers
= smartlist_create();
358 router_add_nonrendezvous_to_list(obsolete_routers
);
359 r
= router_choose_random_node(dir
, options
.RendNodes
, options
.RendExcludeNodes
, obsolete_routers
);
360 smartlist_free(obsolete_routers
);
363 log_fn(LOG_WARN
,"unhandled purpose %d", purpose
);
366 return NULL
; /* never reached */
369 cpath_build_state_t
*onion_new_cpath_build_state(uint8_t purpose
,
370 const char *exit_nickname
) {
373 cpath_build_state_t
*info
;
376 router_get_routerlist(&rl
);
377 r
= new_route_len(options
.PathlenCoinWeight
, purpose
, rl
->routers
);
380 info
= tor_malloc_zero(sizeof(cpath_build_state_t
));
381 info
->desired_path_len
= r
;
382 if(exit_nickname
) { /* the circuit-builder pre-requested one */
383 log_fn(LOG_INFO
,"Using requested exit node '%s'", exit_nickname
);
384 info
->chosen_exit
= tor_strdup(exit_nickname
);
385 } else { /* we have to decide one */
386 exit
= choose_good_exit_server(purpose
, rl
);
388 log_fn(LOG_WARN
,"failed to choose an exit server");
392 info
->chosen_exit
= tor_strdup(exit
->nickname
);
397 static int count_acceptable_routers(smartlist_t
*routers
) {
401 routerinfo_t
*r
, *r2
;
403 n
= smartlist_len(routers
);
405 r
= smartlist_get(routers
, i
);
406 log_fn(LOG_DEBUG
,"Contemplating whether router %d (%s) is a new option...",
408 if(r
->is_running
== 0) {
409 log_fn(LOG_DEBUG
,"Nope, the directory says %d is not running.",i
);
413 conn
= connection_exact_get_by_addr_port(r
->addr
, r
->or_port
);
414 if(!conn
|| conn
->type
!= CONN_TYPE_OR
|| conn
->state
!= OR_CONN_STATE_OPEN
) {
415 log_fn(LOG_DEBUG
,"Nope, %d is not connected.",i
);
420 r2
= smartlist_get(routers
, j
);
421 if(!crypto_pk_cmp_keys(r
->onion_pkey
, r2
->onion_pkey
)) {
422 /* these guys are twins. so we've already counted him. */
423 log_fn(LOG_DEBUG
,"Nope, %d is a twin of %d.",i
,j
);
428 log_fn(LOG_DEBUG
,"I like %d. num_acceptable_routers now %d.",i
, num
);
430 ; /* C requires an explicit statement after the label */
436 static void remove_twins_from_smartlist(smartlist_t
*sl
, routerinfo_t
*twin
) {
443 for(i
=0; i
< smartlist_len(sl
); i
++) {
444 r
= smartlist_get(sl
,i
);
445 if (!crypto_pk_cmp_keys(r
->onion_pkey
, twin
->onion_pkey
)) {
446 smartlist_del(sl
,i
--);
451 void onion_append_to_cpath(crypt_path_t
**head_ptr
, crypt_path_t
*new_hop
)
454 new_hop
->next
= (*head_ptr
);
455 new_hop
->prev
= (*head_ptr
)->prev
;
456 (*head_ptr
)->prev
->next
= new_hop
;
457 (*head_ptr
)->prev
= new_hop
;
460 new_hop
->prev
= new_hop
->next
= new_hop
;
464 int onion_extend_cpath(crypt_path_t
**head_ptr
, cpath_build_state_t
*state
, routerinfo_t
**router_out
)
467 crypt_path_t
*cpath
, *hop
;
469 routerinfo_t
*choice
;
471 smartlist_t
*sl
, *excludednodes
;
480 for (cpath
= *head_ptr
; cpath
->next
!= *head_ptr
; cpath
= cpath
->next
) {
484 if (cur_len
>= state
->desired_path_len
) {
485 log_fn(LOG_DEBUG
, "Path is complete: %d steps long",
486 state
->desired_path_len
);
489 log_fn(LOG_DEBUG
, "Path is %d long; we want %d", cur_len
,
490 state
->desired_path_len
);
492 excludednodes
= smartlist_create();
493 add_nickname_list_to_smartlist(excludednodes
,options
.ExcludeNodes
);
495 if(cur_len
== state
->desired_path_len
- 1) { /* Picking last node */
496 log_fn(LOG_DEBUG
, "Contemplating last hop: choice already made: %s",
498 choice
= router_get_by_nickname(state
->chosen_exit
);
499 smartlist_free(excludednodes
);
501 log_fn(LOG_WARN
,"Our chosen exit %s is no longer in the directory? Discarding this circuit.",
505 } else if(cur_len
== 0) { /* picking first node */
506 /* try the nodes in EntryNodes first */
507 sl
= smartlist_create();
508 add_nickname_list_to_smartlist(sl
,options
.EntryNodes
);
509 /* XXX one day, consider picking chosen_exit knowing what's in EntryNodes */
510 remove_twins_from_smartlist(sl
,router_get_by_nickname(state
->chosen_exit
));
511 remove_twins_from_smartlist(sl
,router_get_my_routerinfo());
512 smartlist_subtract(sl
,excludednodes
);
513 choice
= smartlist_choose(sl
);
516 sl
= smartlist_create();
517 router_add_running_routers_to_smartlist(sl
);
518 remove_twins_from_smartlist(sl
,router_get_by_nickname(state
->chosen_exit
));
519 remove_twins_from_smartlist(sl
,router_get_my_routerinfo());
520 smartlist_subtract(sl
,excludednodes
);
521 choice
= smartlist_choose(sl
);
524 smartlist_free(excludednodes
);
526 log_fn(LOG_WARN
,"No acceptable routers while picking entry node. Discarding this circuit.");
530 log_fn(LOG_DEBUG
, "Contemplating intermediate hop: random choice.");
531 sl
= smartlist_create();
532 router_add_running_routers_to_smartlist(sl
);
533 remove_twins_from_smartlist(sl
,router_get_by_nickname(state
->chosen_exit
));
534 remove_twins_from_smartlist(sl
,router_get_my_routerinfo());
535 for (i
= 0, cpath
= *head_ptr
; i
< cur_len
; ++i
, cpath
=cpath
->next
) {
536 r
= router_get_by_addr_port(cpath
->addr
, cpath
->port
);
538 remove_twins_from_smartlist(sl
,r
);
540 smartlist_subtract(sl
,excludednodes
);
541 choice
= smartlist_choose(sl
);
543 smartlist_free(excludednodes
);
545 log_fn(LOG_WARN
,"No acceptable routers while picking intermediate node. Discarding this circuit.");
550 log_fn(LOG_DEBUG
,"Chose router %s for hop %d (exit is %s)",
551 choice
->nickname
, cur_len
, state
->chosen_exit
);
553 hop
= tor_malloc_zero(sizeof(crypt_path_t
));
555 /* link hop into the cpath, at the end. */
556 onion_append_to_cpath(head_ptr
, hop
);
558 hop
->state
= CPATH_STATE_CLOSED
;
560 hop
->port
= choice
->or_port
;
561 hop
->addr
= choice
->addr
;
563 hop
->package_window
= CIRCWINDOW_START
;
564 hop
->deliver_window
= CIRCWINDOW_START
;
566 log_fn(LOG_DEBUG
, "Extended circuit path with %s for hop %d",
567 choice
->nickname
, cur_len
);
569 *router_out
= choice
;
573 /*----------------------------------------------------------------------*/
575 /* Given a router's 128 byte public key,
576 stores the following in onion_skin_out:
577 [16 bytes] Symmetric key for encrypting blob past RSA
578 [112 bytes] g^x part 1 (inside the RSA)
579 [16 bytes] g^x part 2 (symmetrically encrypted)
581 * Stores the DH private key into handshake_state_out for later completion
584 * The meeting point/cookies and auth are zeroed out for now.
587 onion_skin_create(crypto_pk_env_t
*dest_router_key
,
588 crypto_dh_env_t
**handshake_state_out
,
589 char *onion_skin_out
) /* Must be ONIONSKIN_CHALLENGE_LEN bytes */
591 char *challenge
= NULL
;
592 crypto_dh_env_t
*dh
= NULL
;
593 int dhbytes
, pkbytes
;
595 *handshake_state_out
= NULL
;
596 memset(onion_skin_out
, 0, ONIONSKIN_CHALLENGE_LEN
);
598 if (!(dh
= crypto_dh_new()))
601 dhbytes
= crypto_dh_get_bytes(dh
);
602 pkbytes
= crypto_pk_keysize(dest_router_key
);
603 assert(dhbytes
== 128);
604 assert(pkbytes
== 128);
605 challenge
= tor_malloc_zero(DH_KEY_LEN
);
607 if (crypto_dh_get_public(dh
, challenge
, dhbytes
))
610 #ifdef DEBUG_ONION_SKINS
612 { int _i; for (_i = 0; _i<n; ++_i) printf("%02x ",((int)(a)[_i])&0xFF); }
614 printf("Client: client g^x:");
620 printf("Client: client symkey:");
625 /* set meeting point, meeting cookie, etc here. Leave zero for now. */
626 if (crypto_pk_public_hybrid_encrypt(dest_router_key
, challenge
,
628 onion_skin_out
, PK_PKCS1_OAEP_PADDING
, 1)<0)
632 *handshake_state_out
= dh
;
637 if (dh
) crypto_dh_free(dh
);
641 /* Given an encrypted DH public key as generated by onion_skin_create,
642 * and the private key for this onion router, generate the reply (128-byte
643 * DH plus the first 20 bytes of shared key material), and store the
644 * next key_out_len bytes of key material in key_out.
647 onion_skin_server_handshake(char *onion_skin
, /* ONIONSKIN_CHALLENGE_LEN bytes */
648 crypto_pk_env_t
*private_key
,
649 crypto_pk_env_t
*prev_private_key
,
650 char *handshake_reply_out
, /* ONIONSKIN_REPLY_LEN bytes */
654 char challenge
[ONIONSKIN_CHALLENGE_LEN
];
655 crypto_dh_env_t
*dh
= NULL
;
657 char *key_material
=NULL
;
663 k
= i
==0?private_key
:prev_private_key
;
666 len
= crypto_pk_private_hybrid_decrypt(k
,
667 onion_skin
, ONIONSKIN_CHALLENGE_LEN
,
668 challenge
, PK_PKCS1_OAEP_PADDING
);
673 log_fn(LOG_WARN
, "Couldn't decrypt onionskin");
675 } else if (len
!= DH_KEY_LEN
) {
676 log_fn(LOG_WARN
, "Unexpected onionskin length after decryption: %d",
681 dh
= crypto_dh_new();
682 if (crypto_dh_get_public(dh
, handshake_reply_out
, DH_KEY_LEN
))
685 #ifdef DEBUG_ONION_SKINS
686 printf("Server: server g^y:");
687 PA(handshake_reply_out
+0,3);
689 PA(handshake_reply_out
+125,3);
693 key_material
= tor_malloc(DIGEST_LEN
+key_out_len
);
694 len
= crypto_dh_compute_secret(dh
, challenge
, DH_KEY_LEN
,
695 key_material
, DIGEST_LEN
+key_out_len
);
699 /* send back H(K|0) as proof that we learned K. */
700 memcpy(handshake_reply_out
+DH_KEY_LEN
, key_material
, DIGEST_LEN
);
702 /* use the rest of the key material for our shared keys, digests, etc */
703 memcpy(key_out
, key_material
+DIGEST_LEN
, key_out_len
);
705 #ifdef DEBUG_ONION_SKINS
706 printf("Server: key material:");
709 printf("Server: keys out:");
710 PA(key_out
, key_out_len
);
714 tor_free(key_material
);
718 tor_free(key_material
);
719 if (dh
) crypto_dh_free(dh
);
724 /* Finish the client side of the DH handshake.
725 * Given the 128 byte DH reply + 20 byte hash as generated by
726 * onion_skin_server_handshake and the handshake state generated by
727 * onion_skin_create, verify H(K) with the first 20 bytes of shared
728 * key material, then generate key_out_len more bytes of shared key
729 * material and store them in key_out.
731 * After the invocation, call crypto_dh_free on handshake_state.
734 onion_skin_client_handshake(crypto_dh_env_t
*handshake_state
,
735 char *handshake_reply
, /* Must be ONIONSKIN_REPLY_LEN bytes */
740 char *key_material
=NULL
;
741 assert(crypto_dh_get_bytes(handshake_state
) == DH_KEY_LEN
);
743 #ifdef DEBUG_ONION_SKINS
744 printf("Client: server g^y:");
745 PA(handshake_reply
+0,3);
747 PA(handshake_reply
+125,3);
751 key_material
= tor_malloc(20+key_out_len
);
752 len
= crypto_dh_compute_secret(handshake_state
, handshake_reply
, DH_KEY_LEN
,
753 key_material
, 20+key_out_len
);
757 if(memcmp(key_material
, handshake_reply
+DH_KEY_LEN
, 20)) {
758 /* H(K) does *not* match. Something fishy. */
759 tor_free(key_material
);
760 log_fn(LOG_WARN
,"Digest DOES NOT MATCH on onion handshake. Bug or attack.");
764 /* use the rest of the key material for our shared keys, digests, etc */
765 memcpy(key_out
, key_material
+20, key_out_len
);
767 #ifdef DEBUG_ONION_SKINS
768 printf("Client: keys out:");
769 PA(key_out
, key_out_len
);
773 tor_free(key_material
);