Implemented link padding and receiver token buckets
Each socket reads at most 'bandwidth' bytes per second sustained, but
can handle bursts of up to 10*bandwidth bytes.
Cells are now sent out at evenly-spaced intervals, with padding sent
out otherwise. Set Linkpadding=0 in the rc file to send cells as soon
as they're available (and to never send padding cells).
Added license/copyrights statements at the top of most files.
router->min and router->max have been merged into a single 'bandwidth'
value. We should make the routerinfo_t reflect this (want to do that,
Mat?)
As the bandwidth increases, and we want to stop sleeping more and more
frequently to send a single cell, cpu usage goes up. At 128kB/s we're
pretty much calling poll with a timeout of 1ms or even 0ms. The current
code takes a timeout of 0-9ms and makes it 10ms. prepare_for_poll()
handles everything that should have happened in the past, so as long as
our buffers don't get too full in that 10ms, we're ok.
Speaking of too full, if you run three servers at 100kB/s with -l debug,
it spends too much time printing debugging messages to be able to keep
up with the cells. The outbuf ultimately fills up and it kills that
connection. If you run with -l err, it works fine up through 500kB/s and
probably beyond. Down the road we'll want to teach it to recognize when
an outbuf is getting full, and back off.
svn:r50
2002-07-16 03:12:15 +02:00
|
|
|
/* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
|
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
/* $Id$ */
|
2002-06-27 00:45:49 +02:00
|
|
|
|
|
|
|
#include "or.h"
|
|
|
|
|
2002-11-27 05:08:20 +01:00
|
|
|
extern or_options_t options; /* command-line and config-file options */
|
2002-09-04 08:29:28 +02:00
|
|
|
|
2003-04-08 08:44:38 +02:00
|
|
|
static int count_acceptable_routers(routerinfo_t **rarray, int rarray_len);
|
2003-05-06 01:24:46 +02:00
|
|
|
static int onionskin_process(circuit_t *circ);
|
2002-06-27 00:45:49 +02:00
|
|
|
|
|
|
|
int decide_aci_type(uint32_t local_addr, uint16_t local_port,
|
|
|
|
uint32_t remote_addr, uint16_t remote_port) {
|
|
|
|
|
|
|
|
if(local_addr > remote_addr)
|
|
|
|
return ACI_TYPE_HIGHER;
|
|
|
|
if(local_addr < remote_addr)
|
|
|
|
return ACI_TYPE_LOWER;
|
|
|
|
if(local_port > remote_port)
|
|
|
|
return ACI_TYPE_HIGHER;
|
|
|
|
/* else */
|
|
|
|
return ACI_TYPE_LOWER;
|
|
|
|
}
|
|
|
|
|
2002-11-27 05:08:20 +01:00
|
|
|
/* global (within this file) variables used by the next few functions */
|
|
|
|
static struct onion_queue_t *ol_list=NULL;
|
|
|
|
static struct onion_queue_t *ol_tail=NULL;
|
|
|
|
static int ol_length=0;
|
|
|
|
|
|
|
|
int onion_pending_add(circuit_t *circ) {
|
|
|
|
struct onion_queue_t *tmp;
|
|
|
|
|
|
|
|
tmp = malloc(sizeof(struct onion_queue_t));
|
|
|
|
memset(tmp, 0, sizeof(struct onion_queue_t));
|
|
|
|
tmp->circ = circ;
|
|
|
|
|
|
|
|
if(!ol_tail) {
|
|
|
|
assert(!ol_list);
|
|
|
|
assert(!ol_length);
|
|
|
|
ol_list = tmp;
|
|
|
|
ol_tail = tmp;
|
|
|
|
ol_length++;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(ol_list);
|
|
|
|
assert(!ol_tail->next);
|
|
|
|
|
|
|
|
if(ol_length >= options.MaxOnionsPending) {
|
|
|
|
log(LOG_INFO,"onion_pending_add(): Already have %d onions queued. Closing.", ol_length);
|
|
|
|
free(tmp);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ol_length++;
|
|
|
|
ol_tail->next = tmp;
|
|
|
|
ol_tail = tmp;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int onion_pending_check(void) {
|
|
|
|
if(ol_list)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void onion_pending_process_one(void) {
|
2003-05-01 08:42:29 +02:00
|
|
|
struct relay_queue_t *tmpd;
|
2002-11-28 08:32:30 +01:00
|
|
|
circuit_t *circ;
|
2002-11-27 05:08:20 +01:00
|
|
|
|
|
|
|
if(!ol_list)
|
|
|
|
return; /* no onions pending, we're done */
|
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
assert(ol_list->circ);
|
|
|
|
assert(ol_list->circ->p_conn);
|
2002-11-27 05:08:20 +01:00
|
|
|
assert(ol_length > 0);
|
2002-11-28 08:32:30 +01:00
|
|
|
circ = ol_list->circ;
|
2002-11-27 05:08:20 +01:00
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
if(onionskin_process(circ) < 0) {
|
2002-11-27 05:08:20 +01:00
|
|
|
log(LOG_DEBUG,"onion_pending_process_one(): Failed. Closing.");
|
2002-11-28 08:32:30 +01:00
|
|
|
onion_pending_remove(circ);
|
|
|
|
circuit_close(circ);
|
2002-11-27 05:08:20 +01:00
|
|
|
} else {
|
2003-05-01 08:42:29 +02:00
|
|
|
log(LOG_DEBUG,"onion_pending_process_one(): Succeeded. Delivering queued relay cells.");
|
|
|
|
for(tmpd = ol_list->relay_cells; tmpd; tmpd=tmpd->next) {
|
2003-05-06 01:24:46 +02:00
|
|
|
log(LOG_DEBUG,"onion_pending_process_one(): Delivering relay cell...");
|
2003-05-01 08:42:29 +02:00
|
|
|
command_process_relay_cell(tmpd->cell, circ->p_conn);
|
2002-11-27 05:08:20 +01:00
|
|
|
}
|
2002-11-28 08:32:30 +01:00
|
|
|
onion_pending_remove(circ);
|
2002-11-27 05:08:20 +01:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-12-03 23:18:23 +01:00
|
|
|
/* go through ol_list, find the onion_queue_t element which points to
|
|
|
|
* circ, remove and free that element. leave circ itself alone.
|
2002-11-27 05:08:20 +01:00
|
|
|
*/
|
|
|
|
void onion_pending_remove(circuit_t *circ) {
|
|
|
|
struct onion_queue_t *tmpo, *victim;
|
2003-05-01 08:42:29 +02:00
|
|
|
struct relay_queue_t *tmpd;
|
2002-11-27 05:08:20 +01:00
|
|
|
|
|
|
|
if(!ol_list)
|
|
|
|
return; /* nothing here. */
|
|
|
|
|
|
|
|
/* first check to see if it's the first entry */
|
|
|
|
tmpo = ol_list;
|
|
|
|
if(tmpo->circ == circ) {
|
|
|
|
/* it's the first one. remove it from the list. */
|
|
|
|
ol_list = tmpo->next;
|
|
|
|
if(!ol_list)
|
|
|
|
ol_tail = NULL;
|
|
|
|
ol_length--;
|
|
|
|
victim = tmpo;
|
|
|
|
} else { /* we need to hunt through the rest of the list */
|
|
|
|
for( ;tmpo->next && tmpo->next->circ != circ; tmpo=tmpo->next) ;
|
|
|
|
if(!tmpo->next) {
|
|
|
|
log(LOG_WARNING,"onion_pending_remove(): circ (p_aci %d), not in list!",circ->p_aci);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* now we know tmpo->next->circ == circ */
|
|
|
|
victim = tmpo->next;
|
|
|
|
tmpo->next = victim->next;
|
|
|
|
if(ol_tail == victim)
|
|
|
|
ol_tail = tmpo;
|
|
|
|
ol_length--;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now victim points to the element that needs to be removed */
|
|
|
|
|
2003-05-01 08:42:29 +02:00
|
|
|
/* first dump the attached relay cells too, if any */
|
|
|
|
while(victim->relay_cells) {
|
|
|
|
tmpd = victim->relay_cells;
|
|
|
|
victim->relay_cells = tmpd->next;
|
2002-11-27 05:08:20 +01:00
|
|
|
free(tmpd->cell);
|
|
|
|
free(tmpd);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(victim);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2003-05-02 23:29:25 +02:00
|
|
|
struct relay_queue_t *relay_queue_add(struct relay_queue_t *list, cell_t *cell, crypt_path_t *layer_hint) {
|
2003-05-01 08:42:29 +02:00
|
|
|
struct relay_queue_t *tmpd, *newd;
|
2002-11-27 05:08:20 +01:00
|
|
|
|
2003-05-01 08:42:29 +02:00
|
|
|
newd = malloc(sizeof(struct relay_queue_t));
|
|
|
|
memset(newd, 0, sizeof(struct relay_queue_t));
|
2002-11-27 05:08:20 +01:00
|
|
|
newd->cell = malloc(sizeof(cell_t));
|
|
|
|
memcpy(newd->cell, cell, sizeof(cell_t));
|
2003-05-02 23:29:25 +02:00
|
|
|
newd->layer_hint = layer_hint;
|
2002-11-27 05:08:20 +01:00
|
|
|
|
major overhaul: dns slave subsystem, topics
on startup, it forks off a master dns handler, which forks off dns
slaves (like the apache model). slaves as spawned as load increases,
and then reused. excess slaves are not ever killed, currently.
implemented topics. each topic has a receive window in each direction
at each edge of the circuit, and sends sendme's at the data level, as
per before. each circuit also has receive windows in each direction at
each hop; an edge sends a circuit-level sendme as soon as enough data
cells have arrived (regardless of whether the data cells were flushed
to the exit conns). removed the 'connected' cell type, since it's now
a topic command within data cells.
at the edge of the circuit, there can be multiple connections associated
with a single circuit. you find them via the linked list conn->next_topic.
currently each new ap connection starts its own circuit, so we ought
to see comparable performance to what we had before. but that's only
because i haven't written the code to reattach to old circuits. please
try to break it as-is, and then i'll make it reuse the same circuit and
we'll try to break that.
svn:r152
2003-01-26 10:02:24 +01:00
|
|
|
if(!list) {
|
|
|
|
return newd;
|
|
|
|
}
|
|
|
|
for(tmpd = list; tmpd->next; tmpd=tmpd->next) ;
|
|
|
|
/* now tmpd->next is null */
|
|
|
|
tmpd->next = newd;
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2003-05-01 08:42:29 +02:00
|
|
|
/* a relay cell has arrived for a circuit which is still pending. Find
|
|
|
|
* the right entry in ol_list, and add it to the end of the 'relay_cells'
|
major overhaul: dns slave subsystem, topics
on startup, it forks off a master dns handler, which forks off dns
slaves (like the apache model). slaves as spawned as load increases,
and then reused. excess slaves are not ever killed, currently.
implemented topics. each topic has a receive window in each direction
at each edge of the circuit, and sends sendme's at the data level, as
per before. each circuit also has receive windows in each direction at
each hop; an edge sends a circuit-level sendme as soon as enough data
cells have arrived (regardless of whether the data cells were flushed
to the exit conns). removed the 'connected' cell type, since it's now
a topic command within data cells.
at the edge of the circuit, there can be multiple connections associated
with a single circuit. you find them via the linked list conn->next_topic.
currently each new ap connection starts its own circuit, so we ought
to see comparable performance to what we had before. but that's only
because i haven't written the code to reattach to old circuits. please
try to break it as-is, and then i'll make it reuse the same circuit and
we'll try to break that.
svn:r152
2003-01-26 10:02:24 +01:00
|
|
|
* list.
|
|
|
|
*/
|
2003-05-01 08:42:29 +02:00
|
|
|
void onion_pending_relay_add(circuit_t *circ, cell_t *cell) {
|
major overhaul: dns slave subsystem, topics
on startup, it forks off a master dns handler, which forks off dns
slaves (like the apache model). slaves as spawned as load increases,
and then reused. excess slaves are not ever killed, currently.
implemented topics. each topic has a receive window in each direction
at each edge of the circuit, and sends sendme's at the data level, as
per before. each circuit also has receive windows in each direction at
each hop; an edge sends a circuit-level sendme as soon as enough data
cells have arrived (regardless of whether the data cells were flushed
to the exit conns). removed the 'connected' cell type, since it's now
a topic command within data cells.
at the edge of the circuit, there can be multiple connections associated
with a single circuit. you find them via the linked list conn->next_topic.
currently each new ap connection starts its own circuit, so we ought
to see comparable performance to what we had before. but that's only
because i haven't written the code to reattach to old circuits. please
try to break it as-is, and then i'll make it reuse the same circuit and
we'll try to break that.
svn:r152
2003-01-26 10:02:24 +01:00
|
|
|
struct onion_queue_t *tmpo;
|
|
|
|
|
2002-11-27 05:08:20 +01:00
|
|
|
for(tmpo=ol_list; tmpo; tmpo=tmpo->next) {
|
|
|
|
if(tmpo->circ == circ) {
|
2003-05-02 23:29:25 +02:00
|
|
|
tmpo->relay_cells = relay_queue_add(tmpo->relay_cells, cell, NULL);
|
2002-11-27 05:08:20 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
/* learn keys, initialize, then send a created cell back */
|
|
|
|
static int onionskin_process(circuit_t *circ) {
|
|
|
|
unsigned char iv[16];
|
|
|
|
unsigned char keys[32];
|
2002-11-27 05:08:20 +01:00
|
|
|
cell_t cell;
|
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
memset(iv, 0, 16);
|
2002-10-03 00:54:20 +02:00
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
memset(&cell, 0, sizeof(cell_t));
|
|
|
|
cell.command = CELL_CREATED;
|
|
|
|
cell.aci = circ->p_aci;
|
|
|
|
cell.length = 192;
|
|
|
|
|
|
|
|
circ->state = CIRCUIT_STATE_OPEN;
|
2002-06-27 00:45:49 +02:00
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
log(LOG_DEBUG,"onionskin_process(): Entering.");
|
|
|
|
|
|
|
|
if(onion_skin_server_handshake(circ->onionskin, getprivatekey(),
|
|
|
|
cell.payload, keys, 32) < 0) {
|
|
|
|
log(LOG_ERR,"onionskin_process(): onion_skin_server_handshake failed.");
|
2002-06-27 00:45:49 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
log(LOG_DEBUG,"onionskin_process: init cipher forward %d, backward %d.", *(int*)keys, *(int*)(keys+16));
|
|
|
|
|
|
|
|
if (!(circ->n_crypto =
|
|
|
|
crypto_create_init_cipher(DEFAULT_CIPHER,keys,iv,0))) {
|
|
|
|
log(LOG_ERR,"Cipher initialization failed.");
|
2002-06-27 00:45:49 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
if (!(circ->p_crypto =
|
|
|
|
crypto_create_init_cipher(DEFAULT_CIPHER,keys+16,iv,1))) {
|
|
|
|
log(LOG_ERR,"Cipher initialization failed.");
|
2002-06-27 00:45:49 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
if(connection_write_cell_to_buf(&cell, circ->p_conn) < 0) {
|
2002-06-27 00:45:49 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2003-05-06 01:24:46 +02:00
|
|
|
log(LOG_DEBUG,"onionskin_process(): Finished sending 'created' cell.");
|
2002-06-27 00:45:49 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Integrated onion proxy into or/
The 'or' process can now be told (by the global_role variable) what
roles this server should play -- connect to all ORs, listen for ORs,
listen for OPs, listen for APs, or any combination.
* everything in /src/op/ is now obsolete.
* connection_ap.c now handles all interactions with application proxies
* "port" is now or_port, op_port, ap_port. But routers are still always
referenced (say, in conn_get_by_addr_port()) by addr / or_port. We
should make routers.c actually read these new ports (currently I've
kludged it so op_port = or_port+10, ap_port=or_port+20)
* circuits currently know if they're at the beginning of the path because
circ->cpath is set. They use this instead for crypts (both ways),
if it's set.
* I still obey the "send a 0 back to the AP when you're ready" protocol,
but I think we should phase it out. I can simply not read from the AP
socket until I'm ready.
I need to do a lot of cleanup work here, but the code appears to work, so
now's a good time for a checkin.
svn:r22
2002-07-02 11:36:58 +02:00
|
|
|
/* uses a weighted coin with weight cw to choose a route length */
|
|
|
|
int chooselen(double cw)
|
|
|
|
{
|
|
|
|
int len = 2;
|
2003-04-17 19:10:41 +02:00
|
|
|
uint8_t coin;
|
Integrated onion proxy into or/
The 'or' process can now be told (by the global_role variable) what
roles this server should play -- connect to all ORs, listen for ORs,
listen for OPs, listen for APs, or any combination.
* everything in /src/op/ is now obsolete.
* connection_ap.c now handles all interactions with application proxies
* "port" is now or_port, op_port, ap_port. But routers are still always
referenced (say, in conn_get_by_addr_port()) by addr / or_port. We
should make routers.c actually read these new ports (currently I've
kludged it so op_port = or_port+10, ap_port=or_port+20)
* circuits currently know if they're at the beginning of the path because
circ->cpath is set. They use this instead for crypts (both ways),
if it's set.
* I still obey the "send a 0 back to the AP when you're ready" protocol,
but I think we should phase it out. I can simply not read from the AP
socket until I'm ready.
I need to do a lot of cleanup work here, but the code appears to work, so
now's a good time for a checkin.
svn:r22
2002-07-02 11:36:58 +02:00
|
|
|
|
|
|
|
if ((cw < 0) || (cw >= 1)) /* invalid parameter */
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
while(1)
|
|
|
|
{
|
2003-04-17 19:10:41 +02:00
|
|
|
if (CRYPTO_PSEUDO_RAND_INT(coin))
|
Integrated onion proxy into or/
The 'or' process can now be told (by the global_role variable) what
roles this server should play -- connect to all ORs, listen for ORs,
listen for OPs, listen for APs, or any combination.
* everything in /src/op/ is now obsolete.
* connection_ap.c now handles all interactions with application proxies
* "port" is now or_port, op_port, ap_port. But routers are still always
referenced (say, in conn_get_by_addr_port()) by addr / or_port. We
should make routers.c actually read these new ports (currently I've
kludged it so op_port = or_port+10, ap_port=or_port+20)
* circuits currently know if they're at the beginning of the path because
circ->cpath is set. They use this instead for crypts (both ways),
if it's set.
* I still obey the "send a 0 back to the AP when you're ready" protocol,
but I think we should phase it out. I can simply not read from the AP
socket until I'm ready.
I need to do a lot of cleanup work here, but the code appears to work, so
now's a good time for a checkin.
svn:r22
2002-07-02 11:36:58 +02:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (coin > cw*255) /* don't extend */
|
|
|
|
break;
|
|
|
|
else
|
|
|
|
len++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returns an array of pointers to routent that define a new route through the OR network
|
|
|
|
* int cw is the coin weight to use when choosing the route
|
|
|
|
* order of routers is from last to first
|
|
|
|
*/
|
2002-08-24 06:59:21 +02:00
|
|
|
unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *routelen)
|
Integrated onion proxy into or/
The 'or' process can now be told (by the global_role variable) what
roles this server should play -- connect to all ORs, listen for ORs,
listen for OPs, listen for APs, or any combination.
* everything in /src/op/ is now obsolete.
* connection_ap.c now handles all interactions with application proxies
* "port" is now or_port, op_port, ap_port. But routers are still always
referenced (say, in conn_get_by_addr_port()) by addr / or_port. We
should make routers.c actually read these new ports (currently I've
kludged it so op_port = or_port+10, ap_port=or_port+20)
* circuits currently know if they're at the beginning of the path because
circ->cpath is set. They use this instead for crypts (both ways),
if it's set.
* I still obey the "send a 0 back to the AP when you're ready" protocol,
but I think we should phase it out. I can simply not read from the AP
socket until I'm ready.
I need to do a lot of cleanup work here, but the code appears to work, so
now's a good time for a checkin.
svn:r22
2002-07-02 11:36:58 +02:00
|
|
|
{
|
2003-04-16 18:19:27 +02:00
|
|
|
int i;
|
2003-04-08 08:44:38 +02:00
|
|
|
int num_acceptable_routers;
|
2003-04-16 08:18:31 +02:00
|
|
|
unsigned int *route;
|
Integrated onion proxy into or/
The 'or' process can now be told (by the global_role variable) what
roles this server should play -- connect to all ORs, listen for ORs,
listen for OPs, listen for APs, or any combination.
* everything in /src/op/ is now obsolete.
* connection_ap.c now handles all interactions with application proxies
* "port" is now or_port, op_port, ap_port. But routers are still always
referenced (say, in conn_get_by_addr_port()) by addr / or_port. We
should make routers.c actually read these new ports (currently I've
kludged it so op_port = or_port+10, ap_port=or_port+20)
* circuits currently know if they're at the beginning of the path because
circ->cpath is set. They use this instead for crypts (both ways),
if it's set.
* I still obey the "send a 0 back to the AP when you're ready" protocol,
but I think we should phase it out. I can simply not read from the AP
socket until I'm ready.
I need to do a lot of cleanup work here, but the code appears to work, so
now's a good time for a checkin.
svn:r22
2002-07-02 11:36:58 +02:00
|
|
|
unsigned int oldchoice, choice;
|
2003-04-16 08:18:31 +02:00
|
|
|
|
2002-08-24 06:59:21 +02:00
|
|
|
assert((cw >= 0) && (cw < 1) && (rarray) && (routelen) ); /* valid parameters */
|
2002-07-22 06:38:36 +02:00
|
|
|
|
2002-08-24 06:59:21 +02:00
|
|
|
*routelen = chooselen(cw);
|
|
|
|
if (*routelen == -1) {
|
2002-08-23 05:35:44 +02:00
|
|
|
log(LOG_ERR,"Choosing route length failed.");
|
|
|
|
return NULL;
|
|
|
|
}
|
2002-08-24 06:59:21 +02:00
|
|
|
log(LOG_DEBUG,"new_route(): Chosen route length %d.",*routelen);
|
2002-08-23 05:35:44 +02:00
|
|
|
|
2003-04-08 08:44:38 +02:00
|
|
|
num_acceptable_routers = count_acceptable_routers(rarray, rarray_len);
|
|
|
|
|
2003-04-16 08:18:31 +02:00
|
|
|
if(num_acceptable_routers < 2) {
|
|
|
|
log(LOG_INFO,"new_route(): Not enough acceptable routers. Failing.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2002-08-24 06:59:21 +02:00
|
|
|
if(num_acceptable_routers < *routelen) {
|
|
|
|
log(LOG_DEBUG,"new_route(): Cutting routelen from %d to %d.",*routelen, num_acceptable_routers);
|
|
|
|
*routelen = num_acceptable_routers;
|
2002-08-23 05:35:44 +02:00
|
|
|
}
|
2002-07-22 06:38:36 +02:00
|
|
|
|
2002-08-24 06:59:21 +02:00
|
|
|
if(*routelen < 1) {
|
2002-08-23 05:35:44 +02:00
|
|
|
log(LOG_ERR,"new_route(): Didn't find any acceptable routers. Failing.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allocate memory for the new route */
|
2002-08-24 06:59:21 +02:00
|
|
|
route = (unsigned int *)malloc(*routelen * sizeof(unsigned int));
|
2002-08-23 05:35:44 +02:00
|
|
|
if (!route) {
|
|
|
|
log(LOG_ERR,"Memory allocation failed.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
oldchoice = rarray_len;
|
2002-08-24 06:59:21 +02:00
|
|
|
for(i=0;i<*routelen;i++) {
|
2002-08-23 05:35:44 +02:00
|
|
|
log(LOG_DEBUG,"new_route(): Choosing hop %u.",i);
|
2003-04-17 19:10:41 +02:00
|
|
|
if (CRYPTO_PSEUDO_RAND_INT(choice)) {
|
2002-08-23 05:35:44 +02:00
|
|
|
free((void *)route);
|
Integrated onion proxy into or/
The 'or' process can now be told (by the global_role variable) what
roles this server should play -- connect to all ORs, listen for ORs,
listen for OPs, listen for APs, or any combination.
* everything in /src/op/ is now obsolete.
* connection_ap.c now handles all interactions with application proxies
* "port" is now or_port, op_port, ap_port. But routers are still always
referenced (say, in conn_get_by_addr_port()) by addr / or_port. We
should make routers.c actually read these new ports (currently I've
kludged it so op_port = or_port+10, ap_port=or_port+20)
* circuits currently know if they're at the beginning of the path because
circ->cpath is set. They use this instead for crypts (both ways),
if it's set.
* I still obey the "send a 0 back to the AP when you're ready" protocol,
but I think we should phase it out. I can simply not read from the AP
socket until I'm ready.
I need to do a lot of cleanup work here, but the code appears to work, so
now's a good time for a checkin.
svn:r22
2002-07-02 11:36:58 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2002-08-23 05:35:44 +02:00
|
|
|
choice = choice % (rarray_len);
|
|
|
|
log(LOG_DEBUG,"new_route(): Contemplating router %u.",choice);
|
2002-08-23 07:27:50 +02:00
|
|
|
if(choice == oldchoice ||
|
2002-09-24 12:43:57 +02:00
|
|
|
(oldchoice < rarray_len && !crypto_pk_cmp_keys(rarray[choice]->pkey, rarray[oldchoice]->pkey)) ||
|
2003-03-18 02:49:55 +01:00
|
|
|
(options.ORPort && !connection_twin_get_by_addr_port(rarray[choice]->addr, rarray[choice]->or_port))) {
|
2002-08-23 05:35:44 +02:00
|
|
|
/* Same router as last choice, or router twin,
|
|
|
|
* or no routers with that key are connected to us.
|
|
|
|
* Try again. */
|
|
|
|
log(LOG_DEBUG,"new_route(): Picked a router %d that won't work as next hop.",choice);
|
2002-08-23 07:27:50 +02:00
|
|
|
i--;
|
|
|
|
continue;
|
Integrated onion proxy into or/
The 'or' process can now be told (by the global_role variable) what
roles this server should play -- connect to all ORs, listen for ORs,
listen for OPs, listen for APs, or any combination.
* everything in /src/op/ is now obsolete.
* connection_ap.c now handles all interactions with application proxies
* "port" is now or_port, op_port, ap_port. But routers are still always
referenced (say, in conn_get_by_addr_port()) by addr / or_port. We
should make routers.c actually read these new ports (currently I've
kludged it so op_port = or_port+10, ap_port=or_port+20)
* circuits currently know if they're at the beginning of the path because
circ->cpath is set. They use this instead for crypts (both ways),
if it's set.
* I still obey the "send a 0 back to the AP when you're ready" protocol,
but I think we should phase it out. I can simply not read from the AP
socket until I'm ready.
I need to do a lot of cleanup work here, but the code appears to work, so
now's a good time for a checkin.
svn:r22
2002-07-02 11:36:58 +02:00
|
|
|
}
|
2002-08-23 05:35:44 +02:00
|
|
|
log(LOG_DEBUG,"new_route(): Chosen router %u for hop %u.",choice,i);
|
|
|
|
oldchoice = choice;
|
|
|
|
route[i] = choice;
|
|
|
|
}
|
Integrated onion proxy into or/
The 'or' process can now be told (by the global_role variable) what
roles this server should play -- connect to all ORs, listen for ORs,
listen for OPs, listen for APs, or any combination.
* everything in /src/op/ is now obsolete.
* connection_ap.c now handles all interactions with application proxies
* "port" is now or_port, op_port, ap_port. But routers are still always
referenced (say, in conn_get_by_addr_port()) by addr / or_port. We
should make routers.c actually read these new ports (currently I've
kludged it so op_port = or_port+10, ap_port=or_port+20)
* circuits currently know if they're at the beginning of the path because
circ->cpath is set. They use this instead for crypts (both ways),
if it's set.
* I still obey the "send a 0 back to the AP when you're ready" protocol,
but I think we should phase it out. I can simply not read from the AP
socket until I'm ready.
I need to do a lot of cleanup work here, but the code appears to work, so
now's a good time for a checkin.
svn:r22
2002-07-02 11:36:58 +02:00
|
|
|
|
2002-08-23 05:35:44 +02:00
|
|
|
return route;
|
Integrated onion proxy into or/
The 'or' process can now be told (by the global_role variable) what
roles this server should play -- connect to all ORs, listen for ORs,
listen for OPs, listen for APs, or any combination.
* everything in /src/op/ is now obsolete.
* connection_ap.c now handles all interactions with application proxies
* "port" is now or_port, op_port, ap_port. But routers are still always
referenced (say, in conn_get_by_addr_port()) by addr / or_port. We
should make routers.c actually read these new ports (currently I've
kludged it so op_port = or_port+10, ap_port=or_port+20)
* circuits currently know if they're at the beginning of the path because
circ->cpath is set. They use this instead for crypts (both ways),
if it's set.
* I still obey the "send a 0 back to the AP when you're ready" protocol,
but I think we should phase it out. I can simply not read from the AP
socket until I'm ready.
I need to do a lot of cleanup work here, but the code appears to work, so
now's a good time for a checkin.
svn:r22
2002-07-02 11:36:58 +02:00
|
|
|
}
|
|
|
|
|
2003-04-08 08:44:38 +02:00
|
|
|
static int count_acceptable_routers(routerinfo_t **rarray, int rarray_len) {
|
|
|
|
int i, j;
|
|
|
|
int num=0;
|
2003-04-16 08:18:31 +02:00
|
|
|
connection_t *conn;
|
2003-04-08 08:44:38 +02:00
|
|
|
|
|
|
|
for(i=0;i<rarray_len;i++) {
|
|
|
|
log(LOG_DEBUG,"Contemplating whether router %d is a new option...",i);
|
2003-04-16 08:18:31 +02:00
|
|
|
if(options.ORPort) {
|
|
|
|
conn = connection_exact_get_by_addr_port(rarray[i]->addr, rarray[i]->or_port);
|
|
|
|
if(!conn || conn->type != CONN_TYPE_OR || conn->state != OR_CONN_STATE_OPEN) {
|
|
|
|
log(LOG_DEBUG,"Nope, %d is not connected.",i);
|
|
|
|
goto next_i_loop;
|
|
|
|
}
|
2003-04-08 08:44:38 +02:00
|
|
|
}
|
|
|
|
for(j=0;j<i;j++) {
|
|
|
|
if(!crypto_pk_cmp_keys(rarray[i]->pkey, rarray[j]->pkey)) {
|
|
|
|
/* these guys are twins. so we've already counted him. */
|
|
|
|
log(LOG_DEBUG,"Nope, %d is a twin of %d.",i,j);
|
|
|
|
goto next_i_loop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
num++;
|
|
|
|
log(LOG_DEBUG,"I like %d. num_acceptable_routers now %d.",i, num);
|
|
|
|
next_i_loop:
|
|
|
|
; /* our compiler may need an explicit statement after the label */
|
|
|
|
}
|
|
|
|
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
crypt_path_t *onion_generate_cpath(routerinfo_t **firsthop) {
|
|
|
|
int routelen; /* length of the route */
|
|
|
|
unsigned int *route; /* hops in the route as an array of indexes into rarray */
|
|
|
|
crypt_path_t *cpath=NULL;
|
|
|
|
routerinfo_t **rarray;
|
|
|
|
int rarray_len;
|
2003-05-02 00:55:51 +02:00
|
|
|
int i;
|
|
|
|
crypt_path_t *hop;
|
Integrated onion proxy into or/
The 'or' process can now be told (by the global_role variable) what
roles this server should play -- connect to all ORs, listen for ORs,
listen for OPs, listen for APs, or any combination.
* everything in /src/op/ is now obsolete.
* connection_ap.c now handles all interactions with application proxies
* "port" is now or_port, op_port, ap_port. But routers are still always
referenced (say, in conn_get_by_addr_port()) by addr / or_port. We
should make routers.c actually read these new ports (currently I've
kludged it so op_port = or_port+10, ap_port=or_port+20)
* circuits currently know if they're at the beginning of the path because
circ->cpath is set. They use this instead for crypts (both ways),
if it's set.
* I still obey the "send a 0 back to the AP when you're ready" protocol,
but I think we should phase it out. I can simply not read from the AP
socket until I'm ready.
I need to do a lot of cleanup work here, but the code appears to work, so
now's a good time for a checkin.
svn:r22
2002-07-02 11:36:58 +02:00
|
|
|
routerinfo_t *router;
|
2002-11-23 07:49:01 +01:00
|
|
|
struct in_addr netaddr;
|
2003-05-02 00:55:51 +02:00
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
router_get_rarray(&rarray, &rarray_len);
|
2002-07-20 03:59:28 +02:00
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
/* choose a route */
|
|
|
|
route = new_route(options.CoinWeight, rarray, rarray_len, &routelen);
|
|
|
|
if (!route) {
|
|
|
|
log(LOG_ERR,"onion_generate_cpath(): Error choosing a route through the OR network.");
|
2002-11-23 07:49:01 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
2003-05-06 01:24:46 +02:00
|
|
|
log(LOG_DEBUG,"onion_generate_cpath(): Chosen a route of length %u: ",routelen);
|
|
|
|
|
|
|
|
*firsthop = rarray[route[routelen-1]];
|
|
|
|
assert(*firsthop); /* should always be defined */
|
2003-05-02 00:55:51 +02:00
|
|
|
|
2002-12-03 23:18:23 +01:00
|
|
|
for(i=0; i<routelen; i++) {
|
2002-11-23 07:49:01 +01:00
|
|
|
netaddr.s_addr = htonl((rarray[route[i]])->addr);
|
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
log(LOG_DEBUG,"onion_generate_cpath(): %u : %s:%u, %u/%u",routelen-i,
|
2002-11-23 07:49:01 +01:00
|
|
|
inet_ntoa(netaddr),
|
|
|
|
(rarray[route[i]])->or_port,
|
|
|
|
(rarray[route[i]])->pkey,
|
|
|
|
crypto_pk_keysize((rarray[route[i]])->pkey));
|
|
|
|
}
|
2003-05-02 00:55:51 +02:00
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
/* create the cpath layer by layer, starting at the last hop */
|
2002-11-23 07:49:01 +01:00
|
|
|
for (i=0;i<routelen;i++) {
|
|
|
|
router = rarray[route[i]];
|
2002-12-03 23:18:23 +01:00
|
|
|
|
2002-11-23 07:49:01 +01:00
|
|
|
/* build up the crypt_path */
|
2003-05-02 00:55:51 +02:00
|
|
|
hop = (crypt_path_t *)malloc(sizeof(crypt_path_t));
|
|
|
|
if(!hop) {
|
2003-05-06 01:24:46 +02:00
|
|
|
log(LOG_ERR,"Error allocating crypt path hop memory.");
|
|
|
|
circuit_free_cpath(cpath);
|
|
|
|
free(route);
|
|
|
|
return NULL;
|
2003-05-02 00:55:51 +02:00
|
|
|
}
|
2003-05-06 01:24:46 +02:00
|
|
|
memset(hop, 0, sizeof(crypt_path_t));
|
major overhaul: dns slave subsystem, topics
on startup, it forks off a master dns handler, which forks off dns
slaves (like the apache model). slaves as spawned as load increases,
and then reused. excess slaves are not ever killed, currently.
implemented topics. each topic has a receive window in each direction
at each edge of the circuit, and sends sendme's at the data level, as
per before. each circuit also has receive windows in each direction at
each hop; an edge sends a circuit-level sendme as soon as enough data
cells have arrived (regardless of whether the data cells were flushed
to the exit conns). removed the 'connected' cell type, since it's now
a topic command within data cells.
at the edge of the circuit, there can be multiple connections associated
with a single circuit. you find them via the linked list conn->next_topic.
currently each new ap connection starts its own circuit, so we ought
to see comparable performance to what we had before. but that's only
because i haven't written the code to reattach to old circuits. please
try to break it as-is, and then i'll make it reuse the same circuit and
we'll try to break that.
svn:r152
2003-01-26 10:02:24 +01:00
|
|
|
|
2003-05-02 00:55:51 +02:00
|
|
|
/* link hop into the cpath, at the front */
|
2003-05-06 01:24:46 +02:00
|
|
|
hop->next = cpath;
|
2003-05-02 00:55:51 +02:00
|
|
|
hop->prev = NULL;
|
2003-05-06 01:24:46 +02:00
|
|
|
hop->state = CPATH_STATE_CLOSED;
|
|
|
|
if(cpath) {
|
|
|
|
cpath->prev = hop;
|
2002-11-23 07:49:01 +01:00
|
|
|
}
|
2003-05-06 01:24:46 +02:00
|
|
|
cpath = hop;
|
2003-05-02 00:55:51 +02:00
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
#if 0
|
|
|
|
if (i) { /* not last hop. (last hop has 0's for these.) */
|
|
|
|
hop->port = rarray[route[i-1]]->or_port;
|
|
|
|
hop->addr = rarray[route[i-1]]->addr;
|
Integrated onion proxy into or/
The 'or' process can now be told (by the global_role variable) what
roles this server should play -- connect to all ORs, listen for ORs,
listen for OPs, listen for APs, or any combination.
* everything in /src/op/ is now obsolete.
* connection_ap.c now handles all interactions with application proxies
* "port" is now or_port, op_port, ap_port. But routers are still always
referenced (say, in conn_get_by_addr_port()) by addr / or_port. We
should make routers.c actually read these new ports (currently I've
kludged it so op_port = or_port+10, ap_port=or_port+20)
* circuits currently know if they're at the beginning of the path because
circ->cpath is set. They use this instead for crypts (both ways),
if it's set.
* I still obey the "send a 0 back to the AP when you're ready" protocol,
but I think we should phase it out. I can simply not read from the AP
socket until I'm ready.
I need to do a lot of cleanup work here, but the code appears to work, so
now's a good time for a checkin.
svn:r22
2002-07-02 11:36:58 +02:00
|
|
|
}
|
2003-05-06 01:24:46 +02:00
|
|
|
#endif
|
|
|
|
hop->port = rarray[route[i]]->or_port;
|
|
|
|
hop->addr = rarray[route[i]]->addr;
|
2003-05-02 00:55:51 +02:00
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
log(LOG_DEBUG,"onion_generate_cpath() : Building hop %u of crypt path.",i+1);
|
2002-11-23 07:49:01 +01:00
|
|
|
}
|
Integrated onion proxy into or/
The 'or' process can now be told (by the global_role variable) what
roles this server should play -- connect to all ORs, listen for ORs,
listen for OPs, listen for APs, or any combination.
* everything in /src/op/ is now obsolete.
* connection_ap.c now handles all interactions with application proxies
* "port" is now or_port, op_port, ap_port. But routers are still always
referenced (say, in conn_get_by_addr_port()) by addr / or_port. We
should make routers.c actually read these new ports (currently I've
kludged it so op_port = or_port+10, ap_port=or_port+20)
* circuits currently know if they're at the beginning of the path because
circ->cpath is set. They use this instead for crypts (both ways),
if it's set.
* I still obey the "send a 0 back to the AP when you're ready" protocol,
but I think we should phase it out. I can simply not read from the AP
socket until I'm ready.
I need to do a lot of cleanup work here, but the code appears to work, so
now's a good time for a checkin.
svn:r22
2002-07-02 11:36:58 +02:00
|
|
|
|
2003-05-02 00:55:51 +02:00
|
|
|
/* now link cpath->prev to the end of cpath */
|
2003-05-06 01:24:46 +02:00
|
|
|
for(hop=cpath; hop->next; hop=hop->next) ;
|
|
|
|
hop->next = cpath;
|
|
|
|
cpath->prev = hop;
|
2002-11-23 07:49:01 +01:00
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
free(route);
|
|
|
|
return cpath;
|
2003-04-16 18:19:27 +02:00
|
|
|
}
|
|
|
|
|
2003-05-01 21:42:51 +02:00
|
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
/* Given a router's public key, generates a 208-byte encrypted DH pubkey,
|
|
|
|
* and stores it into onion_skin out. Stores the DH private key into
|
|
|
|
* handshake_state_out for later completion of the handshake.
|
|
|
|
*
|
|
|
|
* The encrypted pubkey is formed as follows:
|
|
|
|
* 16 bytes of symmetric key
|
|
|
|
* 192 bytes of g^x for DH.
|
|
|
|
* The first 128 bytes are RSA-encrypted with the server's public key,
|
|
|
|
* and the last 80 are encrypted with the symmetric key.
|
|
|
|
*/
|
|
|
|
int
|
2003-05-06 01:24:46 +02:00
|
|
|
onion_skin_create(crypto_pk_env_t *dest_router_key,
|
2003-05-01 21:42:51 +02:00
|
|
|
crypto_dh_env_t **handshake_state_out,
|
|
|
|
char *onion_skin_out) /* Must be 208 bytes long */
|
|
|
|
{
|
|
|
|
char iv[16];
|
|
|
|
char *pubkey = NULL;
|
|
|
|
crypto_dh_env_t *dh = NULL;
|
|
|
|
crypto_cipher_env_t *cipher = NULL;
|
|
|
|
int dhbytes, pkbytes;
|
|
|
|
|
|
|
|
*handshake_state_out = NULL;
|
|
|
|
memset(onion_skin_out, 0, 208);
|
2003-05-05 06:27:00 +02:00
|
|
|
memset(iv, 0, 16);
|
2003-05-01 21:42:51 +02:00
|
|
|
|
|
|
|
if (!(dh = crypto_dh_new()))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
dhbytes = crypto_dh_get_bytes(dh);
|
2003-05-06 01:24:46 +02:00
|
|
|
pkbytes = crypto_pk_keysize(dest_router_key);
|
2003-05-01 21:42:51 +02:00
|
|
|
assert(dhbytes+16 == 208);
|
2003-05-05 06:27:00 +02:00
|
|
|
if (!(pubkey = malloc(dhbytes+16)))
|
2003-05-01 21:42:51 +02:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (crypto_rand(16, pubkey))
|
|
|
|
goto err;
|
2003-05-05 06:27:00 +02:00
|
|
|
|
|
|
|
/* XXXX You can't just run around RSA-encrypting any bitstream: if it's
|
|
|
|
* greater than the RSA key, then OpenSSL will happily encrypt,
|
|
|
|
* and later decrypt to the wrong value. So we set the first bit
|
|
|
|
* of 'pubkey' to 0. This means that our symmetric key is really only
|
|
|
|
* 127 bits long, but since it shouldn't be necessary to encrypt
|
|
|
|
* DH public keys values in the first place, we should be fine.
|
|
|
|
*/
|
|
|
|
pubkey[0] &= 0x7f;
|
2003-05-01 21:42:51 +02:00
|
|
|
|
|
|
|
if (crypto_dh_get_public(dh, pubkey+16, dhbytes))
|
|
|
|
goto err;
|
|
|
|
|
2003-05-05 06:27:00 +02:00
|
|
|
#if 0
|
|
|
|
printf("Client DH sent: %x %x %x ... %x %x %x\n",
|
|
|
|
(int) pubkey[16], (int) pubkey[17], (int) pubkey[18],
|
|
|
|
(int) pubkey[205], (int) pubkey[206], (int) pubkey[207]);
|
|
|
|
|
|
|
|
printf("Client key sent: %x %x %x ... %x %x %x\n",
|
|
|
|
pubkey[0],pubkey[1],pubkey[2],
|
|
|
|
pubkey[13],pubkey[14],pubkey[15]);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
cipher = crypto_create_init_cipher(CRYPTO_CIPHER_3DES, pubkey, iv, 1);
|
|
|
|
|
|
|
|
if (!cipher)
|
|
|
|
goto err;
|
|
|
|
|
2003-05-06 01:24:46 +02:00
|
|
|
if (crypto_pk_public_encrypt(dest_router_key, pubkey, pkbytes,
|
2003-05-05 06:27:00 +02:00
|
|
|
onion_skin_out, RSA_NO_PADDING)==-1)
|
2003-05-01 21:42:51 +02:00
|
|
|
goto err;
|
|
|
|
|
2003-05-05 06:27:00 +02:00
|
|
|
if (crypto_cipher_encrypt(cipher, pubkey+pkbytes, dhbytes+16-pkbytes,
|
2003-05-01 21:42:51 +02:00
|
|
|
onion_skin_out+pkbytes))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
free(pubkey);
|
|
|
|
crypto_free_cipher_env(cipher);
|
|
|
|
*handshake_state_out = dh;
|
2003-05-05 06:27:00 +02:00
|
|
|
|
2003-05-01 21:42:51 +02:00
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
if (pubkey) free(pubkey);
|
|
|
|
if (dh) crypto_dh_free(dh);
|
|
|
|
if (cipher) crypto_free_cipher_env(cipher);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Given an encrypted DH public key as generated by onion_skin_create,
|
|
|
|
* and the private key for this onion router, generate the 192-byte DH
|
|
|
|
* reply, and key_out_len bytes of key material, stored in key_out.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
onion_skin_server_handshake(char *onion_skin, /* 208 bytes long */
|
|
|
|
crypto_pk_env_t *private_key,
|
|
|
|
char *handshake_reply_out, /* 192 bytes long */
|
|
|
|
char *key_out,
|
|
|
|
int key_out_len)
|
|
|
|
{
|
|
|
|
char buf[208];
|
|
|
|
char iv[16];
|
|
|
|
crypto_dh_env_t *dh = NULL;
|
|
|
|
crypto_cipher_env_t *cipher = NULL;
|
|
|
|
int pkbytes;
|
|
|
|
|
|
|
|
memset(iv, 0, 16);
|
|
|
|
pkbytes = crypto_pk_keysize(private_key);
|
|
|
|
|
|
|
|
if (crypto_pk_private_decrypt(private_key,
|
|
|
|
onion_skin, pkbytes,
|
2003-05-05 06:27:00 +02:00
|
|
|
buf, RSA_NO_PADDING) == -1)
|
2003-05-01 21:42:51 +02:00
|
|
|
goto err;
|
2003-05-05 06:27:00 +02:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
printf("Client key got: %x %x %x ... %x %x %x\n",
|
|
|
|
buf[0],buf[1],buf[2], buf[13],buf[14],buf[15]);
|
|
|
|
#endif
|
2003-05-01 21:42:51 +02:00
|
|
|
|
|
|
|
cipher = crypto_create_init_cipher(CRYPTO_CIPHER_3DES, buf, iv, 0);
|
|
|
|
|
|
|
|
if (crypto_cipher_decrypt(cipher, onion_skin+pkbytes, 208-pkbytes,
|
|
|
|
buf+pkbytes))
|
|
|
|
goto err;
|
2003-05-05 06:27:00 +02:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
printf("Client DH got: %x %x %x ... %x %x %x\n",
|
|
|
|
(int) buf[16], (int) buf[17], (int) buf[18],
|
|
|
|
(int) buf[205], (int) buf[206], (int) buf[207]);
|
|
|
|
#endif
|
2003-05-01 21:42:51 +02:00
|
|
|
|
|
|
|
dh = crypto_dh_new();
|
|
|
|
if (crypto_dh_get_public(dh, handshake_reply_out, 192))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (crypto_dh_compute_secret(dh, buf+16, 192, buf))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
memcpy(key_out, buf+192-key_out_len, key_out_len);
|
|
|
|
|
|
|
|
crypto_free_cipher_env(cipher);
|
|
|
|
crypto_dh_free(dh);
|
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
if (cipher) crypto_free_cipher_env(cipher);
|
|
|
|
if (dh) crypto_dh_free(dh);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Finish the client side of the DH handshake.
|
|
|
|
* Given the 192 byte DH reply as generated by onion_skin_server_handshake
|
|
|
|
* and the handshake state generated by onion_skin_create, generate
|
|
|
|
* key_out_len bytes of shared key material and store them in key_out.
|
|
|
|
*
|
|
|
|
* After the invocation, call crypto_dh_free on handshake_state.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
onion_skin_client_handshake(crypto_dh_env_t *handshake_state,
|
|
|
|
char *handshake_reply,/* Must be 192 bytes long*/
|
|
|
|
char *key_out,
|
|
|
|
int key_out_len)
|
|
|
|
{
|
|
|
|
char key_material[192];
|
|
|
|
assert(crypto_dh_get_bytes(handshake_state) == 192);
|
|
|
|
|
|
|
|
memset(key_material, 0, 192);
|
|
|
|
|
|
|
|
if (crypto_dh_compute_secret(handshake_state, handshake_reply, 192,
|
|
|
|
key_material))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
memcpy(key_out, key_material+192-key_out_len, key_out_len);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-04-07 04:12:02 +02:00
|
|
|
/*
|
|
|
|
Local Variables:
|
|
|
|
mode:c
|
|
|
|
indent-tabs-mode:nil
|
|
|
|
c-basic-offset:2
|
|
|
|
End:
|
|
|
|
*/
|