Browse Source

Remove the notion of "onion ciphers"; make packing and unpacking separate fns

svn:r236
Nick Mathewson 22 years ago
parent
commit
0c61bc3756
5 changed files with 95 additions and 94 deletions
  1. 2 2
      doc/TODO
  2. 2 5
      doc/tor-spec.txt
  3. 9 17
      src/or/circuit.c
  4. 57 57
      src/or/onion.c
  5. 25 13
      src/or/or.h

+ 2 - 2
doc/TODO

@@ -12,8 +12,8 @@ ARMA    - arma claims
         X Abandoned
         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
                 - aes when we everybody has openssl 0.9.7
         . Topics / circuits
         . Topics / circuits
                 o Implement topics
                 o Implement topics

+ 2 - 5
doc/tor-spec.txt

@@ -273,13 +273,11 @@ which reveals the downstream node.
    in a circuit.  Each (unencrypted) layer has the following fields:
    in a circuit.  Each (unencrypted) layer has the following fields:
 
 
          Version                  [1 byte]
          Version                  [1 byte]
-         Back cipher              [4 bits]
-         Forward cipher           [4 bits]
          Port                     [2 bytes]
          Port                     [2 bytes]
          Address                  [4 bytes]
          Address                  [4 bytes]
          Expiration time          [4 bytes]
          Expiration time          [4 bytes]
          Key seed material        [16 bytes]
          Key seed material        [16 bytes]
-                             [Total: 28 bytes]
+                             [Total: 27 bytes]
 
 
      The value of Version is currently 2.
      The value of Version is currently 2.
 
 
@@ -287,7 +285,7 @@ which reveals the downstream node.
           0: Identity 
           0: Identity 
           1: Single DES in OFB
           1: Single DES in OFB
           2: RC4
           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 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
      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:
       2. For I=N downto 1:
   
   
          A. Create an onion layer L, setting Version=2,
          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.
             ExpirationTime=now + 1 day, and Seed=16 random bytes.
 
 
             If I=N, set Port=Address=0.  Else, set Port and Address to
             If I=N, set Port=Address=0.  Else, set Port and Address to

+ 9 - 17
src/or/circuit.c

@@ -140,7 +140,7 @@ try_again:
   return test_aci;
   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 iv[16];
   unsigned char digest1[20];
   unsigned char digest1[20];
   unsigned char digest2[20];
   unsigned char digest2[20];
@@ -150,19 +150,13 @@ int circuit_init(circuit_t *circ, int aci_type) {
   assert(circ && circ->onion);
   assert(circ && circ->onion);
 
 
   log(LOG_DEBUG,"circuit_init(): starting");
   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);
   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;
   circ->state = CIRCUIT_STATE_OPEN;
 
 
   log(LOG_DEBUG,"circuit_init(): aci_type = %u.",aci_type);
   log(LOG_DEBUG,"circuit_init(): aci_type = %u.",aci_type);
 
 
-
-
   gettimeofday(&start,NULL);
   gettimeofday(&start,NULL);
 
 
   circ->n_aci = get_unique_aci_by_addr_port(circ->n_addr, circ->n_port, aci_type);
   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 */
   /* keys */
   memset(iv, 0, 16);
   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(digest1,20,digest2);
   crypto_SHA_digest(digest2,20,digest1);
   crypto_SHA_digest(digest2,20,digest1);
   log(LOG_DEBUG,"circuit_init(): Computed keys.");
   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);
     log(LOG_ERR,"Cipher initialization failed (ACI %u).",circ->n_aci);
     return -1;
     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);
     log(LOG_ERR,"Cipher initialization failed (ACI %u).",circ->n_aci);
     return -1;
     return -1;
   }
   }
 
 
   log(LOG_DEBUG,"circuit_init(): Cipher initialization complete.");
   log(LOG_DEBUG,"circuit_init(): Cipher initialization complete.");
 
 
-  circ->expire = ntohl(*(uint32_t *)(circ->onion+8));
+  circ->expire = layer->expire;
 
 
   return 0;
   return 0;
 }
 }
@@ -678,7 +674,6 @@ retry_circuit:
 }
 }
 
 
 int circuit_create_onion(void) {
 int circuit_create_onion(void) {
-  int i;
   int routelen; /* length of the route */
   int routelen; /* length of the route */
   unsigned int *route; /* hops in the route as an array of indexes into rarray */
   unsigned int *route; /* hops in the route as an array of indexes into rarray */
   unsigned char *onion; /* holds the onion */
   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(): Created an onion of size %u bytes.",onionlen);
   log(LOG_DEBUG,"circuit_create_onion(): Crypt path :");
   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);
   return circuit_establish_circuit(route, routelen, onion, onionlen, cpath);
 }
 }

+ 57 - 57
src/or/onion.c

