1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#include "or.h"
connection_t *connection_op_new(void) {
return connection_new(CONN_TYPE_OP);
}
connection_t *connection_op_listener_new(void) {
return connection_new(CONN_TYPE_OP_LISTENER);
}
int connection_op_process_inbuf(connection_t *conn) {
assert(conn && conn->type == CONN_TYPE_OP);
if(conn->inbuf_reached_eof) {
/* eof reached, kill it. */
log(LOG_DEBUG,"connection_op_process_inbuf(): conn reached eof. Closing.");
return -1;
}
log(LOG_DEBUG,"connection_op_process_inbuf(): state %d.",conn->state);
switch(conn->state) {
case OP_CONN_STATE_AWAITING_KEYS:
return op_handshake_process_keys(conn);
case OP_CONN_STATE_OPEN:
return connection_process_cell_from_inbuf(conn);
default:
log(LOG_DEBUG,"connection_op_process_inbuf() called in state where I'm writing. Ignoring buf for now.")
;
}
return 0;
}
int op_handshake_process_keys(connection_t *conn) {
int retval;
int x;
/* key exchange message */
unsigned char auth_cipher[128];
unsigned char auth_plain[128];
assert(conn);
log(LOG_DEBUG,"op_handshake_process_keys() entered.");
if(conn->inbuf_datalen < 128) /* entire response available? */
return 0; /* not yet */
if(connection_fetch_from_buf(auth_cipher,128,conn) < 0) {
return -1;
}
log(LOG_DEBUG,"op_handshake_process_keys() : Received auth.");
/* decrypt response */
retval = RSA_private_decrypt(128,auth_cipher,auth_plain,conn->prkey,RSA_PKCS1_PADDING);
if (retval == -1)
{
log(LOG_ERR,"Decrypting keys from new OP failed.");
log(LOG_DEBUG,"op_handshake_process_keys() : Reason : %s.",
ERR_reason_error_string(ERR_get_error()));
return -1;
}
log(LOG_DEBUG,"Successfully decrypted keys from new OP.");
conn->bandwidth = ntohl(*((uint32_t *)auth_plain));
memcpy(conn->b_session_key, auth_plain+4, 8);
memcpy(conn->f_session_key, auth_plain+12, 8);
printf("f_session_key: ");
for(x=0;x<8;x++) {
printf("%d ",conn->f_session_key[x]);
}
printf("\nb_session_key: ");
for(x=0;x<8;x++) {
printf("%d ",conn->b_session_key[x]);
}
printf("\n");
memset((void *)conn->f_session_iv, 0, 8);
memset((void *)conn->b_session_iv, 0, 8);
EVP_CIPHER_CTX_init(&conn->f_ctx);
EVP_CIPHER_CTX_init(&conn->b_ctx);
EVP_EncryptInit(&conn->b_ctx, EVP_des_ofb(), conn->b_session_key, conn->b_session_iv);
EVP_DecryptInit(&conn->f_ctx, EVP_des_ofb(), conn->f_session_key, conn->f_session_iv);
#if 0
/* FIXME must choose conn->aci here? What does it mean for a connection to have an aci? */
log(LOG_DEBUG,"new_entry_connection : Chosen ACI %u.",conn->aci);
#endif
conn->state = OP_CONN_STATE_OPEN;
connection_watch_events(conn, POLLIN);
return 0;
}
int connection_op_finished_flushing(connection_t *conn) {
assert(conn && conn->type == CONN_TYPE_OP);
switch(conn->state) {
case OP_CONN_STATE_OPEN:
/* FIXME down the road, we'll clear out circuits that are pending to close */
connection_watch_events(conn, POLLIN);
return 0;
default:
log(LOG_DEBUG,"Bug: connection_op_finished_flushing() called in unexpected state.");
return 0;
}
return 0;
}
int connection_op_create_listener(RSA *prkey, struct sockaddr_in *local) {
log(LOG_DEBUG,"connection_create_op_listener starting");
return connection_create_listener(prkey, local, CONN_TYPE_OP_LISTENER);
}
int connection_op_handle_listener_read(connection_t *conn) {
log(LOG_NOTICE,"OP: Received a connection request. Waiting for keys.");
return connection_handle_listener_read(conn, CONN_TYPE_OP, OP_CONN_STATE_AWAITING_KEYS);
}
|