Commit c44016e8 authored by Nick Mathewson's avatar Nick Mathewson
Browse files

Merge flagday into main branch.


svn:r1683
parent 83081f5a
......@@ -127,13 +127,18 @@ RSA *_crypto_pk_env_get_rsa(crypto_pk_env_t *env)
}
/* used by tortls.c */
EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env)
EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env, int private)
{
RSA *key = NULL;
EVP_PKEY *pkey = NULL;
assert(env->key);
if (!(key = RSAPrivateKey_dup(env->key)))
goto error;
if (private) {
if (!(key = RSAPrivateKey_dup(env->key)))
goto error;
} else {
if (!(key = RSAPublicKey_dup(env->key)))
goto error;
}
if (!(pkey = EVP_PKEY_new()))
goto error;
if (!(EVP_PKEY_assign_RSA(pkey, key)))
......
......@@ -23,8 +23,8 @@
#include <openssl/asn1.h>
#include <openssl/bio.h>
/* How long do certificates live? (sec) */
#define CERT_LIFETIME (365*24*60*60)
/* How long do identity certificates live? (sec) */
#define IDENTITY_CERT_LIFETIME (365*24*60*60)
/* How much clock skew do we tolerate when checking certificates? (sec) */
#define CERT_ALLOW_SKEW (90*60)
......@@ -44,7 +44,10 @@ struct tor_tls_st {
};
static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa,
const char *nickname);
crypto_pk_env_t *rsa_sign,
const char *cname,
const char *cname_sign,
unsigned int lifetime);
/* global tls context, keep it here because nobody else needs to touch it */
static tor_tls_context *global_tls_context = NULL;
......@@ -54,7 +57,7 @@ static int tls_library_is_initialized = 0;
#define _TOR_TLS_ZERORETURN -5
/* These functions are declared in crypto.c but not exported. */
EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env);
EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env, int private);
crypto_pk_env_t *_crypto_new_pk_env_rsa(RSA *rsa);
DH *_crypto_dh_env_get_dh(crypto_dh_env_t *dh);
......@@ -129,26 +132,32 @@ static int always_accept_verify_cb(int preverify_ok,
}
/* Generate a self-signed certificate with the private key 'rsa' and
* commonName 'nickname', and write it, PEM-encoded, to the file named
* by 'certfile'. Return 0 on success, -1 for failure.
* identity key 'identity and commonName 'nickname'. Return a certificate
* on success, NULL on failure.
* DOCDOC
*/
X509 *
tor_tls_create_certificate(crypto_pk_env_t *rsa,
const char *nickname)
crypto_pk_env_t *rsa_sign,
const char *cname,
const char *cname_sign,
unsigned int cert_lifetime)
{
time_t start_time, end_time;
EVP_PKEY *pkey = NULL;
EVP_PKEY *sign_pkey = NULL, *pkey=NULL;
X509 *x509 = NULL;
X509_NAME *name = NULL;
X509_NAME *name = NULL, *name_issuer=NULL;
int nid;
tor_tls_init();
start_time = time(NULL);
assert(rsa && nickname);
if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa)))
return NULL;
assert(rsa && cname && rsa_sign && cname_sign);
if (!(sign_pkey = _crypto_pk_env_get_evp_pkey(rsa_sign,1)))
goto error;
if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,0)))
goto error;
if (!(x509 = X509_new()))
goto error;
if (!(X509_set_version(x509, 2)))
......@@ -163,20 +172,29 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
"TOR", -1, -1, 0))) goto error;
if ((nid = OBJ_txt2nid("commonName")) == NID_undef) goto error;
if (!(X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC,
(char*)nickname, -1, -1, 0))) goto error;
(char*)cname, -1, -1, 0))) goto error;
if (!(X509_set_subject_name(x509, name)))
goto error;
if (!(X509_set_issuer_name(x509, name)))
if (!(name_issuer = X509_NAME_new()))
goto error;
if (!(X509_set_subject_name(x509, name)))
if ((nid = OBJ_txt2nid("organizationName")) == NID_undef) goto error;
if (!(X509_NAME_add_entry_by_NID(name_issuer, nid, MBSTRING_ASC,
"TOR", -1, -1, 0))) goto error;
if ((nid = OBJ_txt2nid("commonName")) == NID_undef) goto error;
if (!(X509_NAME_add_entry_by_NID(name_issuer, nid, MBSTRING_ASC,
(char*)cname_sign, -1, -1, 0))) goto error;
if (!(X509_set_issuer_name(x509, name_issuer)))
goto error;
if (!X509_time_adj(X509_get_notBefore(x509),0,&start_time))
goto error;
end_time = start_time + CERT_LIFETIME;
end_time = start_time + cert_lifetime;
if (!X509_time_adj(X509_get_notAfter(x509),0,&end_time))
goto error;
if (!X509_set_pubkey(x509, pkey))
goto error;
if (!X509_sign(x509, pkey, EVP_sha1()))
if (!X509_sign(x509, sign_pkey, EVP_sha1()))
goto error;
goto done;
......@@ -186,10 +204,14 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
x509 = NULL;
}
done:
if (sign_pkey)
EVP_PKEY_free(sign_pkey);
if (pkey)
EVP_PKEY_free(pkey);
if (name)
X509_NAME_free(name);
if (name_issuer)
X509_NAME_free(name_issuer);
return x509;
}
......@@ -210,26 +232,37 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
#endif
/* Create a new TLS context. If we are going to be using it as a
* server, it must have isServer set to true, certfile set to a
* filename for a certificate file, and RSA set to the private key
* used for that certificate. Return -1 if failure, else 0.
* server, it must have isServer set to true, 'identity' set to the
* identity key used to sign that certificate, and 'nickname' set to
* the server's nickname. Return -1 if failure, else 0.
*/
int
tor_tls_context_new(crypto_pk_env_t *rsa,
int isServer, const char *nickname)
tor_tls_context_new(crypto_pk_env_t *identity,
int isServer, const char *nickname,
unsigned int key_lifetime)
{
crypto_pk_env_t *rsa = NULL;
crypto_dh_env_t *dh = NULL;
EVP_PKEY *pkey = NULL;
tor_tls_context *result;
X509 *cert = NULL;
tor_tls_context *result = NULL;
X509 *cert = NULL, *idcert = NULL;
char nn2[1024];
sprintf(nn2, "%s <identity>", nickname);
tor_tls_init();
if (rsa) {
cert = tor_tls_create_certificate(rsa, nickname);
if (!cert) {
if (isServer) {
if (!(rsa = crypto_new_pk_env()))
goto error;
if (crypto_pk_generate_key(rsa)<0)
goto error;
cert = tor_tls_create_certificate(rsa, identity, nickname, nn2,
key_lifetime);
idcert = tor_tls_create_certificate(identity, identity, nn2, nn2,
IDENTITY_CERT_LIFETIME);
if (!cert || !idcert) {
log(LOG_WARN, "Error creating certificate");
return -1;
goto error;
}
}
......@@ -249,9 +282,12 @@ tor_tls_context_new(crypto_pk_env_t *rsa,
goto error;
if (cert && !SSL_CTX_use_certificate(result->ctx,cert))
goto error;
if (idcert && !SSL_CTX_add_extra_chain_cert(result->ctx,idcert))
goto error;
SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF);
if (rsa) {
if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa)))
if (isServer) {
assert(rsa);
if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1)))
goto error;
if (!SSL_CTX_use_PrivateKey(result->ctx, pkey))
goto error;
......@@ -283,13 +319,15 @@ tor_tls_context_new(crypto_pk_env_t *rsa,
error:
if (pkey)
EVP_PKEY_free(pkey);
if (rsa)
crypto_free_pk_env(rsa);
if (dh)
crypto_dh_free(dh);
if (result && result->ctx)
SSL_CTX_free(result->ctx);
if (result)
free(result);
/* leak certs XXXX ? */
return -1;
}
......@@ -509,19 +547,19 @@ tor_tls_get_peer_cert_nickname(tor_tls *tls, char *buf, int buflen)
}
/* If the provided tls connection is authenticated and has a
* certificate that is currently valid and is correctly self-signed,
* return its public key. Otherwise return NULL.
* certificate that is currently valid and is correctly signed by
* identity_key, return 0. Else, return -1.
*/
crypto_pk_env_t *
tor_tls_verify(tor_tls *tls)
int
tor_tls_verify(tor_tls *tls, crypto_pk_env_t *identity_key)
{
X509 *cert = NULL;
EVP_PKEY *pkey = NULL;
RSA *rsa = NULL;
EVP_PKEY *id_pkey = NULL;
time_t now, t;
crypto_pk_env_t *r = NULL;
int r = -1;
if (!(cert = SSL_get_peer_certificate(tls->ssl)))
return NULL;
return -1;
now = time(NULL);
t = now + CERT_ALLOW_SKEW;
......@@ -536,33 +574,19 @@ tor_tls_verify(tor_tls *tls)
}
/* Get the public key. */
if (!(pkey = X509_get_pubkey(cert))) {
log_fn(LOG_WARN,"X509_get_pubkey returned null");
goto done;
}
if (X509_verify(cert, pkey) <= 0) {
if (!(id_pkey = _crypto_pk_env_get_evp_pkey(identity_key,0)) ||
X509_verify(cert, id_pkey) <= 0) {
log_fn(LOG_WARN,"X509_verify on cert and pkey returned <= 0");
goto done;
}
rsa = EVP_PKEY_get1_RSA(pkey);
EVP_PKEY_free(pkey);
pkey = NULL;
if (!rsa) {
log_fn(LOG_WARN,"EVP_PKEY_get1_RSA(pkey) returned null");
goto done;
}
r = _crypto_new_pk_env_rsa(rsa);
rsa = NULL;
r = 0;
done:
if (cert)
X509_free(cert);
if (pkey)
EVP_PKEY_free(pkey);
if (rsa)
RSA_free(rsa);
if (id_pkey)
EVP_PKEY_free(id_pkey);
return r;
}
......
......@@ -17,12 +17,13 @@ typedef struct tor_tls_st tor_tls;
#define TOR_TLS_DONE 0
/* X509* tor_tls_write_certificate(char *certfile, crypto_pk_env_t *rsa, char *nickname); */
int tor_tls_context_new(crypto_pk_env_t *rsa, int isServer, const char *nickname);
int tor_tls_context_new(crypto_pk_env_t *rsa, int isServer,
const char *nickname, unsigned int key_lifetime);
tor_tls *tor_tls_new(int sock, int isServer);
void tor_tls_free(tor_tls *tls);
int tor_tls_peer_has_cert(tor_tls *tls);
int tor_tls_get_peer_cert_nickname(tor_tls *tls, char *buf, int buflen);
crypto_pk_env_t *tor_tls_verify(tor_tls *tls);
int tor_tls_verify(tor_tls *tls, crypto_pk_env_t *identity);
int tor_tls_read(tor_tls *tls, char *cp, int len);
int tor_tls_write(tor_tls *tls, char *cp, int n);
int tor_tls_handshake(tor_tls *tls);
......
......@@ -655,6 +655,10 @@ int getconfig(int argc, char **argv, or_options_t *options) {
log(LOG_WARN,"DirFetchPostPeriod option must be positive.");
result = -1;
}
if(options->DirFetchPostPeriod > MIN_ONION_KEY_LIFETIME/2) {
log(LOG_WARN,"DirFetchPostPeriod is too large; clipping.");
options->DirFetchPostPeriod = MIN_ONION_KEY_LIFETIME/2;
}
if(options->KeepalivePeriod < 1) {
log(LOG_WARN,"KeepalivePeriod option must be positive.");
......
......@@ -116,8 +116,6 @@ void connection_free(connection_t *conn) {
if (conn->onion_pkey)
crypto_free_pk_env(conn->onion_pkey);
if (conn->link_pkey)
crypto_free_pk_env(conn->link_pkey);
if (conn->identity_pkey)
crypto_free_pk_env(conn->identity_pkey);
tor_free(conn->nickname);
......
......@@ -84,7 +84,6 @@ void connection_or_init_conn_from_router(connection_t *conn, routerinfo_t *route
conn->port = router->or_port;
conn->receiver_bucket = conn->bandwidth = router->bandwidthburst;
conn->onion_pkey = crypto_pk_dup_key(router->onion_pkey);
conn->link_pkey = crypto_pk_dup_key(router->link_pkey);
conn->identity_pkey = crypto_pk_dup_key(router->identity_pkey);
conn->nickname = tor_strdup(router->nickname);
tor_free(conn->address);
......@@ -178,7 +177,6 @@ int connection_tls_continue_handshake(connection_t *conn) {
}
static int connection_tls_finish_handshake(connection_t *conn) {
crypto_pk_env_t *pk;
routerinfo_t *router;
char nickname[MAX_NICKNAME_LEN+1];
connection_t *c;
......@@ -203,42 +201,34 @@ static int connection_tls_finish_handshake(connection_t *conn) {
return -1;
}
log_fn(LOG_DEBUG, "Other side claims to be '%s'", nickname);
pk = tor_tls_verify(conn->tls);
if(!pk) {
log_fn(LOG_WARN,"Other side '%s' (%s:%d) has a cert but it's invalid. Closing.",
nickname, conn->address, conn->port);
router = router_get_by_nickname(nickname);
if (!router) {
log_fn(LOG_INFO, "Unrecognized router with nickname '%s'", nickname);
return -1;
}
router = router_get_by_link_pk(pk);
if (!router) {
log_fn(LOG_INFO,"Unrecognized public key from peer '%s' (%s:%d). Closing.",
if(tor_tls_verify(conn->tls, router->identity_pkey)<0) {
log_fn(LOG_WARN,"Other side '%s' (%s:%d) has a cert but it's invalid. Closing.",
nickname, conn->address, conn->port);
crypto_free_pk_env(pk);
return -1;
}
if(conn->link_pkey) { /* I initiated this connection. */
if(crypto_pk_cmp_keys(conn->link_pkey, pk)) {
log_fn(LOG_WARN,"We connected to '%s' (%s:%d) but he gave us a different key. Closing.",
nickname, conn->address, conn->port);
crypto_free_pk_env(pk);
log_fn(LOG_DEBUG,"The router's cert is valid.");
if (conn->nickname) {
/* I initiated this connection. */
if (strcmp(conn->nickname, nickname)) {
log_fn(options.DirPort ? LOG_WARN : LOG_INFO,
"Other side is '%s', but we tried to connect to '%s'",
nickname, conn->nickname);
return -1;
}
log_fn(LOG_DEBUG,"The router's pk matches the one we meant to connect to. Good.");
} else {
if((c=connection_exact_get_by_addr_port(router->addr,router->or_port))) {
log_fn(LOG_INFO,"Router %s is already connected on fd %d. Dropping fd %d.", router->nickname, c->s, conn->s);
crypto_free_pk_env(pk);
return -1;
}
connection_or_init_conn_from_router(conn, router);
}
crypto_free_pk_env(pk);
if (strcmp(conn->nickname, nickname)) {
log_fn(options.DirPort ? LOG_WARN : LOG_INFO,
"Other side claims to be '%s', but we expected '%s'",
nickname, conn->nickname);
return -1;
connection_or_init_conn_from_router(conn,router);
}
if (!options.ORPort) { /* If I'm an OP... */
conn->receiver_bucket = conn->bandwidth = DEFAULT_BANDWIDTH_OP;
}
......
......@@ -12,8 +12,9 @@ extern or_options_t options; /* command-line and config-file options */
#define LEN_ONION_QUESTION (1+TAG_LEN+ONIONSKIN_CHALLENGE_LEN)
#define LEN_ONION_RESPONSE (1+TAG_LEN+ONIONSKIN_REPLY_LEN+40+32)
int num_cpuworkers=0;
int num_cpuworkers_busy=0;
static int num_cpuworkers=0;
static int num_cpuworkers_busy=0;
static time_t last_rotation_time=0;
int cpuworker_main(void *data);
static int spawn_cpuworker(void);
......@@ -21,6 +22,7 @@ static void spawn_enough_cpuworkers(void);
static void process_pending_task(connection_t *cpuworker);
void cpu_init(void) {
last_rotation_time=time(NULL);
spawn_enough_cpuworkers();
}
......@@ -47,6 +49,18 @@ static void tag_unpack(char *tag, uint32_t *addr, uint16_t *port, uint16_t *circ
log_fn(LOG_DEBUG,"onion was from %s:%d, circ_id %d.", inet_ntoa(in), *port, *circ_id);
}
void cpuworkers_rotate(void)
{
connection_t *cpuworker;
while ((cpuworker = connection_get_by_type_state(CONN_TYPE_CPUWORKER,
CPUWORKER_STATE_IDLE))) {
connection_mark_for_close(cpuworker,0);
--num_cpuworkers;
}
last_rotation_time = time(NULL);
spawn_enough_cpuworkers();
}
int connection_cpu_process_inbuf(connection_t *conn) {
char success;
unsigned char buf[LEN_ONION_RESPONSE];
......@@ -111,7 +125,13 @@ int connection_cpu_process_inbuf(connection_t *conn) {
done_processing:
conn->state = CPUWORKER_STATE_IDLE;
num_cpuworkers_busy--;
process_pending_task(conn);
if (conn->timestamp_created < last_rotation_time) {
connection_mark_for_close(conn,0);
num_cpuworkers--;
spawn_enough_cpuworkers();
} else {
process_pending_task(conn);
}
return 0;
}
......@@ -126,6 +146,7 @@ int cpuworker_main(void *data) {
unsigned char reply_to_proxy[ONIONSKIN_REPLY_LEN];
unsigned char buf[LEN_ONION_RESPONSE];
char tag[TAG_LEN];
crypto_pk_env_t *onion_key = NULL, *last_onion_key = NULL;
close(fdarray[0]); /* this is the side of the socketpair the parent uses */
fd = fdarray[1]; /* this side is ours */
......@@ -133,27 +154,32 @@ int cpuworker_main(void *data) {
connection_free_all(); /* so the child doesn't hold the parent's fd's open */
#endif
/* XXXX WINDOWS lock here. */
onion_key = crypto_pk_dup_key(get_onion_key());
if (get_previous_onion_key())
last_onion_key = crypto_pk_dup_key(get_previous_onion_key());
for(;;) {
if(recv(fd, &question_type, 1, 0) != 1) {
// log_fn(LOG_ERR,"read type failed. Exiting.");
log_fn(LOG_INFO,"cpuworker exiting because tor process died.");
spawn_exit();
goto end;
}
assert(question_type == CPUWORKER_TASK_ONION);
if(read_all(fd, tag, TAG_LEN, 1) != TAG_LEN) {
log_fn(LOG_ERR,"read tag failed. Exiting.");
spawn_exit();
goto end;
}
if(read_all(fd, question, ONIONSKIN_CHALLENGE_LEN, 1) != ONIONSKIN_CHALLENGE_LEN) {
log_fn(LOG_ERR,"read question failed. Exiting.");
spawn_exit();
goto end;
}
if(question_type == CPUWORKER_TASK_ONION) {
if(onion_skin_server_handshake(question, get_onion_key(),
if(onion_skin_server_handshake(question, onion_key, last_onion_key,
reply_to_proxy, keys, 40+32) < 0) {
/* failure */
log_fn(LOG_WARN,"onion_skin_server_handshake failed.");
......@@ -173,6 +199,12 @@ int cpuworker_main(void *data) {
log_fn(LOG_DEBUG,"finished writing response.");
}
}
end:
if (onion_key)
crypto_free_pk_env(onion_key);
if (last_onion_key)
crypto_free_pk_env(last_onion_key);
spawn_exit();
return 0; /* windows wants this function to return an int */
}
......@@ -263,7 +295,7 @@ int assign_to_cpuworker(connection_t *cpuworker, unsigned char question_type,
return 0;
}
if(!cpuworker)
if (!cpuworker)
cpuworker = connection_get_by_type_state(CONN_TYPE_CPUWORKER, CPUWORKER_STATE_IDLE);
assert(cpuworker);
......
......@@ -437,8 +437,13 @@ dirserv_dump_directory_to_string(char *s, int maxlen,
/* These multiple strlcat calls are inefficient, but dwarfed by the RSA
signature.
*/
if (strlcat(s, "directory-signature\n", maxlen) >= maxlen)
if (strlcat(s, "directory-signature ", maxlen) >= maxlen)
goto truncated;
if (strlcat(s, options.Nickname, maxlen) >= maxlen)
goto truncated;
if (strlcat(s, "\n", maxlen) >= maxlen)
goto truncated;
if (router_get_dir_hash(s,digest)) {
log_fn(LOG_WARN,"couldn't compute digest");
......
......@@ -53,6 +53,7 @@ int has_completed_circuit=0;
****************************************************************************/
int connection_add(connection_t *conn) {
assert(conn);
if(nfds >= options.MaxConn-1) {
log_fn(LOG_WARN,"failing because nfds is too high.");
......@@ -345,9 +346,38 @@ static void run_connection_housekeeping(int i, time_t now) {
static void run_scheduled_events(time_t now) {
static long time_to_fetch_directory = 0;
static time_t last_uploaded_services = 0;
static time_t last_rotated_certificate = 0;
int i;
/* 1. Every DirFetchPostPeriod seconds, we get a new directory and upload
/* 1a. Every MIN_ONION_KEY_LIFETIME seconds, rotate the onion keys,
* shut down and restart all cpuworkers, and update the directory if
* necessary.
*/
if (options.ORPort && get_onion_key_set_at()+MIN_ONION_KEY_LIFETIME < now) {
rotate_onion_key();
cpuworkers_rotate();
if (router_rebuild_descriptor()<0) {
log_fn(LOG_WARN, "Couldn't rebuild router descriptor");
}
router_rebuild_descriptor();
router_upload_dir_desc_to_dirservers();
}
/* 1b. Every MAX_LINK_KEY_LIFETIME seconds, we change our TLS context. */
if (!last_rotated_certificate)
last_rotated_certificate = now;
if (options.ORPort && last_rotated_certificate+MAX_SSL_KEY_LIFETIME < now) {
if (tor_tls_context_new(get_identity_key(), 1, options.Nickname,
MAX_SSL_KEY_LIFETIME) < 0) {
log_fn(LOG_WARN, "Error reinitializing TLS context");
}
last_rotated_certificate = now;
/* XXXX We should rotate TLS connections as well; this code doesn't change
* XXXX them at all. */
}
/* 1c. Every DirFetchPostPeriod seconds, we get a new directory and upload
* our descriptor (if any). */
if(time_to_fetch_directory < now) {
/* it's time to fetch a new directory and/or post our descriptor */
......@@ -371,6 +401,7 @@ static void run_scheduled_events(time_t now) {
time_to_fetch_directory = now + options.DirFetchPostPeriod;
}
/* 2. Every second, we examine pending circuits and prune the
* ones which have been pending for more than a few seconds.
* We do this before step 3, so it can try building more if
......
......@@ -576,9 +576,6 @@ int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state, rout
[16 bytes] Symmetric key for encrypting blob past RSA
[112 bytes] g^x part 1 (inside the RSA)
[16 bytes] g^x part 2 (symmetrically encrypted)
[ 6 bytes] Meeting point (IP/port)
[ 8 bytes] Meeting cookie
[16 bytes] End-to-end authentication [optional]
* Stores the DH private key into handshake_state_out for later completion
* of the handshake.
......@@ -604,7 +601,7 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
pkbytes = crypto_pk_keysize(dest_router_key);
assert(dhbytes == 128);
assert(pkbytes == 128);
challenge = tor_malloc_zero(ONIONSKIN_CHALLENGE_LEN-CIPHER_KEY_LEN);
challenge = tor_malloc_zero(DH_KEY_LEN);
if (crypto_dh_get_public(dh, challenge, dhbytes))
goto err;
......@@ -626,8 +623,8 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
/* set meeting point, meeting cookie, etc here. Leave zero for now. */
if (crypto_pk_public_hybrid_encrypt(dest_router_key, challenge,
ONIONSKIN_CHALLENGE_LEN-CIPHER_KEY_LEN,
onion_skin_out, PK_NO_PADDING, 1)<0)
DH_KEY_LEN,
onion_skin_out, PK_PKCS1_OAEP_PADDING, 1)<0)
goto err;
tor_free(challenge);
......@@ -648,6 +645,7 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,