@@ -217,28 +217,29 @@ static int onion_process(circuit_t *circ) {
   int retval;
   int retval;
   aci_t aci_type;
   aci_t aci_type;
   struct sockaddr_in me; /* my router identity */
   struct sockaddr_in me; /* my router identity */
+  onion_layer_t layer;
 
 
   if(learn_my_address(&me) < 0)
   if(learn_my_address(&me) < 0)
     return -1;
     return -1;
 
 
   /* decrypt it in-place */
   /* 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.");
     log(LOG_DEBUG,"command_process_create_cell(): decrypt_onion() failed, closing circuit.");
     return -1;
     return -1;
   }
   }
   log(LOG_DEBUG,"command_process_create_cell(): Onion decrypted.");
   log(LOG_DEBUG,"command_process_create_cell(): Onion decrypted.");
 
 
   /* check freshness */
   /* 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.");
     log(LOG_NOTICE,"I have just received an expired onion. This could be a replay attack.");
     return -1;
     return -1;
   }
   }
 
 
   aci_type = decide_aci_type(ntohl(me.sin_addr.s_addr), ntohs(me.sin_port),
   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.");
     log(LOG_ERR,"process_onion(): init_circuit() failed.");
     return -1;
     return -1;
   }
   }
@@ -335,7 +336,7 @@ int chooselen(double cw)
  */
  */
 unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *routelen)
 unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *routelen)
 {
 {
-  int i, j;
+  int i;
   int num_acceptable_routers;
   int num_acceptable_routers;
   unsigned int *route;
   unsigned int *route;
   unsigned int oldchoice, choice;
   unsigned int oldchoice, choice;
@@ -431,40 +432,17 @@ static int count_acceptable_routers(routerinfo_t **rarray, int rarray_len) {
   return num;
   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 */
 /* 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)
 unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int *route, int routelen, int *len, crypt_path_t **cpath)
 {
 {
   int i,j;
   int i,j;
-  char *layer;
+  char *layerp;
   crypt_path_t *hop = NULL;
   crypt_path_t *hop = NULL;
   unsigned char *buf;
   unsigned char *buf;
   routerinfo_t *router;
   routerinfo_t *router;
   unsigned char iv[16];
   unsigned char iv[16];
   struct in_addr netaddr;
   struct in_addr netaddr;
+  onion_layer_t layer;
 
 
   assert(rarray && route && len && routelen);
   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));
         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 */
   /* create the onion layer by layer, starting with the innermost */
   for (i=0;i<routelen;i++) {
   for (i=0;i<routelen;i++) {
     router = rarray[route[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() : 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 pointer = %u.",router->pkey);
 //      log(LOG_DEBUG,"create_onion() : Key size = %u.",crypto_pk_keysize(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 */
     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
     else
-      *(uint16_t *)(layer+2) = htons(0);
+      layer.port = 0;
 
 
     /* Dest Addr */
     /* Dest Addr */
     if (i) /* not last hop */
     if (i) /* not last hop */
-      *(uint32_t *)(layer+4) = htonl(rarray[route[i-1]]->addr);
+      layer.addr = rarray[route[i-1]]->addr;
     else
     else
-      *(uint32_t *)(layer+4) = htonl(0);
+      layer.addr = 0;
 
 
     /* Expiration Time */
     /* 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 */
     /* Key Seed Material */
-    if(crypto_rand(16, layer+12)) { /* error */
+    if(crypto_rand(16, layer.keyseed)) { /* error */
       log(LOG_ERR,"Error generating random data.");
       log(LOG_ERR,"Error generating random data.");
       goto error;
       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);
 //      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 */
     /* 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);
       log(LOG_DEBUG,"create_onion() : Building hop %u of crypt path.",i+1);
       hop = cpath[i];
       hop = cpath[i];
-      /* set crypto functions */
-      hop->backf = *(layer+1) >> 4;
-      hop->forwf = *(layer+1) & 0x0f;
 
 
       /* calculate keys */
       /* 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.");
       log(LOG_DEBUG,"create_onion() : First SHA pass performed.");
       crypto_SHA_digest(hop->digest3,20,hop->digest2);
       crypto_SHA_digest(hop->digest3,20,hop->digest2);
       log(LOG_DEBUG,"create_onion() : Second SHA pass performed.");
       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);
       memset((void *)iv,0,16);
 
 
       /* initialize cipher engines */
       /* 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 */
         /* cipher initialization failed */
         log(LOG_ERR,"Could not create a crypto environment.");
         log(LOG_ERR,"Could not create a crypto environment.");
         goto error;
         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 */
         /* cipher initialization failed */
         log(LOG_ERR,"Could not create a crypto environment.");
         log(LOG_ERR,"Could not create a crypto environment.");
         goto error;
         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 */
     /* padding if this is the innermost layer */
     if (!i) {
     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.");
         log(LOG_ERR,"Error generating pseudo-random data.");
         goto error;
         goto error;
       }
       }
@@ -580,14 +556,14 @@ unsigned char *create_onion(routerinfo_t **rarray, int rarray_len, unsigned int
       
       
     /* encrypt */
     /* 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.");
       log(LOG_ERR,"Error encrypting onion layer.");
       goto error;
       goto error;
     }
     }
     log(LOG_DEBUG,"create_onion() : Encrypted layer.");
     log(LOG_DEBUG,"create_onion() : Encrypted layer.");
       
       
     /* calculate pointer to next layer */
     /* calculate pointer to next layer */
-    layer = buf + (routelen-i-2)*ONION_LAYER_SIZE;
+    layerp = buf + (routelen-i-2)*ONION_LAYER_SIZE;
   }
   }
 
 
   return buf;
   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 
 /* 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 */
  * 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 *tmpbuf = NULL; /* temporary buffer for crypto operations */
   unsigned char digest[20]; /* stores SHA1 output - 160 bits */
   unsigned char digest[20]; /* stores SHA1 output - 160 bits */
   unsigned char iv[8];
   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);
   log(LOG_DEBUG,"encrypt_onion() : allocated %u bytes of memory for the encrypted onion (at %u).",onionlen,tmpbuf);
   
   
   /* get key1 = SHA1(KeySeed) */
   /* 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.");
     log(LOG_ERR,"Error computing SHA1 digest.");
     goto error;
     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 */
 /* 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 */
   void *tmpbuf = NULL; /* temporary buffer for crypto operations */
   unsigned char digest[20]; /* stores SHA1 output - 160 bits */
   unsigned char digest[20]; /* stores SHA1 output - 160 bits */
   unsigned char iv[8];
   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.");
   log(LOG_DEBUG,"decrypt_onion() : RSA decryption complete.");
     
     
+  onion_unpack(layer, onion);
+
   /* get key1 = SHA1(KeySeed) */
   /* 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.");
     log(LOG_ERR,"Error computing SHA1 digest.");
     goto error;
     goto error;
   }
   }
@@ -828,6 +806,28 @@ static int find_tracked_onion(unsigned char *onion, uint32_t onionlen) {
   return 0;
   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:
   Local Variables:
   mode:c
   mode:c

+ 25 - 13
src/or/or.h

@@ -132,13 +132,18 @@
 #define TOPIC_STATE_RESOLVING
 #define TOPIC_STATE_RESOLVING
 
 
 /* available cipher functions */
 /* available cipher functions */
+#if 0
 #define ONION_CIPHER_IDENTITY 0
 #define ONION_CIPHER_IDENTITY 0
 #define ONION_CIPHER_DES 1
 #define ONION_CIPHER_DES 1
 #define ONION_CIPHER_RC4 2
 #define ONION_CIPHER_RC4 2
 #define ONION_CIPHER_3DES 3
 #define ONION_CIPHER_3DES 3
+#endif
 
 
 /* default cipher function */
 /* default cipher function */
+#if 0
 #define ONION_DEFAULT_CIPHER ONION_CIPHER_3DES
 #define ONION_DEFAULT_CIPHER ONION_CIPHER_3DES
+#endif
+#define DEFAULT_CIPHER CRYPTO_CIPHER_3DES
 
 
 #define CELL_DIRECTION_IN 1
 #define CELL_DIRECTION_IN 1
 #define CELL_DIRECTION_OUT 2
 #define CELL_DIRECTION_OUT 2
@@ -325,8 +330,6 @@ typedef struct {
 } routerinfo_t;
 } routerinfo_t;
 
 
 typedef struct { 
 typedef struct { 
-  unsigned int forwf;
-  unsigned int backf;
   char digest2[20]; /* second SHA output for onion_layer_t.keyseed */
   char digest2[20]; /* second SHA output for onion_layer_t.keyseed */
   char digest3[20]; /* third 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 */
   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 *p_crypto; /* crypto environments */
   crypto_cipher_env_t *n_crypto;
   crypto_cipher_env_t *n_crypto;
 
 
@@ -383,7 +383,19 @@ struct onion_queue_t {
   struct onion_queue_t *next;
   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)
 #define ONION_PADDING_SIZE (128-ONION_LAYER_SIZE)
 
 
 typedef struct {
 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_stop_edge_reading(circuit_t *circ, int edge_type);
 int circuit_consider_sending_sendme(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(circuit_t *circ);
 void circuit_free_cpath(crypt_path_t **cpath, int cpathlen);
 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);
 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 */
 /* 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);
 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 
 /* 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 */
  * 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 */
 /* 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 pad_onion(unsigned char *onion, uint32_t onionlen, int n);
 
 
 void init_tracked_tree(void);
 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 ***************************/
 /********************************* routers.c ***************************/
 
 
 int learn_my_address(struct sockaddr_in *me);
 int learn_my_address(struct sockaddr_in *me);