[or-cvs] Remove the notion of "onion ciphers"; make packing and unpa...

Nick Mathewson nickm at seul.org
Wed Apr 16 16:19:29 UTC 2003


Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/tmp/cvs-serv29922/src/or

Modified Files:
	circuit.c onion.c or.h 
Log Message:
Remove the notion of "onion ciphers"; make packing and unpacking separate fns

Index: circuit.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuit.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- circuit.c	16 Apr 2003 06:18:30 -0000	1.30
+++ circuit.c	16 Apr 2003 16:19:27 -0000	1.31
@@ -140,7 +140,7 @@
   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 @@
   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 @@
 
   /* 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 @@
 }
 
 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 @@
   }
   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);
 }

Index: onion.c
===================================================================
RCS file: /home/or/cvsroot/src/or/onion.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- onion.c	16 Apr 2003 06:18:30 -0000	1.33
+++ onion.c	16 Apr 2003 16:19:27 -0000	1.34
@@ -217,28 +217,29 @@
   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 @@
  */
 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 @@
   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 @@
         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 @@
 //      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 @@
       
       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 @@
       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 @@
       
     /* 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 @@
       
     /* 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 @@
 
 /* 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 @@
   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 @@
 }
 
 /* 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 @@
   }
   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;
   }
@@ -826,6 +804,28 @@
   log(LOG_DEBUG,"find_tracked_onion(): Remembered new onion (expires %d)", to->expire);
  
   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);
 }
 
 /*

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -d -r1.64 -r1.65
--- or.h	16 Apr 2003 16:17:27 -0000	1.64
+++ or.h	16 Apr 2003 16:19:27 -0000	1.65
@@ -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 @@
 } 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 @@
 
   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 *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 @@
 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,23 +749,23 @@
  */
 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 ***************************/
 



More information about the tor-commits mailing list