prop250: Add unit tests

Signed-off-by: David Goulet <dgoulet@torproject.org>
Signed-off-by: George Kadianakis <desnacked@riseup.net>
This commit is contained in:
David Goulet 2016-05-03 11:42:50 -04:00
parent 727d419a9d
commit 39be8af709
11 changed files with 1449 additions and 9 deletions

View File

@ -1191,8 +1191,8 @@ consensus_is_waiting_for_certs(void)
/** Return the most recent consensus that we have downloaded, or NULL if we
* don't have one. */
networkstatus_t *
networkstatus_get_latest_consensus(void)
MOCK_IMPL(networkstatus_t *,
networkstatus_get_latest_consensus,(void))
{
return current_consensus;
}
@ -1214,8 +1214,8 @@ networkstatus_get_latest_consensus_by_flavor,(consensus_flavor_t f))
/** Return the most recent consensus that we have downloaded, or NULL if it is
* no longer live. */
networkstatus_t *
networkstatus_get_live_consensus(time_t now)
MOCK_IMPL(networkstatus_t *,
networkstatus_get_live_consensus,(time_t now))
{
if (current_consensus &&
current_consensus->valid_after <= now &&

View File

@ -64,10 +64,10 @@ void update_certificate_downloads(time_t now);
int consensus_is_waiting_for_certs(void);
int client_would_use_router(const routerstatus_t *rs, time_t now,
const or_options_t *options);
networkstatus_t *networkstatus_get_latest_consensus(void);
MOCK_DECL(networkstatus_t *,networkstatus_get_latest_consensus,(void));
MOCK_DECL(networkstatus_t *,networkstatus_get_latest_consensus_by_flavor,
(consensus_flavor_t f));
networkstatus_t *networkstatus_get_live_consensus(time_t now);
MOCK_DECL(networkstatus_t *, networkstatus_get_live_consensus,(time_t now));
networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now,
int flavor);
MOCK_DECL(int, networkstatus_consensus_is_bootstrapping,(time_t now));

View File

@ -1291,3 +1291,22 @@ sr_state_init(int save_to_disk, int read_from_disk)
error:
return -1;
}
#ifdef TOR_UNIT_TESTS
/* Set the current phase of the protocol. Used only by unit tests. */
void
set_sr_phase(sr_phase_t phase)
{
tor_assert(sr_state);
sr_state->phase = phase;
}
/* Get the SR state. Used only by unit tests */
sr_state_t *
get_sr_state(void)
{
return sr_state;
}
#endif /* TOR_UNIT_TESTS */

View File

@ -135,4 +135,11 @@ STATIC int is_phase_transition(sr_phase_t next_phase);
#endif /* SHARED_RANDOM_STATE_PRIVATE */
#ifdef TOR_UNIT_TESTS
STATIC void set_sr_phase(sr_phase_t phase);
STATIC sr_state_t *get_sr_state(void);
#endif /* TOR_UNIT_TESTS */
#endif /* TOR_SHARED_RANDOM_STATE_H */

View File

@ -116,6 +116,7 @@ src_test_test_SOURCES = \
src/test/test_routerlist.c \
src/test/test_routerset.c \
src/test/test_scheduler.c \
src/test/test_shared_random.c \
src/test/test_socks.c \
src/test/test_status.c \
src/test/test_threads.c \

View File

