First round of incompatible changes for key rotation. (This is in the

incompat branch, so all is well with the Tor network.)  The basic
functionality for link pkey and onion pkey rotation is both in, but I
changed it a lot since the last version that even kinda worked, so it
probably needs more testing.  Which I'll do now.

Still not in for key rotation:
   - Key rotation is never actually invoked.
   - Connection rotation doesn't really happen.
   - The log messages on failed pkey decryption probably need finetuning.
   - Windows needs locking code to work.


svn:r1648
This commit is contained in:
Nick Mathewson
2004-04-17 01:37:28 +00:00
parent ad6913005a
commit d646f9d5ac
11 changed files with 187 additions and 155 deletions
@@ -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)))
+43 -41
View File
@@ -44,6 +44,7 @@ struct tor_tls_st {
};
static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa,
crypto_pk_env_t *identity,
const char *nickname);
/* global tls context, keep it here because nobody else needs to touch it */
@@ -54,7 +55,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,15 +130,16 @@ 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.
*/
X509 *
tor_tls_create_certificate(crypto_pk_env_t *rsa,
crypto_pk_env_t *identity,
const char *nickname)
{
time_t start_time, end_time;
EVP_PKEY *pkey = NULL;
EVP_PKEY *id_pkey = NULL, *pkey=NULL;
X509 *x509 = NULL;
X509_NAME *name = NULL;
int nid;
@@ -147,8 +149,10 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
start_time = time(NULL);
assert(rsa && nickname);
if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa)))
return NULL;
if (!(id_pkey = _crypto_pk_env_get_evp_pkey(identity,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)))
@@ -176,7 +180,7 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
goto error;
if (!X509_set_pubkey(x509, pkey))
goto error;
if (!X509_sign(x509, pkey, EVP_sha1()))
if (!X509_sign(x509, id_pkey, EVP_sha1()))
goto error;
goto done;
@@ -186,6 +190,8 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
x509 = NULL;
}
done:
if (id_pkey)
EVP_PKEY_free(id_pkey);
if (pkey)
EVP_PKEY_free(pkey);
if (name)
@@ -210,26 +216,31 @@ 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,
tor_tls_context_new(crypto_pk_env_t *identity,
int isServer, const char *nickname)
{
crypto_pk_env_t *rsa = NULL;
crypto_dh_env_t *dh = NULL;
EVP_PKEY *pkey = NULL;
tor_tls_context *result;
tor_tls_context *result = NULL;
X509 *cert = NULL;
tor_tls_init();
if (rsa) {
cert = tor_tls_create_certificate(rsa, nickname);
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);
if (!cert) {
log(LOG_WARN, "Error creating certificate");
return -1;
goto error;
}
}
@@ -250,8 +261,9 @@ tor_tls_context_new(crypto_pk_env_t *rsa,
if (cert && !SSL_CTX_use_certificate(result->ctx,cert))
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,6 +295,8 @@ 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)
@@ -509,19 +523,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;
EVP_PKEY *id_pkey = NULL;
RSA *rsa = 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,31 +550,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 (id_pkey)
EVP_PKEY_free(id_pkey);
if (rsa)
RSA_free(rsa);
return r;
@@ -22,7 +22,7 @@ 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);
@@ -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,36 +201,23 @@ 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) {
router = router_get_by_nickname(nickname);
if (!router) {
log_fn(LOG_INFO, "Unrecognized router with nickname '%s'", nickname);
return -1;
}
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);
return -1;
}
router = router_get_by_link_pk(pk);
if (!router) {
log_fn(LOG_INFO,"Unrecognized public key from peer '%s' (%s:%d). Closing.",
nickname, conn->address, conn->port);
crypto_free_pk_env(pk);
log_fn(LOG_DEBUG,"The router's cert is valid.");
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);
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);
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'",
+40 -8
View File
@@ -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);
+24 -9
View File
@@ -575,9 +575,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.
@@ -603,7 +600,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;
@@ -625,8 +622,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)
ONIONSKIN_CHALLENGE_LEN-CIPHER_KEY_LEN,
onion_skin_out, PK_PKCS1_OAEP_PADDING, 1)<0)
goto err;
tor_free(challenge);
@@ -647,6 +644,7 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
int
onion_skin_server_handshake(char *onion_skin, /* ONIONSKIN_CHALLENGE_LEN bytes */
crypto_pk_env_t *private_key,
crypto_pk_env_t *prev_private_key,
char *handshake_reply_out, /* ONIONSKIN_REPLY_LEN bytes */
char *key_out,
int key_out_len)
@@ -655,11 +653,28 @@ onion_skin_server_handshake(char *onion_skin, /* ONIONSKIN_CHALLENGE_LEN bytes *
crypto_dh_env_t *dh = NULL;
int len;
char *key_material=NULL;
int i;
crypto_pk_env_t *k;
if (crypto_pk_private_hybrid_decrypt(private_key,
onion_skin, ONIONSKIN_CHALLENGE_LEN,
challenge, PK_NO_PADDING)<0)
len = -1;
for (i=0;i<2;++i) {
k = i==0?private_key:prev_private_key;
if (!k)
break;
len = crypto_pk_private_hybrid_decrypt(k,
onion_skin, ONIONSKIN_CHALLENGE_LEN,
challenge, PK_PKCS1_OAEP_PADDING);
if (len>0)
break;
}
if (len<0) {
log_fn(LOG_WARN, "Couldn't decrypt onionskin");
goto err;
} else if (len != DH_KEY_LEN) {
log_fn(LOG_WARN, "Unexpected onionskin length after decryption: %d",
len);
goto err;
}
dh = crypto_dh_new();
if (crypto_dh_get_public(dh, handshake_reply_out, DH_KEY_LEN))
+8 -6
View File
@@ -377,7 +377,6 @@ struct connection_t {
* strdup into this, because free_connection frees it
*/
crypto_pk_env_t *onion_pkey; /* public RSA key for the other side's onions */
crypto_pk_env_t *link_pkey; /* public RSA key for the other side's TLS */
crypto_pk_env_t *identity_pkey; /* public RSA key for the other side's signing */
char *nickname;
@@ -441,7 +440,6 @@ typedef struct {
time_t published_on;
crypto_pk_env_t *onion_pkey; /* public RSA key for onions */
crypto_pk_env_t *link_pkey; /* public RSA key for TLS */
crypto_pk_env_t *identity_pkey; /* public RSA key for signing */
int is_running;
@@ -488,8 +486,10 @@ struct crypt_path_t {
};
#define DH_KEY_LEN DH_BYTES
#define ONIONSKIN_CHALLENGE_LEN (16+DH_KEY_LEN)
#define ONIONSKIN_REPLY_LEN (DH_KEY_LEN+20)
#define ONIONSKIN_CHALLENGE_LEN (PKCS1_OAEP_PADDING_OVERHEAD+\
CIPHER_KEY_LEN+\
DH_KEY_LEN)
#define ONIONSKIN_REPLY_LEN (DH_KEY_LEN+DIGEST_LEN)
#define REND_COOKIE_LEN DIGEST_LEN
typedef struct crypt_path_t crypt_path_t;
@@ -878,6 +878,7 @@ void connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn);
/********************************* cpuworker.c *****************************/
void cpu_init(void);
void cpuworkers_rotate(void);
int connection_cpu_finished_flushing(connection_t *conn);
int connection_cpu_process_inbuf(connection_t *conn);
int cpuworker_main(void *data);
@@ -944,6 +945,7 @@ int onion_skin_create(crypto_pk_env_t *router_key,
int onion_skin_server_handshake(char *onion_skin,
crypto_pk_env_t *private_key,
crypto_pk_env_t *prev_private_key,
char *handshake_reply_out,
char *key_out,
int key_out_len);
@@ -960,11 +962,12 @@ cpath_build_state_t *onion_new_cpath_build_state(uint8_t purpose,
void set_onion_key(crypto_pk_env_t *k);
crypto_pk_env_t *get_onion_key(void);
crypto_pk_env_t *get_previous_onion_key(void);
void set_identity_key(crypto_pk_env_t *k);
crypto_pk_env_t *get_identity_key(void);
crypto_pk_env_t *get_link_key(void);
int init_keys(void);
crypto_pk_env_t *init_key_from_file(const char *fname);
void rotate_onion_key(void);
void router_retry_connections(void);
void router_upload_dir_desc_to_dirservers(void);
@@ -985,7 +988,6 @@ routerinfo_t *router_choose_random_node(routerlist_t *dir,
char *preferred, char *excluded,
struct smartlist_t *excludedsmartlist);
routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port);
routerinfo_t *router_get_by_link_pk(crypto_pk_env_t *pk);
routerinfo_t *router_get_by_nickname(char *nickname);
void router_get_routerlist(routerlist_t **prouterlist);
void routerinfo_free(routerinfo_t *router);
+47 -27
View File
@@ -12,7 +12,7 @@ extern or_options_t options; /* command-line and config-file options */
/* private keys */
static crypto_pk_env_t *onionkey=NULL;
static crypto_pk_env_t *linkkey=NULL;
static crypto_pk_env_t *lastonionkey=NULL;
static crypto_pk_env_t *identitykey=NULL;
void set_onion_key(crypto_pk_env_t *k) {
@@ -24,15 +24,8 @@ crypto_pk_env_t *get_onion_key(void) {
return onionkey;
}
void set_link_key(crypto_pk_env_t *k)
{
linkkey = k;
}
crypto_pk_env_t *get_link_key(void)
{
assert(linkkey);
return linkkey;
crypto_pk_env_t *get_previous_onion_key(void) {
return lastonionkey;
}
void set_identity_key(crypto_pk_env_t *k) {
@@ -46,6 +39,46 @@ crypto_pk_env_t *get_identity_key(void) {
/************************************************************/
/* Replace the previous onion key with the current onion key, and generate
* a new previous onion key. Immediately after calling this function,
* the OR should:
* a) shedule all previous cpuworker to shut down _after_ processing
* pending work. (This will cause fresh cpuworkers to be generated.)
* b) generate and upload a fresh routerinfo.
*/
void rotate_onion_key(void)
{
char fname[512];
crypto_pk_env_t *prkey;
sprintf(fname,"%s/keys/onion.key",options.DataDirectory);
if (!(prkey = crypto_new_pk_env())) {
log(LOG_ERR, "Error creating crypto environment.");
goto error;
}
if (crypto_pk_generate_key(onionkey)) {
log(LOG_ERR, "Error generating key: %s", crypto_perror());
goto error;
}
if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
log(LOG_ERR, "Couldn't write generated key to %s.", fname);
goto error;
}
if (lastonionkey)
crypto_free_pk_env(lastonionkey);
/* XXXX WINDOWS on windows, we need to protect this next bit with a lock.
*/
lastonionkey = onionkey;
onionkey = prkey;
if (router_rebuild_descriptor() <0) {
goto error;
}
router_upload_dir_desc_to_dirservers();
/* Mark all CPU workers to close. */
return;
error:
log_fn(LOG_WARN, "Couldn't rotate onion key.");
}
/* Try to read an RSA key from 'fname'. If 'fname' doesn't exist, create a new
* RSA key and save it in 'fname'. Return the read/created key, or NULL on
* error.
@@ -146,12 +179,7 @@ int init_keys(void) {
set_onion_key(prkey);
/* 3. Initialize link key and TLS context. */
strcpy(cp, "/link.key");
log_fn(LOG_INFO,"Reading/making link key %s...",keydir);
prkey = init_key_from_file(keydir);
if (!prkey) return -1;
set_link_key(prkey);
if (tor_tls_context_new(prkey, 1, options.Nickname) < 0) {
if (tor_tls_context_new(get_identity_key(), 1, options.Nickname) < 0) {
log_fn(LOG_ERR, "Error initializing TLS context");
return -1;
}
@@ -370,7 +398,6 @@ int router_rebuild_descriptor(void) {
ri->dir_port = options.DirPort;
ri->published_on = time(NULL);
ri->onion_pkey = crypto_pk_dup_key(get_onion_key());
ri->link_pkey = crypto_pk_dup_key(get_link_key());
ri->identity_pkey = crypto_pk_dup_key(get_identity_key());
get_platform_str(platform, sizeof(platform));
ri->platform = tor_strdup(platform);
@@ -403,13 +430,12 @@ void get_platform_str(char *platform, int len)
int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
crypto_pk_env_t *ident_key) {
char *onion_pkey;
char *link_pkey;
char *identity_pkey;
struct in_addr in;
char digest[20];
char signature[128];
char published[32];
int onion_pkeylen, link_pkeylen, identity_pkeylen;
int onion_pkeylen, identity_pkeylen;
int written;
int result=0;
struct exit_policy_t *tmpe;
@@ -436,19 +462,14 @@ int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
return -1;
}
if(crypto_pk_write_public_key_to_string(router->link_pkey,
&link_pkey,&link_pkeylen)<0) {
log_fn(LOG_WARN,"write link_pkey to string failed!");
return -1;
}
strftime(published, 32, "%Y-%m-%d %H:%M:%S", gmtime(&router->published_on));
/* XXXX eventually, don't include link key */
result = snprintf(s, maxlen,
"router %s %s %d %d %d %d\n"
"platform %s\n"
"published %s\n"
"onion-key\n%s"
"link-key\n%s"
"signing-key\n%s",
router->nickname,
router->address,
@@ -459,10 +480,9 @@ int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
/* XXXBC also write bandwidthburst */
router->platform,
published,
onion_pkey, link_pkey, identity_pkey);
onion_pkey, identity_pkey);
free(onion_pkey);
free(link_pkey);
free(identity_pkey);
if(result < 0 || result >= maxlen) {
+4 -26
View File
@@ -30,7 +30,7 @@ typedef enum {
K_SIGNED_DIRECTORY,
K_SIGNING_KEY,
K_ONION_KEY,
K_LINK_KEY,
K_LINK_KEY, /* XXXX obsolete */
K_ROUTER_SIGNATURE,
K_PUBLISHED,
K_RUNNING_ROUTERS,
@@ -305,21 +305,6 @@ routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port) {
return NULL;
}
routerinfo_t *router_get_by_link_pk(crypto_pk_env_t *pk)
{
int i;
routerinfo_t *router;
assert(routerlist);
for(i=0;i<smartlist_len(routerlist->routers);i++) {
router = smartlist_get(routerlist->routers, i);
if (0 == crypto_pk_cmp_keys(router->link_pkey, pk))
return router;
}
return NULL;
}
routerinfo_t *router_get_by_nickname(char *nickname)
{
int i;
@@ -354,8 +339,6 @@ void routerinfo_free(routerinfo_t *router)
tor_free(router->platform);
if (router->onion_pkey)
crypto_free_pk_env(router->onion_pkey);
if (router->link_pkey)
crypto_free_pk_env(router->link_pkey);
if (router->identity_pkey)
crypto_free_pk_env(router->identity_pkey);
while (router->exit_policy) {
@@ -380,8 +363,6 @@ routerinfo_t *routerinfo_copy(const routerinfo_t *router)
r->platform = tor_strdup(r->platform);
if (r->onion_pkey)
r->onion_pkey = crypto_pk_dup_key(r->onion_pkey);
if (r->link_pkey)
r->link_pkey = crypto_pk_dup_key(r->link_pkey);
if (r->identity_pkey)
r->identity_pkey = crypto_pk_dup_key(r->identity_pkey);
e = &r->exit_policy;
@@ -949,7 +930,7 @@ routerinfo_t *router_get_entry_from_string(const char *s,
}
router = tor_malloc_zero(sizeof(routerinfo_t));
router->onion_pkey = router->identity_pkey = router->link_pkey = NULL;
router->onion_pkey = router->identity_pkey = NULL;
ports_set = bw_set = 0;
if (tok->n_args == 2 || tok->n_args == 6) {
@@ -1020,12 +1001,9 @@ routerinfo_t *router_get_entry_from_string(const char *s,
router->onion_pkey = tok->key;
tok->key = NULL; /* Prevent free */
if (!(tok = find_first_by_keyword(tokens, K_LINK_KEY))) {
log_fn(LOG_WARN, "Missing onion key"); goto err;
if ((tok = find_first_by_keyword(tokens, K_LINK_KEY))) {
log_fn(LOG_INFO, "Skipping obsolete link-key"); goto err;
}
/* XXX Check key length */
router->link_pkey = tok->key;
tok->key = NULL; /* Prevent free */
if (!(tok = find_first_by_keyword(tokens, K_SIGNING_KEY))) {
log_fn(LOG_WARN, "Missing onion key"); goto err;
+1 -6
View File
@@ -650,7 +650,7 @@ test_onion_handshake() {
/* server handshake */
memset(s_buf, 0, ONIONSKIN_REPLY_LEN);
memset(s_keys, 0, 40);
test_assert(! onion_skin_server_handshake(c_buf, pk, s_buf, s_keys, 40));
test_assert(! onion_skin_server_handshake(c_buf, pk, NULL, s_buf, s_keys, 40));
/* client handshake 2 */
memset(c_keys, 0, 40);
@@ -701,7 +701,6 @@ test_dir_format()
r1.dir_port = 9003;
r1.onion_pkey = pk1;
r1.identity_pkey = pk2;
r1.link_pkey = pk3;
r1.bandwidthrate = r1.bandwidthburst = 1000;
r1.exit_policy = NULL;
r1.nickname = "Magri";
@@ -727,7 +726,6 @@ test_dir_format()
r2.dir_port = 0;
r2.onion_pkey = pk2;
r2.identity_pkey = pk1;
r2.link_pkey = pk2;
r2.bandwidthrate = r2.bandwidthburst = 3000;
r2.exit_policy = &ex1;
r2.nickname = "Fred";
@@ -749,8 +747,6 @@ test_dir_format()
"published 1970-01-01 00:00:00\n"
"onion-key\n");
strcat(buf2, pk1_str);
strcat(buf2, "link-key\n");
strcat(buf2, pk3_str);
strcat(buf2, "signing-key\n");
strcat(buf2, pk2_str);
strcat(buf2, "router-signature\n");
@@ -769,7 +765,6 @@ test_dir_format()
test_eq(rp1->bandwidthrate, r1.bandwidthrate);
// test_eq(rp1->bandwidthburst, r1.bandwidthburst);
test_assert(crypto_pk_cmp_keys(rp1->onion_pkey, pk1) == 0);
test_assert(crypto_pk_cmp_keys(rp1->link_pkey, pk3) == 0);
test_assert(crypto_pk_cmp_keys(rp1->identity_pkey, pk2) == 0);
test_assert(rp1->exit_policy == NULL);