tor

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

cell_introduce1.c (48181B)


      1 /* cell_introduce1.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_introduce1.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 cellintroduce_deadcode_dummy__ = 0;
     19 #define OR_DEADCODE_DUMMY || cellintroduce_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 typedef struct link_specifier_st link_specifier_t;
     40 link_specifier_t *link_specifier_new(void);
     41 void link_specifier_free(link_specifier_t *victim);
     42 ssize_t link_specifier_parse(link_specifier_t **output, const uint8_t *input, const size_t len_in);
     43 ssize_t link_specifier_encoded_len(const link_specifier_t *obj);
     44 ssize_t link_specifier_encode(uint8_t *output, size_t avail, const link_specifier_t *input);
     45 const char *link_specifier_check(const link_specifier_t *obj);
     46 int link_specifier_clear_errors(link_specifier_t *obj);
     47 trn_cell_extension_pow_t *
     48 trn_cell_extension_pow_new(void)
     49 {
     50  trn_cell_extension_pow_t *val = trunnel_calloc(1, sizeof(trn_cell_extension_pow_t));
     51  if (NULL == val)
     52    return NULL;
     53  val->pow_version = 1;
     54  return val;
     55 }
     56 
     57 /** Release all storage held inside 'obj', but do not free 'obj'.
     58 */
     59 static void
     60 trn_cell_extension_pow_clear(trn_cell_extension_pow_t *obj)
     61 {
     62  (void) obj;
     63 }
     64 
     65 void
     66 trn_cell_extension_pow_free(trn_cell_extension_pow_t *obj)
     67 {
     68  if (obj == NULL)
     69    return;
     70  trn_cell_extension_pow_clear(obj);
     71  trunnel_memwipe(obj, sizeof(trn_cell_extension_pow_t));
     72  trunnel_free_(obj);
     73 }
     74 
     75 uint8_t
     76 trn_cell_extension_pow_get_pow_version(const trn_cell_extension_pow_t *inp)
     77 {
     78  return inp->pow_version;
     79 }
     80 int
     81 trn_cell_extension_pow_set_pow_version(trn_cell_extension_pow_t *inp, uint8_t val)
     82 {
     83  if (! ((val == 1))) {
     84     TRUNNEL_SET_ERROR_CODE(inp);
     85     return -1;
     86  }
     87  inp->pow_version = val;
     88  return 0;
     89 }
     90 size_t
     91 trn_cell_extension_pow_getlen_pow_nonce(const trn_cell_extension_pow_t *inp)
     92 {
     93  (void)inp;  return TRUNNEL_POW_NONCE_LEN;
     94 }
     95 
     96 uint8_t
     97 trn_cell_extension_pow_get_pow_nonce(trn_cell_extension_pow_t *inp, size_t idx)
     98 {
     99  trunnel_assert(idx < TRUNNEL_POW_NONCE_LEN);
    100  return inp->pow_nonce[idx];
    101 }
    102 
    103 uint8_t
    104 trn_cell_extension_pow_getconst_pow_nonce(const trn_cell_extension_pow_t *inp, size_t idx)
    105 {
    106  return trn_cell_extension_pow_get_pow_nonce((trn_cell_extension_pow_t*)inp, idx);
    107 }
    108 int
    109 trn_cell_extension_pow_set_pow_nonce(trn_cell_extension_pow_t *inp, size_t idx, uint8_t elt)
    110 {
    111  trunnel_assert(idx < TRUNNEL_POW_NONCE_LEN);
    112  inp->pow_nonce[idx] = elt;
    113  return 0;
    114 }
    115 
    116 uint8_t *
    117 trn_cell_extension_pow_getarray_pow_nonce(trn_cell_extension_pow_t *inp)
    118 {
    119  return inp->pow_nonce;
    120 }
    121 const uint8_t  *
    122 trn_cell_extension_pow_getconstarray_pow_nonce(const trn_cell_extension_pow_t *inp)
    123 {
    124  return (const uint8_t  *)trn_cell_extension_pow_getarray_pow_nonce((trn_cell_extension_pow_t*)inp);
    125 }
    126 uint32_t
    127 trn_cell_extension_pow_get_pow_effort(const trn_cell_extension_pow_t *inp)
    128 {
    129  return inp->pow_effort;
    130 }
    131 int
    132 trn_cell_extension_pow_set_pow_effort(trn_cell_extension_pow_t *inp, uint32_t val)
    133 {
    134  inp->pow_effort = val;
    135  return 0;
    136 }
    137 size_t
    138 trn_cell_extension_pow_getlen_pow_seed(const trn_cell_extension_pow_t *inp)
    139 {
    140  (void)inp;  return TRUNNEL_POW_SEED_HEAD_LEN;
    141 }
    142 
    143 uint8_t
    144 trn_cell_extension_pow_get_pow_seed(trn_cell_extension_pow_t *inp, size_t idx)
    145 {
    146  trunnel_assert(idx < TRUNNEL_POW_SEED_HEAD_LEN);
    147  return inp->pow_seed[idx];
    148 }
    149 
    150 uint8_t
    151 trn_cell_extension_pow_getconst_pow_seed(const trn_cell_extension_pow_t *inp, size_t idx)
    152 {
    153  return trn_cell_extension_pow_get_pow_seed((trn_cell_extension_pow_t*)inp, idx);
    154 }
    155 int
    156 trn_cell_extension_pow_set_pow_seed(trn_cell_extension_pow_t *inp, size_t idx, uint8_t elt)
    157 {
    158  trunnel_assert(idx < TRUNNEL_POW_SEED_HEAD_LEN);
    159  inp->pow_seed[idx] = elt;
    160  return 0;
    161 }
    162 
    163 uint8_t *
    164 trn_cell_extension_pow_getarray_pow_seed(trn_cell_extension_pow_t *inp)
    165 {
    166  return inp->pow_seed;
    167 }
    168 const uint8_t  *
    169 trn_cell_extension_pow_getconstarray_pow_seed(const trn_cell_extension_pow_t *inp)
    170 {
    171  return (const uint8_t  *)trn_cell_extension_pow_getarray_pow_seed((trn_cell_extension_pow_t*)inp);
    172 }
    173 size_t
    174 trn_cell_extension_pow_getlen_pow_solution(const trn_cell_extension_pow_t *inp)
    175 {
    176  (void)inp;  return TRUNNEL_POW_SOLUTION_LEN;
    177 }
    178 
    179 uint8_t
    180 trn_cell_extension_pow_get_pow_solution(trn_cell_extension_pow_t *inp, size_t idx)
    181 {
    182  trunnel_assert(idx < TRUNNEL_POW_SOLUTION_LEN);
    183  return inp->pow_solution[idx];
    184 }
    185 
    186 uint8_t
    187 trn_cell_extension_pow_getconst_pow_solution(const trn_cell_extension_pow_t *inp, size_t idx)
    188 {
    189  return trn_cell_extension_pow_get_pow_solution((trn_cell_extension_pow_t*)inp, idx);
    190 }
    191 int
    192 trn_cell_extension_pow_set_pow_solution(trn_cell_extension_pow_t *inp, size_t idx, uint8_t elt)
    193 {
    194  trunnel_assert(idx < TRUNNEL_POW_SOLUTION_LEN);
    195  inp->pow_solution[idx] = elt;
    196  return 0;
    197 }
    198 
    199 uint8_t *
    200 trn_cell_extension_pow_getarray_pow_solution(trn_cell_extension_pow_t *inp)
    201 {
    202  return inp->pow_solution;
    203 }
    204 const uint8_t  *
    205 trn_cell_extension_pow_getconstarray_pow_solution(const trn_cell_extension_pow_t *inp)
    206 {
    207  return (const uint8_t  *)trn_cell_extension_pow_getarray_pow_solution((trn_cell_extension_pow_t*)inp);
    208 }
    209 const char *
    210 trn_cell_extension_pow_check(const trn_cell_extension_pow_t *obj)
    211 {
    212  if (obj == NULL)
    213    return "Object was NULL";
    214  if (obj->trunnel_error_code_)
    215    return "A set function failed on this object";
    216  if (! (obj->pow_version == 1))
    217    return "Integer out of bounds";
    218  return NULL;
    219 }
    220 
    221 ssize_t
    222 trn_cell_extension_pow_encoded_len(const trn_cell_extension_pow_t *obj)
    223 {
    224  ssize_t result = 0;
    225 
    226  if (NULL != trn_cell_extension_pow_check(obj))
    227     return -1;
    228 
    229 
    230  /* Length of u8 pow_version IN [1] */
    231  result += 1;
    232 
    233  /* Length of u8 pow_nonce[TRUNNEL_POW_NONCE_LEN] */
    234  result += TRUNNEL_POW_NONCE_LEN;
    235 
    236  /* Length of u32 pow_effort */
    237  result += 4;
    238 
    239  /* Length of u8 pow_seed[TRUNNEL_POW_SEED_HEAD_LEN] */
    240  result += TRUNNEL_POW_SEED_HEAD_LEN;
    241 
    242  /* Length of u8 pow_solution[TRUNNEL_POW_SOLUTION_LEN] */
    243  result += TRUNNEL_POW_SOLUTION_LEN;
    244  return result;
    245 }
    246 int
    247 trn_cell_extension_pow_clear_errors(trn_cell_extension_pow_t *obj)
    248 {
    249  int r = obj->trunnel_error_code_;
    250  obj->trunnel_error_code_ = 0;
    251  return r;
    252 }
    253 ssize_t
    254 trn_cell_extension_pow_encode(uint8_t *output, const size_t avail, const trn_cell_extension_pow_t *obj)
    255 {
    256  ssize_t result = 0;
    257  size_t written = 0;
    258  uint8_t *ptr = output;
    259  const char *msg;
    260 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    261  const ssize_t encoded_len = trn_cell_extension_pow_encoded_len(obj);
    262 #endif
    263 
    264  if (NULL != (msg = trn_cell_extension_pow_check(obj)))
    265    goto check_failed;
    266 
    267 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    268  trunnel_assert(encoded_len >= 0);
    269 #endif
    270 
    271  /* Encode u8 pow_version IN [1] */
    272  trunnel_assert(written <= avail);
    273  if (avail - written < 1)
    274    goto truncated;
    275  trunnel_set_uint8(ptr, (obj->pow_version));
    276  written += 1; ptr += 1;
    277 
    278  /* Encode u8 pow_nonce[TRUNNEL_POW_NONCE_LEN] */
    279  trunnel_assert(written <= avail);
    280  if (avail - written < TRUNNEL_POW_NONCE_LEN)
    281    goto truncated;
    282  memcpy(ptr, obj->pow_nonce, TRUNNEL_POW_NONCE_LEN);
    283  written += TRUNNEL_POW_NONCE_LEN; ptr += TRUNNEL_POW_NONCE_LEN;
    284 
    285  /* Encode u32 pow_effort */
    286  trunnel_assert(written <= avail);
    287  if (avail - written < 4)
    288    goto truncated;
    289  trunnel_set_uint32(ptr, trunnel_htonl(obj->pow_effort));
    290  written += 4; ptr += 4;
    291 
    292  /* Encode u8 pow_seed[TRUNNEL_POW_SEED_HEAD_LEN] */
    293  trunnel_assert(written <= avail);
    294  if (avail - written < TRUNNEL_POW_SEED_HEAD_LEN)
    295    goto truncated;
    296  memcpy(ptr, obj->pow_seed, TRUNNEL_POW_SEED_HEAD_LEN);
    297  written += TRUNNEL_POW_SEED_HEAD_LEN; ptr += TRUNNEL_POW_SEED_HEAD_LEN;
    298 
    299  /* Encode u8 pow_solution[TRUNNEL_POW_SOLUTION_LEN] */
    300  trunnel_assert(written <= avail);
    301  if (avail - written < TRUNNEL_POW_SOLUTION_LEN)
    302    goto truncated;
    303  memcpy(ptr, obj->pow_solution, TRUNNEL_POW_SOLUTION_LEN);
    304  written += TRUNNEL_POW_SOLUTION_LEN; ptr += TRUNNEL_POW_SOLUTION_LEN;
    305 
    306 
    307  trunnel_assert(ptr == output + written);
    308 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    309  {
    310    trunnel_assert(encoded_len >= 0);
    311    trunnel_assert((size_t)encoded_len == written);
    312  }
    313 
    314 #endif
    315 
    316  return written;
    317 
    318 truncated:
    319  result = -2;
    320  goto fail;
    321 check_failed:
    322  (void)msg;
    323  result = -1;
    324  goto fail;
    325 fail:
    326  trunnel_assert(result < 0);
    327  return result;
    328 }
    329 
    330 /** As trn_cell_extension_pow_parse(), but do not allocate the output
    331 * object.
    332 */
    333 static ssize_t
    334 trn_cell_extension_pow_parse_into(trn_cell_extension_pow_t *obj, const uint8_t *input, const size_t len_in)
    335 {
    336  const uint8_t *ptr = input;
    337  size_t remaining = len_in;
    338  ssize_t result = 0;
    339  (void)result;
    340 
    341  /* Parse u8 pow_version IN [1] */
    342  CHECK_REMAINING(1, truncated);
    343  obj->pow_version = (trunnel_get_uint8(ptr));
    344  remaining -= 1; ptr += 1;
    345  if (! (obj->pow_version == 1))
    346    goto fail;
    347 
    348  /* Parse u8 pow_nonce[TRUNNEL_POW_NONCE_LEN] */
    349  CHECK_REMAINING(TRUNNEL_POW_NONCE_LEN, truncated);
    350  memcpy(obj->pow_nonce, ptr, TRUNNEL_POW_NONCE_LEN);
    351  remaining -= TRUNNEL_POW_NONCE_LEN; ptr += TRUNNEL_POW_NONCE_LEN;
    352 
    353  /* Parse u32 pow_effort */
    354  CHECK_REMAINING(4, truncated);
    355  obj->pow_effort = trunnel_ntohl(trunnel_get_uint32(ptr));
    356  remaining -= 4; ptr += 4;
    357 
    358  /* Parse u8 pow_seed[TRUNNEL_POW_SEED_HEAD_LEN] */
    359  CHECK_REMAINING(TRUNNEL_POW_SEED_HEAD_LEN, truncated);
    360  memcpy(obj->pow_seed, ptr, TRUNNEL_POW_SEED_HEAD_LEN);
    361  remaining -= TRUNNEL_POW_SEED_HEAD_LEN; ptr += TRUNNEL_POW_SEED_HEAD_LEN;
    362 
    363  /* Parse u8 pow_solution[TRUNNEL_POW_SOLUTION_LEN] */
    364  CHECK_REMAINING(TRUNNEL_POW_SOLUTION_LEN, truncated);
    365  memcpy(obj->pow_solution, ptr, TRUNNEL_POW_SOLUTION_LEN);
    366  remaining -= TRUNNEL_POW_SOLUTION_LEN; ptr += TRUNNEL_POW_SOLUTION_LEN;
    367  trunnel_assert(ptr + remaining == input + len_in);
    368  return len_in - remaining;
    369 
    370 truncated:
    371  return -2;
    372 fail:
    373  result = -1;
    374  return result;
    375 }
    376 
    377 ssize_t
    378 trn_cell_extension_pow_parse(trn_cell_extension_pow_t **output, const uint8_t *input, const size_t len_in)
    379 {
    380  ssize_t result;
    381  *output = trn_cell_extension_pow_new();
    382  if (NULL == *output)
    383    return -1;
    384  result = trn_cell_extension_pow_parse_into(*output, input, len_in);
    385  if (result < 0) {
    386    trn_cell_extension_pow_free(*output);
    387    *output = NULL;
    388  }
    389  return result;
    390 }
    391 trn_cell_introduce1_t *
    392 trn_cell_introduce1_new(void)
    393 {
    394  trn_cell_introduce1_t *val = trunnel_calloc(1, sizeof(trn_cell_introduce1_t));
    395  if (NULL == val)
    396    return NULL;
    397  val->auth_key_type = TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519;
    398  return val;
    399 }
    400 
    401 /** Release all storage held inside 'obj', but do not free 'obj'.
    402 */
    403 static void
    404 trn_cell_introduce1_clear(trn_cell_introduce1_t *obj)
    405 {
    406  (void) obj;
    407  TRUNNEL_DYNARRAY_WIPE(&obj->auth_key);
    408  TRUNNEL_DYNARRAY_CLEAR(&obj->auth_key);
    409  trn_extension_free(obj->extensions);
    410  obj->extensions = NULL;
    411  TRUNNEL_DYNARRAY_WIPE(&obj->encrypted);
    412  TRUNNEL_DYNARRAY_CLEAR(&obj->encrypted);
    413 }
    414 
    415 void
    416 trn_cell_introduce1_free(trn_cell_introduce1_t *obj)
    417 {
    418  if (obj == NULL)
    419    return;
    420  trn_cell_introduce1_clear(obj);
    421  trunnel_memwipe(obj, sizeof(trn_cell_introduce1_t));
    422  trunnel_free_(obj);
    423 }
    424 
    425 size_t
    426 trn_cell_introduce1_getlen_legacy_key_id(const trn_cell_introduce1_t *inp)
    427 {
    428  (void)inp;  return TRUNNEL_SHA1_LEN;
    429 }
    430 
    431 uint8_t
    432 trn_cell_introduce1_get_legacy_key_id(trn_cell_introduce1_t *inp, size_t idx)
    433 {
    434  trunnel_assert(idx < TRUNNEL_SHA1_LEN);
    435  return inp->legacy_key_id[idx];
    436 }
    437 
    438 uint8_t
    439 trn_cell_introduce1_getconst_legacy_key_id(const trn_cell_introduce1_t *inp, size_t idx)
    440 {
    441  return trn_cell_introduce1_get_legacy_key_id((trn_cell_introduce1_t*)inp, idx);
    442 }
    443 int
    444 trn_cell_introduce1_set_legacy_key_id(trn_cell_introduce1_t *inp, size_t idx, uint8_t elt)
    445 {
    446  trunnel_assert(idx < TRUNNEL_SHA1_LEN);
    447  inp->legacy_key_id[idx] = elt;
    448  return 0;
    449 }
    450 
    451 uint8_t *
    452 trn_cell_introduce1_getarray_legacy_key_id(trn_cell_introduce1_t *inp)
    453 {
    454  return inp->legacy_key_id;
    455 }
    456 const uint8_t  *
    457 trn_cell_introduce1_getconstarray_legacy_key_id(const trn_cell_introduce1_t *inp)
    458 {
    459  return (const uint8_t  *)trn_cell_introduce1_getarray_legacy_key_id((trn_cell_introduce1_t*)inp);
    460 }
    461 uint8_t
    462 trn_cell_introduce1_get_auth_key_type(const trn_cell_introduce1_t *inp)
    463 {
    464  return inp->auth_key_type;
    465 }
    466 int
    467 trn_cell_introduce1_set_auth_key_type(trn_cell_introduce1_t *inp, uint8_t val)
    468 {
    469  if (! ((val == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519 || val == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0 || val == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1))) {
    470     TRUNNEL_SET_ERROR_CODE(inp);
    471     return -1;
    472  }
    473  inp->auth_key_type = val;
    474  return 0;
    475 }
    476 uint16_t
    477 trn_cell_introduce1_get_auth_key_len(const trn_cell_introduce1_t *inp)
    478 {
    479  return inp->auth_key_len;
    480 }
    481 int
    482 trn_cell_introduce1_set_auth_key_len(trn_cell_introduce1_t *inp, uint16_t val)
    483 {
    484  inp->auth_key_len = val;
    485  return 0;
    486 }
    487 size_t
    488 trn_cell_introduce1_getlen_auth_key(const trn_cell_introduce1_t *inp)
    489 {
    490  return TRUNNEL_DYNARRAY_LEN(&inp->auth_key);
    491 }
    492 
    493 uint8_t
    494 trn_cell_introduce1_get_auth_key(trn_cell_introduce1_t *inp, size_t idx)
    495 {
    496  return TRUNNEL_DYNARRAY_GET(&inp->auth_key, idx);
    497 }
    498 
    499 uint8_t
    500 trn_cell_introduce1_getconst_auth_key(const trn_cell_introduce1_t *inp, size_t idx)
    501 {
    502  return trn_cell_introduce1_get_auth_key((trn_cell_introduce1_t*)inp, idx);
    503 }
    504 int
    505 trn_cell_introduce1_set_auth_key(trn_cell_introduce1_t *inp, size_t idx, uint8_t elt)
    506 {
    507  TRUNNEL_DYNARRAY_SET(&inp->auth_key, idx, elt);
    508  return 0;
    509 }
    510 int
    511 trn_cell_introduce1_add_auth_key(trn_cell_introduce1_t *inp, uint8_t elt)
    512 {
    513 #if SIZE_MAX >= UINT16_MAX
    514  if (inp->auth_key.n_ == UINT16_MAX)
    515    goto trunnel_alloc_failed;
    516 #endif
    517  TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->auth_key, elt, {});
    518  return 0;
    519 trunnel_alloc_failed:
    520  TRUNNEL_SET_ERROR_CODE(inp);
    521  return -1;
    522 }
    523 
    524 uint8_t *
    525 trn_cell_introduce1_getarray_auth_key(trn_cell_introduce1_t *inp)
    526 {
    527  return inp->auth_key.elts_;
    528 }
    529 const uint8_t  *
    530 trn_cell_introduce1_getconstarray_auth_key(const trn_cell_introduce1_t *inp)
    531 {
    532  return (const uint8_t  *)trn_cell_introduce1_getarray_auth_key((trn_cell_introduce1_t*)inp);
    533 }
    534 int
    535 trn_cell_introduce1_setlen_auth_key(trn_cell_introduce1_t *inp, size_t newlen)
    536 {
    537  uint8_t *newptr;
    538 #if UINT16_MAX < SIZE_MAX
    539  if (newlen > UINT16_MAX)
    540    goto trunnel_alloc_failed;
    541 #endif
    542  newptr = trunnel_dynarray_setlen(&inp->auth_key.allocated_,
    543                 &inp->auth_key.n_, inp->auth_key.elts_, newlen,
    544                 sizeof(inp->auth_key.elts_[0]), (trunnel_free_fn_t) NULL,
    545                 &inp->trunnel_error_code_);
    546  if (newlen != 0 && newptr == NULL)
    547    goto trunnel_alloc_failed;
    548  inp->auth_key.elts_ = newptr;
    549  return 0;
    550 trunnel_alloc_failed:
    551  TRUNNEL_SET_ERROR_CODE(inp);
    552  return -1;
    553 }
    554 struct trn_extension_st *
    555 trn_cell_introduce1_get_extensions(trn_cell_introduce1_t *inp)
    556 {
    557  return inp->extensions;
    558 }
    559 const struct trn_extension_st *
    560 trn_cell_introduce1_getconst_extensions(const trn_cell_introduce1_t *inp)
    561 {
    562  return trn_cell_introduce1_get_extensions((trn_cell_introduce1_t*) inp);
    563 }
    564 int
    565 trn_cell_introduce1_set_extensions(trn_cell_introduce1_t *inp, struct trn_extension_st *val)
    566 {
    567  if (inp->extensions && inp->extensions != val)
    568    trn_extension_free(inp->extensions);
    569  return trn_cell_introduce1_set0_extensions(inp, val);
    570 }
    571 int
    572 trn_cell_introduce1_set0_extensions(trn_cell_introduce1_t *inp, struct trn_extension_st *val)
    573 {
    574  inp->extensions = val;
    575  return 0;
    576 }
    577 size_t
    578 trn_cell_introduce1_getlen_encrypted(const trn_cell_introduce1_t *inp)
    579 {
    580  return TRUNNEL_DYNARRAY_LEN(&inp->encrypted);
    581 }
    582 
    583 uint8_t
    584 trn_cell_introduce1_get_encrypted(trn_cell_introduce1_t *inp, size_t idx)
    585 {
    586  return TRUNNEL_DYNARRAY_GET(&inp->encrypted, idx);
    587 }
    588 
    589 uint8_t
    590 trn_cell_introduce1_getconst_encrypted(const trn_cell_introduce1_t *inp, size_t idx)
    591 {
    592  return trn_cell_introduce1_get_encrypted((trn_cell_introduce1_t*)inp, idx);
    593 }
    594 int
    595 trn_cell_introduce1_set_encrypted(trn_cell_introduce1_t *inp, size_t idx, uint8_t elt)
    596 {
    597  TRUNNEL_DYNARRAY_SET(&inp->encrypted, idx, elt);
    598  return 0;
    599 }
    600 int
    601 trn_cell_introduce1_add_encrypted(trn_cell_introduce1_t *inp, uint8_t elt)
    602 {
    603  TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->encrypted, elt, {});
    604  return 0;
    605 trunnel_alloc_failed:
    606  TRUNNEL_SET_ERROR_CODE(inp);
    607  return -1;
    608 }
    609 
    610 uint8_t *
    611 trn_cell_introduce1_getarray_encrypted(trn_cell_introduce1_t *inp)
    612 {
    613  return inp->encrypted.elts_;
    614 }
    615 const uint8_t  *
    616 trn_cell_introduce1_getconstarray_encrypted(const trn_cell_introduce1_t *inp)
    617 {
    618  return (const uint8_t  *)trn_cell_introduce1_getarray_encrypted((trn_cell_introduce1_t*)inp);
    619 }
    620 int
    621 trn_cell_introduce1_setlen_encrypted(trn_cell_introduce1_t *inp, size_t newlen)
    622 {
    623  uint8_t *newptr;
    624  newptr = trunnel_dynarray_setlen(&inp->encrypted.allocated_,
    625                 &inp->encrypted.n_, inp->encrypted.elts_, newlen,
    626                 sizeof(inp->encrypted.elts_[0]), (trunnel_free_fn_t) NULL,
    627                 &inp->trunnel_error_code_);
    628  if (newlen != 0 && newptr == NULL)
    629    goto trunnel_alloc_failed;
    630  inp->encrypted.elts_ = newptr;
    631  return 0;
    632 trunnel_alloc_failed:
    633  TRUNNEL_SET_ERROR_CODE(inp);
    634  return -1;
    635 }
    636 const char *
    637 trn_cell_introduce1_check(const trn_cell_introduce1_t *obj)
    638 {
    639  if (obj == NULL)
    640    return "Object was NULL";
    641  if (obj->trunnel_error_code_)
    642    return "A set function failed on this object";
    643  if (! (obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1))
    644    return "Integer out of bounds";
    645  if (TRUNNEL_DYNARRAY_LEN(&obj->auth_key) != obj->auth_key_len)
    646    return "Length mismatch for auth_key";
    647  {
    648    const char *msg;
    649    if (NULL != (msg = trn_extension_check(obj->extensions)))
    650      return msg;
    651  }
    652  return NULL;
    653 }
    654 
    655 ssize_t
    656 trn_cell_introduce1_encoded_len(const trn_cell_introduce1_t *obj)
    657 {
    658  ssize_t result = 0;
    659 
    660  if (NULL != trn_cell_introduce1_check(obj))
    661     return -1;
    662 
    663 
    664  /* Length of u8 legacy_key_id[TRUNNEL_SHA1_LEN] */
    665  result += TRUNNEL_SHA1_LEN;
    666 
    667  /* Length of u8 auth_key_type IN [TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1] */
    668  result += 1;
    669 
    670  /* Length of u16 auth_key_len */
    671  result += 2;
    672 
    673  /* Length of u8 auth_key[auth_key_len] */
    674  result += TRUNNEL_DYNARRAY_LEN(&obj->auth_key);
    675 
    676  /* Length of struct trn_extension extensions */
    677  result += trn_extension_encoded_len(obj->extensions);
    678 
    679  /* Length of u8 encrypted[] */
    680  result += TRUNNEL_DYNARRAY_LEN(&obj->encrypted);
    681  return result;
    682 }
    683 int
    684 trn_cell_introduce1_clear_errors(trn_cell_introduce1_t *obj)
    685 {
    686  int r = obj->trunnel_error_code_;
    687  obj->trunnel_error_code_ = 0;
    688  return r;
    689 }
    690 ssize_t
    691 trn_cell_introduce1_encode(uint8_t *output, const size_t avail, const trn_cell_introduce1_t *obj)
    692 {
    693  ssize_t result = 0;
    694  size_t written = 0;
    695  uint8_t *ptr = output;
    696  const char *msg;
    697 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    698  const ssize_t encoded_len = trn_cell_introduce1_encoded_len(obj);
    699 #endif
    700 
    701  if (NULL != (msg = trn_cell_introduce1_check(obj)))
    702    goto check_failed;
    703 
    704 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    705  trunnel_assert(encoded_len >= 0);
    706 #endif
    707 
    708  /* Encode u8 legacy_key_id[TRUNNEL_SHA1_LEN] */
    709  trunnel_assert(written <= avail);
    710  if (avail - written < TRUNNEL_SHA1_LEN)
    711    goto truncated;
    712  memcpy(ptr, obj->legacy_key_id, TRUNNEL_SHA1_LEN);
    713  written += TRUNNEL_SHA1_LEN; ptr += TRUNNEL_SHA1_LEN;
    714 
    715  /* Encode u8 auth_key_type IN [TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1] */
    716  trunnel_assert(written <= avail);
    717  if (avail - written < 1)
    718    goto truncated;
    719  trunnel_set_uint8(ptr, (obj->auth_key_type));
    720  written += 1; ptr += 1;
    721 
    722  /* Encode u16 auth_key_len */
    723  trunnel_assert(written <= avail);
    724  if (avail - written < 2)
    725    goto truncated;
    726  trunnel_set_uint16(ptr, trunnel_htons(obj->auth_key_len));
    727  written += 2; ptr += 2;
    728 
    729  /* Encode u8 auth_key[auth_key_len] */
    730  {
    731    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->auth_key);
    732    trunnel_assert(obj->auth_key_len == elt_len);
    733    trunnel_assert(written <= avail);
    734    if (avail - written < elt_len)
    735      goto truncated;
    736    if (elt_len)
    737      memcpy(ptr, obj->auth_key.elts_, elt_len);
    738    written += elt_len; ptr += elt_len;
    739  }
    740 
    741  /* Encode struct trn_extension extensions */
    742  trunnel_assert(written <= avail);
    743  result = trn_extension_encode(ptr, avail - written, obj->extensions);
    744  if (result < 0)
    745    goto fail; /* XXXXXXX !*/
    746  written += result; ptr += result;
    747 
    748  /* Encode u8 encrypted[] */
    749  {
    750    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->encrypted);
    751    trunnel_assert(written <= avail);
    752    if (avail - written < elt_len)
    753      goto truncated;
    754    if (elt_len)
    755      memcpy(ptr, obj->encrypted.elts_, elt_len);
    756    written += elt_len; ptr += elt_len;
    757  }
    758 
    759 
    760  trunnel_assert(ptr == output + written);
    761 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    762  {
    763    trunnel_assert(encoded_len >= 0);
    764    trunnel_assert((size_t)encoded_len == written);
    765  }
    766 
    767 #endif
    768 
    769  return written;
    770 
    771 truncated:
    772  result = -2;
    773  goto fail;
    774 check_failed:
    775  (void)msg;
    776  result = -1;
    777  goto fail;
    778 fail:
    779  trunnel_assert(result < 0);
    780  return result;
    781 }
    782 
    783 /** As trn_cell_introduce1_parse(), but do not allocate the output
    784 * object.
    785 */
    786 static ssize_t
    787 trn_cell_introduce1_parse_into(trn_cell_introduce1_t *obj, const uint8_t *input, const size_t len_in)
    788 {
    789  const uint8_t *ptr = input;
    790  size_t remaining = len_in;
    791  ssize_t result = 0;
    792  (void)result;
    793 
    794  /* Parse u8 legacy_key_id[TRUNNEL_SHA1_LEN] */
    795  CHECK_REMAINING(TRUNNEL_SHA1_LEN, truncated);
    796  memcpy(obj->legacy_key_id, ptr, TRUNNEL_SHA1_LEN);
    797  remaining -= TRUNNEL_SHA1_LEN; ptr += TRUNNEL_SHA1_LEN;
    798 
    799  /* Parse u8 auth_key_type IN [TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1] */
    800  CHECK_REMAINING(1, truncated);
    801  obj->auth_key_type = (trunnel_get_uint8(ptr));
    802  remaining -= 1; ptr += 1;
    803  if (! (obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1))
    804    goto fail;
    805 
    806  /* Parse u16 auth_key_len */
    807  CHECK_REMAINING(2, truncated);
    808  obj->auth_key_len = trunnel_ntohs(trunnel_get_uint16(ptr));
    809  remaining -= 2; ptr += 2;
    810 
    811  /* Parse u8 auth_key[auth_key_len] */
    812  CHECK_REMAINING(obj->auth_key_len, truncated);
    813  TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->auth_key, obj->auth_key_len, {});
    814  obj->auth_key.n_ = obj->auth_key_len;
    815  if (obj->auth_key_len)
    816    memcpy(obj->auth_key.elts_, ptr, obj->auth_key_len);
    817  ptr += obj->auth_key_len; remaining -= obj->auth_key_len;
    818 
    819  /* Parse struct trn_extension extensions */
    820  result = trn_extension_parse(&obj->extensions, ptr, remaining);
    821  if (result < 0)
    822    goto relay_fail;
    823  trunnel_assert((size_t)result <= remaining);
    824  remaining -= result; ptr += result;
    825 
    826  /* Parse u8 encrypted[] */
    827  TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->encrypted, remaining, {});
    828  obj->encrypted.n_ = remaining;
    829  if (remaining)
    830    memcpy(obj->encrypted.elts_, ptr, remaining);
    831  ptr += remaining; remaining -= remaining;
    832  trunnel_assert(ptr + remaining == input + len_in);
    833  return len_in - remaining;
    834 
    835 truncated:
    836  return -2;
    837 relay_fail:
    838  trunnel_assert(result < 0);
    839  return result;
    840 trunnel_alloc_failed:
    841  return -1;
    842 fail:
    843  result = -1;
    844  return result;
    845 }
    846 
    847 ssize_t
    848 trn_cell_introduce1_parse(trn_cell_introduce1_t **output, const uint8_t *input, const size_t len_in)
    849 {
    850  ssize_t result;
    851  *output = trn_cell_introduce1_new();
    852  if (NULL == *output)
    853    return -1;
    854  result = trn_cell_introduce1_parse_into(*output, input, len_in);
    855  if (result < 0) {
    856    trn_cell_introduce1_free(*output);
    857    *output = NULL;
    858  }
    859  return result;
    860 }
    861 trn_cell_introduce_ack_t *
    862 trn_cell_introduce_ack_new(void)
    863 {
    864  trn_cell_introduce_ack_t *val = trunnel_calloc(1, sizeof(trn_cell_introduce_ack_t));
    865  if (NULL == val)
    866    return NULL;
    867  return val;
    868 }
    869 
    870 /** Release all storage held inside 'obj', but do not free 'obj'.
    871 */
    872 static void
    873 trn_cell_introduce_ack_clear(trn_cell_introduce_ack_t *obj)
    874 {
    875  (void) obj;
    876  trn_extension_free(obj->extensions);
    877  obj->extensions = NULL;
    878 }
    879 
    880 void
    881 trn_cell_introduce_ack_free(trn_cell_introduce_ack_t *obj)
    882 {
    883  if (obj == NULL)
    884    return;
    885  trn_cell_introduce_ack_clear(obj);
    886  trunnel_memwipe(obj, sizeof(trn_cell_introduce_ack_t));
    887  trunnel_free_(obj);
    888 }
    889 
    890 uint16_t
    891 trn_cell_introduce_ack_get_status(const trn_cell_introduce_ack_t *inp)
    892 {
    893  return inp->status;
    894 }
    895 int
    896 trn_cell_introduce_ack_set_status(trn_cell_introduce_ack_t *inp, uint16_t val)
    897 {
    898  inp->status = val;
    899  return 0;
    900 }
    901 struct trn_extension_st *
    902 trn_cell_introduce_ack_get_extensions(trn_cell_introduce_ack_t *inp)
    903 {
    904  return inp->extensions;
    905 }
    906 const struct trn_extension_st *
    907 trn_cell_introduce_ack_getconst_extensions(const trn_cell_introduce_ack_t *inp)
    908 {
    909  return trn_cell_introduce_ack_get_extensions((trn_cell_introduce_ack_t*) inp);
    910 }
    911 int
    912 trn_cell_introduce_ack_set_extensions(trn_cell_introduce_ack_t *inp, struct trn_extension_st *val)
    913 {
    914  if (inp->extensions && inp->extensions != val)
    915    trn_extension_free(inp->extensions);
    916  return trn_cell_introduce_ack_set0_extensions(inp, val);
    917 }
    918 int
    919 trn_cell_introduce_ack_set0_extensions(trn_cell_introduce_ack_t *inp, struct trn_extension_st *val)
    920 {
    921  inp->extensions = val;
    922  return 0;
    923 }
    924 const char *
    925 trn_cell_introduce_ack_check(const trn_cell_introduce_ack_t *obj)
    926 {
    927  if (obj == NULL)
    928    return "Object was NULL";
    929  if (obj->trunnel_error_code_)
    930    return "A set function failed on this object";
    931  {
    932    const char *msg;
    933    if (NULL != (msg = trn_extension_check(obj->extensions)))
    934      return msg;
    935  }
    936  return NULL;
    937 }
    938 
    939 ssize_t
    940 trn_cell_introduce_ack_encoded_len(const trn_cell_introduce_ack_t *obj)
    941 {
    942  ssize_t result = 0;
    943 
    944  if (NULL != trn_cell_introduce_ack_check(obj))
    945     return -1;
    946 
    947 
    948  /* Length of u16 status */
    949  result += 2;
    950 
    951  /* Length of struct trn_extension extensions */
    952  result += trn_extension_encoded_len(obj->extensions);
    953  return result;
    954 }
    955 int
    956 trn_cell_introduce_ack_clear_errors(trn_cell_introduce_ack_t *obj)
    957 {
    958  int r = obj->trunnel_error_code_;
    959  obj->trunnel_error_code_ = 0;
    960  return r;
    961 }
    962 ssize_t
    963 trn_cell_introduce_ack_encode(uint8_t *output, const size_t avail, const trn_cell_introduce_ack_t *obj)
    964 {
    965  ssize_t result = 0;
    966  size_t written = 0;
    967  uint8_t *ptr = output;
    968  const char *msg;
    969 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    970  const ssize_t encoded_len = trn_cell_introduce_ack_encoded_len(obj);
    971 #endif
    972 
    973  if (NULL != (msg = trn_cell_introduce_ack_check(obj)))
    974    goto check_failed;
    975 
    976 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    977  trunnel_assert(encoded_len >= 0);
    978 #endif
    979 
    980  /* Encode u16 status */
    981  trunnel_assert(written <= avail);
    982  if (avail - written < 2)
    983    goto truncated;
    984  trunnel_set_uint16(ptr, trunnel_htons(obj->status));
    985  written += 2; ptr += 2;
    986 
    987  /* Encode struct trn_extension extensions */
    988  trunnel_assert(written <= avail);
    989  result = trn_extension_encode(ptr, avail - written, obj->extensions);
    990  if (result < 0)
    991    goto fail; /* XXXXXXX !*/
    992  written += result; ptr += result;
    993 
    994 
    995  trunnel_assert(ptr == output + written);
    996 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    997  {
    998    trunnel_assert(encoded_len >= 0);
    999    trunnel_assert((size_t)encoded_len == written);
   1000  }
   1001 
   1002 #endif
   1003 
   1004  return written;
   1005 
   1006 truncated:
   1007  result = -2;
   1008  goto fail;
   1009 check_failed:
   1010  (void)msg;
   1011  result = -1;
   1012  goto fail;
   1013 fail:
   1014  trunnel_assert(result < 0);
   1015  return result;
   1016 }
   1017 
   1018 /** As trn_cell_introduce_ack_parse(), but do not allocate the output
   1019 * object.
   1020 */
   1021 static ssize_t
   1022 trn_cell_introduce_ack_parse_into(trn_cell_introduce_ack_t *obj, const uint8_t *input, const size_t len_in)
   1023 {
   1024  const uint8_t *ptr = input;
   1025  size_t remaining = len_in;
   1026  ssize_t result = 0;
   1027  (void)result;
   1028 
   1029  /* Parse u16 status */
   1030  CHECK_REMAINING(2, truncated);
   1031  obj->status = trunnel_ntohs(trunnel_get_uint16(ptr));
   1032  remaining -= 2; ptr += 2;
   1033 
   1034  /* Parse struct trn_extension extensions */
   1035  result = trn_extension_parse(&obj->extensions, ptr, remaining);
   1036  if (result < 0)
   1037    goto relay_fail;
   1038  trunnel_assert((size_t)result <= remaining);
   1039  remaining -= result; ptr += result;
   1040  trunnel_assert(ptr + remaining == input + len_in);
   1041  return len_in - remaining;
   1042 
   1043 truncated:
   1044  return -2;
   1045 relay_fail:
   1046  trunnel_assert(result < 0);
   1047  return result;
   1048 }
   1049 
   1050 ssize_t
   1051 trn_cell_introduce_ack_parse(trn_cell_introduce_ack_t **output, const uint8_t *input, const size_t len_in)
   1052 {
   1053  ssize_t result;
   1054  *output = trn_cell_introduce_ack_new();
   1055  if (NULL == *output)
   1056    return -1;
   1057  result = trn_cell_introduce_ack_parse_into(*output, input, len_in);
   1058  if (result < 0) {
   1059    trn_cell_introduce_ack_free(*output);
   1060    *output = NULL;
   1061  }
   1062  return result;
   1063 }
   1064 trn_cell_introduce_encrypted_t *
   1065 trn_cell_introduce_encrypted_new(void)
   1066 {
   1067  trn_cell_introduce_encrypted_t *val = trunnel_calloc(1, sizeof(trn_cell_introduce_encrypted_t));
   1068  if (NULL == val)
   1069    return NULL;
   1070  val->onion_key_type = TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR;
   1071  return val;
   1072 }
   1073 
   1074 /** Release all storage held inside 'obj', but do not free 'obj'.
   1075 */
   1076 static void
   1077 trn_cell_introduce_encrypted_clear(trn_cell_introduce_encrypted_t *obj)
   1078 {
   1079  (void) obj;
   1080  trn_extension_free(obj->extensions);
   1081  obj->extensions = NULL;
   1082  TRUNNEL_DYNARRAY_WIPE(&obj->onion_key);
   1083  TRUNNEL_DYNARRAY_CLEAR(&obj->onion_key);
   1084  {
   1085 
   1086    unsigned idx;
   1087    for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->nspecs); ++idx) {
   1088      link_specifier_free(TRUNNEL_DYNARRAY_GET(&obj->nspecs, idx));
   1089    }
   1090  }
   1091  TRUNNEL_DYNARRAY_WIPE(&obj->nspecs);
   1092  TRUNNEL_DYNARRAY_CLEAR(&obj->nspecs);
   1093  TRUNNEL_DYNARRAY_WIPE(&obj->pad);
   1094  TRUNNEL_DYNARRAY_CLEAR(&obj->pad);
   1095 }
   1096 
   1097 void
   1098 trn_cell_introduce_encrypted_free(trn_cell_introduce_encrypted_t *obj)
   1099 {
   1100  if (obj == NULL)
   1101    return;
   1102  trn_cell_introduce_encrypted_clear(obj);
   1103  trunnel_memwipe(obj, sizeof(trn_cell_introduce_encrypted_t));
   1104  trunnel_free_(obj);
   1105 }
   1106 
   1107 size_t
   1108 trn_cell_introduce_encrypted_getlen_rend_cookie(const trn_cell_introduce_encrypted_t *inp)
   1109 {
   1110  (void)inp;  return TRUNNEL_REND_COOKIE_LEN;
   1111 }
   1112 
   1113 uint8_t
   1114 trn_cell_introduce_encrypted_get_rend_cookie(trn_cell_introduce_encrypted_t *inp, size_t idx)
   1115 {
   1116  trunnel_assert(idx < TRUNNEL_REND_COOKIE_LEN);
   1117  return inp->rend_cookie[idx];
   1118 }
   1119 
   1120 uint8_t
   1121 trn_cell_introduce_encrypted_getconst_rend_cookie(const trn_cell_introduce_encrypted_t *inp, size_t idx)
   1122 {
   1123  return trn_cell_introduce_encrypted_get_rend_cookie((trn_cell_introduce_encrypted_t*)inp, idx);
   1124 }
   1125 int
   1126 trn_cell_introduce_encrypted_set_rend_cookie(trn_cell_introduce_encrypted_t *inp, size_t idx, uint8_t elt)
   1127 {
   1128  trunnel_assert(idx < TRUNNEL_REND_COOKIE_LEN);
   1129  inp->rend_cookie[idx] = elt;
   1130  return 0;
   1131 }
   1132 
   1133 uint8_t *
   1134 trn_cell_introduce_encrypted_getarray_rend_cookie(trn_cell_introduce_encrypted_t *inp)
   1135 {
   1136  return inp->rend_cookie;
   1137 }
   1138 const uint8_t  *
   1139 trn_cell_introduce_encrypted_getconstarray_rend_cookie(const trn_cell_introduce_encrypted_t *inp)
   1140 {
   1141  return (const uint8_t  *)trn_cell_introduce_encrypted_getarray_rend_cookie((trn_cell_introduce_encrypted_t*)inp);
   1142 }
   1143 struct trn_extension_st *
   1144 trn_cell_introduce_encrypted_get_extensions(trn_cell_introduce_encrypted_t *inp)
   1145 {
   1146  return inp->extensions;
   1147 }
   1148 const struct trn_extension_st *
   1149 trn_cell_introduce_encrypted_getconst_extensions(const trn_cell_introduce_encrypted_t *inp)
   1150 {
   1151  return trn_cell_introduce_encrypted_get_extensions((trn_cell_introduce_encrypted_t*) inp);
   1152 }
   1153 int
   1154 trn_cell_introduce_encrypted_set_extensions(trn_cell_introduce_encrypted_t *inp, struct trn_extension_st *val)
   1155 {
   1156  if (inp->extensions && inp->extensions != val)
   1157    trn_extension_free(inp->extensions);
   1158  return trn_cell_introduce_encrypted_set0_extensions(inp, val);
   1159 }
   1160 int
   1161 trn_cell_introduce_encrypted_set0_extensions(trn_cell_introduce_encrypted_t *inp, struct trn_extension_st *val)
   1162 {
   1163  inp->extensions = val;
   1164  return 0;
   1165 }
   1166 uint8_t
   1167 trn_cell_introduce_encrypted_get_onion_key_type(const trn_cell_introduce_encrypted_t *inp)
   1168 {
   1169  return inp->onion_key_type;
   1170 }
   1171 int
   1172 trn_cell_introduce_encrypted_set_onion_key_type(trn_cell_introduce_encrypted_t *inp, uint8_t val)
   1173 {
   1174  if (! ((val == TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR))) {
   1175     TRUNNEL_SET_ERROR_CODE(inp);
   1176     return -1;
   1177  }
   1178  inp->onion_key_type = val;
   1179  return 0;
   1180 }
   1181 uint16_t
   1182 trn_cell_introduce_encrypted_get_onion_key_len(const trn_cell_introduce_encrypted_t *inp)
   1183 {
   1184  return inp->onion_key_len;
   1185 }
   1186 int
   1187 trn_cell_introduce_encrypted_set_onion_key_len(trn_cell_introduce_encrypted_t *inp, uint16_t val)
   1188 {
   1189  inp->onion_key_len = val;
   1190  return 0;
   1191 }
   1192 size_t
   1193 trn_cell_introduce_encrypted_getlen_onion_key(const trn_cell_introduce_encrypted_t *inp)
   1194 {
   1195  return TRUNNEL_DYNARRAY_LEN(&inp->onion_key);
   1196 }
   1197 
   1198 uint8_t
   1199 trn_cell_introduce_encrypted_get_onion_key(trn_cell_introduce_encrypted_t *inp, size_t idx)
   1200 {
   1201  return TRUNNEL_DYNARRAY_GET(&inp->onion_key, idx);
   1202 }
   1203 
   1204 uint8_t
   1205 trn_cell_introduce_encrypted_getconst_onion_key(const trn_cell_introduce_encrypted_t *inp, size_t idx)
   1206 {
   1207  return trn_cell_introduce_encrypted_get_onion_key((trn_cell_introduce_encrypted_t*)inp, idx);
   1208 }
   1209 int
   1210 trn_cell_introduce_encrypted_set_onion_key(trn_cell_introduce_encrypted_t *inp, size_t idx, uint8_t elt)
   1211 {
   1212  TRUNNEL_DYNARRAY_SET(&inp->onion_key, idx, elt);
   1213  return 0;
   1214 }
   1215 int
   1216 trn_cell_introduce_encrypted_add_onion_key(trn_cell_introduce_encrypted_t *inp, uint8_t elt)
   1217 {
   1218 #if SIZE_MAX >= UINT16_MAX
   1219  if (inp->onion_key.n_ == UINT16_MAX)
   1220    goto trunnel_alloc_failed;
   1221 #endif
   1222  TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->onion_key, elt, {});
   1223  return 0;
   1224 trunnel_alloc_failed:
   1225  TRUNNEL_SET_ERROR_CODE(inp);
   1226  return -1;
   1227 }
   1228 
   1229 uint8_t *
   1230 trn_cell_introduce_encrypted_getarray_onion_key(trn_cell_introduce_encrypted_t *inp)
   1231 {
   1232  return inp->onion_key.elts_;
   1233 }
   1234 const uint8_t  *
   1235 trn_cell_introduce_encrypted_getconstarray_onion_key(const trn_cell_introduce_encrypted_t *inp)
   1236 {
   1237  return (const uint8_t  *)trn_cell_introduce_encrypted_getarray_onion_key((trn_cell_introduce_encrypted_t*)inp);
   1238 }
   1239 int
   1240 trn_cell_introduce_encrypted_setlen_onion_key(trn_cell_introduce_encrypted_t *inp, size_t newlen)
   1241 {
   1242  uint8_t *newptr;
   1243 #if UINT16_MAX < SIZE_MAX
   1244  if (newlen > UINT16_MAX)
   1245    goto trunnel_alloc_failed;
   1246 #endif
   1247  newptr = trunnel_dynarray_setlen(&inp->onion_key.allocated_,
   1248                 &inp->onion_key.n_, inp->onion_key.elts_, newlen,
   1249                 sizeof(inp->onion_key.elts_[0]), (trunnel_free_fn_t) NULL,
   1250                 &inp->trunnel_error_code_);
   1251  if (newlen != 0 && newptr == NULL)
   1252    goto trunnel_alloc_failed;
   1253  inp->onion_key.elts_ = newptr;
   1254  return 0;
   1255 trunnel_alloc_failed:
   1256  TRUNNEL_SET_ERROR_CODE(inp);
   1257  return -1;
   1258 }
   1259 uint8_t
   1260 trn_cell_introduce_encrypted_get_nspec(const trn_cell_introduce_encrypted_t *inp)
   1261 {
   1262  return inp->nspec;
   1263 }
   1264 int
   1265 trn_cell_introduce_encrypted_set_nspec(trn_cell_introduce_encrypted_t *inp, uint8_t val)
   1266 {
   1267  inp->nspec = val;
   1268  return 0;
   1269 }
   1270 size_t
   1271 trn_cell_introduce_encrypted_getlen_nspecs(const trn_cell_introduce_encrypted_t *inp)
   1272 {
   1273  return TRUNNEL_DYNARRAY_LEN(&inp->nspecs);
   1274 }
   1275 
   1276 struct link_specifier_st *
   1277 trn_cell_introduce_encrypted_get_nspecs(trn_cell_introduce_encrypted_t *inp, size_t idx)
   1278 {
   1279  return TRUNNEL_DYNARRAY_GET(&inp->nspecs, idx);
   1280 }
   1281 
   1282 const struct link_specifier_st *
   1283 trn_cell_introduce_encrypted_getconst_nspecs(const trn_cell_introduce_encrypted_t *inp, size_t idx)
   1284 {
   1285  return trn_cell_introduce_encrypted_get_nspecs((trn_cell_introduce_encrypted_t*)inp, idx);
   1286 }
   1287 int
   1288 trn_cell_introduce_encrypted_set_nspecs(trn_cell_introduce_encrypted_t *inp, size_t idx, struct link_specifier_st * elt)
   1289 {
   1290  link_specifier_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->nspecs, idx);
   1291  if (oldval && oldval != elt)
   1292    link_specifier_free(oldval);
   1293  return trn_cell_introduce_encrypted_set0_nspecs(inp, idx, elt);
   1294 }
   1295 int
   1296 trn_cell_introduce_encrypted_set0_nspecs(trn_cell_introduce_encrypted_t *inp, size_t idx, struct link_specifier_st * elt)
   1297 {
   1298  TRUNNEL_DYNARRAY_SET(&inp->nspecs, idx, elt);
   1299  return 0;
   1300 }
   1301 int
   1302 trn_cell_introduce_encrypted_add_nspecs(trn_cell_introduce_encrypted_t *inp, struct link_specifier_st * elt)
   1303 {
   1304 #if SIZE_MAX >= UINT8_MAX
   1305  if (inp->nspecs.n_ == UINT8_MAX)
   1306    goto trunnel_alloc_failed;
   1307 #endif
   1308  TRUNNEL_DYNARRAY_ADD(struct link_specifier_st *, &inp->nspecs, elt, {});
   1309  return 0;
   1310 trunnel_alloc_failed:
   1311  TRUNNEL_SET_ERROR_CODE(inp);
   1312  return -1;
   1313 }
   1314 
   1315 struct link_specifier_st * *
   1316 trn_cell_introduce_encrypted_getarray_nspecs(trn_cell_introduce_encrypted_t *inp)
   1317 {
   1318  return inp->nspecs.elts_;
   1319 }
   1320 const struct link_specifier_st *  const  *
   1321 trn_cell_introduce_encrypted_getconstarray_nspecs(const trn_cell_introduce_encrypted_t *inp)
   1322 {
   1323  return (const struct link_specifier_st *  const  *)trn_cell_introduce_encrypted_getarray_nspecs((trn_cell_introduce_encrypted_t*)inp);
   1324 }
   1325 int
   1326 trn_cell_introduce_encrypted_setlen_nspecs(trn_cell_introduce_encrypted_t *inp, size_t newlen)
   1327 {
   1328  struct link_specifier_st * *newptr;
   1329 #if UINT8_MAX < SIZE_MAX
   1330  if (newlen > UINT8_MAX)
   1331    goto trunnel_alloc_failed;
   1332 #endif
   1333  newptr = trunnel_dynarray_setlen(&inp->nspecs.allocated_,
   1334                 &inp->nspecs.n_, inp->nspecs.elts_, newlen,
   1335                 sizeof(inp->nspecs.elts_[0]), (trunnel_free_fn_t) link_specifier_free,
   1336                 &inp->trunnel_error_code_);
   1337  if (newlen != 0 && newptr == NULL)
   1338    goto trunnel_alloc_failed;
   1339  inp->nspecs.elts_ = newptr;
   1340  return 0;
   1341 trunnel_alloc_failed:
   1342  TRUNNEL_SET_ERROR_CODE(inp);
   1343  return -1;
   1344 }
   1345 size_t
   1346 trn_cell_introduce_encrypted_getlen_pad(const trn_cell_introduce_encrypted_t *inp)
   1347 {
   1348  return TRUNNEL_DYNARRAY_LEN(&inp->pad);
   1349 }
   1350 
   1351 uint8_t
   1352 trn_cell_introduce_encrypted_get_pad(trn_cell_introduce_encrypted_t *inp, size_t idx)
   1353 {
   1354  return TRUNNEL_DYNARRAY_GET(&inp->pad, idx);
   1355 }
   1356 
   1357 uint8_t
   1358 trn_cell_introduce_encrypted_getconst_pad(const trn_cell_introduce_encrypted_t *inp, size_t idx)
   1359 {
   1360  return trn_cell_introduce_encrypted_get_pad((trn_cell_introduce_encrypted_t*)inp, idx);
   1361 }
   1362 int
   1363 trn_cell_introduce_encrypted_set_pad(trn_cell_introduce_encrypted_t *inp, size_t idx, uint8_t elt)
   1364 {
   1365  TRUNNEL_DYNARRAY_SET(&inp->pad, idx, elt);
   1366  return 0;
   1367 }
   1368 int
   1369 trn_cell_introduce_encrypted_add_pad(trn_cell_introduce_encrypted_t *inp, uint8_t elt)
   1370 {
   1371  TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->pad, elt, {});
   1372  return 0;
   1373 trunnel_alloc_failed:
   1374  TRUNNEL_SET_ERROR_CODE(inp);
   1375  return -1;
   1376 }
   1377 
   1378 uint8_t *
   1379 trn_cell_introduce_encrypted_getarray_pad(trn_cell_introduce_encrypted_t *inp)
   1380 {
   1381  return inp->pad.elts_;
   1382 }
   1383 const uint8_t  *
   1384 trn_cell_introduce_encrypted_getconstarray_pad(const trn_cell_introduce_encrypted_t *inp)
   1385 {
   1386  return (const uint8_t  *)trn_cell_introduce_encrypted_getarray_pad((trn_cell_introduce_encrypted_t*)inp);
   1387 }
   1388 int
   1389 trn_cell_introduce_encrypted_setlen_pad(trn_cell_introduce_encrypted_t *inp, size_t newlen)
   1390 {
   1391  uint8_t *newptr;
   1392  newptr = trunnel_dynarray_setlen(&inp->pad.allocated_,
   1393                 &inp->pad.n_, inp->pad.elts_, newlen,
   1394                 sizeof(inp->pad.elts_[0]), (trunnel_free_fn_t) NULL,
   1395                 &inp->trunnel_error_code_);
   1396  if (newlen != 0 && newptr == NULL)
   1397    goto trunnel_alloc_failed;
   1398  inp->pad.elts_ = newptr;
   1399  return 0;
   1400 trunnel_alloc_failed:
   1401  TRUNNEL_SET_ERROR_CODE(inp);
   1402  return -1;
   1403 }
   1404 const char *
   1405 trn_cell_introduce_encrypted_check(const trn_cell_introduce_encrypted_t *obj)
   1406 {
   1407  if (obj == NULL)
   1408    return "Object was NULL";
   1409  if (obj->trunnel_error_code_)
   1410    return "A set function failed on this object";
   1411  {
   1412    const char *msg;
   1413    if (NULL != (msg = trn_extension_check(obj->extensions)))
   1414      return msg;
   1415  }
   1416  if (! (obj->onion_key_type == TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR))
   1417    return "Integer out of bounds";
   1418  if (TRUNNEL_DYNARRAY_LEN(&obj->onion_key) != obj->onion_key_len)
   1419    return "Length mismatch for onion_key";
   1420  {
   1421    const char *msg;
   1422 
   1423    unsigned idx;
   1424    for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->nspecs); ++idx) {
   1425      if (NULL != (msg = link_specifier_check(TRUNNEL_DYNARRAY_GET(&obj->nspecs, idx))))
   1426        return msg;
   1427    }
   1428  }
   1429  if (TRUNNEL_DYNARRAY_LEN(&obj->nspecs) != obj->nspec)
   1430    return "Length mismatch for nspecs";
   1431  return NULL;
   1432 }
   1433 
   1434 ssize_t
   1435 trn_cell_introduce_encrypted_encoded_len(const trn_cell_introduce_encrypted_t *obj)
   1436 {
   1437  ssize_t result = 0;
   1438 
   1439  if (NULL != trn_cell_introduce_encrypted_check(obj))
   1440     return -1;
   1441 
   1442 
   1443  /* Length of u8 rend_cookie[TRUNNEL_REND_COOKIE_LEN] */
   1444  result += TRUNNEL_REND_COOKIE_LEN;
   1445 
   1446  /* Length of struct trn_extension extensions */
   1447  result += trn_extension_encoded_len(obj->extensions);
   1448 
   1449  /* Length of u8 onion_key_type IN [TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR] */
   1450  result += 1;
   1451 
   1452  /* Length of u16 onion_key_len */
   1453  result += 2;
   1454 
   1455  /* Length of u8 onion_key[onion_key_len] */
   1456  result += TRUNNEL_DYNARRAY_LEN(&obj->onion_key);
   1457 
   1458  /* Length of u8 nspec */
   1459  result += 1;
   1460 
   1461  /* Length of struct link_specifier nspecs[nspec] */
   1462  {
   1463 
   1464    unsigned idx;
   1465    for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->nspecs); ++idx) {
   1466      result += link_specifier_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->nspecs, idx));
   1467    }
   1468  }
   1469 
   1470  /* Length of u8 pad[] */
   1471  result += TRUNNEL_DYNARRAY_LEN(&obj->pad);
   1472  return result;
   1473 }
   1474 int
   1475 trn_cell_introduce_encrypted_clear_errors(trn_cell_introduce_encrypted_t *obj)
   1476 {
   1477  int r = obj->trunnel_error_code_;
   1478  obj->trunnel_error_code_ = 0;
   1479  return r;
   1480 }
   1481 ssize_t
   1482 trn_cell_introduce_encrypted_encode(uint8_t *output, const size_t avail, const trn_cell_introduce_encrypted_t *obj)
   1483 {
   1484  ssize_t result = 0;
   1485  size_t written = 0;
   1486  uint8_t *ptr = output;
   1487  const char *msg;
   1488 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1489  const ssize_t encoded_len = trn_cell_introduce_encrypted_encoded_len(obj);
   1490 #endif
   1491 
   1492  if (NULL != (msg = trn_cell_introduce_encrypted_check(obj)))
   1493    goto check_failed;
   1494 
   1495 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1496  trunnel_assert(encoded_len >= 0);
   1497 #endif
   1498 
   1499  /* Encode u8 rend_cookie[TRUNNEL_REND_COOKIE_LEN] */
   1500  trunnel_assert(written <= avail);
   1501  if (avail - written < TRUNNEL_REND_COOKIE_LEN)
   1502    goto truncated;
   1503  memcpy(ptr, obj->rend_cookie, TRUNNEL_REND_COOKIE_LEN);
   1504  written += TRUNNEL_REND_COOKIE_LEN; ptr += TRUNNEL_REND_COOKIE_LEN;
   1505 
   1506  /* Encode struct trn_extension extensions */
   1507  trunnel_assert(written <= avail);
   1508  result = trn_extension_encode(ptr, avail - written, obj->extensions);
   1509  if (result < 0)
   1510    goto fail; /* XXXXXXX !*/
   1511  written += result; ptr += result;
   1512 
   1513  /* Encode u8 onion_key_type IN [TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR] */
   1514  trunnel_assert(written <= avail);
   1515  if (avail - written < 1)
   1516    goto truncated;
   1517  trunnel_set_uint8(ptr, (obj->onion_key_type));
   1518  written += 1; ptr += 1;
   1519 
   1520  /* Encode u16 onion_key_len */
   1521  trunnel_assert(written <= avail);
   1522  if (avail - written < 2)
   1523    goto truncated;
   1524  trunnel_set_uint16(ptr, trunnel_htons(obj->onion_key_len));
   1525  written += 2; ptr += 2;
   1526 
   1527  /* Encode u8 onion_key[onion_key_len] */
   1528  {
   1529    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->onion_key);
   1530    trunnel_assert(obj->onion_key_len == elt_len);
   1531    trunnel_assert(written <= avail);
   1532    if (avail - written < elt_len)
   1533      goto truncated;
   1534    if (elt_len)
   1535      memcpy(ptr, obj->onion_key.elts_, elt_len);
   1536    written += elt_len; ptr += elt_len;
   1537  }
   1538 
   1539  /* Encode u8 nspec */
   1540  trunnel_assert(written <= avail);
   1541  if (avail - written < 1)
   1542    goto truncated;
   1543  trunnel_set_uint8(ptr, (obj->nspec));
   1544  written += 1; ptr += 1;
   1545 
   1546  /* Encode struct link_specifier nspecs[nspec] */
   1547  {
   1548 
   1549    unsigned idx;
   1550    for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->nspecs); ++idx) {
   1551      trunnel_assert(written <= avail);
   1552      result = link_specifier_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->nspecs, idx));
   1553      if (result < 0)
   1554        goto fail; /* XXXXXXX !*/
   1555      written += result; ptr += result;
   1556    }
   1557  }
   1558 
   1559  /* Encode u8 pad[] */
   1560  {
   1561    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->pad);
   1562    trunnel_assert(written <= avail);
   1563    if (avail - written < elt_len)
   1564      goto truncated;
   1565    if (elt_len)
   1566      memcpy(ptr, obj->pad.elts_, elt_len);
   1567    written += elt_len; ptr += elt_len;
   1568  }
   1569 
   1570 
   1571  trunnel_assert(ptr == output + written);
   1572 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1573  {
   1574    trunnel_assert(encoded_len >= 0);
   1575    trunnel_assert((size_t)encoded_len == written);
   1576  }
   1577 
   1578 #endif
   1579 
   1580  return written;
   1581 
   1582 truncated:
   1583  result = -2;
   1584  goto fail;
   1585 check_failed:
   1586  (void)msg;
   1587  result = -1;
   1588  goto fail;
   1589 fail:
   1590  trunnel_assert(result < 0);
   1591  return result;
   1592 }
   1593 
   1594 /** As trn_cell_introduce_encrypted_parse(), but do not allocate the
   1595 * output object.
   1596 */
   1597 static ssize_t
   1598 trn_cell_introduce_encrypted_parse_into(trn_cell_introduce_encrypted_t *obj, const uint8_t *input, const size_t len_in)
   1599 {
   1600  const uint8_t *ptr = input;
   1601  size_t remaining = len_in;
   1602  ssize_t result = 0;
   1603  (void)result;
   1604 
   1605  /* Parse u8 rend_cookie[TRUNNEL_REND_COOKIE_LEN] */
   1606  CHECK_REMAINING(TRUNNEL_REND_COOKIE_LEN, truncated);
   1607  memcpy(obj->rend_cookie, ptr, TRUNNEL_REND_COOKIE_LEN);
   1608  remaining -= TRUNNEL_REND_COOKIE_LEN; ptr += TRUNNEL_REND_COOKIE_LEN;
   1609 
   1610  /* Parse struct trn_extension extensions */
   1611  result = trn_extension_parse(&obj->extensions, ptr, remaining);
   1612  if (result < 0)
   1613    goto relay_fail;
   1614  trunnel_assert((size_t)result <= remaining);
   1615  remaining -= result; ptr += result;
   1616 
   1617  /* Parse u8 onion_key_type IN [TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR] */
   1618  CHECK_REMAINING(1, truncated);
   1619  obj->onion_key_type = (trunnel_get_uint8(ptr));
   1620  remaining -= 1; ptr += 1;
   1621  if (! (obj->onion_key_type == TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR))
   1622    goto fail;
   1623 
   1624  /* Parse u16 onion_key_len */
   1625  CHECK_REMAINING(2, truncated);
   1626  obj->onion_key_len = trunnel_ntohs(trunnel_get_uint16(ptr));
   1627  remaining -= 2; ptr += 2;
   1628 
   1629  /* Parse u8 onion_key[onion_key_len] */
   1630  CHECK_REMAINING(obj->onion_key_len, truncated);
   1631  TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->onion_key, obj->onion_key_len, {});
   1632  obj->onion_key.n_ = obj->onion_key_len;
   1633  if (obj->onion_key_len)
   1634    memcpy(obj->onion_key.elts_, ptr, obj->onion_key_len);
   1635  ptr += obj->onion_key_len; remaining -= obj->onion_key_len;
   1636 
   1637  /* Parse u8 nspec */
   1638  CHECK_REMAINING(1, truncated);
   1639  obj->nspec = (trunnel_get_uint8(ptr));
   1640  remaining -= 1; ptr += 1;
   1641 
   1642  /* Parse struct link_specifier nspecs[nspec] */
   1643  TRUNNEL_DYNARRAY_EXPAND(link_specifier_t *, &obj->nspecs, obj->nspec, {});
   1644  {
   1645    link_specifier_t * elt;
   1646    unsigned idx;
   1647    for (idx = 0; idx < obj->nspec; ++idx) {
   1648      result = link_specifier_parse(&elt, ptr, remaining);
   1649      if (result < 0)
   1650        goto relay_fail;
   1651      trunnel_assert((size_t)result <= remaining);
   1652      remaining -= result; ptr += result;
   1653      TRUNNEL_DYNARRAY_ADD(link_specifier_t *, &obj->nspecs, elt, {link_specifier_free(elt);});
   1654    }
   1655  }
   1656 
   1657  /* Parse u8 pad[] */
   1658  TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->pad, remaining, {});
   1659  obj->pad.n_ = remaining;
   1660  if (remaining)
   1661    memcpy(obj->pad.elts_, ptr, remaining);
   1662  ptr += remaining; remaining -= remaining;
   1663  trunnel_assert(ptr + remaining == input + len_in);
   1664  return len_in - remaining;
   1665 
   1666 truncated:
   1667  return -2;
   1668 relay_fail:
   1669  trunnel_assert(result < 0);
   1670  return result;
   1671 trunnel_alloc_failed:
   1672  return -1;
   1673 fail:
   1674  result = -1;
   1675  return result;
   1676 }
   1677 
   1678 ssize_t
   1679 trn_cell_introduce_encrypted_parse(trn_cell_introduce_encrypted_t **output, const uint8_t *input, const size_t len_in)
   1680 {
   1681  ssize_t result;
   1682  *output = trn_cell_introduce_encrypted_new();
   1683  if (NULL == *output)
   1684    return -1;
   1685  result = trn_cell_introduce_encrypted_parse_into(*output, input, len_in);
   1686  if (result < 0) {
   1687    trn_cell_introduce_encrypted_free(*output);
   1688    *output = NULL;
   1689  }
   1690  return result;
   1691 }