prop289: Keep the digest bytes, not the object

The digest object is as large as the entire internal digest object's state,
which is often much larger than the actual set of bytes you're transmitting.

This commit makes it that we keep the digest itself which is 20 bytes.

Part of #26288

Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
David Goulet 2019-03-07 12:30:13 -05:00
parent 4efe9d653a
commit 77d560af64
6 changed files with 26 additions and 41 deletions

View File

@ -143,12 +143,9 @@ relay_decrypt_cell(circuit_t *circ, cell_t *cell,
*recognized = 1;
*layer_hint = thishop;
/* Keep current digest of this cell for the possible SENDME. */
if (thishop->crypto.sendme_digest) {
crypto_digest_free(thishop->crypto.sendme_digest);
}
thishop->crypto.sendme_digest =
crypto_digest_dup(thishop->crypto.b_digest);
crypto_digest_get_digest(thishop->crypto.b_digest,
(char *) thishop->crypto.sendme_digest,
sizeof(thishop->crypto.sendme_digest));
return 0;
}
}
@ -220,10 +217,9 @@ relay_encrypt_cell_inbound(cell_t *cell,
{
relay_set_digest(or_circ->crypto.b_digest, cell);
/* Keep a record of this cell, we might use it for validating the SENDME. */
if (or_circ->crypto.sendme_digest) {
crypto_digest_free(or_circ->crypto.sendme_digest);
}
or_circ->crypto.sendme_digest = crypto_digest_dup(or_circ->crypto.b_digest);
crypto_digest_get_digest(or_circ->crypto.b_digest,
(char *) or_circ->crypto.sendme_digest,
sizeof(or_circ->crypto.sendme_digest));
/* encrypt one layer */
relay_crypt_one_payload(or_circ->crypto.b_crypto, cell->payload);
}
@ -241,7 +237,6 @@ relay_crypto_clear(relay_crypto_t *crypto)
crypto_cipher_free(crypto->b_crypto);
crypto_digest_free(crypto->f_digest);
crypto_digest_free(crypto->b_digest);
crypto_digest_free(crypto->sendme_digest);
}
/** Initialize <b>crypto</b> from the key material in key_data.

View File

@ -26,7 +26,7 @@ struct relay_crypto_t {
struct crypto_digest_t *b_digest;
/** Digest used for the next SENDME cell if any. */
struct crypto_digest_t *sendme_digest;
uint8_t sendme_digest[DIGEST_LEN];
};
#undef crypto_cipher_t

View File

