LCOV - code coverage report
Current view: top level - core/crypto - relay_crypto.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 126 152 82.9 %
Date: 2021-11-24 03:28:48 Functions: 10 11 90.9 %

          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 relay_crypto.h
       9             :  * @brief Header for relay_crypto.c
      10             :  **/
      11             : 
      12             : #include "core/or/or.h"
      13             : #include "core/or/circuitlist.h"
      14             : #include "core/or/crypt_path.h"
      15             : #include "app/config/config.h"
      16             : #include "lib/crypt_ops/crypto_cipher.h"
      17             : #include "lib/crypt_ops/crypto_util.h"
      18             : #include "core/crypto/hs_ntor.h" // for HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN
      19             : #include "core/or/relay.h"
      20             : #include "core/crypto/relay_crypto.h"
      21             : #include "core/or/sendme.h"
      22             : 
      23             : #include "core/or/cell_st.h"
      24             : #include "core/or/or_circuit_st.h"
      25             : #include "core/or/origin_circuit_st.h"
      26             : 
      27             : /** Update digest from the payload of cell. Assign integrity part to
      28             :  * cell.
      29             :  */
      30             : void
      31         100 : relay_set_digest(crypto_digest_t *digest, cell_t *cell)
      32             : {
      33         100 :   char integrity[4];
      34         100 :   relay_header_t rh;
      35             : 
      36         100 :   crypto_digest_add_bytes(digest, (char*)cell->payload, CELL_PAYLOAD_SIZE);
      37         100 :   crypto_digest_get_digest(digest, integrity, 4);
      38             : //  log_fn(LOG_DEBUG,"Putting digest of %u %u %u %u into relay cell.",
      39             : //    integrity[0], integrity[1], integrity[2], integrity[3]);
      40         100 :   relay_header_unpack(&rh, cell->payload);
      41         100 :   memcpy(rh.integrity, integrity, 4);
      42         100 :   relay_header_pack(cell->payload, &rh);
      43         100 : }
      44             : 
      45             : /** Does the digest for this circuit indicate that this cell is for us?
      46             :  *
      47             :  * Update digest from the payload of cell (with the integrity part set
      48             :  * to 0). If the integrity part is valid, return 1, else restore digest
      49             :  * and cell to their original state and return 0.
      50             :  */
      51             : static int
      52         100 : relay_digest_matches(crypto_digest_t *digest, cell_t *cell)
      53             : {
      54         100 :   uint32_t received_integrity, calculated_integrity;
      55         100 :   relay_header_t rh;
      56         100 :   crypto_digest_checkpoint_t backup_digest;
      57             : 
      58         100 :   crypto_digest_checkpoint(&backup_digest, digest);
      59             : 
      60         100 :   relay_header_unpack(&rh, cell->payload);
      61         100 :   memcpy(&received_integrity, rh.integrity, 4);
      62         100 :   memset(rh.integrity, 0, 4);
      63         100 :   relay_header_pack(cell->payload, &rh);
      64             : 
      65             : //  log_fn(LOG_DEBUG,"Reading digest of %u %u %u %u from relay cell.",
      66             : //    received_integrity[0], received_integrity[1],
      67             : //    received_integrity[2], received_integrity[3]);
      68             : 
      69         100 :   crypto_digest_add_bytes(digest, (char*) cell->payload, CELL_PAYLOAD_SIZE);
      70         100 :   crypto_digest_get_digest(digest, (char*) &calculated_integrity, 4);
      71             : 
      72         100 :   int rv = 1;
      73             : 
      74         100 :   if (calculated_integrity != received_integrity) {
      75             : //    log_fn(LOG_INFO,"Recognized=0 but bad digest. Not recognizing.");
      76             : // (%d vs %d).", received_integrity, calculated_integrity);
      77             :     /* restore digest to its old form */
      78           0 :     crypto_digest_restore(digest, &backup_digest);
      79             :     /* restore the relay header */
      80           0 :     memcpy(rh.integrity, &received_integrity, 4);
      81           0 :     relay_header_pack(cell->payload, &rh);
      82           0 :     rv = 0;
      83             :   }
      84             : 
      85         100 :   memwipe(&backup_digest, 0, sizeof(backup_digest));
      86         100 :   return rv;
      87             : }
      88             : 
      89             : /** Apply <b>cipher</b> to CELL_PAYLOAD_SIZE bytes of <b>in</b>
      90             :  * (in place).
      91             :  *
      92             :  * Note that we use the same operation for encrypting and for decrypting.
      93             :  */
      94             : void
      95         600 : relay_crypt_one_payload(crypto_cipher_t *cipher, uint8_t *in)
      96             : {
      97         600 :   crypto_cipher_crypt_inplace(cipher, (char*) in, CELL_PAYLOAD_SIZE);
      98         600 : }
      99             : 
     100             : /** Return the sendme_digest within the <b>crypto</b> object. */
     101             : uint8_t *
     102          10 : relay_crypto_get_sendme_digest(relay_crypto_t *crypto)
     103             : {
     104          10 :   tor_assert(crypto);
     105          10 :   return crypto->sendme_digest;
     106             : }
     107             : 
     108             : /** Record the cell digest, indicated by is_foward_digest or not, as the
     109             :  * SENDME cell digest. */
     110             : void
     111           0 : relay_crypto_record_sendme_digest(relay_crypto_t *crypto,
     112             :                                   bool is_foward_digest)
     113             : {
     114           0 :   struct crypto_digest_t *digest;
     115             : 
     116           0 :   tor_assert(crypto);
     117             : 
     118           0 :   digest = crypto->b_digest;
     119           0 :   if (is_foward_digest) {
     120           0 :     digest = crypto->f_digest;
     121             :   }
     122             : 
     123           0 :   crypto_digest_get_digest(digest, (char *) crypto->sendme_digest,
     124             :                            sizeof(crypto->sendme_digest));
     125           0 : }
     126             : 
     127             : /** Do the appropriate en/decryptions for <b>cell</b> arriving on
     128             :  * <b>circ</b> in direction <b>cell_direction</b>.
     129             :  *
     130             :  * If cell_direction == CELL_DIRECTION_IN:
     131             :  *   - If we're at the origin (we're the OP), for hops 1..N,
     132             :  *     decrypt cell. If recognized, stop.
     133             :  *   - Else (we're not the OP), encrypt one hop. Cell is not recognized.
     134             :  *
     135             :  * If cell_direction == CELL_DIRECTION_OUT:
     136             :  *   - decrypt one hop. Check if recognized.
     137             :  *
     138             :  * If cell is recognized, set *recognized to 1, and set
     139             :  * *layer_hint to the hop that recognized it.
     140             :  *
     141             :  * Return -1 to indicate that we should mark the circuit for close,
     142             :  * else return 0.
     143             :  */
     144             : int
     145         300 : relay_decrypt_cell(circuit_t *circ, cell_t *cell,
     146             :                    cell_direction_t cell_direction,
     147             :                    crypt_path_t **layer_hint, char *recognized)
     148             : {
     149         300 :   relay_header_t rh;
     150             : 
     151         300 :   tor_assert(circ);
     152         300 :   tor_assert(cell);
     153         300 :   tor_assert(recognized);
     154         300 :   tor_assert(cell_direction == CELL_DIRECTION_IN ||
     155             :              cell_direction == CELL_DIRECTION_OUT);
     156             : 
     157         300 :   if (cell_direction == CELL_DIRECTION_IN) {
     158         150 :     if (CIRCUIT_IS_ORIGIN(circ)) { /* We're at the beginning of the circuit.
     159             :                                     * We'll want to do layered decrypts. */
     160          50 :       crypt_path_t *thishop, *cpath = TO_ORIGIN_CIRCUIT(circ)->cpath;
     161          50 :       thishop = cpath;
     162          50 :       if (thishop->state != CPATH_STATE_OPEN) {
     163           0 :         log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
     164             :                "Relay cell before first created cell? Closing.");
     165           0 :         return -1;
     166             :       }
     167         150 :       do { /* Remember: cpath is in forward order, that is, first hop first. */
     168         150 :         tor_assert(thishop);
     169             : 
     170             :         /* decrypt one layer */
     171         150 :         cpath_crypt_cell(thishop, cell->payload, true);
     172             : 
     173         150 :         relay_header_unpack(&rh, cell->payload);
     174         150 :         if (rh.recognized == 0) {
     175             :           /* it's possibly recognized. have to check digest to be sure. */
     176          50 :           if (relay_digest_matches(cpath_get_incoming_digest(thishop), cell)) {
     177          50 :             *recognized = 1;
     178          50 :             *layer_hint = thishop;
     179          50 :             return 0;
     180             :           }
     181             :         }
     182             : 
     183         100 :         thishop = thishop->next;
     184         100 :       } while (thishop != cpath && thishop->state == CPATH_STATE_OPEN);
     185           0 :       log_fn(LOG_PROTOCOL_WARN, LD_OR,
     186             :              "Incoming cell at client not recognized. Closing.");
     187           0 :       return -1;
     188             :     } else {
     189         100 :       relay_crypto_t *crypto = &TO_OR_CIRCUIT(circ)->crypto;
     190             :       /* We're in the middle. Encrypt one layer. */
     191         100 :       relay_crypt_one_payload(crypto->b_crypto, cell->payload);
     192             :     }
     193             :   } else /* cell_direction == CELL_DIRECTION_OUT */ {
     194             :     /* We're in the middle. Decrypt one layer. */
     195         150 :     relay_crypto_t *crypto = &TO_OR_CIRCUIT(circ)->crypto;
     196             : 
     197         150 :     relay_crypt_one_payload(crypto->f_crypto, cell->payload);
     198             : 
     199         150 :     relay_header_unpack(&rh, cell->payload);
     200         150 :     if (rh.recognized == 0) {
     201             :       /* it's possibly recognized. have to check digest to be sure. */
     202          50 :       if (relay_digest_matches(crypto->f_digest, cell)) {
     203          50 :         *recognized = 1;
     204          50 :         return 0;
     205             :       }
     206             :     }
     207             :   }
     208             :   return 0;
     209             : }
     210             : 
     211             : /**
     212             :  * Encrypt a cell <b>cell</b> that we are creating, and sending outbound on
     213             :  * <b>circ</b> until the hop corresponding to <b>layer_hint</b>.
     214             :  *
     215             :  * The integrity field and recognized field of <b>cell</b>'s relay headers
     216             :  * must be set to zero.
     217             :  */
     218             : void
     219          50 : relay_encrypt_cell_outbound(cell_t *cell,
     220             :                             origin_circuit_t *circ,
     221             :                             crypt_path_t *layer_hint)
     222             : {
     223          50 :   crypt_path_t *thishop; /* counter for repeated crypts */
     224          50 :   cpath_set_cell_forward_digest(layer_hint, cell);
     225             : 
     226             :   /* Record cell digest as the SENDME digest if need be. */
     227          50 :   sendme_record_sending_cell_digest(TO_CIRCUIT(circ), layer_hint);
     228             : 
     229          50 :   thishop = layer_hint;
     230             :   /* moving from farthest to nearest hop */
     231         150 :   do {
     232         150 :     tor_assert(thishop);
     233         150 :     log_debug(LD_OR,"encrypting a layer of the relay cell.");
     234         150 :     cpath_crypt_cell(thishop, cell->payload, false);
     235             : 
     236         150 :     thishop = thishop->prev;
     237         150 :   } while (thishop != circ->cpath->prev);
     238          50 : }
     239             : 
     240             : /**
     241             :  * Encrypt a cell <b>cell</b> that we are creating, and sending on
     242             :  * <b>circuit</b> to the origin.
     243             :  *
     244             :  * The integrity field and recognized field of <b>cell</b>'s relay headers
     245             :  * must be set to zero.
     246             :  */
     247             : void
     248          50 : relay_encrypt_cell_inbound(cell_t *cell,
     249             :                            or_circuit_t *or_circ)
     250             : {
     251          50 :   relay_set_digest(or_circ->crypto.b_digest, cell);
     252             : 
     253             :   /* Record cell digest as the SENDME digest if need be. */
     254          50 :   sendme_record_sending_cell_digest(TO_CIRCUIT(or_circ), NULL);
     255             : 
     256             :   /* encrypt one layer */
     257          50 :   relay_crypt_one_payload(or_circ->crypto.b_crypto, cell->payload);
     258          50 : }
     259             : 
     260             : /**
     261             :  * Release all storage held inside <b>crypto</b>, but do not free
     262             :  * <b>crypto</b> itself: it lives inside another object.
     263             :  */
     264             : void
     265         145 : relay_crypto_clear(relay_crypto_t *crypto)
     266             : {
     267         145 :   if (BUG(!crypto))
     268           0 :     return;
     269         145 :   crypto_cipher_free(crypto->f_crypto);
     270         145 :   crypto_cipher_free(crypto->b_crypto);
     271         145 :   crypto_digest_free(crypto->f_digest);
     272         145 :   crypto_digest_free(crypto->b_digest);
     273             : }
     274             : 
     275             : /** Initialize <b>crypto</b> from the key material in key_data.
     276             :  *
     277             :  * If <b>is_hs_v3</b> is set, this cpath will be used for next gen hidden
     278             :  * service circuits and <b>key_data</b> must be at least
     279             :  * HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN bytes in length.
     280             :  *
     281             :  * If <b>is_hs_v3</b> is not set, key_data must contain CPATH_KEY_MATERIAL_LEN
     282             :  * bytes, which are used as follows:
     283             :  *   - 20 to initialize f_digest
     284             :  *   - 20 to initialize b_digest
     285             :  *   - 16 to key f_crypto
     286             :  *   - 16 to key b_crypto
     287             :  *
     288             :  * (If 'reverse' is true, then f_XX and b_XX are swapped.)
     289             :  *
     290             :  * Return 0 if init was successful, else -1 if it failed.
     291             :  */
     292             : int
     293          64 : relay_crypto_init(relay_crypto_t *crypto,
     294             :                   const char *key_data, size_t key_data_len,
     295             :                   int reverse, int is_hs_v3)
     296             : {
     297          64 :   crypto_digest_t *tmp_digest;
     298          64 :   crypto_cipher_t *tmp_crypto;
     299          64 :   size_t digest_len = 0;
     300          64 :   size_t cipher_key_len = 0;
     301             : 
     302          64 :   tor_assert(crypto);
     303          64 :   tor_assert(key_data);
     304          64 :   tor_assert(!(crypto->f_crypto || crypto->b_crypto ||
     305             :              crypto->f_digest || crypto->b_digest));
     306             : 
     307             :   /* Basic key size validation */
     308          64 :   if (is_hs_v3 && BUG(key_data_len != HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN)) {
     309           0 :     goto err;
     310          64 :   } else if (!is_hs_v3 && BUG(key_data_len != CPATH_KEY_MATERIAL_LEN)) {
     311           0 :     goto err;
     312             :   }
     313             : 
     314             :   /* If we are using this crypto for next gen onion services use SHA3-256,
     315             :      otherwise use good ol' SHA1 */
     316          64 :   if (is_hs_v3) {
     317           5 :     digest_len = DIGEST256_LEN;
     318           5 :     cipher_key_len = CIPHER256_KEY_LEN;
     319           5 :     crypto->f_digest = crypto_digest256_new(DIGEST_SHA3_256);
     320           5 :     crypto->b_digest = crypto_digest256_new(DIGEST_SHA3_256);
     321             :   } else {
     322          59 :     digest_len = DIGEST_LEN;
     323          59 :     cipher_key_len = CIPHER_KEY_LEN;
     324          59 :     crypto->f_digest = crypto_digest_new();
     325          59 :     crypto->b_digest = crypto_digest_new();
     326             :   }
     327             : 
     328          64 :   tor_assert(digest_len != 0);
     329          64 :   tor_assert(cipher_key_len != 0);
     330          64 :   const int cipher_key_bits = (int) cipher_key_len * 8;
     331             : 
     332          64 :   crypto_digest_add_bytes(crypto->f_digest, key_data, digest_len);
     333          64 :   crypto_digest_add_bytes(crypto->b_digest, key_data+digest_len, digest_len);
     334             : 
     335          64 :   crypto->f_crypto = crypto_cipher_new_with_bits(key_data+(2*digest_len),
     336             :                                                 cipher_key_bits);
     337          64 :   if (!crypto->f_crypto) {
     338           0 :     log_warn(LD_BUG,"Forward cipher initialization failed.");
     339           0 :     goto err;
     340             :   }
     341             : 
     342         128 :   crypto->b_crypto = crypto_cipher_new_with_bits(
     343          64 :                                         key_data+(2*digest_len)+cipher_key_len,
     344             :                                         cipher_key_bits);
     345          64 :   if (!crypto->b_crypto) {
     346           0 :     log_warn(LD_BUG,"Backward cipher initialization failed.");
     347           0 :     goto err;
     348             :   }
     349             : 
     350          64 :   if (reverse) {
     351           3 :     tmp_digest = crypto->f_digest;
     352           3 :     crypto->f_digest = crypto->b_digest;
     353           3 :     crypto->b_digest = tmp_digest;
     354           3 :     tmp_crypto = crypto->f_crypto;
     355           3 :     crypto->f_crypto = crypto->b_crypto;
     356           3 :     crypto->b_crypto = tmp_crypto;
     357             :   }
     358             : 
     359             :   return 0;
     360           0 :  err:
     361           0 :   relay_crypto_clear(crypto);
     362           0 :   return -1;
     363             : }
     364             : 
     365             : /** Assert that <b>crypto</b> is valid and set. */
     366             : void
     367           1 : relay_crypto_assert_ok(const relay_crypto_t *crypto)
     368             : {
     369           1 :   tor_assert(crypto->f_crypto);
     370           1 :   tor_assert(crypto->b_crypto);
     371           1 :   tor_assert(crypto->f_digest);
     372           1 :   tor_assert(crypto->b_digest);
     373           1 : }

Generated by: LCOV version 1.14