@ -0,0 +1,71 @@
# This is a reference implementation of the SRV calculation for prop250. We
# use it to generate a test vector for the test_sr_compute_srv() unittest.
# (./test shared-random/sr_compute_srv)
#
# Here is the SRV computation formula:
#
# HASHED_REVEALS = H(ID_a | R_a | ID_b | R_b | ..)
#
# SRV = SHA3-256("shared-random" | INT_8(reveal_num) | INT_4(version) |
# HASHED_REVEALS | previous_SRV)
#
import sys
import hashlib
import struct
# Python 3.6+, the SHA3 is available in hashlib natively. Else this requires
# the pysha3 package (pip install pysha3).
if sys.version_info < (3, 6):
import sha3
# Test vector to make sure the right sha3 version will be used. pysha3 < 1.0
# used the old Keccak implementation. During the finalization of SHA3, NIST
# changed the delimiter suffix from 0x01 to 0x06. The Keccak sponge function
# stayed the same. pysha3 1.0 provides the previous Keccak hash, too.
TEST_VALUE = "e167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51"
if TEST_VALUE != sha3.sha3_256(b"Hello World").hexdigest():
print("pysha3 version is < 1.0. Please install from:")
print("https://github.com/tiran/pysha3https://github.com/tiran/pysha3")
sys.exit(1)
# In this example, we use three reveal values.
reveal_num = 3
version = 1
# We set directly the ascii value because memset(buf, 'A', 20) makes it to 20
# times "41" in the final string.
# Identity and reveal value of dirauth a
ID_a = 20 * "41" # RSA identity of 40 base16 bytes.
R_a = 56 * 'A' # 56 base64 characters
# Identity and reveal value of dirauth b
ID_b = 20 * "42" # RSA identity of 40 base16 bytes.
R_b = 56 * 'B' # 56 base64 characters
# Identity and reveal value of dirauth c
ID_c = 20 * "43" # RSA identity of 40 base16 bytes.
R_c = 56 * 'C' # 56 base64 characters
# Concatenate them all together and hash them to form HASHED_REVEALS.
REVEALS = (ID_a + R_a + ID_b + R_b + ID_c + R_c).encode()
hashed_reveals_object = hashlib.sha3_256(REVEALS)
hashed_reveals = hashed_reveals_object.digest()
previous_SRV = (32 * 'Z').encode()
# Now form the message.
#srv_msg = struct.pack('13sQL256ss', "shared-random", reveal_num, version,
# hashed_reveals, previous_SRV)
invariant_token = b"shared-random"
srv_msg = invariant_token + \
struct.pack('!QL', reveal_num, version) + \
hashed_reveals + \
previous_SRV
# Now calculate the HMAC
srv = hashlib.sha3_256(srv_msg)
print("%s" % srv.hexdigest().upper())
# 2A9B1D6237DAB312A40F575DA85C147663E7ED3F80E9555395F15B515C74253D

View File

