LCOV - code coverage report
Current view: top level - trunnel - ed25519_cert.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 695 1280 54.3 %
Date: 2021-11-24 03:28:48 Functions: 80 203 39.4 %

          Line data    Source code
       1             : /* ed25519_cert.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 "ed25519_cert.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 edcert_deadcode_dummy__ = 0;
      19             : #define OR_DEADCODE_DUMMY || edcert_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             : create2_cell_body_t *
      32         113 : create2_cell_body_new(void)
      33             : {
      34         113 :   create2_cell_body_t *val = trunnel_calloc(1, sizeof(create2_cell_body_t));
      35         113 :   if (NULL == val)
      36           0 :     return NULL;
      37             :   return val;
      38             : }
      39             : 
      40             : /** Release all storage held inside 'obj', but do not free 'obj'.
      41             :  */
      42             : static void
      43         113 : create2_cell_body_clear(create2_cell_body_t *obj)
      44             : {
      45         113 :   (void) obj;
      46         113 :   TRUNNEL_DYNARRAY_WIPE(&obj->handshake_data);
      47         113 :   TRUNNEL_DYNARRAY_CLEAR(&obj->handshake_data);
      48         113 : }
      49             : 
      50             : void
      51       10119 : create2_cell_body_free(create2_cell_body_t *obj)
      52             : {
      53       10119 :   if (obj == NULL)
      54             :     return;
      55         113 :   create2_cell_body_clear(obj);
      56         113 :   trunnel_memwipe(obj, sizeof(create2_cell_body_t));
      57         113 :   trunnel_free_(obj);
      58             : }
      59             : 
      60             : uint16_t
      61           0 : create2_cell_body_get_handshake_type(const create2_cell_body_t *inp)
      62             : {
      63           0 :   return inp->handshake_type;
      64             : }
      65             : int
      66           0 : create2_cell_body_set_handshake_type(create2_cell_body_t *inp, uint16_t val)
      67             : {
      68           0 :   inp->handshake_type = val;
      69           0 :   return 0;
      70             : }
      71             : uint16_t
      72           0 : create2_cell_body_get_handshake_len(const create2_cell_body_t *inp)
      73             : {
      74           0 :   return inp->handshake_len;
      75             : }
      76             : int
      77           0 : create2_cell_body_set_handshake_len(create2_cell_body_t *inp, uint16_t val)
      78             : {
      79           0 :   inp->handshake_len = val;
      80           0 :   return 0;
      81             : }
      82             : size_t
      83           0 : create2_cell_body_getlen_handshake_data(const create2_cell_body_t *inp)
      84             : {
      85           0 :   return TRUNNEL_DYNARRAY_LEN(&inp->handshake_data);
      86             : }
      87             : 
      88             : uint8_t
      89           0 : create2_cell_body_get_handshake_data(create2_cell_body_t *inp, size_t idx)
      90             : {
      91           0 :   return TRUNNEL_DYNARRAY_GET(&inp->handshake_data, idx);
      92             : }
      93             : 
      94             : uint8_t
      95           0 : create2_cell_body_getconst_handshake_data(const create2_cell_body_t *inp, size_t idx)
      96             : {
      97           0 :   return create2_cell_body_get_handshake_data((create2_cell_body_t*)inp, idx);
      98             : }
      99             : int
     100           0 : create2_cell_body_set_handshake_data(create2_cell_body_t *inp, size_t idx, uint8_t elt)
     101             : {
     102           0 :   TRUNNEL_DYNARRAY_SET(&inp->handshake_data, idx, elt);
     103           0 :   return 0;
     104             : }
     105             : int
     106           0 : create2_cell_body_add_handshake_data(create2_cell_body_t *inp, uint8_t elt)
     107             : {
     108             : #if SIZE_MAX >= UINT16_MAX
     109           0 :   if (inp->handshake_data.n_ == UINT16_MAX)
     110           0 :     goto trunnel_alloc_failed;
     111             : #endif
     112           0 :   TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->handshake_data, elt, {});
     113           0 :   return 0;
     114           0 :  trunnel_alloc_failed:
     115           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     116           0 :   return -1;
     117             : }
     118             : 
     119             : uint8_t *
     120           9 : create2_cell_body_getarray_handshake_data(create2_cell_body_t *inp)
     121             : {
     122           9 :   return inp->handshake_data.elts_;
     123             : }
     124             : const uint8_t  *
     125           4 : create2_cell_body_getconstarray_handshake_data(const create2_cell_body_t *inp)
     126             : {
     127           4 :   return (const uint8_t  *)create2_cell_body_getarray_handshake_data((create2_cell_body_t*)inp);
     128             : }
     129             : int
     130           5 : create2_cell_body_setlen_handshake_data(create2_cell_body_t *inp, size_t newlen)
     131             : {
     132           5 :   uint8_t *newptr;
     133             : #if UINT16_MAX < SIZE_MAX
     134           5 :   if (newlen > UINT16_MAX)
     135           0 :     goto trunnel_alloc_failed;
     136             : #endif
     137          10 :   newptr = trunnel_dynarray_setlen(&inp->handshake_data.allocated_,
     138           5 :                  &inp->handshake_data.n_, inp->handshake_data.elts_, newlen,
     139             :                  sizeof(inp->handshake_data.elts_[0]), (trunnel_free_fn_t) NULL,
     140             :                  &inp->trunnel_error_code_);
     141           5 :   if (newlen != 0 && newptr == NULL)
     142           0 :     goto trunnel_alloc_failed;
     143           5 :   inp->handshake_data.elts_ = newptr;
     144           5 :   return 0;
     145           0 :  trunnel_alloc_failed:
     146           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     147           0 :   return -1;
     148             : }
     149             : const char *
     150          10 : create2_cell_body_check(const create2_cell_body_t *obj)
     151             : {
     152          10 :   if (obj == NULL)
     153             :     return "Object was NULL";
     154          10 :   if (obj->trunnel_error_code_)
     155             :     return "A set function failed on this object";
     156          10 :   if (TRUNNEL_DYNARRAY_LEN(&obj->handshake_data) != obj->handshake_len)
     157           0 :     return "Length mismatch for handshake_data";
     158             :   return NULL;
     159             : }
     160             : 
     161             : ssize_t
     162           0 : create2_cell_body_encoded_len(const create2_cell_body_t *obj)
     163             : {
     164           0 :   ssize_t result = 0;
     165             : 
     166           0 :   if (NULL != create2_cell_body_check(obj))
     167             :      return -1;
     168             : 
     169             : 
     170             :   /* Length of u16 handshake_type */
     171           0 :   result += 2;
     172             : 
     173             :   /* Length of u16 handshake_len */
     174           0 :   result += 2;
     175             : 
     176             :   /* Length of u8 handshake_data[handshake_len] */
     177           0 :   result += TRUNNEL_DYNARRAY_LEN(&obj->handshake_data);
     178           0 :   return result;
     179             : }
     180             : int
     181           0 : create2_cell_body_clear_errors(create2_cell_body_t *obj)
     182             : {
     183           0 :   int r = obj->trunnel_error_code_;
     184           0 :   obj->trunnel_error_code_ = 0;
     185           0 :   return r;
     186             : }
     187             : ssize_t
     188           5 : create2_cell_body_encode(uint8_t *output, const size_t avail, const create2_cell_body_t *obj)
     189             : {
     190           5 :   ssize_t result = 0;
     191           5 :   size_t written = 0;
     192           5 :   uint8_t *ptr = output;
     193           5 :   const char *msg;
     194             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     195             :   const ssize_t encoded_len = create2_cell_body_encoded_len(obj);
     196             : #endif
     197             : 
     198           5 :   if (NULL != (msg = create2_cell_body_check(obj)))
     199           0 :     goto check_failed;
     200             : 
     201             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     202             :   trunnel_assert(encoded_len >= 0);
     203             : #endif
     204             : 
     205             :   /* Encode u16 handshake_type */
     206           5 :   trunnel_assert(written <= avail);
     207           5 :   if (avail - written < 2)
     208           0 :     goto truncated;
     209           5 :   trunnel_set_uint16(ptr, trunnel_htons(obj->handshake_type));
     210           5 :   written += 2; ptr += 2;
     211             : 
     212             :   /* Encode u16 handshake_len */
     213           5 :   trunnel_assert(written <= avail);
     214           5 :   if (avail - written < 2)
     215           0 :     goto truncated;
     216           5 :   trunnel_set_uint16(ptr, trunnel_htons(obj->handshake_len));
     217           5 :   written += 2; ptr += 2;
     218             : 
     219             :   /* Encode u8 handshake_data[handshake_len] */
     220             :   {
     221           5 :     size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->handshake_data);
     222           5 :     trunnel_assert(obj->handshake_len == elt_len);
     223           5 :     trunnel_assert(written <= avail);
     224           5 :     if (avail - written < elt_len)
     225           0 :       goto truncated;
     226           5 :     if (elt_len)
     227           5 :       memcpy(ptr, obj->handshake_data.elts_, elt_len);
     228           5 :     written += elt_len; ptr += elt_len;
     229             :   }
     230             : 
     231             : 
     232           5 :   trunnel_assert(ptr == output + written);
     233             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     234             :   {
     235             :     trunnel_assert(encoded_len >= 0);
     236             :     trunnel_assert((size_t)encoded_len == written);
     237             :   }
     238             : 
     239             : #endif
     240             : 
     241           5 :   return written;
     242             : 
     243           0 :  truncated:
     244           0 :   result = -2;
     245           0 :   goto fail;
     246           0 :  check_failed:
     247           0 :   (void)msg;
     248           0 :   result = -1;
     249           0 :   goto fail;
     250             :  fail:
     251             :   trunnel_assert(result < 0);
     252             :   return result;
     253             : }
     254             : 
     255             : /** As create2_cell_body_parse(), but do not allocate the output
     256             :  * object.
     257             :  */
     258             : static ssize_t
     259         108 : create2_cell_body_parse_into(create2_cell_body_t *obj, const uint8_t *input, const size_t len_in)
     260             : {
     261         108 :   const uint8_t *ptr = input;
     262         108 :   size_t remaining = len_in;
     263         108 :   ssize_t result = 0;
     264         108 :   (void)result;
     265             : 
     266             :   /* Parse u16 handshake_type */
     267         108 :   CHECK_REMAINING(2, truncated);
     268         108 :   obj->handshake_type = trunnel_ntohs(trunnel_get_uint16(ptr));
     269         108 :   remaining -= 2; ptr += 2;
     270             : 
     271             :   /* Parse u16 handshake_len */
     272         108 :   CHECK_REMAINING(2, truncated);
     273         108 :   obj->handshake_len = trunnel_ntohs(trunnel_get_uint16(ptr));
     274         108 :   remaining -= 2; ptr += 2;
     275             : 
     276             :   /* Parse u8 handshake_data[handshake_len] */
     277         108 :   CHECK_REMAINING(obj->handshake_len, truncated);
     278           6 :   TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->handshake_data, obj->handshake_len, {});
     279           6 :   obj->handshake_data.n_ = obj->handshake_len;
     280           6 :   if (obj->handshake_len)
     281           5 :     memcpy(obj->handshake_data.elts_, ptr, obj->handshake_len);
     282           6 :   ptr += obj->handshake_len; remaining -= obj->handshake_len;
     283           6 :   trunnel_assert(ptr + remaining == input + len_in);
     284           6 :   return len_in - remaining;
     285             : 
     286             :  truncated:
     287             :   return -2;
     288           0 :  trunnel_alloc_failed:
     289           0 :   return -1;
     290             : }
     291             : 
     292             : ssize_t
     293         108 : create2_cell_body_parse(create2_cell_body_t **output, const uint8_t *input, const size_t len_in)
     294             : {
     295         108 :   ssize_t result;
     296         108 :   *output = create2_cell_body_new();
     297         108 :   if (NULL == *output)
     298             :     return -1;
     299         108 :   result = create2_cell_body_parse_into(*output, input, len_in);
     300         108 :   if (result < 0) {
     301         102 :     create2_cell_body_free(*output);
     302         102 :     *output = NULL;
     303             :   }
     304             :   return result;
     305             : }
     306             : ed25519_cert_extension_t *
     307        2154 : ed25519_cert_extension_new(void)
     308             : {
     309        2154 :   ed25519_cert_extension_t *val = trunnel_calloc(1, sizeof(ed25519_cert_extension_t));
     310        2154 :   if (NULL == val)
     311           0 :     return NULL;
     312             :   return val;
     313             : }
     314             : 
     315             : /** Release all storage held inside 'obj', but do not free 'obj'.
     316             :  */
     317             : static void
     318        2154 : ed25519_cert_extension_clear(ed25519_cert_extension_t *obj)
     319             : {
     320        2154 :   (void) obj;
     321        2154 :   TRUNNEL_DYNARRAY_WIPE(&obj->un_unparsed);
     322        2154 :   TRUNNEL_DYNARRAY_CLEAR(&obj->un_unparsed);
     323        2154 : }
     324             : 
     325             : void
     326        2154 : ed25519_cert_extension_free(ed25519_cert_extension_t *obj)
     327             : {
     328        2154 :   if (obj == NULL)
     329             :     return;
     330        2154 :   ed25519_cert_extension_clear(obj);
     331        2154 :   trunnel_memwipe(obj, sizeof(ed25519_cert_extension_t));
     332        2154 :   trunnel_free_(obj);
     333             : }
     334             : 
     335             : uint16_t
     336           0 : ed25519_cert_extension_get_ext_length(const ed25519_cert_extension_t *inp)
     337             : {
     338           0 :   return inp->ext_length;
     339             : }
     340             : int
     341           0 : ed25519_cert_extension_set_ext_length(ed25519_cert_extension_t *inp, uint16_t val)
     342             : {
     343           0 :   inp->ext_length = val;
     344           0 :   return 0;
     345             : }
     346             : uint8_t
     347           0 : ed25519_cert_extension_get_ext_type(const ed25519_cert_extension_t *inp)
     348             : {
     349           0 :   return inp->ext_type;
     350             : }
     351             : int
     352           0 : ed25519_cert_extension_set_ext_type(ed25519_cert_extension_t *inp, uint8_t val)
     353             : {
     354           0 :   inp->ext_type = val;
     355           0 :   return 0;
     356             : }
     357             : uint8_t
     358           0 : ed25519_cert_extension_get_ext_flags(const ed25519_cert_extension_t *inp)
     359             : {
     360           0 :   return inp->ext_flags;
     361             : }
     362             : int
     363           0 : ed25519_cert_extension_set_ext_flags(ed25519_cert_extension_t *inp, uint8_t val)
     364             : {
     365           0 :   inp->ext_flags = val;
     366           0 :   return 0;
     367             : }
     368             : size_t
     369           0 : ed25519_cert_extension_getlen_un_signing_key(const ed25519_cert_extension_t *inp)
     370             : {
     371           0 :   (void)inp;  return 32;
     372             : }
     373             : 
     374             : uint8_t
     375           0 : ed25519_cert_extension_get_un_signing_key(ed25519_cert_extension_t *inp, size_t idx)
     376             : {
     377           0 :   trunnel_assert(idx < 32);
     378           0 :   return inp->un_signing_key[idx];
     379             : }
     380             : 
     381             : uint8_t
     382           0 : ed25519_cert_extension_getconst_un_signing_key(const ed25519_cert_extension_t *inp, size_t idx)
     383             : {
     384           0 :   return ed25519_cert_extension_get_un_signing_key((ed25519_cert_extension_t*)inp, idx);
     385             : }
     386             : int
     387           0 : ed25519_cert_extension_set_un_signing_key(ed25519_cert_extension_t *inp, size_t idx, uint8_t elt)
     388             : {
     389           0 :   trunnel_assert(idx < 32);
     390           0 :   inp->un_signing_key[idx] = elt;
     391           0 :   return 0;
     392             : }
     393             : 
     394             : uint8_t *
     395           0 : ed25519_cert_extension_getarray_un_signing_key(ed25519_cert_extension_t *inp)
     396             : {
     397           0 :   return inp->un_signing_key;
     398             : }
     399             : const uint8_t  *
     400           0 : ed25519_cert_extension_getconstarray_un_signing_key(const ed25519_cert_extension_t *inp)
     401             : {
     402           0 :   return (const uint8_t  *)ed25519_cert_extension_getarray_un_signing_key((ed25519_cert_extension_t*)inp);
     403             : }
     404             : size_t
     405           0 : ed25519_cert_extension_getlen_un_unparsed(const ed25519_cert_extension_t *inp)
     406             : {
     407           0 :   return TRUNNEL_DYNARRAY_LEN(&inp->un_unparsed);
     408             : }
     409             : 
     410             : uint8_t
     411           0 : ed25519_cert_extension_get_un_unparsed(ed25519_cert_extension_t *inp, size_t idx)
     412             : {
     413           0 :   return TRUNNEL_DYNARRAY_GET(&inp->un_unparsed, idx);
     414             : }
     415             : 
     416             : uint8_t
     417           0 : ed25519_cert_extension_getconst_un_unparsed(const ed25519_cert_extension_t *inp, size_t idx)
     418             : {
     419           0 :   return ed25519_cert_extension_get_un_unparsed((ed25519_cert_extension_t*)inp, idx);
     420             : }
     421             : int
     422           0 : ed25519_cert_extension_set_un_unparsed(ed25519_cert_extension_t *inp, size_t idx, uint8_t elt)
     423             : {
     424           0 :   TRUNNEL_DYNARRAY_SET(&inp->un_unparsed, idx, elt);
     425           0 :   return 0;
     426             : }
     427             : int
     428           0 : ed25519_cert_extension_add_un_unparsed(ed25519_cert_extension_t *inp, uint8_t elt)
     429             : {
     430           0 :   TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->un_unparsed, elt, {});
     431           0 :   return 0;
     432           0 :  trunnel_alloc_failed:
     433           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     434           0 :   return -1;
     435             : }
     436             : 
     437             : uint8_t *
     438           0 : ed25519_cert_extension_getarray_un_unparsed(ed25519_cert_extension_t *inp)
     439             : {
     440           0 :   return inp->un_unparsed.elts_;
     441             : }
     442             : const uint8_t  *
     443           0 : ed25519_cert_extension_getconstarray_un_unparsed(const ed25519_cert_extension_t *inp)
     444             : {
     445           0 :   return (const uint8_t  *)ed25519_cert_extension_getarray_un_unparsed((ed25519_cert_extension_t*)inp);
     446             : }
     447             : int
     448           0 : ed25519_cert_extension_setlen_un_unparsed(ed25519_cert_extension_t *inp, size_t newlen)
     449             : {
     450           0 :   uint8_t *newptr;
     451           0 :   newptr = trunnel_dynarray_setlen(&inp->un_unparsed.allocated_,
     452           0 :                  &inp->un_unparsed.n_, inp->un_unparsed.elts_, newlen,
     453             :                  sizeof(inp->un_unparsed.elts_[0]), (trunnel_free_fn_t) NULL,
     454             :                  &inp->trunnel_error_code_);
     455           0 :   if (newlen != 0 && newptr == NULL)
     456           0 :     goto trunnel_alloc_failed;
     457           0 :   inp->un_unparsed.elts_ = newptr;
     458           0 :   return 0;
     459           0 :  trunnel_alloc_failed:
     460           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     461           0 :   return -1;
     462             : }
     463             : const char *
     464        1276 : ed25519_cert_extension_check(const ed25519_cert_extension_t *obj)
     465             : {
     466        1276 :   if (obj == NULL)
     467             :     return "Object was NULL";
     468        1276 :   if (obj->trunnel_error_code_)
     469           0 :     return "A set function failed on this object";
     470             :   switch (obj->ext_type) {
     471             : 
     472             :     case CERTEXT_SIGNED_WITH_KEY:
     473             :       break;
     474             : 
     475             :     default:
     476             :       break;
     477             :   }
     478             :   return NULL;
     479             : }
     480             : 
     481             : ssize_t
     482         319 : ed25519_cert_extension_encoded_len(const ed25519_cert_extension_t *obj)
     483             : {
     484         319 :   ssize_t result = 0;
     485             : 
     486         319 :   if (NULL != ed25519_cert_extension_check(obj))
     487             :      return -1;
     488             : 
     489             : 
     490             :   /* Length of u16 ext_length */
     491         319 :   result += 2;
     492             : 
     493             :   /* Length of u8 ext_type */
     494         319 :   result += 1;
     495             : 
     496             :   /* Length of u8 ext_flags */
     497         319 :   result += 1;
     498         319 :   switch (obj->ext_type) {
     499             : 
     500             :     case CERTEXT_SIGNED_WITH_KEY:
     501             : 
     502             :       /* Length of u8 un_signing_key[32] */
     503             :       result += 32;
     504             :       break;
     505             : 
     506           0 :     default:
     507             : 
     508             :       /* Length of u8 un_unparsed[] */
     509           0 :       result += TRUNNEL_DYNARRAY_LEN(&obj->un_unparsed);
     510           0 :       break;
     511             :   }
     512             :   return result;
     513             : }
     514             : int
     515           0 : ed25519_cert_extension_clear_errors(ed25519_cert_extension_t *obj)
     516             : {
     517           0 :   int r = obj->trunnel_error_code_;
     518           0 :   obj->trunnel_error_code_ = 0;
     519           0 :   return r;
     520             : }
     521             : ssize_t
     522         319 : ed25519_cert_extension_encode(uint8_t *output, const size_t avail, const ed25519_cert_extension_t *obj)
     523             : {
     524         319 :   ssize_t result = 0;
     525         319 :   size_t written = 0;
     526         319 :   uint8_t *ptr = output;
     527         319 :   const char *msg;
     528             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     529             :   const ssize_t encoded_len = ed25519_cert_extension_encoded_len(obj);
     530             : #endif
     531             : 
     532         319 :   uint8_t *backptr_ext_length = NULL;
     533             : 
     534         319 :   if (NULL != (msg = ed25519_cert_extension_check(obj)))
     535           0 :     goto check_failed;
     536             : 
     537             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     538             :   trunnel_assert(encoded_len >= 0);
     539             : #endif
     540             : 
     541             :   /* Encode u16 ext_length */
     542         319 :   backptr_ext_length = ptr;
     543         319 :   trunnel_assert(written <= avail);
     544         319 :   if (avail - written < 2)
     545           0 :     goto truncated;
     546         319 :   trunnel_set_uint16(ptr, trunnel_htons(obj->ext_length));
     547         319 :   written += 2; ptr += 2;
     548             : 
     549             :   /* Encode u8 ext_type */
     550         319 :   trunnel_assert(written <= avail);
     551         319 :   if (avail - written < 1)
     552           0 :     goto truncated;
     553         319 :   trunnel_set_uint8(ptr, (obj->ext_type));
     554         319 :   written += 1; ptr += 1;
     555             : 
     556             :   /* Encode u8 ext_flags */
     557         319 :   trunnel_assert(written <= avail);
     558         319 :   if (avail - written < 1)
     559           0 :     goto truncated;
     560         319 :   trunnel_set_uint8(ptr, (obj->ext_flags));
     561         319 :   written += 1; ptr += 1;
     562             :   {
     563         319 :     size_t written_before_union = written;
     564             : 
     565             :     /* Encode union un[ext_type] */
     566         319 :     trunnel_assert(written <= avail);
     567         319 :     switch (obj->ext_type) {
     568             : 
     569             :       case CERTEXT_SIGNED_WITH_KEY:
     570             : 
     571             :         /* Encode u8 un_signing_key[32] */
     572         319 :         trunnel_assert(written <= avail);
     573         319 :         if (avail - written < 32)
     574           0 :           goto truncated;
     575         319 :         memcpy(ptr, obj->un_signing_key, 32);
     576         319 :         written += 32; ptr += 32;
     577         319 :         break;
     578             : 
     579           0 :       default:
     580             : 
     581             :         /* Encode u8 un_unparsed[] */
     582             :         {
     583           0 :           size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->un_unparsed);
     584           0 :           trunnel_assert(written <= avail);
     585           0 :           if (avail - written < elt_len)
     586           0 :             goto truncated;
     587           0 :           if (elt_len)
     588           0 :             memcpy(ptr, obj->un_unparsed.elts_, elt_len);
     589           0 :           written += elt_len; ptr += elt_len;
     590             :         }
     591           0 :         break;
     592             :     }
     593             :     /* Write the length field back to ext_length */
     594         319 :     trunnel_assert(written >= written_before_union);
     595             : #if UINT16_MAX < SIZE_MAX
     596         319 :     if (written - written_before_union > UINT16_MAX)
     597           0 :       goto check_failed;
     598             : #endif
     599         319 :     trunnel_set_uint16(backptr_ext_length, trunnel_htons(written - written_before_union));
     600             :   }
     601             : 
     602             : 
     603         319 :   trunnel_assert(ptr == output + written);
     604             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     605             :   {
     606             :     trunnel_assert(encoded_len >= 0);
     607             :     trunnel_assert((size_t)encoded_len == written);
     608             :   }
     609             : 
     610             : #endif
     611             : 
     612         319 :   return written;
     613             : 
     614           0 :  truncated:
     615           0 :   result = -2;
     616           0 :   goto fail;
     617           0 :  check_failed:
     618           0 :   (void)msg;
     619           0 :   result = -1;
     620           0 :   goto fail;
     621             :  fail:
     622             :   trunnel_assert(result < 0);
     623             :   return result;
     624             : }
     625             : 
     626             : /** As ed25519_cert_extension_parse(), but do not allocate the output
     627             :  * object.
     628             :  */
     629             : static ssize_t
     630        1835 : ed25519_cert_extension_parse_into(ed25519_cert_extension_t *obj, const uint8_t *input, const size_t len_in)
     631             : {
     632        1835 :   const uint8_t *ptr = input;
     633        1835 :   size_t remaining = len_in;
     634        1835 :   ssize_t result = 0;
     635        1835 :   (void)result;
     636             : 
     637             :   /* Parse u16 ext_length */
     638        1835 :   CHECK_REMAINING(2, truncated);
     639        1829 :   obj->ext_length = trunnel_ntohs(trunnel_get_uint16(ptr));
     640        1829 :   remaining -= 2; ptr += 2;
     641             : 
     642             :   /* Parse u8 ext_type */
     643        1829 :   CHECK_REMAINING(1, truncated);
     644        1826 :   obj->ext_type = (trunnel_get_uint8(ptr));
     645        1826 :   remaining -= 1; ptr += 1;
     646             : 
     647             :   /* Parse u8 ext_flags */
     648        1826 :   CHECK_REMAINING(1, truncated);
     649        1823 :   obj->ext_flags = (trunnel_get_uint8(ptr));
     650        1823 :   remaining -= 1; ptr += 1;
     651             :   {
     652        1823 :     size_t remaining_after;
     653        1823 :     CHECK_REMAINING(obj->ext_length, truncated);
     654        1821 :     remaining_after = remaining - obj->ext_length;
     655        1821 :     remaining = obj->ext_length;
     656             : 
     657             :     /* Parse union un[ext_type] */
     658        1821 :     switch (obj->ext_type) {
     659             : 
     660        1113 :       case CERTEXT_SIGNED_WITH_KEY:
     661             : 
     662             :         /* Parse u8 un_signing_key[32] */
     663        1113 :         CHECK_REMAINING(32, fail);
     664        1111 :         memcpy(obj->un_signing_key, ptr, 32);
     665        1111 :         remaining -= 32; ptr += 32;
     666        1111 :         break;
     667             : 
     668         708 :       default:
     669             : 
     670             :         /* Parse u8 un_unparsed[] */
     671         708 :         TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->un_unparsed, remaining, {});
     672         708 :         obj->un_unparsed.n_ = remaining;
     673         708 :         if (remaining)
     674          81 :           memcpy(obj->un_unparsed.elts_, ptr, remaining);
     675         708 :         ptr += remaining; remaining -= remaining;
     676         708 :         break;
     677             :     }
     678        1819 :     if (remaining != 0)
     679           1 :       goto fail;
     680        1818 :     remaining = remaining_after;
     681             :   }
     682        1818 :   trunnel_assert(ptr + remaining == input + len_in);
     683        1818 :   return len_in - remaining;
     684             : 
     685             :  truncated:
     686             :   return -2;
     687           0 :  trunnel_alloc_failed:
     688           0 :   return -1;
     689             :  fail:
     690        1835 :   result = -1;
     691             :   return result;
     692             : }
     693             : 
     694             : ssize_t
     695        1835 : ed25519_cert_extension_parse(ed25519_cert_extension_t **output, const uint8_t *input, const size_t len_in)
     696             : {
     697        1835 :   ssize_t result;
     698        1835 :   *output = ed25519_cert_extension_new();
     699        1835 :   if (NULL == *output)
     700             :     return -1;
     701        1835 :   result = ed25519_cert_extension_parse_into(*output, input, len_in);
     702        1835 :   if (result < 0) {
     703          17 :     ed25519_cert_extension_free(*output);
     704          17 :     *output = NULL;
     705             :   }
     706             :   return result;
     707             : }
     708             : extend1_cell_body_t *
     709           2 : extend1_cell_body_new(void)
     710             : {
     711           2 :   extend1_cell_body_t *val = trunnel_calloc(1, sizeof(extend1_cell_body_t));
     712           2 :   if (NULL == val)
     713           0 :     return NULL;
     714             :   return val;
     715             : }
     716             : 
     717             : /** Release all storage held inside 'obj', but do not free 'obj'.
     718             :  */
     719             : static void
     720             : extend1_cell_body_clear(extend1_cell_body_t *obj)
     721             : {
     722             :   (void) obj;
     723             : }
     724             : 
     725             : void
     726           2 : extend1_cell_body_free(extend1_cell_body_t *obj)
     727             : {
     728           2 :   if (obj == NULL)
     729             :     return;
     730           2 :   extend1_cell_body_clear(obj);
     731           2 :   trunnel_memwipe(obj, sizeof(extend1_cell_body_t));
     732           2 :   trunnel_free_(obj);
     733             : }
     734             : 
     735             : uint32_t
     736           0 : extend1_cell_body_get_ipv4addr(const extend1_cell_body_t *inp)
     737             : {
     738           0 :   return inp->ipv4addr;
     739             : }
     740             : int
     741           0 : extend1_cell_body_set_ipv4addr(extend1_cell_body_t *inp, uint32_t val)
     742             : {
     743           0 :   inp->ipv4addr = val;
     744           0 :   return 0;
     745             : }
     746             : uint16_t
     747           0 : extend1_cell_body_get_port(const extend1_cell_body_t *inp)
     748             : {
     749           0 :   return inp->port;
     750             : }
     751             : int
     752           0 : extend1_cell_body_set_port(extend1_cell_body_t *inp, uint16_t val)
     753             : {
     754           0 :   inp->port = val;
     755           0 :   return 0;
     756             : }
     757             : size_t
     758           0 : extend1_cell_body_getlen_onionskin(const extend1_cell_body_t *inp)
     759             : {
     760           0 :   (void)inp;  return 186;
     761             : }
     762             : 
     763             : uint8_t
     764           0 : extend1_cell_body_get_onionskin(extend1_cell_body_t *inp, size_t idx)
     765             : {
     766           0 :   trunnel_assert(idx < 186);
     767           0 :   return inp->onionskin[idx];
     768             : }
     769             : 
     770             : uint8_t
     771           0 : extend1_cell_body_getconst_onionskin(const extend1_cell_body_t *inp, size_t idx)
     772             : {
     773           0 :   return extend1_cell_body_get_onionskin((extend1_cell_body_t*)inp, idx);
     774             : }
     775             : int
     776           0 : extend1_cell_body_set_onionskin(extend1_cell_body_t *inp, size_t idx, uint8_t elt)
     777             : {
     778           0 :   trunnel_assert(idx < 186);
     779           0 :   inp->onionskin[idx] = elt;
     780           0 :   return 0;
     781             : }
     782             : 
     783             : uint8_t *
     784           0 : extend1_cell_body_getarray_onionskin(extend1_cell_body_t *inp)
     785             : {
     786           0 :   return inp->onionskin;
     787             : }
     788             : const uint8_t  *
     789           0 : extend1_cell_body_getconstarray_onionskin(const extend1_cell_body_t *inp)
     790             : {
     791           0 :   return (const uint8_t  *)extend1_cell_body_getarray_onionskin((extend1_cell_body_t*)inp);
     792             : }
     793             : size_t
     794           0 : extend1_cell_body_getlen_identity(const extend1_cell_body_t *inp)
     795             : {
     796           0 :   (void)inp;  return 20;
     797             : }
     798             : 
     799             : uint8_t
     800           0 : extend1_cell_body_get_identity(extend1_cell_body_t *inp, size_t idx)
     801             : {
     802           0 :   trunnel_assert(idx < 20);
     803           0 :   return inp->identity[idx];
     804             : }
     805             : 
     806             : uint8_t
     807           0 : extend1_cell_body_getconst_identity(const extend1_cell_body_t *inp, size_t idx)
     808             : {
     809           0 :   return extend1_cell_body_get_identity((extend1_cell_body_t*)inp, idx);
     810             : }
     811             : int
     812           0 : extend1_cell_body_set_identity(extend1_cell_body_t *inp, size_t idx, uint8_t elt)
     813             : {
     814           0 :   trunnel_assert(idx < 20);
     815           0 :   inp->identity[idx] = elt;
     816           0 :   return 0;
     817             : }
     818             : 
     819             : uint8_t *
     820           0 : extend1_cell_body_getarray_identity(extend1_cell_body_t *inp)
     821             : {
     822           0 :   return inp->identity;
     823             : }
     824             : const uint8_t  *
     825           0 : extend1_cell_body_getconstarray_identity(const extend1_cell_body_t *inp)
     826             : {
     827           0 :   return (const uint8_t  *)extend1_cell_body_getarray_identity((extend1_cell_body_t*)inp);
     828             : }
     829             : const char *
     830           0 : extend1_cell_body_check(const extend1_cell_body_t *obj)
     831             : {
     832           0 :   if (obj == NULL)
     833             :     return "Object was NULL";
     834           0 :   if (obj->trunnel_error_code_)
     835           0 :     return "A set function failed on this object";
     836             :   return NULL;
     837             : }
     838             : 
     839             : ssize_t
     840           0 : extend1_cell_body_encoded_len(const extend1_cell_body_t *obj)
     841             : {
     842           0 :   ssize_t result = 0;
     843             : 
     844           0 :   if (NULL != extend1_cell_body_check(obj))
     845           0 :      return -1;
     846             : 
     847             : 
     848             :   /* Length of u32 ipv4addr */
     849             :   result += 4;
     850             : 
     851             :   /* Length of u16 port */
     852             :   result += 2;
     853             : 
     854             :   /* Length of u8 onionskin[186] */
     855             :   result += 186;
     856             : 
     857             :   /* Length of u8 identity[20] */
     858           0 :   result += 20;
     859             :   return result;
     860             : }
     861             : int
     862           0 : extend1_cell_body_clear_errors(extend1_cell_body_t *obj)
     863             : {
     864           0 :   int r = obj->trunnel_error_code_;
     865           0 :   obj->trunnel_error_code_ = 0;
     866           0 :   return r;
     867             : }
     868             : ssize_t
     869           0 : extend1_cell_body_encode(uint8_t *output, const size_t avail, const extend1_cell_body_t *obj)
     870             : {
     871           0 :   ssize_t result = 0;
     872           0 :   size_t written = 0;
     873           0 :   uint8_t *ptr = output;
     874           0 :   const char *msg;
     875             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     876             :   const ssize_t encoded_len = extend1_cell_body_encoded_len(obj);
     877             : #endif
     878             : 
     879           0 :   if (NULL != (msg = extend1_cell_body_check(obj)))
     880           0 :     goto check_failed;
     881             : 
     882             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     883             :   trunnel_assert(encoded_len >= 0);
     884             : #endif
     885             : 
     886             :   /* Encode u32 ipv4addr */
     887           0 :   trunnel_assert(written <= avail);
     888           0 :   if (avail - written < 4)
     889           0 :     goto truncated;
     890           0 :   trunnel_set_uint32(ptr, trunnel_htonl(obj->ipv4addr));
     891           0 :   written += 4; ptr += 4;
     892             : 
     893             :   /* Encode u16 port */
     894           0 :   trunnel_assert(written <= avail);
     895           0 :   if (avail - written < 2)
     896           0 :     goto truncated;
     897           0 :   trunnel_set_uint16(ptr, trunnel_htons(obj->port));
     898           0 :   written += 2; ptr += 2;
     899             : 
     900             :   /* Encode u8 onionskin[186] */
     901           0 :   trunnel_assert(written <= avail);
     902           0 :   if (avail - written < 186)
     903           0 :     goto truncated;
     904           0 :   memcpy(ptr, obj->onionskin, 186);
     905           0 :   written += 186; ptr += 186;
     906             : 
     907             :   /* Encode u8 identity[20] */
     908           0 :   trunnel_assert(written <= avail);
     909           0 :   if (avail - written < 20)
     910           0 :     goto truncated;
     911           0 :   memcpy(ptr, obj->identity, 20);
     912           0 :   written += 20; ptr += 20;
     913             : 
     914             : 
     915           0 :   trunnel_assert(ptr == output + written);
     916             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     917             :   {
     918             :     trunnel_assert(encoded_len >= 0);
     919             :     trunnel_assert((size_t)encoded_len == written);
     920             :   }
     921             : 
     922             : #endif
     923             : 
     924             :   return written;
     925             : 
     926           0 :  truncated:
     927           0 :   result = -2;
     928           0 :   goto fail;
     929           0 :  check_failed:
     930           0 :   (void)msg;
     931           0 :   result = -1;
     932           0 :   goto fail;
     933             :  fail:
     934             :   trunnel_assert(result < 0);
     935             :   return result;
     936             : }
     937             : 
     938             : /** As extend1_cell_body_parse(), but do not allocate the output
     939             :  * object.
     940             :  */
     941             : static ssize_t
     942           2 : extend1_cell_body_parse_into(extend1_cell_body_t *obj, const uint8_t *input, const size_t len_in)
     943             : {
     944           2 :   const uint8_t *ptr = input;
     945           2 :   size_t remaining = len_in;
     946           2 :   ssize_t result = 0;
     947           2 :   (void)result;
     948             : 
     949             :   /* Parse u32 ipv4addr */
     950           2 :   CHECK_REMAINING(4, truncated);
     951           2 :   obj->ipv4addr = trunnel_ntohl(trunnel_get_uint32(ptr));
     952           2 :   remaining -= 4; ptr += 4;
     953             : 
     954             :   /* Parse u16 port */
     955           2 :   CHECK_REMAINING(2, truncated);
     956           2 :   obj->port = trunnel_ntohs(trunnel_get_uint16(ptr));
     957           2 :   remaining -= 2; ptr += 2;
     958             : 
     959             :   /* Parse u8 onionskin[186] */
     960           2 :   CHECK_REMAINING(186, truncated);
     961           2 :   memcpy(obj->onionskin, ptr, 186);
     962           2 :   remaining -= 186; ptr += 186;
     963             : 
     964             :   /* Parse u8 identity[20] */
     965           2 :   CHECK_REMAINING(20, truncated);
     966           2 :   memcpy(obj->identity, ptr, 20);
     967           2 :   remaining -= 20; ptr += 20;
     968           2 :   trunnel_assert(ptr + remaining == input + len_in);
     969             :   return len_in - remaining;
     970             : 
     971             :  truncated:
     972             :   return -2;
     973             : }
     974             : 
     975             : ssize_t
     976           2 : extend1_cell_body_parse(extend1_cell_body_t **output, const uint8_t *input, const size_t len_in)
     977             : {
     978           2 :   ssize_t result;
     979           2 :   *output = extend1_cell_body_new();
     980           2 :   if (NULL == *output)
     981             :     return -1;
     982           2 :   result = extend1_cell_body_parse_into(*output, input, len_in);
     983           2 :   if (result < 0) {
     984           0 :     extend1_cell_body_free(*output);
     985           0 :     *output = NULL;
     986             :   }
     987             :   return result;
     988             : }
     989             : link_specifier_t *
     990       26563 : link_specifier_new(void)
     991             : {
     992       26563 :   link_specifier_t *val = trunnel_calloc(1, sizeof(link_specifier_t));
     993       26563 :   if (NULL == val)
     994           0 :     return NULL;
     995             :   return val;
     996             : }
     997             : 
     998             : /** Release all storage held inside 'obj', but do not free 'obj'.
     999             :  */
    1000             : static void
    1001       26547 : link_specifier_clear(link_specifier_t *obj)
    1002             : {
    1003       26547 :   (void) obj;
    1004       26547 :   TRUNNEL_DYNARRAY_WIPE(&obj->un_unrecognized);
    1005       26547 :   TRUNNEL_DYNARRAY_CLEAR(&obj->un_unrecognized);
    1006       26547 : }
    1007             : 
    1008             : void
    1009       26547 : link_specifier_free(link_specifier_t *obj)
    1010             : {
    1011       26547 :   if (obj == NULL)
    1012             :     return;
    1013       26547 :   link_specifier_clear(obj);
    1014       26547 :   trunnel_memwipe(obj, sizeof(link_specifier_t));
    1015       26547 :   trunnel_free_(obj);
    1016             : }
    1017             : 
    1018             : uint8_t
    1019         335 : link_specifier_get_ls_type(const link_specifier_t *inp)
    1020             : {
    1021         335 :   return inp->ls_type;
    1022             : }
    1023             : int
    1024         207 : link_specifier_set_ls_type(link_specifier_t *inp, uint8_t val)
    1025             : {
    1026         207 :   inp->ls_type = val;
    1027         207 :   return 0;
    1028             : }
    1029             : uint8_t
    1030           0 : link_specifier_get_ls_len(const link_specifier_t *inp)
    1031             : {
    1032           0 :   return inp->ls_len;
    1033             : }
    1034             : int
    1035           9 : link_specifier_set_ls_len(link_specifier_t *inp, uint8_t val)
    1036             : {
    1037           9 :   inp->ls_len = val;
    1038           9 :   return 0;
    1039             : }
    1040             : uint32_t
    1041         109 : link_specifier_get_un_ipv4_addr(const link_specifier_t *inp)
    1042             : {
    1043         109 :   return inp->un_ipv4_addr;
    1044             : }
    1045             : int
    1046          70 : link_specifier_set_un_ipv4_addr(link_specifier_t *inp, uint32_t val)
    1047             : {
    1048          70 :   inp->un_ipv4_addr = val;
    1049          70 :   return 0;
    1050             : }
    1051             : uint16_t
    1052         109 : link_specifier_get_un_ipv4_port(const link_specifier_t *inp)
    1053             : {
    1054         109 :   return inp->un_ipv4_port;
    1055             : }
    1056             : int
    1057          70 : link_specifier_set_un_ipv4_port(link_specifier_t *inp, uint16_t val)
    1058             : {
    1059          70 :   inp->un_ipv4_port = val;
    1060          70 :   return 0;
    1061             : }
    1062             : size_t
    1063          32 : link_specifier_getlen_un_ipv6_addr(const link_specifier_t *inp)
    1064             : {
    1065          32 :   (void)inp;  return 16;
    1066             : }
    1067             : 
    1068             : uint8_t
    1069           0 : link_specifier_get_un_ipv6_addr(link_specifier_t *inp, size_t idx)
    1070             : {
    1071           0 :   trunnel_assert(idx < 16);
    1072           0 :   return inp->un_ipv6_addr[idx];
    1073             : }
    1074             : 
    1075             : uint8_t
    1076           0 : link_specifier_getconst_un_ipv6_addr(const link_specifier_t *inp, size_t idx)
    1077             : {
    1078           0 :   return link_specifier_get_un_ipv6_addr((link_specifier_t*)inp, idx);
    1079             : }
    1080             : int
    1081           0 : link_specifier_set_un_ipv6_addr(link_specifier_t *inp, size_t idx, uint8_t elt)
    1082             : {
    1083           0 :   trunnel_assert(idx < 16);
    1084           0 :   inp->un_ipv6_addr[idx] = elt;
    1085           0 :   return 0;
    1086             : }
    1087             : 
    1088             : uint8_t *
    1089          44 : link_specifier_getarray_un_ipv6_addr(link_specifier_t *inp)
    1090             : {
    1091          44 :   return inp->un_ipv6_addr;
    1092             : }
    1093             : const uint8_t  *
    1094          21 : link_specifier_getconstarray_un_ipv6_addr(const link_specifier_t *inp)
    1095             : {
    1096          21 :   return (const uint8_t  *)link_specifier_getarray_un_ipv6_addr((link_specifier_t*)inp);
    1097             : }
    1098             : uint16_t
    1099          21 : link_specifier_get_un_ipv6_port(const link_specifier_t *inp)
    1100             : {
    1101          21 :   return inp->un_ipv6_port;
    1102             : }
    1103             : int
    1104          23 : link_specifier_set_un_ipv6_port(link_specifier_t *inp, uint16_t val)
    1105             : {
    1106          23 :   inp->un_ipv6_port = val;
    1107          23 :   return 0;
    1108             : }
    1109             : size_t
    1110         230 : link_specifier_getlen_un_legacy_id(const link_specifier_t *inp)
    1111             : {
    1112         230 :   (void)inp;  return 20;
    1113             : }
    1114             : 
    1115             : uint8_t
    1116           0 : link_specifier_get_un_legacy_id(link_specifier_t *inp, size_t idx)
    1117             : {
    1118           0 :   trunnel_assert(idx < 20);
    1119           0 :   return inp->un_legacy_id[idx];
    1120             : }
    1121             : 
    1122             : uint8_t
    1123           0 : link_specifier_getconst_un_legacy_id(const link_specifier_t *inp, size_t idx)
    1124             : {
    1125           0 :   return link_specifier_get_un_legacy_id((link_specifier_t*)inp, idx);
    1126             : }
    1127             : int
    1128           0 : link_specifier_set_un_legacy_id(link_specifier_t *inp, size_t idx, uint8_t elt)
    1129             : {
    1130           0 :   trunnel_assert(idx < 20);
    1131           0 :   inp->un_legacy_id[idx] = elt;
    1132           0 :   return 0;
    1133             : }
    1134             : 
    1135             : uint8_t *
    1136         230 : link_specifier_getarray_un_legacy_id(link_specifier_t *inp)
    1137             : {
    1138         230 :   return inp->un_legacy_id;
    1139             : }
    1140             : const uint8_t  *
    1141         127 : link_specifier_getconstarray_un_legacy_id(const link_specifier_t *inp)
    1142             : {
    1143         127 :   return (const uint8_t  *)link_specifier_getarray_un_legacy_id((link_specifier_t*)inp);
    1144             : }
    1145             : size_t
    1146           4 : link_specifier_getlen_un_ed25519_id(const link_specifier_t *inp)
    1147             : {
    1148           4 :   (void)inp;  return 32;
    1149             : }
    1150             : 
    1151             : uint8_t
    1152           0 : link_specifier_get_un_ed25519_id(link_specifier_t *inp, size_t idx)
    1153             : {
    1154           0 :   trunnel_assert(idx < 32);
    1155           0 :   return inp->un_ed25519_id[idx];
    1156             : }
    1157             : 
    1158             : uint8_t
    1159           0 : link_specifier_getconst_un_ed25519_id(const link_specifier_t *inp, size_t idx)
    1160             : {
    1161           0 :   return link_specifier_get_un_ed25519_id((link_specifier_t*)inp, idx);
    1162             : }
    1163             : int
    1164           0 : link_specifier_set_un_ed25519_id(link_specifier_t *inp, size_t idx, uint8_t elt)
    1165             : {
    1166           0 :   trunnel_assert(idx < 32);
    1167           0 :   inp->un_ed25519_id[idx] = elt;
    1168           0 :   return 0;
    1169             : }
    1170             : 
    1171             : uint8_t *
    1172           2 : link_specifier_getarray_un_ed25519_id(link_specifier_t *inp)
    1173             : {
    1174           2 :   return inp->un_ed25519_id;
    1175             : }
    1176             : const uint8_t  *
    1177           0 : link_specifier_getconstarray_un_ed25519_id(const link_specifier_t *inp)
    1178             : {
    1179           0 :   return (const uint8_t  *)link_specifier_getarray_un_ed25519_id((link_specifier_t*)inp);
    1180             : }
    1181             : size_t
    1182           0 : link_specifier_getlen_un_unrecognized(const link_specifier_t *inp)
    1183             : {
    1184           0 :   return TRUNNEL_DYNARRAY_LEN(&inp->un_unrecognized);
    1185             : }
    1186             : 
    1187             : uint8_t
    1188           0 : link_specifier_get_un_unrecognized(link_specifier_t *inp, size_t idx)
    1189             : {
    1190           0 :   return TRUNNEL_DYNARRAY_GET(&inp->un_unrecognized, idx);
    1191             : }
    1192             : 
    1193             : uint8_t
    1194           0 : link_specifier_getconst_un_unrecognized(const link_specifier_t *inp, size_t idx)
    1195             : {
    1196           0 :   return link_specifier_get_un_unrecognized((link_specifier_t*)inp, idx);
    1197             : }
    1198             : int
    1199           0 : link_specifier_set_un_unrecognized(link_specifier_t *inp, size_t idx, uint8_t elt)
    1200             : {
    1201           0 :   TRUNNEL_DYNARRAY_SET(&inp->un_unrecognized, idx, elt);
    1202           0 :   return 0;
    1203             : }
    1204             : int
    1205           0 : link_specifier_add_un_unrecognized(link_specifier_t *inp, uint8_t elt)
    1206             : {
    1207           0 :   TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->un_unrecognized, elt, {});
    1208           0 :   return 0;
    1209           0 :  trunnel_alloc_failed:
    1210           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    1211           0 :   return -1;
    1212             : }
    1213             : 
    1214             : uint8_t *
    1215           0 : link_specifier_getarray_un_unrecognized(link_specifier_t *inp)
    1216             : {
    1217           0 :   return inp->un_unrecognized.elts_;
    1218             : }
    1219             : const uint8_t  *
    1220           0 : link_specifier_getconstarray_un_unrecognized(const link_specifier_t *inp)
    1221             : {
    1222           0 :   return (const uint8_t  *)link_specifier_getarray_un_unrecognized((link_specifier_t*)inp);
    1223             : }
    1224             : int
    1225           0 : link_specifier_setlen_un_unrecognized(link_specifier_t *inp, size_t newlen)
    1226             : {
    1227           0 :   uint8_t *newptr;
    1228           0 :   newptr = trunnel_dynarray_setlen(&inp->un_unrecognized.allocated_,
    1229           0 :                  &inp->un_unrecognized.n_, inp->un_unrecognized.elts_, newlen,
    1230             :                  sizeof(inp->un_unrecognized.elts_[0]), (trunnel_free_fn_t) NULL,
    1231             :                  &inp->trunnel_error_code_);
    1232           0 :   if (newlen != 0 && newptr == NULL)
    1233           0 :     goto trunnel_alloc_failed;
    1234           0 :   inp->un_unrecognized.elts_ = newptr;
    1235           0 :   return 0;
    1236           0 :  trunnel_alloc_failed:
    1237           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    1238           0 :   return -1;
    1239             : }
    1240             : const char *
    1241        1878 : link_specifier_check(const link_specifier_t *obj)
    1242             : {
    1243        1878 :   if (obj == NULL)
    1244             :     return "Object was NULL";
    1245        1878 :   if (obj->trunnel_error_code_)
    1246           0 :     return "A set function failed on this object";
    1247             :   switch (obj->ls_type) {
    1248             : 
    1249             :     case LS_IPV4:
    1250             :       break;
    1251             : 
    1252             :     case LS_IPV6:
    1253             :       break;
    1254             : 
    1255             :     case LS_LEGACY_ID:
    1256             :       break;
    1257             : 
    1258             :     case LS_ED25519_ID:
    1259             :       break;
    1260             : 
    1261             :     default:
    1262             :       break;
    1263             :   }
    1264             :   return NULL;
    1265             : }
    1266             : 
    1267             : ssize_t
    1268         713 : link_specifier_encoded_len(const link_specifier_t *obj)
    1269             : {
    1270         713 :   ssize_t result = 0;
    1271             : 
    1272         713 :   if (NULL != link_specifier_check(obj))
    1273             :      return -1;
    1274             : 
    1275             : 
    1276             :   /* Length of u8 ls_type */
    1277         713 :   result += 1;
    1278             : 
    1279             :   /* Length of u8 ls_len */
    1280         713 :   result += 1;
    1281         713 :   switch (obj->ls_type) {
    1282             : 
    1283             :     case LS_IPV4:
    1284             : 
    1285             :       /* Length of u32 un_ipv4_addr */
    1286             :       result += 4;
    1287             : 
    1288             :       /* Length of u16 un_ipv4_port */
    1289             :       result += 2;
    1290             :       break;
    1291             : 
    1292             :     case LS_IPV6:
    1293             : 
    1294             :       /* Length of u8 un_ipv6_addr[16] */
    1295             :       result += 16;
    1296             : 
    1297             :       /* Length of u16 un_ipv6_port */
    1298             :       result += 2;
    1299             :       break;
    1300             : 
    1301             :     case LS_LEGACY_ID:
    1302             : 
    1303             :       /* Length of u8 un_legacy_id[20] */
    1304             :       result += 20;
    1305             :       break;
    1306             : 
    1307             :     case LS_ED25519_ID:
    1308             : 
    1309             :       /* Length of u8 un_ed25519_id[32] */
    1310             :       result += 32;
    1311             :       break;
    1312             : 
    1313           0 :     default:
    1314             : 
    1315             :       /* Length of u8 un_unrecognized[] */
    1316           0 :       result += TRUNNEL_DYNARRAY_LEN(&obj->un_unrecognized);
    1317           0 :       break;
    1318             :   }
    1319             :   return result;
    1320             : }
    1321             : int
    1322           0 : link_specifier_clear_errors(link_specifier_t *obj)
    1323             : {
    1324           0 :   int r = obj->trunnel_error_code_;
    1325           0 :   obj->trunnel_error_code_ = 0;
    1326           0 :   return r;
    1327             : }
    1328             : ssize_t
    1329         727 : link_specifier_encode(uint8_t *output, const size_t avail, const link_specifier_t *obj)
    1330             : {
    1331         727 :   ssize_t result = 0;
    1332         727 :   size_t written = 0;
    1333         727 :   uint8_t *ptr = output;
    1334         727 :   const char *msg;
    1335             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    1336             :   const ssize_t encoded_len = link_specifier_encoded_len(obj);
    1337             : #endif
    1338             : 
    1339         727 :   uint8_t *backptr_ls_len = NULL;
    1340             : 
    1341         727 :   if (NULL != (msg = link_specifier_check(obj)))
    1342           0 :     goto check_failed;
    1343             : 
    1344             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    1345             :   trunnel_assert(encoded_len >= 0);
    1346             : #endif
    1347             : 
    1348             :   /* Encode u8 ls_type */
    1349         727 :   trunnel_assert(written <= avail);
    1350         727 :   if (avail - written < 1)
    1351           0 :     goto truncated;
    1352         727 :   trunnel_set_uint8(ptr, (obj->ls_type));
    1353         727 :   written += 1; ptr += 1;
    1354             : 
    1355             :   /* Encode u8 ls_len */
    1356         727 :   backptr_ls_len = ptr;
    1357         727 :   trunnel_assert(written <= avail);
    1358         727 :   if (avail - written < 1)
    1359           0 :     goto truncated;
    1360         727 :   trunnel_set_uint8(ptr, (obj->ls_len));
    1361         727 :   written += 1; ptr += 1;
    1362             :   {
    1363         727 :     size_t written_before_union = written;
    1364             : 
    1365             :     /* Encode union un[ls_type] */
    1366         727 :     trunnel_assert(written <= avail);
    1367         727 :     switch (obj->ls_type) {
    1368             : 
    1369             :       case LS_IPV4:
    1370             : 
    1371             :         /* Encode u32 un_ipv4_addr */
    1372         277 :         trunnel_assert(written <= avail);
    1373         277 :         if (avail - written < 4)
    1374           0 :           goto truncated;
    1375         277 :         trunnel_set_uint32(ptr, trunnel_htonl(obj->un_ipv4_addr));
    1376         277 :         written += 4; ptr += 4;
    1377             : 
    1378             :         /* Encode u16 un_ipv4_port */
    1379         277 :         trunnel_assert(written <= avail);
    1380         277 :         if (avail - written < 2)
    1381           0 :           goto truncated;
    1382         277 :         trunnel_set_uint16(ptr, trunnel_htons(obj->un_ipv4_port));
    1383         277 :         written += 2; ptr += 2;
    1384         277 :         break;
    1385             : 
    1386             :       case LS_IPV6:
    1387             : 
    1388             :         /* Encode u8 un_ipv6_addr[16] */
    1389          92 :         trunnel_assert(written <= avail);
    1390          92 :         if (avail - written < 16)
    1391           0 :           goto truncated;
    1392          92 :         memcpy(ptr, obj->un_ipv6_addr, 16);
    1393          92 :         written += 16; ptr += 16;
    1394             : 
    1395             :         /* Encode u16 un_ipv6_port */
    1396          92 :         trunnel_assert(written <= avail);
    1397          92 :         if (avail - written < 2)
    1398           0 :           goto truncated;
    1399          92 :         trunnel_set_uint16(ptr, trunnel_htons(obj->un_ipv6_port));
    1400          92 :         written += 2; ptr += 2;
    1401          92 :         break;
    1402             : 
    1403             :       case LS_LEGACY_ID:
    1404             : 
    1405             :         /* Encode u8 un_legacy_id[20] */
    1406         357 :         trunnel_assert(written <= avail);
    1407         357 :         if (avail - written < 20)
    1408           0 :           goto truncated;
    1409         357 :         memcpy(ptr, obj->un_legacy_id, 20);
    1410         357 :         written += 20; ptr += 20;
    1411         357 :         break;
    1412             : 
    1413             :       case LS_ED25519_ID:
    1414             : 
    1415             :         /* Encode u8 un_ed25519_id[32] */
    1416           1 :         trunnel_assert(written <= avail);
    1417           1 :         if (avail - written < 32)
    1418           0 :           goto truncated;
    1419           1 :         memcpy(ptr, obj->un_ed25519_id, 32);
    1420           1 :         written += 32; ptr += 32;
    1421           1 :         break;
    1422             : 
    1423           0 :       default:
    1424             : 
    1425             :         /* Encode u8 un_unrecognized[] */
    1426             :         {
    1427           0 :           size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->un_unrecognized);
    1428           0 :           trunnel_assert(written <= avail);
    1429           0 :           if (avail - written < elt_len)
    1430           0 :             goto truncated;
    1431           0 :           if (elt_len)
    1432           0 :             memcpy(ptr, obj->un_unrecognized.elts_, elt_len);
    1433           0 :           written += elt_len; ptr += elt_len;
    1434             :         }
    1435           0 :         break;
    1436             :     }
    1437             :     /* Write the length field back to ls_len */
    1438         727 :     trunnel_assert(written >= written_before_union);
    1439             : #if UINT8_MAX < SIZE_MAX
    1440         727 :     if (written - written_before_union > UINT8_MAX)
    1441           0 :       goto check_failed;
    1442             : #endif
    1443         727 :     trunnel_set_uint8(backptr_ls_len, (written - written_before_union));
    1444             :   }
    1445             : 
    1446             : 
    1447         727 :   trunnel_assert(ptr == output + written);
    1448             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    1449             :   {
    1450             :     trunnel_assert(encoded_len >= 0);
    1451             :     trunnel_assert((size_t)encoded_len == written);
    1452             :   }
    1453             : 
    1454             : #endif
    1455             : 
    1456         727 :   return written;
    1457             : 
    1458           0 :  truncated:
    1459           0 :   result = -2;
    1460           0 :   goto fail;
    1461           0 :  check_failed:
    1462           0 :   (void)msg;
    1463           0 :   result = -1;
    1464           0 :   goto fail;
    1465             :  fail:
    1466             :   trunnel_assert(result < 0);
    1467             :   return result;
    1468             : }
    1469             : 
    1470             : /** As link_specifier_parse(), but do not allocate the output object.
    1471             :  */
    1472             : static ssize_t
    1473       26337 : link_specifier_parse_into(link_specifier_t *obj, const uint8_t *input, const size_t len_in)
    1474             : {
    1475       26337 :   const uint8_t *ptr = input;
    1476       26337 :   size_t remaining = len_in;
    1477       26337 :   ssize_t result = 0;
    1478       26337 :   (void)result;
    1479             : 
    1480             :   /* Parse u8 ls_type */
    1481       26337 :   CHECK_REMAINING(1, truncated);
    1482       26241 :   obj->ls_type = (trunnel_get_uint8(ptr));
    1483       26241 :   remaining -= 1; ptr += 1;
    1484             : 
    1485             :   /* Parse u8 ls_len */
    1486       26241 :   CHECK_REMAINING(1, truncated);
    1487       26157 :   obj->ls_len = (trunnel_get_uint8(ptr));
    1488       26157 :   remaining -= 1; ptr += 1;
    1489             :   {
    1490       26157 :     size_t remaining_after;
    1491       26157 :     CHECK_REMAINING(obj->ls_len, truncated);
    1492       16692 :     remaining_after = remaining - obj->ls_len;
    1493       16692 :     remaining = obj->ls_len;
    1494             : 
    1495             :     /* Parse union un[ls_type] */
    1496       16692 :     switch (obj->ls_type) {
    1497             : 
    1498         380 :       case LS_IPV4:
    1499             : 
    1500             :         /* Parse u32 un_ipv4_addr */
    1501         380 :         CHECK_REMAINING(4, fail);
    1502         376 :         obj->un_ipv4_addr = trunnel_ntohl(trunnel_get_uint32(ptr));
    1503         376 :         remaining -= 4; ptr += 4;
    1504             : 
    1505             :         /* Parse u16 un_ipv4_port */
    1506         376 :         CHECK_REMAINING(2, fail);
    1507         375 :         obj->un_ipv4_port = trunnel_ntohs(trunnel_get_uint16(ptr));
    1508         375 :         remaining -= 2; ptr += 2;
    1509         375 :         break;
    1510             : 
    1511         153 :       case LS_IPV6:
    1512             : 
    1513             :         /* Parse u8 un_ipv6_addr[16] */
    1514         153 :         CHECK_REMAINING(16, fail);
    1515         147 :         memcpy(obj->un_ipv6_addr, ptr, 16);
    1516         147 :         remaining -= 16; ptr += 16;
    1517             : 
    1518             :         /* Parse u16 un_ipv6_port */
    1519         147 :         CHECK_REMAINING(2, fail);
    1520         146 :         obj->un_ipv6_port = trunnel_ntohs(trunnel_get_uint16(ptr));
    1521         146 :         remaining -= 2; ptr += 2;
    1522         146 :         break;
    1523             : 
    1524         459 :       case LS_LEGACY_ID:
    1525             : 
    1526             :         /* Parse u8 un_legacy_id[20] */
    1527         459 :         CHECK_REMAINING(20, fail);
    1528         451 :         memcpy(obj->un_legacy_id, ptr, 20);
    1529         451 :         remaining -= 20; ptr += 20;
    1530         451 :         break;
    1531             : 
    1532          63 :       case LS_ED25519_ID:
    1533             : 
    1534             :         /* Parse u8 un_ed25519_id[32] */
    1535          63 :         CHECK_REMAINING(32, fail);
    1536          54 :         memcpy(obj->un_ed25519_id, ptr, 32);
    1537          54 :         remaining -= 32; ptr += 32;
    1538          54 :         break;
    1539             : 
    1540       15637 :       default:
    1541             : 
    1542             :         /* Parse u8 un_unrecognized[] */
    1543       15637 :         TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->un_unrecognized, remaining, {});
    1544       15637 :         obj->un_unrecognized.n_ = remaining;
    1545       15637 :         if (remaining)
    1546       15552 :           memcpy(obj->un_unrecognized.elts_, ptr, remaining);
    1547       15637 :         ptr += remaining; remaining -= remaining;
    1548       15637 :         break;
    1549             :     }
    1550       16663 :     if (remaining != 0)
    1551         211 :       goto fail;
    1552       16452 :     remaining = remaining_after;
    1553             :   }
    1554       16452 :   trunnel_assert(ptr + remaining == input + len_in);
    1555       16452 :   return len_in - remaining;
    1556             : 
    1557             :  truncated:
    1558             :   return -2;
    1559           0 :  trunnel_alloc_failed:
    1560           0 :   return -1;
    1561             :  fail:
    1562       26337 :   result = -1;
    1563             :   return result;
    1564             : }
    1565             : 
    1566             : ssize_t
    1567       26337 : link_specifier_parse(link_specifier_t **output, const uint8_t *input, const size_t len_in)
    1568             : {
    1569       26337 :   ssize_t result;
    1570       26337 :   *output = link_specifier_new();
    1571       26337 :   if (NULL == *output)
    1572             :     return -1;
    1573       26337 :   result = link_specifier_parse_into(*output, input, len_in);
    1574       26337 :   if (result < 0) {
    1575        9885 :     link_specifier_free(*output);
    1576        9885 :     *output = NULL;
    1577             :   }
    1578             :   return result;
    1579             : }
    1580             : ed25519_cert_t *
    1581        1747 : ed25519_cert_new(void)
    1582             : {
    1583        1747 :   ed25519_cert_t *val = trunnel_calloc(1, sizeof(ed25519_cert_t));
    1584        1747 :   if (NULL == val)
    1585             :     return NULL;
    1586        1747 :   val->version = 1;
    1587        1747 :   return val;
    1588             : }
    1589             : 
    1590             : /** Release all storage held inside 'obj', but do not free 'obj'.
    1591             :  */
    1592             : static void
    1593        1747 : ed25519_cert_clear(ed25519_cert_t *obj)
    1594             : {
    1595        1747 :   (void) obj;
    1596             :   {
    1597             : 
    1598        1747 :     unsigned idx;
    1599        3884 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
    1600        2137 :       ed25519_cert_extension_free(TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
    1601             :     }
    1602             :   }
    1603        1747 :   TRUNNEL_DYNARRAY_WIPE(&obj->ext);
    1604        1747 :   TRUNNEL_DYNARRAY_CLEAR(&obj->ext);
    1605        1747 : }
    1606             : 
    1607             : void
    1608        1783 : ed25519_cert_free(ed25519_cert_t *obj)
    1609             : {
    1610        1783 :   if (obj == NULL)
    1611             :     return;
    1612        1747 :   ed25519_cert_clear(obj);
    1613        1747 :   trunnel_memwipe(obj, sizeof(ed25519_cert_t));
    1614        1747 :   trunnel_free_(obj);
    1615             : }
    1616             : 
    1617             : uint8_t
    1618           0 : ed25519_cert_get_version(const ed25519_cert_t *inp)
    1619             : {
    1620           0 :   return inp->version;
    1621             : }
    1622             : int
    1623           0 : ed25519_cert_set_version(ed25519_cert_t *inp, uint8_t val)
    1624             : {
    1625           0 :   if (! ((val == 1))) {
    1626           0 :      TRUNNEL_SET_ERROR_CODE(inp);
    1627           0 :      return -1;
    1628             :   }
    1629           0 :   inp->version = val;
    1630           0 :   return 0;
    1631             : }
    1632             : uint8_t
    1633           0 : ed25519_cert_get_cert_type(const ed25519_cert_t *inp)
    1634             : {
    1635           0 :   return inp->cert_type;
    1636             : }
    1637             : int
    1638           0 : ed25519_cert_set_cert_type(ed25519_cert_t *inp, uint8_t val)
    1639             : {
    1640           0 :   inp->cert_type = val;
    1641           0 :   return 0;
    1642             : }
    1643             : uint32_t
    1644           0 : ed25519_cert_get_exp_field(const ed25519_cert_t *inp)
    1645             : {
    1646           0 :   return inp->exp_field;
    1647             : }
    1648             : int
    1649           0 : ed25519_cert_set_exp_field(ed25519_cert_t *inp, uint32_t val)
    1650             : {
    1651           0 :   inp->exp_field = val;
    1652           0 :   return 0;
    1653             : }
    1654             : uint8_t
    1655           0 : ed25519_cert_get_cert_key_type(const ed25519_cert_t *inp)
    1656             : {
    1657           0 :   return inp->cert_key_type;
    1658             : }
    1659             : int
    1660           0 : ed25519_cert_set_cert_key_type(ed25519_cert_t *inp, uint8_t val)
    1661             : {
    1662           0 :   inp->cert_key_type = val;
    1663           0 :   return 0;
    1664             : }
    1665             : size_t
    1666           0 : ed25519_cert_getlen_certified_key(const ed25519_cert_t *inp)
    1667             : {
    1668           0 :   (void)inp;  return 32;
    1669             : }
    1670             : 
    1671             : uint8_t
    1672           0 : ed25519_cert_get_certified_key(ed25519_cert_t *inp, size_t idx)
    1673             : {
    1674           0 :   trunnel_assert(idx < 32);
    1675           0 :   return inp->certified_key[idx];
    1676             : }
    1677             : 
    1678             : uint8_t
    1679           0 : ed25519_cert_getconst_certified_key(const ed25519_cert_t *inp, size_t idx)
    1680             : {
    1681           0 :   return ed25519_cert_get_certified_key((ed25519_cert_t*)inp, idx);
    1682             : }
    1683             : int
    1684           0 : ed25519_cert_set_certified_key(ed25519_cert_t *inp, size_t idx, uint8_t elt)
    1685             : {
    1686           0 :   trunnel_assert(idx < 32);
    1687           0 :   inp->certified_key[idx] = elt;
    1688           0 :   return 0;
    1689             : }
    1690             : 
    1691             : uint8_t *
    1692           0 : ed25519_cert_getarray_certified_key(ed25519_cert_t *inp)
    1693             : {
    1694           0 :   return inp->certified_key;
    1695             : }
    1696             : const uint8_t  *
    1697           0 : ed25519_cert_getconstarray_certified_key(const ed25519_cert_t *inp)
    1698             : {
    1699           0 :   return (const uint8_t  *)ed25519_cert_getarray_certified_key((ed25519_cert_t*)inp);
    1700             : }
    1701             : uint8_t
    1702           0 : ed25519_cert_get_n_extensions(const ed25519_cert_t *inp)
    1703             : {
    1704           0 :   return inp->n_extensions;
    1705             : }
    1706             : int
    1707           0 : ed25519_cert_set_n_extensions(ed25519_cert_t *inp, uint8_t val)
    1708             : {
    1709           0 :   inp->n_extensions = val;
    1710           0 :   return 0;
    1711             : }
    1712             : size_t
    1713        2362 : ed25519_cert_getlen_ext(const ed25519_cert_t *inp)
    1714             : {
    1715        2362 :   return TRUNNEL_DYNARRAY_LEN(&inp->ext);
    1716             : }
    1717             : 
    1718             : struct ed25519_cert_extension_st *
    1719        1160 : ed25519_cert_get_ext(ed25519_cert_t *inp, size_t idx)
    1720             : {
    1721        1160 :   return TRUNNEL_DYNARRAY_GET(&inp->ext, idx);
    1722             : }
    1723             : 
    1724             :  const struct ed25519_cert_extension_st *
    1725           0 : ed25519_cert_getconst_ext(const ed25519_cert_t *inp, size_t idx)
    1726             : {
    1727           0 :   return ed25519_cert_get_ext((ed25519_cert_t*)inp, idx);
    1728             : }
    1729             : int
    1730           0 : ed25519_cert_set_ext(ed25519_cert_t *inp, size_t idx, struct ed25519_cert_extension_st * elt)
    1731             : {
    1732           0 :   ed25519_cert_extension_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->ext, idx);
    1733           0 :   if (oldval && oldval != elt)
    1734           0 :     ed25519_cert_extension_free(oldval);
    1735           0 :   return ed25519_cert_set0_ext(inp, idx, elt);
    1736             : }
    1737             : int
    1738           0 : ed25519_cert_set0_ext(ed25519_cert_t *inp, size_t idx, struct ed25519_cert_extension_st * elt)
    1739             : {
    1740           0 :   TRUNNEL_DYNARRAY_SET(&inp->ext, idx, elt);
    1741           0 :   return 0;
    1742             : }
    1743             : int
    1744         319 : ed25519_cert_add_ext(ed25519_cert_t *inp, struct ed25519_cert_extension_st * elt)
    1745             : {
    1746             : #if SIZE_MAX >= UINT8_MAX
    1747         319 :   if (inp->ext.n_ == UINT8_MAX)
    1748           0 :     goto trunnel_alloc_failed;
    1749             : #endif
    1750         319 :   TRUNNEL_DYNARRAY_ADD(struct ed25519_cert_extension_st *, &inp->ext, elt, {});
    1751         319 :   return 0;
    1752           0 :  trunnel_alloc_failed:
    1753           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    1754           0 :   return -1;
    1755             : }
    1756             : 
    1757             : struct ed25519_cert_extension_st * *
    1758           0 : ed25519_cert_getarray_ext(ed25519_cert_t *inp)
    1759             : {
    1760           0 :   return inp->ext.elts_;
    1761             : }
    1762             : const struct ed25519_cert_extension_st *  const  *
    1763           0 : ed25519_cert_getconstarray_ext(const ed25519_cert_t *inp)
    1764             : {
    1765           0 :   return (const struct ed25519_cert_extension_st *  const  *)ed25519_cert_getarray_ext((ed25519_cert_t*)inp);
    1766             : }
    1767             : int
    1768           0 : ed25519_cert_setlen_ext(ed25519_cert_t *inp, size_t newlen)
    1769             : {
    1770           0 :   struct ed25519_cert_extension_st * *newptr;
    1771             : #if UINT8_MAX < SIZE_MAX
    1772           0 :   if (newlen > UINT8_MAX)
    1773           0 :     goto trunnel_alloc_failed;
    1774             : #endif
    1775           0 :   newptr = trunnel_dynarray_setlen(&inp->ext.allocated_,
    1776           0 :                  &inp->ext.n_, inp->ext.elts_, newlen,
    1777             :                  sizeof(inp->ext.elts_[0]), (trunnel_free_fn_t) ed25519_cert_extension_free,
    1778             :                  &inp->trunnel_error_code_);
    1779           0 :   if (newlen != 0 && newptr == NULL)
    1780           0 :     goto trunnel_alloc_failed;
    1781           0 :   inp->ext.elts_ = newptr;
    1782           0 :   return 0;
    1783           0 :  trunnel_alloc_failed:
    1784           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    1785           0 :   return -1;
    1786             : }
    1787             : size_t
    1788           0 : ed25519_cert_getlen_signature(const ed25519_cert_t *inp)
    1789             : {
    1790           0 :   (void)inp;  return 64;
    1791             : }
    1792             : 
    1793             : uint8_t
    1794           0 : ed25519_cert_get_signature(ed25519_cert_t *inp, size_t idx)
    1795             : {
    1796           0 :   trunnel_assert(idx < 64);
    1797           0 :   return inp->signature[idx];
    1798             : }
    1799             : 
    1800             : uint8_t
    1801           0 : ed25519_cert_getconst_signature(const ed25519_cert_t *inp, size_t idx)
    1802             : {
    1803           0 :   return ed25519_cert_get_signature((ed25519_cert_t*)inp, idx);
    1804             : }
    1805             : int
    1806           0 : ed25519_cert_set_signature(ed25519_cert_t *inp, size_t idx, uint8_t elt)
    1807             : {
    1808           0 :   trunnel_assert(idx < 64);
    1809           0 :   inp->signature[idx] = elt;
    1810           0 :   return 0;
    1811             : }
    1812             : 
    1813             : uint8_t *
    1814           0 : ed25519_cert_getarray_signature(ed25519_cert_t *inp)
    1815             : {
    1816           0 :   return inp->signature;
    1817             : }
    1818             : const uint8_t  *
    1819           0 : ed25519_cert_getconstarray_signature(const ed25519_cert_t *inp)
    1820             : {
    1821           0 :   return (const uint8_t  *)ed25519_cert_getarray_signature((ed25519_cert_t*)inp);
    1822             : }
    1823             : const char *
    1824         998 : ed25519_cert_check(const ed25519_cert_t *obj)
    1825             : {
    1826         998 :   if (obj == NULL)
    1827             :     return "Object was NULL";
    1828         998 :   if (obj->trunnel_error_code_)
    1829             :     return "A set function failed on this object";
    1830         998 :   if (! (obj->version == 1))
    1831             :     return "Integer out of bounds";
    1832             :   {
    1833             :     const char *msg;
    1834             : 
    1835             :     unsigned idx;
    1836        1636 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
    1837         638 :       if (NULL != (msg = ed25519_cert_extension_check(TRUNNEL_DYNARRAY_GET(&obj->ext, idx))))
    1838           0 :         return msg;
    1839             :     }
    1840             :   }
    1841         998 :   if (TRUNNEL_DYNARRAY_LEN(&obj->ext) != obj->n_extensions)
    1842           0 :     return "Length mismatch for ext";
    1843             :   return NULL;
    1844             : }
    1845             : 
    1846             : ssize_t
    1847         499 : ed25519_cert_encoded_len(const ed25519_cert_t *obj)
    1848             : {
    1849         499 :   ssize_t result = 0;
    1850             : 
    1851         499 :   if (NULL != ed25519_cert_check(obj))
    1852             :      return -1;
    1853             : 
    1854             : 
    1855             :   /* Length of u8 version IN [1] */
    1856             :   result += 1;
    1857             : 
    1858             :   /* Length of u8 cert_type */
    1859             :   result += 1;
    1860             : 
    1861             :   /* Length of u32 exp_field */
    1862             :   result += 4;
    1863             : 
    1864             :   /* Length of u8 cert_key_type */
    1865             :   result += 1;
    1866             : 
    1867             :   /* Length of u8 certified_key[32] */
    1868             :   result += 32;
    1869             : 
    1870             :   /* Length of u8 n_extensions */
    1871             :   result += 1;
    1872             : 
    1873             :   /* Length of struct ed25519_cert_extension ext[n_extensions] */
    1874             :   {
    1875             : 
    1876             :     unsigned idx;
    1877         818 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
    1878         319 :       result += ed25519_cert_extension_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
    1879             :     }
    1880             :   }
    1881             : 
    1882             :   /* Length of u8 signature[64] */
    1883         499 :   result += 64;
    1884         499 :   return result;
    1885             : }
    1886             : int
    1887           0 : ed25519_cert_clear_errors(ed25519_cert_t *obj)
    1888             : {
    1889           0 :   int r = obj->trunnel_error_code_;
    1890           0 :   obj->trunnel_error_code_ = 0;
    1891           0 :   return r;
    1892             : }
    1893             : ssize_t
    1894         499 : ed25519_cert_encode(uint8_t *output, const size_t avail, const ed25519_cert_t *obj)
    1895             : {
    1896         499 :   ssize_t result = 0;
    1897         499 :   size_t written = 0;
    1898         499 :   uint8_t *ptr = output;
    1899         499 :   const char *msg;
    1900             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    1901             :   const ssize_t encoded_len = ed25519_cert_encoded_len(obj);
    1902             : #endif
    1903             : 
    1904         499 :   if (NULL != (msg = ed25519_cert_check(obj)))
    1905           0 :     goto check_failed;
    1906             : 
    1907             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    1908             :   trunnel_assert(encoded_len >= 0);
    1909             : #endif
    1910             : 
    1911             :   /* Encode u8 version IN [1] */
    1912         499 :   trunnel_assert(written <= avail);
    1913         499 :   if (avail - written < 1)
    1914           0 :     goto truncated;
    1915         499 :   trunnel_set_uint8(ptr, (obj->version));
    1916         499 :   written += 1; ptr += 1;
    1917             : 
    1918             :   /* Encode u8 cert_type */
    1919         499 :   trunnel_assert(written <= avail);
    1920         499 :   if (avail - written < 1)
    1921           0 :     goto truncated;
    1922         499 :   trunnel_set_uint8(ptr, (obj->cert_type));
    1923         499 :   written += 1; ptr += 1;
    1924             : 
    1925             :   /* Encode u32 exp_field */
    1926         499 :   trunnel_assert(written <= avail);
    1927         499 :   if (avail - written < 4)
    1928           0 :     goto truncated;
    1929         499 :   trunnel_set_uint32(ptr, trunnel_htonl(obj->exp_field));
    1930         499 :   written += 4; ptr += 4;
    1931             : 
    1932             :   /* Encode u8 cert_key_type */
    1933         499 :   trunnel_assert(written <= avail);
    1934         499 :   if (avail - written < 1)
    1935           0 :     goto truncated;
    1936         499 :   trunnel_set_uint8(ptr, (obj->cert_key_type));
    1937         499 :   written += 1; ptr += 1;
    1938             : 
    1939             :   /* Encode u8 certified_key[32] */
    1940         499 :   trunnel_assert(written <= avail);
    1941         499 :   if (avail - written < 32)
    1942           0 :     goto truncated;
    1943         499 :   memcpy(ptr, obj->certified_key, 32);
    1944         499 :   written += 32; ptr += 32;
    1945             : 
    1946             :   /* Encode u8 n_extensions */
    1947         499 :   trunnel_assert(written <= avail);
    1948         499 :   if (avail - written < 1)
    1949           0 :     goto truncated;
    1950         499 :   trunnel_set_uint8(ptr, (obj->n_extensions));
    1951         499 :   written += 1; ptr += 1;
    1952             : 
    1953             :   /* Encode struct ed25519_cert_extension ext[n_extensions] */
    1954             :   {
    1955             : 
    1956         499 :     unsigned idx;
    1957         818 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
    1958         319 :       trunnel_assert(written <= avail);
    1959         319 :       result = ed25519_cert_extension_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
    1960         319 :       if (result < 0)
    1961           0 :         goto fail; /* XXXXXXX !*/
    1962         319 :       written += result; ptr += result;
    1963             :     }
    1964             :   }
    1965             : 
    1966             :   /* Encode u8 signature[64] */
    1967         499 :   trunnel_assert(written <= avail);
    1968         499 :   if (avail - written < 64)
    1969           0 :     goto truncated;
    1970         499 :   memcpy(ptr, obj->signature, 64);
    1971         499 :   written += 64; ptr += 64;
    1972             : 
    1973             : 
    1974         499 :   trunnel_assert(ptr == output + written);
    1975             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    1976             :   {
    1977             :     trunnel_assert(encoded_len >= 0);
    1978             :     trunnel_assert((size_t)encoded_len == written);
    1979             :   }
    1980             : 
    1981             : #endif
    1982             : 
    1983         499 :   return written;
    1984             : 
    1985           0 :  truncated:
    1986           0 :   result = -2;
    1987           0 :   goto fail;
    1988           0 :  check_failed:
    1989           0 :   (void)msg;
    1990           0 :   result = -1;
    1991           0 :   goto fail;
    1992           0 :  fail:
    1993           0 :   trunnel_assert(result < 0);
    1994             :   return result;
    1995             : }
    1996             : 
    1997             : /** As ed25519_cert_parse(), but do not allocate the output object.
    1998             :  */
    1999             : static ssize_t
    2000        1248 : ed25519_cert_parse_into(ed25519_cert_t *obj, const uint8_t *input, const size_t len_in)
    2001             : {
    2002        1248 :   const uint8_t *ptr = input;
    2003        1248 :   size_t remaining = len_in;
    2004        1248 :   ssize_t result = 0;
    2005        1248 :   (void)result;
    2006             : 
    2007             :   /* Parse u8 version IN [1] */
    2008        1248 :   CHECK_REMAINING(1, truncated);
    2009        1246 :   obj->version = (trunnel_get_uint8(ptr));
    2010        1246 :   remaining -= 1; ptr += 1;
    2011        1246 :   if (! (obj->version == 1))
    2012           2 :     goto fail;
    2013             : 
    2014             :   /* Parse u8 cert_type */
    2015        1244 :   CHECK_REMAINING(1, truncated);
    2016        1241 :   obj->cert_type = (trunnel_get_uint8(ptr));
    2017        1241 :   remaining -= 1; ptr += 1;
    2018             : 
    2019             :   /* Parse u32 exp_field */
    2020        1241 :   CHECK_REMAINING(4, truncated);
    2021        1239 :   obj->exp_field = trunnel_ntohl(trunnel_get_uint32(ptr));
    2022        1239 :   remaining -= 4; ptr += 4;
    2023             : 
    2024             :   /* Parse u8 cert_key_type */
    2025        1239 :   CHECK_REMAINING(1, truncated);
    2026        1237 :   obj->cert_key_type = (trunnel_get_uint8(ptr));
    2027        1237 :   remaining -= 1; ptr += 1;
    2028             : 
    2029             :   /* Parse u8 certified_key[32] */
    2030        1237 :   CHECK_REMAINING(32, truncated);
    2031        1234 :   memcpy(obj->certified_key, ptr, 32);
    2032        1234 :   remaining -= 32; ptr += 32;
    2033             : 
    2034             :   /* Parse u8 n_extensions */
    2035        1234 :   CHECK_REMAINING(1, truncated);
    2036        1232 :   obj->n_extensions = (trunnel_get_uint8(ptr));
    2037        1232 :   remaining -= 1; ptr += 1;
    2038             : 
    2039             :   /* Parse struct ed25519_cert_extension ext[n_extensions] */
    2040        1232 :   TRUNNEL_DYNARRAY_EXPAND(ed25519_cert_extension_t *, &obj->ext, obj->n_extensions, {});
    2041             :   {
    2042        1232 :     ed25519_cert_extension_t * elt;
    2043        1232 :     unsigned idx;
    2044        3050 :     for (idx = 0; idx < obj->n_extensions; ++idx) {
    2045        1835 :       result = ed25519_cert_extension_parse(&elt, ptr, remaining);
    2046        1835 :       if (result < 0)
    2047          17 :         goto relay_fail;
    2048        1818 :       trunnel_assert((size_t)result <= remaining);
    2049        1818 :       remaining -= result; ptr += result;
    2050        1818 :       TRUNNEL_DYNARRAY_ADD(ed25519_cert_extension_t *, &obj->ext, elt, {ed25519_cert_extension_free(elt);});
    2051             :     }
    2052             :   }
    2053             : 
    2054             :   /* Parse u8 signature[64] */
    2055        1215 :   CHECK_REMAINING(64, truncated);
    2056        1212 :   memcpy(obj->signature, ptr, 64);
    2057        1212 :   remaining -= 64; ptr += 64;
    2058        1212 :   trunnel_assert(ptr + remaining == input + len_in);
    2059        1212 :   return len_in - remaining;
    2060             : 
    2061             :  truncated:
    2062             :   return -2;
    2063          17 :  relay_fail:
    2064          17 :   trunnel_assert(result < 0);
    2065             :   return result;
    2066             :  trunnel_alloc_failed:
    2067             :   return -1;
    2068           2 :  fail:
    2069           2 :   result = -1;
    2070           2 :   return result;
    2071             : }
    2072             : 
    2073             : ssize_t
    2074        1248 : ed25519_cert_parse(ed25519_cert_t **output, const uint8_t *input, const size_t len_in)
    2075             : {
    2076        1248 :   ssize_t result;
    2077        1248 :   *output = ed25519_cert_new();
    2078        1248 :   if (NULL == *output)
    2079             :     return -1;
    2080        1248 :   result = ed25519_cert_parse_into(*output, input, len_in);
    2081        1248 :   if (result < 0) {
    2082          36 :     ed25519_cert_free(*output);
    2083          36 :     *output = NULL;
    2084             :   }
    2085             :   return result;
    2086             : }
    2087             : extend2_cell_body_t *
    2088       10017 : extend2_cell_body_new(void)
    2089             : {
    2090       10017 :   extend2_cell_body_t *val = trunnel_calloc(1, sizeof(extend2_cell_body_t));
    2091       10017 :   if (NULL == val)
    2092           0 :     return NULL;
    2093             :   return val;
    2094             : }
    2095             : 
    2096             : /** Release all storage held inside 'obj', but do not free 'obj'.
    2097             :  */
    2098             : static void
    2099       10017 : extend2_cell_body_clear(extend2_cell_body_t *obj)
    2100             : {
    2101       10017 :   (void) obj;
    2102             :   {
    2103             : 
    2104       10017 :     unsigned idx;
    2105       25689 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
    2106       15672 :       link_specifier_free(TRUNNEL_DYNARRAY_GET(&obj->ls, idx));
    2107             :     }
    2108             :   }
    2109       10017 :   TRUNNEL_DYNARRAY_WIPE(&obj->ls);
    2110       10017 :   TRUNNEL_DYNARRAY_CLEAR(&obj->ls);
    2111       10017 :   create2_cell_body_free(obj->create2);
    2112       10017 :   obj->create2 = NULL;
    2113       10017 : }
    2114             : 
    2115             : void
    2116       10017 : extend2_cell_body_free(extend2_cell_body_t *obj)
    2117             : {
    2118       10017 :   if (obj == NULL)
    2119             :     return;
    2120       10017 :   extend2_cell_body_clear(obj);
    2121       10017 :   trunnel_memwipe(obj, sizeof(extend2_cell_body_t));
    2122       10017 :   trunnel_free_(obj);
    2123             : }
    2124             : 
    2125             : uint8_t
    2126           0 : extend2_cell_body_get_n_spec(const extend2_cell_body_t *inp)
    2127             : {
    2128           0 :   return inp->n_spec;
    2129             : }
    2130             : int
    2131           0 : extend2_cell_body_set_n_spec(extend2_cell_body_t *inp, uint8_t val)
    2132             : {
    2133           0 :   inp->n_spec = val;
    2134           0 :   return 0;
    2135             : }
    2136             : size_t
    2137           0 : extend2_cell_body_getlen_ls(const extend2_cell_body_t *inp)
    2138             : {
    2139           0 :   return TRUNNEL_DYNARRAY_LEN(&inp->ls);
    2140             : }
    2141             : 
    2142             : struct link_specifier_st *
    2143          16 : extend2_cell_body_get_ls(extend2_cell_body_t *inp, size_t idx)
    2144             : {
    2145          16 :   return TRUNNEL_DYNARRAY_GET(&inp->ls, idx);
    2146             : }
    2147             : 
    2148             :  const struct link_specifier_st *
    2149          16 : extend2_cell_body_getconst_ls(const extend2_cell_body_t *inp, size_t idx)
    2150             : {
    2151          16 :   return extend2_cell_body_get_ls((extend2_cell_body_t*)inp, idx);
    2152             : }
    2153             : int
    2154           0 : extend2_cell_body_set_ls(extend2_cell_body_t *inp, size_t idx, struct link_specifier_st * elt)
    2155             : {
    2156           0 :   link_specifier_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->ls, idx);
    2157           0 :   if (oldval && oldval != elt)
    2158           0 :     link_specifier_free(oldval);
    2159           0 :   return extend2_cell_body_set0_ls(inp, idx, elt);
    2160             : }
    2161             : int
    2162           0 : extend2_cell_body_set0_ls(extend2_cell_body_t *inp, size_t idx, struct link_specifier_st * elt)
    2163             : {
    2164           0 :   TRUNNEL_DYNARRAY_SET(&inp->ls, idx, elt);
    2165           0 :   return 0;
    2166             : }
    2167             : int
    2168          14 : extend2_cell_body_add_ls(extend2_cell_body_t *inp, struct link_specifier_st * elt)
    2169             : {
    2170             : #if SIZE_MAX >= UINT8_MAX
    2171          14 :   if (inp->ls.n_ == UINT8_MAX)
    2172           0 :     goto trunnel_alloc_failed;
    2173             : #endif
    2174          14 :   TRUNNEL_DYNARRAY_ADD(struct link_specifier_st *, &inp->ls, elt, {});
    2175          14 :   return 0;
    2176           0 :  trunnel_alloc_failed:
    2177           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    2178           0 :   return -1;
    2179             : }
    2180             : 
    2181             : struct link_specifier_st * *
    2182           0 : extend2_cell_body_getarray_ls(extend2_cell_body_t *inp)
    2183             : {
    2184           0 :   return inp->ls.elts_;
    2185             : }
    2186             : const struct link_specifier_st *  const  *
    2187           0 : extend2_cell_body_getconstarray_ls(const extend2_cell_body_t *inp)
    2188             : {
    2189           0 :   return (const struct link_specifier_st *  const  *)extend2_cell_body_getarray_ls((extend2_cell_body_t*)inp);
    2190             : }
    2191             : int
    2192           0 : extend2_cell_body_setlen_ls(extend2_cell_body_t *inp, size_t newlen)
    2193             : {
    2194           0 :   struct link_specifier_st * *newptr;
    2195             : #if UINT8_MAX < SIZE_MAX
    2196           0 :   if (newlen > UINT8_MAX)
    2197           0 :     goto trunnel_alloc_failed;
    2198             : #endif
    2199           0 :   newptr = trunnel_dynarray_setlen(&inp->ls.allocated_,
    2200           0 :                  &inp->ls.n_, inp->ls.elts_, newlen,
    2201             :                  sizeof(inp->ls.elts_[0]), (trunnel_free_fn_t) link_specifier_free,
    2202             :                  &inp->trunnel_error_code_);
    2203           0 :   if (newlen != 0 && newptr == NULL)
    2204           0 :     goto trunnel_alloc_failed;
    2205           0 :   inp->ls.elts_ = newptr;
    2206           0 :   return 0;
    2207           0 :  trunnel_alloc_failed:
    2208           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    2209           0 :   return -1;
    2210             : }
    2211             : struct create2_cell_body_st *
    2212           0 : extend2_cell_body_get_create2(extend2_cell_body_t *inp)
    2213             : {
    2214           0 :   return inp->create2;
    2215             : }
    2216             : const struct create2_cell_body_st *
    2217           0 : extend2_cell_body_getconst_create2(const extend2_cell_body_t *inp)
    2218             : {
    2219           0 :   return extend2_cell_body_get_create2((extend2_cell_body_t*) inp);
    2220             : }
    2221             : int
    2222           0 : extend2_cell_body_set_create2(extend2_cell_body_t *inp, struct create2_cell_body_st *val)
    2223             : {
    2224           0 :   if (inp->create2 && inp->create2 != val)
    2225           0 :     create2_cell_body_free(inp->create2);
    2226           0 :   return extend2_cell_body_set0_create2(inp, val);
    2227             : }
    2228             : int
    2229           0 : extend2_cell_body_set0_create2(extend2_cell_body_t *inp, struct create2_cell_body_st *val)
    2230             : {
    2231           0 :   inp->create2 = val;
    2232           0 :   return 0;
    2233             : }
    2234             : const char *
    2235           5 : extend2_cell_body_check(const extend2_cell_body_t *obj)
    2236             : {
    2237           5 :   if (obj == NULL)
    2238             :     return "Object was NULL";
    2239           5 :   if (obj->trunnel_error_code_)
    2240             :     return "A set function failed on this object";
    2241             :   {
    2242             :     const char *msg;
    2243             : 
    2244             :     unsigned idx;
    2245          19 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
    2246          14 :       if (NULL != (msg = link_specifier_check(TRUNNEL_DYNARRAY_GET(&obj->ls, idx))))
    2247           0 :         return msg;
    2248             :     }
    2249             :   }
    2250           5 :   if (TRUNNEL_DYNARRAY_LEN(&obj->ls) != obj->n_spec)
    2251             :     return "Length mismatch for ls";
    2252             :   {
    2253           5 :     const char *msg;
    2254           5 :     if (NULL != (msg = create2_cell_body_check(obj->create2)))
    2255           0 :       return msg;
    2256             :   }
    2257             :   return NULL;
    2258             : }
    2259             : 
    2260             : ssize_t
    2261           0 : extend2_cell_body_encoded_len(const extend2_cell_body_t *obj)
    2262             : {
    2263           0 :   ssize_t result = 0;
    2264             : 
    2265           0 :   if (NULL != extend2_cell_body_check(obj))
    2266             :      return -1;
    2267             : 
    2268             : 
    2269             :   /* Length of u8 n_spec */
    2270             :   result += 1;
    2271             : 
    2272             :   /* Length of struct link_specifier ls[n_spec] */
    2273             :   {
    2274             : 
    2275             :     unsigned idx;
    2276           0 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
    2277           0 :       result += link_specifier_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->ls, idx));
    2278             :     }
    2279             :   }
    2280             : 
    2281             :   /* Length of struct create2_cell_body create2 */
    2282           0 :   result += create2_cell_body_encoded_len(obj->create2);
    2283           0 :   return result;
    2284             : }
    2285             : int
    2286           0 : extend2_cell_body_clear_errors(extend2_cell_body_t *obj)
    2287             : {
    2288           0 :   int r = obj->trunnel_error_code_;
    2289           0 :   obj->trunnel_error_code_ = 0;
    2290           0 :   return r;
    2291             : }
    2292             : ssize_t
    2293           5 : extend2_cell_body_encode(uint8_t *output, const size_t avail, const extend2_cell_body_t *obj)
    2294             : {
    2295           5 :   ssize_t result = 0;
    2296           5 :   size_t written = 0;
    2297           5 :   uint8_t *ptr = output;
    2298           5 :   const char *msg;
    2299             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2300             :   const ssize_t encoded_len = extend2_cell_body_encoded_len(obj);
    2301             : #endif
    2302             : 
    2303           5 :   if (NULL != (msg = extend2_cell_body_check(obj)))
    2304           0 :     goto check_failed;
    2305             : 
    2306             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2307             :   trunnel_assert(encoded_len >= 0);
    2308             : #endif
    2309             : 
    2310             :   /* Encode u8 n_spec */
    2311           5 :   trunnel_assert(written <= avail);
    2312           5 :   if (avail - written < 1)
    2313           0 :     goto truncated;
    2314           5 :   trunnel_set_uint8(ptr, (obj->n_spec));
    2315           5 :   written += 1; ptr += 1;
    2316             : 
    2317             :   /* Encode struct link_specifier ls[n_spec] */
    2318             :   {
    2319             : 
    2320           5 :     unsigned idx;
    2321          19 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
    2322          14 :       trunnel_assert(written <= avail);
    2323          14 :       result = link_specifier_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->ls, idx));
    2324          14 :       if (result < 0)
    2325           0 :         goto fail; /* XXXXXXX !*/
    2326          14 :       written += result; ptr += result;
    2327             :     }
    2328             :   }
    2329             : 
    2330             :   /* Encode struct create2_cell_body create2 */
    2331           5 :   trunnel_assert(written <= avail);
    2332           5 :   result = create2_cell_body_encode(ptr, avail - written, obj->create2);
    2333           5 :   if (result < 0)
    2334           0 :     goto fail; /* XXXXXXX !*/
    2335           5 :   written += result; ptr += result;
    2336             : 
    2337             : 
    2338           5 :   trunnel_assert(ptr == output + written);
    2339             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2340             :   {
    2341             :     trunnel_assert(encoded_len >= 0);
    2342             :     trunnel_assert((size_t)encoded_len == written);
    2343             :   }
    2344             : 
    2345             : #endif
    2346             : 
    2347           5 :   return written;
    2348             : 
    2349           0 :  truncated:
    2350           0 :   result = -2;
    2351           0 :   goto fail;
    2352           0 :  check_failed:
    2353           0 :   (void)msg;
    2354           0 :   result = -1;
    2355           0 :   goto fail;
    2356             :  fail:
    2357           0 :   trunnel_assert(result < 0);
    2358             :   return result;
    2359             : }
    2360             : 
    2361             : /** As extend2_cell_body_parse(), but do not allocate the output
    2362             :  * object.
    2363             :  */
    2364             : static ssize_t
    2365       10012 : extend2_cell_body_parse_into(extend2_cell_body_t *obj, const uint8_t *input, const size_t len_in)
    2366             : {
    2367       10012 :   const uint8_t *ptr = input;
    2368       10012 :   size_t remaining = len_in;
    2369       10012 :   ssize_t result = 0;
    2370       10012 :   (void)result;
    2371             : 
    2372             :   /* Parse u8 n_spec */
    2373       10012 :   CHECK_REMAINING(1, truncated);
    2374        9993 :   obj->n_spec = (trunnel_get_uint8(ptr));
    2375        9993 :   remaining -= 1; ptr += 1;
    2376             : 
    2377             :   /* Parse struct link_specifier ls[n_spec] */
    2378        9993 :   TRUNNEL_DYNARRAY_EXPAND(link_specifier_t *, &obj->ls, obj->n_spec, {});
    2379             :   {
    2380        9993 :     link_specifier_t * elt;
    2381        9993 :     unsigned idx;
    2382       25651 :     for (idx = 0; idx < obj->n_spec; ++idx) {
    2383       25543 :       result = link_specifier_parse(&elt, ptr, remaining);
    2384       25543 :       if (result < 0)
    2385        9885 :         goto relay_fail;
    2386       15658 :       trunnel_assert((size_t)result <= remaining);
    2387       15658 :       remaining -= result; ptr += result;
    2388       15658 :       TRUNNEL_DYNARRAY_ADD(link_specifier_t *, &obj->ls, elt, {link_specifier_free(elt);});
    2389             :     }
    2390             :   }
    2391             : 
    2392             :   /* Parse struct create2_cell_body create2 */
    2393         108 :   result = create2_cell_body_parse(&obj->create2, ptr, remaining);
    2394         108 :   if (result < 0)
    2395         102 :     goto relay_fail;
    2396           6 :   trunnel_assert((size_t)result <= remaining);
    2397           6 :   remaining -= result; ptr += result;
    2398           6 :   trunnel_assert(ptr + remaining == input + len_in);
    2399           6 :   return len_in - remaining;
    2400             : 
    2401          19 :  truncated:
    2402          19 :   return -2;
    2403             :  relay_fail:
    2404             :   trunnel_assert(result < 0);
    2405             :   return result;
    2406             :  trunnel_alloc_failed:
    2407             :   return -1;
    2408             : }
    2409             : 
    2410             : ssize_t
    2411       10012 : extend2_cell_body_parse(extend2_cell_body_t **output, const uint8_t *input, const size_t len_in)
    2412             : {
    2413       10012 :   ssize_t result;
    2414       10012 :   *output = extend2_cell_body_new();
    2415       10012 :   if (NULL == *output)
    2416             :     return -1;
    2417       10012 :   result = extend2_cell_body_parse_into(*output, input, len_in);
    2418       10012 :   if (result < 0) {
    2419       10006 :     extend2_cell_body_free(*output);
    2420       10006 :     *output = NULL;
    2421             :   }
    2422             :   return result;
    2423             : }
    2424             : link_specifier_list_t *
    2425         248 : link_specifier_list_new(void)
    2426             : {
    2427         248 :   link_specifier_list_t *val = trunnel_calloc(1, sizeof(link_specifier_list_t));
    2428         248 :   if (NULL == val)
    2429           0 :     return NULL;
    2430             :   return val;
    2431             : }
    2432             : 
    2433             : /** Release all storage held inside 'obj', but do not free 'obj'.
    2434             :  */
    2435             : static void
    2436         248 : link_specifier_list_clear(link_specifier_list_t *obj)
    2437             : {
    2438         248 :   (void) obj;
    2439             :   {
    2440             : 
    2441         248 :     unsigned idx;
    2442         744 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
    2443         496 :       link_specifier_free(TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
    2444             :     }
    2445             :   }
    2446         248 :   TRUNNEL_DYNARRAY_WIPE(&obj->spec);
    2447         248 :   TRUNNEL_DYNARRAY_CLEAR(&obj->spec);
    2448         248 : }
    2449             : 
    2450             : void
    2451         248 : link_specifier_list_free(link_specifier_list_t *obj)
    2452             : {
    2453         248 :   if (obj == NULL)
    2454             :     return;
    2455         248 :   link_specifier_list_clear(obj);
    2456         248 :   trunnel_memwipe(obj, sizeof(link_specifier_list_t));
    2457         248 :   trunnel_free_(obj);
    2458             : }
    2459             : 
    2460             : uint8_t
    2461           0 : link_specifier_list_get_n_spec(const link_specifier_list_t *inp)
    2462             : {
    2463           0 :   return inp->n_spec;
    2464             : }
    2465             : int
    2466         104 : link_specifier_list_set_n_spec(link_specifier_list_t *inp, uint8_t val)
    2467             : {
    2468         104 :   inp->n_spec = val;
    2469         104 :   return 0;
    2470             : }
    2471             : size_t
    2472         432 : link_specifier_list_getlen_spec(const link_specifier_list_t *inp)
    2473             : {
    2474         432 :   return TRUNNEL_DYNARRAY_LEN(&inp->spec);
    2475             : }
    2476             : 
    2477             : struct link_specifier_st *
    2478         288 : link_specifier_list_get_spec(link_specifier_list_t *inp, size_t idx)
    2479             : {
    2480         288 :   return TRUNNEL_DYNARRAY_GET(&inp->spec, idx);
    2481             : }
    2482             : 
    2483             :  const struct link_specifier_st *
    2484           0 : link_specifier_list_getconst_spec(const link_specifier_list_t *inp, size_t idx)
    2485             : {
    2486           0 :   return link_specifier_list_get_spec((link_specifier_list_t*)inp, idx);
    2487             : }
    2488             : int
    2489           0 : link_specifier_list_set_spec(link_specifier_list_t *inp, size_t idx, struct link_specifier_st * elt)
    2490             : {
    2491           0 :   link_specifier_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->spec, idx);
    2492           0 :   if (oldval && oldval != elt)
    2493           0 :     link_specifier_free(oldval);
    2494           0 :   return link_specifier_list_set0_spec(inp, idx, elt);
    2495             : }
    2496             : int
    2497           0 : link_specifier_list_set0_spec(link_specifier_list_t *inp, size_t idx, struct link_specifier_st * elt)
    2498             : {
    2499           0 :   TRUNNEL_DYNARRAY_SET(&inp->spec, idx, elt);
    2500           0 :   return 0;
    2501             : }
    2502             : int
    2503         208 : link_specifier_list_add_spec(link_specifier_list_t *inp, struct link_specifier_st * elt)
    2504             : {
    2505             : #if SIZE_MAX >= UINT8_MAX
    2506         208 :   if (inp->spec.n_ == UINT8_MAX)
    2507           0 :     goto trunnel_alloc_failed;
    2508             : #endif
    2509         208 :   TRUNNEL_DYNARRAY_ADD(struct link_specifier_st *, &inp->spec, elt, {});
    2510         208 :   return 0;
    2511           0 :  trunnel_alloc_failed:
    2512           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    2513           0 :   return -1;
    2514             : }
    2515             : 
    2516             : struct link_specifier_st * *
    2517           0 : link_specifier_list_getarray_spec(link_specifier_list_t *inp)
    2518             : {
    2519           0 :   return inp->spec.elts_;
    2520             : }
    2521             : const struct link_specifier_st *  const  *
    2522           0 : link_specifier_list_getconstarray_spec(const link_specifier_list_t *inp)
    2523             : {
    2524           0 :   return (const struct link_specifier_st *  const  *)link_specifier_list_getarray_spec((link_specifier_list_t*)inp);
    2525             : }
    2526             : int
    2527           0 : link_specifier_list_setlen_spec(link_specifier_list_t *inp, size_t newlen)
    2528             : {
    2529           0 :   struct link_specifier_st * *newptr;
    2530             : #if UINT8_MAX < SIZE_MAX
    2531           0 :   if (newlen > UINT8_MAX)
    2532           0 :     goto trunnel_alloc_failed;
    2533             : #endif
    2534           0 :   newptr = trunnel_dynarray_setlen(&inp->spec.allocated_,
    2535           0 :                  &inp->spec.n_, inp->spec.elts_, newlen,
    2536             :                  sizeof(inp->spec.elts_[0]), (trunnel_free_fn_t) link_specifier_free,
    2537             :                  &inp->trunnel_error_code_);
    2538           0 :   if (newlen != 0 && newptr == NULL)
    2539           0 :     goto trunnel_alloc_failed;
    2540           0 :   inp->spec.elts_ = newptr;
    2541           0 :   return 0;
    2542           0 :  trunnel_alloc_failed:
    2543           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    2544           0 :   return -1;
    2545             : }
    2546             : const char *
    2547         208 : link_specifier_list_check(const link_specifier_list_t *obj)
    2548             : {
    2549         208 :   if (obj == NULL)
    2550             :     return "Object was NULL";
    2551         208 :   if (obj->trunnel_error_code_)
    2552             :     return "A set function failed on this object";
    2553             :   {
    2554             :     const char *msg;
    2555             : 
    2556             :     unsigned idx;
    2557         624 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
    2558         416 :       if (NULL != (msg = link_specifier_check(TRUNNEL_DYNARRAY_GET(&obj->spec, idx))))
    2559           0 :         return msg;
    2560             :     }
    2561             :   }
    2562         208 :   if (TRUNNEL_DYNARRAY_LEN(&obj->spec) != obj->n_spec)
    2563           0 :     return "Length mismatch for spec";
    2564             :   return NULL;
    2565             : }
    2566             : 
    2567             : ssize_t
    2568         104 : link_specifier_list_encoded_len(const link_specifier_list_t *obj)
    2569             : {
    2570         104 :   ssize_t result = 0;
    2571             : 
    2572         104 :   if (NULL != link_specifier_list_check(obj))
    2573             :      return -1;
    2574             : 
    2575             : 
    2576             :   /* Length of u8 n_spec */
    2577             :   result += 1;
    2578             : 
    2579             :   /* Length of struct link_specifier spec[n_spec] */
    2580             :   {
    2581             : 
    2582             :     unsigned idx;
    2583         312 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
    2584         208 :       result += link_specifier_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
    2585             :     }
    2586             :   }
    2587             :   return result;
    2588             : }
    2589             : int
    2590           0 : link_specifier_list_clear_errors(link_specifier_list_t *obj)
    2591             : {
    2592           0 :   int r = obj->trunnel_error_code_;
    2593           0 :   obj->trunnel_error_code_ = 0;
    2594           0 :   return r;
    2595             : }
    2596             : ssize_t
    2597         104 : link_specifier_list_encode(uint8_t *output, const size_t avail, const link_specifier_list_t *obj)
    2598             : {
    2599         104 :   ssize_t result = 0;
    2600         104 :   size_t written = 0;
    2601         104 :   uint8_t *ptr = output;
    2602         104 :   const char *msg;
    2603             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2604             :   const ssize_t encoded_len = link_specifier_list_encoded_len(obj);
    2605             : #endif
    2606             : 
    2607         104 :   if (NULL != (msg = link_specifier_list_check(obj)))
    2608           0 :     goto check_failed;
    2609             : 
    2610             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2611             :   trunnel_assert(encoded_len >= 0);
    2612             : #endif
    2613             : 
    2614             :   /* Encode u8 n_spec */
    2615         104 :   trunnel_assert(written <= avail);
    2616         104 :   if (avail - written < 1)
    2617           0 :     goto truncated;
    2618         104 :   trunnel_set_uint8(ptr, (obj->n_spec));
    2619         104 :   written += 1; ptr += 1;
    2620             : 
    2621             :   /* Encode struct link_specifier spec[n_spec] */
    2622             :   {
    2623             : 
    2624         104 :     unsigned idx;
    2625         312 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
    2626         208 :       trunnel_assert(written <= avail);
    2627         208 :       result = link_specifier_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
    2628         208 :       if (result < 0)
    2629           0 :         goto fail; /* XXXXXXX !*/
    2630         208 :       written += result; ptr += result;
    2631             :     }
    2632             :   }
    2633             : 
    2634             : 
    2635         104 :   trunnel_assert(ptr == output + written);
    2636             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    2637             :   {
    2638             :     trunnel_assert(encoded_len >= 0);
    2639             :     trunnel_assert((size_t)encoded_len == written);
    2640             :   }
    2641             : 
    2642             : #endif
    2643             : 
    2644         104 :   return written;
    2645             : 
    2646           0 :  truncated:
    2647           0 :   result = -2;
    2648           0 :   goto fail;
    2649           0 :  check_failed:
    2650           0 :   (void)msg;
    2651           0 :   result = -1;
    2652           0 :   goto fail;
    2653           0 :  fail:
    2654           0 :   trunnel_assert(result < 0);
    2655             :   return result;
    2656             : }
    2657             : 
    2658             : /** As link_specifier_list_parse(), but do not allocate the output
    2659             :  * object.
    2660             :  */
    2661             : static ssize_t
    2662         144 : link_specifier_list_parse_into(link_specifier_list_t *obj, const uint8_t *input, const size_t len_in)
    2663             : {
    2664         144 :   const uint8_t *ptr = input;
    2665         144 :   size_t remaining = len_in;
    2666         144 :   ssize_t result = 0;
    2667         144 :   (void)result;
    2668             : 
    2669             :   /* Parse u8 n_spec */
    2670         144 :   CHECK_REMAINING(1, truncated);
    2671         144 :   obj->n_spec = (trunnel_get_uint8(ptr));
    2672         144 :   remaining -= 1; ptr += 1;
    2673             : 
    2674             :   /* Parse struct link_specifier spec[n_spec] */
    2675         144 :   TRUNNEL_DYNARRAY_EXPAND(link_specifier_t *, &obj->spec, obj->n_spec, {});
    2676             :   {
    2677         144 :     link_specifier_t * elt;
    2678         144 :     unsigned idx;
    2679         432 :     for (idx = 0; idx < obj->n_spec; ++idx) {
    2680         288 :       result = link_specifier_parse(&elt, ptr, remaining);
    2681         288 :       if (result < 0)
    2682           0 :         goto relay_fail;
    2683         288 :       trunnel_assert((size_t)result <= remaining);
    2684         288 :       remaining -= result; ptr += result;
    2685         288 :       TRUNNEL_DYNARRAY_ADD(link_specifier_t *, &obj->spec, elt, {link_specifier_free(elt);});
    2686             :     }
    2687             :   }
    2688         144 :   trunnel_assert(ptr + remaining == input + len_in);
    2689         144 :   return len_in - remaining;
    2690             : 
    2691           0 :  truncated:
    2692           0 :   return -2;
    2693           0 :  relay_fail:
    2694           0 :   trunnel_assert(result < 0);
    2695             :   return result;
    2696             :  trunnel_alloc_failed:
    2697             :   return -1;
    2698             : }
    2699             : 
    2700             : ssize_t
    2701         144 : link_specifier_list_parse(link_specifier_list_t **output, const uint8_t *input, const size_t len_in)
    2702             : {
    2703         144 :   ssize_t result;
    2704         144 :   *output = link_specifier_list_new();
    2705         144 :   if (NULL == *output)
    2706             :     return -1;
    2707         144 :   result = link_specifier_list_parse_into(*output, input, len_in);
    2708         144 :   if (result < 0) {
    2709           0 :     link_specifier_list_free(*output);
    2710           0 :     *output = NULL;
    2711             :   }
    2712             :   return result;
    2713             : }

Generated by: LCOV version 1.14