LCOV - code coverage report
Current view: top level - trunnel/hs - cell_introduce1.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 412 668 61.7 %
Date: 2021-11-24 03:28:48 Functions: 60 104 57.7 %

          Line data    Source code
       1             : /* cell_introduce1.c -- generated by Trunnel v1.5.3.
       2             :  * https://gitweb.torproject.org/trunnel.git
       3             :  * You probably shouldn't edit this file.
       4             :  */
       5             : #include <stdlib.h>
       6             : #include "trunnel-impl.h"
       7             : 
       8             : #include "cell_introduce1.h"
       9             : 
      10             : #define TRUNNEL_SET_ERROR_CODE(obj) \
      11             :   do {                              \
      12             :     (obj)->trunnel_error_code_ = 1; \
      13             :   } while (0)
      14             : 
      15             : #if defined(__COVERITY__) || defined(__clang_analyzer__)
      16             : /* If we're running a static analysis tool, we don't want it to complain
      17             :  * that some of our remaining-bytes checks are dead-code. */
      18             : int cellintroduce_deadcode_dummy__ = 0;
      19             : #define OR_DEADCODE_DUMMY || cellintroduce_deadcode_dummy__
      20             : #else
      21             : #define OR_DEADCODE_DUMMY
      22             : #endif
      23             : 
      24             : #define CHECK_REMAINING(nbytes, label)                           \
      25             :   do {                                                           \
      26             :     if (remaining < (nbytes) OR_DEADCODE_DUMMY) {                \
      27             :       goto label;                                                \
      28             :     }                                                            \
      29             :   } while (0)
      30             : 
      31             : typedef struct trn_cell_extension_st trn_cell_extension_t;
      32             : trn_cell_extension_t *trn_cell_extension_new(void);
      33             : void trn_cell_extension_free(trn_cell_extension_t *victim);
      34             : ssize_t trn_cell_extension_parse(trn_cell_extension_t **output, const uint8_t *input, const size_t len_in);
      35             : ssize_t trn_cell_extension_encoded_len(const trn_cell_extension_t *obj);
      36             : ssize_t trn_cell_extension_encode(uint8_t *output, size_t avail, const trn_cell_extension_t *input);
      37             : const char *trn_cell_extension_check(const trn_cell_extension_t *obj);
      38             : int trn_cell_extension_clear_errors(trn_cell_extension_t *obj);
      39             : typedef struct link_specifier_st link_specifier_t;
      40             : link_specifier_t *link_specifier_new(void);
      41             : void link_specifier_free(link_specifier_t *victim);
      42             : ssize_t link_specifier_parse(link_specifier_t **output, const uint8_t *input, const size_t len_in);
      43             : ssize_t link_specifier_encoded_len(const link_specifier_t *obj);
      44             : ssize_t link_specifier_encode(uint8_t *output, size_t avail, const link_specifier_t *input);
      45             : const char *link_specifier_check(const link_specifier_t *obj);
      46             : int link_specifier_clear_errors(link_specifier_t *obj);
      47             : trn_cell_introduce1_t *
      48          16 : trn_cell_introduce1_new(void)
      49             : {
      50          16 :   trn_cell_introduce1_t *val = trunnel_calloc(1, sizeof(trn_cell_introduce1_t));
      51          16 :   if (NULL == val)
      52             :     return NULL;
      53          16 :   val->auth_key_type = TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519;
      54          16 :   return val;
      55             : }
      56             : 
      57             : /** Release all storage held inside 'obj', but do not free 'obj'.
      58             :  */
      59             : static void
      60          16 : trn_cell_introduce1_clear(trn_cell_introduce1_t *obj)
      61             : {
      62          16 :   (void) obj;
      63          16 :   TRUNNEL_DYNARRAY_WIPE(&obj->auth_key);
      64          16 :   TRUNNEL_DYNARRAY_CLEAR(&obj->auth_key);
      65          16 :   trn_cell_extension_free(obj->extensions);
      66          16 :   obj->extensions = NULL;
      67          16 :   TRUNNEL_DYNARRAY_WIPE(&obj->encrypted);
      68          16 :   TRUNNEL_DYNARRAY_CLEAR(&obj->encrypted);
      69          16 : }
      70             : 
      71             : void
      72          17 : trn_cell_introduce1_free(trn_cell_introduce1_t *obj)
      73             : {
      74          17 :   if (obj == NULL)
      75             :     return;
      76          16 :   trn_cell_introduce1_clear(obj);
      77          16 :   trunnel_memwipe(obj, sizeof(trn_cell_introduce1_t));
      78          16 :   trunnel_free_(obj);
      79             : }
      80             : 
      81             : size_t
      82          10 : trn_cell_introduce1_getlen_legacy_key_id(const trn_cell_introduce1_t *inp)
      83             : {
      84          10 :   (void)inp;  return TRUNNEL_SHA1_LEN;
      85             : }
      86             : 
      87             : uint8_t
      88           0 : trn_cell_introduce1_get_legacy_key_id(trn_cell_introduce1_t *inp, size_t idx)
      89             : {
      90           0 :   trunnel_assert(idx < TRUNNEL_SHA1_LEN);
      91           0 :   return inp->legacy_key_id[idx];
      92             : }
      93             : 
      94             : uint8_t
      95           0 : trn_cell_introduce1_getconst_legacy_key_id(const trn_cell_introduce1_t *inp, size_t idx)
      96             : {
      97           0 :   return trn_cell_introduce1_get_legacy_key_id((trn_cell_introduce1_t*)inp, idx);
      98             : }
      99             : int
     100           0 : trn_cell_introduce1_set_legacy_key_id(trn_cell_introduce1_t *inp, size_t idx, uint8_t elt)
     101             : {
     102           0 :   trunnel_assert(idx < TRUNNEL_SHA1_LEN);
     103           0 :   inp->legacy_key_id[idx] = elt;
     104           0 :   return 0;
     105             : }
     106             : 
     107             : uint8_t *
     108          10 : trn_cell_introduce1_getarray_legacy_key_id(trn_cell_introduce1_t *inp)
     109             : {
     110          10 :   return inp->legacy_key_id;
     111             : }
     112             : const uint8_t  *
     113          10 : trn_cell_introduce1_getconstarray_legacy_key_id(const trn_cell_introduce1_t *inp)
     114             : {
     115          10 :   return (const uint8_t  *)trn_cell_introduce1_getarray_legacy_key_id((trn_cell_introduce1_t*)inp);
     116             : }
     117             : uint8_t
     118          10 : trn_cell_introduce1_get_auth_key_type(const trn_cell_introduce1_t *inp)
     119             : {
     120          10 :   return inp->auth_key_type;
     121             : }
     122             : int
     123           6 : trn_cell_introduce1_set_auth_key_type(trn_cell_introduce1_t *inp, uint8_t val)
     124             : {
     125           6 :   if (! ((val == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519 || val == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0 || val == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1))) {
     126           0 :      TRUNNEL_SET_ERROR_CODE(inp);
     127           0 :      return -1;
     128             :   }
     129           6 :   inp->auth_key_type = val;
     130           6 :   return 0;
     131             : }
     132             : uint16_t
     133           9 : trn_cell_introduce1_get_auth_key_len(const trn_cell_introduce1_t *inp)
     134             : {
     135           9 :   return inp->auth_key_len;
     136             : }
     137             : int
     138           6 : trn_cell_introduce1_set_auth_key_len(trn_cell_introduce1_t *inp, uint16_t val)
     139             : {
     140           6 :   inp->auth_key_len = val;
     141           6 :   return 0;
     142             : }
     143             : size_t
     144          12 : trn_cell_introduce1_getlen_auth_key(const trn_cell_introduce1_t *inp)
     145             : {
     146          12 :   return TRUNNEL_DYNARRAY_LEN(&inp->auth_key);
     147             : }
     148             : 
     149             : uint8_t
     150           0 : trn_cell_introduce1_get_auth_key(trn_cell_introduce1_t *inp, size_t idx)
     151             : {
     152           0 :   return TRUNNEL_DYNARRAY_GET(&inp->auth_key, idx);
     153             : }
     154             : 
     155             : uint8_t
     156           0 : trn_cell_introduce1_getconst_auth_key(const trn_cell_introduce1_t *inp, size_t idx)
     157             : {
     158           0 :   return trn_cell_introduce1_get_auth_key((trn_cell_introduce1_t*)inp, idx);
     159             : }
     160             : int
     161           0 : trn_cell_introduce1_set_auth_key(trn_cell_introduce1_t *inp, size_t idx, uint8_t elt)
     162             : {
     163           0 :   TRUNNEL_DYNARRAY_SET(&inp->auth_key, idx, elt);
     164           0 :   return 0;
     165             : }
     166             : int
     167           0 : trn_cell_introduce1_add_auth_key(trn_cell_introduce1_t *inp, uint8_t elt)
     168             : {
     169             : #if SIZE_MAX >= UINT16_MAX
     170           0 :   if (inp->auth_key.n_ == UINT16_MAX)
     171           0 :     goto trunnel_alloc_failed;
     172             : #endif
     173           0 :   TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->auth_key, elt, {});
     174           0 :   return 0;
     175           0 :  trunnel_alloc_failed:
     176           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     177           0 :   return -1;
     178             : }
     179             : 
     180             : uint8_t *
     181           8 : trn_cell_introduce1_getarray_auth_key(trn_cell_introduce1_t *inp)
     182             : {
     183           8 :   return inp->auth_key.elts_;
     184             : }
     185             : const uint8_t  *
     186           2 : trn_cell_introduce1_getconstarray_auth_key(const trn_cell_introduce1_t *inp)
     187             : {
     188           2 :   return (const uint8_t  *)trn_cell_introduce1_getarray_auth_key((trn_cell_introduce1_t*)inp);
     189             : }
     190             : int
     191           8 : trn_cell_introduce1_setlen_auth_key(trn_cell_introduce1_t *inp, size_t newlen)
     192             : {
     193           8 :   uint8_t *newptr;
     194             : #if UINT16_MAX < SIZE_MAX
     195           8 :   if (newlen > UINT16_MAX)
     196           0 :     goto trunnel_alloc_failed;
     197             : #endif
     198          16 :   newptr = trunnel_dynarray_setlen(&inp->auth_key.allocated_,
     199           8 :                  &inp->auth_key.n_, inp->auth_key.elts_, newlen,
     200             :                  sizeof(inp->auth_key.elts_[0]), (trunnel_free_fn_t) NULL,
     201             :                  &inp->trunnel_error_code_);
     202           8 :   if (newlen != 0 && newptr == NULL)
     203           0 :     goto trunnel_alloc_failed;
     204           8 :   inp->auth_key.elts_ = newptr;
     205           8 :   return 0;
     206           0 :  trunnel_alloc_failed:
     207           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     208           0 :   return -1;
     209             : }
     210             : struct trn_cell_extension_st *
     211           0 : trn_cell_introduce1_get_extensions(trn_cell_introduce1_t *inp)
     212             : {
     213           0 :   return inp->extensions;
     214             : }
     215             : const struct trn_cell_extension_st *
     216           0 : trn_cell_introduce1_getconst_extensions(const trn_cell_introduce1_t *inp)
     217             : {
     218           0 :   return trn_cell_introduce1_get_extensions((trn_cell_introduce1_t*) inp);
     219             : }
     220             : int
     221           6 : trn_cell_introduce1_set_extensions(trn_cell_introduce1_t *inp, struct trn_cell_extension_st *val)
     222             : {
     223           6 :   if (inp->extensions && inp->extensions != val)
     224           0 :     trn_cell_extension_free(inp->extensions);
     225           6 :   return trn_cell_introduce1_set0_extensions(inp, val);
     226             : }
     227             : int
     228           6 : trn_cell_introduce1_set0_extensions(trn_cell_introduce1_t *inp, struct trn_cell_extension_st *val)
     229             : {
     230           6 :   inp->extensions = val;
     231           6 :   return 0;
     232             : }
     233             : size_t
     234          14 : trn_cell_introduce1_getlen_encrypted(const trn_cell_introduce1_t *inp)
     235             : {
     236          14 :   return TRUNNEL_DYNARRAY_LEN(&inp->encrypted);
     237             : }
     238             : 
     239             : uint8_t
     240           0 : trn_cell_introduce1_get_encrypted(trn_cell_introduce1_t *inp, size_t idx)
     241             : {
     242           0 :   return TRUNNEL_DYNARRAY_GET(&inp->encrypted, idx);
     243             : }
     244             : 
     245             : uint8_t
     246           0 : trn_cell_introduce1_getconst_encrypted(const trn_cell_introduce1_t *inp, size_t idx)
     247             : {
     248           0 :   return trn_cell_introduce1_get_encrypted((trn_cell_introduce1_t*)inp, idx);
     249             : }
     250             : int
     251           0 : trn_cell_introduce1_set_encrypted(trn_cell_introduce1_t *inp, size_t idx, uint8_t elt)
     252             : {
     253           0 :   TRUNNEL_DYNARRAY_SET(&inp->encrypted, idx, elt);
     254           0 :   return 0;
     255             : }
     256             : int
     257           0 : trn_cell_introduce1_add_encrypted(trn_cell_introduce1_t *inp, uint8_t elt)
     258             : {
     259           0 :   TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->encrypted, elt, {});
     260           0 :   return 0;
     261           0 :  trunnel_alloc_failed:
     262           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     263           0 :   return -1;
     264             : }
     265             : 
     266             : uint8_t *
     267          14 : trn_cell_introduce1_getarray_encrypted(trn_cell_introduce1_t *inp)
     268             : {
     269          14 :   return inp->encrypted.elts_;
     270             : }
     271             : const uint8_t  *
     272           8 : trn_cell_introduce1_getconstarray_encrypted(const trn_cell_introduce1_t *inp)
     273             : {
     274           8 :   return (const uint8_t  *)trn_cell_introduce1_getarray_encrypted((trn_cell_introduce1_t*)inp);
     275             : }
     276             : int
     277           8 : trn_cell_introduce1_setlen_encrypted(trn_cell_introduce1_t *inp, size_t newlen)
     278             : {
     279           8 :   uint8_t *newptr;
     280          16 :   newptr = trunnel_dynarray_setlen(&inp->encrypted.allocated_,
     281           8 :                  &inp->encrypted.n_, inp->encrypted.elts_, newlen,
     282             :                  sizeof(inp->encrypted.elts_[0]), (trunnel_free_fn_t) NULL,
     283             :                  &inp->trunnel_error_code_);
     284           8 :   if (newlen != 0 && newptr == NULL)
     285           0 :     goto trunnel_alloc_failed;
     286           8 :   inp->encrypted.elts_ = newptr;
     287           8 :   return 0;
     288           0 :  trunnel_alloc_failed:
     289           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     290           0 :   return -1;
     291             : }
     292             : const char *
     293          14 : trn_cell_introduce1_check(const trn_cell_introduce1_t *obj)
     294             : {
     295          14 :   if (obj == NULL)
     296             :     return "Object was NULL";
     297          14 :   if (obj->trunnel_error_code_)
     298             :     return "A set function failed on this object";
     299          14 :   if (! (obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1))
     300             :     return "Integer out of bounds";
     301          14 :   if (TRUNNEL_DYNARRAY_LEN(&obj->auth_key) != obj->auth_key_len)
     302             :     return "Length mismatch for auth_key";
     303             :   {
     304          14 :     const char *msg;
     305          14 :     if (NULL != (msg = trn_cell_extension_check(obj->extensions)))
     306           0 :       return msg;
     307             :   }
     308             :   return NULL;
     309             : }
     310             : 
     311             : ssize_t
     312           5 : trn_cell_introduce1_encoded_len(const trn_cell_introduce1_t *obj)
     313             : {
     314           5 :   ssize_t result = 0;
     315             : 
     316           5 :   if (NULL != trn_cell_introduce1_check(obj))
     317             :      return -1;
     318             : 
     319             : 
     320             :   /* Length of u8 legacy_key_id[TRUNNEL_SHA1_LEN] */
     321           5 :   result += TRUNNEL_SHA1_LEN;
     322             : 
     323             :   /* Length of u8 auth_key_type IN [TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1] */
     324           5 :   result += 1;
     325             : 
     326             :   /* Length of u16 auth_key_len */
     327           5 :   result += 2;
     328             : 
     329             :   /* Length of u8 auth_key[auth_key_len] */
     330           5 :   result += TRUNNEL_DYNARRAY_LEN(&obj->auth_key);
     331             : 
     332             :   /* Length of struct trn_cell_extension extensions */
     333           5 :   result += trn_cell_extension_encoded_len(obj->extensions);
     334             : 
     335             :   /* Length of u8 encrypted[] */
     336           5 :   result += TRUNNEL_DYNARRAY_LEN(&obj->encrypted);
     337           5 :   return result;
     338             : }
     339             : int
     340           0 : trn_cell_introduce1_clear_errors(trn_cell_introduce1_t *obj)
     341             : {
     342           0 :   int r = obj->trunnel_error_code_;
     343           0 :   obj->trunnel_error_code_ = 0;
     344           0 :   return r;
     345             : }
     346             : ssize_t
     347           9 : trn_cell_introduce1_encode(uint8_t *output, const size_t avail, const trn_cell_introduce1_t *obj)
     348             : {
     349           9 :   ssize_t result = 0;
     350           9 :   size_t written = 0;
     351           9 :   uint8_t *ptr = output;
     352           9 :   const char *msg;
     353             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     354             :   const ssize_t encoded_len = trn_cell_introduce1_encoded_len(obj);
     355             : #endif
     356             : 
     357           9 :   if (NULL != (msg = trn_cell_introduce1_check(obj)))
     358           0 :     goto check_failed;
     359             : 
     360             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     361             :   trunnel_assert(encoded_len >= 0);
     362             : #endif
     363             : 
     364             :   /* Encode u8 legacy_key_id[TRUNNEL_SHA1_LEN] */
     365           9 :   trunnel_assert(written <= avail);
     366           9 :   if (avail - written < TRUNNEL_SHA1_LEN)
     367           0 :     goto truncated;
     368           9 :   memcpy(ptr, obj->legacy_key_id, TRUNNEL_SHA1_LEN);
     369           9 :   written += TRUNNEL_SHA1_LEN; ptr += TRUNNEL_SHA1_LEN;
     370             : 
     371             :   /* Encode u8 auth_key_type IN [TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1] */
     372           9 :   trunnel_assert(written <= avail);
     373           9 :   if (avail - written < 1)
     374           0 :     goto truncated;
     375           9 :   trunnel_set_uint8(ptr, (obj->auth_key_type));
     376           9 :   written += 1; ptr += 1;
     377             : 
     378             :   /* Encode u16 auth_key_len */
     379           9 :   trunnel_assert(written <= avail);
     380           9 :   if (avail - written < 2)
     381           0 :     goto truncated;
     382           9 :   trunnel_set_uint16(ptr, trunnel_htons(obj->auth_key_len));
     383           9 :   written += 2; ptr += 2;
     384             : 
     385             :   /* Encode u8 auth_key[auth_key_len] */
     386             :   {
     387           9 :     size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->auth_key);
     388           9 :     trunnel_assert(obj->auth_key_len == elt_len);
     389           9 :     trunnel_assert(written <= avail);
     390           9 :     if (avail - written < elt_len)
     391           0 :       goto truncated;
     392           9 :     if (elt_len)
     393           9 :       memcpy(ptr, obj->auth_key.elts_, elt_len);
     394           9 :     written += elt_len; ptr += elt_len;
     395             :   }
     396             : 
     397             :   /* Encode struct trn_cell_extension extensions */
     398           9 :   trunnel_assert(written <= avail);
     399           9 :   result = trn_cell_extension_encode(ptr, avail - written, obj->extensions);
     400           9 :   if (result < 0)
     401           0 :     goto fail; /* XXXXXXX !*/
     402           9 :   written += result; ptr += result;
     403             : 
     404             :   /* Encode u8 encrypted[] */
     405             :   {
     406           9 :     size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->encrypted);
     407           9 :     trunnel_assert(written <= avail);
     408           9 :     if (avail - written < elt_len)
     409           0 :       goto truncated;
     410           9 :     if (elt_len)
     411           5 :       memcpy(ptr, obj->encrypted.elts_, elt_len);
     412           9 :     written += elt_len; ptr += elt_len;
     413             :   }
     414             : 
     415             : 
     416           9 :   trunnel_assert(ptr == output + written);
     417             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     418             :   {
     419             :     trunnel_assert(encoded_len >= 0);
     420             :     trunnel_assert((size_t)encoded_len == written);
     421             :   }
     422             : 
     423             : #endif
     424             : 
     425           9 :   return written;
     426             : 
     427           0 :  truncated:
     428           0 :   result = -2;
     429           0 :   goto fail;
     430           0 :  check_failed:
     431           0 :   (void)msg;
     432           0 :   result = -1;
     433           0 :   goto fail;
     434           0 :  fail:
     435           0 :   trunnel_assert(result < 0);
     436             :   return result;
     437             : }
     438             : 
     439             : /** As trn_cell_introduce1_parse(), but do not allocate the output
     440             :  * object.
     441             :  */
     442             : static ssize_t
     443          10 : trn_cell_introduce1_parse_into(trn_cell_introduce1_t *obj, const uint8_t *input, const size_t len_in)
     444             : {
     445          10 :   const uint8_t *ptr = input;
     446          10 :   size_t remaining = len_in;
     447          10 :   ssize_t result = 0;
     448          10 :   (void)result;
     449             : 
     450             :   /* Parse u8 legacy_key_id[TRUNNEL_SHA1_LEN] */
     451          10 :   CHECK_REMAINING(TRUNNEL_SHA1_LEN, truncated);
     452           9 :   memcpy(obj->legacy_key_id, ptr, TRUNNEL_SHA1_LEN);
     453           9 :   remaining -= TRUNNEL_SHA1_LEN; ptr += TRUNNEL_SHA1_LEN;
     454             : 
     455             :   /* Parse u8 auth_key_type IN [TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1] */
     456           9 :   CHECK_REMAINING(1, truncated);
     457           9 :   obj->auth_key_type = (trunnel_get_uint8(ptr));
     458           9 :   remaining -= 1; ptr += 1;
     459           9 :   if (! (obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1))
     460           0 :     goto fail;
     461             : 
     462             :   /* Parse u16 auth_key_len */
     463           9 :   CHECK_REMAINING(2, truncated);
     464           9 :   obj->auth_key_len = trunnel_ntohs(trunnel_get_uint16(ptr));
     465           9 :   remaining -= 2; ptr += 2;
     466             : 
     467             :   /* Parse u8 auth_key[auth_key_len] */
     468           9 :   CHECK_REMAINING(obj->auth_key_len, truncated);
     469           9 :   TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->auth_key, obj->auth_key_len, {});
     470           9 :   obj->auth_key.n_ = obj->auth_key_len;
     471           9 :   if (obj->auth_key_len)
     472           8 :     memcpy(obj->auth_key.elts_, ptr, obj->auth_key_len);
     473           9 :   ptr += obj->auth_key_len; remaining -= obj->auth_key_len;
     474             : 
     475             :   /* Parse struct trn_cell_extension extensions */
     476           9 :   result = trn_cell_extension_parse(&obj->extensions, ptr, remaining);
     477           9 :   if (result < 0)
     478           0 :     goto relay_fail;
     479           9 :   trunnel_assert((size_t)result <= remaining);
     480           9 :   remaining -= result; ptr += result;
     481             : 
     482             :   /* Parse u8 encrypted[] */
     483           9 :   TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->encrypted, remaining, {});
     484           9 :   obj->encrypted.n_ = remaining;
     485           9 :   if (remaining)
     486           9 :     memcpy(obj->encrypted.elts_, ptr, remaining);
     487           9 :   ptr += remaining; remaining -= remaining;
     488           9 :   trunnel_assert(ptr + remaining == input + len_in);
     489           9 :   return len_in - remaining;
     490             : 
     491             :  truncated:
     492             :   return -2;
     493           0 :  relay_fail:
     494           0 :   trunnel_assert(result < 0);
     495             :   return result;
     496             :  trunnel_alloc_failed:
     497             :   return -1;
     498           0 :  fail:
     499           0 :   result = -1;
     500           0 :   return result;
     501             : }
     502             : 
     503             : ssize_t
     504          10 : trn_cell_introduce1_parse(trn_cell_introduce1_t **output, const uint8_t *input, const size_t len_in)
     505             : {
     506          10 :   ssize_t result;
     507          10 :   *output = trn_cell_introduce1_new();
     508          10 :   if (NULL == *output)
     509             :     return -1;
     510          10 :   result = trn_cell_introduce1_parse_into(*output, input, len_in);
     511          10 :   if (result < 0) {
     512           1 :     trn_cell_introduce1_free(*output);
     513           1 :     *output = NULL;
     514             :   }
     515             :   return result;
     516             : }
     517             : trn_cell_introduce_ack_t *
     518           2 : trn_cell_introduce_ack_new(void)
     519             : {
     520           2 :   trn_cell_introduce_ack_t *val = trunnel_calloc(1, sizeof(trn_cell_introduce_ack_t));
     521           2 :   if (NULL == val)
     522           0 :     return NULL;
     523             :   return val;
     524             : }
     525             : 
     526             : /** Release all storage held inside 'obj', but do not free 'obj'.
     527             :  */
     528             : static void
     529           2 : trn_cell_introduce_ack_clear(trn_cell_introduce_ack_t *obj)
     530             : {
     531           2 :   (void) obj;
     532           2 :   trn_cell_extension_free(obj->extensions);
     533           2 :   obj->extensions = NULL;
     534           2 : }
     535             : 
     536             : void
     537           2 : trn_cell_introduce_ack_free(trn_cell_introduce_ack_t *obj)
     538             : {
     539           2 :   if (obj == NULL)
     540             :     return;
     541           2 :   trn_cell_introduce_ack_clear(obj);
     542           2 :   trunnel_memwipe(obj, sizeof(trn_cell_introduce_ack_t));
     543           2 :   trunnel_free_(obj);
     544             : }
     545             : 
     546             : uint16_t
     547           0 : trn_cell_introduce_ack_get_status(const trn_cell_introduce_ack_t *inp)
     548             : {
     549           0 :   return inp->status;
     550             : }
     551             : int
     552           2 : trn_cell_introduce_ack_set_status(trn_cell_introduce_ack_t *inp, uint16_t val)
     553             : {
     554           2 :   inp->status = val;
     555           2 :   return 0;
     556             : }
     557             : struct trn_cell_extension_st *
     558           0 : trn_cell_introduce_ack_get_extensions(trn_cell_introduce_ack_t *inp)
     559             : {
     560           0 :   return inp->extensions;
     561             : }
     562             : const struct trn_cell_extension_st *
     563           0 : trn_cell_introduce_ack_getconst_extensions(const trn_cell_introduce_ack_t *inp)
     564             : {
     565           0 :   return trn_cell_introduce_ack_get_extensions((trn_cell_introduce_ack_t*) inp);
     566             : }
     567             : int
     568           2 : trn_cell_introduce_ack_set_extensions(trn_cell_introduce_ack_t *inp, struct trn_cell_extension_st *val)
     569             : {
     570           2 :   if (inp->extensions && inp->extensions != val)
     571           0 :     trn_cell_extension_free(inp->extensions);
     572           2 :   return trn_cell_introduce_ack_set0_extensions(inp, val);
     573             : }
     574             : int
     575           2 : trn_cell_introduce_ack_set0_extensions(trn_cell_introduce_ack_t *inp, struct trn_cell_extension_st *val)
     576             : {
     577           2 :   inp->extensions = val;
     578           2 :   return 0;
     579             : }
     580             : const char *
     581           4 : trn_cell_introduce_ack_check(const trn_cell_introduce_ack_t *obj)
     582             : {
     583           4 :   if (obj == NULL)
     584             :     return "Object was NULL";
     585           4 :   if (obj->trunnel_error_code_)
     586             :     return "A set function failed on this object";
     587             :   {
     588           4 :     const char *msg;
     589           4 :     if (NULL != (msg = trn_cell_extension_check(obj->extensions)))
     590           0 :       return msg;
     591             :   }
     592             :   return NULL;
     593             : }
     594             : 
     595             : ssize_t
     596           2 : trn_cell_introduce_ack_encoded_len(const trn_cell_introduce_ack_t *obj)
     597             : {
     598           2 :   ssize_t result = 0;
     599             : 
     600           2 :   if (NULL != trn_cell_introduce_ack_check(obj))
     601             :      return -1;
     602             : 
     603             : 
     604             :   /* Length of u16 status */
     605           2 :   result += 2;
     606             : 
     607             :   /* Length of struct trn_cell_extension extensions */
     608           2 :   result += trn_cell_extension_encoded_len(obj->extensions);
     609           2 :   return result;
     610             : }
     611             : int
     612           0 : trn_cell_introduce_ack_clear_errors(trn_cell_introduce_ack_t *obj)
     613             : {
     614           0 :   int r = obj->trunnel_error_code_;
     615           0 :   obj->trunnel_error_code_ = 0;
     616           0 :   return r;
     617             : }
     618             : ssize_t
     619           2 : trn_cell_introduce_ack_encode(uint8_t *output, const size_t avail, const trn_cell_introduce_ack_t *obj)
     620             : {
     621           2 :   ssize_t result = 0;
     622           2 :   size_t written = 0;
     623           2 :   uint8_t *ptr = output;
     624           2 :   const char *msg;
     625             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     626             :   const ssize_t encoded_len = trn_cell_introduce_ack_encoded_len(obj);
     627             : #endif
     628             : 
     629           2 :   if (NULL != (msg = trn_cell_introduce_ack_check(obj)))
     630           0 :     goto check_failed;
     631             : 
     632             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     633             :   trunnel_assert(encoded_len >= 0);
     634             : #endif
     635             : 
     636             :   /* Encode u16 status */
     637           2 :   trunnel_assert(written <= avail);
     638           2 :   if (avail - written < 2)
     639           0 :     goto truncated;
     640           2 :   trunnel_set_uint16(ptr, trunnel_htons(obj->status));
     641           2 :   written += 2; ptr += 2;
     642             : 
     643             :   /* Encode struct trn_cell_extension extensions */
     644           2 :   trunnel_assert(written <= avail);
     645           2 :   result = trn_cell_extension_encode(ptr, avail - written, obj->extensions);
     646           2 :   if (result < 0)
     647           0 :     goto fail; /* XXXXXXX !*/
     648           2 :   written += result; ptr += result;
     649             : 
     650             : 
     651           2 :   trunnel_assert(ptr == output + written);
     652             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     653             :   {
     654             :     trunnel_assert(encoded_len >= 0);
     655             :     trunnel_assert((size_t)encoded_len == written);
     656             :   }
     657             : 
     658             : #endif
     659             : 
     660           2 :   return written;
     661             : 
     662           0 :  truncated:
     663           0 :   result = -2;
     664           0 :   goto fail;
     665           0 :  check_failed:
     666           0 :   (void)msg;
     667           0 :   result = -1;
     668           0 :   goto fail;
     669           0 :  fail:
     670           0 :   trunnel_assert(result < 0);
     671             :   return result;
     672             : }
     673             : 
     674             : /** As trn_cell_introduce_ack_parse(), but do not allocate the output
     675             :  * object.
     676             :  */
     677             : static ssize_t
     678           0 : trn_cell_introduce_ack_parse_into(trn_cell_introduce_ack_t *obj, const uint8_t *input, const size_t len_in)
     679             : {
     680           0 :   const uint8_t *ptr = input;
     681           0 :   size_t remaining = len_in;
     682           0 :   ssize_t result = 0;
     683           0 :   (void)result;
     684             : 
     685             :   /* Parse u16 status */
     686           0 :   CHECK_REMAINING(2, truncated);
     687           0 :   obj->status = trunnel_ntohs(trunnel_get_uint16(ptr));
     688           0 :   remaining -= 2; ptr += 2;
     689             : 
     690             :   /* Parse struct trn_cell_extension extensions */
     691           0 :   result = trn_cell_extension_parse(&obj->extensions, ptr, remaining);
     692           0 :   if (result < 0)
     693           0 :     goto relay_fail;
     694           0 :   trunnel_assert((size_t)result <= remaining);
     695           0 :   remaining -= result; ptr += result;
     696           0 :   trunnel_assert(ptr + remaining == input + len_in);
     697           0 :   return len_in - remaining;
     698             : 
     699           0 :  truncated:
     700           0 :   return -2;
     701           0 :  relay_fail:
     702           0 :   trunnel_assert(result < 0);
     703             :   return result;
     704             : }
     705             : 
     706             : ssize_t
     707           0 : trn_cell_introduce_ack_parse(trn_cell_introduce_ack_t **output, const uint8_t *input, const size_t len_in)
     708             : {
     709           0 :   ssize_t result;
     710           0 :   *output = trn_cell_introduce_ack_new();
     711           0 :   if (NULL == *output)
     712             :     return -1;
     713           0 :   result = trn_cell_introduce_ack_parse_into(*output, input, len_in);
     714           0 :   if (result < 0) {
     715           0 :     trn_cell_introduce_ack_free(*output);
     716           0 :     *output = NULL;
     717             :   }
     718             :   return result;
     719             : }
     720             : trn_cell_introduce_encrypted_t *
     721           9 : trn_cell_introduce_encrypted_new(void)
     722             : {
     723           9 :   trn_cell_introduce_encrypted_t *val = trunnel_calloc(1, sizeof(trn_cell_introduce_encrypted_t));
     724           9 :   if (NULL == val)
     725             :     return NULL;
     726           9 :   val->onion_key_type = TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR;
     727           9 :   return val;
     728             : }
     729             : 
     730             : /** Release all storage held inside 'obj', but do not free 'obj'.
     731             :  */
     732             : static void
     733           9 : trn_cell_introduce_encrypted_clear(trn_cell_introduce_encrypted_t *obj)
     734             : {
     735           9 :   (void) obj;
     736           9 :   trn_cell_extension_free(obj->extensions);
     737           9 :   obj->extensions = NULL;
     738           9 :   TRUNNEL_DYNARRAY_WIPE(&obj->onion_key);
     739           9 :   TRUNNEL_DYNARRAY_CLEAR(&obj->onion_key);
     740             :   {
     741             : 
     742           9 :     unsigned idx;
     743          18 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->nspecs); ++idx) {
     744           9 :       link_specifier_free(TRUNNEL_DYNARRAY_GET(&obj->nspecs, idx));
     745             :     }
     746             :   }
     747           9 :   TRUNNEL_DYNARRAY_WIPE(&obj->nspecs);
     748           9 :   TRUNNEL_DYNARRAY_CLEAR(&obj->nspecs);
     749           9 :   TRUNNEL_DYNARRAY_WIPE(&obj->pad);
     750           9 :   TRUNNEL_DYNARRAY_CLEAR(&obj->pad);
     751           9 : }
     752             : 
     753             : void
     754          12 : trn_cell_introduce_encrypted_free(trn_cell_introduce_encrypted_t *obj)
     755             : {
     756          12 :   if (obj == NULL)
     757             :     return;
     758           9 :   trn_cell_introduce_encrypted_clear(obj);
     759           9 :   trunnel_memwipe(obj, sizeof(trn_cell_introduce_encrypted_t));
     760           9 :   trunnel_free_(obj);
     761             : }
     762             : 
     763             : size_t
     764           0 : trn_cell_introduce_encrypted_getlen_rend_cookie(const trn_cell_introduce_encrypted_t *inp)
     765             : {
     766           0 :   (void)inp;  return TRUNNEL_REND_COOKIE_LEN;
     767             : }
     768             : 
     769             : uint8_t
     770           0 : trn_cell_introduce_encrypted_get_rend_cookie(trn_cell_introduce_encrypted_t *inp, size_t idx)
     771             : {
     772           0 :   trunnel_assert(idx < TRUNNEL_REND_COOKIE_LEN);
     773           0 :   return inp->rend_cookie[idx];
     774             : }
     775             : 
     776             : uint8_t
     777           0 : trn_cell_introduce_encrypted_getconst_rend_cookie(const trn_cell_introduce_encrypted_t *inp, size_t idx)
     778             : {
     779           0 :   return trn_cell_introduce_encrypted_get_rend_cookie((trn_cell_introduce_encrypted_t*)inp, idx);
     780             : }
     781             : int
     782           0 : trn_cell_introduce_encrypted_set_rend_cookie(trn_cell_introduce_encrypted_t *inp, size_t idx, uint8_t elt)
     783             : {
     784           0 :   trunnel_assert(idx < TRUNNEL_REND_COOKIE_LEN);
     785           0 :   inp->rend_cookie[idx] = elt;
     786           0 :   return 0;
     787             : }
     788             : 
     789             : uint8_t *
     790           9 : trn_cell_introduce_encrypted_getarray_rend_cookie(trn_cell_introduce_encrypted_t *inp)
     791             : {
     792           9 :   return inp->rend_cookie;
     793             : }
     794             : const uint8_t  *
     795           5 : trn_cell_introduce_encrypted_getconstarray_rend_cookie(const trn_cell_introduce_encrypted_t *inp)
     796             : {
     797           5 :   return (const uint8_t  *)trn_cell_introduce_encrypted_getarray_rend_cookie((trn_cell_introduce_encrypted_t*)inp);
     798             : }
     799             : struct trn_cell_extension_st *
     800           0 : trn_cell_introduce_encrypted_get_extensions(trn_cell_introduce_encrypted_t *inp)
     801             : {
     802           0 :   return inp->extensions;
     803             : }
     804             : const struct trn_cell_extension_st *
     805           0 : trn_cell_introduce_encrypted_getconst_extensions(const trn_cell_introduce_encrypted_t *inp)
     806             : {
     807           0 :   return trn_cell_introduce_encrypted_get_extensions((trn_cell_introduce_encrypted_t*) inp);
     808             : }
     809             : int
     810           4 : trn_cell_introduce_encrypted_set_extensions(trn_cell_introduce_encrypted_t *inp, struct trn_cell_extension_st *val)
     811             : {
     812           4 :   if (inp->extensions && inp->extensions != val)
     813           0 :     trn_cell_extension_free(inp->extensions);
     814           4 :   return trn_cell_introduce_encrypted_set0_extensions(inp, val);
     815             : }
     816             : int
     817           4 : trn_cell_introduce_encrypted_set0_extensions(trn_cell_introduce_encrypted_t *inp, struct trn_cell_extension_st *val)
     818             : {
     819           4 :   inp->extensions = val;
     820           4 :   return 0;
     821             : }
     822             : uint8_t
     823           5 : trn_cell_introduce_encrypted_get_onion_key_type(const trn_cell_introduce_encrypted_t *inp)
     824             : {
     825           5 :   return inp->onion_key_type;
     826             : }
     827             : int
     828           4 : trn_cell_introduce_encrypted_set_onion_key_type(trn_cell_introduce_encrypted_t *inp, uint8_t val)
     829             : {
     830           4 :   if (! ((val == TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR))) {
     831           0 :      TRUNNEL_SET_ERROR_CODE(inp);
     832           0 :      return -1;
     833             :   }
     834           4 :   inp->onion_key_type = val;
     835           4 :   return 0;
     836             : }
     837             : uint16_t
     838           0 : trn_cell_introduce_encrypted_get_onion_key_len(const trn_cell_introduce_encrypted_t *inp)
     839             : {
     840           0 :   return inp->onion_key_len;
     841             : }
     842             : int
     843           4 : trn_cell_introduce_encrypted_set_onion_key_len(trn_cell_introduce_encrypted_t *inp, uint16_t val)
     844             : {
     845           4 :   inp->onion_key_len = val;
     846           4 :   return 0;
     847             : }
     848             : size_t
     849           9 : trn_cell_introduce_encrypted_getlen_onion_key(const trn_cell_introduce_encrypted_t *inp)
     850             : {
     851           9 :   return TRUNNEL_DYNARRAY_LEN(&inp->onion_key);
     852             : }
     853             : 
     854             : uint8_t
     855           0 : trn_cell_introduce_encrypted_get_onion_key(trn_cell_introduce_encrypted_t *inp, size_t idx)
     856             : {
     857           0 :   return TRUNNEL_DYNARRAY_GET(&inp->onion_key, idx);
     858             : }
     859             : 
     860             : uint8_t
     861           0 : trn_cell_introduce_encrypted_getconst_onion_key(const trn_cell_introduce_encrypted_t *inp, size_t idx)
     862             : {
     863           0 :   return trn_cell_introduce_encrypted_get_onion_key((trn_cell_introduce_encrypted_t*)inp, idx);
     864             : }
     865             : int
     866           0 : trn_cell_introduce_encrypted_set_onion_key(trn_cell_introduce_encrypted_t *inp, size_t idx, uint8_t elt)
     867             : {
     868           0 :   TRUNNEL_DYNARRAY_SET(&inp->onion_key, idx, elt);
     869           0 :   return 0;
     870             : }
     871             : int
     872           0 : trn_cell_introduce_encrypted_add_onion_key(trn_cell_introduce_encrypted_t *inp, uint8_t elt)
     873             : {
     874             : #if SIZE_MAX >= UINT16_MAX
     875           0 :   if (inp->onion_key.n_ == UINT16_MAX)
     876           0 :     goto trunnel_alloc_failed;
     877             : #endif
     878           0 :   TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->onion_key, elt, {});
     879           0 :   return 0;
     880           0 :  trunnel_alloc_failed:
     881           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     882           0 :   return -1;
     883             : }
     884             : 
     885             : uint8_t *
     886           9 : trn_cell_introduce_encrypted_getarray_onion_key(trn_cell_introduce_encrypted_t *inp)
     887             : {
     888           9 :   return inp->onion_key.elts_;
     889             : }
     890             : const uint8_t  *
     891           5 : trn_cell_introduce_encrypted_getconstarray_onion_key(const trn_cell_introduce_encrypted_t *inp)
     892             : {
     893           5 :   return (const uint8_t  *)trn_cell_introduce_encrypted_getarray_onion_key((trn_cell_introduce_encrypted_t*)inp);
     894             : }
     895             : int
     896           4 : trn_cell_introduce_encrypted_setlen_onion_key(trn_cell_introduce_encrypted_t *inp, size_t newlen)
     897             : {
     898           4 :   uint8_t *newptr;
     899             : #if UINT16_MAX < SIZE_MAX
     900           4 :   if (newlen > UINT16_MAX)
     901           0 :     goto trunnel_alloc_failed;
     902             : #endif
     903           8 :   newptr = trunnel_dynarray_setlen(&inp->onion_key.allocated_,
     904           4 :                  &inp->onion_key.n_, inp->onion_key.elts_, newlen,
     905             :                  sizeof(inp->onion_key.elts_[0]), (trunnel_free_fn_t) NULL,
     906             :                  &inp->trunnel_error_code_);
     907           4 :   if (newlen != 0 && newptr == NULL)
     908           0 :     goto trunnel_alloc_failed;
     909           4 :   inp->onion_key.elts_ = newptr;
     910           4 :   return 0;
     911           0 :  trunnel_alloc_failed:
     912           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     913           0 :   return -1;
     914             : }
     915             : uint8_t
     916          10 : trn_cell_introduce_encrypted_get_nspec(const trn_cell_introduce_encrypted_t *inp)
     917             : {
     918          10 :   return inp->nspec;
     919             : }
     920             : int
     921           4 : trn_cell_introduce_encrypted_set_nspec(trn_cell_introduce_encrypted_t *inp, uint8_t val)
     922             : {
     923           4 :   inp->nspec = val;
     924           4 :   return 0;
     925             : }
     926             : size_t
     927           0 : trn_cell_introduce_encrypted_getlen_nspecs(const trn_cell_introduce_encrypted_t *inp)
     928             : {
     929           0 :   return TRUNNEL_DYNARRAY_LEN(&inp->nspecs);
     930             : }
     931             : 
     932             : struct link_specifier_st *
     933           5 : trn_cell_introduce_encrypted_get_nspecs(trn_cell_introduce_encrypted_t *inp, size_t idx)
     934             : {
     935           5 :   return TRUNNEL_DYNARRAY_GET(&inp->nspecs, idx);
     936             : }
     937             : 
     938             :  const struct link_specifier_st *
     939           0 : trn_cell_introduce_encrypted_getconst_nspecs(const trn_cell_introduce_encrypted_t *inp, size_t idx)
     940             : {
     941           0 :   return trn_cell_introduce_encrypted_get_nspecs((trn_cell_introduce_encrypted_t*)inp, idx);
     942             : }
     943             : int
     944           0 : trn_cell_introduce_encrypted_set_nspecs(trn_cell_introduce_encrypted_t *inp, size_t idx, struct link_specifier_st * elt)
     945             : {
     946           0 :   link_specifier_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->nspecs, idx);
     947           0 :   if (oldval && oldval != elt)
     948           0 :     link_specifier_free(oldval);
     949           0 :   return trn_cell_introduce_encrypted_set0_nspecs(inp, idx, elt);
     950             : }
     951             : int
     952           0 : trn_cell_introduce_encrypted_set0_nspecs(trn_cell_introduce_encrypted_t *inp, size_t idx, struct link_specifier_st * elt)
     953             : {
     954           0 :   TRUNNEL_DYNARRAY_SET(&inp->nspecs, idx, elt);
     955           0 :   return 0;
     956             : }
     957             : int
     958           4 : trn_cell_introduce_encrypted_add_nspecs(trn_cell_introduce_encrypted_t *inp, struct link_specifier_st * elt)
     959             : {
     960             : #if SIZE_MAX >= UINT8_MAX
     961           4 :   if (inp->nspecs.n_ == UINT8_MAX)
     962           0 :     goto trunnel_alloc_failed;
     963             : #endif
     964           4 :   TRUNNEL_DYNARRAY_ADD(struct link_specifier_st *, &inp->nspecs, elt, {});
     965           4 :   return 0;
     966           0 :  trunnel_alloc_failed:
     967           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     968           0 :   return -1;
     969             : }
     970             : 
     971             : struct link_specifier_st * *
     972           0 : trn_cell_introduce_encrypted_getarray_nspecs(trn_cell_introduce_encrypted_t *inp)
     973             : {
     974           0 :   return inp->nspecs.elts_;
     975             : }
     976             : const struct link_specifier_st *  const  *
     977           0 : trn_cell_introduce_encrypted_getconstarray_nspecs(const trn_cell_introduce_encrypted_t *inp)
     978             : {
     979           0 :   return (const struct link_specifier_st *  const  *)trn_cell_introduce_encrypted_getarray_nspecs((trn_cell_introduce_encrypted_t*)inp);
     980             : }
     981             : int
     982           0 : trn_cell_introduce_encrypted_setlen_nspecs(trn_cell_introduce_encrypted_t *inp, size_t newlen)
     983             : {
     984           0 :   struct link_specifier_st * *newptr;
     985             : #if UINT8_MAX < SIZE_MAX
     986           0 :   if (newlen > UINT8_MAX)
     987           0 :     goto trunnel_alloc_failed;
     988             : #endif
     989           0 :   newptr = trunnel_dynarray_setlen(&inp->nspecs.allocated_,
     990           0 :                  &inp->nspecs.n_, inp->nspecs.elts_, newlen,
     991             :                  sizeof(inp->nspecs.elts_[0]), (trunnel_free_fn_t) link_specifier_free,
     992             :                  &inp->trunnel_error_code_);
     993           0 :   if (newlen != 0 && newptr == NULL)
     994           0 :     goto trunnel_alloc_failed;
     995           0 :   inp->nspecs.elts_ = newptr;
     996           0 :   return 0;
     997           0 :  trunnel_alloc_failed:
     998           0 :   TRUNNEL_SET_ERROR_CODE(inp);
     999           0 :   return -1;
    1000             : }
    1001             : size_t
    1002           4 : trn_cell_introduce_encrypted_getlen_pad(const trn_cell_introduce_encrypted_t *inp)
    1003             : {
    1004           4 :   return TRUNNEL_DYNARRAY_LEN(&inp->pad);
    1005             : }
    1006             : 
    1007             : uint8_t
    1008           0 : trn_cell_introduce_encrypted_get_pad(trn_cell_introduce_encrypted_t *inp, size_t idx)
    1009             : {
    1010           0 :   return TRUNNEL_DYNARRAY_GET(&inp->pad, idx);
    1011             : }
    1012             : 
    1013             : uint8_t
    1014           0 : trn_cell_introduce_encrypted_getconst_pad(const trn_cell_introduce_encrypted_t *inp, size_t idx)
    1015             : {
    1016           0 :   return trn_cell_introduce_encrypted_get_pad((trn_cell_introduce_encrypted_t*)inp, idx);
    1017             : }
    1018             : int
    1019           0 : trn_cell_introduce_encrypted_set_pad(trn_cell_introduce_encrypted_t *inp, size_t idx, uint8_t elt)
    1020             : {
    1021           0 :   TRUNNEL_DYNARRAY_SET(&inp->pad, idx, elt);
    1022           0 :   return 0;
    1023             : }
    1024             : int
    1025           0 : trn_cell_introduce_encrypted_add_pad(trn_cell_introduce_encrypted_t *inp, uint8_t elt)
    1026             : {
    1027           0 :   TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->pad, elt, {});
    1028           0 :   return 0;
    1029           0 :  trunnel_alloc_failed:
    1030           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    1031           0 :   return -1;
    1032             : }
    1033             : 
    1034             : uint8_t *
    1035           4 : trn_cell_introduce_encrypted_getarray_pad(trn_cell_introduce_encrypted_t *inp)
    1036             : {
    1037           4 :   return inp->pad.elts_;
    1038             : }
    1039             : const uint8_t  *
    1040           0 : trn_cell_introduce_encrypted_getconstarray_pad(const trn_cell_introduce_encrypted_t *inp)
    1041             : {
    1042           0 :   return (const uint8_t  *)trn_cell_introduce_encrypted_getarray_pad((trn_cell_introduce_encrypted_t*)inp);
    1043             : }
    1044             : int
    1045           4 : trn_cell_introduce_encrypted_setlen_pad(trn_cell_introduce_encrypted_t *inp, size_t newlen)
    1046             : {
    1047           4 :   uint8_t *newptr;
    1048           8 :   newptr = trunnel_dynarray_setlen(&inp->pad.allocated_,
    1049           4 :                  &inp->pad.n_, inp->pad.elts_, newlen,
    1050             :                  sizeof(inp->pad.elts_[0]), (trunnel_free_fn_t) NULL,
    1051             :                  &inp->trunnel_error_code_);
    1052           4 :   if (newlen != 0 && newptr == NULL)
    1053           0 :     goto trunnel_alloc_failed;
    1054           4 :   inp->pad.elts_ = newptr;
    1055           4 :   return 0;
    1056           0 :  trunnel_alloc_failed:
    1057           0 :   TRUNNEL_SET_ERROR_CODE(inp);
    1058           0 :   return -1;
    1059             : }
    1060             : const char *
    1061           8 : trn_cell_introduce_encrypted_check(const trn_cell_introduce_encrypted_t *obj)
    1062             : {
    1063           8 :   if (obj == NULL)
    1064             :     return "Object was NULL";
    1065           8 :   if (obj->trunnel_error_code_)
    1066             :     return "A set function failed on this object";
    1067             :   {
    1068           8 :     const char *msg;
    1069           8 :     if (NULL != (msg = trn_cell_extension_check(obj->extensions)))
    1070             :       return msg;
    1071             :   }
    1072           8 :   if (! (obj->onion_key_type == TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR))
    1073             :     return "Integer out of bounds";
    1074           8 :   if (TRUNNEL_DYNARRAY_LEN(&obj->onion_key) != obj->onion_key_len)
    1075             :     return "Length mismatch for onion_key";
    1076             :   {
    1077             :     const char *msg;
    1078             : 
    1079             :     unsigned idx;
    1080          16 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->nspecs); ++idx) {
    1081           8 :       if (NULL != (msg = link_specifier_check(TRUNNEL_DYNARRAY_GET(&obj->nspecs, idx))))
    1082           0 :         return msg;
    1083             :     }
    1084             :   }
    1085           8 :   if (TRUNNEL_DYNARRAY_LEN(&obj->nspecs) != obj->nspec)
    1086           0 :     return "Length mismatch for nspecs";
    1087             :   return NULL;
    1088             : }
    1089             : 
    1090             : ssize_t
    1091           4 : trn_cell_introduce_encrypted_encoded_len(const trn_cell_introduce_encrypted_t *obj)
    1092             : {
    1093           4 :   ssize_t result = 0;
    1094             : 
    1095           4 :   if (NULL != trn_cell_introduce_encrypted_check(obj))
    1096             :      return -1;
    1097             : 
    1098             : 
    1099             :   /* Length of u8 rend_cookie[TRUNNEL_REND_COOKIE_LEN] */
    1100           4 :   result += TRUNNEL_REND_COOKIE_LEN;
    1101             : 
    1102             :   /* Length of struct trn_cell_extension extensions */
    1103           4 :   result += trn_cell_extension_encoded_len(obj->extensions);
    1104             : 
    1105             :   /* Length of u8 onion_key_type IN [TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR] */
    1106           4 :   result += 1;
    1107             : 
    1108             :   /* Length of u16 onion_key_len */
    1109           4 :   result += 2;
    1110             : 
    1111             :   /* Length of u8 onion_key[onion_key_len] */
    1112           4 :   result += TRUNNEL_DYNARRAY_LEN(&obj->onion_key);
    1113             : 
    1114             :   /* Length of u8 nspec */
    1115           4 :   result += 1;
    1116             : 
    1117             :   /* Length of struct link_specifier nspecs[nspec] */
    1118             :   {
    1119             : 
    1120           4 :     unsigned idx;
    1121           8 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->nspecs); ++idx) {
    1122           4 :       result += link_specifier_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->nspecs, idx));
    1123             :     }
    1124             :   }
    1125             : 
    1126             :   /* Length of u8 pad[] */
    1127           4 :   result += TRUNNEL_DYNARRAY_LEN(&obj->pad);
    1128           4 :   return result;
    1129             : }
    1130             : int
    1131           0 : trn_cell_introduce_encrypted_clear_errors(trn_cell_introduce_encrypted_t *obj)
    1132             : {
    1133           0 :   int r = obj->trunnel_error_code_;
    1134           0 :   obj->trunnel_error_code_ = 0;
    1135           0 :   return r;
    1136             : }
    1137             : ssize_t
    1138           4 : trn_cell_introduce_encrypted_encode(uint8_t *output, const size_t avail, const trn_cell_introduce_encrypted_t *obj)
    1139             : {
    1140           4 :   ssize_t result = 0;
    1141           4 :   size_t written = 0;
    1142           4 :   uint8_t *ptr = output;
    1143           4 :   const char *msg;
    1144             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    1145             :   const ssize_t encoded_len = trn_cell_introduce_encrypted_encoded_len(obj);
    1146             : #endif
    1147             : 
    1148           4 :   if (NULL != (msg = trn_cell_introduce_encrypted_check(obj)))
    1149           0 :     goto check_failed;
    1150             : 
    1151             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    1152             :   trunnel_assert(encoded_len >= 0);
    1153             : #endif
    1154             : 
    1155             :   /* Encode u8 rend_cookie[TRUNNEL_REND_COOKIE_LEN] */
    1156           4 :   trunnel_assert(written <= avail);
    1157           4 :   if (avail - written < TRUNNEL_REND_COOKIE_LEN)
    1158           0 :     goto truncated;
    1159           4 :   memcpy(ptr, obj->rend_cookie, TRUNNEL_REND_COOKIE_LEN);
    1160           4 :   written += TRUNNEL_REND_COOKIE_LEN; ptr += TRUNNEL_REND_COOKIE_LEN;
    1161             : 
    1162             :   /* Encode struct trn_cell_extension extensions */
    1163           4 :   trunnel_assert(written <= avail);
    1164           4 :   result = trn_cell_extension_encode(ptr, avail - written, obj->extensions);
    1165           4 :   if (result < 0)
    1166           0 :     goto fail; /* XXXXXXX !*/
    1167           4 :   written += result; ptr += result;
    1168             : 
    1169             :   /* Encode u8 onion_key_type IN [TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR] */
    1170           4 :   trunnel_assert(written <= avail);
    1171           4 :   if (avail - written < 1)
    1172           0 :     goto truncated;
    1173           4 :   trunnel_set_uint8(ptr, (obj->onion_key_type));
    1174           4 :   written += 1; ptr += 1;
    1175             : 
    1176             :   /* Encode u16 onion_key_len */
    1177           4 :   trunnel_assert(written <= avail);
    1178           4 :   if (avail - written < 2)
    1179           0 :     goto truncated;
    1180           4 :   trunnel_set_uint16(ptr, trunnel_htons(obj->onion_key_len));
    1181           4 :   written += 2; ptr += 2;
    1182             : 
    1183             :   /* Encode u8 onion_key[onion_key_len] */
    1184             :   {
    1185           4 :     size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->onion_key);
    1186           4 :     trunnel_assert(obj->onion_key_len == elt_len);
    1187           4 :     trunnel_assert(written <= avail);
    1188           4 :     if (avail - written < elt_len)
    1189           0 :       goto truncated;
    1190           4 :     if (elt_len)
    1191           4 :       memcpy(ptr, obj->onion_key.elts_, elt_len);
    1192           4 :     written += elt_len; ptr += elt_len;
    1193             :   }
    1194             : 
    1195             :   /* Encode u8 nspec */
    1196           4 :   trunnel_assert(written <= avail);
    1197           4 :   if (avail - written < 1)
    1198           0 :     goto truncated;
    1199           4 :   trunnel_set_uint8(ptr, (obj->nspec));
    1200           4 :   written += 1; ptr += 1;
    1201             : 
    1202             :   /* Encode struct link_specifier nspecs[nspec] */
    1203             :   {
    1204             : 
    1205           4 :     unsigned idx;
    1206           8 :     for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->nspecs); ++idx) {
    1207           4 :       trunnel_assert(written <= avail);
    1208           4 :       result = link_specifier_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->nspecs, idx));
    1209           4 :       if (result < 0)
    1210           0 :         goto fail; /* XXXXXXX !*/
    1211           4 :       written += result; ptr += result;
    1212             :     }
    1213             :   }
    1214             : 
    1215             :   /* Encode u8 pad[] */
    1216             :   {
    1217           4 :     size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->pad);
    1218           4 :     trunnel_assert(written <= avail);
    1219           4 :     if (avail - written < elt_len)
    1220           0 :       goto truncated;
    1221           4 :     if (elt_len)
    1222           4 :       memcpy(ptr, obj->pad.elts_, elt_len);
    1223           4 :     written += elt_len; ptr += elt_len;
    1224             :   }
    1225             : 
    1226             : 
    1227           4 :   trunnel_assert(ptr == output + written);
    1228             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
    1229             :   {
    1230             :     trunnel_assert(encoded_len >= 0);
    1231             :     trunnel_assert((size_t)encoded_len == written);
    1232             :   }
    1233             : 
    1234             : #endif
    1235             : 
    1236           4 :   return written;
    1237             : 
    1238           0 :  truncated:
    1239           0 :   result = -2;
    1240           0 :   goto fail;
    1241           0 :  check_failed:
    1242           0 :   (void)msg;
    1243           0 :   result = -1;
    1244           0 :   goto fail;
    1245             :  fail:
    1246           0 :   trunnel_assert(result < 0);
    1247             :   return result;
    1248             : }
    1249             : 
    1250             : /** As trn_cell_introduce_encrypted_parse(), but do not allocate the
    1251             :  * output object.
    1252             :  */
    1253             : static ssize_t
    1254           5 : trn_cell_introduce_encrypted_parse_into(trn_cell_introduce_encrypted_t *obj, const uint8_t *input, const size_t len_in)
    1255             : {
    1256           5 :   const uint8_t *ptr = input;
    1257           5 :   size_t remaining = len_in;
    1258           5 :   ssize_t result = 0;
    1259           5 :   (void)result;
    1260             : 
    1261             :   /* Parse u8 rend_cookie[TRUNNEL_REND_COOKIE_LEN] */
    1262           5 :   CHECK_REMAINING(TRUNNEL_REND_COOKIE_LEN, truncated);
    1263           5 :   memcpy(obj->rend_cookie, ptr, TRUNNEL_REND_COOKIE_LEN);
    1264           5 :   remaining -= TRUNNEL_REND_COOKIE_LEN; ptr += TRUNNEL_REND_COOKIE_LEN;
    1265             : 
    1266             :   /* Parse struct trn_cell_extension extensions */
    1267           5 :   result = trn_cell_extension_parse(&obj->extensions, ptr, remaining);
    1268           5 :   if (result < 0)
    1269           0 :     goto relay_fail;
    1270           5 :   trunnel_assert((size_t)result <= remaining);
    1271           5 :   remaining -= result; ptr += result;
    1272             : 
    1273             :   /* Parse u8 onion_key_type IN [TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR] */
    1274           5 :   CHECK_REMAINING(1, truncated);
    1275           5 :   obj->onion_key_type = (trunnel_get_uint8(ptr));
    1276           5 :   remaining -= 1; ptr += 1;
    1277           5 :   if (! (obj->onion_key_type == TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR))
    1278           0 :     goto fail;
    1279             : 
    1280             :   /* Parse u16 onion_key_len */
    1281           5 :   CHECK_REMAINING(2, truncated);
    1282           5 :   obj->onion_key_len = trunnel_ntohs(trunnel_get_uint16(ptr));
    1283           5 :   remaining -= 2; ptr += 2;
    1284             : 
    1285             :   /* Parse u8 onion_key[onion_key_len] */
    1286           5 :   CHECK_REMAINING(obj->onion_key_len, truncated);
    1287           5 :   TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->onion_key, obj->onion_key_len, {});
    1288           5 :   obj->onion_key.n_ = obj->onion_key_len;
    1289           5 :   if (obj->onion_key_len)
    1290           5 :     memcpy(obj->onion_key.elts_, ptr, obj->onion_key_len);
    1291           5 :   ptr += obj->onion_key_len; remaining -= obj->onion_key_len;
    1292             : 
    1293             :   /* Parse u8 nspec */
    1294           5 :   CHECK_REMAINING(1, truncated);
    1295           5 :   obj->nspec = (trunnel_get_uint8(ptr));
    1296           5 :   remaining -= 1; ptr += 1;
    1297             : 
    1298             :   /* Parse struct link_specifier nspecs[nspec] */
    1299           5 :   TRUNNEL_DYNARRAY_EXPAND(link_specifier_t *, &obj->nspecs, obj->nspec, {});
    1300             :   {
    1301           5 :     link_specifier_t * elt;
    1302           5 :     unsigned idx;
    1303          10 :     for (idx = 0; idx < obj->nspec; ++idx) {
    1304           5 :       result = link_specifier_parse(&elt, ptr, remaining);
    1305           5 :       if (result < 0)
    1306           0 :         goto relay_fail;
    1307           5 :       trunnel_assert((size_t)result <= remaining);
    1308           5 :       remaining -= result; ptr += result;
    1309           5 :       TRUNNEL_DYNARRAY_ADD(link_specifier_t *, &obj->nspecs, elt, {link_specifier_free(elt);});
    1310             :     }
    1311             :   }
    1312             : 
    1313             :   /* Parse u8 pad[] */
    1314           5 :   TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->pad, remaining, {});
    1315           5 :   obj->pad.n_ = remaining;
    1316           5 :   if (remaining)
    1317           5 :     memcpy(obj->pad.elts_, ptr, remaining);
    1318           5 :   ptr += remaining; remaining -= remaining;
    1319           5 :   trunnel_assert(ptr + remaining == input + len_in);
    1320           5 :   return len_in - remaining;
    1321             : 
    1322             :  truncated:
    1323             :   return -2;
    1324             :  relay_fail:
    1325             :   trunnel_assert(result < 0);
    1326             :   return result;
    1327             :  trunnel_alloc_failed:
    1328             :   return -1;
    1329           0 :  fail:
    1330           0 :   result = -1;
    1331           0 :   return result;
    1332             : }
    1333             : 
    1334             : ssize_t
    1335           5 : trn_cell_introduce_encrypted_parse(trn_cell_introduce_encrypted_t **output, const uint8_t *input, const size_t len_in)
    1336             : {
    1337           5 :   ssize_t result;
    1338           5 :   *output = trn_cell_introduce_encrypted_new();
    1339           5 :   if (NULL == *output)
    1340             :     return -1;
    1341           5 :   result = trn_cell_introduce_encrypted_parse_into(*output, input, len_in);
    1342           5 :   if (result < 0) {
    1343           0 :     trn_cell_introduce_encrypted_free(*output);
    1344           0 :     *output = NULL;
    1345             :   }
    1346             :   return result;
    1347             : }

Generated by: LCOV version 1.14