/** 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; }
hs_desc_intro_point_t * hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now, const char *addr, int legacy) { int ret; ed25519_keypair_t auth_kp; hs_desc_intro_point_t *intro_point = NULL; hs_desc_intro_point_t *ip = hs_desc_intro_point_new(); /* For a usable intro point we need at least two link specifiers: One legacy * keyid and one ipv4 */ { tor_addr_t a; tor_addr_make_unspec(&a); link_specifier_t *ls_legacy = link_specifier_new(); link_specifier_t *ls_ip = link_specifier_new(); link_specifier_set_ls_type(ls_legacy, LS_LEGACY_ID); memset(link_specifier_getarray_un_legacy_id(ls_legacy), 'C', link_specifier_getlen_un_legacy_id(ls_legacy)); int family = tor_addr_parse(&a, addr); switch (family) { case AF_INET: link_specifier_set_ls_type(ls_ip, LS_IPV4); link_specifier_set_un_ipv4_addr(ls_ip, tor_addr_to_ipv4h(&a)); link_specifier_set_un_ipv4_port(ls_ip, 9001); break; case AF_INET6: link_specifier_set_ls_type(ls_ip, LS_IPV6); memcpy(link_specifier_getarray_un_ipv6_addr(ls_ip), tor_addr_to_in6_addr8(&a), link_specifier_getlen_un_ipv6_addr(ls_ip)); link_specifier_set_un_ipv6_port(ls_ip, 9001); break; default: /* Stop the test, not supposed to have an error. * Compare with -1 to show the actual family. */ tt_int_op(family, OP_EQ, -1); } smartlist_add(ip->link_specifiers, ls_legacy); smartlist_add(ip->link_specifiers, ls_ip); } ret = ed25519_keypair_generate(&auth_kp, 0); tt_int_op(ret, ==, 0); ip->auth_key_cert = tor_cert_create(signing_kp, CERT_TYPE_AUTH_HS_IP_KEY, &auth_kp.pubkey, now, HS_DESC_CERT_LIFETIME, CERT_FLAG_INCLUDE_SIGNING_KEY); tt_assert(ip->auth_key_cert); if (legacy) { ip->legacy.key = crypto_pk_new(); tt_assert(ip->legacy.key); ret = crypto_pk_generate_key(ip->legacy.key); tt_int_op(ret, ==, 0); ssize_t cert_len = tor_make_rsa_ed25519_crosscert( &signing_kp->pubkey, ip->legacy.key, now + HS_DESC_CERT_LIFETIME, &ip->legacy.cert.encoded); tt_assert(ip->legacy.cert.encoded); tt_u64_op(cert_len, OP_GT, 0); ip->legacy.cert.len = cert_len; } /* Encryption key. */ { int signbit; curve25519_keypair_t curve25519_kp; ed25519_keypair_t ed25519_kp; tor_cert_t *cross_cert; ret = curve25519_keypair_generate(&curve25519_kp, 0); tt_int_op(ret, ==, 0); ed25519_keypair_from_curve25519_keypair(&ed25519_kp, &signbit, &curve25519_kp); cross_cert = tor_cert_create(signing_kp, CERT_TYPE_CROSS_HS_IP_KEYS, &ed25519_kp.pubkey, time(NULL), HS_DESC_CERT_LIFETIME, CERT_FLAG_INCLUDE_SIGNING_KEY); tt_assert(cross_cert); ip->enc_key_cert = cross_cert; } intro_point = ip; done: if (intro_point == NULL) tor_free(ip); return intro_point; }