From: Nick Mathewson Date: Wed, 28 May 2025 16:02:39 +0000 (-0400) Subject: Allow SENDME tags to be 16 or 20 bytes. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fd1720314a4df1e59a53677aab9d03d5d2078d74;p=thirdparty%2Ftor.git Allow SENDME tags to be 16 or 20 bytes. --- diff --git a/src/core/crypto/relay_crypto.c b/src/core/crypto/relay_crypto.c index 9b9f623cc3..baddd704e0 100644 --- a/src/core/crypto/relay_crypto.c +++ b/src/core/crypto/relay_crypto.c @@ -28,7 +28,8 @@ // XXXX: Remove this definition once I'm done refactoring. #define pvt_crypto crypto_crypt_path_private_field -/** Return the sendme_digest within the crypto object. +/** Return the sendme tag within the crypto object, + * along with its length. * * This is the digest from the most recent cell that we originated * or recognized, _in either direction_. @@ -36,9 +37,11 @@ * this digest. */ const uint8_t * -relay_crypto_get_sendme_digest(relay_crypto_t *crypto) +relay_crypto_get_sendme_tag(relay_crypto_t *crypto, + size_t *len_out) { tor_assert(crypto); + *len_out = DIGEST_LEN; return crypto->sendme_digest; } diff --git a/src/core/crypto/relay_crypto.h b/src/core/crypto/relay_crypto.h index 34bf189b73..5340c07338 100644 --- a/src/core/crypto/relay_crypto.h +++ b/src/core/crypto/relay_crypto.h @@ -27,6 +27,7 @@ void relay_crypto_clear(relay_crypto_t *crypto); void relay_crypto_assert_ok(const relay_crypto_t *crypto); -const uint8_t *relay_crypto_get_sendme_digest(relay_crypto_t *crypto); +const uint8_t *relay_crypto_get_sendme_tag(relay_crypto_t *crypto, + size_t *len_out); #endif /* !defined(TOR_RELAY_CRYPTO_H) */ diff --git a/src/core/or/crypt_path.c b/src/core/or/crypt_path.c index 56be7b2311..bf2e4df74e 100644 --- a/src/core/or/crypt_path.c +++ b/src/core/or/crypt_path.c @@ -177,11 +177,12 @@ cpath_free(crypt_path_t *victim) /************ cpath sendme API ***************************/ -/** Return the sendme_digest of this cpath. */ +/** Return the sendme tag of this cpath, + * along with its length. */ const uint8_t * -cpath_get_sendme_digest(crypt_path_t *cpath) +cpath_get_sendme_tag(crypt_path_t *cpath, size_t *len_out) { - return relay_crypto_get_sendme_digest(&cpath->pvt_crypto); + return relay_crypto_get_sendme_tag(&cpath->pvt_crypto, len_out); } /************ other cpath functions ***************************/ diff --git a/src/core/or/crypt_path.h b/src/core/or/crypt_path.h index 2cf36b02b1..36bd2bd81d 100644 --- a/src/core/or/crypt_path.h +++ b/src/core/or/crypt_path.h @@ -25,7 +25,7 @@ crypt_path_t *cpath_get_next_non_open_hop(crypt_path_t *cpath); void cpath_sendme_circuit_record_inbound_cell(crypt_path_t *cpath); -const uint8_t *cpath_get_sendme_digest(crypt_path_t *cpath); +const uint8_t *cpath_get_sendme_tag(crypt_path_t *cpath, size_t *len_out); #if defined(TOR_UNIT_TESTS) unsigned int cpath_get_n_hops(crypt_path_t **head_ptr); diff --git a/src/core/or/sendme.c b/src/core/or/sendme.c index 6128845373..a02f3a5376 100644 --- a/src/core/or/sendme.c +++ b/src/core/or/sendme.c @@ -27,6 +27,18 @@ #include "lib/ctime/di_ops.h" #include "trunnel/sendme_cell.h" +#define SHORT_TAG_LEN 16 +#define LONG_TAG_LEN 20 + +/** + * Return true iff tag_len is some length we recognize. + */ +static inline bool +tag_len_ok(size_t tag_len) +{ + return tag_len == SHORT_TAG_LEN || tag_len == LONG_TAG_LEN; +} + /* Return the minimum version given by the consensus (if any) that should be * used when emitting a SENDME cell. */ STATIC int @@ -71,17 +83,18 @@ pop_first_cell_digest(const circuit_t *circ) return circ_digest; } -/* Return true iff the given cell digest matches the first digest in the +/* Return true iff the given cell tag matches the first digest in the * circuit sendme list. */ static bool -v1_digest_matches(const uint8_t *circ_digest, const uint8_t *cell_digest) +v1_tag_matches(const uint8_t *circ_digest, + const uint8_t *cell_tag, size_t tag_len) { tor_assert(circ_digest); - tor_assert(cell_digest); + tor_assert(cell_tag); /* Compare the digest with the one in the SENDME. This cell is invalid * without a perfect match. */ - if (tor_memneq(circ_digest, cell_digest, TRUNNEL_SENDME_V1_DIGEST_LEN)) { + if (tor_memneq(circ_digest, cell_tag, tag_len)) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "SENDME v1 cell digest do not match."); return false; @@ -103,8 +116,16 @@ cell_v1_is_valid(const sendme_cell_t *cell, const uint8_t *circ_digest) tor_assert(cell); tor_assert(circ_digest); + // XXXX TODO: make sure that length is the length we _expected_. + + size_t tag_len = sendme_cell_get_data_len(cell); + if (! tag_len_ok(tag_len)) + return false; + if (sendme_cell_getlen_data_v1_digest(cell) < tag_len) + return false; + const uint8_t *cell_digest = sendme_cell_getconstarray_data_v1_digest(cell); - return v1_digest_matches(circ_digest, cell_digest); + return v1_tag_matches(circ_digest, cell_digest, tag_len); } /* Return true iff the given cell version can be handled or if the minimum @@ -234,12 +255,14 @@ 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(const uint8_t *cell_digest, uint8_t *payload) +build_cell_payload_v1(const uint8_t *cell_tag, const size_t tag_len, + uint8_t *payload) { ssize_t len = -1; sendme_cell_t *cell = NULL; - tor_assert(cell_digest); + tor_assert(cell_tag); + tor_assert(tag_len_ok(tag_len)); tor_assert(payload); cell = sendme_cell_new(); @@ -247,11 +270,11 @@ build_cell_payload_v1(const uint8_t *cell_digest, uint8_t *payload) /* Building a payload for version 1. */ sendme_cell_set_version(cell, 0x01); /* Set the data length field for v1. */ - sendme_cell_set_data_len(cell, TRUNNEL_SENDME_V1_DIGEST_LEN); + sendme_cell_set_data_len(cell, tag_len); + sendme_cell_setlen_data_v1_digest(cell, tag_len); /* Copy the digest into the data payload. */ - memcpy(sendme_cell_getarray_data_v1_digest(cell), cell_digest, - sendme_cell_get_data_len(cell)); + memcpy(sendme_cell_getarray_data_v1_digest(cell), cell_tag, tag_len); /* Finally, encode the cell into the payload. */ len = sendme_cell_encode(payload, RELAY_PAYLOAD_SIZE_MAX, cell); @@ -267,19 +290,19 @@ build_cell_payload_v1(const uint8_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, - const uint8_t *cell_digest) + const uint8_t *cell_tag, size_t tag_len) { uint8_t emit_version; uint8_t payload[RELAY_PAYLOAD_SIZE_MAX]; ssize_t payload_len; tor_assert(circ); - tor_assert(cell_digest); + tor_assert(cell_tag); emit_version = get_emit_min_version(); switch (emit_version) { case 0x01: - payload_len = build_cell_payload_v1(cell_digest, payload); + payload_len = build_cell_payload_v1(cell_tag, tag_len, payload); if (BUG(payload_len < 0)) { /* Unable to encode the cell, abort. We can recover from this by closing * the circuit but in theory it should never happen. */ @@ -307,19 +330,33 @@ send_circuit_level_sendme(circuit_t *circ, crypt_path_t *layer_hint, return 0; } -/* Record the cell digest only if the next cell is expected to be a SENDME. */ +/* Record the sendme tag as expected in a future SENDME, */ static void -record_cell_digest_on_circ(circuit_t *circ, const uint8_t *sendme_digest) +record_cell_digest_on_circ(circuit_t *circ, + const uint8_t *sendme_tag, + size_t tag_len) { tor_assert(circ); - tor_assert(sendme_digest); + tor_assert(sendme_tag); /* Add the digest to the last seen list in the circuit. */ if (circ->sendme_last_digests == NULL) { circ->sendme_last_digests = smartlist_new(); } - smartlist_add(circ->sendme_last_digests, - tor_memdup(sendme_digest, DIGEST_LEN)); + // We always allocate the largest possible tag here to + // make sure we don't have heap overflow bugs. + uint8_t *tag; + if (tag_len == SHORT_TAG_LEN) { + tag = tor_malloc(sizeof(LONG_TAG_LEN)); + memcpy(tag, sendme_tag, tag_len); + memset(tag+SHORT_TAG_LEN, 0, LONG_TAG_LEN - SHORT_TAG_LEN); + } else if (tag_len == LONG_TAG_LEN) { + tag = tor_memdup(sendme_tag, LONG_TAG_LEN); + } else { + tor_assert_unreached(); + } + + smartlist_add(circ->sendme_last_digests, tag); } /* @@ -421,7 +458,8 @@ void sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint) { bool sent_one_sendme = false; - const uint8_t *digest; + const uint8_t *tag; + size_t tag_len = 0; int sendme_inc = sendme_get_inc_count(circ, layer_hint); while ((layer_hint ? layer_hint->deliver_window : circ->deliver_window) <= @@ -429,12 +467,13 @@ sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint) log_debug(LD_CIRC,"Queuing circuit sendme."); if (layer_hint) { layer_hint->deliver_window += sendme_inc; - digest = cpath_get_sendme_digest(layer_hint); + tag = cpath_get_sendme_tag(layer_hint, &tag_len); } else { circ->deliver_window += sendme_inc; - digest = relay_crypto_get_sendme_digest(&TO_OR_CIRCUIT(circ)->crypto); + tag = relay_crypto_get_sendme_tag(&TO_OR_CIRCUIT(circ)->crypto, + &tag_len); } - if (send_circuit_level_sendme(circ, layer_hint, digest) < 0) { + if (send_circuit_level_sendme(circ, layer_hint, tag, tag_len) < 0) { return; /* The circuit's closed, don't continue */ } /* Current implementation is not suppose to send multiple SENDME at once @@ -698,7 +737,8 @@ sendme_note_stream_data_packaged(edge_connection_t *conn, size_t len) void sendme_record_cell_digest_on_circ(circuit_t *circ, crypt_path_t *cpath) { - const uint8_t *sendme_digest; + const uint8_t *sendme_tag; + size_t tag_len = 0; tor_assert(circ); @@ -712,11 +752,11 @@ sendme_record_cell_digest_on_circ(circuit_t *circ, crypt_path_t *cpath) /* Getting the digest is expensive so we only do it once we are certain to * record it on the circuit. */ if (cpath) { - sendme_digest = cpath_get_sendme_digest(cpath); + sendme_tag = cpath_get_sendme_tag(cpath, &tag_len); } else { - sendme_digest = - relay_crypto_get_sendme_digest(&TO_OR_CIRCUIT(circ)->crypto); + sendme_tag = + relay_crypto_get_sendme_tag(&TO_OR_CIRCUIT(circ)->crypto, &tag_len); } - record_cell_digest_on_circ(circ, sendme_digest); + record_cell_digest_on_circ(circ, sendme_tag, tag_len); } diff --git a/src/core/or/sendme.h b/src/core/or/sendme.h index 8bb293471b..c21726f5c8 100644 --- a/src/core/or/sendme.h +++ b/src/core/or/sendme.h @@ -65,7 +65,8 @@ STATIC int get_accept_min_version(void); STATIC bool cell_version_can_be_handled(uint8_t cell_version); -STATIC ssize_t build_cell_payload_v1(const uint8_t *cell_digest, +STATIC ssize_t build_cell_payload_v1(const uint8_t *cell_tag, + size_t tag_len, uint8_t *payload); STATIC bool sendme_is_valid(const circuit_t *circ, const uint8_t *cell_payload, diff --git a/src/test/test_crypto_cgo.c b/src/test/test_crypto_cgo.c index 403dcaa98b..5aea89e984 100644 --- a/src/test/test_crypto_cgo.c +++ b/src/test/test_crypto_cgo.c @@ -255,6 +255,8 @@ test_crypto_cgo_uiv_testvec(void *arg) cgo_uiv_clear(&uiv); } +#include "core/or/relay_crypto_st.h" + static void test_crypto_cgo_uiv_update_testvec(void *arg) { diff --git a/src/test/test_sendme.c b/src/test/test_sendme.c index 93a828643b..ff24ec96c6 100644 --- a/src/test/test_sendme.c +++ b/src/test/test_sendme.c @@ -153,7 +153,7 @@ test_v1_build_cell(void *arg) smartlist_add(circ->sendme_last_digests, tor_memdup(digest, sizeof(digest))); /* SENDME v1 payload is 3 bytes + 20 bytes digest. See spec. */ - ret = build_cell_payload_v1(digest, payload); + ret = build_cell_payload_v1(digest, 20, payload); tt_int_op(ret, OP_EQ, 23); /* Validation. */ diff --git a/src/trunnel/sendme_cell.c b/src/trunnel/sendme_cell.c index b9f8fe967f..0b51a133b0 100644 --- a/src/trunnel/sendme_cell.c +++ b/src/trunnel/sendme_cell.c @@ -34,6 +34,7 @@ sendme_cell_new(void) sendme_cell_t *val = trunnel_calloc(1, sizeof(sendme_cell_t)); if (NULL == val) return NULL; + val->data_len = 16; return val; } @@ -43,6 +44,8 @@ static void sendme_cell_clear(sendme_cell_t *obj) { (void) obj; + TRUNNEL_DYNARRAY_WIPE(&obj->data_v1_digest); + TRUNNEL_DYNARRAY_CLEAR(&obj->data_v1_digest); } void @@ -78,20 +81,23 @@ sendme_cell_get_data_len(const sendme_cell_t *inp) int sendme_cell_set_data_len(sendme_cell_t *inp, uint16_t val) { + if (! ((val == 16 || val == 20))) { + TRUNNEL_SET_ERROR_CODE(inp); + return -1; + } inp->data_len = val; return 0; } size_t sendme_cell_getlen_data_v1_digest(const sendme_cell_t *inp) { - (void)inp; return TRUNNEL_SENDME_V1_DIGEST_LEN; + return TRUNNEL_DYNARRAY_LEN(&inp->data_v1_digest); } uint8_t sendme_cell_get_data_v1_digest(sendme_cell_t *inp, size_t idx) { - trunnel_assert(idx < TRUNNEL_SENDME_V1_DIGEST_LEN); - return inp->data_v1_digest[idx]; + return TRUNNEL_DYNARRAY_GET(&inp->data_v1_digest, idx); } uint8_t @@ -102,21 +108,45 @@ sendme_cell_getconst_data_v1_digest(const sendme_cell_t *inp, size_t idx) int sendme_cell_set_data_v1_digest(sendme_cell_t *inp, size_t idx, uint8_t elt) { - trunnel_assert(idx < TRUNNEL_SENDME_V1_DIGEST_LEN); - inp->data_v1_digest[idx] = elt; + TRUNNEL_DYNARRAY_SET(&inp->data_v1_digest, idx, elt); + return 0; +} +int +sendme_cell_add_data_v1_digest(sendme_cell_t *inp, uint8_t elt) +{ + TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->data_v1_digest, elt, {}); return 0; + trunnel_alloc_failed: + TRUNNEL_SET_ERROR_CODE(inp); + return -1; } uint8_t * sendme_cell_getarray_data_v1_digest(sendme_cell_t *inp) { - return inp->data_v1_digest; + return inp->data_v1_digest.elts_; } const uint8_t * sendme_cell_getconstarray_data_v1_digest(const sendme_cell_t *inp) { return (const uint8_t *)sendme_cell_getarray_data_v1_digest((sendme_cell_t*)inp); } +int +sendme_cell_setlen_data_v1_digest(sendme_cell_t *inp, size_t newlen) +{ + uint8_t *newptr; + newptr = trunnel_dynarray_setlen(&inp->data_v1_digest.allocated_, + &inp->data_v1_digest.n_, inp->data_v1_digest.elts_, newlen, + sizeof(inp->data_v1_digest.elts_[0]), (trunnel_free_fn_t) NULL, + &inp->trunnel_error_code_); + if (newlen != 0 && newptr == NULL) + goto trunnel_alloc_failed; + inp->data_v1_digest.elts_ = newptr; + return 0; + trunnel_alloc_failed: + TRUNNEL_SET_ERROR_CODE(inp); + return -1; +} const char * sendme_cell_check(const sendme_cell_t *obj) { @@ -126,6 +156,8 @@ sendme_cell_check(const sendme_cell_t *obj) return "A set function failed on this object"; if (! (obj->version == 0 || obj->version == 1)) return "Integer out of bounds"; + if (! (obj->data_len == 16 || obj->data_len == 20)) + return "Integer out of bounds"; switch (obj->version) { case 0: @@ -153,7 +185,7 @@ sendme_cell_encoded_len(const sendme_cell_t *obj) /* Length of u8 version IN [0, 1] */ result += 1; - /* Length of u16 data_len */ + /* Length of u16 data_len IN [16, 20] */ result += 2; switch (obj->version) { @@ -162,8 +194,8 @@ sendme_cell_encoded_len(const sendme_cell_t *obj) case 1: - /* Length of u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */ - result += TRUNNEL_SENDME_V1_DIGEST_LEN; + /* Length of u8 data_v1_digest[] */ + result += TRUNNEL_DYNARRAY_LEN(&obj->data_v1_digest); break; default: @@ -206,7 +238,7 @@ sendme_cell_encode(uint8_t *output, const size_t avail, const sendme_cell_t *obj trunnel_set_uint8(ptr, (obj->version)); written += 1; ptr += 1; - /* Encode u16 data_len */ + /* Encode u16 data_len IN [16, 20] */ backptr_data_len = ptr; trunnel_assert(written <= avail); if (avail - written < 2) @@ -225,12 +257,16 @@ sendme_cell_encode(uint8_t *output, const size_t avail, const sendme_cell_t *obj case 1: - /* Encode u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */ - trunnel_assert(written <= avail); - if (avail - written < TRUNNEL_SENDME_V1_DIGEST_LEN) - goto truncated; - memcpy(ptr, obj->data_v1_digest, TRUNNEL_SENDME_V1_DIGEST_LEN); - written += TRUNNEL_SENDME_V1_DIGEST_LEN; ptr += TRUNNEL_SENDME_V1_DIGEST_LEN; + /* Encode u8 data_v1_digest[] */ + { + size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->data_v1_digest); + trunnel_assert(written <= avail); + if (avail - written < elt_len) + goto truncated; + if (elt_len) + memcpy(ptr, obj->data_v1_digest.elts_, elt_len); + written += elt_len; ptr += elt_len; + } break; default: @@ -287,10 +323,12 @@ sendme_cell_parse_into(sendme_cell_t *obj, const uint8_t *input, const size_t le if (! (obj->version == 0 || obj->version == 1)) goto fail; - /* Parse u16 data_len */ + /* Parse u16 data_len IN [16, 20] */ CHECK_REMAINING(2, truncated); obj->data_len = trunnel_ntohs(trunnel_get_uint16(ptr)); remaining -= 2; ptr += 2; + if (! (obj->data_len == 16 || obj->data_len == 20)) + goto fail; { size_t remaining_after; CHECK_REMAINING(obj->data_len, truncated); @@ -307,10 +345,12 @@ sendme_cell_parse_into(sendme_cell_t *obj, const uint8_t *input, const size_t le case 1: - /* Parse u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */ - CHECK_REMAINING(TRUNNEL_SENDME_V1_DIGEST_LEN, fail); - memcpy(obj->data_v1_digest, ptr, TRUNNEL_SENDME_V1_DIGEST_LEN); - remaining -= TRUNNEL_SENDME_V1_DIGEST_LEN; ptr += TRUNNEL_SENDME_V1_DIGEST_LEN; + /* Parse u8 data_v1_digest[] */ + TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->data_v1_digest, remaining, {}); + obj->data_v1_digest.n_ = remaining; + if (remaining) + memcpy(obj->data_v1_digest.elts_, ptr, remaining); + ptr += remaining; remaining -= remaining; break; default: @@ -326,6 +366,8 @@ sendme_cell_parse_into(sendme_cell_t *obj, const uint8_t *input, const size_t le truncated: return -2; + trunnel_alloc_failed: + return -1; fail: result = -1; return result; diff --git a/src/trunnel/sendme_cell.h b/src/trunnel/sendme_cell.h index 45efb9f10d..3d642d279d 100644 --- a/src/trunnel/sendme_cell.h +++ b/src/trunnel/sendme_cell.h @@ -8,12 +8,11 @@ #include #include "trunnel.h" -#define TRUNNEL_SENDME_V1_DIGEST_LEN 20 #if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_SENDME_CELL) struct sendme_cell_st { uint8_t version; uint16_t data_len; - uint8_t data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN]; + TRUNNEL_DYNARRAY_HEAD(, uint8_t) data_v1_digest; uint8_t trunnel_error_code_; }; #endif @@ -71,11 +70,11 @@ uint16_t sendme_cell_get_data_len(const sendme_cell_t *inp); * 'inp' on failure. */ int sendme_cell_set_data_len(sendme_cell_t *inp, uint16_t val); -/** Return the (constant) length of the array holding the - * data_v1_digest field of the sendme_cell_t in 'inp'. +/** Return the length of the dynamic array holding the data_v1_digest + * field of the sendme_cell_t in 'inp'. */ size_t sendme_cell_getlen_data_v1_digest(const sendme_cell_t *inp); -/** Return the element at position 'idx' of the fixed array field +/** Return the element at position 'idx' of the dynamic array field * data_v1_digest of the sendme_cell_t in 'inp'. */ uint8_t sendme_cell_get_data_v1_digest(sendme_cell_t *inp, size_t idx); @@ -83,19 +82,29 @@ uint8_t sendme_cell_get_data_v1_digest(sendme_cell_t *inp, size_t idx); * pointer */ uint8_t sendme_cell_getconst_data_v1_digest(const sendme_cell_t *inp, size_t idx); -/** Change the element at position 'idx' of the fixed array field +/** Change the element at position 'idx' of the dynamic array field * data_v1_digest of the sendme_cell_t in 'inp', so that it will hold * the value 'elt'. */ int sendme_cell_set_data_v1_digest(sendme_cell_t *inp, size_t idx, uint8_t elt); -/** Return a pointer to the TRUNNEL_SENDME_V1_DIGEST_LEN-element array - * field data_v1_digest of 'inp'. +/** Append a new element 'elt' to the dynamic array field + * data_v1_digest of the sendme_cell_t in 'inp'. + */ +int sendme_cell_add_data_v1_digest(sendme_cell_t *inp, uint8_t elt); +/** Return a pointer to the variable-length array field data_v1_digest + * of 'inp'. */ uint8_t * sendme_cell_getarray_data_v1_digest(sendme_cell_t *inp); /** As sendme_cell_get_data_v1_digest, but take and return a const * pointer */ const uint8_t * sendme_cell_getconstarray_data_v1_digest(const sendme_cell_t *inp); +/** Change the length of the variable-length array field + * data_v1_digest of 'inp' to 'newlen'.Fill extra elements with 0. + * Return 0 on success; return -1 and set the error code on 'inp' on + * failure. + */ +int sendme_cell_setlen_data_v1_digest(sendme_cell_t *inp, size_t newlen); #endif diff --git a/src/trunnel/sendme_cell.trunnel b/src/trunnel/sendme_cell.trunnel index 300963e679..f3ff26cb5a 100644 --- a/src/trunnel/sendme_cell.trunnel +++ b/src/trunnel/sendme_cell.trunnel @@ -1,19 +1,19 @@ /* This file contains the SENDME cell definition. */ -/* v1 digest length in bytes. */ -const TRUNNEL_SENDME_V1_DIGEST_LEN = 20; - /* SENDME cell declaration. */ struct sendme_cell { /* Version field. */ u8 version IN [0x00, 0x01]; /* Length of data contained in this cell. */ - u16 data_len; + u16 data_len IN [16, 20]; /* The data content depends on the version. */ union data[version] with length data_len { 0x00: ignore; - 0x01: u8 v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN]; + /* I'd like to use data_len here, but trunnel doesn't + * allow that. Instead have v1_digest run to the end of the cell. + */ + 0x01: u8 v1_digest[]; }; }