LCOV - code coverage report
Current view: top level - core/crypto - onion_crypto.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 15 114 13.2 %
Date: 2021-11-24 03:28:48 Functions: 2 6 33.3 %

          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_crypto.c
       9             :  * \brief Functions to handle different kinds of circuit extension crypto.
      10             :  *
      11             :  * In this module, we provide a set of abstractions to create a uniform
      12             :  * interface over the three circuit extension handshakes that Tor has used
      13             :  * over the years (TAP, CREATE_FAST, and ntor).  These handshakes are
      14             :  * implemented in onion_tap.c, onion_fast.c, and onion_ntor.c respectively.
      15             :  *
      16             :  * All[*] of these handshakes follow a similar pattern: a client, knowing
      17             :  * some key from the relay it wants to extend through, generates the
      18             :  * first part of a handshake. A relay receives that handshake, and sends
      19             :  * a reply.  Once the client handles the reply, it knows that it is
      20             :  * talking to the right relay, and it shares some freshly negotiated key
      21             :  * material with that relay.
      22             :  *
      23             :  * We sometimes call the client's part of the handshake an "onionskin".
      24             :  * We do this because historically, Onion Routing used a multi-layer
      25             :  * structure called an "onion" to construct circuits. Each layer of the
      26             :  * onion contained key material chosen by the client, the identity of
      27             :  * the next relay in the circuit, and a smaller onion, encrypted with
      28             :  * the key of the next relay.  When we changed Tor to use a telescoping
      29             :  * circuit extension design, it corresponded to sending each layer of the
      30             :  * onion separately -- as a series of onionskins.
      31             :  **/
      32             : 
      33             : #include "core/or/or.h"
      34             : #include "core/or/extendinfo.h"
      35             : #include "core/crypto/onion_crypto.h"
      36             : #include "core/crypto/onion_fast.h"
      37             : #include "core/crypto/onion_ntor.h"
      38             : #include "core/crypto/onion_tap.h"
      39             : #include "feature/relay/router.h"
      40             : #include "lib/crypt_ops/crypto_dh.h"
      41             : #include "lib/crypt_ops/crypto_util.h"
      42             : 
      43             : #include "core/or/crypt_path_st.h"
      44             : #include "core/or/extend_info_st.h"
      45             : 
      46             : /** Return a new server_onion_keys_t object with all of the keys
      47             :  * and other info we might need to do onion handshakes.  (We make a copy of
      48             :  * our keys for each cpuworker to avoid race conditions with the main thread,
      49             :  * and to avoid locking) */
      50             : server_onion_keys_t *
      51           0 : server_onion_keys_new(void)
      52             : {
      53           0 :   server_onion_keys_t *keys = tor_malloc_zero(sizeof(server_onion_keys_t));
      54           0 :   memcpy(keys->my_identity, router_get_my_id_digest(), DIGEST_LEN);
      55           0 :   dup_onion_keys(&keys->onion_key, &keys->last_onion_key);
      56           0 :   keys->curve25519_key_map = construct_ntor_key_map();
      57           0 :   keys->junk_keypair = tor_malloc_zero(sizeof(curve25519_keypair_t));
      58           0 :   curve25519_keypair_generate(keys->junk_keypair, 0);
      59           0 :   return keys;
      60             : }
      61             : /** Release all storage held in <b>keys</b>. */
      62             : void
      63           0 : server_onion_keys_free_(server_onion_keys_t *keys)
      64             : {
      65           0 :   if (! keys)
      66             :     return;
      67             : 
      68           0 :   crypto_pk_free(keys->onion_key);
      69           0 :   crypto_pk_free(keys->last_onion_key);
      70           0 :   ntor_key_map_free(keys->curve25519_key_map);
      71           0 :   tor_free(keys->junk_keypair);
      72           0 :   memwipe(keys, 0, sizeof(server_onion_keys_t));
      73           0 :   tor_free(keys);
      74             : }
      75             : 
      76             : /** Release whatever storage is held in <b>state</b>, depending on its
      77             :  * type, and clear its pointer. */
      78             : void
      79          77 : onion_handshake_state_release(onion_handshake_state_t *state)
      80             : {
      81          77 :   switch (state->tag) {
      82          77 :   case ONION_HANDSHAKE_TYPE_TAP:
      83          77 :     crypto_dh_free(state->u.tap);
      84          77 :     state->u.tap = NULL;
      85          77 :     break;
      86           0 :   case ONION_HANDSHAKE_TYPE_FAST:
      87           0 :     fast_handshake_state_free(state->u.fast);
      88           0 :     state->u.fast = NULL;
      89           0 :     break;
      90           0 :   case ONION_HANDSHAKE_TYPE_NTOR:
      91           0 :     ntor_handshake_state_free(state->u.ntor);
      92           0 :     state->u.ntor = NULL;
      93           0 :     break;
      94           0 :   default:
      95             :     /* LCOV_EXCL_START
      96             :      * This state should not even exist. */
      97             :     log_warn(LD_BUG, "called with unknown handshake state type %d",
      98             :              (int)state->tag);
      99             :     tor_fragile_assert();
     100             :     /* LCOV_EXCL_STOP */
     101             :   }
     102          77 : }
     103             : 
     104             : /** Perform the first step of a circuit-creation handshake of type <b>type</b>
     105             :  * (one of ONION_HANDSHAKE_TYPE_*): generate the initial "onion skin" in
     106             :  * <b>onion_skin_out</b>, and store any state information in <b>state_out</b>.
     107             :  * Return -1 on failure, and the length of the onionskin on acceptance.
     108             :  */
     109             : int
     110           5 : onion_skin_create(int type,
     111             :                   const extend_info_t *node,
     112             :                   onion_handshake_state_t *state_out,
     113             :                   uint8_t *onion_skin_out)
     114             : {
     115           5 :   int r = -1;
     116             : 
     117           5 :   switch (type) {
     118           3 :   case ONION_HANDSHAKE_TYPE_TAP:
     119           3 :     if (!node->onion_key)
     120             :       return -1;
     121             : 
     122           0 :     if (onion_skin_TAP_create(node->onion_key,
     123             :                               &state_out->u.tap,
     124             :                               (char*)onion_skin_out) < 0)
     125             :       return -1;
     126             : 
     127             :     r = TAP_ONIONSKIN_CHALLENGE_LEN;
     128             :     break;
     129           2 :   case ONION_HANDSHAKE_TYPE_FAST:
     130           2 :     if (fast_onionskin_create(&state_out->u.fast, onion_skin_out) < 0)
     131             :       return -1;
     132             : 
     133             :     r = CREATE_FAST_LEN;
     134             :     break;
     135           0 :   case ONION_HANDSHAKE_TYPE_NTOR:
     136           0 :     if (!extend_info_supports_ntor(node))
     137             :       return -1;
     138           0 :     if (onion_skin_ntor_create((const uint8_t*)node->identity_digest,
     139           0 :                                &node->curve25519_onion_key,
     140           0 :                                &state_out->u.ntor,
     141             :                                onion_skin_out) < 0)
     142             :       return -1;
     143             : 
     144             :     r = NTOR_ONIONSKIN_LEN;
     145             :     break;
     146           0 :   default:
     147             :     /* LCOV_EXCL_START
     148             :      * We should never try to create an impossible handshake type. */
     149             :     log_warn(LD_BUG, "called with unknown handshake state type %d", type);
     150             :     tor_fragile_assert();
     151             :     r = -1;
     152             :     /* LCOV_EXCL_STOP */
     153             :   }
     154             : 
     155             :   if (r > 0)
     156           2 :     state_out->tag = (uint16_t) type;
     157             : 
     158             :   return r;
     159             : }
     160             : 
     161             : /* This is the maximum value for keys_out_len passed to
     162             :  * onion_skin_server_handshake, plus 16. We can make it bigger if needed:
     163             :  * It just defines how many bytes to stack-allocate. */
     164             : #define MAX_KEYS_TMP_LEN 128
     165             : 
     166             : /** Perform the second (server-side) step of a circuit-creation handshake of
     167             :  * type <b>type</b>, responding to the client request in <b>onion_skin</b>
     168             :  * using the keys in <b>keys</b>.  On success, write our response into
     169             :  * <b>reply_out</b>, generate <b>keys_out_len</b> bytes worth of key material
     170             :  * in <b>keys_out_len</b>, a hidden service nonce to <b>rend_nonce_out</b>,
     171             :  * and return the length of the reply. On failure, return -1.
     172             :  */
     173             : int
     174           0 : onion_skin_server_handshake(int type,
     175             :                       const uint8_t *onion_skin, size_t onionskin_len,
     176             :                       const server_onion_keys_t *keys,
     177             :                       uint8_t *reply_out,
     178             :                       uint8_t *keys_out, size_t keys_out_len,
     179             :                       uint8_t *rend_nonce_out)
     180             : {
     181           0 :   int r = -1;
     182             : 
     183           0 :   switch (type) {
     184           0 :   case ONION_HANDSHAKE_TYPE_TAP:
     185           0 :     if (onionskin_len != TAP_ONIONSKIN_CHALLENGE_LEN)
     186             :       return -1;
     187           0 :     if (onion_skin_TAP_server_handshake((const char*)onion_skin,
     188           0 :                                         keys->onion_key, keys->last_onion_key,
     189             :                                         (char*)reply_out,
     190             :                                         (char*)keys_out, keys_out_len)<0)
     191             :       return -1;
     192           0 :     r = TAP_ONIONSKIN_REPLY_LEN;
     193           0 :     memcpy(rend_nonce_out, reply_out+DH1024_KEY_LEN, DIGEST_LEN);
     194             :     break;
     195           0 :   case ONION_HANDSHAKE_TYPE_FAST:
     196           0 :     if (onionskin_len != CREATE_FAST_LEN)
     197             :       return -1;
     198           0 :     if (fast_server_handshake(onion_skin, reply_out, keys_out, keys_out_len)<0)
     199             :       return -1;
     200           0 :     r = CREATED_FAST_LEN;
     201           0 :     memcpy(rend_nonce_out, reply_out+DIGEST_LEN, DIGEST_LEN);
     202             :     break;
     203           0 :   case ONION_HANDSHAKE_TYPE_NTOR:
     204           0 :     if (onionskin_len < NTOR_ONIONSKIN_LEN)
     205             :       return -1;
     206             :     {
     207           0 :       size_t keys_tmp_len = keys_out_len + DIGEST_LEN;
     208           0 :       tor_assert(keys_tmp_len <= MAX_KEYS_TMP_LEN);
     209           0 :       uint8_t keys_tmp[MAX_KEYS_TMP_LEN];
     210             : 
     211           0 :       if (onion_skin_ntor_server_handshake(
     212           0 :                                    onion_skin, keys->curve25519_key_map,
     213           0 :                                    keys->junk_keypair,
     214           0 :                                    keys->my_identity,
     215             :                                    reply_out, keys_tmp, keys_tmp_len)<0) {
     216             :         /* no need to memwipe here, since the output will never be used */
     217           0 :         return -1;
     218             :       }
     219             : 
     220           0 :       memcpy(keys_out, keys_tmp, keys_out_len);
     221           0 :       memcpy(rend_nonce_out, keys_tmp+keys_out_len, DIGEST_LEN);
     222           0 :       memwipe(keys_tmp, 0, sizeof(keys_tmp));
     223           0 :       r = NTOR_REPLY_LEN;
     224             :     }
     225           0 :     break;
     226           0 :   default:
     227             :     /* LCOV_EXCL_START
     228             :      * We should have rejected this far before this point */
     229             :     log_warn(LD_BUG, "called with unknown handshake state type %d", type);
     230             :     tor_fragile_assert();
     231             :     return -1;
     232             :     /* LCOV_EXCL_STOP */
     233             :   }
     234             : 
     235             :   return r;
     236             : }
     237             : 
     238             : /** Perform the final (client-side) step of a circuit-creation handshake of
     239             :  * type <b>type</b>, using our state in <b>handshake_state</b> and the
     240             :  * server's response in <b>reply</b>. On success, generate <b>keys_out_len</b>
     241             :  * bytes worth of key material in <b>keys_out_len</b>, set
     242             :  * <b>rend_authenticator_out</b> to the "KH" field that can be used to
     243             :  * establish introduction points at this hop, and return 0. On failure,
     244             :  * return -1, and set *msg_out to an error message if this is worth
     245             :  * complaining to the user about. */
     246             : int
     247           0 : onion_skin_client_handshake(int type,
     248             :                       const onion_handshake_state_t *handshake_state,
     249             :                       const uint8_t *reply, size_t reply_len,
     250             :                       uint8_t *keys_out, size_t keys_out_len,
     251             :                       uint8_t *rend_authenticator_out,
     252             :                       const char **msg_out)
     253             : {
     254           0 :   if (handshake_state->tag != type)
     255             :     return -1;
     256             : 
     257           0 :   switch (type) {
     258           0 :   case ONION_HANDSHAKE_TYPE_TAP:
     259           0 :     if (reply_len != TAP_ONIONSKIN_REPLY_LEN) {
     260           0 :       if (msg_out)
     261           0 :         *msg_out = "TAP reply was not of the correct length.";
     262           0 :       return -1;
     263             :     }
     264           0 :     if (onion_skin_TAP_client_handshake(handshake_state->u.tap,
     265             :                                         (const char*)reply,
     266             :                                         (char *)keys_out, keys_out_len,
     267             :                                         msg_out) < 0)
     268             :       return -1;
     269             : 
     270           0 :     memcpy(rend_authenticator_out, reply+DH1024_KEY_LEN, DIGEST_LEN);
     271             : 
     272           0 :     return 0;
     273           0 :   case ONION_HANDSHAKE_TYPE_FAST:
     274           0 :     if (reply_len != CREATED_FAST_LEN) {
     275           0 :       if (msg_out)
     276           0 :         *msg_out = "TAP reply was not of the correct length.";
     277           0 :       return -1;
     278             :     }
     279           0 :     if (fast_client_handshake(handshake_state->u.fast, reply,
     280             :                               keys_out, keys_out_len, msg_out) < 0)
     281             :       return -1;
     282             : 
     283           0 :     memcpy(rend_authenticator_out, reply+DIGEST_LEN, DIGEST_LEN);
     284           0 :     return 0;
     285           0 :   case ONION_HANDSHAKE_TYPE_NTOR:
     286           0 :     if (reply_len < NTOR_REPLY_LEN) {
     287           0 :       if (msg_out)
     288           0 :         *msg_out = "ntor reply was not of the correct length.";
     289           0 :       return -1;
     290             :     }
     291             :     {
     292           0 :       size_t keys_tmp_len = keys_out_len + DIGEST_LEN;
     293           0 :       uint8_t *keys_tmp = tor_malloc(keys_tmp_len);
     294           0 :       if (onion_skin_ntor_client_handshake(handshake_state->u.ntor,
     295             :                                         reply,
     296             :                                         keys_tmp, keys_tmp_len, msg_out) < 0) {
     297           0 :         tor_free(keys_tmp);
     298           0 :         return -1;
     299             :       }
     300           0 :       memcpy(keys_out, keys_tmp, keys_out_len);
     301           0 :       memcpy(rend_authenticator_out, keys_tmp + keys_out_len, DIGEST_LEN);
     302           0 :       memwipe(keys_tmp, 0, keys_tmp_len);
     303           0 :       tor_free(keys_tmp);
     304             :     }
     305           0 :     return 0;
     306           0 :   default:
     307           0 :     log_warn(LD_BUG, "called with unknown handshake state type %d", type);
     308           0 :     tor_fragile_assert();
     309             :     return -1;
     310             :   }
     311             : }

Generated by: LCOV version 1.14