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_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); }
/** Create a new TLS context for use with Tor TLS handshakes. * <b>identity</b> should be set to the identity key used to sign the * certificate, and <b>nickname</b> set to the nickname to use. * * You can call this function multiple times. Each time you call it, * it generates new certificates; all new connections will use * the new SSL context. */ int tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) { crypto_pk_env_t *rsa = NULL; EVP_PKEY *pkey = NULL; tor_tls_context_t *result = NULL; X509 *cert = NULL, *idcert = NULL; char *nickname = NULL, *nn2 = NULL; tor_tls_init(); nickname = crypto_random_hostname(8, 20, "www.", ".net"); nn2 = crypto_random_hostname(8, 20, "www.", ".net"); /* Generate short-term RSA key. */ if (!(rsa = crypto_new_pk_env())) goto error; if (crypto_pk_generate_key(rsa)<0) goto error; /* Create certificate signed by identity key. */ cert = tor_tls_create_certificate(rsa, identity, nickname, nn2, key_lifetime); /* Create self-signed certificate for identity key. */ idcert = tor_tls_create_certificate(identity, identity, nn2, nn2, IDENTITY_CERT_LIFETIME); if (!cert || !idcert) { log(LOG_WARN, LD_CRYPTO, "Error creating certificate"); goto error; } result = tor_malloc_zero(sizeof(tor_tls_context_t)); result->refcnt = 1; result->my_cert = X509_dup(cert); result->my_id_cert = X509_dup(idcert); result->key = crypto_pk_dup_key(rsa); #ifdef EVERYONE_HAS_AES /* Tell OpenSSL to only use TLS1 */ if (!(result->ctx = SSL_CTX_new(TLSv1_method()))) goto error; #else /* Tell OpenSSL to use SSL3 or TLS1 but not SSL2. */ if (!(result->ctx = SSL_CTX_new(SSLv23_method()))) goto error; SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv2); #endif SSL_CTX_set_options(result->ctx, SSL_OP_SINGLE_DH_USE); #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION SSL_CTX_set_options(result->ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif /* Yes, we know what we are doing here. No, we do not treat a renegotiation * as authenticating any earlier-received data. */ if (use_unsafe_renegotiation_op) { SSL_CTX_set_options(result->ctx, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); } /* Don't actually allow compression; it uses ram and time, but the data * we transmit is all encrypted anyway. */ if (result->ctx->comp_methods) result->ctx->comp_methods = NULL; #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(result->ctx, SSL_MODE_RELEASE_BUFFERS); #endif if (cert && !SSL_CTX_use_certificate(result->ctx,cert)) goto error; X509_free(cert); /* We just added a reference to cert. */ cert=NULL; if (idcert) { X509_STORE *s = SSL_CTX_get_cert_store(result->ctx); tor_assert(s); X509_STORE_add_cert(s, idcert); X509_free(idcert); /* The context now owns the reference to idcert */ idcert = NULL; } SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF); tor_assert(rsa); if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1))) goto error; if (!SSL_CTX_use_PrivateKey(result->ctx, pkey)) goto error; EVP_PKEY_free(pkey); pkey = NULL; if (!SSL_CTX_check_private_key(result->ctx)) goto error; { crypto_dh_env_t *dh = crypto_dh_new(); SSL_CTX_set_tmp_dh(result->ctx, _crypto_dh_env_get_dh(dh)); crypto_dh_free(dh); } SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER, always_accept_verify_cb); /* let us realloc bufs that we're writing from */ SSL_CTX_set_mode(result->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); /* Free the old context if one exists. */ if (global_tls_context) { /* This is safe even if there are open connections: OpenSSL does * reference counting with SSL and SSL_CTX objects. */ tor_tls_context_decref(global_tls_context); } global_tls_context = result; if (rsa) crypto_free_pk_env(rsa); tor_free(nickname); tor_free(nn2); return 0; error: tls_log_errors(NULL, LOG_WARN, "creating TLS context"); tor_free(nickname); tor_free(nn2); if (pkey) EVP_PKEY_free(pkey); if (rsa) crypto_free_pk_env(rsa); if (result) tor_tls_context_decref(result); if (cert) X509_free(cert); if (idcert) X509_free(idcert); return -1; }