diff options
author | Nick Mathewson <nickm@torproject.org> | 2018-03-17 11:23:05 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2018-03-24 13:49:08 -0400 |
commit | 7db4d0c55f1e0146ecd0207f788075b672411cc2 (patch) | |
tree | 7065f8bb6976c7b7c5878458d25927734f8ef505 /src/test/test_relaycrypt.c | |
parent | 5ecad6c95d5e8e9a0abe5c86b5f8f066cc7a8f1c (diff) | |
download | tor-7db4d0c55f1e0146ecd0207f788075b672411cc2.tar.gz tor-7db4d0c55f1e0146ecd0207f788075b672411cc2.zip |
Basic unit tests for relay_crypto.c
These tests handle incoming and outgoing cells on a three-hop
circuit, and make sure that the crypto works end-to-end. They don't
yet test spec conformance, leaky-pipe, or various error cases.
Diffstat (limited to 'src/test/test_relaycrypt.c')
-rw-r--r-- | src/test/test_relaycrypt.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/src/test/test_relaycrypt.c b/src/test/test_relaycrypt.c new file mode 100644 index 0000000000..eba9897184 --- /dev/null +++ b/src/test/test_relaycrypt.c @@ -0,0 +1,184 @@ +/* Copyright 2001-2004 Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "or.h" +#include "circuitbuild.h" +#define CIRCUITLIST_PRIVATE +#include "circuitlist.h" +#include "relay.h" +#include "relay_crypto.h" +#include "test.h" + +static const char KEY_MATERIAL[3][CPATH_KEY_MATERIAL_LEN] = { + " 'My public key is in this signed x509 object', said Tom assertively.", + "'Let's chart the pedal phlanges in the tomb', said Tom cryptographically", + " 'Segmentation fault bugs don't _just happen_', said Tom seethingly.", +}; + +typedef struct testing_circuitset_t { + or_circuit_t *or_circ[3]; + origin_circuit_t *origin_circ; +} testing_circuitset_t; + +static int testing_circuitset_teardown(const struct testcase_t *testcase, + void *ptr); + +static void * +testing_circuitset_setup(const struct testcase_t *testcase) +{ + testing_circuitset_t *cs = tor_malloc_zero(sizeof(testing_circuitset_t)); + int i; + + for (i=0; i<3; ++i) { + cs->or_circ[i] = or_circuit_new(0, NULL); + tt_int_op(0, OP_EQ, + relay_crypto_init(&cs->or_circ[i]->crypto, + KEY_MATERIAL[i], sizeof(KEY_MATERIAL[i]), + 0, 0)); + } + + cs->origin_circ = origin_circuit_new(); + cs->origin_circ->base_.purpose = CIRCUIT_PURPOSE_C_GENERAL; + for (i=0; i<3; ++i) { + crypt_path_t *hop = tor_malloc_zero(sizeof(*hop)); + relay_crypto_init(&hop->crypto, KEY_MATERIAL[i], sizeof(KEY_MATERIAL[i]), + 0, 0); + hop->state = CPATH_STATE_OPEN; + onion_append_to_cpath(&cs->origin_circ->cpath, hop); + tt_ptr_op(hop, OP_EQ, cs->origin_circ->cpath->prev); + } + + return cs; + done: + testing_circuitset_teardown(testcase, cs); + return NULL; +} + +static int +testing_circuitset_teardown(const struct testcase_t *testcase, void *ptr) +{ + (void)testcase; + testing_circuitset_t *cs = ptr; + int i; + for (i=0; i<3; ++i) { + circuit_free_(TO_CIRCUIT(cs->or_circ[i])); + } + circuit_free_(TO_CIRCUIT(cs->origin_circ)); + tor_free(cs); + return 1; +} + +static const struct testcase_setup_t relaycrypt_setup = { + testing_circuitset_setup, testing_circuitset_teardown +}; + +/* Test encrypting a cell to the final hop on a circuit, decrypting it + * at each hop, and recognizing it at the other end. Then do it again + * and again as the state evolves. */ +static void +test_relaycrypt_outbound(void *arg) +{ + testing_circuitset_t *cs = arg; + tt_assert(cs); + + relay_header_t rh; + cell_t orig; + cell_t encrypted; + int i, j; + + for (i = 0; i < 50; ++i) { + crypto_rand((char *)&orig, sizeof(orig)); + + relay_header_unpack(&rh, orig.payload); + rh.recognized = 0; + memset(rh.integrity, 0, sizeof(rh.integrity)); + relay_header_pack(orig.payload, &rh); + + memcpy(&encrypted, &orig, sizeof(orig)); + + /* Encrypt the cell to the last hop */ + relay_encrypt_cell_outbound(&encrypted, cs->origin_circ, + cs->origin_circ->cpath->prev); + + for (j = 0; j < 3; ++j) { + crypt_path_t *layer_hint = NULL; + char recognized = 0; + int r = relay_decrypt_cell(TO_CIRCUIT(cs->or_circ[j]), + &encrypted, + CELL_DIRECTION_OUT, + &layer_hint, &recognized); + tt_int_op(r, OP_EQ, 0); + tt_ptr_op(layer_hint, OP_EQ, NULL); + tt_int_op(recognized != 0, OP_EQ, j == 2); + } + + tt_mem_op(orig.payload, OP_EQ, encrypted.payload, CELL_PAYLOAD_SIZE); + } + + done: + ; +} + +/* As above, but simulate inbound cells from the last hop. */ +static void +test_relaycrypt_inbound(void *arg) +{ + testing_circuitset_t *cs = arg; + tt_assert(cs); + + relay_header_t rh; + cell_t orig; + cell_t encrypted; + int i, j; + + for (i = 0; i < 50; ++i) { + crypto_rand((char *)&orig, sizeof(orig)); + + relay_header_unpack(&rh, orig.payload); + rh.recognized = 0; + memset(rh.integrity, 0, sizeof(rh.integrity)); + relay_header_pack(orig.payload, &rh); + + memcpy(&encrypted, &orig, sizeof(orig)); + + /* Encrypt the cell to the last hop */ + relay_encrypt_cell_inbound(&encrypted, cs->or_circ[2]); + + crypt_path_t *layer_hint = NULL; + char recognized = 0; + int r; + for (j = 1; j >= 0; --j) { + r = relay_decrypt_cell(TO_CIRCUIT(cs->or_circ[j]), + &encrypted, + CELL_DIRECTION_IN, + &layer_hint, &recognized); + tt_int_op(r, OP_EQ, 0); + tt_ptr_op(layer_hint, OP_EQ, NULL); + tt_int_op(recognized, OP_EQ, 0); + } + + relay_decrypt_cell(TO_CIRCUIT(cs->origin_circ), + &encrypted, + CELL_DIRECTION_IN, + &layer_hint, &recognized); + tt_int_op(r, OP_EQ, 0); + tt_int_op(recognized, OP_EQ, 1); + tt_ptr_op(layer_hint, OP_EQ, cs->origin_circ->cpath->prev); + + tt_mem_op(orig.payload, OP_EQ, encrypted.payload, CELL_PAYLOAD_SIZE); + } + done: + ; +} + +#define TEST(name) \ + { # name, test_relaycrypt_ ## name, 0, &relaycrypt_setup, NULL } + +struct testcase_t relaycrypt_tests[] = { + TEST(outbound), + TEST(inbound), + END_OF_TESTCASES +}; + |