tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

cell_establish_intro.c (32697B)


      1 /* cell_establish_intro.c -- generated by Trunnel v1.5.3.
      2 * https://gitweb.torproject.org/trunnel.git
      3 * You probably shouldn't edit this file.
      4 */
      5 #include <stdlib.h>
      6 #include "trunnel-impl.h"
      7 
      8 #include "cell_establish_intro.h"
      9 
     10 #define TRUNNEL_SET_ERROR_CODE(obj) \
     11  do {                              \
     12    (obj)->trunnel_error_code_ = 1; \
     13  } while (0)
     14 
     15 #if defined(__COVERITY__) || defined(__clang_analyzer__)
     16 /* If we're running a static analysis tool, we don't want it to complain
     17 * that some of our remaining-bytes checks are dead-code. */
     18 int cellestablishintro_deadcode_dummy__ = 0;
     19 #define OR_DEADCODE_DUMMY || cellestablishintro_deadcode_dummy__
     20 #else
     21 #define OR_DEADCODE_DUMMY
     22 #endif
     23 
     24 #define CHECK_REMAINING(nbytes, label)                           \
     25  do {                                                           \
     26    if (remaining < (nbytes) OR_DEADCODE_DUMMY) {                \
     27      goto label;                                                \
     28    }                                                            \
     29  } while (0)
     30 
     31 typedef struct trn_extension_st trn_extension_t;
     32 trn_extension_t *trn_extension_new(void);
     33 void trn_extension_free(trn_extension_t *victim);
     34 ssize_t trn_extension_parse(trn_extension_t **output, const uint8_t *input, const size_t len_in);
     35 ssize_t trn_extension_encoded_len(const trn_extension_t *obj);
     36 ssize_t trn_extension_encode(uint8_t *output, size_t avail, const trn_extension_t *input);
     37 const char *trn_extension_check(const trn_extension_t *obj);
     38 int trn_extension_clear_errors(trn_extension_t *obj);
     39 trn_cell_extension_dos_param_t *
     40 trn_cell_extension_dos_param_new(void)
     41 {
     42  trn_cell_extension_dos_param_t *val = trunnel_calloc(1, sizeof(trn_cell_extension_dos_param_t));
     43  if (NULL == val)
     44    return NULL;
     45  return val;
     46 }
     47 
     48 /** Release all storage held inside 'obj', but do not free 'obj'.
     49 */
     50 static void
     51 trn_cell_extension_dos_param_clear(trn_cell_extension_dos_param_t *obj)
     52 {
     53  (void) obj;
     54 }
     55 
     56 void
     57 trn_cell_extension_dos_param_free(trn_cell_extension_dos_param_t *obj)
     58 {
     59  if (obj == NULL)
     60    return;
     61  trn_cell_extension_dos_param_clear(obj);
     62  trunnel_memwipe(obj, sizeof(trn_cell_extension_dos_param_t));
     63  trunnel_free_(obj);
     64 }
     65 
     66 uint8_t
     67 trn_cell_extension_dos_param_get_type(const trn_cell_extension_dos_param_t *inp)
     68 {
     69  return inp->type;
     70 }
     71 int
     72 trn_cell_extension_dos_param_set_type(trn_cell_extension_dos_param_t *inp, uint8_t val)
     73 {
     74  inp->type = val;
     75  return 0;
     76 }
     77 uint64_t
     78 trn_cell_extension_dos_param_get_value(const trn_cell_extension_dos_param_t *inp)
     79 {
     80  return inp->value;
     81 }
     82 int
     83 trn_cell_extension_dos_param_set_value(trn_cell_extension_dos_param_t *inp, uint64_t val)
     84 {
     85  inp->value = val;
     86  return 0;
     87 }
     88 const char *
     89 trn_cell_extension_dos_param_check(const trn_cell_extension_dos_param_t *obj)
     90 {
     91  if (obj == NULL)
     92    return "Object was NULL";
     93  if (obj->trunnel_error_code_)
     94    return "A set function failed on this object";
     95  return NULL;
     96 }
     97 
     98 ssize_t
     99 trn_cell_extension_dos_param_encoded_len(const trn_cell_extension_dos_param_t *obj)
    100 {
    101  ssize_t result = 0;
    102 
    103  if (NULL != trn_cell_extension_dos_param_check(obj))
    104     return -1;
    105 
    106 
    107  /* Length of u8 type */
    108  result += 1;
    109 
    110  /* Length of u64 value */
    111  result += 8;
    112  return result;
    113 }
    114 int
    115 trn_cell_extension_dos_param_clear_errors(trn_cell_extension_dos_param_t *obj)
    116 {
    117  int r = obj->trunnel_error_code_;
    118  obj->trunnel_error_code_ = 0;
    119  return r;
    120 }
    121 ssize_t
    122 trn_cell_extension_dos_param_encode(uint8_t *output, const size_t avail, const trn_cell_extension_dos_param_t *obj)
    123 {
    124  ssize_t result = 0;
    125  size_t written = 0;
    126  uint8_t *ptr = output;
    127  const char *msg;
    128 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    129  const ssize_t encoded_len = trn_cell_extension_dos_param_encoded_len(obj);
    130 #endif
    131 
    132  if (NULL != (msg = trn_cell_extension_dos_param_check(obj)))
    133    goto check_failed;
    134 
    135 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    136  trunnel_assert(encoded_len >= 0);
    137 #endif
    138 
    139  /* Encode u8 type */
    140  trunnel_assert(written <= avail);
    141  if (avail - written < 1)
    142    goto truncated;
    143  trunnel_set_uint8(ptr, (obj->type));
    144  written += 1; ptr += 1;
    145 
    146  /* Encode u64 value */
    147  trunnel_assert(written <= avail);
    148  if (avail - written < 8)
    149    goto truncated;
    150  trunnel_set_uint64(ptr, trunnel_htonll(obj->value));
    151  written += 8; ptr += 8;
    152 
    153 
    154  trunnel_assert(ptr == output + written);
    155 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    156  {
    157    trunnel_assert(encoded_len >= 0);
    158    trunnel_assert((size_t)encoded_len == written);
    159  }
    160 
    161 #endif
    162 
    163  return written;
    164 
    165 truncated:
    166  result = -2;
    167  goto fail;
    168 check_failed:
    169  (void)msg;
    170  result = -1;
    171  goto fail;
    172 fail:
    173  trunnel_assert(result < 0);
    174  return result;
    175 }
    176 
    177 /** As trn_cell_extension_dos_param_parse(), but do not allocate the
    178 * output object.
    179 */
    180 static ssize_t
    181 trn_cell_extension_dos_param_parse_into(trn_cell_extension_dos_param_t *obj, const uint8_t *input, const size_t len_in)
    182 {
    183  const uint8_t *ptr = input;
    184  size_t remaining = len_in;
    185  ssize_t result = 0;
    186  (void)result;
    187 
    188  /* Parse u8 type */
    189  CHECK_REMAINING(1, truncated);
    190  obj->type = (trunnel_get_uint8(ptr));
    191  remaining -= 1; ptr += 1;
    192 
    193  /* Parse u64 value */
    194  CHECK_REMAINING(8, truncated);
    195  obj->value = trunnel_ntohll(trunnel_get_uint64(ptr));
    196  remaining -= 8; ptr += 8;
    197  trunnel_assert(ptr + remaining == input + len_in);
    198  return len_in - remaining;
    199 
    200 truncated:
    201  return -2;
    202 }
    203 
    204 ssize_t
    205 trn_cell_extension_dos_param_parse(trn_cell_extension_dos_param_t **output, const uint8_t *input, const size_t len_in)
    206 {
    207  ssize_t result;
    208  *output = trn_cell_extension_dos_param_new();
    209  if (NULL == *output)
    210    return -1;
    211  result = trn_cell_extension_dos_param_parse_into(*output, input, len_in);
    212  if (result < 0) {
    213    trn_cell_extension_dos_param_free(*output);
    214    *output = NULL;
    215  }
    216  return result;
    217 }
    218 trn_cell_establish_intro_t *
    219 trn_cell_establish_intro_new(void)
    220 {
    221  trn_cell_establish_intro_t *val = trunnel_calloc(1, sizeof(trn_cell_establish_intro_t));
    222  if (NULL == val)
    223    return NULL;
    224  return val;
    225 }
    226 
    227 /** Release all storage held inside 'obj', but do not free 'obj'.
    228 */
    229 static void
    230 trn_cell_establish_intro_clear(trn_cell_establish_intro_t *obj)
    231 {
    232  (void) obj;
    233  TRUNNEL_DYNARRAY_WIPE(&obj->auth_key);
    234  TRUNNEL_DYNARRAY_CLEAR(&obj->auth_key);
    235  trn_extension_free(obj->extensions);
    236  obj->extensions = NULL;
    237  TRUNNEL_DYNARRAY_WIPE(&obj->sig);
    238  TRUNNEL_DYNARRAY_CLEAR(&obj->sig);
    239 }
    240 
    241 void
    242 trn_cell_establish_intro_free(trn_cell_establish_intro_t *obj)
    243 {
    244  if (obj == NULL)
    245    return;
    246  trn_cell_establish_intro_clear(obj);
    247  trunnel_memwipe(obj, sizeof(trn_cell_establish_intro_t));
    248  trunnel_free_(obj);
    249 }
    250 
    251 const uint8_t *
    252 trn_cell_establish_intro_get_start_cell(const trn_cell_establish_intro_t *inp)
    253 {
    254  return inp->start_cell;
    255 }
    256 uint8_t
    257 trn_cell_establish_intro_get_auth_key_type(const trn_cell_establish_intro_t *inp)
    258 {
    259  return inp->auth_key_type;
    260 }
    261 int
    262 trn_cell_establish_intro_set_auth_key_type(trn_cell_establish_intro_t *inp, uint8_t val)
    263 {
    264  if (! ((val == 0 || val == 1 || val == 2))) {
    265     TRUNNEL_SET_ERROR_CODE(inp);
    266     return -1;
    267  }
    268  inp->auth_key_type = val;
    269  return 0;
    270 }
    271 uint16_t
    272 trn_cell_establish_intro_get_auth_key_len(const trn_cell_establish_intro_t *inp)
    273 {
    274  return inp->auth_key_len;
    275 }
    276 int
    277 trn_cell_establish_intro_set_auth_key_len(trn_cell_establish_intro_t *inp, uint16_t val)
    278 {
    279  inp->auth_key_len = val;
    280  return 0;
    281 }
    282 size_t
    283 trn_cell_establish_intro_getlen_auth_key(const trn_cell_establish_intro_t *inp)
    284 {
    285  return TRUNNEL_DYNARRAY_LEN(&inp->auth_key);
    286 }
    287 
    288 uint8_t
    289 trn_cell_establish_intro_get_auth_key(trn_cell_establish_intro_t *inp, size_t idx)
    290 {
    291  return TRUNNEL_DYNARRAY_GET(&inp->auth_key, idx);
    292 }
    293 
    294 uint8_t
    295 trn_cell_establish_intro_getconst_auth_key(const trn_cell_establish_intro_t *inp, size_t idx)
    296 {
    297  return trn_cell_establish_intro_get_auth_key((trn_cell_establish_intro_t*)inp, idx);
    298 }
    299 int
    300 trn_cell_establish_intro_set_auth_key(trn_cell_establish_intro_t *inp, size_t idx, uint8_t elt)
    301 {
    302  TRUNNEL_DYNARRAY_SET(&inp->auth_key, idx, elt);
    303  return 0;
    304 }
    305 int
    306 trn_cell_establish_intro_add_auth_key(trn_cell_establish_intro_t *inp, uint8_t elt)
    307 {
    308 #if SIZE_MAX >= UINT16_MAX
    309  if (inp->auth_key.n_ == UINT16_MAX)
    310    goto trunnel_alloc_failed;
    311 #endif
    312  TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->auth_key, elt, {});
    313  return 0;
    314 trunnel_alloc_failed:
    315  TRUNNEL_SET_ERROR_CODE(inp);
    316  return -1;
    317 }
    318 
    319 uint8_t *
    320 trn_cell_establish_intro_getarray_auth_key(trn_cell_establish_intro_t *inp)
    321 {
    322  return inp->auth_key.elts_;
    323 }
    324 const uint8_t  *
    325 trn_cell_establish_intro_getconstarray_auth_key(const trn_cell_establish_intro_t *inp)
    326 {
    327  return (const uint8_t  *)trn_cell_establish_intro_getarray_auth_key((trn_cell_establish_intro_t*)inp);
    328 }
    329 int
    330 trn_cell_establish_intro_setlen_auth_key(trn_cell_establish_intro_t *inp, size_t newlen)
    331 {
    332  uint8_t *newptr;
    333 #if UINT16_MAX < SIZE_MAX
    334  if (newlen > UINT16_MAX)
    335    goto trunnel_alloc_failed;
    336 #endif
    337  newptr = trunnel_dynarray_setlen(&inp->auth_key.allocated_,
    338                 &inp->auth_key.n_, inp->auth_key.elts_, newlen,
    339                 sizeof(inp->auth_key.elts_[0]), (trunnel_free_fn_t) NULL,
    340                 &inp->trunnel_error_code_);
    341  if (newlen != 0 && newptr == NULL)
    342    goto trunnel_alloc_failed;
    343  inp->auth_key.elts_ = newptr;
    344  return 0;
    345 trunnel_alloc_failed:
    346  TRUNNEL_SET_ERROR_CODE(inp);
    347  return -1;
    348 }
    349 struct trn_extension_st *
    350 trn_cell_establish_intro_get_extensions(trn_cell_establish_intro_t *inp)
    351 {
    352  return inp->extensions;
    353 }
    354 const struct trn_extension_st *
    355 trn_cell_establish_intro_getconst_extensions(const trn_cell_establish_intro_t *inp)
    356 {
    357  return trn_cell_establish_intro_get_extensions((trn_cell_establish_intro_t*) inp);
    358 }
    359 int
    360 trn_cell_establish_intro_set_extensions(trn_cell_establish_intro_t *inp, struct trn_extension_st *val)
    361 {
    362  if (inp->extensions && inp->extensions != val)
    363    trn_extension_free(inp->extensions);
    364  return trn_cell_establish_intro_set0_extensions(inp, val);
    365 }
    366 int
    367 trn_cell_establish_intro_set0_extensions(trn_cell_establish_intro_t *inp, struct trn_extension_st *val)
    368 {
    369  inp->extensions = val;
    370  return 0;
    371 }
    372 const uint8_t *
    373 trn_cell_establish_intro_get_end_mac_fields(const trn_cell_establish_intro_t *inp)
    374 {
    375  return inp->end_mac_fields;
    376 }
    377 size_t
    378 trn_cell_establish_intro_getlen_handshake_mac(const trn_cell_establish_intro_t *inp)
    379 {
    380  (void)inp;  return TRUNNEL_SHA3_256_LEN;
    381 }
    382 
    383 uint8_t
    384 trn_cell_establish_intro_get_handshake_mac(trn_cell_establish_intro_t *inp, size_t idx)
    385 {
    386  trunnel_assert(idx < TRUNNEL_SHA3_256_LEN);
    387  return inp->handshake_mac[idx];
    388 }
    389 
    390 uint8_t
    391 trn_cell_establish_intro_getconst_handshake_mac(const trn_cell_establish_intro_t *inp, size_t idx)
    392 {
    393  return trn_cell_establish_intro_get_handshake_mac((trn_cell_establish_intro_t*)inp, idx);
    394 }
    395 int
    396 trn_cell_establish_intro_set_handshake_mac(trn_cell_establish_intro_t *inp, size_t idx, uint8_t elt)
    397 {
    398  trunnel_assert(idx < TRUNNEL_SHA3_256_LEN);
    399  inp->handshake_mac[idx] = elt;
    400  return 0;
    401 }
    402 
    403 uint8_t *
    404 trn_cell_establish_intro_getarray_handshake_mac(trn_cell_establish_intro_t *inp)
    405 {
    406  return inp->handshake_mac;
    407 }
    408 const uint8_t  *
    409 trn_cell_establish_intro_getconstarray_handshake_mac(const trn_cell_establish_intro_t *inp)
    410 {
    411  return (const uint8_t  *)trn_cell_establish_intro_getarray_handshake_mac((trn_cell_establish_intro_t*)inp);
    412 }
    413 const uint8_t *
    414 trn_cell_establish_intro_get_end_sig_fields(const trn_cell_establish_intro_t *inp)
    415 {
    416  return inp->end_sig_fields;
    417 }
    418 uint16_t
    419 trn_cell_establish_intro_get_sig_len(const trn_cell_establish_intro_t *inp)
    420 {
    421  return inp->sig_len;
    422 }
    423 int
    424 trn_cell_establish_intro_set_sig_len(trn_cell_establish_intro_t *inp, uint16_t val)
    425 {
    426  inp->sig_len = val;
    427  return 0;
    428 }
    429 size_t
    430 trn_cell_establish_intro_getlen_sig(const trn_cell_establish_intro_t *inp)
    431 {
    432  return TRUNNEL_DYNARRAY_LEN(&inp->sig);
    433 }
    434 
    435 uint8_t
    436 trn_cell_establish_intro_get_sig(trn_cell_establish_intro_t *inp, size_t idx)
    437 {
    438  return TRUNNEL_DYNARRAY_GET(&inp->sig, idx);
    439 }
    440 
    441 uint8_t
    442 trn_cell_establish_intro_getconst_sig(const trn_cell_establish_intro_t *inp, size_t idx)
    443 {
    444  return trn_cell_establish_intro_get_sig((trn_cell_establish_intro_t*)inp, idx);
    445 }
    446 int
    447 trn_cell_establish_intro_set_sig(trn_cell_establish_intro_t *inp, size_t idx, uint8_t elt)
    448 {
    449  TRUNNEL_DYNARRAY_SET(&inp->sig, idx, elt);
    450  return 0;
    451 }
    452 int
    453 trn_cell_establish_intro_add_sig(trn_cell_establish_intro_t *inp, uint8_t elt)
    454 {
    455 #if SIZE_MAX >= UINT16_MAX
    456  if (inp->sig.n_ == UINT16_MAX)
    457    goto trunnel_alloc_failed;
    458 #endif
    459  TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->sig, elt, {});
    460  return 0;
    461 trunnel_alloc_failed:
    462  TRUNNEL_SET_ERROR_CODE(inp);
    463  return -1;
    464 }
    465 
    466 uint8_t *
    467 trn_cell_establish_intro_getarray_sig(trn_cell_establish_intro_t *inp)
    468 {
    469  return inp->sig.elts_;
    470 }
    471 const uint8_t  *
    472 trn_cell_establish_intro_getconstarray_sig(const trn_cell_establish_intro_t *inp)
    473 {
    474  return (const uint8_t  *)trn_cell_establish_intro_getarray_sig((trn_cell_establish_intro_t*)inp);
    475 }
    476 int
    477 trn_cell_establish_intro_setlen_sig(trn_cell_establish_intro_t *inp, size_t newlen)
    478 {
    479  uint8_t *newptr;
    480 #if UINT16_MAX < SIZE_MAX
    481  if (newlen > UINT16_MAX)
    482    goto trunnel_alloc_failed;
    483 #endif
    484  newptr = trunnel_dynarray_setlen(&inp->sig.allocated_,
    485                 &inp->sig.n_, inp->sig.elts_, newlen,
    486                 sizeof(inp->sig.elts_[0]), (trunnel_free_fn_t) NULL,
    487                 &inp->trunnel_error_code_);
    488  if (newlen != 0 && newptr == NULL)
    489    goto trunnel_alloc_failed;
    490  inp->sig.elts_ = newptr;
    491  return 0;
    492 trunnel_alloc_failed:
    493  TRUNNEL_SET_ERROR_CODE(inp);
    494  return -1;
    495 }
    496 const char *
    497 trn_cell_establish_intro_check(const trn_cell_establish_intro_t *obj)
    498 {
    499  if (obj == NULL)
    500    return "Object was NULL";
    501  if (obj->trunnel_error_code_)
    502    return "A set function failed on this object";
    503  if (! (obj->auth_key_type == 0 || obj->auth_key_type == 1 || obj->auth_key_type == 2))
    504    return "Integer out of bounds";
    505  if (TRUNNEL_DYNARRAY_LEN(&obj->auth_key) != obj->auth_key_len)
    506    return "Length mismatch for auth_key";
    507  {
    508    const char *msg;
    509    if (NULL != (msg = trn_extension_check(obj->extensions)))
    510      return msg;
    511  }
    512  if (TRUNNEL_DYNARRAY_LEN(&obj->sig) != obj->sig_len)
    513    return "Length mismatch for sig";
    514  return NULL;
    515 }
    516 
    517 ssize_t
    518 trn_cell_establish_intro_encoded_len(const trn_cell_establish_intro_t *obj)
    519 {
    520  ssize_t result = 0;
    521 
    522  if (NULL != trn_cell_establish_intro_check(obj))
    523     return -1;
    524 
    525 
    526  /* Length of u8 auth_key_type IN [0, 1, 2] */
    527  result += 1;
    528 
    529  /* Length of u16 auth_key_len */
    530  result += 2;
    531 
    532  /* Length of u8 auth_key[auth_key_len] */
    533  result += TRUNNEL_DYNARRAY_LEN(&obj->auth_key);
    534 
    535  /* Length of struct trn_extension extensions */
    536  result += trn_extension_encoded_len(obj->extensions);
    537 
    538  /* Length of u8 handshake_mac[TRUNNEL_SHA3_256_LEN] */
    539  result += TRUNNEL_SHA3_256_LEN;
    540 
    541  /* Length of u16 sig_len */
    542  result += 2;
    543 
    544  /* Length of u8 sig[sig_len] */
    545  result += TRUNNEL_DYNARRAY_LEN(&obj->sig);
    546  return result;
    547 }
    548 int
    549 trn_cell_establish_intro_clear_errors(trn_cell_establish_intro_t *obj)
    550 {
    551  int r = obj->trunnel_error_code_;
    552  obj->trunnel_error_code_ = 0;
    553  return r;
    554 }
    555 ssize_t
    556 trn_cell_establish_intro_encode(uint8_t *output, const size_t avail, const trn_cell_establish_intro_t *obj)
    557 {
    558  ssize_t result = 0;
    559  size_t written = 0;
    560  uint8_t *ptr = output;
    561  const char *msg;
    562 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    563  const ssize_t encoded_len = trn_cell_establish_intro_encoded_len(obj);
    564 #endif
    565 
    566  if (NULL != (msg = trn_cell_establish_intro_check(obj)))
    567    goto check_failed;
    568 
    569 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    570  trunnel_assert(encoded_len >= 0);
    571 #endif
    572 
    573  /* Encode u8 auth_key_type IN [0, 1, 2] */
    574  trunnel_assert(written <= avail);
    575  if (avail - written < 1)
    576    goto truncated;
    577  trunnel_set_uint8(ptr, (obj->auth_key_type));
    578  written += 1; ptr += 1;
    579 
    580  /* Encode u16 auth_key_len */
    581  trunnel_assert(written <= avail);
    582  if (avail - written < 2)
    583    goto truncated;
    584  trunnel_set_uint16(ptr, trunnel_htons(obj->auth_key_len));
    585  written += 2; ptr += 2;
    586 
    587  /* Encode u8 auth_key[auth_key_len] */
    588  {
    589    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->auth_key);
    590    trunnel_assert(obj->auth_key_len == elt_len);
    591    trunnel_assert(written <= avail);
    592    if (avail - written < elt_len)
    593      goto truncated;
    594    if (elt_len)
    595      memcpy(ptr, obj->auth_key.elts_, elt_len);
    596    written += elt_len; ptr += elt_len;
    597  }
    598 
    599  /* Encode struct trn_extension extensions */
    600  trunnel_assert(written <= avail);
    601  result = trn_extension_encode(ptr, avail - written, obj->extensions);
    602  if (result < 0)
    603    goto fail; /* XXXXXXX !*/
    604  written += result; ptr += result;
    605 
    606  /* Encode u8 handshake_mac[TRUNNEL_SHA3_256_LEN] */
    607  trunnel_assert(written <= avail);
    608  if (avail - written < TRUNNEL_SHA3_256_LEN)
    609    goto truncated;
    610  memcpy(ptr, obj->handshake_mac, TRUNNEL_SHA3_256_LEN);
    611  written += TRUNNEL_SHA3_256_LEN; ptr += TRUNNEL_SHA3_256_LEN;
    612 
    613  /* Encode u16 sig_len */
    614  trunnel_assert(written <= avail);
    615  if (avail - written < 2)
    616    goto truncated;
    617  trunnel_set_uint16(ptr, trunnel_htons(obj->sig_len));
    618  written += 2; ptr += 2;
    619 
    620  /* Encode u8 sig[sig_len] */
    621  {
    622    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->sig);
    623    trunnel_assert(obj->sig_len == elt_len);
    624    trunnel_assert(written <= avail);
    625    if (avail - written < elt_len)
    626      goto truncated;
    627    if (elt_len)
    628      memcpy(ptr, obj->sig.elts_, elt_len);
    629    written += elt_len; ptr += elt_len;
    630  }
    631 
    632 
    633  trunnel_assert(ptr == output + written);
    634 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    635  {
    636    trunnel_assert(encoded_len >= 0);
    637    trunnel_assert((size_t)encoded_len == written);
    638  }
    639 
    640 #endif
    641 
    642  return written;
    643 
    644 truncated:
    645  result = -2;
    646  goto fail;
    647 check_failed:
    648  (void)msg;
    649  result = -1;
    650  goto fail;
    651 fail:
    652  trunnel_assert(result < 0);
    653  return result;
    654 }
    655 
    656 /** As trn_cell_establish_intro_parse(), but do not allocate the
    657 * output object.
    658 */
    659 static ssize_t
    660 trn_cell_establish_intro_parse_into(trn_cell_establish_intro_t *obj, const uint8_t *input, const size_t len_in)
    661 {
    662  const uint8_t *ptr = input;
    663  size_t remaining = len_in;
    664  ssize_t result = 0;
    665  (void)result;
    666  obj->start_cell = ptr;
    667 
    668  /* Parse u8 auth_key_type IN [0, 1, 2] */
    669  CHECK_REMAINING(1, truncated);
    670  obj->auth_key_type = (trunnel_get_uint8(ptr));
    671  remaining -= 1; ptr += 1;
    672  if (! (obj->auth_key_type == 0 || obj->auth_key_type == 1 || obj->auth_key_type == 2))
    673    goto fail;
    674 
    675  /* Parse u16 auth_key_len */
    676  CHECK_REMAINING(2, truncated);
    677  obj->auth_key_len = trunnel_ntohs(trunnel_get_uint16(ptr));
    678  remaining -= 2; ptr += 2;
    679 
    680  /* Parse u8 auth_key[auth_key_len] */
    681  CHECK_REMAINING(obj->auth_key_len, truncated);
    682  TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->auth_key, obj->auth_key_len, {});
    683  obj->auth_key.n_ = obj->auth_key_len;
    684  if (obj->auth_key_len)
    685    memcpy(obj->auth_key.elts_, ptr, obj->auth_key_len);
    686  ptr += obj->auth_key_len; remaining -= obj->auth_key_len;
    687 
    688  /* Parse struct trn_extension extensions */
    689  result = trn_extension_parse(&obj->extensions, ptr, remaining);
    690  if (result < 0)
    691    goto relay_fail;
    692  trunnel_assert((size_t)result <= remaining);
    693  remaining -= result; ptr += result;
    694  obj->end_mac_fields = ptr;
    695 
    696  /* Parse u8 handshake_mac[TRUNNEL_SHA3_256_LEN] */
    697  CHECK_REMAINING(TRUNNEL_SHA3_256_LEN, truncated);
    698  memcpy(obj->handshake_mac, ptr, TRUNNEL_SHA3_256_LEN);
    699  remaining -= TRUNNEL_SHA3_256_LEN; ptr += TRUNNEL_SHA3_256_LEN;
    700  obj->end_sig_fields = ptr;
    701 
    702  /* Parse u16 sig_len */
    703  CHECK_REMAINING(2, truncated);
    704  obj->sig_len = trunnel_ntohs(trunnel_get_uint16(ptr));
    705  remaining -= 2; ptr += 2;
    706 
    707  /* Parse u8 sig[sig_len] */
    708  CHECK_REMAINING(obj->sig_len, truncated);
    709  TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->sig, obj->sig_len, {});
    710  obj->sig.n_ = obj->sig_len;
    711  if (obj->sig_len)
    712    memcpy(obj->sig.elts_, ptr, obj->sig_len);
    713  ptr += obj->sig_len; remaining -= obj->sig_len;
    714  trunnel_assert(ptr + remaining == input + len_in);
    715  return len_in - remaining;
    716 
    717 truncated:
    718  return -2;
    719 relay_fail:
    720  trunnel_assert(result < 0);
    721  return result;
    722 trunnel_alloc_failed:
    723  return -1;
    724 fail:
    725  result = -1;
    726  return result;
    727 }
    728 
    729 ssize_t
    730 trn_cell_establish_intro_parse(trn_cell_establish_intro_t **output, const uint8_t *input, const size_t len_in)
    731 {
    732  ssize_t result;
    733  *output = trn_cell_establish_intro_new();
    734  if (NULL == *output)
    735    return -1;
    736  result = trn_cell_establish_intro_parse_into(*output, input, len_in);
    737  if (result < 0) {
    738    trn_cell_establish_intro_free(*output);
    739    *output = NULL;
    740  }
    741  return result;
    742 }
    743 trn_cell_extension_dos_t *
    744 trn_cell_extension_dos_new(void)
    745 {
    746  trn_cell_extension_dos_t *val = trunnel_calloc(1, sizeof(trn_cell_extension_dos_t));
    747  if (NULL == val)
    748    return NULL;
    749  return val;
    750 }
    751 
    752 /** Release all storage held inside 'obj', but do not free 'obj'.
    753 */
    754 static void
    755 trn_cell_extension_dos_clear(trn_cell_extension_dos_t *obj)
    756 {
    757  (void) obj;
    758  {
    759 
    760    unsigned idx;
    761    for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->params); ++idx) {
    762      trn_cell_extension_dos_param_free(TRUNNEL_DYNARRAY_GET(&obj->params, idx));
    763    }
    764  }
    765  TRUNNEL_DYNARRAY_WIPE(&obj->params);
    766  TRUNNEL_DYNARRAY_CLEAR(&obj->params);
    767 }
    768 
    769 void
    770 trn_cell_extension_dos_free(trn_cell_extension_dos_t *obj)
    771 {
    772  if (obj == NULL)
    773    return;
    774  trn_cell_extension_dos_clear(obj);
    775  trunnel_memwipe(obj, sizeof(trn_cell_extension_dos_t));
    776  trunnel_free_(obj);
    777 }
    778 
    779 uint8_t
    780 trn_cell_extension_dos_get_n_params(const trn_cell_extension_dos_t *inp)
    781 {
    782  return inp->n_params;
    783 }
    784 int
    785 trn_cell_extension_dos_set_n_params(trn_cell_extension_dos_t *inp, uint8_t val)
    786 {
    787  inp->n_params = val;
    788  return 0;
    789 }
    790 size_t
    791 trn_cell_extension_dos_getlen_params(const trn_cell_extension_dos_t *inp)
    792 {
    793  return TRUNNEL_DYNARRAY_LEN(&inp->params);
    794 }
    795 
    796 struct trn_cell_extension_dos_param_st *
    797 trn_cell_extension_dos_get_params(trn_cell_extension_dos_t *inp, size_t idx)
    798 {
    799  return TRUNNEL_DYNARRAY_GET(&inp->params, idx);
    800 }
    801 
    802 const struct trn_cell_extension_dos_param_st *
    803 trn_cell_extension_dos_getconst_params(const trn_cell_extension_dos_t *inp, size_t idx)
    804 {
    805  return trn_cell_extension_dos_get_params((trn_cell_extension_dos_t*)inp, idx);
    806 }
    807 int
    808 trn_cell_extension_dos_set_params(trn_cell_extension_dos_t *inp, size_t idx, struct trn_cell_extension_dos_param_st * elt)
    809 {
    810  trn_cell_extension_dos_param_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->params, idx);
    811  if (oldval && oldval != elt)
    812    trn_cell_extension_dos_param_free(oldval);
    813  return trn_cell_extension_dos_set0_params(inp, idx, elt);
    814 }
    815 int
    816 trn_cell_extension_dos_set0_params(trn_cell_extension_dos_t *inp, size_t idx, struct trn_cell_extension_dos_param_st * elt)
    817 {
    818  TRUNNEL_DYNARRAY_SET(&inp->params, idx, elt);
    819  return 0;
    820 }
    821 int
    822 trn_cell_extension_dos_add_params(trn_cell_extension_dos_t *inp, struct trn_cell_extension_dos_param_st * elt)
    823 {
    824 #if SIZE_MAX >= UINT8_MAX
    825  if (inp->params.n_ == UINT8_MAX)
    826    goto trunnel_alloc_failed;
    827 #endif
    828  TRUNNEL_DYNARRAY_ADD(struct trn_cell_extension_dos_param_st *, &inp->params, elt, {});
    829  return 0;
    830 trunnel_alloc_failed:
    831  TRUNNEL_SET_ERROR_CODE(inp);
    832  return -1;
    833 }
    834 
    835 struct trn_cell_extension_dos_param_st * *
    836 trn_cell_extension_dos_getarray_params(trn_cell_extension_dos_t *inp)
    837 {
    838  return inp->params.elts_;
    839 }
    840 const struct trn_cell_extension_dos_param_st *  const  *
    841 trn_cell_extension_dos_getconstarray_params(const trn_cell_extension_dos_t *inp)
    842 {
    843  return (const struct trn_cell_extension_dos_param_st *  const  *)trn_cell_extension_dos_getarray_params((trn_cell_extension_dos_t*)inp);
    844 }
    845 int
    846 trn_cell_extension_dos_setlen_params(trn_cell_extension_dos_t *inp, size_t newlen)
    847 {
    848  struct trn_cell_extension_dos_param_st * *newptr;
    849 #if UINT8_MAX < SIZE_MAX
    850  if (newlen > UINT8_MAX)
    851    goto trunnel_alloc_failed;
    852 #endif
    853  newptr = trunnel_dynarray_setlen(&inp->params.allocated_,
    854                 &inp->params.n_, inp->params.elts_, newlen,
    855                 sizeof(inp->params.elts_[0]), (trunnel_free_fn_t) trn_cell_extension_dos_param_free,
    856                 &inp->trunnel_error_code_);
    857  if (newlen != 0 && newptr == NULL)
    858    goto trunnel_alloc_failed;
    859  inp->params.elts_ = newptr;
    860  return 0;
    861 trunnel_alloc_failed:
    862  TRUNNEL_SET_ERROR_CODE(inp);
    863  return -1;
    864 }
    865 const char *
    866 trn_cell_extension_dos_check(const trn_cell_extension_dos_t *obj)
    867 {
    868  if (obj == NULL)
    869    return "Object was NULL";
    870  if (obj->trunnel_error_code_)
    871    return "A set function failed on this object";
    872  {
    873    const char *msg;
    874 
    875    unsigned idx;
    876    for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->params); ++idx) {
    877      if (NULL != (msg = trn_cell_extension_dos_param_check(TRUNNEL_DYNARRAY_GET(&obj->params, idx))))
    878        return msg;
    879    }
    880  }
    881  if (TRUNNEL_DYNARRAY_LEN(&obj->params) != obj->n_params)
    882    return "Length mismatch for params";
    883  return NULL;
    884 }
    885 
    886 ssize_t
    887 trn_cell_extension_dos_encoded_len(const trn_cell_extension_dos_t *obj)
    888 {
    889  ssize_t result = 0;
    890 
    891  if (NULL != trn_cell_extension_dos_check(obj))
    892     return -1;
    893 
    894 
    895  /* Length of u8 n_params */
    896  result += 1;
    897 
    898  /* Length of struct trn_cell_extension_dos_param params[n_params] */
    899  {
    900 
    901    unsigned idx;
    902    for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->params); ++idx) {
    903      result += trn_cell_extension_dos_param_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->params, idx));
    904    }
    905  }
    906  return result;
    907 }
    908 int
    909 trn_cell_extension_dos_clear_errors(trn_cell_extension_dos_t *obj)
    910 {
    911  int r = obj->trunnel_error_code_;
    912  obj->trunnel_error_code_ = 0;
    913  return r;
    914 }
    915 ssize_t
    916 trn_cell_extension_dos_encode(uint8_t *output, const size_t avail, const trn_cell_extension_dos_t *obj)
    917 {
    918  ssize_t result = 0;
    919  size_t written = 0;
    920  uint8_t *ptr = output;
    921  const char *msg;
    922 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    923  const ssize_t encoded_len = trn_cell_extension_dos_encoded_len(obj);
    924 #endif
    925 
    926  if (NULL != (msg = trn_cell_extension_dos_check(obj)))
    927    goto check_failed;
    928 
    929 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    930  trunnel_assert(encoded_len >= 0);
    931 #endif
    932 
    933  /* Encode u8 n_params */
    934  trunnel_assert(written <= avail);
    935  if (avail - written < 1)
    936    goto truncated;
    937  trunnel_set_uint8(ptr, (obj->n_params));
    938  written += 1; ptr += 1;
    939 
    940  /* Encode struct trn_cell_extension_dos_param params[n_params] */
    941  {
    942 
    943    unsigned idx;
    944    for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->params); ++idx) {
    945      trunnel_assert(written <= avail);
    946      result = trn_cell_extension_dos_param_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->params, idx));
    947      if (result < 0)
    948        goto fail; /* XXXXXXX !*/
    949      written += result; ptr += result;
    950    }
    951  }
    952 
    953 
    954  trunnel_assert(ptr == output + written);
    955 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    956  {
    957    trunnel_assert(encoded_len >= 0);
    958    trunnel_assert((size_t)encoded_len == written);
    959  }
    960 
    961 #endif
    962 
    963  return written;
    964 
    965 truncated:
    966  result = -2;
    967  goto fail;
    968 check_failed:
    969  (void)msg;
    970  result = -1;
    971  goto fail;
    972 fail:
    973  trunnel_assert(result < 0);
    974  return result;
    975 }
    976 
    977 /** As trn_cell_extension_dos_parse(), but do not allocate the output
    978 * object.
    979 */
    980 static ssize_t
    981 trn_cell_extension_dos_parse_into(trn_cell_extension_dos_t *obj, const uint8_t *input, const size_t len_in)
    982 {
    983  const uint8_t *ptr = input;
    984  size_t remaining = len_in;
    985  ssize_t result = 0;
    986  (void)result;
    987 
    988  /* Parse u8 n_params */
    989  CHECK_REMAINING(1, truncated);
    990  obj->n_params = (trunnel_get_uint8(ptr));
    991  remaining -= 1; ptr += 1;
    992 
    993  /* Parse struct trn_cell_extension_dos_param params[n_params] */
    994  TRUNNEL_DYNARRAY_EXPAND(trn_cell_extension_dos_param_t *, &obj->params, obj->n_params, {});
    995  {
    996    trn_cell_extension_dos_param_t * elt;
    997    unsigned idx;
    998    for (idx = 0; idx < obj->n_params; ++idx) {
    999      result = trn_cell_extension_dos_param_parse(&elt, ptr, remaining);
   1000      if (result < 0)
   1001        goto relay_fail;
   1002      trunnel_assert((size_t)result <= remaining);
   1003      remaining -= result; ptr += result;
   1004      TRUNNEL_DYNARRAY_ADD(trn_cell_extension_dos_param_t *, &obj->params, elt, {trn_cell_extension_dos_param_free(elt);});
   1005    }
   1006  }
   1007  trunnel_assert(ptr + remaining == input + len_in);
   1008  return len_in - remaining;
   1009 
   1010 truncated:
   1011  return -2;
   1012 relay_fail:
   1013  trunnel_assert(result < 0);
   1014  return result;
   1015 trunnel_alloc_failed:
   1016  return -1;
   1017 }
   1018 
   1019 ssize_t
   1020 trn_cell_extension_dos_parse(trn_cell_extension_dos_t **output, const uint8_t *input, const size_t len_in)
   1021 {
   1022  ssize_t result;
   1023  *output = trn_cell_extension_dos_new();
   1024  if (NULL == *output)
   1025    return -1;
   1026  result = trn_cell_extension_dos_parse_into(*output, input, len_in);
   1027  if (result < 0) {
   1028    trn_cell_extension_dos_free(*output);
   1029    *output = NULL;
   1030  }
   1031  return result;
   1032 }
   1033 trn_cell_intro_established_t *
   1034 trn_cell_intro_established_new(void)
   1035 {
   1036  trn_cell_intro_established_t *val = trunnel_calloc(1, sizeof(trn_cell_intro_established_t));
   1037  if (NULL == val)
   1038    return NULL;
   1039  return val;
   1040 }
   1041 
   1042 /** Release all storage held inside 'obj', but do not free 'obj'.
   1043 */
   1044 static void
   1045 trn_cell_intro_established_clear(trn_cell_intro_established_t *obj)
   1046 {
   1047  (void) obj;
   1048  trn_extension_free(obj->extensions);
   1049  obj->extensions = NULL;
   1050 }
   1051 
   1052 void
   1053 trn_cell_intro_established_free(trn_cell_intro_established_t *obj)
   1054 {
   1055  if (obj == NULL)
   1056    return;
   1057  trn_cell_intro_established_clear(obj);
   1058  trunnel_memwipe(obj, sizeof(trn_cell_intro_established_t));
   1059  trunnel_free_(obj);
   1060 }
   1061 
   1062 struct trn_extension_st *
   1063 trn_cell_intro_established_get_extensions(trn_cell_intro_established_t *inp)
   1064 {
   1065  return inp->extensions;
   1066 }
   1067 const struct trn_extension_st *
   1068 trn_cell_intro_established_getconst_extensions(const trn_cell_intro_established_t *inp)
   1069 {
   1070  return trn_cell_intro_established_get_extensions((trn_cell_intro_established_t*) inp);
   1071 }
   1072 int
   1073 trn_cell_intro_established_set_extensions(trn_cell_intro_established_t *inp, struct trn_extension_st *val)
   1074 {
   1075  if (inp->extensions && inp->extensions != val)
   1076    trn_extension_free(inp->extensions);
   1077  return trn_cell_intro_established_set0_extensions(inp, val);
   1078 }
   1079 int
   1080 trn_cell_intro_established_set0_extensions(trn_cell_intro_established_t *inp, struct trn_extension_st *val)
   1081 {
   1082  inp->extensions = val;
   1083  return 0;
   1084 }
   1085 const char *
   1086 trn_cell_intro_established_check(const trn_cell_intro_established_t *obj)
   1087 {
   1088  if (obj == NULL)
   1089    return "Object was NULL";
   1090  if (obj->trunnel_error_code_)
   1091    return "A set function failed on this object";
   1092  {
   1093    const char *msg;
   1094    if (NULL != (msg = trn_extension_check(obj->extensions)))
   1095      return msg;
   1096  }
   1097  return NULL;
   1098 }
   1099 
   1100 ssize_t
   1101 trn_cell_intro_established_encoded_len(const trn_cell_intro_established_t *obj)
   1102 {
   1103  ssize_t result = 0;
   1104 
   1105  if (NULL != trn_cell_intro_established_check(obj))
   1106     return -1;
   1107 
   1108 
   1109  /* Length of struct trn_extension extensions */
   1110  result += trn_extension_encoded_len(obj->extensions);
   1111  return result;
   1112 }
   1113 int
   1114 trn_cell_intro_established_clear_errors(trn_cell_intro_established_t *obj)
   1115 {
   1116  int r = obj->trunnel_error_code_;
   1117  obj->trunnel_error_code_ = 0;
   1118  return r;
   1119 }
   1120 ssize_t
   1121 trn_cell_intro_established_encode(uint8_t *output, const size_t avail, const trn_cell_intro_established_t *obj)
   1122 {
   1123  ssize_t result = 0;
   1124  size_t written = 0;
   1125  uint8_t *ptr = output;
   1126  const char *msg;
   1127 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1128  const ssize_t encoded_len = trn_cell_intro_established_encoded_len(obj);
   1129 #endif
   1130 
   1131  if (NULL != (msg = trn_cell_intro_established_check(obj)))
   1132    goto check_failed;
   1133 
   1134 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1135  trunnel_assert(encoded_len >= 0);
   1136 #endif
   1137 
   1138  /* Encode struct trn_extension extensions */
   1139  trunnel_assert(written <= avail);
   1140  result = trn_extension_encode(ptr, avail - written, obj->extensions);
   1141  if (result < 0)
   1142    goto fail; /* XXXXXXX !*/
   1143  written += result; ptr += result;
   1144 
   1145 
   1146  trunnel_assert(ptr == output + written);
   1147 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1148  {
   1149    trunnel_assert(encoded_len >= 0);
   1150    trunnel_assert((size_t)encoded_len == written);
   1151  }
   1152 
   1153 #endif
   1154 
   1155  return written;
   1156 
   1157 check_failed:
   1158  (void)msg;
   1159  result = -1;
   1160  goto fail;
   1161 fail:
   1162  trunnel_assert(result < 0);
   1163  return result;
   1164 }
   1165 
   1166 /** As trn_cell_intro_established_parse(), but do not allocate the
   1167 * output object.
   1168 */
   1169 static ssize_t
   1170 trn_cell_intro_established_parse_into(trn_cell_intro_established_t *obj, const uint8_t *input, const size_t len_in)
   1171 {
   1172  const uint8_t *ptr = input;
   1173  size_t remaining = len_in;
   1174  ssize_t result = 0;
   1175  (void)result;
   1176 
   1177  /* Parse struct trn_extension extensions */
   1178  result = trn_extension_parse(&obj->extensions, ptr, remaining);
   1179  if (result < 0)
   1180    goto relay_fail;
   1181  trunnel_assert((size_t)result <= remaining);
   1182  remaining -= result; ptr += result;
   1183  trunnel_assert(ptr + remaining == input + len_in);
   1184  return len_in - remaining;
   1185 
   1186 relay_fail:
   1187  trunnel_assert(result < 0);
   1188  return result;
   1189 }
   1190 
   1191 ssize_t
   1192 trn_cell_intro_established_parse(trn_cell_intro_established_t **output, const uint8_t *input, const size_t len_in)
   1193 {
   1194  ssize_t result;
   1195  *output = trn_cell_intro_established_new();
   1196  if (NULL == *output)
   1197    return -1;
   1198  result = trn_cell_intro_established_parse_into(*output, input, len_in);
   1199  if (result < 0) {
   1200    trn_cell_intro_established_free(*output);
   1201    *output = NULL;
   1202  }
   1203  return result;
   1204 }