mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 13:53:31 +01:00
r17963@catbus: nickm | 2008-02-07 10:14:25 -0500
Be more thorough about memory poisoning and clearing. Add an in-place version of aes_crypt in order to remove a memcpy from relay_crypt_one_payload. svn:r13414
This commit is contained in:
parent
842a33ff20
commit
eecc44dab8
@ -13,6 +13,10 @@ Changes in version 0.2.0.19-alpha - 2008-02-??
|
|||||||
- Give more descriptive well-formedness errors for out-of-range
|
- Give more descriptive well-formedness errors for out-of-range
|
||||||
hidden service descriptor/protocol versions.
|
hidden service descriptor/protocol versions.
|
||||||
|
|
||||||
|
o Minor features (security):
|
||||||
|
- Be slightly more paranoid about overwriting sensitive memory on free,
|
||||||
|
as a defensive programming tactic to ensure forward secrecy.
|
||||||
|
|
||||||
o Deprecated features (controller):
|
o Deprecated features (controller):
|
||||||
- The status/version/num-versioning and status/version/num-concurring
|
- The status/version/num-versioning and status/version/num-concurring
|
||||||
GETINFO options are no longer useful in the V3 directory protocol:
|
GETINFO options are no longer useful in the V3 directory protocol:
|
||||||
@ -59,6 +63,8 @@ Changes in version 0.2.0.19-alpha - 2008-02-??
|
|||||||
from a CREATE cell that we are waiting for a cpuworker to be
|
from a CREATE cell that we are waiting for a cpuworker to be
|
||||||
assigned" and "onionskin from an EXTEND cell that we are going to
|
assigned" and "onionskin from an EXTEND cell that we are going to
|
||||||
send to an OR as soon as we are connected".
|
send to an OR as soon as we are connected".
|
||||||
|
- Add an in-place version of aes_crypt so that we can avoid doing a
|
||||||
|
needless memcpy() call on each cell payload.
|
||||||
|
|
||||||
|
|
||||||
Changes in version 0.2.0.18-alpha - 2008-01-25
|
Changes in version 0.2.0.18-alpha - 2008-01-25
|
||||||
|
@ -289,7 +289,7 @@ aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len,
|
|||||||
* of alignmement, using a bigger buffer, and so on. Not till after 0.1.2.x,
|
* of alignmement, using a bigger buffer, and so on. Not till after 0.1.2.x,
|
||||||
* though. */
|
* though. */
|
||||||
int c = cipher->pos;
|
int c = cipher->pos;
|
||||||
if (!len) return;
|
if (PREDICT_UNLIKELY(!len)) return;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
do {
|
do {
|
||||||
@ -312,6 +312,42 @@ aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Encrypt <b>len</b> bytes from <b>input</b>, storing the results in place.
|
||||||
|
* Uses the key in <b>cipher</b>, and advances the counter by <b>len</b> bytes
|
||||||
|
* as it encrypts.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* XXXX This function is up to 5% of our runtime in some profiles;
|
||||||
|
* we should look into unrolling some of the loops; taking advantage
|
||||||
|
* of alignmement, using a bigger buffer, and so on. Not till after 0.1.2.x,
|
||||||
|
* though. */
|
||||||
|
int c = cipher->pos;
|
||||||
|
if (PREDICT_UNLIKELY(!len)) return;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
do {
|
||||||
|
if (len-- == 0) { cipher->pos = c; return; }
|
||||||
|
*(data++) ^= cipher->buf[c];
|
||||||
|
} while (++c != 16);
|
||||||
|
cipher->pos = c = 0;
|
||||||
|
if (PREDICT_UNLIKELY(! ++COUNTER(cipher, 0))) {
|
||||||
|
if (PREDICT_UNLIKELY(! ++COUNTER(cipher, 1))) {
|
||||||
|
if (PREDICT_UNLIKELY(! ++COUNTER(cipher, 2))) {
|
||||||
|
++COUNTER(cipher, 3);
|
||||||
|
UPDATE_CTR_BUF(cipher, 3);
|
||||||
|
}
|
||||||
|
UPDATE_CTR_BUF(cipher, 2);
|
||||||
|
}
|
||||||
|
UPDATE_CTR_BUF(cipher, 1);
|
||||||
|
}
|
||||||
|
UPDATE_CTR_BUF(cipher, 0);
|
||||||
|
_aes_fill_buf(cipher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Reset the 128-bit counter of <b>cipher</b> to the 16-bit big-endian value
|
/** Reset the 128-bit counter of <b>cipher</b> to the 16-bit big-endian value
|
||||||
* in <b>iv</b>. */
|
* in <b>iv</b>. */
|
||||||
void
|
void
|
||||||
|
@ -25,6 +25,7 @@ void aes_free_cipher(aes_cnt_cipher_t *cipher);
|
|||||||
void aes_set_key(aes_cnt_cipher_t *cipher, const char *key, int key_bits);
|
void aes_set_key(aes_cnt_cipher_t *cipher, const char *key, int key_bits);
|
||||||
void aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len,
|
void aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len,
|
||||||
char *output);
|
char *output);
|
||||||
|
void aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len);
|
||||||
void aes_set_iv(aes_cnt_cipher_t *cipher, const char *iv);
|
void aes_set_iv(aes_cnt_cipher_t *cipher, const char *iv);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -380,6 +380,7 @@ crypto_free_cipher_env(crypto_cipher_env_t *env)
|
|||||||
|
|
||||||
tor_assert(env->cipher);
|
tor_assert(env->cipher);
|
||||||
aes_free_cipher(env->cipher);
|
aes_free_cipher(env->cipher);
|
||||||
|
memset(env, 0, sizeof(crypto_cipher_env_t));
|
||||||
tor_free(env);
|
tor_free(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -775,10 +776,13 @@ int
|
|||||||
crypto_pk_private_sign_digest(crypto_pk_env_t *env, char *to,
|
crypto_pk_private_sign_digest(crypto_pk_env_t *env, char *to,
|
||||||
const char *from, size_t fromlen)
|
const char *from, size_t fromlen)
|
||||||
{
|
{
|
||||||
|
int r;
|
||||||
char digest[DIGEST_LEN];
|
char digest[DIGEST_LEN];
|
||||||
if (crypto_digest(digest,from,fromlen)<0)
|
if (crypto_digest(digest,from,fromlen)<0)
|
||||||
return -1;
|
return -1;
|
||||||
return crypto_pk_private_sign(env,to,digest,DIGEST_LEN);
|
r = crypto_pk_private_sign(env,to,digest,DIGEST_LEN);
|
||||||
|
memset(digest, 0, sizeof(digest));
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Perform a hybrid (public/secret) encryption on <b>fromlen</b>
|
/** Perform a hybrid (public/secret) encryption on <b>fromlen</b>
|
||||||
@ -1156,6 +1160,16 @@ crypto_cipher_decrypt(crypto_cipher_env_t *env, char *to,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Encrypt <b>len</b> bytes on <b>from</b> using the cipher in <b>env</b>;
|
||||||
|
* on success, return 0. On failure, return -1.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
crypto_cipher_crypt_inplace(crypto_cipher_env_t *env, char *buf, size_t len)
|
||||||
|
{
|
||||||
|
aes_crypt_inplace(env->cipher, buf, len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Encrypt <b>fromlen</b> bytes (at least 1) from <b>from</b> with the key in
|
/** Encrypt <b>fromlen</b> bytes (at least 1) from <b>from</b> with the key in
|
||||||
* <b>cipher</b> to the buffer in <b>to</b> of length
|
* <b>cipher</b> to the buffer in <b>to</b> of length
|
||||||
* <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> plus
|
* <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> plus
|
||||||
@ -1250,6 +1264,7 @@ crypto_new_digest_env(void)
|
|||||||
void
|
void
|
||||||
crypto_free_digest_env(crypto_digest_env_t *digest)
|
crypto_free_digest_env(crypto_digest_env_t *digest)
|
||||||
{
|
{
|
||||||
|
memset(digest, 0, sizeof(crypto_digest_env_t));
|
||||||
tor_free(digest);
|
tor_free(digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1286,6 +1301,7 @@ crypto_digest_get_digest(crypto_digest_env_t *digest,
|
|||||||
memcpy(&tmpctx, &digest->d, sizeof(SHA_CTX));
|
memcpy(&tmpctx, &digest->d, sizeof(SHA_CTX));
|
||||||
SHA1_Final(r, &tmpctx);
|
SHA1_Final(r, &tmpctx);
|
||||||
memcpy(out, r, out_len);
|
memcpy(out, r, out_len);
|
||||||
|
memset(r, 0, sizeof(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Allocate and return a new digest object with the same state as
|
/** Allocate and return a new digest object with the same state as
|
||||||
@ -1588,11 +1604,13 @@ crypto_expand_key_material(const char *key_in, size_t key_in_len,
|
|||||||
}
|
}
|
||||||
memset(tmp, 0, key_in_len+1);
|
memset(tmp, 0, key_in_len+1);
|
||||||
tor_free(tmp);
|
tor_free(tmp);
|
||||||
|
memset(digest, 0, sizeof(digest));
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
memset(tmp, 0, key_in_len+1);
|
memset(tmp, 0, key_in_len+1);
|
||||||
tor_free(tmp);
|
tor_free(tmp);
|
||||||
|
memset(digest, 0, sizeof(digest));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1668,6 +1686,7 @@ crypto_seed_rng(void)
|
|||||||
return rand_poll_status ? 0 : -1;
|
return rand_poll_status ? 0 : -1;
|
||||||
}
|
}
|
||||||
RAND_seed(buf, sizeof(buf));
|
RAND_seed(buf, sizeof(buf));
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
for (i = 0; filenames[i]; ++i) {
|
for (i = 0; filenames[i]; ++i) {
|
||||||
@ -1682,6 +1701,7 @@ crypto_seed_rng(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
RAND_seed(buf, sizeof(buf));
|
RAND_seed(buf, sizeof(buf));
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1863,7 +1883,6 @@ base64_decode(char *dest, size_t destlen, const char *src, size_t srclen)
|
|||||||
ret += len;
|
ret += len;
|
||||||
return ret;
|
return ret;
|
||||||
#else
|
#else
|
||||||
#define ACC32
|
|
||||||
const char *eos = src+srclen;
|
const char *eos = src+srclen;
|
||||||
uint32_t n=0;
|
uint32_t n=0;
|
||||||
int n_idx=0;
|
int n_idx=0;
|
||||||
@ -2056,6 +2075,7 @@ base32_decode(char *dest, size_t destlen, const char *src, size_t srclen)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(tmp, 0, srclen);
|
||||||
tor_free(tmp);
|
tor_free(tmp);
|
||||||
tmp = NULL;
|
tmp = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
@ -2099,6 +2119,7 @@ secret_to_key(char *key_out, size_t key_out_len, const char *secret,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
crypto_digest_get_digest(d, key_out, key_out_len);
|
crypto_digest_get_digest(d, key_out, key_out_len);
|
||||||
|
memset(tmp, 0, 8+secret_len);
|
||||||
tor_free(tmp);
|
tor_free(tmp);
|
||||||
crypto_free_digest_env(d);
|
crypto_free_digest_env(d);
|
||||||
}
|
}
|
||||||
|
@ -128,6 +128,7 @@ int crypto_cipher_encrypt(crypto_cipher_env_t *env, char *to,
|
|||||||
const char *from, size_t fromlen);
|
const char *from, size_t fromlen);
|
||||||
int crypto_cipher_decrypt(crypto_cipher_env_t *env, char *to,
|
int crypto_cipher_decrypt(crypto_cipher_env_t *env, char *to,
|
||||||
const char *from, size_t fromlen);
|
const char *from, size_t fromlen);
|
||||||
|
int crypto_cipher_crypt_inplace(crypto_cipher_env_t *env, char *d, size_t len);
|
||||||
|
|
||||||
int crypto_cipher_encrypt_with_iv(crypto_cipher_env_t *env,
|
int crypto_cipher_encrypt_with_iv(crypto_cipher_env_t *env,
|
||||||
char *to, size_t tolen,
|
char *to, size_t tolen,
|
||||||
|
@ -378,10 +378,12 @@ static void
|
|||||||
circuit_free(circuit_t *circ)
|
circuit_free(circuit_t *circ)
|
||||||
{
|
{
|
||||||
void *mem;
|
void *mem;
|
||||||
|
size_t memlen;
|
||||||
tor_assert(circ);
|
tor_assert(circ);
|
||||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||||
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
|
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
|
||||||
mem = ocirc;
|
mem = ocirc;
|
||||||
|
memlen = sizeof(origin_circuit_t);
|
||||||
tor_assert(circ->magic == ORIGIN_CIRCUIT_MAGIC);
|
tor_assert(circ->magic == ORIGIN_CIRCUIT_MAGIC);
|
||||||
if (ocirc->build_state) {
|
if (ocirc->build_state) {
|
||||||
if (ocirc->build_state->chosen_exit)
|
if (ocirc->build_state->chosen_exit)
|
||||||
@ -398,6 +400,7 @@ circuit_free(circuit_t *circ)
|
|||||||
} else {
|
} else {
|
||||||
or_circuit_t *ocirc = TO_OR_CIRCUIT(circ);
|
or_circuit_t *ocirc = TO_OR_CIRCUIT(circ);
|
||||||
mem = ocirc;
|
mem = ocirc;
|
||||||
|
memlen = sizeof(or_circuit_t);
|
||||||
tor_assert(circ->magic == OR_CIRCUIT_MAGIC);
|
tor_assert(circ->magic == OR_CIRCUIT_MAGIC);
|
||||||
|
|
||||||
if (ocirc->p_crypto)
|
if (ocirc->p_crypto)
|
||||||
@ -432,7 +435,7 @@ circuit_free(circuit_t *circ)
|
|||||||
* "active" checks will be violated. */
|
* "active" checks will be violated. */
|
||||||
cell_queue_clear(&circ->n_conn_cells);
|
cell_queue_clear(&circ->n_conn_cells);
|
||||||
|
|
||||||
memset(circ, 0xAA, sizeof(circuit_t)); /* poison memory */
|
memset(circ, 0xAA, memlen); /* poison memory */
|
||||||
tor_free(mem);
|
tor_free(mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,7 +502,7 @@ circuit_free_cpath_node(crypt_path_t *victim)
|
|||||||
if (victim->extend_info)
|
if (victim->extend_info)
|
||||||
extend_info_free(victim->extend_info);
|
extend_info_free(victim->extend_info);
|
||||||
|
|
||||||
victim->magic = 0xDEADBEEFu;
|
memset(victim, 0xBB, sizeof(crypt_path_t)); /* poison memory */
|
||||||
tor_free(victim);
|
tor_free(victim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,27 +266,33 @@ static void
|
|||||||
_connection_free(connection_t *conn)
|
_connection_free(connection_t *conn)
|
||||||
{
|
{
|
||||||
void *mem;
|
void *mem;
|
||||||
|
size_t memlen;
|
||||||
switch (conn->type) {
|
switch (conn->type) {
|
||||||
case CONN_TYPE_OR:
|
case CONN_TYPE_OR:
|
||||||
tor_assert(conn->magic == OR_CONNECTION_MAGIC);
|
tor_assert(conn->magic == OR_CONNECTION_MAGIC);
|
||||||
mem = TO_OR_CONN(conn);
|
mem = TO_OR_CONN(conn);
|
||||||
|
memlen = sizeof(or_connection_t);
|
||||||
break;
|
break;
|
||||||
case CONN_TYPE_AP:
|
case CONN_TYPE_AP:
|
||||||
case CONN_TYPE_EXIT:
|
case CONN_TYPE_EXIT:
|
||||||
tor_assert(conn->magic == EDGE_CONNECTION_MAGIC);
|
tor_assert(conn->magic == EDGE_CONNECTION_MAGIC);
|
||||||
mem = TO_EDGE_CONN(conn);
|
mem = TO_EDGE_CONN(conn);
|
||||||
|
memlen = sizeof(edge_connection_t);
|
||||||
break;
|
break;
|
||||||
case CONN_TYPE_DIR:
|
case CONN_TYPE_DIR:
|
||||||
tor_assert(conn->magic == DIR_CONNECTION_MAGIC);
|
tor_assert(conn->magic == DIR_CONNECTION_MAGIC);
|
||||||
mem = TO_DIR_CONN(conn);
|
mem = TO_DIR_CONN(conn);
|
||||||
|
memlen = sizeof(dir_connection_t);
|
||||||
break;
|
break;
|
||||||
case CONN_TYPE_CONTROL:
|
case CONN_TYPE_CONTROL:
|
||||||
tor_assert(conn->magic == CONTROL_CONNECTION_MAGIC);
|
tor_assert(conn->magic == CONTROL_CONNECTION_MAGIC);
|
||||||
mem = TO_CONTROL_CONN(conn);
|
mem = TO_CONTROL_CONN(conn);
|
||||||
|
memlen = sizeof(control_connection_t);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tor_assert(conn->magic == BASE_CONNECTION_MAGIC);
|
tor_assert(conn->magic == BASE_CONNECTION_MAGIC);
|
||||||
mem = conn;
|
mem = conn;
|
||||||
|
memlen = sizeof(connection_t);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,6 +337,7 @@ _connection_free(connection_t *conn)
|
|||||||
if (CONN_IS_EDGE(conn)) {
|
if (CONN_IS_EDGE(conn)) {
|
||||||
edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
|
edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
|
||||||
tor_free(edge_conn->chosen_exit_name);
|
tor_free(edge_conn->chosen_exit_name);
|
||||||
|
memset(edge_conn->socks_request, 0xcc, sizeof(socks_request_t));
|
||||||
tor_free(edge_conn->socks_request);
|
tor_free(edge_conn->socks_request);
|
||||||
}
|
}
|
||||||
if (conn->type == CONN_TYPE_CONTROL) {
|
if (conn->type == CONN_TYPE_CONTROL) {
|
||||||
@ -365,7 +372,7 @@ _connection_free(connection_t *conn)
|
|||||||
connection_or_remove_from_identity_map(TO_OR_CONN(conn));
|
connection_or_remove_from_identity_map(TO_OR_CONN(conn));
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(conn, 0xAA, sizeof(connection_t)); /* poison memory */
|
memset(conn, 0xAA, memlen); /* poison memory */
|
||||||
tor_free(mem);
|
tor_free(mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
|
|||||||
crypto_dh_env_t **handshake_state_out,
|
crypto_dh_env_t **handshake_state_out,
|
||||||
char *onion_skin_out) /* ONIONSKIN_CHALLENGE_LEN bytes */
|
char *onion_skin_out) /* ONIONSKIN_CHALLENGE_LEN bytes */
|
||||||
{
|
{
|
||||||
char *challenge = NULL;
|
char challenge[DH_KEY_LEN];
|
||||||
crypto_dh_env_t *dh = NULL;
|
crypto_dh_env_t *dh = NULL;
|
||||||
int dhbytes, pkbytes;
|
int dhbytes, pkbytes;
|
||||||
|
|
||||||
@ -183,7 +183,6 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
|
|||||||
pkbytes = crypto_pk_keysize(dest_router_key);
|
pkbytes = crypto_pk_keysize(dest_router_key);
|
||||||
tor_assert(dhbytes == 128);
|
tor_assert(dhbytes == 128);
|
||||||
tor_assert(pkbytes == 128);
|
tor_assert(pkbytes == 128);
|
||||||
challenge = tor_malloc_zero(DH_KEY_LEN);
|
|
||||||
|
|
||||||
if (crypto_dh_get_public(dh, challenge, dhbytes))
|
if (crypto_dh_get_public(dh, challenge, dhbytes))
|
||||||
goto err;
|
goto err;
|
||||||
@ -211,12 +210,12 @@ onion_skin_create(crypto_pk_env_t *dest_router_key,
|
|||||||
PK_PKCS1_OAEP_PADDING, 1)<0)
|
PK_PKCS1_OAEP_PADDING, 1)<0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
tor_free(challenge);
|
memset(challenge, 0, sizeof(challenge));
|
||||||
*handshake_state_out = dh;
|
*handshake_state_out = dh;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
tor_free(challenge);
|
memset(challenge, 0, sizeof(challenge));
|
||||||
if (dh) crypto_dh_free(dh);
|
if (dh) crypto_dh_free(dh);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -238,6 +237,7 @@ onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/
|
|||||||
crypto_dh_env_t *dh = NULL;
|
crypto_dh_env_t *dh = NULL;
|
||||||
int len;
|
int len;
|
||||||
char *key_material=NULL;
|
char *key_material=NULL;
|
||||||
|
size_t key_material_len=0;
|
||||||
int i;
|
int i;
|
||||||
crypto_pk_env_t *k;
|
crypto_pk_env_t *k;
|
||||||
|
|
||||||
@ -277,9 +277,10 @@ onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/
|
|||||||
puts("");
|
puts("");
|
||||||
#endif
|
#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,
|
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) {
|
if (len < 0) {
|
||||||
log_info(LD_GENERAL, "crypto_dh_compute_secret failed.");
|
log_info(LD_GENERAL, "crypto_dh_compute_secret failed.");
|
||||||
goto err;
|
goto err;
|
||||||
@ -300,11 +301,17 @@ onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/
|
|||||||
puts("");
|
puts("");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
memset(challenge, 0, sizeof(challenge));
|
||||||
|
memset(key_material, 0, key_material_len);
|
||||||
tor_free(key_material);
|
tor_free(key_material);
|
||||||
crypto_dh_free(dh);
|
crypto_dh_free(dh);
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
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);
|
if (dh) crypto_dh_free(dh);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
@ -327,6 +334,7 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state,
|
|||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
char *key_material=NULL;
|
char *key_material=NULL;
|
||||||
|
size_t key_material_len;
|
||||||
tor_assert(crypto_dh_get_bytes(handshake_state) == DH_KEY_LEN);
|
tor_assert(crypto_dh_get_bytes(handshake_state) == DH_KEY_LEN);
|
||||||
|
|
||||||
#ifdef DEBUG_ONION_SKINS
|
#ifdef DEBUG_ONION_SKINS
|
||||||
@ -337,13 +345,14 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state,
|
|||||||
puts("");
|
puts("");
|
||||||
#endif
|
#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,
|
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)
|
if (len < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (memcmp(key_material, handshake_reply+DH_KEY_LEN, 20)) {
|
if (memcmp(key_material, handshake_reply+DH_KEY_LEN, DIGEST_LEN)) {
|
||||||
/* H(K) does *not* match. Something fishy. */
|
/* H(K) does *not* match. Something fishy. */
|
||||||
log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on onion handshake. "
|
log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on onion handshake. "
|
||||||
"Bug or attack.");
|
"Bug or attack.");
|
||||||
@ -351,7 +360,7 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* use the rest of the key material for our shared keys, digests, etc */
|
/* 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
|
#ifdef DEBUG_ONION_SKINS
|
||||||
printf("Client: keys out:");
|
printf("Client: keys out:");
|
||||||
@ -359,9 +368,11 @@ onion_skin_client_handshake(crypto_dh_env_t *handshake_state,
|
|||||||
puts("");
|
puts("");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
memset(key_material, 0, key_material_len);
|
||||||
tor_free(key_material);
|
tor_free(key_material);
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
|
memset(key_material, 0, key_material_len);
|
||||||
tor_free(key_material);
|
tor_free(key_material);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -380,8 +391,9 @@ fast_server_handshake(const char *key_in, /* DIGEST_LEN bytes */
|
|||||||
size_t key_out_len)
|
size_t key_out_len)
|
||||||
{
|
{
|
||||||
char tmp[DIGEST_LEN+DIGEST_LEN];
|
char tmp[DIGEST_LEN+DIGEST_LEN];
|
||||||
char *out;
|
char *out = NULL;
|
||||||
size_t out_len;
|
size_t out_len;
|
||||||
|
int r = -1;
|
||||||
|
|
||||||
if (crypto_rand(handshake_reply_out, DIGEST_LEN)<0)
|
if (crypto_rand(handshake_reply_out, DIGEST_LEN)<0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -391,15 +403,16 @@ fast_server_handshake(const char *key_in, /* DIGEST_LEN bytes */
|
|||||||
out_len = key_out_len+DIGEST_LEN;
|
out_len = key_out_len+DIGEST_LEN;
|
||||||
out = tor_malloc(out_len);
|
out = tor_malloc(out_len);
|
||||||
if (crypto_expand_key_material(tmp, sizeof(tmp), out, out_len)) {
|
if (crypto_expand_key_material(tmp, sizeof(tmp), out, out_len)) {
|
||||||
tor_free(out);
|
goto done;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
memcpy(handshake_reply_out+DIGEST_LEN, out, DIGEST_LEN);
|
memcpy(handshake_reply_out+DIGEST_LEN, out, DIGEST_LEN);
|
||||||
memcpy(key_out, out+DIGEST_LEN, key_out_len);
|
memcpy(key_out, out+DIGEST_LEN, key_out_len);
|
||||||
|
r = 0;
|
||||||
|
done:
|
||||||
memset(tmp, 0, sizeof(tmp));
|
memset(tmp, 0, sizeof(tmp));
|
||||||
memset(out, 0, out_len);
|
memset(out, 0, out_len);
|
||||||
tor_free(out);
|
tor_free(out);
|
||||||
return 0;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Implement the second half of the client side of the CREATE_FAST handshake.
|
/** Implement the second half of the client side of the CREATE_FAST handshake.
|
||||||
@ -423,27 +436,28 @@ fast_client_handshake(const char *handshake_state, /* DIGEST_LEN bytes */
|
|||||||
char tmp[DIGEST_LEN+DIGEST_LEN];
|
char tmp[DIGEST_LEN+DIGEST_LEN];
|
||||||
char *out;
|
char *out;
|
||||||
size_t out_len;
|
size_t out_len;
|
||||||
|
int r;
|
||||||
|
|
||||||
memcpy(tmp, handshake_state, DIGEST_LEN);
|
memcpy(tmp, handshake_state, DIGEST_LEN);
|
||||||
memcpy(tmp+DIGEST_LEN, handshake_reply_out, DIGEST_LEN);
|
memcpy(tmp+DIGEST_LEN, handshake_reply_out, DIGEST_LEN);
|
||||||
out_len = key_out_len+DIGEST_LEN;
|
out_len = key_out_len+DIGEST_LEN;
|
||||||
out = tor_malloc(out_len);
|
out = tor_malloc(out_len);
|
||||||
if (crypto_expand_key_material(tmp, sizeof(tmp), out, out_len)) {
|
if (crypto_expand_key_material(tmp, sizeof(tmp), out, out_len)) {
|
||||||
tor_free(out);
|
goto done;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
if (memcmp(out, handshake_reply_out+DIGEST_LEN, DIGEST_LEN)) {
|
if (memcmp(out, handshake_reply_out+DIGEST_LEN, DIGEST_LEN)) {
|
||||||
/* H(K) does *not* match. Something fishy. */
|
/* H(K) does *not* match. Something fishy. */
|
||||||
log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on fast handshake. "
|
log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on fast handshake. "
|
||||||
"Bug or attack.");
|
"Bug or attack.");
|
||||||
tor_free(out);
|
goto done;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
memcpy(key_out, out+DIGEST_LEN, key_out_len);
|
memcpy(key_out, out+DIGEST_LEN, key_out_len);
|
||||||
|
r = 0;
|
||||||
|
done:
|
||||||
memset(tmp, 0, sizeof(tmp));
|
memset(tmp, 0, sizeof(tmp));
|
||||||
memset(out, 0, out_len);
|
memset(out, 0, out_len);
|
||||||
tor_free(out);
|
tor_free(out);
|
||||||
return 0;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Remove all circuits from the pending list. Called from tor_free_all. */
|
/** Remove all circuits from the pending list. Called from tor_free_all. */
|
||||||
|
@ -117,19 +117,14 @@ static int
|
|||||||
relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in,
|
relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in,
|
||||||
int encrypt_mode)
|
int encrypt_mode)
|
||||||
{
|
{
|
||||||
char out[CELL_PAYLOAD_SIZE]; /* 'in' must be this size too */
|
|
||||||
int r;
|
int r;
|
||||||
|
(void)encrypt_mode;
|
||||||
if (encrypt_mode)
|
r = crypto_cipher_crypt_inplace(cipher, in, CELL_PAYLOAD_SIZE);
|
||||||
r = crypto_cipher_encrypt(cipher, out, in, CELL_PAYLOAD_SIZE);
|
|
||||||
else
|
|
||||||
r = crypto_cipher_decrypt(cipher, out, in, CELL_PAYLOAD_SIZE);
|
|
||||||
|
|
||||||
if (r) {
|
if (r) {
|
||||||
log_warn(LD_BUG,"Error during relay encryption");
|
log_warn(LD_BUG,"Error during relay encryption");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(in,out,CELL_PAYLOAD_SIZE);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user