@ -215,7 +215,7 @@ sendme_is_valid(const circuit_t *circ, const uint8_t *cell_payload,
* Return the size in bytes of the encoded cell in payload. A negative value
* is returned on encoding failure. */
STATIC ssize_t
build_cell_payload_v1(crypto_digest_t *cell_digest, uint8_t *payload)
build_cell_payload_v1(const uint8_t *cell_digest, uint8_t *payload)
{
ssize_t len = -1;
sendme_cell_t *cell = NULL;
@ -231,9 +231,8 @@ build_cell_payload_v1(crypto_digest_t *cell_digest, uint8_t *payload)
sendme_cell_set_data_len(cell, TRUNNEL_SENDME_V1_DIGEST_LEN);
/* Copy the digest into the data payload. */
crypto_digest_get_digest(cell_digest,
(char *) sendme_cell_getarray_data_v1_digest(cell),
sendme_cell_get_data_len(cell));
memcpy(sendme_cell_getarray_data_v1_digest(cell), cell_digest,
sendme_cell_get_data_len(cell));
/* Finally, encode the cell into the payload. */
len = sendme_cell_encode(payload, RELAY_PAYLOAD_SIZE, cell);
@ -249,7 +248,7 @@ build_cell_payload_v1(crypto_digest_t *cell_digest, uint8_t *payload)
* because we failed to send the cell on it. */
static int
send_circuit_level_sendme(circuit_t *circ, crypt_path_t *layer_hint,
crypto_digest_t *cell_digest)
const uint8_t *cell_digest)
{
uint8_t emit_version;
uint8_t payload[RELAY_PAYLOAD_SIZE];
@ -340,7 +339,7 @@ sendme_connection_edge_consider_sending(edge_connection_t *conn)
void
sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint)
{
crypto_digest_t *digest;
const uint8_t *digest;
while ((layer_hint ? layer_hint->deliver_window : circ->deliver_window) <=
CIRCWINDOW_START - CIRCWINDOW_INCREMENT) {
@ -539,7 +538,7 @@ sendme_note_stream_data_packaged(edge_connection_t *conn)
void
sendme_note_cell_digest(circuit_t *circ)
{
uint8_t *digest;
const uint8_t *digest;
tor_assert(circ);
@ -555,16 +554,10 @@ sendme_note_cell_digest(circuit_t *circ)
return;
}
/* Only note the digest if we actually have the digest of the previous cell
* recorded. It should never happen in theory as we always record the last
* digest for the v1 SENDME. */
if (TO_OR_CIRCUIT(circ)->crypto.sendme_digest) {
digest = tor_malloc_zero(TRUNNEL_SENDME_V1_DIGEST_LEN);
crypto_digest_get_digest(TO_OR_CIRCUIT(circ)->crypto.sendme_digest,
(char *) digest, TRUNNEL_SENDME_V1_DIGEST_LEN);
if (circ->sendme_last_digests == NULL) {
circ->sendme_last_digests = smartlist_new();
}
smartlist_add(circ->sendme_last_digests, digest);
/* Add the digest to the last seen list in the circuit. */
digest = TO_OR_CIRCUIT(circ)->crypto.sendme_digest;
if (circ->sendme_last_digests == NULL) {
circ->sendme_last_digests = smartlist_new();
}
smartlist_add(circ->sendme_last_digests, tor_memdup(digest, DIGEST_LEN));
}

View File

@ -50,7 +50,7 @@ STATIC int get_accept_min_version(void);
STATIC bool cell_version_is_valid(uint8_t cell_version);
STATIC ssize_t build_cell_payload_v1(crypto_digest_t *cell_digest,
STATIC ssize_t build_cell_payload_v1(const uint8_t *cell_digest,
uint8_t *payload);
STATIC bool sendme_is_valid(const circuit_t *circ,
const uint8_t *cell_payload,

View File

@ -705,7 +705,6 @@ test_circbw_relay(void *arg)
circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL, 0);
circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
circ->cpath->deliver_window = CIRCWINDOW_START;
circ->cpath->crypto.sendme_digest = crypto_digest_new();
entryconn1 = fake_entry_conn(circ, 1);
edgeconn = ENTRY_TO_EDGE_CONN(entryconn1);

View File

@ -16,6 +16,8 @@
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/networkstatus_st.h"
#include "lib/crypt_ops/crypto_digest.h"
#include "test/test.h"
#include "test/log_test_helpers.h"
@ -64,7 +66,6 @@ test_v1_note_digest(void *arg)
circuit_free_(circ);
/* Points it to the OR circuit now. */
circ = TO_CIRCUIT(or_circ);
or_circ->crypto.sendme_digest = crypto_digest_new();
/* The package window has to be a multiple of CIRCWINDOW_INCREMENT minus 1
* in order to catched the CIRCWINDOW_INCREMENT-nth cell. Try something that
@ -144,7 +145,7 @@ test_v1_consensus_params(void *arg)
static void
test_v1_build_cell(void *arg)
{
uint8_t payload[RELAY_PAYLOAD_SIZE];
uint8_t payload[RELAY_PAYLOAD_SIZE], digest[DIGEST_LEN];
ssize_t ret;
crypto_digest_t *cell_digest = NULL;
or_circuit_t *or_circ = NULL;
@ -156,11 +157,12 @@ test_v1_build_cell(void *arg)
circ = TO_CIRCUIT(or_circ);
cell_digest = crypto_digest_new();
crypto_digest_add_bytes(cell_digest, "AAAAAAAAAAAAAAAAAAAA", 20);
tt_assert(cell_digest);
crypto_digest_add_bytes(cell_digest, "AAAAAAAAAAAAAAAAAAAA", 20);
crypto_digest_get_digest(cell_digest, (char *) digest, sizeof(digest));
/* SENDME v1 payload is 3 bytes + 20 bytes digest. See spec. */
ret = build_cell_payload_v1(cell_digest, payload);
ret = build_cell_payload_v1(digest, payload);
tt_int_op(ret, OP_EQ, 23);
/* Validation. */
@ -183,7 +185,6 @@ test_v1_build_cell(void *arg)
teardown_capture_of_logs();
/* Note the wrong digest in the circuit, cell should fail validation. */
or_circ->crypto.sendme_digest = crypto_digest_new();
circ->package_window = CIRCWINDOW_INCREMENT + 1;
sendme_note_cell_digest(circ);
tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1);
@ -194,11 +195,8 @@ test_v1_build_cell(void *arg)
expect_log_msg_containing("SENDME v1 cell digest do not match.");
teardown_capture_of_logs();
/* Cleanup */
crypto_digest_free(or_circ->crypto.sendme_digest);
/* Record the cell digest into the circuit, cell should validate. */
or_circ->crypto.sendme_digest = crypto_digest_dup(cell_digest);
memcpy(or_circ->crypto.sendme_digest, digest, sizeof(digest));
circ->package_window = CIRCWINDOW_INCREMENT + 1;
sendme_note_cell_digest(circ);
tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1);