diff options
author | Nick Mathewson <nickm@torproject.org> | 2017-05-08 13:54:59 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2017-05-08 13:54:59 -0400 |
commit | 4d30dde15670bd4fb572025116304286880db636 (patch) | |
tree | 7a368ad50ff8949ff106f03012888f0b9f2a5521 /src/trunnel | |
parent | 35025ee51ff9204271fcfc787a99334082e531a1 (diff) | |
parent | 9f8e462c89a8320f161f5a77661d573d889651cf (diff) | |
download | tor-4d30dde15670bd4fb572025116304286880db636.tar.gz tor-4d30dde15670bd4fb572025116304286880db636.zip |
Merge branch 'netflow_padding-v6-rebased2-squashed'
Diffstat (limited to 'src/trunnel')
-rw-r--r-- | src/trunnel/channelpadding_negotiation.c | 281 | ||||
-rw-r--r-- | src/trunnel/channelpadding_negotiation.h | 98 | ||||
-rw-r--r-- | src/trunnel/channelpadding_negotiation.trunnel | 17 | ||||
-rw-r--r-- | src/trunnel/include.am | 9 |
4 files changed, 402 insertions, 3 deletions
diff --git a/src/trunnel/channelpadding_negotiation.c b/src/trunnel/channelpadding_negotiation.c new file mode 100644 index 0000000000..172d6f8a03 --- /dev/null +++ b/src/trunnel/channelpadding_negotiation.c @@ -0,0 +1,281 @@ +/* channelpadding_negotiation.c -- generated by Trunnel v1.4.3. + * https://gitweb.torproject.org/trunnel.git + * You probably shouldn't edit this file. + */ +#include <stdlib.h> +#include "trunnel-impl.h" + +#include "channelpadding_negotiation.h" + +#define TRUNNEL_SET_ERROR_CODE(obj) \ + do { \ + (obj)->trunnel_error_code_ = 1; \ + } while (0) + +#if defined(__COVERITY__) || defined(__clang_analyzer__) +/* If we're runnning a static analysis tool, we don't want it to complain + * that some of our remaining-bytes checks are dead-code. */ +int channelpaddingnegotiation_deadcode_dummy__ = 0; +#define OR_DEADCODE_DUMMY || channelpaddingnegotiation_deadcode_dummy__ +#else +#define OR_DEADCODE_DUMMY +#endif + +#define CHECK_REMAINING(nbytes, label) \ + do { \ + if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \ + goto label; \ + } \ + } while (0) + +channelpadding_negotiate_t * +channelpadding_negotiate_new(void) +{ + channelpadding_negotiate_t *val = trunnel_calloc(1, sizeof(channelpadding_negotiate_t)); + if (NULL == val) + return NULL; + val->command = CHANNELPADDING_COMMAND_START; + return val; +} + +/** Release all storage held inside 'obj', but do not free 'obj'. + */ +static void +channelpadding_negotiate_clear(channelpadding_negotiate_t *obj) +{ + (void) obj; +} + +void +channelpadding_negotiate_free(channelpadding_negotiate_t *obj) +{ + if (obj == NULL) + return; + channelpadding_negotiate_clear(obj); + trunnel_memwipe(obj, sizeof(channelpadding_negotiate_t)); + trunnel_free_(obj); +} + +uint8_t +channelpadding_negotiate_get_version(channelpadding_negotiate_t *inp) +{ + return inp->version; +} +int +channelpadding_negotiate_set_version(channelpadding_negotiate_t *inp, uint8_t val) +{ + if (! ((val == 0))) { + TRUNNEL_SET_ERROR_CODE(inp); + return -1; + } + inp->version = val; + return 0; +} +uint8_t +channelpadding_negotiate_get_command(channelpadding_negotiate_t *inp) +{ + return inp->command; +} +int +channelpadding_negotiate_set_command(channelpadding_negotiate_t *inp, uint8_t val) +{ + if (! ((val == CHANNELPADDING_COMMAND_START || val == CHANNELPADDING_COMMAND_STOP))) { + TRUNNEL_SET_ERROR_CODE(inp); + return -1; + } + inp->command = val; + return 0; +} +uint16_t +channelpadding_negotiate_get_ito_low_ms(channelpadding_negotiate_t *inp) +{ + return inp->ito_low_ms; +} +int +channelpadding_negotiate_set_ito_low_ms(channelpadding_negotiate_t *inp, uint16_t val) +{ + inp->ito_low_ms = val; + return 0; +} +uint16_t +channelpadding_negotiate_get_ito_high_ms(channelpadding_negotiate_t *inp) +{ + return inp->ito_high_ms; +} +int +channelpadding_negotiate_set_ito_high_ms(channelpadding_negotiate_t *inp, uint16_t val) +{ + inp->ito_high_ms = val; + return 0; +} +const char * +channelpadding_negotiate_check(const channelpadding_negotiate_t *obj) +{ + if (obj == NULL) + return "Object was NULL"; + if (obj->trunnel_error_code_) + return "A set function failed on this object"; + if (! (obj->version == 0)) + return "Integer out of bounds"; + if (! (obj->command == CHANNELPADDING_COMMAND_START || obj->command == CHANNELPADDING_COMMAND_STOP)) + return "Integer out of bounds"; + return NULL; +} + +ssize_t +channelpadding_negotiate_encoded_len(const channelpadding_negotiate_t *obj) +{ + ssize_t result = 0; + + if (NULL != channelpadding_negotiate_check(obj)) + return -1; + + + /* Length of u8 version IN [0] */ + result += 1; + + /* Length of u8 command IN [CHANNELPADDING_COMMAND_START, CHANNELPADDING_COMMAND_STOP] */ + result += 1; + + /* Length of u16 ito_low_ms */ + result += 2; + + /* Length of u16 ito_high_ms */ + result += 2; + return result; +} +int +channelpadding_negotiate_clear_errors(channelpadding_negotiate_t *obj) +{ + int r = obj->trunnel_error_code_; + obj->trunnel_error_code_ = 0; + return r; +} +ssize_t +channelpadding_negotiate_encode(uint8_t *output, const size_t avail, const channelpadding_negotiate_t *obj) +{ + ssize_t result = 0; + size_t written = 0; + uint8_t *ptr = output; + const char *msg; +#ifdef TRUNNEL_CHECK_ENCODED_LEN + const ssize_t encoded_len = channelpadding_negotiate_encoded_len(obj); +#endif + + if (NULL != (msg = channelpadding_negotiate_check(obj))) + goto check_failed; + +#ifdef TRUNNEL_CHECK_ENCODED_LEN + trunnel_assert(encoded_len >= 0); +#endif + + /* Encode u8 version IN [0] */ + trunnel_assert(written <= avail); + if (avail - written < 1) + goto truncated; + trunnel_set_uint8(ptr, (obj->version)); + written += 1; ptr += 1; + + /* Encode u8 command IN [CHANNELPADDING_COMMAND_START, CHANNELPADDING_COMMAND_STOP] */ + trunnel_assert(written <= avail); + if (avail - written < 1) + goto truncated; + trunnel_set_uint8(ptr, (obj->command)); + written += 1; ptr += 1; + + /* Encode u16 ito_low_ms */ + trunnel_assert(written <= avail); + if (avail - written < 2) + goto truncated; + trunnel_set_uint16(ptr, trunnel_htons(obj->ito_low_ms)); + written += 2; ptr += 2; + + /* Encode u16 ito_high_ms */ + trunnel_assert(written <= avail); + if (avail - written < 2) + goto truncated; + trunnel_set_uint16(ptr, trunnel_htons(obj->ito_high_ms)); + written += 2; ptr += 2; + + + trunnel_assert(ptr == output + written); +#ifdef TRUNNEL_CHECK_ENCODED_LEN + { + trunnel_assert(encoded_len >= 0); + trunnel_assert((size_t)encoded_len == written); + } + +#endif + + return written; + + truncated: + result = -2; + goto fail; + check_failed: + (void)msg; + result = -1; + goto fail; + fail: + trunnel_assert(result < 0); + return result; +} + +/** As channelpadding_negotiate_parse(), but do not allocate the + * output object. + */ +static ssize_t +channelpadding_negotiate_parse_into(channelpadding_negotiate_t *obj, const uint8_t *input, const size_t len_in) +{ + const uint8_t *ptr = input; + size_t remaining = len_in; + ssize_t result = 0; + (void)result; + + /* Parse u8 version IN [0] */ + CHECK_REMAINING(1, truncated); + obj->version = (trunnel_get_uint8(ptr)); + remaining -= 1; ptr += 1; + if (! (obj->version == 0)) + goto fail; + + /* Parse u8 command IN [CHANNELPADDING_COMMAND_START, CHANNELPADDING_COMMAND_STOP] */ + CHECK_REMAINING(1, truncated); + obj->command = (trunnel_get_uint8(ptr)); + remaining -= 1; ptr += 1; + if (! (obj->command == CHANNELPADDING_COMMAND_START || obj->command == CHANNELPADDING_COMMAND_STOP)) + goto fail; + + /* Parse u16 ito_low_ms */ + CHECK_REMAINING(2, truncated); + obj->ito_low_ms = trunnel_ntohs(trunnel_get_uint16(ptr)); + remaining -= 2; ptr += 2; + + /* Parse u16 ito_high_ms */ + CHECK_REMAINING(2, truncated); + obj->ito_high_ms = trunnel_ntohs(trunnel_get_uint16(ptr)); + remaining -= 2; ptr += 2; + trunnel_assert(ptr + remaining == input + len_in); + return len_in - remaining; + + truncated: + return -2; + fail: + result = -1; + return result; +} + +ssize_t +channelpadding_negotiate_parse(channelpadding_negotiate_t **output, const uint8_t *input, const size_t len_in) +{ + ssize_t result; + *output = channelpadding_negotiate_new(); + if (NULL == *output) + return -1; + result = channelpadding_negotiate_parse_into(*output, input, len_in); + if (result < 0) { + channelpadding_negotiate_free(*output); + *output = NULL; + } + return result; +} diff --git a/src/trunnel/channelpadding_negotiation.h b/src/trunnel/channelpadding_negotiation.h new file mode 100644 index 0000000000..e58bda3be1 --- /dev/null +++ b/src/trunnel/channelpadding_negotiation.h @@ -0,0 +1,98 @@ +/* channelpadding_negotiation.h -- generated by by Trunnel v1.4.3. + * https://gitweb.torproject.org/trunnel.git + * You probably shouldn't edit this file. + */ +#ifndef TRUNNEL_CHANNELPADDING_NEGOTIATION_H +#define TRUNNEL_CHANNELPADDING_NEGOTIATION_H + +#include <stdint.h> +#include "trunnel.h" + +#define CHANNELPADDING_COMMAND_STOP 1 +#define CHANNELPADDING_COMMAND_START 2 +#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_CHANNELPADDING_NEGOTIATE) +struct channelpadding_negotiate_st { + uint8_t version; + uint8_t command; + uint16_t ito_low_ms; + uint16_t ito_high_ms; + uint8_t trunnel_error_code_; +}; +#endif +typedef struct channelpadding_negotiate_st channelpadding_negotiate_t; +/** Return a newly allocated channelpadding_negotiate with all + * elements set to zero. + */ +channelpadding_negotiate_t *channelpadding_negotiate_new(void); +/** Release all storage held by the channelpadding_negotiate in + * 'victim'. (Do nothing if 'victim' is NULL.) + */ +void channelpadding_negotiate_free(channelpadding_negotiate_t *victim); +/** Try to parse a channelpadding_negotiate from the buffer in + * 'input', using up to 'len_in' bytes from the input buffer. On + * success, return the number of bytes consumed and set *output to the + * newly allocated channelpadding_negotiate_t. On failure, return -2 + * if the input appears truncated, and -1 if the input is otherwise + * invalid. + */ +ssize_t channelpadding_negotiate_parse(channelpadding_negotiate_t **output, const uint8_t *input, const size_t len_in); +/** Return the number of bytes we expect to need to encode the + * channelpadding_negotiate in 'obj'. On failure, return a negative + * value. Note that this value may be an overestimate, and can even be + * an underestimate for certain unencodeable objects. + */ +ssize_t channelpadding_negotiate_encoded_len(const channelpadding_negotiate_t *obj); +/** Try to encode the channelpadding_negotiate from 'input' into the + * buffer at 'output', using up to 'avail' bytes of the output buffer. + * On success, return the number of bytes used. On failure, return -2 + * if the buffer was not long enough, and -1 if the input was invalid. + */ +ssize_t channelpadding_negotiate_encode(uint8_t *output, size_t avail, const channelpadding_negotiate_t *input); +/** Check whether the internal state of the channelpadding_negotiate + * in 'obj' is consistent. Return NULL if it is, and a short message + * if it is not. + */ +const char *channelpadding_negotiate_check(const channelpadding_negotiate_t *obj); +/** Clear any errors that were set on the object 'obj' by its setter + * functions. Return true iff errors were cleared. + */ +int channelpadding_negotiate_clear_errors(channelpadding_negotiate_t *obj); +/** Return the value of the version field of the + * channelpadding_negotiate_t in 'inp' + */ +uint8_t channelpadding_negotiate_get_version(channelpadding_negotiate_t *inp); +/** Set the value of the version field of the + * channelpadding_negotiate_t in 'inp' to 'val'. Return 0 on success; + * return -1 and set the error code on 'inp' on failure. + */ +int channelpadding_negotiate_set_version(channelpadding_negotiate_t *inp, uint8_t val); +/** Return the value of the command field of the + * channelpadding_negotiate_t in 'inp' + */ +uint8_t channelpadding_negotiate_get_command(channelpadding_negotiate_t *inp); +/** Set the value of the command field of the + * channelpadding_negotiate_t in 'inp' to 'val'. Return 0 on success; + * return -1 and set the error code on 'inp' on failure. + */ +int channelpadding_negotiate_set_command(channelpadding_negotiate_t *inp, uint8_t val); +/** Return the value of the ito_low_ms field of the + * channelpadding_negotiate_t in 'inp' + */ +uint16_t channelpadding_negotiate_get_ito_low_ms(channelpadding_negotiate_t *inp); +/** Set the value of the ito_low_ms field of the + * channelpadding_negotiate_t in 'inp' to 'val'. Return 0 on success; + * return -1 and set the error code on 'inp' on failure. + */ +int channelpadding_negotiate_set_ito_low_ms(channelpadding_negotiate_t *inp, uint16_t val); +/** Return the value of the ito_high_ms field of the + * channelpadding_negotiate_t in 'inp' + */ +uint16_t channelpadding_negotiate_get_ito_high_ms(channelpadding_negotiate_t *inp); +/** Set the value of the ito_high_ms field of the + * channelpadding_negotiate_t in 'inp' to 'val'. Return 0 on success; + * return -1 and set the error code on 'inp' on failure. + */ +int channelpadding_negotiate_set_ito_high_ms(channelpadding_negotiate_t *inp, uint16_t val); + + +#endif diff --git a/src/trunnel/channelpadding_negotiation.trunnel b/src/trunnel/channelpadding_negotiation.trunnel new file mode 100644 index 0000000000..7f2d4795b0 --- /dev/null +++ b/src/trunnel/channelpadding_negotiation.trunnel @@ -0,0 +1,17 @@ +const CHANNELPADDING_COMMAND_STOP = 1; +const CHANNELPADDING_COMMAND_START = 2; + +/* This command tells the relay to alter its min and max netflow + timeout range values, and send padding at that rate (resuming + if stopped). */ +struct channelpadding_negotiate { + u8 version IN [0]; + u8 command IN [CHANNELPADDING_COMMAND_START, CHANNELPADDING_COMMAND_STOP]; + + /* Min must not be lower than the current consensus parameter + nf_ito_low. */ + u16 ito_low_ms; + + /* Max must not be lower than ito_low_ms */ + u16 ito_high_ms; +}; diff --git a/src/trunnel/include.am b/src/trunnel/include.am index 9b26d58615..de6cf4781f 100644 --- a/src/trunnel/include.am +++ b/src/trunnel/include.am @@ -11,7 +11,8 @@ AM_CPPFLAGS += -I$(srcdir)/src/ext/trunnel -I$(srcdir)/src/trunnel TRUNNELINPUTS = \ src/trunnel/ed25519_cert.trunnel \ src/trunnel/link_handshake.trunnel \ - src/trunnel/pwbox.trunnel + src/trunnel/pwbox.trunnel \ + src/trunnel/channelpadding_negotiation.trunnel TRUNNELSOURCES = \ src/ext/trunnel/trunnel.c \ @@ -20,7 +21,8 @@ TRUNNELSOURCES = \ src/trunnel/pwbox.c \ src/trunnel/hs/cell_common.c \ src/trunnel/hs/cell_establish_intro.c \ - src/trunnel/hs/cell_introduce1.c + src/trunnel/hs/cell_introduce1.c \ + src/trunnel/channelpadding_negotiation.c TRUNNELHEADERS = \ src/ext/trunnel/trunnel.h \ @@ -31,7 +33,8 @@ TRUNNELHEADERS = \ src/trunnel/pwbox.h \ src/trunnel/hs/cell_common.h \ src/trunnel/hs/cell_establish_intro.h \ - src/trunnel/hs/cell_introduce1.h + src/trunnel/hs/cell_introduce1.h \ + src/trunnel/channelpadding_negotiation.h src_trunnel_libor_trunnel_a_SOURCES = $(TRUNNELSOURCES) src_trunnel_libor_trunnel_a_CPPFLAGS = -DTRUNNEL_LOCAL_H $(AM_CPPFLAGS) |