|
@@ -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:");
|