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:
parent
727d419a9d
commit
39be8af709
|
@ -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 &&
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
|
@ -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 },
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue