|  | @@ -122,10 +122,10 @@ void onion_pending_remove(circuit_t *circ) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* given a response payload and keys, initialize, then send a created cell back */
 | 
	
		
			
				|  |  |  int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *keys) {
 | 
	
		
			
				|  |  | -  unsigned char iv[CIPHER_IV_LEN];
 | 
	
		
			
				|  |  |    cell_t cell;
 | 
	
		
			
				|  |  | +  crypt_path_t *tmp_cpath;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  memset(iv, 0, CIPHER_IV_LEN);
 | 
	
		
			
				|  |  | +  tmp_cpath = tor_malloc_zero(sizeof(tmp_cpath));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    memset(&cell, 0, sizeof(cell_t));
 | 
	
		
			
				|  |  |    cell.command = CELL_CREATED;
 | 
	
	
		
			
				|  | @@ -139,21 +139,16 @@ int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *key
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    log_fn(LOG_INFO,"init digest forward 0x%.8x, backward 0x%.8x.",
 | 
	
		
			
				|  |  |           (unsigned int)*(uint32_t*)(keys), (unsigned int)*(uint32_t*)(keys+20));
 | 
	
		
			
				|  |  | -  circ->n_digest = crypto_new_digest_env();
 | 
	
		
			
				|  |  | -  crypto_digest_add_bytes(circ->n_digest, keys, DIGEST_LEN);
 | 
	
		
			
				|  |  | -  circ->p_digest = crypto_new_digest_env();
 | 
	
		
			
				|  |  | -  crypto_digest_add_bytes(circ->p_digest, keys+DIGEST_LEN, DIGEST_LEN);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  log_fn(LOG_DEBUG,"init cipher forward 0x%.8x, backward 0x%.8x.",
 | 
	
		
			
				|  |  | -         (unsigned int)*(uint32_t*)(keys+40), (unsigned int)*(uint32_t*)(keys+40+16));
 | 
	
		
			
				|  |  | -  if (!(circ->n_crypto = crypto_create_init_cipher(keys+40,iv,0))) {
 | 
	
		
			
				|  |  | -    log_fn(LOG_WARN,"Cipher initialization failed (n).");
 | 
	
		
			
				|  |  | -    return -1;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  if (!(circ->p_crypto = crypto_create_init_cipher(keys+40+16,iv,1))) {
 | 
	
		
			
				|  |  | -    log_fn(LOG_WARN,"Cipher initialization failed (p).");
 | 
	
		
			
				|  |  | +  if (circuit_init_cpath_crypto(tmp_cpath, keys, 0)<0) {
 | 
	
		
			
				|  |  | +    log_fn(LOG_WARN,"Circuit initialization failed");
 | 
	
		
			
				|  |  | +    tor_free(tmp_cpath);
 | 
	
		
			
				|  |  |      return -1;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +  circ->n_digest = tmp_cpath->f_digest;
 | 
	
		
			
				|  |  | +  circ->n_crypto = tmp_cpath->f_crypto;
 | 
	
		
			
				|  |  | +  circ->p_digest = tmp_cpath->b_digest;
 | 
	
		
			
				|  |  | +  circ->p_crypto = tmp_cpath->b_crypto;
 | 
	
		
			
				|  |  | +  tor_free(tmp_cpath);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    memcpy(circ->handshake_digest, cell.payload+DH_KEY_LEN, DIGEST_LEN);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -553,15 +548,12 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
 | 
	
		
			
				|  |  |                    crypto_dh_env_t **handshake_state_out,
 | 
	
		
			
				|  |  |                    char *onion_skin_out) /* Must be ONIONSKIN_CHALLENGE_LEN bytes */
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  char iv[16];
 | 
	
		
			
				|  |  |    char *challenge = 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, ONIONSKIN_CHALLENGE_LEN);
 | 
	
		
			
				|  |  | -  memset(iv, 0, 16);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (!(dh = crypto_dh_new()))
 | 
	
		
			
				|  |  |      goto err;
 | 
	
	
		
			
				|  | @@ -570,20 +562,9 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
 | 
	
		
			
				|  |  |    pkbytes = crypto_pk_keysize(dest_router_key);
 | 
	
		
			
				|  |  |    assert(dhbytes == 128);
 | 
	
		
			
				|  |  |    assert(pkbytes == 128);
 | 
	
		
			
				|  |  | -  challenge = (char *)tor_malloc_zero(ONIONSKIN_CHALLENGE_LEN);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (crypto_rand(16, challenge))
 | 
	
		
			
				|  |  | -    goto err;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /* 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 'challenge' to 0.  This means that our symmetric key is really
 | 
	
		
			
				|  |  | -   * only 127 bits.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -  challenge[0] &= 0x7f;
 | 
	
		
			
				|  |  | +  challenge = (char *)tor_malloc_zero(ONIONSKIN_CHALLENGE_LEN-CIPHER_KEY_LEN);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (crypto_dh_get_public(dh, challenge+16, dhbytes))
 | 
	
		
			
				|  |  | +  if (crypto_dh_get_public(dh, challenge, dhbytes))
 | 
	
		
			
				|  |  |      goto err;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #ifdef DEBUG_ONION_SKINS
 | 
	
	
		
			
				|  | @@ -602,29 +583,18 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* set meeting point, meeting cookie, etc here. Leave zero for now. */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  cipher = crypto_create_init_cipher(challenge, iv, 1);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (!cipher)
 | 
	
		
			
				|  |  | -    goto err;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (crypto_pk_public_encrypt(dest_router_key, challenge, pkbytes,
 | 
	
		
			
				|  |  | -                               onion_skin_out, PK_NO_PADDING)==-1)
 | 
	
		
			
				|  |  | -    goto err;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (crypto_cipher_encrypt(cipher, challenge+pkbytes, ONIONSKIN_CHALLENGE_LEN-pkbytes,
 | 
	
		
			
				|  |  | -                            onion_skin_out+pkbytes))
 | 
	
		
			
				|  |  | +  if (crypto_pk_public_hybrid_encrypt(dest_router_key, challenge,
 | 
	
		
			
				|  |  | +                                      ONIONSKIN_CHALLENGE_LEN-CIPHER_KEY_LEN,
 | 
	
		
			
				|  |  | +                                      onion_skin_out, PK_NO_PADDING)<0)
 | 
	
		
			
				|  |  |      goto err;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    tor_free(challenge);
 | 
	
		
			
				|  |  | -  crypto_free_cipher_env(cipher);
 | 
	
		
			
				|  |  |    *handshake_state_out = dh;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    return 0;
 | 
	
		
			
				|  |  |   err:
 | 
	
		
			
				|  |  |    tor_free(challenge);
 | 
	
		
			
				|  |  |    if (dh) crypto_dh_free(dh);
 | 
	
		
			
				|  |  | -  if (cipher) crypto_free_cipher_env(cipher);
 | 
	
		
			
				|  |  |    return -1;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -641,41 +611,16 @@ onion_skin_server_handshake(char *onion_skin, /* ONIONSKIN_CHALLENGE_LEN bytes *
 | 
	
		
			
				|  |  |                              int key_out_len)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    char challenge[ONIONSKIN_CHALLENGE_LEN];
 | 
	
		
			
				|  |  | -  char iv[16];
 | 
	
		
			
				|  |  |    crypto_dh_env_t *dh = NULL;
 | 
	
		
			
				|  |  |    crypto_cipher_env_t *cipher = NULL;
 | 
	
		
			
				|  |  | -  int pkbytes;
 | 
	
		
			
				|  |  |    int len;
 | 
	
		
			
				|  |  |    char *key_material=NULL;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  memset(iv, 0, 16);
 | 
	
		
			
				|  |  | -  pkbytes = crypto_pk_keysize(private_key);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (crypto_pk_private_decrypt(private_key,
 | 
	
		
			
				|  |  | -                                onion_skin, pkbytes,
 | 
	
		
			
				|  |  | -                                challenge, PK_NO_PADDING) == -1)
 | 
	
		
			
				|  |  | +  if (crypto_pk_private_hybrid_decrypt(private_key,
 | 
	
		
			
				|  |  | +                                       onion_skin, ONIONSKIN_CHALLENGE_LEN,
 | 
	
		
			
				|  |  | +                                       challenge, PK_NO_PADDING)<0)
 | 
	
		
			
				|  |  |      goto err;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#ifdef DEBUG_ONION_SKINS
 | 
	
		
			
				|  |  | -  printf("Server: client symkey:");
 | 
	
		
			
				|  |  | -  PA(buf+0,16);
 | 
	
		
			
				|  |  | -  puts("");
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  cipher = crypto_create_init_cipher(challenge, iv, 0);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (crypto_cipher_decrypt(cipher, onion_skin+pkbytes, ONIONSKIN_CHALLENGE_LEN-pkbytes,
 | 
	
		
			
				|  |  | -                            challenge+pkbytes))
 | 
	
		
			
				|  |  | -    goto err;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#ifdef DEBUG_ONION_SKINS
 | 
	
		
			
				|  |  | -  printf("Server: client g^x:");
 | 
	
		
			
				|  |  | -  PA(buf+16,3);
 | 
	
		
			
				|  |  | -  printf("...");
 | 
	
		
			
				|  |  | -  PA(buf+141,3);
 | 
	
		
			
				|  |  | -  puts("");
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    dh = crypto_dh_new();
 | 
	
		
			
				|  |  |    if (crypto_dh_get_public(dh, handshake_reply_out, DH_KEY_LEN))
 | 
	
		
			
				|  |  |      goto err;
 | 
	
	
		
			
				|  | @@ -688,17 +633,17 @@ onion_skin_server_handshake(char *onion_skin, /* ONIONSKIN_CHALLENGE_LEN bytes *
 | 
	
		
			
				|  |  |    puts("");
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  key_material = tor_malloc(20+key_out_len);
 | 
	
		
			
				|  |  | -  len = crypto_dh_compute_secret(dh, challenge+16, DH_KEY_LEN,
 | 
	
		
			
				|  |  | -                                 key_material, 20+key_out_len);
 | 
	
		
			
				|  |  | +  key_material = tor_malloc(DIGEST_LEN+key_out_len);
 | 
	
		
			
				|  |  | +  len = crypto_dh_compute_secret(dh, challenge, DH_KEY_LEN,
 | 
	
		
			
				|  |  | +                                 key_material, DIGEST_LEN+key_out_len);
 | 
	
		
			
				|  |  |    if (len < 0)
 | 
	
		
			
				|  |  |      goto err;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* send back H(K|0) as proof that we learned K. */
 | 
	
		
			
				|  |  | -  memcpy(handshake_reply_out+DH_KEY_LEN, key_material, 20);
 | 
	
		
			
				|  |  | +  memcpy(handshake_reply_out+DH_KEY_LEN, key_material, DIGEST_LEN);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* use the rest of the key material for our shared keys, digests, etc */
 | 
	
		
			
				|  |  | -  memcpy(key_out, key_material+20, key_out_len);
 | 
	
		
			
				|  |  | +  memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #ifdef DEBUG_ONION_SKINS
 | 
	
		
			
				|  |  |    printf("Server: key material:");
 |