@ -1170,6 +1170,7 @@ struct testgroup_t testgroups[] = {
{ "routerset/" , routerset_tests },
{ "scheduler/", scheduler_tests },
{ "socks/", socks_tests },
{ "shared-random/", sr_tests },
{ "status/" , status_tests },
{ "tortls/", tortls_tests },
{ "util/", util_tests },

View File

@ -225,6 +225,7 @@ extern struct testcase_t util_format_tests[];
extern struct testcase_t util_process_tests[];
extern struct testcase_t dns_tests[];
extern struct testcase_t handle_tests[];
extern struct testcase_t sr_tests[];
extern struct testcase_t slow_crypto_tests[];
extern struct testcase_t slow_util_tests[];

View File

@ -30,6 +30,7 @@
#include "routerlist.h"
#include "routerparse.h"
#include "routerset.h"
#include "shared_random_state.h"
#include "test.h"
#include "test_dir_common.h"
#include "torcert.h"
@ -1544,6 +1545,43 @@ test_dir_param_voting(void *arg)
return;
}
static void
test_dir_param_voting_lookup(void *arg)
{
(void)arg;
smartlist_t *lst = smartlist_new();
smartlist_split_string(lst,
"moomin=9 moomin=10 moomintroll=5 fred "
"jack= electricity=sdk opa=6z abc=9 abcd=99",
NULL, 0, 0);
tt_int_op(1000,
OP_EQ, dirvote_get_intermediate_param_value(lst, "ab", 1000));
tt_int_op(9, OP_EQ, dirvote_get_intermediate_param_value(lst, "abc", 1000));
tt_int_op(99, OP_EQ, dirvote_get_intermediate_param_value(lst, "abcd", 1000));
/* moomin appears twice. */
tt_int_op(-100, OP_EQ,
dirvote_get_intermediate_param_value(lst, "moomin", -100));
/* fred and jack are truncated */
tt_int_op(-100, OP_EQ,
dirvote_get_intermediate_param_value(lst, "fred", -100));
tt_int_op(-100, OP_EQ,
dirvote_get_intermediate_param_value(lst, "jack", -100));
/* electricity and opa aren't integers. */
tt_int_op(-100, OP_EQ,
dirvote_get_intermediate_param_value(lst, "electricity", -100));
tt_int_op(-100, OP_EQ,
dirvote_get_intermediate_param_value(lst, "opa", -100));
done:
SMARTLIST_FOREACH(lst, char *, cp, tor_free(cp));
smartlist_free(lst);
}
#undef dirvote_compute_params
/** Helper: Test that two networkstatus_voter_info_t do in fact represent the
* same voting authority, and that they do in fact have all the same
* information. */
@ -1788,6 +1826,15 @@ test_routerstatus_for_v3ns(routerstatus_t *rs, time_t now)
return;
}
static authority_cert_t *mock_cert;
static authority_cert_t *
get_my_v3_authority_cert_m(void)
{
tor_assert(mock_cert);
return mock_cert;
}
/** Run a unit tests for generating and parsing networkstatuses, with
* the supply test fns. */
static void
@ -1831,10 +1878,30 @@ test_a_networkstatus(
tt_assert(rs_test);
tt_assert(vrs_test);
tt_assert(!dir_common_authority_pk_init(&cert1, &cert2, &cert3,
&sign_skey_1, &sign_skey_2,
&sign_skey_3));
MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
/* Parse certificates and keys. */
cert1 = mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
tt_assert(cert1);
cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2, NULL);
tt_assert(cert2);
cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3, NULL);
tt_assert(cert3);
sign_skey_1 = crypto_pk_new();
sign_skey_2 = crypto_pk_new();
sign_skey_3 = crypto_pk_new();
sign_skey_leg1 = pk_generate(4);
sr_state_init(0, 0);
tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_1,
AUTHORITY_SIGNKEY_1, -1));
tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_2,
AUTHORITY_SIGNKEY_2, -1));
tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_3,
AUTHORITY_SIGNKEY_3, -1));
tt_assert(!crypto_pk_cmp_keys(sign_skey_1, cert1->signing_key));
tt_assert(!crypto_pk_cmp_keys(sign_skey_2, cert2->signing_key));
tt_assert(!dir_common_construct_vote_1(&vote, cert1, sign_skey_1, vrs_gen,
&v1, &n_vrs, now, 1));

View File

@ -19,13 +19,24 @@
#include "networkstatus.h"
#include "nodelist.h"
#include "policies.h"
#include "router.h"
#include "routerlist.h"
#include "routerparse.h"
#include "shared_random.h"
#include "test.h"
#include "test_dir_common.h"
void construct_consensus(char **consensus_text_md);
static authority_cert_t *mock_cert;
static authority_cert_t *
get_my_v3_authority_cert_m(void)
{
tor_assert(mock_cert);
return mock_cert;
}
/* 4 digests + 3 sep + pre + post + NULL */
static char output[4*BASE64_DIGEST256_LEN+3+2+2+1];
@ -227,6 +238,12 @@ test_router_pick_directory_server_impl(void *arg)
tt_assert(networkstatus_consensus_is_bootstrapping(now + 2*24*60*60));
tt_assert(networkstatus_consensus_is_bootstrapping(now - 2*24*60*60));
/* Init SR subsystem. */
MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
sr_init(0);
UNMOCK(get_my_v3_authority_cert);
/* No consensus available, fail early */
rs = router_pick_directory_server_impl(V3_DIRINFO, (const int) 0, NULL);
tt_assert(rs == NULL);

File diff suppressed because it is too large Load Diff