commit 5f6fc4f0e8df14733fa137134bd6063438098904
parent 089e53ba54df65fd191e5e46d3c29ac632aa95e2
Author: Nick Mathewson <nickm@torproject.org>
Date: Wed, 23 Apr 2025 11:19:43 -0400
CGO: Split modes into forward and backward variants.
I'll need this for getting tags right wrt torspec!328.
Diffstat:
3 files changed, 24 insertions(+), 15 deletions(-)
diff --git a/src/core/crypto/relay_crypto_cgo.c b/src/core/crypto/relay_crypto_cgo.c
@@ -363,7 +363,8 @@ cgo_crypt_new(cgo_mode_t mode, int aesbits, const uint8_t *keys, size_t keylen)
const uint8_t *end_of_keys = keys + keylen;
// Relays encrypt; clients decrypt.
// Don't reverse this: UIV+ is only non-malleable for _encryption_.
- bool encrypt = (mode == CGO_MODE_RELAY);
+ bool encrypt = (mode == CGO_MODE_RELAY_BACKWARD ||
+ mode == CGO_MODE_RELAY_FORWARD);
int r;
cgo_crypt_t *cgo = tor_malloc_zero(sizeof(cgo_crypt_t));
@@ -397,7 +398,8 @@ cgo_crypt_free_(cgo_crypt_t *cgo)
static void
cgo_crypt_update(cgo_crypt_t *cgo, cgo_mode_t mode)
{
- bool encrypt = (mode == CGO_MODE_RELAY);
+ bool encrypt = (mode == CGO_MODE_RELAY_BACKWARD ||
+ mode == CGO_MODE_RELAY_FORWARD);
cgo_uiv_update(&cgo->uiv, cgo->aes_bytes * 8, encrypt, cgo->nonce);
}
@@ -426,7 +428,7 @@ cgo_crypt_relay_forward(cgo_crypt_t *cgo, cell_t *cell,
cgo_uiv_encrypt(&cgo->uiv, h, cell->payload);
memcpy(cgo->tprime, cell->payload, CGO_TAG_LEN);
if (tor_memeq(cell->payload, cgo->nonce, CGO_TAG_LEN)) {
- cgo_crypt_update(cgo, CGO_MODE_RELAY);
+ cgo_crypt_update(cgo, CGO_MODE_RELAY_FORWARD);
// XXXX: Here and in Arti, we've used tprime as the value
// of our tag, but the proposal says to use T. We should
// fix that, unless the CGO implementors say it's better!
@@ -483,7 +485,7 @@ cgo_crypt_relay_originate(cgo_crypt_t *cgo, cell_t *cell,
// fix that, unless the CGO implementors say it's better!
*tag_out = cgo->tprime;
}
- cgo_crypt_update(cgo, CGO_MODE_RELAY);
+ cgo_crypt_update(cgo, CGO_MODE_RELAY_BACKWARD);
}
/**
@@ -523,7 +525,7 @@ cgo_crypt_client_originate(cgo_crypt_t *cgo, cell_t *cell,
{
memcpy(cell->payload, cgo->nonce, CGO_TAG_LEN);
cgo_crypt_client_forward(cgo, cell);
- cgo_crypt_update(cgo, CGO_MODE_CLIENT);
+ cgo_crypt_update(cgo, CGO_MODE_CLIENT_FORWARD);
// XXXX: Here and elsewhere, we've used tprime as the value
// of our tag, but the proposal says to use T. We should
// fix that, unless the CGO implementors say it's better!
@@ -559,7 +561,7 @@ cgo_crypt_client_backward(cgo_crypt_t *cgo, cell_t *cell,
memcpy(cgo->tprime, t_orig, CGO_TAG_LEN);
if (tor_memeq(cell->payload, cgo->nonce, CGO_TAG_LEN)) {
memcpy(cgo->nonce, t_orig, CGO_TAG_LEN);
- cgo_crypt_update(cgo, CGO_MODE_CLIENT);
+ cgo_crypt_update(cgo, CGO_MODE_CLIENT_BACKWARD);
// XXXX: Here and elsewhere, we've used tprime as the value
// of our tag, but the proposal says to use T. We should
// fix that, unless the CGO implementors say it's better!
diff --git a/src/core/crypto/relay_crypto_cgo.h b/src/core/crypto/relay_crypto_cgo.h
@@ -23,8 +23,10 @@
typedef struct cgo_crypt_t cgo_crypt_t;
typedef enum {
- CGO_MODE_CLIENT,
- CGO_MODE_RELAY,
+ CGO_MODE_CLIENT_FORWARD,
+ CGO_MODE_CLIENT_BACKWARD,
+ CGO_MODE_RELAY_FORWARD,
+ CGO_MODE_RELAY_BACKWARD,
} cgo_mode_t;
/**
@@ -204,6 +206,8 @@ struct cgo_crypt_t {
uint8_t nonce[CGO_TAG_LEN];
uint8_t tprime[CGO_TAG_LEN];
uint8_t aes_bytes;
+
+ uint8_t last_tag_relay_fwd[CGO_TAG_LEN];
};
#endif
diff --git a/src/test/test_crypto_cgo.c b/src/test/test_crypto_cgo.c
@@ -325,9 +325,9 @@ test_crypto_cgo_fwd(void *arg)
tt_uint_op(klen, OP_LE, sizeof(key_material[0]));
crypto_rand((char*)&key_material, sizeof(key_material));
for (int i = 0; i < N_HOPS; ++i) {
- client[i] = cgo_crypt_new(CGO_MODE_CLIENT,
+ client[i] = cgo_crypt_new(CGO_MODE_CLIENT_FORWARD,
aesbits, key_material[i], klen);
- relays[i] = cgo_crypt_new(CGO_MODE_RELAY,
+ relays[i] = cgo_crypt_new(CGO_MODE_RELAY_FORWARD,
aesbits, key_material[i], klen);
}
for (int trial = 0; trial < 64; ++trial) {
@@ -406,9 +406,9 @@ test_crypto_cgo_rev(void *arg)
tt_uint_op(klen, OP_LE, sizeof(key_material[0]));
crypto_rand((char*)&key_material, sizeof(key_material));
for (int i = 0; i < N_HOPS; ++i) {
- client[i] = cgo_crypt_new(CGO_MODE_CLIENT,
+ client[i] = cgo_crypt_new(CGO_MODE_CLIENT_BACKWARD,
aesbits, key_material[i], klen);
- relays[i] = cgo_crypt_new(CGO_MODE_RELAY,
+ relays[i] = cgo_crypt_new(CGO_MODE_RELAY_BACKWARD,
aesbits, key_material[i], klen);
}
for (int trial = 0; trial < 64; ++trial) {
@@ -477,7 +477,9 @@ test_crypto_cgo_relay_testvec(void *arg)
cell_t expect_cell;
tt_int_op(sizeof(keys), OP_EQ, cgo_key_material_len(aesbits));
UNHEX2(keys, tv->state_in.keys, tv->state_in.nonce);
- cgo = cgo_crypt_new(CGO_MODE_RELAY, aesbits, keys, sizeof(keys));
+ cgo_mode_t mode =
+ tv->inbound ? CGO_MODE_RELAY_BACKWARD : CGO_MODE_RELAY_FORWARD;
+ cgo = cgo_crypt_new(mode, aesbits, keys, sizeof(keys));
tt_assert(cgo);
UNHEX(cgo->tprime, tv->state_in.tprime);
memset(&cell, 0, sizeof(cell));
@@ -528,7 +530,7 @@ test_crypto_cgo_relay_originate_testvec(void *arg)
cell_t expect_cell;
tt_int_op(sizeof(keys), OP_EQ, cgo_key_material_len(aesbits));
UNHEX2(keys, tv->state_in.keys, tv->state_in.nonce);
- cgo = cgo_crypt_new(CGO_MODE_RELAY, aesbits, keys, sizeof(keys));
+ cgo = cgo_crypt_new(CGO_MODE_RELAY_BACKWARD, aesbits, keys, sizeof(keys));
tt_assert(cgo);
UNHEX(cgo->tprime, tv->state_in.tprime);
memset(&cell, 0, sizeof(cell));
@@ -577,7 +579,8 @@ test_crypto_cgo_client_originate_testvec(void *arg)
for (int i = 0; i < 3; ++i) {
tt_int_op(sizeof(keys), OP_EQ, cgo_key_material_len(aesbits));
UNHEX2(keys, tv->state_in[i].keys, tv->state_in[i].nonce);
- cgo[i] = cgo_crypt_new(CGO_MODE_CLIENT, aesbits, keys, sizeof(keys));
+ cgo[i] = cgo_crypt_new(CGO_MODE_CLIENT_FORWARD,
+ aesbits, keys, sizeof(keys));
tt_assert(cgo[i]);
UNHEX(cgo[i]->tprime, tv->state_in[i].tprime);
}