/* Copyright (c) 2014-2016, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "orconfig.h" #define CHANNELTLS_PRIVATE #define CONNECTION_PRIVATE #define TOR_CHANNEL_INTERNAL_ #define TORTLS_PRIVATE #include #include #include "or.h" #include "config.h" #include "connection.h" #include "connection_or.h" #include "channeltls.h" #include "link_handshake.h" #include "router.h" #include "routerkeys.h" #include "scheduler.h" #include "torcert.h" #include "test.h" #include "log_test_helpers.h" static var_cell_t *mock_got_var_cell = NULL; static void mock_write_var_cell(const var_cell_t *vc, or_connection_t *conn) { (void)conn; var_cell_t *newcell = var_cell_new(vc->payload_len); memcpy(newcell, vc, sizeof(var_cell_t)); memcpy(newcell->payload, vc->payload, vc->payload_len); mock_got_var_cell = newcell; } static int mock_tls_cert_matches_key(const tor_tls_t *tls, const tor_x509_cert_t *cert) { (void) tls; (void) cert; // XXXX look at this. return 1; } static tor_tls_t *mock_peer_cert_expect_tortls = NULL; static tor_x509_cert_t *mock_peer_cert = NULL; static tor_x509_cert_t * mock_get_peer_cert(tor_tls_t *tls) { if (mock_peer_cert_expect_tortls && mock_peer_cert_expect_tortls != tls) return NULL; return mock_peer_cert; } static int mock_send_netinfo_called = 0; static int mock_send_netinfo(or_connection_t *conn) { (void) conn; ++mock_send_netinfo_called;// XXX check_this return 0; } static int mock_close_called = 0; static void mock_close_for_err(or_connection_t *orconn, int flush) { (void)orconn; (void)flush; ++mock_close_called; } static int mock_send_authenticate_called = 0; static int mock_send_authenticate_called_with_type = 0; static int mock_send_authenticate(or_connection_t *conn, int type) { (void) conn; mock_send_authenticate_called_with_type = type; ++mock_send_authenticate_called;// XXX check_this return 0; } static int mock_export_key_material(tor_tls_t *tls, uint8_t *secrets_out, const uint8_t *context, size_t context_len, const char *label) { (void) tls; (void)secrets_out; (void)context; (void)context_len; (void)label; memcpy(secrets_out, "int getRandomNumber(){return 4;}", 32); return 0; } /* Test good certs cells */ static void test_link_handshake_certs_ok(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; const int with_ed = !strcmp((const char *)arg, "Ed25519"); 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); MOCK(tor_tls_get_peer_cert, mock_get_peer_cert); 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); if (with_ed) { /* If we're making a CERTS cell for an ed handshake, let's make sure we * have some Ed25519 certificates and keys. */ init_mock_ed_keys(key2); } /* c1 has started_here == 1 */ 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 has started_here == 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)); if (with_ed) { tt_int_op(5, ==, cc1->n_certs); tt_int_op(5, ==, cc2->n_certs); } else { 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); if (with_ed) { tt_int_op(certs_cell_get_certs(cc1, 2)->cert_type, ==, CERTTYPE_ED_ID_SIGN); tt_int_op(certs_cell_get_certs(cc1, 3)->cert_type, ==, CERTTYPE_ED_SIGN_AUTH); tt_int_op(certs_cell_get_certs(cc1, 4)->cert_type, ==, CERTTYPE_RSA1024_ID_EDID); tt_int_op(certs_cell_get_certs(cc2, 2)->cert_type, ==, CERTTYPE_ED_ID_SIGN); tt_int_op(certs_cell_get_certs(cc2, 3)->cert_type, ==, CERTTYPE_ED_SIGN_LINK); tt_int_op(certs_cell_get_certs(cc2, 4)->cert_type, ==, CERTTYPE_RSA1024_ID_EDID); } 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); if (with_ed) { const tor_x509_cert_t *linkc, *idc; tor_tls_get_my_certs(1, &linkc, &idc); mock_peer_cert_expect_tortls = c1->tls; /* We should see this tls... */ mock_peer_cert = tor_x509_cert_dup(linkc); /* and when we do, the peer's * cert is this... */ } channel_tls_process_certs_cell(cell2, chan1); mock_peer_cert_expect_tortls = NULL; mock_peer_cert = NULL; tor_assert(c1->handshake_state->authenticated); tt_assert(c1->handshake_state->received_certs_cell); tt_assert(c1->handshake_state->certs->auth_cert == NULL); tt_assert(c1->handshake_state->certs->ed_sign_auth == NULL); tt_assert(c1->handshake_state->certs->id_cert); if (with_ed) { tt_assert(c1->handshake_state->certs->ed_sign_link); tt_assert(c1->handshake_state->certs->ed_rsa_crosscert); tt_assert(c1->handshake_state->certs->ed_id_sign); tt_assert(c1->handshake_state->authenticated_rsa); tt_assert(c1->handshake_state->authenticated_ed25519); } else { tt_assert(c1->handshake_state->certs->ed_sign_link == NULL); tt_assert(c1->handshake_state->certs->ed_rsa_crosscert == NULL); tt_assert(c1->handshake_state->certs->ed_id_sign == NULL); tt_assert(c1->handshake_state->authenticated_rsa); tt_assert(! c1->handshake_state->authenticated_ed25519); } tt_assert(! tor_mem_is_zero( (char*)c1->handshake_state->authenticated_rsa_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); if (with_ed) { tt_assert(c2->handshake_state->certs->ed_sign_auth); tt_assert(c2->handshake_state->certs->ed_rsa_crosscert); tt_assert(c2->handshake_state->certs->ed_id_sign); } else { tt_assert(c2->handshake_state->certs->auth_cert); tt_assert(c2->handshake_state->certs->ed_sign_auth == NULL); tt_assert(c2->handshake_state->certs->ed_rsa_crosscert == NULL); tt_assert(c2->handshake_state->certs->ed_id_sign == NULL); } tt_assert(c2->handshake_state->certs->id_cert); tt_assert(tor_mem_is_zero( (char*)c2->handshake_state->authenticated_rsa_peer_id, 20)); /* no authentication has happened yet, since we haen't gotten an AUTH cell. */ tt_assert(! c2->handshake_state->authenticated); tt_assert(! c2->handshake_state->authenticated_rsa); tt_assert(! c2->handshake_state->authenticated_ed25519); done: UNMOCK(tor_tls_cert_matches_key); UNMOCK(connection_or_write_var_cell_to_buf); UNMOCK(connection_or_send_netinfo); UNMOCK(tor_tls_get_peer_cert); memset(c1->identity_digest, 0, sizeof(c1->identity_digest)); memset(c2->identity_digest, 0, sizeof(c2->identity_digest)); 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); } typedef struct certs_data_s { int is_ed; int is_link_cert; or_connection_t *c; channel_tls_t *chan; certs_cell_t *ccell; var_cell_t *cell; crypto_pk_t *key1, *key2; } certs_data_t; static int recv_certs_cleanup(const struct testcase_t *test, void *obj) { (void)test; certs_data_t *d = obj; UNMOCK(tor_tls_cert_matches_key); UNMOCK(connection_or_send_netinfo); UNMOCK(connection_or_close_for_error); UNMOCK(tor_tls_get_peer_cert); if (d) { tor_free(d->cell); certs_cell_free(d->ccell); connection_or_remove_from_identity_map(d->c); connection_free_(TO_CONN(d->c)); circuitmux_free(d->chan->base_.cmux); tor_free(d->chan); crypto_pk_free(d->key1); crypto_pk_free(d->key2); tor_free(d); } routerkeys_free_all(); return 1; } 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; int is_ed = d->is_ed = !strcmpstart(test->setup_data, "Ed25519"); int is_rsa = !strcmpstart(test->setup_data, "RSA"); int is_link = d->is_link_cert = !strcmpend(test->setup_data, "-Link"); int is_auth = !strcmpend(test->setup_data, "-Auth"); tor_assert(is_ed != is_rsa); tor_assert(is_link != is_auth); 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); if (is_ed) { init_mock_ed_keys(d->key2); } else { routerkeys_free_all(); } 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 = is_link ? 1 : 3; 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(is_link ? 1 : 0, &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); if (is_ed) { certs_cell_cert_t *ccc3 = NULL; /* Id->Sign */ certs_cell_cert_t *ccc4 = NULL; /* Sign->Link or Sign->Auth. */ certs_cell_cert_t *ccc5 = NULL; /* RSAId->Ed Id. */ const tor_cert_t *id_sign = get_master_signing_key_cert(); const tor_cert_t *secondary = is_link ? get_current_link_cert_cert() : get_current_auth_key_cert(); const uint8_t *cc = NULL; size_t cc_sz; get_master_rsa_crosscert(&cc, &cc_sz); ccc3 = certs_cell_cert_new(); ccc4 = certs_cell_cert_new(); ccc5 = certs_cell_cert_new(); certs_cell_add_certs(d->ccell, ccc3); certs_cell_add_certs(d->ccell, ccc4); certs_cell_add_certs(d->ccell, ccc5); ccc3->cert_len = id_sign->encoded_len; ccc4->cert_len = secondary->encoded_len; ccc5->cert_len = cc_sz; certs_cell_cert_setlen_body(ccc3, ccc3->cert_len); certs_cell_cert_setlen_body(ccc4, ccc4->cert_len); certs_cell_cert_setlen_body(ccc5, ccc5->cert_len); memcpy(certs_cell_cert_getarray_body(ccc3), id_sign->encoded, ccc3->cert_len); memcpy(certs_cell_cert_getarray_body(ccc4), secondary->encoded, ccc4->cert_len); memcpy(certs_cell_cert_getarray_body(ccc5), cc, ccc5->cert_len); ccc3->cert_type = 4; ccc4->cert_type = is_link ? 5 : 6; ccc5->cert_type = 7; d->ccell->n_certs = 5; } 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); MOCK(tor_tls_get_peer_cert, mock_get_peer_cert); if (is_link) { /* Say that this is the peer's certificate */ mock_peer_cert = tor_x509_cert_dup(a); } 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; } static struct testcase_setup_t setup_recv_certs = { .setup_fn = recv_certs_setup, .cleanup_fn = recv_certs_cleanup }; static void test_link_handshake_recv_certs_ok(void *arg) { certs_data_t *d = arg; channel_tls_process_certs_cell(d->cell, d->chan); tt_int_op(0, ==, mock_close_called); tt_int_op(d->c->handshake_state->authenticated, ==, 1); tt_int_op(d->c->handshake_state->authenticated_rsa, ==, 1); tt_int_op(d->c->handshake_state->received_certs_cell, ==, 1); tt_assert(d->c->handshake_state->certs->id_cert != NULL); tt_assert(d->c->handshake_state->certs->auth_cert == NULL); if (d->is_ed) { tt_assert(d->c->handshake_state->certs->ed_id_sign != NULL); tt_assert(d->c->handshake_state->certs->ed_sign_link != NULL); tt_assert(d->c->handshake_state->certs->ed_sign_auth == NULL); tt_assert(d->c->handshake_state->certs->ed_rsa_crosscert != NULL); tt_int_op(d->c->handshake_state->authenticated_ed25519, ==, 1); } else { tt_assert(d->c->handshake_state->certs->ed_id_sign == NULL); tt_assert(d->c->handshake_state->certs->ed_sign_link == NULL); tt_assert(d->c->handshake_state->certs->ed_sign_auth == NULL); tt_assert(d->c->handshake_state->certs->ed_rsa_crosscert == NULL); tt_int_op(d->c->handshake_state->authenticated_ed25519, ==, 0); } done: ; } static void test_link_handshake_recv_certs_ok_server(void *arg) { certs_data_t *d = arg; d->c->handshake_state->started_here = 0; d->c->handshake_state->certs->started_here = 0; channel_tls_process_certs_cell(d->cell, d->chan); tt_int_op(0, ==, mock_close_called); tt_int_op(d->c->handshake_state->authenticated, ==, 0); tt_int_op(d->c->handshake_state->received_certs_cell, ==, 1); tt_assert(d->c->handshake_state->certs->id_cert != NULL); tt_assert(d->c->handshake_state->certs->link_cert == NULL); if (d->is_ed) { tt_assert(d->c->handshake_state->certs->ed_sign_auth != NULL); tt_assert(d->c->handshake_state->certs->auth_cert == NULL); } else { tt_assert(d->c->handshake_state->certs->ed_sign_auth == NULL); tt_assert(d->c->handshake_state->certs->auth_cert != NULL); } done: ; } #define CERTS_FAIL(name, code) \ static void \ test_link_handshake_recv_certs_ ## name(void *arg) \ { \ certs_data_t *d = arg; \ const char *require_failure_message = NULL; \ setup_capture_of_logs(LOG_INFO); \ { code ; } \ channel_tls_process_certs_cell(d->cell, d->chan); \ tt_int_op(1, ==, mock_close_called); \ tt_int_op(0, ==, mock_send_authenticate_called); \ tt_int_op(0, ==, mock_send_netinfo_called); \ tt_int_op(0, ==, d->c->handshake_state->authenticated_rsa); \ tt_int_op(0, ==, d->c->handshake_state->authenticated_ed25519); \ if (require_failure_message) { \ expect_log_msg_containing(require_failure_message); \ } \ done: \ teardown_capture_of_logs(); \ } CERTS_FAIL(badstate, require_failure_message = "We're not doing a v3 handshake!"; d->c->base_.state = OR_CONN_STATE_CONNECTING;) CERTS_FAIL(badproto, require_failure_message = "not using link protocol >= 3"; d->c->link_proto = 2) CERTS_FAIL(duplicate, require_failure_message = "We already got one"; d->c->handshake_state->received_certs_cell = 1) CERTS_FAIL(already_authenticated, require_failure_message = "We're already authenticated!"; d->c->handshake_state->authenticated = 1) CERTS_FAIL(empty, require_failure_message = "It had no body"; d->cell->payload_len = 0) CERTS_FAIL(bad_circid, require_failure_message = "It had a nonzero circuit ID"; d->cell->circ_id = 1) CERTS_FAIL(truncated_1, require_failure_message = "It couldn't be parsed"; d->cell->payload[0] = 5) CERTS_FAIL(truncated_2, { require_failure_message = "It couldn't be parsed"; d->cell->payload_len = 4; memcpy(d->cell->payload, "\x01\x01\x00\x05", 4); }) CERTS_FAIL(truncated_3, { require_failure_message = "It couldn't be parsed"; d->cell->payload_len = 7; memcpy(d->cell->payload, "\x01\x01\x00\x05""abc", 7); }) CERTS_FAIL(truncated_4, /* ed25519 */ { require_failure_message = "It couldn't be parsed"; d->cell->payload_len -= 10; }) CERTS_FAIL(truncated_5, /* ed25519 */ { require_failure_message = "It couldn't be parsed"; d->cell->payload_len -= 100; }) #define REENCODE() do { \ const char *msg = certs_cell_check(d->ccell); \ if (msg) puts(msg); \ ssize_t n = certs_cell_encode(d->cell->payload, 4096, d->ccell); \ tt_int_op(n, >, 0); \ d->cell->payload_len = n; \ } while (0) CERTS_FAIL(truncated_6, /* ed25519 */ { /* truncate the link certificate */ require_failure_message = "undecodable Ed certificate"; certs_cell_cert_setlen_body(certs_cell_get_certs(d->ccell, 3), 7); certs_cell_get_certs(d->ccell, 3)->cert_len = 7; REENCODE(); }) CERTS_FAIL(truncated_7, /* ed25519 */ { /* truncate the crosscert */ require_failure_message = "Unparseable or overlong crosscert"; certs_cell_cert_setlen_body(certs_cell_get_certs(d->ccell, 4), 7); certs_cell_get_certs(d->ccell, 4)->cert_len = 7; REENCODE(); }) CERTS_FAIL(not_x509, { require_failure_message = "Received undecodable certificate"; certs_cell_cert_setlen_body(certs_cell_get_certs(d->ccell, 0), 3); certs_cell_get_certs(d->ccell, 0)->cert_len = 3; REENCODE(); }) CERTS_FAIL(both_link, { require_failure_message = "Duplicate x509 certificate"; certs_cell_get_certs(d->ccell, 0)->cert_type = 1; certs_cell_get_certs(d->ccell, 1)->cert_type = 1; REENCODE(); }) CERTS_FAIL(both_id_rsa, { require_failure_message = "Duplicate x509 certificate"; certs_cell_get_certs(d->ccell, 0)->cert_type = 2; certs_cell_get_certs(d->ccell, 1)->cert_type = 2; REENCODE(); }) CERTS_FAIL(both_auth, { require_failure_message = "Duplicate x509 certificate"; certs_cell_get_certs(d->ccell, 0)->cert_type = 3; certs_cell_get_certs(d->ccell, 1)->cert_type = 3; REENCODE(); }) CERTS_FAIL(duplicate_id, /* ed25519 */ { require_failure_message = "Duplicate Ed25519 certificate"; certs_cell_get_certs(d->ccell, 2)->cert_type = 4; certs_cell_get_certs(d->ccell, 3)->cert_type = 4; REENCODE(); }) CERTS_FAIL(duplicate_link, /* ed25519 */ { require_failure_message = "Duplicate Ed25519 certificate"; certs_cell_get_certs(d->ccell, 2)->cert_type = 5; certs_cell_get_certs(d->ccell, 3)->cert_type = 5; REENCODE(); }) CERTS_FAIL(duplicate_crosscert, /* ed25519 */ { require_failure_message = "Duplicate RSA->Ed25519 crosscert"; certs_cell_get_certs(d->ccell, 2)->cert_type = 7; certs_cell_get_certs(d->ccell, 3)->cert_type = 7; REENCODE(); }) static void test_link_handshake_recv_certs_missing_id(void *arg) /* ed25519 */ { certs_data_t *d = arg; tt_int_op(certs_cell_getlen_certs(d->ccell), OP_EQ, 5); certs_cell_set_certs(d->ccell, 2, certs_cell_get_certs(d->ccell, 4)); certs_cell_set0_certs(d->ccell, 4, NULL); /* prevent free */ certs_cell_setlen_certs(d->ccell, 4); d->ccell->n_certs = 4; REENCODE(); /* This handshake succeeds, but since we have no ID cert, we will * just do the RSA handshake. */ channel_tls_process_certs_cell(d->cell, d->chan); tt_int_op(0, ==, mock_close_called); tt_int_op(0, ==, d->c->handshake_state->authenticated_ed25519); tt_int_op(1, ==, d->c->handshake_state->authenticated_rsa); done: ; } CERTS_FAIL(missing_signing_key, /* ed25519 */ { require_failure_message = "No Ed25519 signing key"; tt_int_op(certs_cell_getlen_certs(d->ccell), OP_EQ, 5); certs_cell_cert_t *cert = certs_cell_get_certs(d->ccell, 2); tt_int_op(cert->cert_type, ==, CERTTYPE_ED_ID_SIGN); /* replace this with a valid master->signing cert, but with no * signing key. */ const ed25519_keypair_t *mk = get_master_identity_keypair(); const ed25519_keypair_t *sk = get_master_signing_keypair(); tor_cert_t *bad_cert = tor_cert_create(mk, CERT_TYPE_ID_SIGNING, &sk->pubkey, time(NULL), 86400, 0 /* don't include signer */); certs_cell_cert_setlen_body(cert, bad_cert->encoded_len); memcpy(certs_cell_cert_getarray_body(cert), bad_cert->encoded, bad_cert->encoded_len); cert->cert_len = bad_cert->encoded_len; tor_cert_free(bad_cert); REENCODE(); }) CERTS_FAIL(missing_link, /* ed25519 */ { require_failure_message = "No Ed25519 link key"; tt_int_op(certs_cell_getlen_certs(d->ccell), OP_EQ, 5); certs_cell_set_certs(d->ccell, 3, certs_cell_get_certs(d->ccell, 4)); certs_cell_set0_certs(d->ccell, 4, NULL); /* prevent free */ certs_cell_setlen_certs(d->ccell, 4); d->ccell->n_certs = 4; REENCODE(); }) CERTS_FAIL(missing_auth, /* ed25519 */ { d->c->handshake_state->started_here = 0; d->c->handshake_state->certs->started_here = 0; require_failure_message = "No Ed25519 link authentication key"; tt_int_op(certs_cell_getlen_certs(d->ccell), OP_EQ, 5); certs_cell_set_certs(d->ccell, 3, certs_cell_get_certs(d->ccell, 4)); certs_cell_set0_certs(d->ccell, 4, NULL); /* prevent free */ certs_cell_setlen_certs(d->ccell, 4); d->ccell->n_certs = 4; REENCODE(); }) CERTS_FAIL(missing_crosscert, /* ed25519 */ { require_failure_message = "Missing RSA->Ed25519 crosscert"; tt_int_op(certs_cell_getlen_certs(d->ccell), OP_EQ, 5); certs_cell_setlen_certs(d->ccell, 4); d->ccell->n_certs = 4; REENCODE(); }) CERTS_FAIL(missing_rsa_id, /* ed25519 */ { require_failure_message = "Missing legacy RSA ID cert"; tt_int_op(certs_cell_getlen_certs(d->ccell), OP_EQ, 5); certs_cell_set_certs(d->ccell, 1, certs_cell_get_certs(d->ccell, 4)); certs_cell_set0_certs(d->ccell, 4, NULL); /* prevent free */ certs_cell_setlen_certs(d->ccell, 4); d->ccell->n_certs = 4; REENCODE(); }) CERTS_FAIL(link_mismatch, /* ed25519 */ { require_failure_message = "Link certificate does not match " "TLS certificate"; const tor_x509_cert_t *idc; tor_tls_get_my_certs(1, NULL, &idc); tor_x509_cert_free(mock_peer_cert); /* Pretend that the peer cert was something else. */ mock_peer_cert = tor_x509_cert_dup(idc); /* No reencode needed. */ }) CERTS_FAIL(bad_ed_sig, /* ed25519 */ { require_failure_message = "At least one Ed25519 certificate was " "badly signed"; certs_cell_cert_t *cert = certs_cell_get_certs(d->ccell, 3); uint8_t *body = certs_cell_cert_getarray_body(cert); ssize_t body_len = certs_cell_cert_getlen_body(cert); /* Frob a byte in the signature */ body[body_len - 13] ^= 7; REENCODE(); }) CERTS_FAIL(bad_crosscert, /*ed25519*/ { require_failure_message = "Invalid RSA->Ed25519 crosscert"; certs_cell_cert_t *cert = certs_cell_get_certs(d->ccell, 4); uint8_t *body = certs_cell_cert_getarray_body(cert); ssize_t body_len = certs_cell_cert_getlen_body(cert); /* Frob a byte in the signature */ body[body_len - 13] ^= 7; REENCODE(); }) CERTS_FAIL(bad_rsa_id_cert, /*ed25519*/ { require_failure_message = "legacy RSA ID certificate was not valid"; certs_cell_cert_t *cert = certs_cell_get_certs(d->ccell, 1); uint8_t *body = certs_cell_cert_getarray_body(cert); ssize_t body_len = certs_cell_cert_getlen_body(cert); /* Frob a byte in the signature */ body[body_len - 13] ^= 7; REENCODE(); }) CERTS_FAIL(expired_rsa_id, /* both */ { require_failure_message = "Certificate already expired"; /* we're going to replace the identity cert with an expired one. */ certs_cell_cert_t *cert = certs_cell_get_certs(d->ccell, 1); const tor_x509_cert_t *idc; tor_tls_get_my_certs(1, NULL, &idc); X509 *newc = X509_dup(idc->cert); time_t new_end = time(NULL) - 86400 * 10; X509_time_adj(X509_get_notAfter(newc), 0, &new_end); EVP_PKEY *pk = crypto_pk_get_evp_pkey_(d->key2, 1); tt_assert(X509_sign(newc, pk, EVP_sha1())); int len = i2d_X509(newc, NULL); certs_cell_cert_setlen_body(cert, len); uint8_t *body = certs_cell_cert_getarray_body(cert); int len2 = i2d_X509(newc, &body); tt_int_op(len, ==, len2); REENCODE(); X509_free(newc); EVP_PKEY_free(pk); }) CERTS_FAIL(expired_ed_id, /* ed25519 */ { /* we're going to replace the Ed Id->sign cert with an expired one. */ require_failure_message = "At least one certificate expired"; /* We don't need to re-sign, since we check for expiration first. */ certs_cell_cert_t *cert = certs_cell_get_certs(d->ccell, 2); uint8_t *body = certs_cell_cert_getarray_body(cert); /* The expiration field is bytes [2..5]. It is in HOURS since the * epoch. */ set_uint32(body+2, htonl(24)); /* Back to jan 2, 1970. */ REENCODE(); }) CERTS_FAIL(expired_ed_link, /* ed25519 */ { /* we're going to replace the Ed Sign->link cert with an expired one. */ require_failure_message = "At least one certificate expired"; /* We don't need to re-sign, since we check for expiration first. */ certs_cell_cert_t *cert = certs_cell_get_certs(d->ccell, 3); uint8_t *body = certs_cell_cert_getarray_body(cert); /* The expiration field is bytes [2..5]. It is in HOURS since the * epoch. */ set_uint32(body+2, htonl(24)); /* Back to jan 2, 1970. */ REENCODE(); }) CERTS_FAIL(expired_crosscert, /* ed25519 */ { /* we're going to replace the Ed Sign->link cert with an expired one. */ require_failure_message = "Crosscert is expired"; /* We don't need to re-sign, since we check for expiration first. */ certs_cell_cert_t *cert = certs_cell_get_certs(d->ccell, 4); uint8_t *body = certs_cell_cert_getarray_body(cert); /* The expiration field is bytes [32..35]. once again, HOURS. */ set_uint32(body+32, htonl(24)); /* Back to jan 2, 1970. */ REENCODE(); }) CERTS_FAIL(wrong_labels_1, { require_failure_message = "The link certificate was not valid"; certs_cell_get_certs(d->ccell, 0)->cert_type = 2; certs_cell_get_certs(d->ccell, 1)->cert_type = 1; REENCODE(); }) CERTS_FAIL(wrong_labels_2, { const tor_x509_cert_t *a; const tor_x509_cert_t *b; const uint8_t *enca; size_t lena; require_failure_message = "The link certificate was not valid"; tor_tls_get_my_certs(1, &a, &b); tor_x509_cert_get_der(a, &enca, &lena); certs_cell_cert_setlen_body(certs_cell_get_certs(d->ccell, 1), lena); memcpy(certs_cell_cert_getarray_body(certs_cell_get_certs(d->ccell, 1)), enca, lena); certs_cell_get_certs(d->ccell, 1)->cert_len = lena; REENCODE(); }) CERTS_FAIL(wrong_labels_3, { require_failure_message = "The certs we wanted (ID, Link) were missing"; certs_cell_get_certs(d->ccell, 0)->cert_type = 2; certs_cell_get_certs(d->ccell, 1)->cert_type = 3; REENCODE(); }) CERTS_FAIL(server_missing_certs, { require_failure_message = "The certs we wanted (ID, Auth) were missing"; d->c->handshake_state->started_here = 0; d->c->handshake_state->certs->started_here = 0; }) CERTS_FAIL(server_wrong_labels_1, { require_failure_message = "The authentication certificate was not valid"; d->c->handshake_state->started_here = 0; d->c->handshake_state->certs->started_here = 0; certs_cell_get_certs(d->ccell, 0)->cert_type = 2; certs_cell_get_certs(d->ccell, 1)->cert_type = 3; REENCODE(); }) static void test_link_handshake_send_authchallenge(void *arg) { (void)arg; or_connection_t *c1 = or_connection_new(CONN_TYPE_OR, AF_INET); var_cell_t *cell1=NULL, *cell2=NULL; MOCK(connection_or_write_var_cell_to_buf, mock_write_var_cell); tt_int_op(connection_init_or_handshake_state(c1, 0), ==, 0); c1->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; tt_assert(! mock_got_var_cell); tt_int_op(0, ==, connection_or_send_auth_challenge_cell(c1)); cell1 = mock_got_var_cell; tt_int_op(0, ==, connection_or_send_auth_challenge_cell(c1)); cell2 = mock_got_var_cell; tt_int_op(40, ==, cell1->payload_len); tt_int_op(40, ==, cell2->payload_len); tt_int_op(0, ==, cell1->circ_id); tt_int_op(0, ==, cell2->circ_id); tt_int_op(CELL_AUTH_CHALLENGE, ==, cell1->command); tt_int_op(CELL_AUTH_CHALLENGE, ==, cell2->command); tt_mem_op("\x00\x03\x00\x01\x00\x02\x00\x03", ==, cell1->payload + 32, 8); tt_mem_op("\x00\x03\x00\x01\x00\x02\x00\x03", ==, cell2->payload + 32, 8); tt_mem_op(cell1->payload, !=, cell2->payload, 32); done: UNMOCK(connection_or_write_var_cell_to_buf); connection_free_(TO_CONN(c1)); tor_free(cell1); tor_free(cell2); } typedef struct authchallenge_data_s { or_connection_t *c; channel_tls_t *chan; var_cell_t *cell; } authchallenge_data_t; static int recv_authchallenge_cleanup(const struct testcase_t *test, void *obj) { (void)test; authchallenge_data_t *d = obj; UNMOCK(connection_or_send_netinfo); UNMOCK(connection_or_close_for_error); UNMOCK(connection_or_send_authenticate_cell); if (d) { tor_free(d->cell); connection_free_(TO_CONN(d->c)); circuitmux_free(d->chan->base_.cmux); tor_free(d->chan); tor_free(d); } return 1; } static void * recv_authchallenge_setup(const struct testcase_t *test) { (void)test; authchallenge_data_t *d = tor_malloc_zero(sizeof(*d)); 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->c->handshake_state->received_certs_cell = 1; d->cell = var_cell_new(128); d->cell->payload_len = 38; d->cell->payload[33] = 2; /* 2 methods */ d->cell->payload[35] = 7; /* This one isn't real */ d->cell->payload[37] = 1; /* This is the old RSA one. */ d->cell->command = CELL_AUTH_CHALLENGE; get_options_mutable()->ORPort_set = 1; MOCK(connection_or_close_for_error, mock_close_for_err); MOCK(connection_or_send_netinfo, mock_send_netinfo); MOCK(connection_or_send_authenticate_cell, mock_send_authenticate); tt_int_op(0, ==, d->c->handshake_state->received_auth_challenge); tt_int_op(0, ==, mock_send_authenticate_called); tt_int_op(0, ==, mock_send_netinfo_called); return d; done: recv_authchallenge_cleanup(test, d); return NULL; } static struct testcase_setup_t setup_recv_authchallenge = { .setup_fn = recv_authchallenge_setup, .cleanup_fn = recv_authchallenge_cleanup }; static void test_link_handshake_recv_authchallenge_ok(void *arg) { authchallenge_data_t *d = arg; channel_tls_process_auth_challenge_cell(d->cell, d->chan); tt_int_op(0, ==, mock_close_called); tt_int_op(1, ==, d->c->handshake_state->received_auth_challenge); tt_int_op(1, ==, mock_send_authenticate_called); tt_int_op(1, ==, mock_send_netinfo_called); tt_int_op(1, ==, mock_send_authenticate_called_with_type); /* RSA */ done: ; } static void test_link_handshake_recv_authchallenge_ok_ed25519(void *arg) { authchallenge_data_t *d = arg; /* Add the ed25519 authentication mechanism here. */ d->cell->payload[33] = 3; /* 3 types are supported now. */ d->cell->payload[39] = 3; d->cell->payload_len += 2; channel_tls_process_auth_challenge_cell(d->cell, d->chan); tt_int_op(0, ==, mock_close_called); tt_int_op(1, ==, d->c->handshake_state->received_auth_challenge); tt_int_op(1, ==, mock_send_authenticate_called); tt_int_op(1, ==, mock_send_netinfo_called); tt_int_op(3, ==, mock_send_authenticate_called_with_type); /* Ed25519 */ done: ; } static void test_link_handshake_recv_authchallenge_ok_noserver(void *arg) { authchallenge_data_t *d = arg; get_options_mutable()->ORPort_set = 0; channel_tls_process_auth_challenge_cell(d->cell, d->chan); tt_int_op(0, ==, mock_close_called); tt_int_op(1, ==, d->c->handshake_state->received_auth_challenge); tt_int_op(0, ==, mock_send_authenticate_called); tt_int_op(0, ==, mock_send_netinfo_called); done: ; } static void test_link_handshake_recv_authchallenge_ok_unrecognized(void *arg) { authchallenge_data_t *d = arg; d->cell->payload[37] = 99; channel_tls_process_auth_challenge_cell(d->cell, d->chan); tt_int_op(0, ==, mock_close_called); tt_int_op(1, ==, d->c->handshake_state->received_auth_challenge); tt_int_op(0, ==, mock_send_authenticate_called); tt_int_op(1, ==, mock_send_netinfo_called); done: ; } #define AUTHCHALLENGE_FAIL(name, code) \ static void \ test_link_handshake_recv_authchallenge_ ## name(void *arg) \ { \ authchallenge_data_t *d = arg; \ const char *require_failure_message = NULL; \ setup_capture_of_logs(LOG_INFO); \ { code ; } \ channel_tls_process_auth_challenge_cell(d->cell, d->chan); \ tt_int_op(1, ==, mock_close_called); \ tt_int_op(0, ==, mock_send_authenticate_called); \ tt_int_op(0, ==, mock_send_netinfo_called); \ if (require_failure_message) { \ expect_log_msg_containing(require_failure_message); \ } \ done: \ teardown_capture_of_logs(); \ } AUTHCHALLENGE_FAIL(badstate, require_failure_message = "We're not currently doing a " "v3 handshake"; d->c->base_.state = OR_CONN_STATE_CONNECTING) AUTHCHALLENGE_FAIL(badproto, require_failure_message = "not using link protocol >= 3"; d->c->link_proto = 2) AUTHCHALLENGE_FAIL(as_server, require_failure_message = "We didn't originate this " "connection"; d->c->handshake_state->started_here = 0; d->c->handshake_state->certs->started_here = 0;) AUTHCHALLENGE_FAIL(duplicate, require_failure_message = "We already received one"; d->c->handshake_state->received_auth_challenge = 1) AUTHCHALLENGE_FAIL(nocerts, require_failure_message = "We haven't gotten a CERTS " "cell yet"; d->c->handshake_state->received_certs_cell = 0) AUTHCHALLENGE_FAIL(tooshort, require_failure_message = "It was not well-formed"; d->cell->payload_len = 33) AUTHCHALLENGE_FAIL(truncated, require_failure_message = "It was not well-formed"; d->cell->payload_len = 34) AUTHCHALLENGE_FAIL(nonzero_circid, require_failure_message = "It had a nonzero circuit ID"; d->cell->circ_id = 1337) static int mock_get_tlssecrets(tor_tls_t *tls, uint8_t *secrets_out) { (void)tls; memcpy(secrets_out, "int getRandomNumber(){return 4;}", 32); return 0; } static void mock_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd, int consider_identity) { (void) chan; (void) identity_rcvd; (void) consider_identity; } typedef struct authenticate_data_s { int is_ed; or_connection_t *c1, *c2; channel_tls_t *chan2; var_cell_t *cell; crypto_pk_t *key1, *key2; } authenticate_data_t; static int authenticate_data_cleanup(const struct testcase_t *test, void *arg) { (void) test; UNMOCK(connection_or_write_var_cell_to_buf); UNMOCK(tor_tls_get_peer_cert); UNMOCK(tor_tls_get_tlssecrets); UNMOCK(connection_or_close_for_error); UNMOCK(channel_set_circid_type); UNMOCK(tor_tls_export_key_material); authenticate_data_t *d = arg; if (d) { tor_free(d->cell); connection_or_remove_from_identity_map(d->c1); connection_or_remove_from_identity_map(d->c2); connection_free_(TO_CONN(d->c1)); connection_free_(TO_CONN(d->c2)); circuitmux_free(d->chan2->base_.cmux); tor_free(d->chan2); crypto_pk_free(d->key1); crypto_pk_free(d->key2); tor_free(d); } mock_peer_cert = NULL; return 1; } static void * authenticate_data_setup(const struct testcase_t *test) { authenticate_data_t *d = tor_malloc_zero(sizeof(*d)); int is_ed = d->is_ed = (test->setup_data == (void*)3); scheduler_init(); MOCK(connection_or_write_var_cell_to_buf, mock_write_var_cell); MOCK(tor_tls_get_peer_cert, mock_get_peer_cert); MOCK(tor_tls_get_tlssecrets, mock_get_tlssecrets); MOCK(connection_or_close_for_error, mock_close_for_err); MOCK(channel_set_circid_type, mock_set_circid_type); MOCK(tor_tls_export_key_material, mock_export_key_material); d->c1 = or_connection_new(CONN_TYPE_OR, AF_INET); d->c2 = or_connection_new(CONN_TYPE_OR, AF_INET); tor_addr_from_ipv4h(&d->c1->base_.addr, 0x01020304); tor_addr_from_ipv4h(&d->c2->base_.addr, 0x05060708); 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); init_mock_ed_keys(d->key2); d->c1->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; d->c1->link_proto = 3; tt_int_op(connection_init_or_handshake_state(d->c1, 1), ==, 0); d->c2->base_.state = OR_CONN_STATE_OR_HANDSHAKING_V3; d->c2->link_proto = 3; tt_int_op(connection_init_or_handshake_state(d->c2, 0), ==, 0); var_cell_t *cell = var_cell_new(16); cell->command = CELL_CERTS; or_handshake_state_record_var_cell(d->c1, d->c1->handshake_state, cell, 1); or_handshake_state_record_var_cell(d->c2, d->c2->handshake_state, cell, 0); memset(cell->payload, 0xf0, 16); or_handshake_state_record_var_cell(d->c1, d->c1->handshake_state, cell, 0); or_handshake_state_record_var_cell(d->c2, d->c2->handshake_state, cell, 1); tor_free(cell); d->chan2 = tor_malloc_zero(sizeof(*d->chan2)); channel_tls_common_init(d->chan2); d->c2->chan = d->chan2; d->chan2->conn = d->c2; d->c2->base_.address = tor_strdup("C2"); d->c2->tls = tor_tls_new(-1, 1); d->c2->handshake_state->received_certs_cell = 1; const tor_x509_cert_t *id_cert=NULL, *link_cert=NULL, *auth_cert=NULL; tt_assert(! tor_tls_get_my_certs(1, &link_cert, &id_cert)); const uint8_t *der; size_t sz; tor_x509_cert_get_der(id_cert, &der, &sz); d->c1->handshake_state->certs->id_cert = tor_x509_cert_decode(der, sz); d->c2->handshake_state->certs->id_cert = tor_x509_cert_decode(der, sz); if (is_ed) { d->c1->handshake_state->certs->ed_id_sign = tor_cert_dup(get_master_signing_key_cert()); d->c2->handshake_state->certs->ed_id_sign = tor_cert_dup(get_master_signing_key_cert()); d->c2->handshake_state->certs->ed_sign_auth = tor_cert_dup(get_current_auth_key_cert()); } else { tt_assert(! tor_tls_get_my_certs(0, &auth_cert, &id_cert)); tor_x509_cert_get_der(auth_cert, &der, &sz); d->c2->handshake_state->certs->auth_cert = tor_x509_cert_decode(der, sz); } tor_x509_cert_get_der(link_cert, &der, &sz); mock_peer_cert = tor_x509_cert_decode(der, sz); tt_assert(mock_peer_cert); /* Make an authenticate cell ... */ int authtype; if (is_ed) authtype = AUTHTYPE_ED25519_SHA256_RFC5705; else authtype = AUTHTYPE_RSA_SHA256_TLSSECRET; tt_int_op(0, ==, connection_or_send_authenticate_cell(d->c1, authtype)); tt_assert(mock_got_var_cell); d->cell = mock_got_var_cell; mock_got_var_cell = NULL; return d; done: authenticate_data_cleanup(test, d); return NULL; } static struct testcase_setup_t setup_authenticate = { .setup_fn = authenticate_data_setup, .cleanup_fn = authenticate_data_cleanup }; static void test_link_handshake_auth_cell(void *arg) { authenticate_data_t *d = arg; auth1_t *auth1 = NULL; crypto_pk_t *auth_pubkey = NULL; /* Is the cell well-formed on the outer layer? */ tt_int_op(d->cell->command, ==, CELL_AUTHENTICATE); tt_int_op(d->cell->payload[0], ==, 0); if (d->is_ed) tt_int_op(d->cell->payload[1], ==, 3); else tt_int_op(d->cell->payload[1], ==, 1); tt_int_op(ntohs(get_uint16(d->cell->payload + 2)), ==, d->cell->payload_len - 4); /* Check it out for plausibility... */ auth_ctx_t ctx; ctx.is_ed = d->is_ed; tt_int_op(d->cell->payload_len-4, ==, auth1_parse(&auth1, d->cell->payload+4, d->cell->payload_len - 4, &ctx)); tt_assert(auth1); if (d->is_ed) { tt_mem_op(auth1->type, ==, "AUTH0003", 8); } else { tt_mem_op(auth1->type, ==, "AUTH0001", 8); } tt_mem_op(auth1->tlssecrets, ==, "int getRandomNumber(){return 4;}", 32); /* Is the signature okay? */ const uint8_t *start = d->cell->payload+4, *end = auth1->end_of_signed; if (d->is_ed) { ed25519_signature_t sig; tt_int_op(auth1_getlen_sig(auth1), ==, ED25519_SIG_LEN); memcpy(&sig.sig, auth1_getarray_sig(auth1), ED25519_SIG_LEN); tt_assert(!ed25519_checksig(&sig, start, end-start, &get_current_auth_keypair()->pubkey)); } else { uint8_t sig[128]; uint8_t digest[32]; tt_int_op(auth1_getlen_sig(auth1), >, 120); auth_pubkey = tor_tls_cert_get_key(d->c2->handshake_state->certs->auth_cert); int n = crypto_pk_public_checksig( auth_pubkey, (char*)sig, sizeof(sig), (char*)auth1_getarray_sig(auth1), auth1_getlen_sig(auth1)); tt_int_op(n, ==, 32); crypto_digest256((char*)digest, (const char*)start, end-start, DIGEST_SHA256); tt_mem_op(sig, ==, digest, 32); } /* Then feed it to c2. */ tt_int_op(d->c2->handshake_state->authenticated, ==, 0); channel_tls_process_authenticate_cell(d->cell, d->chan2); tt_int_op(mock_close_called, ==, 0); tt_int_op(d->c2->handshake_state->authenticated, ==, 1); if (d->is_ed) { tt_int_op(d->c2->handshake_state->authenticated_ed25519, ==, 1); tt_int_op(d->c2->handshake_state->authenticated_rsa, ==, 1); } else { tt_int_op(d->c2->handshake_state->authenticated_ed25519, ==, 0); tt_int_op(d->c2->handshake_state->authenticated_rsa, ==, 1); } done: auth1_free(auth1); crypto_pk_free(auth_pubkey); } #define AUTHENTICATE_FAIL(name, code) \ static void \ test_link_handshake_auth_ ## name(void *arg) \ { \ authenticate_data_t *d = arg; \ const char *require_failure_message = NULL; \ setup_capture_of_logs(LOG_INFO); \ { code ; } \ tt_int_op(d->c2->handshake_state->authenticated, ==, 0); \ channel_tls_process_authenticate_cell(d->cell, d->chan2); \ tt_int_op(mock_close_called, ==, 1); \ tt_int_op(d->c2->handshake_state->authenticated, ==, 0); \ if (require_failure_message) { \ expect_log_msg_containing(require_failure_message); \ } \ done: \ teardown_capture_of_logs(); \ } AUTHENTICATE_FAIL(badstate, require_failure_message = "We're not doing a v3 handshake"; d->c2->base_.state = OR_CONN_STATE_CONNECTING) AUTHENTICATE_FAIL(badproto, require_failure_message = "not using link protocol >= 3"; d->c2->link_proto = 2) AUTHENTICATE_FAIL(atclient, require_failure_message = "We originated this connection"; d->c2->handshake_state->started_here = 1; d->c2->handshake_state->certs->started_here = 1;) AUTHENTICATE_FAIL(duplicate, require_failure_message = "We already got one"; d->c2->handshake_state->received_authenticate = 1) static void test_link_handshake_auth_already_authenticated(void *arg) { authenticate_data_t *d = arg; setup_capture_of_logs(LOG_INFO); d->c2->handshake_state->authenticated = 1; channel_tls_process_authenticate_cell(d->cell, d->chan2); tt_int_op(mock_close_called, ==, 1); tt_int_op(d->c2->handshake_state->authenticated, ==, 1); expect_log_msg_containing("The peer is already authenticated"); done: teardown_capture_of_logs(); } AUTHENTICATE_FAIL(nocerts, require_failure_message = "We never got a certs cell"; d->c2->handshake_state->received_certs_cell = 0) AUTHENTICATE_FAIL(noidcert, require_failure_message = "We never got an identity " "certificate"; tor_x509_cert_free(d->c2->handshake_state->certs->id_cert); d->c2->handshake_state->certs->id_cert = NULL) AUTHENTICATE_FAIL(noauthcert, require_failure_message = "We never got an RSA " "authentication certificate"; tor_x509_cert_free(d->c2->handshake_state->certs->auth_cert); d->c2->handshake_state->certs->auth_cert = NULL) AUTHENTICATE_FAIL(tooshort, require_failure_message = "Cell was way too short"; d->cell->payload_len = 3) AUTHENTICATE_FAIL(badtype, require_failure_message = "Authenticator type was not " "recognized"; d->cell->payload[0] = 0xff) AUTHENTICATE_FAIL(truncated_1, require_failure_message = "Authenticator was truncated"; d->cell->payload[2]++) AUTHENTICATE_FAIL(truncated_2, require_failure_message = "Authenticator was truncated"; d->cell->payload[3]++) AUTHENTICATE_FAIL(tooshort_1, require_failure_message = "Authenticator was too short"; tt_int_op(d->cell->payload_len, >=, 260); d->cell->payload[2] -= 1; d->cell->payload_len -= 256;) AUTHENTICATE_FAIL(badcontent, require_failure_message = "Some field in the AUTHENTICATE " "cell body was not as expected"; d->cell->payload[10] ^= 0xff) AUTHENTICATE_FAIL(badsig_1, if (d->is_ed) require_failure_message = "Ed25519 signature wasn't valid"; else require_failure_message = "RSA signature wasn't valid"; d->cell->payload[d->cell->payload_len - 5] ^= 0xff) AUTHENTICATE_FAIL(missing_ed_id, { tor_cert_free(d->c2->handshake_state->certs->ed_id_sign); d->c2->handshake_state->certs->ed_id_sign = NULL; require_failure_message = "Ed authenticate without Ed ID " "cert from peer"; }) AUTHENTICATE_FAIL(missing_ed_auth, { tor_cert_free(d->c2->handshake_state->certs->ed_sign_auth); d->c2->handshake_state->certs->ed_sign_auth = NULL; require_failure_message = "We never got an Ed25519 " "authentication certificate"; }) #define TEST_RSA(name, flags) \ { #name , test_link_handshake_ ## name, (flags), \ &passthrough_setup, (void*)"RSA" } #define TEST_ED(name, flags) \ { #name "_ed25519" , test_link_handshake_ ## name, (flags), \ &passthrough_setup, (void*)"Ed25519" } #define TEST_RCV_AUTHCHALLENGE(name) \ { "recv_authchallenge/" #name , \ test_link_handshake_recv_authchallenge_ ## name, TT_FORK, \ &setup_recv_authchallenge, NULL } #define TEST_RCV_CERTS(name) \ { "recv_certs/" #name , \ test_link_handshake_recv_certs_ ## name, TT_FORK, \ &setup_recv_certs, (void*)"RSA-Link" } #define TEST_RCV_CERTS_RSA(name,type) \ { "recv_certs/" #name , \ test_link_handshake_recv_certs_ ## name, TT_FORK, \ &setup_recv_certs, (void*)type } #define TEST_RCV_CERTS_ED(name, type) \ { "recv_certs/" #name "_ed25519", \ test_link_handshake_recv_certs_ ## name, TT_FORK, \ &setup_recv_certs, (void*)type } #define TEST_AUTHENTICATE(name) \ { "authenticate/" #name , test_link_handshake_auth_ ## name, TT_FORK, \ &setup_authenticate, NULL } #define TEST_AUTHENTICATE_ED(name) \ { "authenticate/" #name "_ed25519" , test_link_handshake_auth_ ## name, \ TT_FORK, &setup_authenticate, (void*)3 } struct testcase_t link_handshake_tests[] = { TEST_RSA(certs_ok, TT_FORK), TEST_ED(certs_ok, TT_FORK), TEST_RCV_CERTS(ok), TEST_RCV_CERTS_ED(ok, "Ed25519-Link"), TEST_RCV_CERTS_RSA(ok_server, "RSA-Auth"), TEST_RCV_CERTS_ED(ok_server, "Ed25519-Auth"), TEST_RCV_CERTS(badstate), TEST_RCV_CERTS(badproto), TEST_RCV_CERTS(duplicate), TEST_RCV_CERTS(already_authenticated), TEST_RCV_CERTS(empty), TEST_RCV_CERTS(bad_circid), TEST_RCV_CERTS(truncated_1), TEST_RCV_CERTS(truncated_2), TEST_RCV_CERTS(truncated_3), TEST_RCV_CERTS_ED(truncated_4, "Ed25519-Link"), TEST_RCV_CERTS_ED(truncated_5, "Ed25519-Link"), TEST_RCV_CERTS_ED(truncated_6, "Ed25519-Link"), TEST_RCV_CERTS_ED(truncated_7, "Ed25519-Link"), TEST_RCV_CERTS(not_x509), TEST_RCV_CERTS(both_link), TEST_RCV_CERTS(both_id_rsa), TEST_RCV_CERTS(both_auth), TEST_RCV_CERTS_ED(duplicate_id, "Ed25519-Link"), TEST_RCV_CERTS_ED(duplicate_link, "Ed25519-Link"), TEST_RCV_CERTS_ED(duplicate_crosscert, "Ed25519-Link"), TEST_RCV_CERTS_ED(missing_crosscert, "Ed25519-Link"), TEST_RCV_CERTS_ED(missing_id, "Ed25519-Link"), TEST_RCV_CERTS_ED(missing_signing_key, "Ed25519-Link"), TEST_RCV_CERTS_ED(missing_link, "Ed25519-Link"), TEST_RCV_CERTS_ED(missing_auth, "Ed25519-Auth"), TEST_RCV_CERTS_ED(missing_rsa_id, "Ed25519-Link"), TEST_RCV_CERTS_ED(link_mismatch, "Ed25519-Link"), TEST_RCV_CERTS_ED(bad_ed_sig, "Ed25519-Link"), TEST_RCV_CERTS_ED(bad_rsa_id_cert, "Ed25519-Link"), TEST_RCV_CERTS_ED(bad_crosscert, "Ed25519-Link"), TEST_RCV_CERTS_RSA(expired_rsa_id, "RSA-Link"), TEST_RCV_CERTS_ED(expired_rsa_id, "Ed25519-Link"), TEST_RCV_CERTS_ED(expired_ed_id, "Ed25519-Link"), TEST_RCV_CERTS_ED(expired_ed_link, "Ed25519-Link"), TEST_RCV_CERTS_ED(expired_crosscert, "Ed25519-Link"), TEST_RCV_CERTS(wrong_labels_1), TEST_RCV_CERTS(wrong_labels_2), TEST_RCV_CERTS(wrong_labels_3), TEST_RCV_CERTS(server_missing_certs), TEST_RCV_CERTS(server_wrong_labels_1), TEST_RSA(send_authchallenge, TT_FORK), TEST_RCV_AUTHCHALLENGE(ok), TEST_RCV_AUTHCHALLENGE(ok_ed25519), TEST_RCV_AUTHCHALLENGE(ok_noserver), TEST_RCV_AUTHCHALLENGE(ok_unrecognized), TEST_RCV_AUTHCHALLENGE(badstate), TEST_RCV_AUTHCHALLENGE(badproto), TEST_RCV_AUTHCHALLENGE(as_server), TEST_RCV_AUTHCHALLENGE(duplicate), TEST_RCV_AUTHCHALLENGE(nocerts), TEST_RCV_AUTHCHALLENGE(tooshort), TEST_RCV_AUTHCHALLENGE(truncated), TEST_RCV_AUTHCHALLENGE(nonzero_circid), TEST_AUTHENTICATE(cell), TEST_AUTHENTICATE_ED(cell), TEST_AUTHENTICATE(badstate), TEST_AUTHENTICATE(badproto), TEST_AUTHENTICATE(atclient), TEST_AUTHENTICATE(duplicate), TEST_AUTHENTICATE(already_authenticated), TEST_AUTHENTICATE(nocerts), TEST_AUTHENTICATE(noidcert), TEST_AUTHENTICATE(noauthcert), TEST_AUTHENTICATE(tooshort), TEST_AUTHENTICATE(badtype), TEST_AUTHENTICATE(truncated_1), TEST_AUTHENTICATE(truncated_2), TEST_AUTHENTICATE(tooshort_1), TEST_AUTHENTICATE(badcontent), TEST_AUTHENTICATE(badsig_1), TEST_AUTHENTICATE_ED(badsig_1), TEST_AUTHENTICATE_ED(missing_ed_id), TEST_AUTHENTICATE_ED(missing_ed_auth), //TEST_AUTHENTICATE(), END_OF_TESTCASES };