diff --git a/doc/TODO b/doc/TODO index f7b5c0110a7a3ed0e4cd5eb170f3177e49e118df..b5623c28bc8860325269956fc5bc276af1273277 100644 --- a/doc/TODO +++ b/doc/TODO @@ -12,8 +12,8 @@ ARMA - arma claims X Abandoned - - Use a stronger cipher -NICK - 3des for now + . Use a stronger cipher + o 3des for now - aes when we everybody has openssl 0.9.7 . Topics / circuits o Implement topics diff --git a/doc/tor-spec.txt b/doc/tor-spec.txt index 166df9999b307072fc0772e8573fa70d45a36907..196349d4c385a0d0bc534cc3feaa9b3ccb28c18b 100644 --- a/doc/tor-spec.txt +++ b/doc/tor-spec.txt @@ -273,13 +273,11 @@ which reveals the downstream node. in a circuit. Each (unencrypted) layer has the following fields: Version [1 byte] - Back cipher [4 bits] - Forward cipher [4 bits] Port [2 bytes] Address [4 bytes] Expiration time [4 bytes] Key seed material [16 bytes] - [Total: 28 bytes] + [Total: 27 bytes] The value of Version is currently 2. @@ -287,7 +285,7 @@ which reveals the downstream node. 0: Identity 1: Single DES in OFB 2: RC4 - 3: Triple DES in OFB + 3: Triple DES (encrypt-decrypt-encrypt) in OFB The port and address field denote the IPV4 address and port of the next onion router in the circuit, or are set to 0 for the @@ -305,7 +303,6 @@ which reveals the downstream node. 2. For I=N downto 1: A. Create an onion layer L, setting Version=2, - BackCipher=DES/OFB(1), ForwardCipher=DES/OFB(2), ExpirationTime=now + 1 day, and Seed=16 random bytes. If I=N, set Port=Address=0. Else, set Port and Address to diff --git a/src/or/circuit.c b/src/or/circuit.c index 2157be0f2646927699f7a321e020e922710c9bfe..17dcc0662eace52c82f04d533bd47f3ace628cf4 100644 --- a/src/or/circuit.c +++ b/src/or/circuit.c @@ -140,7 +140,7 @@ try_again: return test_aci; } -int circuit_init(circuit_t *circ, int aci_type) { +int circuit_init(circuit_t *circ, int aci_type, onion_layer_t *layer) { unsigned char iv[16]; unsigned char digest1[20]; unsigned char digest2[20]; @@ -150,19 +150,13 @@ int circuit_init(circuit_t *circ, int aci_type) { assert(circ && circ->onion); log(LOG_DEBUG,"circuit_init(): starting"); - circ->n_port = ntohs(*(uint16_t *)(circ->onion+2)); + circ->n_port = layer->port; log(LOG_DEBUG,"circuit_init(): Set port to %u.",circ->n_port); - circ->n_addr = ntohl(*(uint32_t *)(circ->onion+4)); - circ->p_f = *(circ->onion+1) >> 4; /* backf */ - log(LOG_DEBUG,"circuit_init(): Set BACKF to %u.",circ->p_f); - circ->n_f = *(circ->onion+1) & 0x0f; /* forwf */ - log(LOG_DEBUG,"circuit_init(): Set FORWF to %u.",circ->n_f); + circ->n_addr = layer->addr; circ->state = CIRCUIT_STATE_OPEN; log(LOG_DEBUG,"circuit_init(): aci_type = %u.",aci_type); - - gettimeofday(&start,NULL); circ->n_aci = get_unique_aci_by_addr_port(circ->n_addr, circ->n_port, aci_type); @@ -188,24 +182,26 @@ int circuit_init(circuit_t *circ, int aci_type) { /* keys */ memset(iv, 0, 16); - crypto_SHA_digest(circ->onion+12,16,digest1); + crypto_SHA_digest(layer->keyseed,16,digest1); crypto_SHA_digest(digest1,20,digest2); crypto_SHA_digest(digest2,20,digest1); log(LOG_DEBUG,"circuit_init(): Computed keys."); - if (!(circ->p_crypto = create_onion_cipher(circ->p_f,digest2,iv,1))) { + if (!(circ->p_crypto = + crypto_create_init_cipher(DEFAULT_CIPHER,digest2,iv,1))) { log(LOG_ERR,"Cipher initialization failed (ACI %u).",circ->n_aci); return -1; } - if (!(circ->n_crypto = create_onion_cipher(circ->n_f, digest1, iv, 0))) { + if (!(circ->n_crypto = + crypto_create_init_cipher(DEFAULT_CIPHER,digest1,iv,0))) { log(LOG_ERR,"Cipher initialization failed (ACI %u).",circ->n_aci); return -1; } log(LOG_DEBUG,"circuit_init(): Cipher initialization complete."); - circ->expire = ntohl(*(uint32_t *)(circ->onion+8)); + circ->expire = layer->expire; return 0; } @@ -678,7 +674,6 @@ retry_circuit: } int circuit_create_onion(void) { - int i; int routelen; /* length of the route */ unsigned int *route; /* hops in the route as an array of indexes into rarray */ unsigned char *onion; /* holds the onion */ @@ -711,9 +706,6 @@ int circuit_create_onion(void) { } log(LOG_DEBUG,"circuit_create_onion(): Created an onion of size %u bytes.",onionlen); log(LOG_DEBUG,"circuit_create_onion(): Crypt path :"); - for (i=0;i<routelen;i++) { - log(LOG_DEBUG,"circuit_create_onion() : %u/%u",(cpath[i])->forwf, (cpath[i])->backf); - } return circuit_establish_circuit(route, routelen, onion, onionlen, cpath); } diff --git a/src/or/onion.c b/src/or/onion.c index d2cc6839b3abd4c48acd4c54d31dd1ec48484312..1fd23a66b3cce1b90485449f7a6b09b526429541 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -217,28 +217,29 @@ static int onion_process(circuit_t *circ) { int retval; aci_t aci_type; struct sockaddr_in me; /* my router identity */ + onion_layer_t layer; if(learn_my_address(&me) < 0) return -1; /* decrypt it in-place */ - if(decrypt_onion(circ->onion,circ->onionlen,getprivatekey()) < 0) { + if(decrypt_onion(circ->onion,circ->onionlen,getprivatekey(),&layer) < 0) { log(LOG_DEBUG,"command_process_create_cell(): decrypt_onion() failed, closing circuit."); return -1; } log(LOG_DEBUG,"command_process_create_cell(): Onion decrypted."); /* check freshness */ - if (ntohl(*(uint32_t *)(circ->onion+8)) < (uint32_t)time(NULL)) /* expired onion */ + if (layer.expire < (uint32_t)time(NULL)) /* expired onion */ /*XXXX*/ { log(LOG_NOTICE,"I have just received an expired onion. This could be a replay attack."); return -1; } aci_type = decide_aci_type(ntohl(me.sin_addr.s_addr), ntohs(me.sin_port), - ntohl(*(uint32_t *)(circ->onion+4)),ntohs(*(uint16_t *)(circ->onion+2))); + layer.addr, layer.port); - if(circuit_init(circ, aci_type) < 0) { + if(circuit_init(circ, aci_type, &layer) < 0) { log(LOG_ERR,"process_onion(): init_circuit() failed."); return -1; } @@ -335,7 +336,7 @@ int chooselen(double cw) */ unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *routelen) { - int i, j; + int i; int num_acceptable_routers; unsigned int *route; unsigned int oldchoice, choice; @@ -431,40 +432,17 @@ static int count_acceptable_routers(routerinfo_t **rarray, int rarray_len) { return num; } - -crypto_cipher_env_t * -create_onion_cipher(int cipher_type, char *key, char *iv, int encrypt_mode) -{ - switch (cipher_type) { - case ONION_CIPHER_DES: - cipher_type = CRYPTO_CIPHER_DES; - break; - case ONION_CIPHER_3DES: - cipher_type = CRYPTO_CIPHER_3DES; - break; - case ONION_CIPHER_RC4 : - cipher_type = CRYPTO_CIPHER_RC4; - break; - case ONION_CIPHER_IDENTITY : - cipher_type = CRYPTO_CIPHER_IDENTITY; - break; - default: - log(LOG_ERR, "Unknown cipher type %d", cipher_type); - return NULL; - } - return crypto_create_init_cipher(cipher_type, key, iv, encrypt_mode); -} - /* creates a new onion from route, stores it and its length into buf and len respectively */ unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int *route, int routelen, int *len, crypt_path_t **cpath) { int i,j; - char *layer; + char *layerp; crypt_path_t *hop = NULL; unsigned char *buf; routerinfo_t *router; unsigned char iv[16]; struct in_addr netaddr; + onion_layer_t layer; assert(rarray && route && len && routelen); @@ -491,7 +469,7 @@ unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int crypto_pk_keysize((rarray[route[i]])->pkey)); } - layer = buf + *len - ONION_LAYER_SIZE - ONION_PADDING_SIZE; /* pointer to innermost layer */ + layerp = buf + *len - ONION_LAYER_SIZE - ONION_PADDING_SIZE; /* pointer to innermost layer */ /* create the onion layer by layer, starting with the innermost */ for (i=0;i<routelen;i++) { router = rarray[route[i]]; @@ -500,32 +478,31 @@ unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int // log(LOG_DEBUG,"create_onion() : This router is %s:%u",inet_ntoa(*((struct in_addr *)&router->addr)),router->or_port); // log(LOG_DEBUG,"create_onion() : Key pointer = %u.",router->pkey); // log(LOG_DEBUG,"create_onion() : Key size = %u.",crypto_pk_keysize(router->pkey)); - - *layer = OR_VERSION; - /* Back F + Forw F both use DES OFB*/ - *(layer+1) = (ONION_DEFAULT_CIPHER << 4) /* for backf */ + - ONION_DEFAULT_CIPHER; /* for forwf */ + - /* Dest Port */ + layer.version = OR_VERSION; if (i) /* not last hop */ - *(uint16_t *)(layer+2) = htons(rarray[route[i-1]]->or_port); + layer.port = rarray[route[i-1]]->or_port; else - *(uint16_t *)(layer+2) = htons(0); + layer.port = 0; /* Dest Addr */ if (i) /* not last hop */ - *(uint32_t *)(layer+4) = htonl(rarray[route[i-1]]->addr); + layer.addr = rarray[route[i-1]]->addr; else - *(uint32_t *)(layer+4) = htonl(0); + layer.addr = 0; /* Expiration Time */ - *(uint32_t *)(layer+8) = htonl((uint32_t)(time(NULL) + 86400)); /* NOW + 1 day */ - + layer.expire = (uint32_t)(time(NULL) + 86400); /* NOW + 1 day */ + /* Key Seed Material */ - if(crypto_rand(16, layer+12)) { /* error */ + if(crypto_rand(16, layer.keyseed)) { /* error */ log(LOG_ERR,"Error generating random data."); goto error; } + + onion_pack(layerp, &layer); + // log(LOG_DEBUG,"create_onion() : Onion layer %u built : %u, %u, %u, %s, %u.",i+1,layer->zero,layer->backf,layer->forwf,inet_ntoa(*((struct in_addr *)&layer->addr)),layer->port); /* build up the crypt_path */ @@ -538,12 +515,9 @@ unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int log(LOG_DEBUG,"create_onion() : Building hop %u of crypt path.",i+1); hop = cpath[i]; - /* set crypto functions */ - hop->backf = *(layer+1) >> 4; - hop->forwf = *(layer+1) & 0x0f; /* calculate keys */ - crypto_SHA_digest(layer+12,16,hop->digest3); + crypto_SHA_digest(layer.keyseed,16,hop->digest3); log(LOG_DEBUG,"create_onion() : First SHA pass performed."); crypto_SHA_digest(hop->digest3,20,hop->digest2); log(LOG_DEBUG,"create_onion() : Second SHA pass performed."); @@ -554,13 +528,15 @@ unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int memset((void *)iv,0,16); /* initialize cipher engines */ - if (! (hop->f_crypto = create_onion_cipher(hop->forwf, hop->digest3, iv, 1))) { + if (! (hop->f_crypto = + crypto_create_init_cipher(DEFAULT_CIPHER, hop->digest3, iv, 1))) { /* cipher initialization failed */ log(LOG_ERR,"Could not create a crypto environment."); goto error; } - if (! (hop->b_crypto = create_onion_cipher(hop->backf, hop->digest2, iv, 0))) { + if (! (hop->b_crypto = + crypto_create_init_cipher(DEFAULT_CIPHER, hop->digest2, iv, 0))) { /* cipher initialization failed */ log(LOG_ERR,"Could not create a crypto environment."); goto error; @@ -571,7 +547,7 @@ unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int /* padding if this is the innermost layer */ if (!i) { - if (crypto_pseudo_rand(ONION_PADDING_SIZE, layer + ONION_LAYER_SIZE)) { /* error */ + if (crypto_pseudo_rand(ONION_PADDING_SIZE, layerp + ONION_LAYER_SIZE)) { /* error */ log(LOG_ERR,"Error generating pseudo-random data."); goto error; } @@ -580,14 +556,14 @@ unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int /* encrypt */ - if(encrypt_onion(layer,ONION_PADDING_SIZE+(i+1)*ONION_LAYER_SIZE,router->pkey) < 0) { + if(encrypt_onion(layerp,ONION_PADDING_SIZE+(i+1)*ONION_LAYER_SIZE,router->pkey,layer.keyseed) < 0) { log(LOG_ERR,"Error encrypting onion layer."); goto error; } log(LOG_DEBUG,"create_onion() : Encrypted layer."); /* calculate pointer to next layer */ - layer = buf + (routelen-i-2)*ONION_LAYER_SIZE; + layerp = buf + (routelen-i-2)*ONION_LAYER_SIZE; } return buf; @@ -609,7 +585,7 @@ unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int /* encrypts 128 bytes of the onion with the specified public key, the rest with * DES OFB with the key as defined in the outter layer */ -int encrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *pkey) { +int encrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *pkey, char* keyseed) { unsigned char *tmpbuf = NULL; /* temporary buffer for crypto operations */ unsigned char digest[20]; /* stores SHA1 output - 160 bits */ unsigned char iv[8]; @@ -631,7 +607,7 @@ int encrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *pkey log(LOG_DEBUG,"encrypt_onion() : allocated %u bytes of memory for the encrypted onion (at %u).",onionlen,tmpbuf); /* get key1 = SHA1(KeySeed) */ - if (crypto_SHA_digest(onion+12,16,digest)) { + if (crypto_SHA_digest(keyseed,16,digest)) { log(LOG_ERR,"Error computing SHA1 digest."); goto error; } @@ -675,7 +651,7 @@ int encrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *pkey } /* decrypts the first 128 bytes using RSA and prkey, decrypts the rest with DES OFB with key1 */ -int decrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *prkey) { +int decrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *prkey, onion_layer_t *layer) { void *tmpbuf = NULL; /* temporary buffer for crypto operations */ unsigned char digest[20]; /* stores SHA1 output - 160 bits */ unsigned char iv[8]; @@ -702,8 +678,10 @@ int decrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *prke } log(LOG_DEBUG,"decrypt_onion() : RSA decryption complete."); + onion_unpack(layer, onion); + /* get key1 = SHA1(KeySeed) */ - if (crypto_SHA_digest(tmpbuf+12,16,digest)) { + if (crypto_SHA_digest(layer->keyseed,16,digest)) { log(LOG_ERR,"Error computing SHA1 digest."); goto error; } @@ -828,6 +806,28 @@ static int find_tracked_onion(unsigned char *onion, uint32_t onionlen) { return 0; } +void +onion_pack(char *dest, onion_layer_t *src) +{ + assert((src->version & 0x80) == 0); + + *(uint8_t*)dest = src->version; + *(uint16_t*)(dest+1) = htons(src->port); + *(uint32_t*)(dest+3) = htonl(src->addr); + *(uint32_t*)(dest+7) = htonl(src->expire); + memcpy(dest+11, src->keyseed, ONION_KEYSEED_LEN); +} + +void +onion_unpack(onion_layer_t *dest, char *src) +{ + dest->version = *(uint8_t*)src; + dest->port = ntohs(*(uint16_t*)(src+1)); + dest->addr = ntohl(*(uint32_t*)(src+3)); + dest->expire = ntohl(*(uint32_t*)(src+7)); + memcpy(dest->keyseed, src+11, ONION_KEYSEED_LEN); +} + /* Local Variables: mode:c diff --git a/src/or/or.h b/src/or/or.h index 1c7d9b53e4194643e3cff6a0b8165fb0b8e6a7cc..b0be6b91ea0411ef468df52a74aed5e716ca297a 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -132,13 +132,18 @@ #define TOPIC_STATE_RESOLVING /* available cipher functions */ +#if 0 #define ONION_CIPHER_IDENTITY 0 #define ONION_CIPHER_DES 1 #define ONION_CIPHER_RC4 2 #define ONION_CIPHER_3DES 3 +#endif /* default cipher function */ +#if 0 #define ONION_DEFAULT_CIPHER ONION_CIPHER_3DES +#endif +#define DEFAULT_CIPHER CRYPTO_CIPHER_3DES #define CELL_DIRECTION_IN 1 #define CELL_DIRECTION_OUT 2 @@ -325,8 +330,6 @@ typedef struct { } routerinfo_t; typedef struct { - unsigned int forwf; - unsigned int backf; char digest2[20]; /* second SHA output for onion_layer_t.keyseed */ char digest3[20]; /* third SHA output for onion_layer_t.keyseed */ @@ -355,9 +358,6 @@ typedef struct { struct data_queue_t *data_queue; /* for queueing cells at the edges */ - unsigned char p_f; /* crypto functions */ - unsigned char n_f; - crypto_cipher_env_t *p_crypto; /* crypto environments */ crypto_cipher_env_t *n_crypto; @@ -383,7 +383,19 @@ struct onion_queue_t { struct onion_queue_t *next; }; -#define ONION_LAYER_SIZE 28 +#define ONION_KEYSEED_LEN 16 + +typedef struct { + uint8_t version; + uint16_t port; + uint32_t addr; + uint32_t expire; + unsigned char keyseed[ONION_KEYSEED_LEN]; +} onion_layer_t; +/* ugly hack XXXX */ +#define ONION_KEYSEED_OFFSET 11 + +#define ONION_LAYER_SIZE 27 #define ONION_PADDING_SIZE (128-ONION_LAYER_SIZE) typedef struct { @@ -490,7 +502,7 @@ void circuit_resume_edge_reading(circuit_t *circ, int edge_type); int circuit_consider_stop_edge_reading(circuit_t *circ, int edge_type); int circuit_consider_sending_sendme(circuit_t *circ, int edge_type); -int circuit_init(circuit_t *circ, int aci_type); +int circuit_init(circuit_t *circ, int aci_type, onion_layer_t *layer); void circuit_free(circuit_t *circ); void circuit_free_cpath(crypt_path_t **cpath, int cpathlen); @@ -737,24 +749,24 @@ int chooselen(double cw); */ unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *routelen); -/* create a cipher by onion cipher type. */ -crypto_cipher_env_t *create_onion_cipher(int cipher_type, char *key, char *iv, int encrypt_mode); - /* creates a new onion from route, stores it and its length into bufp and lenp respectively */ unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int *route, int routelen, int *len, crypt_path_t **cpath); /* encrypts 128 bytes of the onion with the specified public key, the rest with * DES OFB with the key as defined in the outter layer */ -int encrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *pkey); +int encrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *pkey, char *keyseed); -/* decrypts the first 128 bytes using RSA and prkey, decrypts the rest with DES OFB with key1 */ -int decrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *prkey); +/* decrypts the first 128 bytes using RSA and prkey, decrypts the rest with DES OFB with key1. Writes the first layer into 'layer' */ +int decrypt_onion(unsigned char *onion, uint32_t onionlen, crypto_pk_env_t *prkey, onion_layer_t *layer); /* delete first n bytes of the onion and pads the end with n bytes of random data */ void pad_onion(unsigned char *onion, uint32_t onionlen, int n); void init_tracked_tree(void); +void onion_pack(char *dest, onion_layer_t *src); +void onion_unpack(onion_layer_t *dest, char *src); + /********************************* routers.c ***************************/ int learn_my_address(struct sockaddr_in *me);