cell_establish_intro.c 32 KB

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