/** Run unit tests for the onion handshake code. */ static void test_onion_handshake(void *arg) { /* client-side */ crypto_dh_t *c_dh = NULL; char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN]; char c_keys[40]; /* server-side */ char s_buf[TAP_ONIONSKIN_REPLY_LEN]; char s_keys[40]; int i; /* shared */ crypto_pk_t *pk = NULL, *pk2 = NULL; (void)arg; pk = pk_generate(0); pk2 = pk_generate(1); /* client handshake 1. */ memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN); tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf)); for (i = 1; i <= 3; ++i) { crypto_pk_t *k1, *k2; if (i==1) { /* server handshake: only one key known. */ k1 = pk; k2 = NULL; } else if (i==2) { /* server handshake: try the right key first. */ k1 = pk; k2 = pk2; } else { /* server handshake: try the right key second. */ k1 = pk2; k2 = pk; } memset(s_buf, 0, TAP_ONIONSKIN_REPLY_LEN); memset(s_keys, 0, 40); tt_assert(! onion_skin_TAP_server_handshake(c_buf, k1, k2, s_buf, s_keys, 40)); /* client handshake 2 */ memset(c_keys, 0, 40); tt_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, NULL)); tt_mem_op(c_keys,OP_EQ, s_keys, 40); memset(s_buf, 0, 40); tt_mem_op(c_keys,OP_NE, s_buf, 40); } done: crypto_dh_free(c_dh); crypto_pk_free(pk); crypto_pk_free(pk2); }
static void test_rend_cache_free_all(void *data) { rend_cache_failure_t *failure; rend_cache_entry_t *one; rend_service_descriptor_t *desc_one; (void)data; rend_cache_init(); failure = rend_cache_failure_entry_new(); strmap_set_lc(rend_cache_failure, "foo1", failure); one = tor_malloc_zero(sizeof(rend_cache_entry_t)); desc_one = tor_malloc_zero(sizeof(rend_service_descriptor_t)); one->parsed = desc_one; desc_one->timestamp = time(NULL) + TIME_IN_THE_PAST; desc_one->pk = pk_generate(0); strmap_set_lc(rend_cache, "foo1", one); rend_cache_free_all(); tt_assert(!rend_cache); tt_assert(!rend_cache_v2_dir); tt_assert(!rend_cache_failure); tt_assert(!rend_cache_total_allocation); done: rend_cache_free_all(); }
/* Helper function: Send a well-formed v2 ESTABLISH_INTRO cell to * <b>intro_circ</b>. Return the public key advertised in the cell. */ static crypto_pk_t * helper_establish_intro_v2(or_circuit_t *intro_circ) { crypto_pk_t *key1 = NULL; int retval; uint8_t cell_body[RELAY_PAYLOAD_SIZE]; ssize_t cell_len = 0; char circ_nonce[DIGEST_LEN] = {0}; tt_assert(intro_circ); /* Prepare the circuit for the incoming ESTABLISH_INTRO */ crypto_rand(circ_nonce, sizeof(circ_nonce)); helper_prepare_circ_for_intro(intro_circ, circ_nonce); /* Send legacy establish_intro */ key1 = pk_generate(0); /* Use old circ_nonce why not */ cell_len = rend_service_encode_establish_intro_cell( (char*)cell_body, sizeof(cell_body), key1, circ_nonce); tt_int_op(cell_len, OP_GT, 0); /* Receive legacy establish_intro */ retval = hs_intro_received_establish_intro(intro_circ, cell_body, (size_t) cell_len); tt_int_op(retval, OP_EQ, 0); done: return key1; }
static void test_routerkeys_rsa_ed_crosscert(void *arg) { (void)arg; ed25519_public_key_t ed; crypto_pk_t *rsa = pk_generate(2); uint8_t *cc = NULL; ssize_t cc_len; time_t expires_in = 1470846177; tt_int_op(0, OP_EQ, ed25519_public_from_base64(&ed, "ThisStringCanContainAnythingSoNoKeyHereNowX")); cc_len = tor_make_rsa_ed25519_crosscert(&ed, rsa, expires_in, &cc); tt_int_op(cc_len, OP_GT, 0); tt_int_op(cc_len, OP_GT, 37); /* key, expires, siglen */ tt_mem_op(cc, OP_EQ, ed.pubkey, 32); time_t expires_out = 3600 * ntohl(get_uint32(cc+32)); tt_int_op(expires_out, OP_GE, expires_in); tt_int_op(expires_out, OP_LE, expires_in + 3600); tt_int_op(cc_len, OP_EQ, 37 + get_uint8(cc+36)); tt_int_op(0, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed, expires_in - 10)); /* Now try after it has expired */ tt_int_op(-4, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed, expires_out + 1)); /* Truncated object */ tt_int_op(-2, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len - 2, rsa, &ed, expires_in - 10)); /* Key not as expected */ cc[0] ^= 3; tt_int_op(-3, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed, expires_in - 10)); cc[0] ^= 3; /* Bad signature */ cc[40] ^= 3; tt_int_op(-5, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed, expires_in - 10)); cc[40] ^= 3; /* Signature of wrong data */ cc[0] ^= 3; ed.pubkey[0] ^= 3; tt_int_op(-6, OP_EQ, rsa_ed25519_crosscert_check(cc, cc_len, rsa, &ed, expires_in - 10)); cc[0] ^= 3; ed.pubkey[0] ^= 3; done: crypto_pk_free(rsa); tor_free(cc); }
static void test_routerkeys_cross_certify_tap(void *args) { (void)args; uint8_t *cc = NULL; int cc_len; ed25519_public_key_t master_key; crypto_pk_t *onion_key = pk_generate(2), *id_key = pk_generate(1); char digest[20]; char buf[128]; int n; tt_int_op(0, OP_EQ, ed25519_public_from_base64(&master_key, "IAlreadyWroteTestsForRouterdescsUsingTheseX")); cc = make_tap_onion_key_crosscert(onion_key, &master_key, id_key, &cc_len); tt_assert(cc); tt_assert(cc_len); n = crypto_pk_public_checksig(onion_key, buf, sizeof(buf), (char*)cc, cc_len); tt_int_op(n,OP_GT,0); tt_int_op(n,OP_EQ,52); crypto_pk_get_digest(id_key, digest); tt_mem_op(buf,OP_EQ,digest,20); tt_mem_op(buf+20,OP_EQ,master_key.pubkey,32); tt_int_op(0, OP_EQ, check_tap_onion_key_crosscert(cc, cc_len, onion_key, &master_key, (uint8_t*)digest)); done: tor_free(cc); crypto_pk_free(id_key); crypto_pk_free(onion_key); }
static const routerinfo_t* NS(router_get_my_routerinfo)(void) { crypto_pk_t* ident_key; crypto_pk_t* tap_key; time_t now; if (!mock_routerinfo) { /* Mock the published timestamp, otherwise router_dump_router_to_string() * will poop its pants. */ time(&now); /* We'll need keys, or router_dump_router_to_string() would return NULL. */ ident_key = pk_generate(0); tap_key = pk_generate(0); tor_assert(ident_key != NULL); tor_assert(tap_key != NULL); mock_routerinfo = tor_malloc_zero(sizeof(routerinfo_t)); mock_routerinfo->nickname = tor_strdup("ConlonNancarrow"); mock_routerinfo->addr = 123456789; mock_routerinfo->or_port = 443; mock_routerinfo->platform = tor_strdup("unittest"); mock_routerinfo->cache_info.published_on = now; mock_routerinfo->identity_pkey = crypto_pk_dup_key(ident_key); router_set_rsa_onion_pkey(tap_key, &mock_routerinfo->onion_pkey, &mock_routerinfo->onion_pkey_len); mock_routerinfo->bandwidthrate = 9001; mock_routerinfo->bandwidthburst = 9002; crypto_pk_free(ident_key); crypto_pk_free(tap_key); } return mock_routerinfo; }
static void test_rend_cache_clean_v2_descs_as_dir(void *data) { rend_cache_entry_t *e; time_t now, cutoff; rend_service_descriptor_t *desc; now = time(NULL); cutoff = now - (REND_CACHE_MAX_AGE + REND_CACHE_MAX_SKEW); const char key[DIGEST_LEN] = "abcde"; (void)data; rend_cache_init(); // Test running with an empty cache rend_cache_clean_v2_descs_as_dir(cutoff); tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0); // Test with only one new entry e = tor_malloc_zero(sizeof(rend_cache_entry_t)); e->last_served = now; desc = tor_malloc_zero(sizeof(rend_service_descriptor_t)); desc->timestamp = now; desc->pk = pk_generate(0); e->parsed = desc; digestmap_set(rend_cache_v2_dir, key, e); /* Set the cutoff to minus 10 seconds. */ rend_cache_clean_v2_descs_as_dir(cutoff - 10); tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 1); // Test with one old entry desc->timestamp = cutoff - 1000; rend_cache_clean_v2_descs_as_dir(cutoff); tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0); done: rend_cache_free_all(); }
static void test_rend_cache_failure_remove(void *data) { rend_service_descriptor_t *desc; (void)data; rend_cache_init(); // Test that it deals well with a NULL desc rend_cache_failure_remove(NULL); // Test a descriptor that isn't in the cache desc = tor_malloc_zero(sizeof(rend_service_descriptor_t)); desc->pk = pk_generate(0); rend_cache_failure_remove(desc); // There seems to not exist any way of getting rend_cache_failure_remove() // to fail because of a problem with rend_get_service_id from here rend_cache_free_all(); rend_service_descriptor_free(desc); /* done: */ /* (void)0; */ }
static void test_rend_cache_clean(void *data) { rend_cache_entry_t *one, *two; rend_service_descriptor_t *desc_one, *desc_two; strmap_iter_t *iter = NULL; const char *key; void *val; (void)data; rend_cache_init(); // Test with empty rendcache rend_cache_clean(time(NULL), REND_CACHE_TYPE_CLIENT); tt_int_op(strmap_size(rend_cache), OP_EQ, 0); // Test with two old entries one = tor_malloc_zero(sizeof(rend_cache_entry_t)); two = tor_malloc_zero(sizeof(rend_cache_entry_t)); desc_one = tor_malloc_zero(sizeof(rend_service_descriptor_t)); desc_two = tor_malloc_zero(sizeof(rend_service_descriptor_t)); one->parsed = desc_one; two->parsed = desc_two; desc_one->timestamp = time(NULL) + TIME_IN_THE_PAST; desc_two->timestamp = (time(NULL) + TIME_IN_THE_PAST) - 10; desc_one->pk = pk_generate(0); desc_two->pk = pk_generate(1); strmap_set_lc(rend_cache, "foo1", one); strmap_set_lc(rend_cache, "foo2", two); rend_cache_clean(time(NULL), REND_CACHE_TYPE_CLIENT); tt_int_op(strmap_size(rend_cache), OP_EQ, 0); // Test with one old entry and one newer entry one = tor_malloc_zero(sizeof(rend_cache_entry_t)); two = tor_malloc_zero(sizeof(rend_cache_entry_t)); desc_one = tor_malloc_zero(sizeof(rend_service_descriptor_t)); desc_two = tor_malloc_zero(sizeof(rend_service_descriptor_t)); one->parsed = desc_one; two->parsed = desc_two; desc_one->timestamp = (time(NULL) + TIME_IN_THE_PAST) - 10; desc_two->timestamp = time(NULL) - 100; desc_one->pk = pk_generate(0); desc_two->pk = pk_generate(1); strmap_set_lc(rend_cache, "foo1", one); strmap_set_lc(rend_cache, "foo2", two); rend_cache_clean(time(NULL), REND_CACHE_TYPE_CLIENT); tt_int_op(strmap_size(rend_cache), OP_EQ, 1); iter = strmap_iter_init(rend_cache); strmap_iter_get(iter, &key, &val); tt_str_op(key, OP_EQ, "foo2"); done: rend_cache_free_all(); }
static void test_rend_cache_clean_v2_descs_as_dir(void *data) { rend_cache_entry_t *e; time_t now; rend_service_descriptor_t *desc; now = time(NULL); const char key[DIGEST_LEN] = "abcde"; (void)data; rend_cache_init(); // Test running with an empty cache rend_cache_clean_v2_descs_as_dir(now, 0); tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0); // Test with only one new entry e = tor_malloc_zero(sizeof(rend_cache_entry_t)); e->last_served = now; desc = tor_malloc_zero(sizeof(rend_service_descriptor_t)); desc->timestamp = now; desc->pk = pk_generate(0); e->parsed = desc; digestmap_set(rend_cache_v2_dir, key, e); rend_cache_clean_v2_descs_as_dir(now, 0); tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 1); // Test with one old entry desc->timestamp = now - (REND_CACHE_MAX_AGE + REND_CACHE_MAX_SKEW + 1000); rend_cache_clean_v2_descs_as_dir(now, 0); tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0); // Test with one entry that has an old last served e = tor_malloc_zero(sizeof(rend_cache_entry_t)); e->last_served = now - (REND_CACHE_MAX_AGE + REND_CACHE_MAX_SKEW + 1000); desc = tor_malloc_zero(sizeof(rend_service_descriptor_t)); desc->timestamp = now; desc->pk = pk_generate(0); e->parsed = desc; digestmap_set(rend_cache_v2_dir, key, e); rend_cache_clean_v2_descs_as_dir(now, 0); tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 0); // Test a run through asking for a large force_remove e = tor_malloc_zero(sizeof(rend_cache_entry_t)); e->last_served = now; desc = tor_malloc_zero(sizeof(rend_service_descriptor_t)); desc->timestamp = now; desc->pk = pk_generate(0); e->parsed = desc; digestmap_set(rend_cache_v2_dir, key, e); rend_cache_clean_v2_descs_as_dir(now, 20000); tt_int_op(digestmap_size(rend_cache_v2_dir), OP_EQ, 1); done: rend_cache_free_all(); }
static void test_routerkeys_write_fingerprint(void *arg) { crypto_pk_t *key = pk_generate(2); or_options_t *options = get_options_mutable(); const char *ddir = get_fname("write_fingerprint"); char *cp = NULL, *cp2 = NULL; char fp[FINGERPRINT_LEN+1]; (void)arg; tt_assert(key); options->ORPort_set = 1; /* So that we can get the server ID key */ tor_free(options->DataDirectory); options->DataDirectory = tor_strdup(ddir); options->Nickname = tor_strdup("haflinger"); set_server_identity_key(key); set_client_identity_key(crypto_pk_dup_key(key)); tt_int_op(0, OP_EQ, check_private_dir(ddir, CPD_CREATE, NULL)); tt_int_op(crypto_pk_cmp_keys(get_server_identity_key(),key),OP_EQ,0); /* Write fingerprint file */ tt_int_op(0, OP_EQ, router_write_fingerprint(0)); cp = read_file_to_str(get_fname("write_fingerprint/fingerprint"), 0, NULL); crypto_pk_get_fingerprint(key, fp, 0); tor_asprintf(&cp2, "haflinger %s\n", fp); tt_str_op(cp, OP_EQ, cp2); tor_free(cp); tor_free(cp2); /* Write hashed-fingerprint file */ tt_int_op(0, OP_EQ, router_write_fingerprint(1)); cp = read_file_to_str(get_fname("write_fingerprint/hashed-fingerprint"), 0, NULL); crypto_pk_get_hashed_fingerprint(key, fp); tor_asprintf(&cp2, "haflinger %s\n", fp); tt_str_op(cp, OP_EQ, cp2); tor_free(cp); tor_free(cp2); /* Replace outdated file */ write_str_to_file(get_fname("write_fingerprint/hashed-fingerprint"), "junk goes here", 0); tt_int_op(0, OP_EQ, router_write_fingerprint(1)); cp = read_file_to_str(get_fname("write_fingerprint/hashed-fingerprint"), 0, NULL); crypto_pk_get_hashed_fingerprint(key, fp); tor_asprintf(&cp2, "haflinger %s\n", fp); tt_str_op(cp, OP_EQ, cp2); tor_free(cp); tor_free(cp2); done: crypto_pk_free(key); set_client_identity_key(NULL); tor_free(cp); tor_free(cp2); }
/** Run unit tests for our public key crypto functions */ static void test_crypto_pk(void) { crypto_pk_t *pk1 = NULL, *pk2 = NULL; char *encoded = NULL; char data1[1024], data2[1024], data3[1024]; size_t size; int i, j, p, len; /* Public-key ciphers */ pk1 = pk_generate(0); pk2 = crypto_pk_new(); test_assert(pk1 && pk2); test_assert(! crypto_pk_write_public_key_to_string(pk1, &encoded, &size)); test_assert(! crypto_pk_read_public_key_from_string(pk2, encoded, size)); test_eq(0, crypto_pk_cmp_keys(pk1, pk2)); /* comparison between keys and NULL */ tt_int_op(crypto_pk_cmp_keys(NULL, pk1), <, 0); tt_int_op(crypto_pk_cmp_keys(NULL, NULL), ==, 0); tt_int_op(crypto_pk_cmp_keys(pk1, NULL), >, 0); test_eq(128, crypto_pk_keysize(pk1)); test_eq(1024, crypto_pk_num_bits(pk1)); test_eq(128, crypto_pk_keysize(pk2)); test_eq(1024, crypto_pk_num_bits(pk2)); test_eq(128, crypto_pk_public_encrypt(pk2, data1, sizeof(data1), "Hello whirled.", 15, PK_PKCS1_OAEP_PADDING)); test_eq(128, crypto_pk_public_encrypt(pk1, data2, sizeof(data1), "Hello whirled.", 15, PK_PKCS1_OAEP_PADDING)); /* oaep padding should make encryption not match */ test_memneq(data1, data2, 128); test_eq(15, crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data1, 128, PK_PKCS1_OAEP_PADDING,1)); test_streq(data3, "Hello whirled."); memset(data3, 0, 1024); test_eq(15, crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data2, 128, PK_PKCS1_OAEP_PADDING,1)); test_streq(data3, "Hello whirled."); /* Can't decrypt with public key. */ test_eq(-1, crypto_pk_private_decrypt(pk2, data3, sizeof(data3), data2, 128, PK_PKCS1_OAEP_PADDING,1)); /* Try again with bad padding */ memcpy(data2+1, "XYZZY", 5); /* This has fails ~ once-in-2^40 */ test_eq(-1, crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data2, 128, PK_PKCS1_OAEP_PADDING,1)); /* File operations: save and load private key */ test_assert(! crypto_pk_write_private_key_to_filename(pk1, get_fname("pkey1"))); /* failing case for read: can't read. */ test_assert(crypto_pk_read_private_key_from_filename(pk2, get_fname("xyzzy")) < 0); write_str_to_file(get_fname("xyzzy"), "foobar", 6); /* Failing case for read: no key. */ test_assert(crypto_pk_read_private_key_from_filename(pk2, get_fname("xyzzy")) < 0); test_assert(! crypto_pk_read_private_key_from_filename(pk2, get_fname("pkey1"))); test_eq(15, crypto_pk_private_decrypt(pk2, data3, sizeof(data3), data1, 128, PK_PKCS1_OAEP_PADDING,1)); /* Now try signing. */ strlcpy(data1, "Ossifrage", 1024); test_eq(128, crypto_pk_private_sign(pk1, data2, sizeof(data2), data1, 10)); test_eq(10, crypto_pk_public_checksig(pk1, data3, sizeof(data3), data2, 128)); test_streq(data3, "Ossifrage"); /* Try signing digests. */ test_eq(128, crypto_pk_private_sign_digest(pk1, data2, sizeof(data2), data1, 10)); test_eq(20, crypto_pk_public_checksig(pk1, data3, sizeof(data3), data2, 128)); test_eq(0, crypto_pk_public_checksig_digest(pk1, data1, 10, data2, 128)); test_eq(-1, crypto_pk_public_checksig_digest(pk1, data1, 11, data2, 128)); /*XXXX test failed signing*/ /* Try encoding */ crypto_pk_free(pk2); pk2 = NULL; i = crypto_pk_asn1_encode(pk1, data1, 1024); test_assert(i>0); pk2 = crypto_pk_asn1_decode(data1, i); test_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); /* Try with hybrid encryption wrappers. */ crypto_rand(data1, 1024); for (i = 0; i < 2; ++i) { for (j = 85; j < 140; ++j) { memset(data2,0,1024); memset(data3,0,1024); p = (i==0)?PK_PKCS1_PADDING:PK_PKCS1_OAEP_PADDING; len = crypto_pk_public_hybrid_encrypt(pk1,data2,sizeof(data2), data1,j,p,0); test_assert(len>=0); len = crypto_pk_private_hybrid_decrypt(pk1,data3,sizeof(data3), data2,len,p,1); test_eq(len,j); test_memeq(data1,data3,j); } } /* Try copy_full */ crypto_pk_free(pk2); pk2 = crypto_pk_copy_full(pk1); test_assert(pk2 != NULL); test_neq_ptr(pk1, pk2); test_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); done: if (pk1) crypto_pk_free(pk1); if (pk2) crypto_pk_free(pk2); tor_free(encoded); }
void construct_consensus(char **consensus_text_md) { networkstatus_t *vote = NULL; networkstatus_t *v1 = NULL, *v2 = NULL, *v3 = NULL; networkstatus_voter_info_t *voter = NULL; authority_cert_t *cert1=NULL, *cert2=NULL, *cert3=NULL; crypto_pk_t *sign_skey_1=NULL, *sign_skey_2=NULL, *sign_skey_3=NULL; crypto_pk_t *sign_skey_leg=NULL; time_t now = time(NULL); smartlist_t *votes = NULL; int n_vrs; tt_assert(!dir_common_authority_pk_init(&cert1, &cert2, &cert3, &sign_skey_1, &sign_skey_2, &sign_skey_3)); sign_skey_leg = pk_generate(4); dir_common_construct_vote_1(&vote, cert1, sign_skey_1, &dir_common_gen_routerstatus_for_v3ns, &v1, &n_vrs, now, 1); networkstatus_vote_free(vote); tt_assert(v1); tt_int_op(n_vrs, ==, 4); tt_int_op(smartlist_len(v1->routerstatus_list), ==, 4); dir_common_construct_vote_2(&vote, cert2, sign_skey_2, &dir_common_gen_routerstatus_for_v3ns, &v2, &n_vrs, now, 1); networkstatus_vote_free(vote); tt_assert(v2); tt_int_op(n_vrs, ==, 4); tt_int_op(smartlist_len(v2->routerstatus_list), ==, 4); dir_common_construct_vote_3(&vote, cert3, sign_skey_3, &dir_common_gen_routerstatus_for_v3ns, &v3, &n_vrs, now, 1); tt_assert(v3); tt_int_op(n_vrs, ==, 4); tt_int_op(smartlist_len(v3->routerstatus_list), ==, 4); networkstatus_vote_free(vote); votes = smartlist_new(); smartlist_add(votes, v1); smartlist_add(votes, v2); smartlist_add(votes, v3); *consensus_text_md = networkstatus_compute_consensus(votes, 3, cert1->identity_key, sign_skey_1, "AAAAAAAAAAAAAAAAAAAA", sign_skey_leg, FLAV_MICRODESC); tt_assert(*consensus_text_md); done: tor_free(voter); networkstatus_vote_free(v1); networkstatus_vote_free(v2); networkstatus_vote_free(v3); smartlist_free(votes); authority_cert_free(cert1); authority_cert_free(cert2); authority_cert_free(cert3); crypto_pk_free(sign_skey_1); crypto_pk_free(sign_skey_2); crypto_pk_free(sign_skey_3); crypto_pk_free(sign_skey_leg); }
static void test_add_onion_helper_keyarg(void *arg) { crypto_pk_t *pk = NULL; crypto_pk_t *pk2 = NULL; const char *key_new_alg = NULL; char *key_new_blob = NULL; char *err_msg = NULL; char *encoded = NULL; char *arg_str = NULL; (void) arg; /* Test explicit RSA1024 key generation. */ pk = add_onion_helper_keyarg("NEW:RSA1024", 0, &key_new_alg, &key_new_blob, &err_msg); tt_assert(pk); tt_str_op(key_new_alg, OP_EQ, "RSA1024"); tt_assert(key_new_blob); tt_assert(!err_msg); /* Test "BEST" key generation (Assumes BEST = RSA1024). */ crypto_pk_free(pk); tor_free(key_new_blob); pk = add_onion_helper_keyarg("NEW:BEST", 0, &key_new_alg, &key_new_blob, &err_msg); tt_assert(pk); tt_str_op(key_new_alg, OP_EQ, "RSA1024"); tt_assert(key_new_blob); tt_assert(!err_msg); /* Test discarding the private key. */ crypto_pk_free(pk); tor_free(key_new_blob); pk = add_onion_helper_keyarg("NEW:BEST", 1, &key_new_alg, &key_new_blob, &err_msg); tt_assert(pk); tt_assert(!key_new_alg); tt_assert(!key_new_blob); tt_assert(!err_msg); /* Test generating a invalid key type. */ crypto_pk_free(pk); pk = add_onion_helper_keyarg("NEW:RSA512", 0, &key_new_alg, &key_new_blob, &err_msg); tt_assert(!pk); tt_assert(!key_new_alg); tt_assert(!key_new_blob); tt_assert(err_msg); /* Test loading a RSA1024 key. */ tor_free(err_msg); pk = pk_generate(0); tt_int_op(0, OP_EQ, crypto_pk_base64_encode(pk, &encoded)); tor_asprintf(&arg_str, "RSA1024:%s", encoded); pk2 = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob, &err_msg); tt_assert(pk2); tt_assert(!key_new_alg); tt_assert(!key_new_blob); tt_assert(!err_msg); tt_assert(crypto_pk_cmp_keys(pk, pk2) == 0); /* Test loading a invalid key type. */ tor_free(arg_str); crypto_pk_free(pk); pk = NULL; tor_asprintf(&arg_str, "RSA512:%s", encoded); pk = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob, &err_msg); tt_assert(!pk); tt_assert(!key_new_alg); tt_assert(!key_new_blob); tt_assert(err_msg); /* Test loading a invalid key. */ tor_free(arg_str); crypto_pk_free(pk); pk = NULL; tor_free(err_msg); encoded[strlen(encoded)/2] = '\0'; tor_asprintf(&arg_str, "RSA1024:%s", encoded); pk = add_onion_helper_keyarg(arg_str, 0, &key_new_alg, &key_new_blob, &err_msg); tt_assert(!pk); tt_assert(!key_new_alg); tt_assert(!key_new_blob); tt_assert(err_msg); done: crypto_pk_free(pk); crypto_pk_free(pk2); tor_free(key_new_blob); tor_free(err_msg); tor_free(encoded); tor_free(arg_str); }
static void test_routerkeys_ed_keys_init_all(void *arg) { (void)arg; char *dir = tor_strdup(get_fname("test_ed_keys_init_all")); char *keydir = tor_strdup(get_fname("test_ed_keys_init_all/KEYS")); or_options_t *options = tor_malloc_zero(sizeof(or_options_t)); time_t now = time(NULL); ed25519_public_key_t id; ed25519_keypair_t sign, auth; tor_cert_t *link_cert = NULL; get_options_mutable()->ORPort_set = 1; crypto_pk_t *rsa = pk_generate(0); set_server_identity_key(rsa); set_client_identity_key(rsa); router_initialize_tls_context(); options->SigningKeyLifetime = 30*86400; options->TestingAuthKeyLifetime = 2*86400; options->TestingLinkCertLifetime = 2*86400; options->TestingSigningKeySlop = 2*86400; options->TestingAuthKeySlop = 2*3600; options->TestingLinkKeySlop = 2*3600; #ifdef _WIN32 mkdir(dir); mkdir(keydir); #else mkdir(dir, 0700); mkdir(keydir, 0700); #endif /* defined(_WIN32) */ options->DataDirectory = dir; options->KeyDirectory = keydir; tt_int_op(1, OP_EQ, load_ed_keys(options, now)); tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now, 0)); tt_assert(get_master_identity_key()); tt_assert(get_master_identity_key()); tt_assert(get_master_signing_keypair()); tt_assert(get_current_auth_keypair()); tt_assert(get_master_signing_key_cert()); tt_assert(get_current_link_cert_cert()); tt_assert(get_current_auth_key_cert()); memcpy(&id, get_master_identity_key(), sizeof(id)); memcpy(&sign, get_master_signing_keypair(), sizeof(sign)); memcpy(&auth, get_current_auth_keypair(), sizeof(auth)); link_cert = tor_cert_dup(get_current_link_cert_cert()); /* Call load_ed_keys again, but nothing has changed. */ tt_int_op(0, OP_EQ, load_ed_keys(options, now)); tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now, 0)); tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); tt_mem_op(&sign, OP_EQ, get_master_signing_keypair(), sizeof(sign)); tt_mem_op(&auth, OP_EQ, get_current_auth_keypair(), sizeof(auth)); tt_assert(tor_cert_eq(link_cert, get_current_link_cert_cert())); /* Force a reload: we make new link/auth keys. */ routerkeys_free_all(); tt_int_op(1, OP_EQ, load_ed_keys(options, now)); tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now, 0)); tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); tt_mem_op(&sign, OP_EQ, get_master_signing_keypair(), sizeof(sign)); tt_assert(tor_cert_eq(link_cert, get_current_link_cert_cert())); tt_mem_op(&auth, OP_NE, get_current_auth_keypair(), sizeof(auth)); tt_assert(get_master_signing_key_cert()); tt_assert(get_current_link_cert_cert()); tt_assert(get_current_auth_key_cert()); tor_cert_free(link_cert); link_cert = tor_cert_dup(get_current_link_cert_cert()); memcpy(&auth, get_current_auth_keypair(), sizeof(auth)); /* Force a link/auth-key regeneration by advancing time. */ tt_int_op(0, OP_EQ, load_ed_keys(options, now+3*86400)); tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now+3*86400, 0)); tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); tt_mem_op(&sign, OP_EQ, get_master_signing_keypair(), sizeof(sign)); tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert())); tt_mem_op(&auth, OP_NE, get_current_auth_keypair(), sizeof(auth)); tt_assert(get_master_signing_key_cert()); tt_assert(get_current_link_cert_cert()); tt_assert(get_current_auth_key_cert()); tor_cert_free(link_cert); link_cert = tor_cert_dup(get_current_link_cert_cert()); memcpy(&auth, get_current_auth_keypair(), sizeof(auth)); /* Force a signing-key regeneration by advancing time. */ tt_int_op(1, OP_EQ, load_ed_keys(options, now+100*86400)); tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now+100*86400, 0)); tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); tt_mem_op(&sign, OP_NE, get_master_signing_keypair(), sizeof(sign)); tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert())); tt_mem_op(&auth, OP_NE, get_current_auth_keypair(), sizeof(auth)); tt_assert(get_master_signing_key_cert()); tt_assert(get_current_link_cert_cert()); tt_assert(get_current_auth_key_cert()); memcpy(&sign, get_master_signing_keypair(), sizeof(sign)); tor_cert_free(link_cert); link_cert = tor_cert_dup(get_current_link_cert_cert()); memcpy(&auth, get_current_auth_keypair(), sizeof(auth)); /* Demonstrate that we can start up with no secret identity key */ routerkeys_free_all(); unlink(get_fname("test_ed_keys_init_all/KEYS/" "ed25519_master_id_secret_key")); tt_int_op(1, OP_EQ, load_ed_keys(options, now)); tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now, 0)); tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); tt_mem_op(&sign, OP_EQ, get_master_signing_keypair(), sizeof(sign)); tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert())); tt_mem_op(&auth, OP_NE, get_current_auth_keypair(), sizeof(auth)); tt_assert(get_master_signing_key_cert()); tt_assert(get_current_link_cert_cert()); tt_assert(get_current_auth_key_cert()); /* But we're in trouble if we have no id key and our signing key has expired. */ log_global_min_severity_ = LOG_ERR; /* Suppress warnings. * XXX (better way to do this)? */ routerkeys_free_all(); tt_int_op(-1, OP_EQ, load_ed_keys(options, now+200*86400)); done: tor_free(dir); tor_free(keydir); tor_free(options); tor_cert_free(link_cert); routerkeys_free_all(); }
static void test_bad_onion_handshake(void *arg) { char junk_buf[TAP_ONIONSKIN_CHALLENGE_LEN]; char junk_buf2[TAP_ONIONSKIN_CHALLENGE_LEN]; /* client-side */ crypto_dh_t *c_dh = NULL; char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN]; char c_keys[40]; /* server-side */ char s_buf[TAP_ONIONSKIN_REPLY_LEN]; char s_keys[40]; /* shared */ crypto_pk_t *pk = NULL, *pk2 = NULL; (void)arg; pk = pk_generate(0); pk2 = pk_generate(1); /* Server: Case 1: the encrypted data is degenerate. */ memset(junk_buf, 0, sizeof(junk_buf)); crypto_pk_obsolete_public_hybrid_encrypt(pk, junk_buf2, TAP_ONIONSKIN_CHALLENGE_LEN, junk_buf, DH_KEY_LEN, PK_PKCS1_OAEP_PADDING, 1); tt_int_op(-1, OP_EQ, onion_skin_TAP_server_handshake(junk_buf2, pk, NULL, s_buf, s_keys, 40)); /* Server: Case 2: the encrypted data is not long enough. */ memset(junk_buf, 0, sizeof(junk_buf)); memset(junk_buf2, 0, sizeof(junk_buf2)); crypto_pk_public_encrypt(pk, junk_buf2, sizeof(junk_buf2), junk_buf, 48, PK_PKCS1_OAEP_PADDING); tt_int_op(-1, OP_EQ, onion_skin_TAP_server_handshake(junk_buf2, pk, NULL, s_buf, s_keys, 40)); /* client handshake 1: do it straight. */ memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN); tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf)); /* Server: Case 3: we just don't have the right key. */ tt_int_op(-1, OP_EQ, onion_skin_TAP_server_handshake(c_buf, pk2, NULL, s_buf, s_keys, 40)); /* Server: Case 4: The RSA-encrypted portion is corrupt. */ c_buf[64] ^= 33; tt_int_op(-1, OP_EQ, onion_skin_TAP_server_handshake(c_buf, pk, NULL, s_buf, s_keys, 40)); c_buf[64] ^= 33; /* (Let the server procede) */ tt_int_op(0, OP_EQ, onion_skin_TAP_server_handshake(c_buf, pk, NULL, s_buf, s_keys, 40)); /* Client: Case 1: The server sent back junk. */ const char *msg = NULL; s_buf[64] ^= 33; tt_int_op(-1, OP_EQ, onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg)); s_buf[64] ^= 33; tt_str_op(msg, OP_EQ, "Digest DOES NOT MATCH on onion handshake. " "Bug or attack."); /* Let the client finish; make sure it can. */ msg = NULL; tt_int_op(0, OP_EQ, onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg)); tt_mem_op(s_keys,OP_EQ, c_keys, 40); tt_ptr_op(msg, OP_EQ, NULL); /* Client: Case 2: The server sent back a degenerate DH. */ memset(s_buf, 0, sizeof(s_buf)); tt_int_op(-1, OP_EQ, onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg)); tt_str_op(msg, OP_EQ, "DH computation failed."); done: crypto_dh_free(c_dh); crypto_pk_free(pk); crypto_pk_free(pk2); }
/* Test good certs cells */ static void test_link_handshake_certs_ok(void *arg) { (void) arg; or_connection_t *c1 = or_connection_new(CONN_TYPE_OR, AF_INET); or_connection_t *c2 = or_connection_new(CONN_TYPE_OR, AF_INET); var_cell_t *cell1 = NULL, *cell2 = NULL; certs_cell_t *cc1 = NULL, *cc2 = NULL; channel_tls_t *chan1 = NULL, *chan2 = NULL; crypto_pk_t *key1 = NULL, *key2 = NULL; scheduler_init(); MOCK(tor_tls_cert_matches_key, mock_tls_cert_matches_key); MOCK(connection_or_write_var_cell_to_buf, mock_write_var_cell); MOCK(connection_or_send_netinfo, mock_send_netinfo); key1 = pk_generate(2); key2 = pk_generate(3); /* We need to make sure that our TLS certificates are set up before we can * actually generate a CERTS cell. */ tt_int_op(tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER, key1, key2, 86400), ==, 0); c1->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; c1->link_proto = 3; tt_int_op(connection_init_or_handshake_state(c1, 1), ==, 0); c2->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; c2->link_proto = 3; tt_int_op(connection_init_or_handshake_state(c2, 0), ==, 0); tt_int_op(0, ==, connection_or_send_certs_cell(c1)); tt_assert(mock_got_var_cell); cell1 = mock_got_var_cell; tt_int_op(0, ==, connection_or_send_certs_cell(c2)); tt_assert(mock_got_var_cell); cell2 = mock_got_var_cell; tt_int_op(cell1->command, ==, CELL_CERTS); tt_int_op(cell1->payload_len, >, 1); tt_int_op(cell2->command, ==, CELL_CERTS); tt_int_op(cell2->payload_len, >, 1); tt_int_op(cell1->payload_len, ==, certs_cell_parse(&cc1, cell1->payload, cell1->payload_len)); tt_int_op(cell2->payload_len, ==, certs_cell_parse(&cc2, cell2->payload, cell2->payload_len)); tt_int_op(2, ==, cc1->n_certs); tt_int_op(2, ==, cc2->n_certs); tt_int_op(certs_cell_get_certs(cc1, 0)->cert_type, ==, CERTTYPE_RSA1024_ID_AUTH); tt_int_op(certs_cell_get_certs(cc1, 1)->cert_type, ==, CERTTYPE_RSA1024_ID_ID); tt_int_op(certs_cell_get_certs(cc2, 0)->cert_type, ==, CERTTYPE_RSA1024_ID_LINK); tt_int_op(certs_cell_get_certs(cc2, 1)->cert_type, ==, CERTTYPE_RSA1024_ID_ID); chan1 = tor_malloc_zero(sizeof(*chan1)); channel_tls_common_init(chan1); c1->chan = chan1; chan1->conn = c1; c1->base_.address = tor_strdup("C1"); c1->tls = tor_tls_new(-1, 0); c1->link_proto = 4; c1->base_.conn_array_index = -1; crypto_pk_get_digest(key2, c1->identity_digest); channel_tls_process_certs_cell(cell2, chan1); tt_assert(c1->handshake_state->received_certs_cell); tt_assert(c1->handshake_state->auth_cert == NULL); tt_assert(c1->handshake_state->id_cert); tt_assert(! tor_mem_is_zero( (char*)c1->handshake_state->authenticated_peer_id, 20)); chan2 = tor_malloc_zero(sizeof(*chan2)); channel_tls_common_init(chan2); c2->chan = chan2; chan2->conn = c2; c2->base_.address = tor_strdup("C2"); c2->tls = tor_tls_new(-1, 1); c2->link_proto = 4; c2->base_.conn_array_index = -1; crypto_pk_get_digest(key1, c2->identity_digest); channel_tls_process_certs_cell(cell1, chan2); tt_assert(c2->handshake_state->received_certs_cell); tt_assert(c2->handshake_state->auth_cert); tt_assert(c2->handshake_state->id_cert); tt_assert(tor_mem_is_zero( (char*)c2->handshake_state->authenticated_peer_id, 20)); done: UNMOCK(tor_tls_cert_matches_key); UNMOCK(connection_or_write_var_cell_to_buf); UNMOCK(connection_or_send_netinfo); connection_free_(TO_CONN(c1)); connection_free_(TO_CONN(c2)); tor_free(cell1); tor_free(cell2); certs_cell_free(cc1); certs_cell_free(cc2); if (chan1) circuitmux_free(chan1->base_.cmux); tor_free(chan1); if (chan2) circuitmux_free(chan2->base_.cmux); tor_free(chan2); crypto_pk_free(key1); crypto_pk_free(key2); }
static void * recv_certs_setup(const struct testcase_t *test) { (void)test; certs_data_t *d = tor_malloc_zero(sizeof(*d)); certs_cell_cert_t *ccc1 = NULL; certs_cell_cert_t *ccc2 = NULL; ssize_t n; d->c = or_connection_new(CONN_TYPE_OR, AF_INET); d->chan = tor_malloc_zero(sizeof(*d->chan)); d->c->chan = d->chan; d->c->base_.address = tor_strdup("HaveAnAddress"); d->c->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; d->chan->conn = d->c; tt_int_op(connection_init_or_handshake_state(d->c, 1), ==, 0); d->c->link_proto = 4; d->key1 = pk_generate(2); d->key2 = pk_generate(3); tt_int_op(tor_tls_context_init(TOR_TLS_CTX_IS_PUBLIC_SERVER, d->key1, d->key2, 86400), ==, 0); d->ccell = certs_cell_new(); ccc1 = certs_cell_cert_new(); certs_cell_add_certs(d->ccell, ccc1); ccc2 = certs_cell_cert_new(); certs_cell_add_certs(d->ccell, ccc2); d->ccell->n_certs = 2; ccc1->cert_type = 1; ccc2->cert_type = 2; const tor_x509_cert_t *a,*b; const uint8_t *enca, *encb; size_t lena, lenb; tor_tls_get_my_certs(1, &a, &b); tor_x509_cert_get_der(a, &enca, &lena); tor_x509_cert_get_der(b, &encb, &lenb); certs_cell_cert_setlen_body(ccc1, lena); ccc1->cert_len = lena; certs_cell_cert_setlen_body(ccc2, lenb); ccc2->cert_len = lenb; memcpy(certs_cell_cert_getarray_body(ccc1), enca, lena); memcpy(certs_cell_cert_getarray_body(ccc2), encb, lenb); d->cell = var_cell_new(4096); d->cell->command = CELL_CERTS; n = certs_cell_encode(d->cell->payload, 4096, d->ccell); tt_int_op(n, >, 0); d->cell->payload_len = n; MOCK(tor_tls_cert_matches_key, mock_tls_cert_matches_key); MOCK(connection_or_send_netinfo, mock_send_netinfo); MOCK(connection_or_close_for_error, mock_close_for_err); tt_int_op(0, ==, d->c->handshake_state->received_certs_cell); tt_int_op(0, ==, mock_send_authenticate_called); tt_int_op(0, ==, mock_send_netinfo_called); return d; done: recv_certs_cleanup(test, d); return NULL; }