tor

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

link_handshake.c (43614B)


      1 /* link_handshake.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 "link_handshake.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 linkhandshake_deadcode_dummy__ = 0;
     19 #define OR_DEADCODE_DUMMY || linkhandshake_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 auth1_t *
     32 auth1_new(void)
     33 {
     34  auth1_t *val = trunnel_calloc(1, sizeof(auth1_t));
     35  if (NULL == val)
     36    return NULL;
     37  return val;
     38 }
     39 
     40 /** Release all storage held inside 'obj', but do not free 'obj'.
     41 */
     42 static void
     43 auth1_clear(auth1_t *obj)
     44 {
     45  (void) obj;
     46  TRUNNEL_DYNARRAY_WIPE(&obj->sig);
     47  TRUNNEL_DYNARRAY_CLEAR(&obj->sig);
     48 }
     49 
     50 void
     51 auth1_free(auth1_t *obj)
     52 {
     53  if (obj == NULL)
     54    return;
     55  auth1_clear(obj);
     56  trunnel_memwipe(obj, sizeof(auth1_t));
     57  trunnel_free_(obj);
     58 }
     59 
     60 size_t
     61 auth1_getlen_type(const auth1_t *inp)
     62 {
     63  (void)inp;  return 8;
     64 }
     65 
     66 uint8_t
     67 auth1_get_type(auth1_t *inp, size_t idx)
     68 {
     69  trunnel_assert(idx < 8);
     70  return inp->type[idx];
     71 }
     72 
     73 uint8_t
     74 auth1_getconst_type(const auth1_t *inp, size_t idx)
     75 {
     76  return auth1_get_type((auth1_t*)inp, idx);
     77 }
     78 int
     79 auth1_set_type(auth1_t *inp, size_t idx, uint8_t elt)
     80 {
     81  trunnel_assert(idx < 8);
     82  inp->type[idx] = elt;
     83  return 0;
     84 }
     85 
     86 uint8_t *
     87 auth1_getarray_type(auth1_t *inp)
     88 {
     89  return inp->type;
     90 }
     91 const uint8_t  *
     92 auth1_getconstarray_type(const auth1_t *inp)
     93 {
     94  return (const uint8_t  *)auth1_getarray_type((auth1_t*)inp);
     95 }
     96 size_t
     97 auth1_getlen_cid(const auth1_t *inp)
     98 {
     99  (void)inp;  return 32;
    100 }
    101 
    102 uint8_t
    103 auth1_get_cid(auth1_t *inp, size_t idx)
    104 {
    105  trunnel_assert(idx < 32);
    106  return inp->cid[idx];
    107 }
    108 
    109 uint8_t
    110 auth1_getconst_cid(const auth1_t *inp, size_t idx)
    111 {
    112  return auth1_get_cid((auth1_t*)inp, idx);
    113 }
    114 int
    115 auth1_set_cid(auth1_t *inp, size_t idx, uint8_t elt)
    116 {
    117  trunnel_assert(idx < 32);
    118  inp->cid[idx] = elt;
    119  return 0;
    120 }
    121 
    122 uint8_t *
    123 auth1_getarray_cid(auth1_t *inp)
    124 {
    125  return inp->cid;
    126 }
    127 const uint8_t  *
    128 auth1_getconstarray_cid(const auth1_t *inp)
    129 {
    130  return (const uint8_t  *)auth1_getarray_cid((auth1_t*)inp);
    131 }
    132 size_t
    133 auth1_getlen_sid(const auth1_t *inp)
    134 {
    135  (void)inp;  return 32;
    136 }
    137 
    138 uint8_t
    139 auth1_get_sid(auth1_t *inp, size_t idx)
    140 {
    141  trunnel_assert(idx < 32);
    142  return inp->sid[idx];
    143 }
    144 
    145 uint8_t
    146 auth1_getconst_sid(const auth1_t *inp, size_t idx)
    147 {
    148  return auth1_get_sid((auth1_t*)inp, idx);
    149 }
    150 int
    151 auth1_set_sid(auth1_t *inp, size_t idx, uint8_t elt)
    152 {
    153  trunnel_assert(idx < 32);
    154  inp->sid[idx] = elt;
    155  return 0;
    156 }
    157 
    158 uint8_t *
    159 auth1_getarray_sid(auth1_t *inp)
    160 {
    161  return inp->sid;
    162 }
    163 const uint8_t  *
    164 auth1_getconstarray_sid(const auth1_t *inp)
    165 {
    166  return (const uint8_t  *)auth1_getarray_sid((auth1_t*)inp);
    167 }
    168 size_t
    169 auth1_getlen_cid_ed(const auth1_t *inp)
    170 {
    171  (void)inp;  return 32;
    172 }
    173 
    174 uint8_t
    175 auth1_get_cid_ed(auth1_t *inp, size_t idx)
    176 {
    177  trunnel_assert(idx < 32);
    178  return inp->cid_ed[idx];
    179 }
    180 
    181 uint8_t
    182 auth1_getconst_cid_ed(const auth1_t *inp, size_t idx)
    183 {
    184  return auth1_get_cid_ed((auth1_t*)inp, idx);
    185 }
    186 int
    187 auth1_set_cid_ed(auth1_t *inp, size_t idx, uint8_t elt)
    188 {
    189  trunnel_assert(idx < 32);
    190  inp->cid_ed[idx] = elt;
    191  return 0;
    192 }
    193 
    194 uint8_t *
    195 auth1_getarray_cid_ed(auth1_t *inp)
    196 {
    197  return inp->cid_ed;
    198 }
    199 const uint8_t  *
    200 auth1_getconstarray_cid_ed(const auth1_t *inp)
    201 {
    202  return (const uint8_t  *)auth1_getarray_cid_ed((auth1_t*)inp);
    203 }
    204 size_t
    205 auth1_getlen_sid_ed(const auth1_t *inp)
    206 {
    207  (void)inp;  return 32;
    208 }
    209 
    210 uint8_t
    211 auth1_get_sid_ed(auth1_t *inp, size_t idx)
    212 {
    213  trunnel_assert(idx < 32);
    214  return inp->sid_ed[idx];
    215 }
    216 
    217 uint8_t
    218 auth1_getconst_sid_ed(const auth1_t *inp, size_t idx)
    219 {
    220  return auth1_get_sid_ed((auth1_t*)inp, idx);
    221 }
    222 int
    223 auth1_set_sid_ed(auth1_t *inp, size_t idx, uint8_t elt)
    224 {
    225  trunnel_assert(idx < 32);
    226  inp->sid_ed[idx] = elt;
    227  return 0;
    228 }
    229 
    230 uint8_t *
    231 auth1_getarray_sid_ed(auth1_t *inp)
    232 {
    233  return inp->sid_ed;
    234 }
    235 const uint8_t  *
    236 auth1_getconstarray_sid_ed(const auth1_t *inp)
    237 {
    238  return (const uint8_t  *)auth1_getarray_sid_ed((auth1_t*)inp);
    239 }
    240 size_t
    241 auth1_getlen_slog(const auth1_t *inp)
    242 {
    243  (void)inp;  return 32;
    244 }
    245 
    246 uint8_t
    247 auth1_get_slog(auth1_t *inp, size_t idx)
    248 {
    249  trunnel_assert(idx < 32);
    250  return inp->slog[idx];
    251 }
    252 
    253 uint8_t
    254 auth1_getconst_slog(const auth1_t *inp, size_t idx)
    255 {
    256  return auth1_get_slog((auth1_t*)inp, idx);
    257 }
    258 int
    259 auth1_set_slog(auth1_t *inp, size_t idx, uint8_t elt)
    260 {
    261  trunnel_assert(idx < 32);
    262  inp->slog[idx] = elt;
    263  return 0;
    264 }
    265 
    266 uint8_t *
    267 auth1_getarray_slog(auth1_t *inp)
    268 {
    269  return inp->slog;
    270 }
    271 const uint8_t  *
    272 auth1_getconstarray_slog(const auth1_t *inp)
    273 {
    274  return (const uint8_t  *)auth1_getarray_slog((auth1_t*)inp);
    275 }
    276 size_t
    277 auth1_getlen_clog(const auth1_t *inp)
    278 {
    279  (void)inp;  return 32;
    280 }
    281 
    282 uint8_t
    283 auth1_get_clog(auth1_t *inp, size_t idx)
    284 {
    285  trunnel_assert(idx < 32);
    286  return inp->clog[idx];
    287 }
    288 
    289 uint8_t
    290 auth1_getconst_clog(const auth1_t *inp, size_t idx)
    291 {
    292  return auth1_get_clog((auth1_t*)inp, idx);
    293 }
    294 int
    295 auth1_set_clog(auth1_t *inp, size_t idx, uint8_t elt)
    296 {
    297  trunnel_assert(idx < 32);
    298  inp->clog[idx] = elt;
    299  return 0;
    300 }
    301 
    302 uint8_t *
    303 auth1_getarray_clog(auth1_t *inp)
    304 {
    305  return inp->clog;
    306 }
    307 const uint8_t  *
    308 auth1_getconstarray_clog(const auth1_t *inp)
    309 {
    310  return (const uint8_t  *)auth1_getarray_clog((auth1_t*)inp);
    311 }
    312 size_t
    313 auth1_getlen_scert(const auth1_t *inp)
    314 {
    315  (void)inp;  return 32;
    316 }
    317 
    318 uint8_t
    319 auth1_get_scert(auth1_t *inp, size_t idx)
    320 {
    321  trunnel_assert(idx < 32);
    322  return inp->scert[idx];
    323 }
    324 
    325 uint8_t
    326 auth1_getconst_scert(const auth1_t *inp, size_t idx)
    327 {
    328  return auth1_get_scert((auth1_t*)inp, idx);
    329 }
    330 int
    331 auth1_set_scert(auth1_t *inp, size_t idx, uint8_t elt)
    332 {
    333  trunnel_assert(idx < 32);
    334  inp->scert[idx] = elt;
    335  return 0;
    336 }
    337 
    338 uint8_t *
    339 auth1_getarray_scert(auth1_t *inp)
    340 {
    341  return inp->scert;
    342 }
    343 const uint8_t  *
    344 auth1_getconstarray_scert(const auth1_t *inp)
    345 {
    346  return (const uint8_t  *)auth1_getarray_scert((auth1_t*)inp);
    347 }
    348 size_t
    349 auth1_getlen_tlssecrets(const auth1_t *inp)
    350 {
    351  (void)inp;  return 32;
    352 }
    353 
    354 uint8_t
    355 auth1_get_tlssecrets(auth1_t *inp, size_t idx)
    356 {
    357  trunnel_assert(idx < 32);
    358  return inp->tlssecrets[idx];
    359 }
    360 
    361 uint8_t
    362 auth1_getconst_tlssecrets(const auth1_t *inp, size_t idx)
    363 {
    364  return auth1_get_tlssecrets((auth1_t*)inp, idx);
    365 }
    366 int
    367 auth1_set_tlssecrets(auth1_t *inp, size_t idx, uint8_t elt)
    368 {
    369  trunnel_assert(idx < 32);
    370  inp->tlssecrets[idx] = elt;
    371  return 0;
    372 }
    373 
    374 uint8_t *
    375 auth1_getarray_tlssecrets(auth1_t *inp)
    376 {
    377  return inp->tlssecrets;
    378 }
    379 const uint8_t  *
    380 auth1_getconstarray_tlssecrets(const auth1_t *inp)
    381 {
    382  return (const uint8_t  *)auth1_getarray_tlssecrets((auth1_t*)inp);
    383 }
    384 const uint8_t *
    385 auth1_get_end_of_fixed_part(const auth1_t *inp)
    386 {
    387  return inp->end_of_fixed_part;
    388 }
    389 size_t
    390 auth1_getlen_rand(const auth1_t *inp)
    391 {
    392  (void)inp;  return 24;
    393 }
    394 
    395 uint8_t
    396 auth1_get_rand(auth1_t *inp, size_t idx)
    397 {
    398  trunnel_assert(idx < 24);
    399  return inp->rand[idx];
    400 }
    401 
    402 uint8_t
    403 auth1_getconst_rand(const auth1_t *inp, size_t idx)
    404 {
    405  return auth1_get_rand((auth1_t*)inp, idx);
    406 }
    407 int
    408 auth1_set_rand(auth1_t *inp, size_t idx, uint8_t elt)
    409 {
    410  trunnel_assert(idx < 24);
    411  inp->rand[idx] = elt;
    412  return 0;
    413 }
    414 
    415 uint8_t *
    416 auth1_getarray_rand(auth1_t *inp)
    417 {
    418  return inp->rand;
    419 }
    420 const uint8_t  *
    421 auth1_getconstarray_rand(const auth1_t *inp)
    422 {
    423  return (const uint8_t  *)auth1_getarray_rand((auth1_t*)inp);
    424 }
    425 const uint8_t *
    426 auth1_get_end_of_signed(const auth1_t *inp)
    427 {
    428  return inp->end_of_signed;
    429 }
    430 size_t
    431 auth1_getlen_sig(const auth1_t *inp)
    432 {
    433  return TRUNNEL_DYNARRAY_LEN(&inp->sig);
    434 }
    435 
    436 uint8_t
    437 auth1_get_sig(auth1_t *inp, size_t idx)
    438 {
    439  return TRUNNEL_DYNARRAY_GET(&inp->sig, idx);
    440 }
    441 
    442 uint8_t
    443 auth1_getconst_sig(const auth1_t *inp, size_t idx)
    444 {
    445  return auth1_get_sig((auth1_t*)inp, idx);
    446 }
    447 int
    448 auth1_set_sig(auth1_t *inp, size_t idx, uint8_t elt)
    449 {
    450  TRUNNEL_DYNARRAY_SET(&inp->sig, idx, elt);
    451  return 0;
    452 }
    453 int
    454 auth1_add_sig(auth1_t *inp, uint8_t elt)
    455 {
    456  TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->sig, elt, {});
    457  return 0;
    458 trunnel_alloc_failed:
    459  TRUNNEL_SET_ERROR_CODE(inp);
    460  return -1;
    461 }
    462 
    463 uint8_t *
    464 auth1_getarray_sig(auth1_t *inp)
    465 {
    466  return inp->sig.elts_;
    467 }
    468 const uint8_t  *
    469 auth1_getconstarray_sig(const auth1_t *inp)
    470 {
    471  return (const uint8_t  *)auth1_getarray_sig((auth1_t*)inp);
    472 }
    473 int
    474 auth1_setlen_sig(auth1_t *inp, size_t newlen)
    475 {
    476  uint8_t *newptr;
    477  newptr = trunnel_dynarray_setlen(&inp->sig.allocated_,
    478                 &inp->sig.n_, inp->sig.elts_, newlen,
    479                 sizeof(inp->sig.elts_[0]), (trunnel_free_fn_t) NULL,
    480                 &inp->trunnel_error_code_);
    481  if (newlen != 0 && newptr == NULL)
    482    goto trunnel_alloc_failed;
    483  inp->sig.elts_ = newptr;
    484  return 0;
    485 trunnel_alloc_failed:
    486  TRUNNEL_SET_ERROR_CODE(inp);
    487  return -1;
    488 }
    489 const char *
    490 auth1_check(const auth1_t *obj)
    491 {
    492  if (obj == NULL)
    493    return "Object was NULL";
    494  if (obj->trunnel_error_code_)
    495    return "A set function failed on this object";
    496  return NULL;
    497 }
    498 
    499 ssize_t
    500 auth1_encoded_len(const auth1_t *obj)
    501 {
    502  ssize_t result = 0;
    503 
    504  if (NULL != auth1_check(obj))
    505     return -1;
    506 
    507 
    508  /* Length of u8 type[8] */
    509  result += 8;
    510 
    511  /* Length of u8 cid[32] */
    512  result += 32;
    513 
    514  /* Length of u8 sid[32] */
    515  result += 32;
    516 
    517  /* Length of u8 cid_ed[32] */
    518  result += 32;
    519 
    520  /* Length of u8 sid_ed[32] */
    521  result += 32;
    522 
    523  /* Length of u8 slog[32] */
    524  result += 32;
    525 
    526  /* Length of u8 clog[32] */
    527  result += 32;
    528 
    529  /* Length of u8 scert[32] */
    530  result += 32;
    531 
    532  /* Length of u8 tlssecrets[32] */
    533  result += 32;
    534 
    535  /* Length of u8 rand[24] */
    536  result += 24;
    537 
    538  /* Length of u8 sig[] */
    539  result += TRUNNEL_DYNARRAY_LEN(&obj->sig);
    540  return result;
    541 }
    542 int
    543 auth1_clear_errors(auth1_t *obj)
    544 {
    545  int r = obj->trunnel_error_code_;
    546  obj->trunnel_error_code_ = 0;
    547  return r;
    548 }
    549 ssize_t
    550 auth1_encode(uint8_t *output, const size_t avail, const auth1_t *obj)
    551 {
    552  ssize_t result = 0;
    553  size_t written = 0;
    554  uint8_t *ptr = output;
    555  const char *msg;
    556 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    557  const ssize_t encoded_len = auth1_encoded_len(obj);
    558 #endif
    559 
    560  if (NULL != (msg = auth1_check(obj)))
    561    goto check_failed;
    562 
    563 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    564  trunnel_assert(encoded_len >= 0);
    565 #endif
    566 
    567  /* Encode u8 type[8] */
    568  trunnel_assert(written <= avail);
    569  if (avail - written < 8)
    570    goto truncated;
    571  memcpy(ptr, obj->type, 8);
    572  written += 8; ptr += 8;
    573 
    574  /* Encode u8 cid[32] */
    575  trunnel_assert(written <= avail);
    576  if (avail - written < 32)
    577    goto truncated;
    578  memcpy(ptr, obj->cid, 32);
    579  written += 32; ptr += 32;
    580 
    581  /* Encode u8 sid[32] */
    582  trunnel_assert(written <= avail);
    583  if (avail - written < 32)
    584    goto truncated;
    585  memcpy(ptr, obj->sid, 32);
    586  written += 32; ptr += 32;
    587 
    588  /* Encode u8 cid_ed[32] */
    589  trunnel_assert(written <= avail);
    590  if (avail - written < 32)
    591    goto truncated;
    592  memcpy(ptr, obj->cid_ed, 32);
    593  written += 32; ptr += 32;
    594 
    595  /* Encode u8 sid_ed[32] */
    596  trunnel_assert(written <= avail);
    597  if (avail - written < 32)
    598    goto truncated;
    599  memcpy(ptr, obj->sid_ed, 32);
    600  written += 32; ptr += 32;
    601 
    602  /* Encode u8 slog[32] */
    603  trunnel_assert(written <= avail);
    604  if (avail - written < 32)
    605    goto truncated;
    606  memcpy(ptr, obj->slog, 32);
    607  written += 32; ptr += 32;
    608 
    609  /* Encode u8 clog[32] */
    610  trunnel_assert(written <= avail);
    611  if (avail - written < 32)
    612    goto truncated;
    613  memcpy(ptr, obj->clog, 32);
    614  written += 32; ptr += 32;
    615 
    616  /* Encode u8 scert[32] */
    617  trunnel_assert(written <= avail);
    618  if (avail - written < 32)
    619    goto truncated;
    620  memcpy(ptr, obj->scert, 32);
    621  written += 32; ptr += 32;
    622 
    623  /* Encode u8 tlssecrets[32] */
    624  trunnel_assert(written <= avail);
    625  if (avail - written < 32)
    626    goto truncated;
    627  memcpy(ptr, obj->tlssecrets, 32);
    628  written += 32; ptr += 32;
    629 
    630  /* Encode u8 rand[24] */
    631  trunnel_assert(written <= avail);
    632  if (avail - written < 24)
    633    goto truncated;
    634  memcpy(ptr, obj->rand, 24);
    635  written += 24; ptr += 24;
    636 
    637  /* Encode u8 sig[] */
    638  {
    639    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->sig);
    640    trunnel_assert(written <= avail);
    641    if (avail - written < elt_len)
    642      goto truncated;
    643    if (elt_len)
    644      memcpy(ptr, obj->sig.elts_, elt_len);
    645    written += elt_len; ptr += elt_len;
    646  }
    647 
    648 
    649  trunnel_assert(ptr == output + written);
    650 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    651  {
    652    trunnel_assert(encoded_len >= 0);
    653    trunnel_assert((size_t)encoded_len == written);
    654  }
    655 
    656 #endif
    657 
    658  return written;
    659 
    660 truncated:
    661  result = -2;
    662  goto fail;
    663 check_failed:
    664  (void)msg;
    665  result = -1;
    666  goto fail;
    667 fail:
    668  trunnel_assert(result < 0);
    669  return result;
    670 }
    671 
    672 /** As auth1_parse(), but do not allocate the output object.
    673 */
    674 static ssize_t
    675 auth1_parse_into(auth1_t *obj, const uint8_t *input, const size_t len_in)
    676 {
    677  const uint8_t *ptr = input;
    678  size_t remaining = len_in;
    679  ssize_t result = 0;
    680  (void)result;
    681 
    682  /* Parse u8 type[8] */
    683  CHECK_REMAINING(8, truncated);
    684  memcpy(obj->type, ptr, 8);
    685  remaining -= 8; ptr += 8;
    686 
    687  /* Parse u8 cid[32] */
    688  CHECK_REMAINING(32, truncated);
    689  memcpy(obj->cid, ptr, 32);
    690  remaining -= 32; ptr += 32;
    691 
    692  /* Parse u8 sid[32] */
    693  CHECK_REMAINING(32, truncated);
    694  memcpy(obj->sid, ptr, 32);
    695  remaining -= 32; ptr += 32;
    696 
    697  /* Parse u8 cid_ed[32] */
    698  CHECK_REMAINING(32, truncated);
    699  memcpy(obj->cid_ed, ptr, 32);
    700  remaining -= 32; ptr += 32;
    701 
    702  /* Parse u8 sid_ed[32] */
    703  CHECK_REMAINING(32, truncated);
    704  memcpy(obj->sid_ed, ptr, 32);
    705  remaining -= 32; ptr += 32;
    706 
    707  /* Parse u8 slog[32] */
    708  CHECK_REMAINING(32, truncated);
    709  memcpy(obj->slog, ptr, 32);
    710  remaining -= 32; ptr += 32;
    711 
    712  /* Parse u8 clog[32] */
    713  CHECK_REMAINING(32, truncated);
    714  memcpy(obj->clog, ptr, 32);
    715  remaining -= 32; ptr += 32;
    716 
    717  /* Parse u8 scert[32] */
    718  CHECK_REMAINING(32, truncated);
    719  memcpy(obj->scert, ptr, 32);
    720  remaining -= 32; ptr += 32;
    721 
    722  /* Parse u8 tlssecrets[32] */
    723  CHECK_REMAINING(32, truncated);
    724  memcpy(obj->tlssecrets, ptr, 32);
    725  remaining -= 32; ptr += 32;
    726  obj->end_of_fixed_part = ptr;
    727 
    728  /* Parse u8 rand[24] */
    729  CHECK_REMAINING(24, truncated);
    730  memcpy(obj->rand, ptr, 24);
    731  remaining -= 24; ptr += 24;
    732  obj->end_of_signed = ptr;
    733 
    734  /* Parse u8 sig[] */
    735  TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->sig, remaining, {});
    736  obj->sig.n_ = remaining;
    737  if (remaining)
    738    memcpy(obj->sig.elts_, ptr, remaining);
    739  ptr += remaining; remaining -= remaining;
    740  trunnel_assert(ptr + remaining == input + len_in);
    741  return len_in - remaining;
    742 
    743 truncated:
    744  return -2;
    745 trunnel_alloc_failed:
    746  return -1;
    747 }
    748 
    749 ssize_t
    750 auth1_parse(auth1_t **output, const uint8_t *input, const size_t len_in)
    751 {
    752  ssize_t result;
    753  *output = auth1_new();
    754  if (NULL == *output)
    755    return -1;
    756  result = auth1_parse_into(*output, input, len_in);
    757  if (result < 0) {
    758    auth1_free(*output);
    759    *output = NULL;
    760  }
    761  return result;
    762 }
    763 auth_challenge_cell_t *
    764 auth_challenge_cell_new(void)
    765 {
    766  auth_challenge_cell_t *val = trunnel_calloc(1, sizeof(auth_challenge_cell_t));
    767  if (NULL == val)
    768    return NULL;
    769  return val;
    770 }
    771 
    772 /** Release all storage held inside 'obj', but do not free 'obj'.
    773 */
    774 static void
    775 auth_challenge_cell_clear(auth_challenge_cell_t *obj)
    776 {
    777  (void) obj;
    778  TRUNNEL_DYNARRAY_WIPE(&obj->methods);
    779  TRUNNEL_DYNARRAY_CLEAR(&obj->methods);
    780 }
    781 
    782 void
    783 auth_challenge_cell_free(auth_challenge_cell_t *obj)
    784 {
    785  if (obj == NULL)
    786    return;
    787  auth_challenge_cell_clear(obj);
    788  trunnel_memwipe(obj, sizeof(auth_challenge_cell_t));
    789  trunnel_free_(obj);
    790 }
    791 
    792 size_t
    793 auth_challenge_cell_getlen_challenge(const auth_challenge_cell_t *inp)
    794 {
    795  (void)inp;  return 32;
    796 }
    797 
    798 uint8_t
    799 auth_challenge_cell_get_challenge(auth_challenge_cell_t *inp, size_t idx)
    800 {
    801  trunnel_assert(idx < 32);
    802  return inp->challenge[idx];
    803 }
    804 
    805 uint8_t
    806 auth_challenge_cell_getconst_challenge(const auth_challenge_cell_t *inp, size_t idx)
    807 {
    808  return auth_challenge_cell_get_challenge((auth_challenge_cell_t*)inp, idx);
    809 }
    810 int
    811 auth_challenge_cell_set_challenge(auth_challenge_cell_t *inp, size_t idx, uint8_t elt)
    812 {
    813  trunnel_assert(idx < 32);
    814  inp->challenge[idx] = elt;
    815  return 0;
    816 }
    817 
    818 uint8_t *
    819 auth_challenge_cell_getarray_challenge(auth_challenge_cell_t *inp)
    820 {
    821  return inp->challenge;
    822 }
    823 const uint8_t  *
    824 auth_challenge_cell_getconstarray_challenge(const auth_challenge_cell_t *inp)
    825 {
    826  return (const uint8_t  *)auth_challenge_cell_getarray_challenge((auth_challenge_cell_t*)inp);
    827 }
    828 uint16_t
    829 auth_challenge_cell_get_n_methods(const auth_challenge_cell_t *inp)
    830 {
    831  return inp->n_methods;
    832 }
    833 int
    834 auth_challenge_cell_set_n_methods(auth_challenge_cell_t *inp, uint16_t val)
    835 {
    836  inp->n_methods = val;
    837  return 0;
    838 }
    839 size_t
    840 auth_challenge_cell_getlen_methods(const auth_challenge_cell_t *inp)
    841 {
    842  return TRUNNEL_DYNARRAY_LEN(&inp->methods);
    843 }
    844 
    845 uint16_t
    846 auth_challenge_cell_get_methods(auth_challenge_cell_t *inp, size_t idx)
    847 {
    848  return TRUNNEL_DYNARRAY_GET(&inp->methods, idx);
    849 }
    850 
    851 uint16_t
    852 auth_challenge_cell_getconst_methods(const auth_challenge_cell_t *inp, size_t idx)
    853 {
    854  return auth_challenge_cell_get_methods((auth_challenge_cell_t*)inp, idx);
    855 }
    856 int
    857 auth_challenge_cell_set_methods(auth_challenge_cell_t *inp, size_t idx, uint16_t elt)
    858 {
    859  TRUNNEL_DYNARRAY_SET(&inp->methods, idx, elt);
    860  return 0;
    861 }
    862 int
    863 auth_challenge_cell_add_methods(auth_challenge_cell_t *inp, uint16_t elt)
    864 {
    865 #if SIZE_MAX >= UINT16_MAX
    866  if (inp->methods.n_ == UINT16_MAX)
    867    goto trunnel_alloc_failed;
    868 #endif
    869  TRUNNEL_DYNARRAY_ADD(uint16_t, &inp->methods, elt, {});
    870  return 0;
    871 trunnel_alloc_failed:
    872  TRUNNEL_SET_ERROR_CODE(inp);
    873  return -1;
    874 }
    875 
    876 uint16_t *
    877 auth_challenge_cell_getarray_methods(auth_challenge_cell_t *inp)
    878 {
    879  return inp->methods.elts_;
    880 }
    881 const uint16_t  *
    882 auth_challenge_cell_getconstarray_methods(const auth_challenge_cell_t *inp)
    883 {
    884  return (const uint16_t  *)auth_challenge_cell_getarray_methods((auth_challenge_cell_t*)inp);
    885 }
    886 int
    887 auth_challenge_cell_setlen_methods(auth_challenge_cell_t *inp, size_t newlen)
    888 {
    889  uint16_t *newptr;
    890 #if UINT16_MAX < SIZE_MAX
    891  if (newlen > UINT16_MAX)
    892    goto trunnel_alloc_failed;
    893 #endif
    894  newptr = trunnel_dynarray_setlen(&inp->methods.allocated_,
    895                 &inp->methods.n_, inp->methods.elts_, newlen,
    896                 sizeof(inp->methods.elts_[0]), (trunnel_free_fn_t) NULL,
    897                 &inp->trunnel_error_code_);
    898  if (newlen != 0 && newptr == NULL)
    899    goto trunnel_alloc_failed;
    900  inp->methods.elts_ = newptr;
    901  return 0;
    902 trunnel_alloc_failed:
    903  TRUNNEL_SET_ERROR_CODE(inp);
    904  return -1;
    905 }
    906 const char *
    907 auth_challenge_cell_check(const auth_challenge_cell_t *obj)
    908 {
    909  if (obj == NULL)
    910    return "Object was NULL";
    911  if (obj->trunnel_error_code_)
    912    return "A set function failed on this object";
    913  if (TRUNNEL_DYNARRAY_LEN(&obj->methods) != obj->n_methods)
    914    return "Length mismatch for methods";
    915  return NULL;
    916 }
    917 
    918 ssize_t
    919 auth_challenge_cell_encoded_len(const auth_challenge_cell_t *obj)
    920 {
    921  ssize_t result = 0;
    922 
    923  if (NULL != auth_challenge_cell_check(obj))
    924     return -1;
    925 
    926 
    927  /* Length of u8 challenge[32] */
    928  result += 32;
    929 
    930  /* Length of u16 n_methods */
    931  result += 2;
    932 
    933  /* Length of u16 methods[n_methods] */
    934  result += 2 * TRUNNEL_DYNARRAY_LEN(&obj->methods);
    935  return result;
    936 }
    937 int
    938 auth_challenge_cell_clear_errors(auth_challenge_cell_t *obj)
    939 {
    940  int r = obj->trunnel_error_code_;
    941  obj->trunnel_error_code_ = 0;
    942  return r;
    943 }
    944 ssize_t
    945 auth_challenge_cell_encode(uint8_t *output, const size_t avail, const auth_challenge_cell_t *obj)
    946 {
    947  ssize_t result = 0;
    948  size_t written = 0;
    949  uint8_t *ptr = output;
    950  const char *msg;
    951 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    952  const ssize_t encoded_len = auth_challenge_cell_encoded_len(obj);
    953 #endif
    954 
    955  if (NULL != (msg = auth_challenge_cell_check(obj)))
    956    goto check_failed;
    957 
    958 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    959  trunnel_assert(encoded_len >= 0);
    960 #endif
    961 
    962  /* Encode u8 challenge[32] */
    963  trunnel_assert(written <= avail);
    964  if (avail - written < 32)
    965    goto truncated;
    966  memcpy(ptr, obj->challenge, 32);
    967  written += 32; ptr += 32;
    968 
    969  /* Encode u16 n_methods */
    970  trunnel_assert(written <= avail);
    971  if (avail - written < 2)
    972    goto truncated;
    973  trunnel_set_uint16(ptr, trunnel_htons(obj->n_methods));
    974  written += 2; ptr += 2;
    975 
    976  /* Encode u16 methods[n_methods] */
    977  {
    978 
    979    unsigned idx;
    980    for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->methods); ++idx) {
    981      trunnel_assert(written <= avail);
    982      if (avail - written < 2)
    983        goto truncated;
    984      trunnel_set_uint16(ptr, trunnel_htons(TRUNNEL_DYNARRAY_GET(&obj->methods, idx)));
    985      written += 2; ptr += 2;
    986    }
    987  }
    988 
    989 
    990  trunnel_assert(ptr == output + written);
    991 #ifdef TRUNNEL_CHECK_ENCODED_LEN
    992  {
    993    trunnel_assert(encoded_len >= 0);
    994    trunnel_assert((size_t)encoded_len == written);
    995  }
    996 
    997 #endif
    998 
    999  return written;
   1000 
   1001 truncated:
   1002  result = -2;
   1003  goto fail;
   1004 check_failed:
   1005  (void)msg;
   1006  result = -1;
   1007  goto fail;
   1008 fail:
   1009  trunnel_assert(result < 0);
   1010  return result;
   1011 }
   1012 
   1013 /** As auth_challenge_cell_parse(), but do not allocate the output
   1014 * object.
   1015 */
   1016 static ssize_t
   1017 auth_challenge_cell_parse_into(auth_challenge_cell_t *obj, const uint8_t *input, const size_t len_in)
   1018 {
   1019  const uint8_t *ptr = input;
   1020  size_t remaining = len_in;
   1021  ssize_t result = 0;
   1022  (void)result;
   1023 
   1024  /* Parse u8 challenge[32] */
   1025  CHECK_REMAINING(32, truncated);
   1026  memcpy(obj->challenge, ptr, 32);
   1027  remaining -= 32; ptr += 32;
   1028 
   1029  /* Parse u16 n_methods */
   1030  CHECK_REMAINING(2, truncated);
   1031  obj->n_methods = trunnel_ntohs(trunnel_get_uint16(ptr));
   1032  remaining -= 2; ptr += 2;
   1033 
   1034  /* Parse u16 methods[n_methods] */
   1035  TRUNNEL_DYNARRAY_EXPAND(uint16_t, &obj->methods, obj->n_methods, {});
   1036  {
   1037    uint16_t elt;
   1038    unsigned idx;
   1039    for (idx = 0; idx < obj->n_methods; ++idx) {
   1040      CHECK_REMAINING(2, truncated);
   1041      elt = trunnel_ntohs(trunnel_get_uint16(ptr));
   1042      remaining -= 2; ptr += 2;
   1043      TRUNNEL_DYNARRAY_ADD(uint16_t, &obj->methods, elt, {});
   1044    }
   1045  }
   1046  trunnel_assert(ptr + remaining == input + len_in);
   1047  return len_in - remaining;
   1048 
   1049 truncated:
   1050  return -2;
   1051 trunnel_alloc_failed:
   1052  return -1;
   1053 }
   1054 
   1055 ssize_t
   1056 auth_challenge_cell_parse(auth_challenge_cell_t **output, const uint8_t *input, const size_t len_in)
   1057 {
   1058  ssize_t result;
   1059  *output = auth_challenge_cell_new();
   1060  if (NULL == *output)
   1061    return -1;
   1062  result = auth_challenge_cell_parse_into(*output, input, len_in);
   1063  if (result < 0) {
   1064    auth_challenge_cell_free(*output);
   1065    *output = NULL;
   1066  }
   1067  return result;
   1068 }
   1069 certs_cell_cert_t *
   1070 certs_cell_cert_new(void)
   1071 {
   1072  certs_cell_cert_t *val = trunnel_calloc(1, sizeof(certs_cell_cert_t));
   1073  if (NULL == val)
   1074    return NULL;
   1075  return val;
   1076 }
   1077 
   1078 /** Release all storage held inside 'obj', but do not free 'obj'.
   1079 */
   1080 static void
   1081 certs_cell_cert_clear(certs_cell_cert_t *obj)
   1082 {
   1083  (void) obj;
   1084  TRUNNEL_DYNARRAY_WIPE(&obj->body);
   1085  TRUNNEL_DYNARRAY_CLEAR(&obj->body);
   1086 }
   1087 
   1088 void
   1089 certs_cell_cert_free(certs_cell_cert_t *obj)
   1090 {
   1091  if (obj == NULL)
   1092    return;
   1093  certs_cell_cert_clear(obj);
   1094  trunnel_memwipe(obj, sizeof(certs_cell_cert_t));
   1095  trunnel_free_(obj);
   1096 }
   1097 
   1098 uint8_t
   1099 certs_cell_cert_get_cert_type(const certs_cell_cert_t *inp)
   1100 {
   1101  return inp->cert_type;
   1102 }
   1103 int
   1104 certs_cell_cert_set_cert_type(certs_cell_cert_t *inp, uint8_t val)
   1105 {
   1106  inp->cert_type = val;
   1107  return 0;
   1108 }
   1109 uint16_t
   1110 certs_cell_cert_get_cert_len(const certs_cell_cert_t *inp)
   1111 {
   1112  return inp->cert_len;
   1113 }
   1114 int
   1115 certs_cell_cert_set_cert_len(certs_cell_cert_t *inp, uint16_t val)
   1116 {
   1117  inp->cert_len = val;
   1118  return 0;
   1119 }
   1120 size_t
   1121 certs_cell_cert_getlen_body(const certs_cell_cert_t *inp)
   1122 {
   1123  return TRUNNEL_DYNARRAY_LEN(&inp->body);
   1124 }
   1125 
   1126 uint8_t
   1127 certs_cell_cert_get_body(certs_cell_cert_t *inp, size_t idx)
   1128 {
   1129  return TRUNNEL_DYNARRAY_GET(&inp->body, idx);
   1130 }
   1131 
   1132 uint8_t
   1133 certs_cell_cert_getconst_body(const certs_cell_cert_t *inp, size_t idx)
   1134 {
   1135  return certs_cell_cert_get_body((certs_cell_cert_t*)inp, idx);
   1136 }
   1137 int
   1138 certs_cell_cert_set_body(certs_cell_cert_t *inp, size_t idx, uint8_t elt)
   1139 {
   1140  TRUNNEL_DYNARRAY_SET(&inp->body, idx, elt);
   1141  return 0;
   1142 }
   1143 int
   1144 certs_cell_cert_add_body(certs_cell_cert_t *inp, uint8_t elt)
   1145 {
   1146 #if SIZE_MAX >= UINT16_MAX
   1147  if (inp->body.n_ == UINT16_MAX)
   1148    goto trunnel_alloc_failed;
   1149 #endif
   1150  TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->body, elt, {});
   1151  return 0;
   1152 trunnel_alloc_failed:
   1153  TRUNNEL_SET_ERROR_CODE(inp);
   1154  return -1;
   1155 }
   1156 
   1157 uint8_t *
   1158 certs_cell_cert_getarray_body(certs_cell_cert_t *inp)
   1159 {
   1160  return inp->body.elts_;
   1161 }
   1162 const uint8_t  *
   1163 certs_cell_cert_getconstarray_body(const certs_cell_cert_t *inp)
   1164 {
   1165  return (const uint8_t  *)certs_cell_cert_getarray_body((certs_cell_cert_t*)inp);
   1166 }
   1167 int
   1168 certs_cell_cert_setlen_body(certs_cell_cert_t *inp, size_t newlen)
   1169 {
   1170  uint8_t *newptr;
   1171 #if UINT16_MAX < SIZE_MAX
   1172  if (newlen > UINT16_MAX)
   1173    goto trunnel_alloc_failed;
   1174 #endif
   1175  newptr = trunnel_dynarray_setlen(&inp->body.allocated_,
   1176                 &inp->body.n_, inp->body.elts_, newlen,
   1177                 sizeof(inp->body.elts_[0]), (trunnel_free_fn_t) NULL,
   1178                 &inp->trunnel_error_code_);
   1179  if (newlen != 0 && newptr == NULL)
   1180    goto trunnel_alloc_failed;
   1181  inp->body.elts_ = newptr;
   1182  return 0;
   1183 trunnel_alloc_failed:
   1184  TRUNNEL_SET_ERROR_CODE(inp);
   1185  return -1;
   1186 }
   1187 const char *
   1188 certs_cell_cert_check(const certs_cell_cert_t *obj)
   1189 {
   1190  if (obj == NULL)
   1191    return "Object was NULL";
   1192  if (obj->trunnel_error_code_)
   1193    return "A set function failed on this object";
   1194  if (TRUNNEL_DYNARRAY_LEN(&obj->body) != obj->cert_len)
   1195    return "Length mismatch for body";
   1196  return NULL;
   1197 }
   1198 
   1199 ssize_t
   1200 certs_cell_cert_encoded_len(const certs_cell_cert_t *obj)
   1201 {
   1202  ssize_t result = 0;
   1203 
   1204  if (NULL != certs_cell_cert_check(obj))
   1205     return -1;
   1206 
   1207 
   1208  /* Length of u8 cert_type */
   1209  result += 1;
   1210 
   1211  /* Length of u16 cert_len */
   1212  result += 2;
   1213 
   1214  /* Length of u8 body[cert_len] */
   1215  result += TRUNNEL_DYNARRAY_LEN(&obj->body);
   1216  return result;
   1217 }
   1218 int
   1219 certs_cell_cert_clear_errors(certs_cell_cert_t *obj)
   1220 {
   1221  int r = obj->trunnel_error_code_;
   1222  obj->trunnel_error_code_ = 0;
   1223  return r;
   1224 }
   1225 ssize_t
   1226 certs_cell_cert_encode(uint8_t *output, const size_t avail, const certs_cell_cert_t *obj)
   1227 {
   1228  ssize_t result = 0;
   1229  size_t written = 0;
   1230  uint8_t *ptr = output;
   1231  const char *msg;
   1232 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1233  const ssize_t encoded_len = certs_cell_cert_encoded_len(obj);
   1234 #endif
   1235 
   1236  if (NULL != (msg = certs_cell_cert_check(obj)))
   1237    goto check_failed;
   1238 
   1239 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1240  trunnel_assert(encoded_len >= 0);
   1241 #endif
   1242 
   1243  /* Encode u8 cert_type */
   1244  trunnel_assert(written <= avail);
   1245  if (avail - written < 1)
   1246    goto truncated;
   1247  trunnel_set_uint8(ptr, (obj->cert_type));
   1248  written += 1; ptr += 1;
   1249 
   1250  /* Encode u16 cert_len */
   1251  trunnel_assert(written <= avail);
   1252  if (avail - written < 2)
   1253    goto truncated;
   1254  trunnel_set_uint16(ptr, trunnel_htons(obj->cert_len));
   1255  written += 2; ptr += 2;
   1256 
   1257  /* Encode u8 body[cert_len] */
   1258  {
   1259    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->body);
   1260    trunnel_assert(obj->cert_len == elt_len);
   1261    trunnel_assert(written <= avail);
   1262    if (avail - written < elt_len)
   1263      goto truncated;
   1264    if (elt_len)
   1265      memcpy(ptr, obj->body.elts_, elt_len);
   1266    written += elt_len; ptr += elt_len;
   1267  }
   1268 
   1269 
   1270  trunnel_assert(ptr == output + written);
   1271 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1272  {
   1273    trunnel_assert(encoded_len >= 0);
   1274    trunnel_assert((size_t)encoded_len == written);
   1275  }
   1276 
   1277 #endif
   1278 
   1279  return written;
   1280 
   1281 truncated:
   1282  result = -2;
   1283  goto fail;
   1284 check_failed:
   1285  (void)msg;
   1286  result = -1;
   1287  goto fail;
   1288 fail:
   1289  trunnel_assert(result < 0);
   1290  return result;
   1291 }
   1292 
   1293 /** As certs_cell_cert_parse(), but do not allocate the output object.
   1294 */
   1295 static ssize_t
   1296 certs_cell_cert_parse_into(certs_cell_cert_t *obj, const uint8_t *input, const size_t len_in)
   1297 {
   1298  const uint8_t *ptr = input;
   1299  size_t remaining = len_in;
   1300  ssize_t result = 0;
   1301  (void)result;
   1302 
   1303  /* Parse u8 cert_type */
   1304  CHECK_REMAINING(1, truncated);
   1305  obj->cert_type = (trunnel_get_uint8(ptr));
   1306  remaining -= 1; ptr += 1;
   1307 
   1308  /* Parse u16 cert_len */
   1309  CHECK_REMAINING(2, truncated);
   1310  obj->cert_len = trunnel_ntohs(trunnel_get_uint16(ptr));
   1311  remaining -= 2; ptr += 2;
   1312 
   1313  /* Parse u8 body[cert_len] */
   1314  CHECK_REMAINING(obj->cert_len, truncated);
   1315  TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->body, obj->cert_len, {});
   1316  obj->body.n_ = obj->cert_len;
   1317  if (obj->cert_len)
   1318    memcpy(obj->body.elts_, ptr, obj->cert_len);
   1319  ptr += obj->cert_len; remaining -= obj->cert_len;
   1320  trunnel_assert(ptr + remaining == input + len_in);
   1321  return len_in - remaining;
   1322 
   1323 truncated:
   1324  return -2;
   1325 trunnel_alloc_failed:
   1326  return -1;
   1327 }
   1328 
   1329 ssize_t
   1330 certs_cell_cert_parse(certs_cell_cert_t **output, const uint8_t *input, const size_t len_in)
   1331 {
   1332  ssize_t result;
   1333  *output = certs_cell_cert_new();
   1334  if (NULL == *output)
   1335    return -1;
   1336  result = certs_cell_cert_parse_into(*output, input, len_in);
   1337  if (result < 0) {
   1338    certs_cell_cert_free(*output);
   1339    *output = NULL;
   1340  }
   1341  return result;
   1342 }
   1343 rsa_ed_crosscert_t *
   1344 rsa_ed_crosscert_new(void)
   1345 {
   1346  rsa_ed_crosscert_t *val = trunnel_calloc(1, sizeof(rsa_ed_crosscert_t));
   1347  if (NULL == val)
   1348    return NULL;
   1349  return val;
   1350 }
   1351 
   1352 /** Release all storage held inside 'obj', but do not free 'obj'.
   1353 */
   1354 static void
   1355 rsa_ed_crosscert_clear(rsa_ed_crosscert_t *obj)
   1356 {
   1357  (void) obj;
   1358  TRUNNEL_DYNARRAY_WIPE(&obj->sig);
   1359  TRUNNEL_DYNARRAY_CLEAR(&obj->sig);
   1360 }
   1361 
   1362 void
   1363 rsa_ed_crosscert_free(rsa_ed_crosscert_t *obj)
   1364 {
   1365  if (obj == NULL)
   1366    return;
   1367  rsa_ed_crosscert_clear(obj);
   1368  trunnel_memwipe(obj, sizeof(rsa_ed_crosscert_t));
   1369  trunnel_free_(obj);
   1370 }
   1371 
   1372 size_t
   1373 rsa_ed_crosscert_getlen_ed_key(const rsa_ed_crosscert_t *inp)
   1374 {
   1375  (void)inp;  return 32;
   1376 }
   1377 
   1378 uint8_t
   1379 rsa_ed_crosscert_get_ed_key(rsa_ed_crosscert_t *inp, size_t idx)
   1380 {
   1381  trunnel_assert(idx < 32);
   1382  return inp->ed_key[idx];
   1383 }
   1384 
   1385 uint8_t
   1386 rsa_ed_crosscert_getconst_ed_key(const rsa_ed_crosscert_t *inp, size_t idx)
   1387 {
   1388  return rsa_ed_crosscert_get_ed_key((rsa_ed_crosscert_t*)inp, idx);
   1389 }
   1390 int
   1391 rsa_ed_crosscert_set_ed_key(rsa_ed_crosscert_t *inp, size_t idx, uint8_t elt)
   1392 {
   1393  trunnel_assert(idx < 32);
   1394  inp->ed_key[idx] = elt;
   1395  return 0;
   1396 }
   1397 
   1398 uint8_t *
   1399 rsa_ed_crosscert_getarray_ed_key(rsa_ed_crosscert_t *inp)
   1400 {
   1401  return inp->ed_key;
   1402 }
   1403 const uint8_t  *
   1404 rsa_ed_crosscert_getconstarray_ed_key(const rsa_ed_crosscert_t *inp)
   1405 {
   1406  return (const uint8_t  *)rsa_ed_crosscert_getarray_ed_key((rsa_ed_crosscert_t*)inp);
   1407 }
   1408 uint32_t
   1409 rsa_ed_crosscert_get_expiration(const rsa_ed_crosscert_t *inp)
   1410 {
   1411  return inp->expiration;
   1412 }
   1413 int
   1414 rsa_ed_crosscert_set_expiration(rsa_ed_crosscert_t *inp, uint32_t val)
   1415 {
   1416  inp->expiration = val;
   1417  return 0;
   1418 }
   1419 const uint8_t *
   1420 rsa_ed_crosscert_get_end_of_signed(const rsa_ed_crosscert_t *inp)
   1421 {
   1422  return inp->end_of_signed;
   1423 }
   1424 uint8_t
   1425 rsa_ed_crosscert_get_sig_len(const rsa_ed_crosscert_t *inp)
   1426 {
   1427  return inp->sig_len;
   1428 }
   1429 int
   1430 rsa_ed_crosscert_set_sig_len(rsa_ed_crosscert_t *inp, uint8_t val)
   1431 {
   1432  inp->sig_len = val;
   1433  return 0;
   1434 }
   1435 size_t
   1436 rsa_ed_crosscert_getlen_sig(const rsa_ed_crosscert_t *inp)
   1437 {
   1438  return TRUNNEL_DYNARRAY_LEN(&inp->sig);
   1439 }
   1440 
   1441 uint8_t
   1442 rsa_ed_crosscert_get_sig(rsa_ed_crosscert_t *inp, size_t idx)
   1443 {
   1444  return TRUNNEL_DYNARRAY_GET(&inp->sig, idx);
   1445 }
   1446 
   1447 uint8_t
   1448 rsa_ed_crosscert_getconst_sig(const rsa_ed_crosscert_t *inp, size_t idx)
   1449 {
   1450  return rsa_ed_crosscert_get_sig((rsa_ed_crosscert_t*)inp, idx);
   1451 }
   1452 int
   1453 rsa_ed_crosscert_set_sig(rsa_ed_crosscert_t *inp, size_t idx, uint8_t elt)
   1454 {
   1455  TRUNNEL_DYNARRAY_SET(&inp->sig, idx, elt);
   1456  return 0;
   1457 }
   1458 int
   1459 rsa_ed_crosscert_add_sig(rsa_ed_crosscert_t *inp, uint8_t elt)
   1460 {
   1461 #if SIZE_MAX >= UINT8_MAX
   1462  if (inp->sig.n_ == UINT8_MAX)
   1463    goto trunnel_alloc_failed;
   1464 #endif
   1465  TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->sig, elt, {});
   1466  return 0;
   1467 trunnel_alloc_failed:
   1468  TRUNNEL_SET_ERROR_CODE(inp);
   1469  return -1;
   1470 }
   1471 
   1472 uint8_t *
   1473 rsa_ed_crosscert_getarray_sig(rsa_ed_crosscert_t *inp)
   1474 {
   1475  return inp->sig.elts_;
   1476 }
   1477 const uint8_t  *
   1478 rsa_ed_crosscert_getconstarray_sig(const rsa_ed_crosscert_t *inp)
   1479 {
   1480  return (const uint8_t  *)rsa_ed_crosscert_getarray_sig((rsa_ed_crosscert_t*)inp);
   1481 }
   1482 int
   1483 rsa_ed_crosscert_setlen_sig(rsa_ed_crosscert_t *inp, size_t newlen)
   1484 {
   1485  uint8_t *newptr;
   1486 #if UINT8_MAX < SIZE_MAX
   1487  if (newlen > UINT8_MAX)
   1488    goto trunnel_alloc_failed;
   1489 #endif
   1490  newptr = trunnel_dynarray_setlen(&inp->sig.allocated_,
   1491                 &inp->sig.n_, inp->sig.elts_, newlen,
   1492                 sizeof(inp->sig.elts_[0]), (trunnel_free_fn_t) NULL,
   1493                 &inp->trunnel_error_code_);
   1494  if (newlen != 0 && newptr == NULL)
   1495    goto trunnel_alloc_failed;
   1496  inp->sig.elts_ = newptr;
   1497  return 0;
   1498 trunnel_alloc_failed:
   1499  TRUNNEL_SET_ERROR_CODE(inp);
   1500  return -1;
   1501 }
   1502 const char *
   1503 rsa_ed_crosscert_check(const rsa_ed_crosscert_t *obj)
   1504 {
   1505  if (obj == NULL)
   1506    return "Object was NULL";
   1507  if (obj->trunnel_error_code_)
   1508    return "A set function failed on this object";
   1509  if (TRUNNEL_DYNARRAY_LEN(&obj->sig) != obj->sig_len)
   1510    return "Length mismatch for sig";
   1511  return NULL;
   1512 }
   1513 
   1514 ssize_t
   1515 rsa_ed_crosscert_encoded_len(const rsa_ed_crosscert_t *obj)
   1516 {
   1517  ssize_t result = 0;
   1518 
   1519  if (NULL != rsa_ed_crosscert_check(obj))
   1520     return -1;
   1521 
   1522 
   1523  /* Length of u8 ed_key[32] */
   1524  result += 32;
   1525 
   1526  /* Length of u32 expiration */
   1527  result += 4;
   1528 
   1529  /* Length of u8 sig_len */
   1530  result += 1;
   1531 
   1532  /* Length of u8 sig[sig_len] */
   1533  result += TRUNNEL_DYNARRAY_LEN(&obj->sig);
   1534  return result;
   1535 }
   1536 int
   1537 rsa_ed_crosscert_clear_errors(rsa_ed_crosscert_t *obj)
   1538 {
   1539  int r = obj->trunnel_error_code_;
   1540  obj->trunnel_error_code_ = 0;
   1541  return r;
   1542 }
   1543 ssize_t
   1544 rsa_ed_crosscert_encode(uint8_t *output, const size_t avail, const rsa_ed_crosscert_t *obj)
   1545 {
   1546  ssize_t result = 0;
   1547  size_t written = 0;
   1548  uint8_t *ptr = output;
   1549  const char *msg;
   1550 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1551  const ssize_t encoded_len = rsa_ed_crosscert_encoded_len(obj);
   1552 #endif
   1553 
   1554  if (NULL != (msg = rsa_ed_crosscert_check(obj)))
   1555    goto check_failed;
   1556 
   1557 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1558  trunnel_assert(encoded_len >= 0);
   1559 #endif
   1560 
   1561  /* Encode u8 ed_key[32] */
   1562  trunnel_assert(written <= avail);
   1563  if (avail - written < 32)
   1564    goto truncated;
   1565  memcpy(ptr, obj->ed_key, 32);
   1566  written += 32; ptr += 32;
   1567 
   1568  /* Encode u32 expiration */
   1569  trunnel_assert(written <= avail);
   1570  if (avail - written < 4)
   1571    goto truncated;
   1572  trunnel_set_uint32(ptr, trunnel_htonl(obj->expiration));
   1573  written += 4; ptr += 4;
   1574 
   1575  /* Encode u8 sig_len */
   1576  trunnel_assert(written <= avail);
   1577  if (avail - written < 1)
   1578    goto truncated;
   1579  trunnel_set_uint8(ptr, (obj->sig_len));
   1580  written += 1; ptr += 1;
   1581 
   1582  /* Encode u8 sig[sig_len] */
   1583  {
   1584    size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->sig);
   1585    trunnel_assert(obj->sig_len == elt_len);
   1586    trunnel_assert(written <= avail);
   1587    if (avail - written < elt_len)
   1588      goto truncated;
   1589    if (elt_len)
   1590      memcpy(ptr, obj->sig.elts_, elt_len);
   1591    written += elt_len; ptr += elt_len;
   1592  }
   1593 
   1594 
   1595  trunnel_assert(ptr == output + written);
   1596 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1597  {
   1598    trunnel_assert(encoded_len >= 0);
   1599    trunnel_assert((size_t)encoded_len == written);
   1600  }
   1601 
   1602 #endif
   1603 
   1604  return written;
   1605 
   1606 truncated:
   1607  result = -2;
   1608  goto fail;
   1609 check_failed:
   1610  (void)msg;
   1611  result = -1;
   1612  goto fail;
   1613 fail:
   1614  trunnel_assert(result < 0);
   1615  return result;
   1616 }
   1617 
   1618 /** As rsa_ed_crosscert_parse(), but do not allocate the output
   1619 * object.
   1620 */
   1621 static ssize_t
   1622 rsa_ed_crosscert_parse_into(rsa_ed_crosscert_t *obj, const uint8_t *input, const size_t len_in)
   1623 {
   1624  const uint8_t *ptr = input;
   1625  size_t remaining = len_in;
   1626  ssize_t result = 0;
   1627  (void)result;
   1628 
   1629  /* Parse u8 ed_key[32] */
   1630  CHECK_REMAINING(32, truncated);
   1631  memcpy(obj->ed_key, ptr, 32);
   1632  remaining -= 32; ptr += 32;
   1633 
   1634  /* Parse u32 expiration */
   1635  CHECK_REMAINING(4, truncated);
   1636  obj->expiration = trunnel_ntohl(trunnel_get_uint32(ptr));
   1637  remaining -= 4; ptr += 4;
   1638  obj->end_of_signed = ptr;
   1639 
   1640  /* Parse u8 sig_len */
   1641  CHECK_REMAINING(1, truncated);
   1642  obj->sig_len = (trunnel_get_uint8(ptr));
   1643  remaining -= 1; ptr += 1;
   1644 
   1645  /* Parse u8 sig[sig_len] */
   1646  CHECK_REMAINING(obj->sig_len, truncated);
   1647  TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->sig, obj->sig_len, {});
   1648  obj->sig.n_ = obj->sig_len;
   1649  if (obj->sig_len)
   1650    memcpy(obj->sig.elts_, ptr, obj->sig_len);
   1651  ptr += obj->sig_len; remaining -= obj->sig_len;
   1652  trunnel_assert(ptr + remaining == input + len_in);
   1653  return len_in - remaining;
   1654 
   1655 truncated:
   1656  return -2;
   1657 trunnel_alloc_failed:
   1658  return -1;
   1659 }
   1660 
   1661 ssize_t
   1662 rsa_ed_crosscert_parse(rsa_ed_crosscert_t **output, const uint8_t *input, const size_t len_in)
   1663 {
   1664  ssize_t result;
   1665  *output = rsa_ed_crosscert_new();
   1666  if (NULL == *output)
   1667    return -1;
   1668  result = rsa_ed_crosscert_parse_into(*output, input, len_in);
   1669  if (result < 0) {
   1670    rsa_ed_crosscert_free(*output);
   1671    *output = NULL;
   1672  }
   1673  return result;
   1674 }
   1675 certs_cell_t *
   1676 certs_cell_new(void)
   1677 {
   1678  certs_cell_t *val = trunnel_calloc(1, sizeof(certs_cell_t));
   1679  if (NULL == val)
   1680    return NULL;
   1681  return val;
   1682 }
   1683 
   1684 /** Release all storage held inside 'obj', but do not free 'obj'.
   1685 */
   1686 static void
   1687 certs_cell_clear(certs_cell_t *obj)
   1688 {
   1689  (void) obj;
   1690  {
   1691 
   1692    unsigned idx;
   1693    for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->certs); ++idx) {
   1694      certs_cell_cert_free(TRUNNEL_DYNARRAY_GET(&obj->certs, idx));
   1695    }
   1696  }
   1697  TRUNNEL_DYNARRAY_WIPE(&obj->certs);
   1698  TRUNNEL_DYNARRAY_CLEAR(&obj->certs);
   1699 }
   1700 
   1701 void
   1702 certs_cell_free(certs_cell_t *obj)
   1703 {
   1704  if (obj == NULL)
   1705    return;
   1706  certs_cell_clear(obj);
   1707  trunnel_memwipe(obj, sizeof(certs_cell_t));
   1708  trunnel_free_(obj);
   1709 }
   1710 
   1711 uint8_t
   1712 certs_cell_get_n_certs(const certs_cell_t *inp)
   1713 {
   1714  return inp->n_certs;
   1715 }
   1716 int
   1717 certs_cell_set_n_certs(certs_cell_t *inp, uint8_t val)
   1718 {
   1719  inp->n_certs = val;
   1720  return 0;
   1721 }
   1722 size_t
   1723 certs_cell_getlen_certs(const certs_cell_t *inp)
   1724 {
   1725  return TRUNNEL_DYNARRAY_LEN(&inp->certs);
   1726 }
   1727 
   1728 struct certs_cell_cert_st *
   1729 certs_cell_get_certs(certs_cell_t *inp, size_t idx)
   1730 {
   1731  return TRUNNEL_DYNARRAY_GET(&inp->certs, idx);
   1732 }
   1733 
   1734 const struct certs_cell_cert_st *
   1735 certs_cell_getconst_certs(const certs_cell_t *inp, size_t idx)
   1736 {
   1737  return certs_cell_get_certs((certs_cell_t*)inp, idx);
   1738 }
   1739 int
   1740 certs_cell_set_certs(certs_cell_t *inp, size_t idx, struct certs_cell_cert_st * elt)
   1741 {
   1742  certs_cell_cert_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->certs, idx);
   1743  if (oldval && oldval != elt)
   1744    certs_cell_cert_free(oldval);
   1745  return certs_cell_set0_certs(inp, idx, elt);
   1746 }
   1747 int
   1748 certs_cell_set0_certs(certs_cell_t *inp, size_t idx, struct certs_cell_cert_st * elt)
   1749 {
   1750  TRUNNEL_DYNARRAY_SET(&inp->certs, idx, elt);
   1751  return 0;
   1752 }
   1753 int
   1754 certs_cell_add_certs(certs_cell_t *inp, struct certs_cell_cert_st * elt)
   1755 {
   1756 #if SIZE_MAX >= UINT8_MAX
   1757  if (inp->certs.n_ == UINT8_MAX)
   1758    goto trunnel_alloc_failed;
   1759 #endif
   1760  TRUNNEL_DYNARRAY_ADD(struct certs_cell_cert_st *, &inp->certs, elt, {});
   1761  return 0;
   1762 trunnel_alloc_failed:
   1763  TRUNNEL_SET_ERROR_CODE(inp);
   1764  return -1;
   1765 }
   1766 
   1767 struct certs_cell_cert_st * *
   1768 certs_cell_getarray_certs(certs_cell_t *inp)
   1769 {
   1770  return inp->certs.elts_;
   1771 }
   1772 const struct certs_cell_cert_st *  const  *
   1773 certs_cell_getconstarray_certs(const certs_cell_t *inp)
   1774 {
   1775  return (const struct certs_cell_cert_st *  const  *)certs_cell_getarray_certs((certs_cell_t*)inp);
   1776 }
   1777 int
   1778 certs_cell_setlen_certs(certs_cell_t *inp, size_t newlen)
   1779 {
   1780  struct certs_cell_cert_st * *newptr;
   1781 #if UINT8_MAX < SIZE_MAX
   1782  if (newlen > UINT8_MAX)
   1783    goto trunnel_alloc_failed;
   1784 #endif
   1785  newptr = trunnel_dynarray_setlen(&inp->certs.allocated_,
   1786                 &inp->certs.n_, inp->certs.elts_, newlen,
   1787                 sizeof(inp->certs.elts_[0]), (trunnel_free_fn_t) certs_cell_cert_free,
   1788                 &inp->trunnel_error_code_);
   1789  if (newlen != 0 && newptr == NULL)
   1790    goto trunnel_alloc_failed;
   1791  inp->certs.elts_ = newptr;
   1792  return 0;
   1793 trunnel_alloc_failed:
   1794  TRUNNEL_SET_ERROR_CODE(inp);
   1795  return -1;
   1796 }
   1797 const char *
   1798 certs_cell_check(const certs_cell_t *obj)
   1799 {
   1800  if (obj == NULL)
   1801    return "Object was NULL";
   1802  if (obj->trunnel_error_code_)
   1803    return "A set function failed on this object";
   1804  {
   1805    const char *msg;
   1806 
   1807    unsigned idx;
   1808    for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->certs); ++idx) {
   1809      if (NULL != (msg = certs_cell_cert_check(TRUNNEL_DYNARRAY_GET(&obj->certs, idx))))
   1810        return msg;
   1811    }
   1812  }
   1813  if (TRUNNEL_DYNARRAY_LEN(&obj->certs) != obj->n_certs)
   1814    return "Length mismatch for certs";
   1815  return NULL;
   1816 }
   1817 
   1818 ssize_t
   1819 certs_cell_encoded_len(const certs_cell_t *obj)
   1820 {
   1821  ssize_t result = 0;
   1822 
   1823  if (NULL != certs_cell_check(obj))
   1824     return -1;
   1825 
   1826 
   1827  /* Length of u8 n_certs */
   1828  result += 1;
   1829 
   1830  /* Length of struct certs_cell_cert certs[n_certs] */
   1831  {
   1832 
   1833    unsigned idx;
   1834    for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->certs); ++idx) {
   1835      result += certs_cell_cert_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->certs, idx));
   1836    }
   1837  }
   1838  return result;
   1839 }
   1840 int
   1841 certs_cell_clear_errors(certs_cell_t *obj)
   1842 {
   1843  int r = obj->trunnel_error_code_;
   1844  obj->trunnel_error_code_ = 0;
   1845  return r;
   1846 }
   1847 ssize_t
   1848 certs_cell_encode(uint8_t *output, const size_t avail, const certs_cell_t *obj)
   1849 {
   1850  ssize_t result = 0;
   1851  size_t written = 0;
   1852  uint8_t *ptr = output;
   1853  const char *msg;
   1854 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1855  const ssize_t encoded_len = certs_cell_encoded_len(obj);
   1856 #endif
   1857 
   1858  if (NULL != (msg = certs_cell_check(obj)))
   1859    goto check_failed;
   1860 
   1861 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1862  trunnel_assert(encoded_len >= 0);
   1863 #endif
   1864 
   1865  /* Encode u8 n_certs */
   1866  trunnel_assert(written <= avail);
   1867  if (avail - written < 1)
   1868    goto truncated;
   1869  trunnel_set_uint8(ptr, (obj->n_certs));
   1870  written += 1; ptr += 1;
   1871 
   1872  /* Encode struct certs_cell_cert certs[n_certs] */
   1873  {
   1874 
   1875    unsigned idx;
   1876    for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->certs); ++idx) {
   1877      trunnel_assert(written <= avail);
   1878      result = certs_cell_cert_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->certs, idx));
   1879      if (result < 0)
   1880        goto fail; /* XXXXXXX !*/
   1881      written += result; ptr += result;
   1882    }
   1883  }
   1884 
   1885 
   1886  trunnel_assert(ptr == output + written);
   1887 #ifdef TRUNNEL_CHECK_ENCODED_LEN
   1888  {
   1889    trunnel_assert(encoded_len >= 0);
   1890    trunnel_assert((size_t)encoded_len == written);
   1891  }
   1892 
   1893 #endif
   1894 
   1895  return written;
   1896 
   1897 truncated:
   1898  result = -2;
   1899  goto fail;
   1900 check_failed:
   1901  (void)msg;
   1902  result = -1;
   1903  goto fail;
   1904 fail:
   1905  trunnel_assert(result < 0);
   1906  return result;
   1907 }
   1908 
   1909 /** As certs_cell_parse(), but do not allocate the output object.
   1910 */
   1911 static ssize_t
   1912 certs_cell_parse_into(certs_cell_t *obj, const uint8_t *input, const size_t len_in)
   1913 {
   1914  const uint8_t *ptr = input;
   1915  size_t remaining = len_in;
   1916  ssize_t result = 0;
   1917  (void)result;
   1918 
   1919  /* Parse u8 n_certs */
   1920  CHECK_REMAINING(1, truncated);
   1921  obj->n_certs = (trunnel_get_uint8(ptr));
   1922  remaining -= 1; ptr += 1;
   1923 
   1924  /* Parse struct certs_cell_cert certs[n_certs] */
   1925  TRUNNEL_DYNARRAY_EXPAND(certs_cell_cert_t *, &obj->certs, obj->n_certs, {});
   1926  {
   1927    certs_cell_cert_t * elt;
   1928    unsigned idx;
   1929    for (idx = 0; idx < obj->n_certs; ++idx) {
   1930      result = certs_cell_cert_parse(&elt, ptr, remaining);
   1931      if (result < 0)
   1932        goto relay_fail;
   1933      trunnel_assert((size_t)result <= remaining);
   1934      remaining -= result; ptr += result;
   1935      TRUNNEL_DYNARRAY_ADD(certs_cell_cert_t *, &obj->certs, elt, {certs_cell_cert_free(elt);});
   1936    }
   1937  }
   1938  trunnel_assert(ptr + remaining == input + len_in);
   1939  return len_in - remaining;
   1940 
   1941 truncated:
   1942  return -2;
   1943 relay_fail:
   1944  trunnel_assert(result < 0);
   1945  return result;
   1946 trunnel_alloc_failed:
   1947  return -1;
   1948 }
   1949 
   1950 ssize_t
   1951 certs_cell_parse(certs_cell_t **output, const uint8_t *input, const size_t len_in)
   1952 {
   1953  ssize_t result;
   1954  *output = certs_cell_new();
   1955  if (NULL == *output)
   1956    return -1;
   1957  result = certs_cell_parse_into(*output, input, len_in);
   1958  if (result < 0) {
   1959    certs_cell_free(*output);
   1960    *output = NULL;
   1961  }
   1962  return result;
   1963 }