|
@@ -166,7 +166,7 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
|
|
|
crypto_dh_env_t **handshake_state_out,
|
|
|
char *onion_skin_out)
|
|
|
{
|
|
|
- char *challenge = NULL;
|
|
|
+ char challenge[DH_KEY_LEN];
|
|
|
crypto_dh_env_t *dh = NULL;
|
|
|
int dhbytes, pkbytes;
|
|
|
|
|
@@ -183,7 +183,6 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
|
|
|
pkbytes = crypto_pk_keysize(dest_router_key);
|
|
|
tor_assert(dhbytes == 128);
|
|
|
tor_assert(pkbytes == 128);
|
|
|
- challenge = tor_malloc_zero(DH_KEY_LEN);
|
|
|
|
|
|
if (crypto_dh_get_public(dh, challenge, dhbytes))
|
|
|
goto err;
|
|
@@ -211,12 +210,12 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
|
|
|
PK_PKCS1_OAEP_PADDING, 1)<0)
|
|
|
goto err;
|
|
|
|
|
|
- tor_free(challenge);
|
|
|
+ memset(challenge, 0, sizeof(challenge));
|
|
|
*handshake_state_out = dh;
|
|
|
|
|
|
return 0;
|
|
|
err:
|
|
|
- tor_free(challenge);
|
|
|
+ memset(challenge, 0, sizeof(challenge));
|
|
|
if (dh) crypto_dh_free(dh);
|
|
|
return -1;
|
|
|
}
|
|
@@ -238,6 +237,7 @@ onion_skin_server_handshake(const char *onion_skin,
|
|
|
crypto_dh_env_t *dh = NULL;
|
|
|
int len;
|
|
|
char *key_material=NULL;
|
|
|
+ size_t key_material_len=0;
|
|
|
int i;
|
|
|
crypto_pk_env_t *k;
|
|
|
|
|
@@ -277,9 +277,10 @@ onion_skin_server_handshake(const char *onion_skin,
|
|
|
puts("");
|
|
|
#endif
|
|
|
|
|
|
- key_material = tor_malloc(DIGEST_LEN+key_out_len);
|
|
|
+ key_material_len = DIGEST_LEN+key_out_len;
|
|
|
+ key_material = tor_malloc(key_material_len);
|
|
|
len = crypto_dh_compute_secret(dh, challenge, DH_KEY_LEN,
|
|
|
- key_material, DIGEST_LEN+key_out_len);
|
|
|
+ key_material, key_material_len);
|
|
|
if (len < 0) {
|
|
|
log_info(LD_GENERAL, "crypto_dh_compute_secret failed.");
|
|
|
goto err;
|
|
@@ -300,11 +301,17 @@ onion_skin_server_handshake(const char *onion_skin,
|
|
|
puts("");
|
|
|
#endif
|
|
|
|
|
|
+ memset(challenge, 0, sizeof(challenge));
|
|
|
+ memset(key_material, 0, key_material_len);
|
|
|
tor_free(key_material);
|
|
|
crypto_dh_free(dh);
|
|
|
return 0;
|
|
|
err:
|
|
|
- tor_free(key_material);
|
|
|
+ memset(challenge, 0, sizeof(challenge));
|
|
|
+ if (key_material) {
|
|
|
+ memset(key_material, 0, key_material_len);
|
|
|
+ tor_free(key_material);
|
|
|
+ }
|
|
|
if (dh) crypto_dh_free(dh);
|
|
|
|
|
|
return -1;
|
|
@@ -327,6 +334,7 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state,
|
|
|
{
|
|
|
int len;
|
|
|
char *key_material=NULL;
|
|
|
+ size_t key_material_len;
|
|
|
tor_assert(crypto_dh_get_bytes(handshake_state) == DH_KEY_LEN);
|
|
|
|
|
|
#ifdef DEBUG_ONION_SKINS
|
|
@@ -337,13 +345,14 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state,
|
|
|
puts("");
|
|
|
#endif
|
|
|
|
|
|
- key_material = tor_malloc(20+key_out_len);
|
|
|
+ key_material_len = DIGEST_LEN + key_out_len;
|
|
|
+ key_material = tor_malloc(key_material_len);
|
|
|
len = crypto_dh_compute_secret(handshake_state, handshake_reply, DH_KEY_LEN,
|
|
|
- key_material, 20+key_out_len);
|
|
|
+ key_material, key_material_len);
|
|
|
if (len < 0)
|
|
|
goto err;
|
|
|
|
|
|
- if (memcmp(key_material, handshake_reply+DH_KEY_LEN, 20)) {
|
|
|
+ if (memcmp(key_material, handshake_reply+DH_KEY_LEN, DIGEST_LEN)) {
|
|
|
|
|
|
log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on onion handshake. "
|
|
|
"Bug or attack.");
|
|
@@ -351,7 +360,7 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state,
|
|
|
}
|
|
|
|
|
|
|
|
|
- memcpy(key_out, key_material+20, key_out_len);
|
|
|
+ memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
|
|
|
|
|
|
#ifdef DEBUG_ONION_SKINS
|
|
|
printf("Client: keys out:");
|
|
@@ -359,9 +368,11 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state,
|
|
|
puts("");
|
|
|
#endif
|
|
|
|
|
|
+ memset(key_material, 0, key_material_len);
|
|
|
tor_free(key_material);
|
|
|
return 0;
|
|
|
err:
|
|
|
+ memset(key_material, 0, key_material_len);
|
|
|
tor_free(key_material);
|
|
|
return -1;
|
|
|
}
|
|
@@ -380,8 +391,9 @@ fast_server_handshake(const char *key_in,
|
|
|
size_t key_out_len)
|
|
|
{
|
|
|
char tmp[DIGEST_LEN+DIGEST_LEN];
|
|
|
- char *out;
|
|
|
+ char *out = NULL;
|
|
|
size_t out_len;
|
|
|
+ int r = -1;
|
|
|
|
|
|
if (crypto_rand(handshake_reply_out, DIGEST_LEN)<0)
|
|
|
return -1;
|
|
@@ -391,15 +403,16 @@ fast_server_handshake(const char *key_in,
|
|
|
out_len = key_out_len+DIGEST_LEN;
|
|
|
out = tor_malloc(out_len);
|
|
|
if (crypto_expand_key_material(tmp, sizeof(tmp), out, out_len)) {
|
|
|
- tor_free(out);
|
|
|
- return -1;
|
|
|
+ goto done;
|
|
|
}
|
|
|
memcpy(handshake_reply_out+DIGEST_LEN, out, DIGEST_LEN);
|
|
|
memcpy(key_out, out+DIGEST_LEN, key_out_len);
|
|
|
+ r = 0;
|
|
|
+ done:
|
|
|
memset(tmp, 0, sizeof(tmp));
|
|
|
memset(out, 0, out_len);
|
|
|
tor_free(out);
|
|
|
- return 0;
|
|
|
+ return r;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -423,27 +436,28 @@ fast_client_handshake(const char *handshake_state,
|
|
|
char tmp[DIGEST_LEN+DIGEST_LEN];
|
|
|
char *out;
|
|
|
size_t out_len;
|
|
|
+ int r;
|
|
|
|
|
|
memcpy(tmp, handshake_state, DIGEST_LEN);
|
|
|
memcpy(tmp+DIGEST_LEN, handshake_reply_out, DIGEST_LEN);
|
|
|
out_len = key_out_len+DIGEST_LEN;
|
|
|
out = tor_malloc(out_len);
|
|
|
if (crypto_expand_key_material(tmp, sizeof(tmp), out, out_len)) {
|
|
|
- tor_free(out);
|
|
|
- return -1;
|
|
|
+ goto done;
|
|
|
}
|
|
|
if (memcmp(out, handshake_reply_out+DIGEST_LEN, DIGEST_LEN)) {
|
|
|
|
|
|
log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on fast handshake. "
|
|
|
"Bug or attack.");
|
|
|
- tor_free(out);
|
|
|
- return -1;
|
|
|
+ goto done;
|
|
|
}
|
|
|
memcpy(key_out, out+DIGEST_LEN, key_out_len);
|
|
|
+ r = 0;
|
|
|
+ done:
|
|
|
memset(tmp, 0, sizeof(tmp));
|
|
|
memset(out, 0, out_len);
|
|
|
tor_free(out);
|
|
|
- return 0;
|
|
|
+ return r;
|
|
|
}
|
|
|
|
|
|
|