ed25519_cert.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720
  1. /* ed25519_cert.c -- generated by Trunnel v1.4.4.
  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 "ed25519_cert.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 runnning a static analysis tool, we don't want it to complain
  14. * that some of our remaining-bytes checks are dead-code. */
  15. int edcert_deadcode_dummy__ = 0;
  16. #define OR_DEADCODE_DUMMY || edcert_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. ed25519_cert_extension_t *
  27. ed25519_cert_extension_new(void)
  28. {
  29. ed25519_cert_extension_t *val = trunnel_calloc(1, sizeof(ed25519_cert_extension_t));
  30. if (NULL == val)
  31. return NULL;
  32. return val;
  33. }
  34. /** Release all storage held inside 'obj', but do not free 'obj'.
  35. */
  36. static void
  37. ed25519_cert_extension_clear(ed25519_cert_extension_t *obj)
  38. {
  39. (void) obj;
  40. TRUNNEL_DYNARRAY_WIPE(&obj->un_unparsed);
  41. TRUNNEL_DYNARRAY_CLEAR(&obj->un_unparsed);
  42. }
  43. void
  44. ed25519_cert_extension_free(ed25519_cert_extension_t *obj)
  45. {
  46. if (obj == NULL)
  47. return;
  48. ed25519_cert_extension_clear(obj);
  49. trunnel_memwipe(obj, sizeof(ed25519_cert_extension_t));
  50. trunnel_free_(obj);
  51. }
  52. uint16_t
  53. ed25519_cert_extension_get_ext_length(ed25519_cert_extension_t *inp)
  54. {
  55. return inp->ext_length;
  56. }
  57. int
  58. ed25519_cert_extension_set_ext_length(ed25519_cert_extension_t *inp, uint16_t val)
  59. {
  60. inp->ext_length = val;
  61. return 0;
  62. }
  63. uint8_t
  64. ed25519_cert_extension_get_ext_type(ed25519_cert_extension_t *inp)
  65. {
  66. return inp->ext_type;
  67. }
  68. int
  69. ed25519_cert_extension_set_ext_type(ed25519_cert_extension_t *inp, uint8_t val)
  70. {
  71. inp->ext_type = val;
  72. return 0;
  73. }
  74. uint8_t
  75. ed25519_cert_extension_get_ext_flags(ed25519_cert_extension_t *inp)
  76. {
  77. return inp->ext_flags;
  78. }
  79. int
  80. ed25519_cert_extension_set_ext_flags(ed25519_cert_extension_t *inp, uint8_t val)
  81. {
  82. inp->ext_flags = val;
  83. return 0;
  84. }
  85. size_t
  86. ed25519_cert_extension_getlen_un_signing_key(const ed25519_cert_extension_t *inp)
  87. {
  88. (void)inp; return 32;
  89. }
  90. uint8_t
  91. ed25519_cert_extension_get_un_signing_key(const ed25519_cert_extension_t *inp, size_t idx)
  92. {
  93. trunnel_assert(idx < 32);
  94. return inp->un_signing_key[idx];
  95. }
  96. int
  97. ed25519_cert_extension_set_un_signing_key(ed25519_cert_extension_t *inp, size_t idx, uint8_t elt)
  98. {
  99. trunnel_assert(idx < 32);
  100. inp->un_signing_key[idx] = elt;
  101. return 0;
  102. }
  103. uint8_t *
  104. ed25519_cert_extension_getarray_un_signing_key(ed25519_cert_extension_t *inp)
  105. {
  106. return inp->un_signing_key;
  107. }
  108. size_t
  109. ed25519_cert_extension_getlen_un_unparsed(const ed25519_cert_extension_t *inp)
  110. {
  111. return TRUNNEL_DYNARRAY_LEN(&inp->un_unparsed);
  112. }
  113. uint8_t
  114. ed25519_cert_extension_get_un_unparsed(ed25519_cert_extension_t *inp, size_t idx)
  115. {
  116. return TRUNNEL_DYNARRAY_GET(&inp->un_unparsed, idx);
  117. }
  118. int
  119. ed25519_cert_extension_set_un_unparsed(ed25519_cert_extension_t *inp, size_t idx, uint8_t elt)
  120. {
  121. TRUNNEL_DYNARRAY_SET(&inp->un_unparsed, idx, elt);
  122. return 0;
  123. }
  124. int
  125. ed25519_cert_extension_add_un_unparsed(ed25519_cert_extension_t *inp, uint8_t elt)
  126. {
  127. TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->un_unparsed, elt, {});
  128. return 0;
  129. trunnel_alloc_failed:
  130. TRUNNEL_SET_ERROR_CODE(inp);
  131. return -1;
  132. }
  133. uint8_t *
  134. ed25519_cert_extension_getarray_un_unparsed(ed25519_cert_extension_t *inp)
  135. {
  136. return inp->un_unparsed.elts_;
  137. }
  138. int
  139. ed25519_cert_extension_setlen_un_unparsed(ed25519_cert_extension_t *inp, size_t newlen)
  140. {
  141. uint8_t *newptr;
  142. newptr = trunnel_dynarray_setlen(&inp->un_unparsed.allocated_,
  143. &inp->un_unparsed.n_, inp->un_unparsed.elts_, newlen,
  144. sizeof(inp->un_unparsed.elts_[0]), (trunnel_free_fn_t) NULL,
  145. &inp->trunnel_error_code_);
  146. if (newptr == NULL)
  147. goto trunnel_alloc_failed;
  148. inp->un_unparsed.elts_ = newptr;
  149. return 0;
  150. trunnel_alloc_failed:
  151. TRUNNEL_SET_ERROR_CODE(inp);
  152. return -1;
  153. }
  154. const char *
  155. ed25519_cert_extension_check(const ed25519_cert_extension_t *obj)
  156. {
  157. if (obj == NULL)
  158. return "Object was NULL";
  159. if (obj->trunnel_error_code_)
  160. return "A set function failed on this object";
  161. switch (obj->ext_type) {
  162. case CERTEXT_SIGNED_WITH_KEY:
  163. break;
  164. default:
  165. break;
  166. }
  167. return NULL;
  168. }
  169. ssize_t
  170. ed25519_cert_extension_encoded_len(const ed25519_cert_extension_t *obj)
  171. {
  172. ssize_t result = 0;
  173. if (NULL != ed25519_cert_extension_check(obj))
  174. return -1;
  175. /* Length of u16 ext_length */
  176. result += 2;
  177. /* Length of u8 ext_type */
  178. result += 1;
  179. /* Length of u8 ext_flags */
  180. result += 1;
  181. switch (obj->ext_type) {
  182. case CERTEXT_SIGNED_WITH_KEY:
  183. /* Length of u8 un_signing_key[32] */
  184. result += 32;
  185. break;
  186. default:
  187. /* Length of u8 un_unparsed[] */
  188. result += TRUNNEL_DYNARRAY_LEN(&obj->un_unparsed);
  189. break;
  190. }
  191. return result;
  192. }
  193. int
  194. ed25519_cert_extension_clear_errors(ed25519_cert_extension_t *obj)
  195. {
  196. int r = obj->trunnel_error_code_;
  197. obj->trunnel_error_code_ = 0;
  198. return r;
  199. }
  200. ssize_t
  201. ed25519_cert_extension_encode(uint8_t *output, const size_t avail, const ed25519_cert_extension_t *obj)
  202. {
  203. ssize_t result = 0;
  204. size_t written = 0;
  205. uint8_t *ptr = output;
  206. const char *msg;
  207. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  208. const ssize_t encoded_len = ed25519_cert_extension_encoded_len(obj);
  209. #endif
  210. uint8_t *backptr_ext_length = NULL;
  211. if (NULL != (msg = ed25519_cert_extension_check(obj)))
  212. goto check_failed;
  213. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  214. trunnel_assert(encoded_len >= 0);
  215. #endif
  216. /* Encode u16 ext_length */
  217. backptr_ext_length = ptr;
  218. trunnel_assert(written <= avail);
  219. if (avail - written < 2)
  220. goto truncated;
  221. trunnel_set_uint16(ptr, trunnel_htons(obj->ext_length));
  222. written += 2; ptr += 2;
  223. /* Encode u8 ext_type */
  224. trunnel_assert(written <= avail);
  225. if (avail - written < 1)
  226. goto truncated;
  227. trunnel_set_uint8(ptr, (obj->ext_type));
  228. written += 1; ptr += 1;
  229. /* Encode u8 ext_flags */
  230. trunnel_assert(written <= avail);
  231. if (avail - written < 1)
  232. goto truncated;
  233. trunnel_set_uint8(ptr, (obj->ext_flags));
  234. written += 1; ptr += 1;
  235. {
  236. size_t written_before_union = written;
  237. /* Encode union un[ext_type] */
  238. trunnel_assert(written <= avail);
  239. switch (obj->ext_type) {
  240. case CERTEXT_SIGNED_WITH_KEY:
  241. /* Encode u8 un_signing_key[32] */
  242. trunnel_assert(written <= avail);
  243. if (avail - written < 32)
  244. goto truncated;
  245. memcpy(ptr, obj->un_signing_key, 32);
  246. written += 32; ptr += 32;
  247. break;
  248. default:
  249. /* Encode u8 un_unparsed[] */
  250. {
  251. size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->un_unparsed);
  252. trunnel_assert(written <= avail);
  253. if (avail - written < elt_len)
  254. goto truncated;
  255. if (elt_len)
  256. memcpy(ptr, obj->un_unparsed.elts_, elt_len);
  257. written += elt_len; ptr += elt_len;
  258. }
  259. break;
  260. }
  261. /* Write the length field back to ext_length */
  262. trunnel_assert(written >= written_before_union);
  263. #if UINT16_MAX < SIZE_MAX
  264. if (written - written_before_union > UINT16_MAX)
  265. goto check_failed;
  266. #endif
  267. trunnel_set_uint16(backptr_ext_length, trunnel_htons(written - written_before_union));
  268. }
  269. trunnel_assert(ptr == output + written);
  270. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  271. {
  272. trunnel_assert(encoded_len >= 0);
  273. trunnel_assert((size_t)encoded_len == written);
  274. }
  275. #endif
  276. return written;
  277. truncated:
  278. result = -2;
  279. goto fail;
  280. check_failed:
  281. (void)msg;
  282. result = -1;
  283. goto fail;
  284. fail:
  285. trunnel_assert(result < 0);
  286. return result;
  287. }
  288. /** As ed25519_cert_extension_parse(), but do not allocate the output
  289. * object.
  290. */
  291. static ssize_t
  292. ed25519_cert_extension_parse_into(ed25519_cert_extension_t *obj, const uint8_t *input, const size_t len_in)
  293. {
  294. const uint8_t *ptr = input;
  295. size_t remaining = len_in;
  296. ssize_t result = 0;
  297. (void)result;
  298. /* Parse u16 ext_length */
  299. CHECK_REMAINING(2, truncated);
  300. obj->ext_length = trunnel_ntohs(trunnel_get_uint16(ptr));
  301. remaining -= 2; ptr += 2;
  302. /* Parse u8 ext_type */
  303. CHECK_REMAINING(1, truncated);
  304. obj->ext_type = (trunnel_get_uint8(ptr));
  305. remaining -= 1; ptr += 1;
  306. /* Parse u8 ext_flags */
  307. CHECK_REMAINING(1, truncated);
  308. obj->ext_flags = (trunnel_get_uint8(ptr));
  309. remaining -= 1; ptr += 1;
  310. {
  311. size_t remaining_after;
  312. CHECK_REMAINING(obj->ext_length, truncated);
  313. remaining_after = remaining - obj->ext_length;
  314. remaining = obj->ext_length;
  315. /* Parse union un[ext_type] */
  316. switch (obj->ext_type) {
  317. case CERTEXT_SIGNED_WITH_KEY:
  318. /* Parse u8 un_signing_key[32] */
  319. CHECK_REMAINING(32, fail);
  320. memcpy(obj->un_signing_key, ptr, 32);
  321. remaining -= 32; ptr += 32;
  322. break;
  323. default:
  324. /* Parse u8 un_unparsed[] */
  325. TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->un_unparsed, remaining, {});
  326. obj->un_unparsed.n_ = remaining;
  327. if (remaining)
  328. memcpy(obj->un_unparsed.elts_, ptr, remaining);
  329. ptr += remaining; remaining -= remaining;
  330. break;
  331. }
  332. if (remaining != 0)
  333. goto fail;
  334. remaining = remaining_after;
  335. }
  336. trunnel_assert(ptr + remaining == input + len_in);
  337. return len_in - remaining;
  338. truncated:
  339. return -2;
  340. trunnel_alloc_failed:
  341. return -1;
  342. fail:
  343. result = -1;
  344. return result;
  345. }
  346. ssize_t
  347. ed25519_cert_extension_parse(ed25519_cert_extension_t **output, const uint8_t *input, const size_t len_in)
  348. {
  349. ssize_t result;
  350. *output = ed25519_cert_extension_new();
  351. if (NULL == *output)
  352. return -1;
  353. result = ed25519_cert_extension_parse_into(*output, input, len_in);
  354. if (result < 0) {
  355. ed25519_cert_extension_free(*output);
  356. *output = NULL;
  357. }
  358. return result;
  359. }
  360. link_specifier_t *
  361. link_specifier_new(void)
  362. {
  363. link_specifier_t *val = trunnel_calloc(1, sizeof(link_specifier_t));
  364. if (NULL == val)
  365. return NULL;
  366. return val;
  367. }
  368. /** Release all storage held inside 'obj', but do not free 'obj'.
  369. */
  370. static void
  371. link_specifier_clear(link_specifier_t *obj)
  372. {
  373. (void) obj;
  374. TRUNNEL_DYNARRAY_WIPE(&obj->un_unrecognized);
  375. TRUNNEL_DYNARRAY_CLEAR(&obj->un_unrecognized);
  376. }
  377. void
  378. link_specifier_free(link_specifier_t *obj)
  379. {
  380. if (obj == NULL)
  381. return;
  382. link_specifier_clear(obj);
  383. trunnel_memwipe(obj, sizeof(link_specifier_t));
  384. trunnel_free_(obj);
  385. }
  386. uint8_t
  387. link_specifier_get_ls_type(link_specifier_t *inp)
  388. {
  389. return inp->ls_type;
  390. }
  391. int
  392. link_specifier_set_ls_type(link_specifier_t *inp, uint8_t val)
  393. {
  394. inp->ls_type = val;
  395. return 0;
  396. }
  397. uint8_t
  398. link_specifier_get_ls_len(link_specifier_t *inp)
  399. {
  400. return inp->ls_len;
  401. }
  402. int
  403. link_specifier_set_ls_len(link_specifier_t *inp, uint8_t val)
  404. {
  405. inp->ls_len = val;
  406. return 0;
  407. }
  408. uint32_t
  409. link_specifier_get_un_ipv4_addr(link_specifier_t *inp)
  410. {
  411. return inp->un_ipv4_addr;
  412. }
  413. int
  414. link_specifier_set_un_ipv4_addr(link_specifier_t *inp, uint32_t val)
  415. {
  416. inp->un_ipv4_addr = val;
  417. return 0;
  418. }
  419. uint16_t
  420. link_specifier_get_un_ipv4_port(link_specifier_t *inp)
  421. {
  422. return inp->un_ipv4_port;
  423. }
  424. int
  425. link_specifier_set_un_ipv4_port(link_specifier_t *inp, uint16_t val)
  426. {
  427. inp->un_ipv4_port = val;
  428. return 0;
  429. }
  430. size_t
  431. link_specifier_getlen_un_ipv6_addr(const link_specifier_t *inp)
  432. {
  433. (void)inp; return 16;
  434. }
  435. uint8_t
  436. link_specifier_get_un_ipv6_addr(const link_specifier_t *inp, size_t idx)
  437. {
  438. trunnel_assert(idx < 16);
  439. return inp->un_ipv6_addr[idx];
  440. }
  441. int
  442. link_specifier_set_un_ipv6_addr(link_specifier_t *inp, size_t idx, uint8_t elt)
  443. {
  444. trunnel_assert(idx < 16);
  445. inp->un_ipv6_addr[idx] = elt;
  446. return 0;
  447. }
  448. uint8_t *
  449. link_specifier_getarray_un_ipv6_addr(link_specifier_t *inp)
  450. {
  451. return inp->un_ipv6_addr;
  452. }
  453. uint16_t
  454. link_specifier_get_un_ipv6_port(link_specifier_t *inp)
  455. {
  456. return inp->un_ipv6_port;
  457. }
  458. int
  459. link_specifier_set_un_ipv6_port(link_specifier_t *inp, uint16_t val)
  460. {
  461. inp->un_ipv6_port = val;
  462. return 0;
  463. }
  464. size_t
  465. link_specifier_getlen_un_legacy_id(const link_specifier_t *inp)
  466. {
  467. (void)inp; return 20;
  468. }
  469. uint8_t
  470. link_specifier_get_un_legacy_id(const link_specifier_t *inp, size_t idx)
  471. {
  472. trunnel_assert(idx < 20);
  473. return inp->un_legacy_id[idx];
  474. }
  475. int
  476. link_specifier_set_un_legacy_id(link_specifier_t *inp, size_t idx, uint8_t elt)
  477. {
  478. trunnel_assert(idx < 20);
  479. inp->un_legacy_id[idx] = elt;
  480. return 0;
  481. }
  482. uint8_t *
  483. link_specifier_getarray_un_legacy_id(link_specifier_t *inp)
  484. {
  485. return inp->un_legacy_id;
  486. }
  487. size_t
  488. link_specifier_getlen_un_ed25519_id(const link_specifier_t *inp)
  489. {
  490. (void)inp; return 32;
  491. }
  492. uint8_t
  493. link_specifier_get_un_ed25519_id(const link_specifier_t *inp, size_t idx)
  494. {
  495. trunnel_assert(idx < 32);
  496. return inp->un_ed25519_id[idx];
  497. }
  498. int
  499. link_specifier_set_un_ed25519_id(link_specifier_t *inp, size_t idx, uint8_t elt)
  500. {
  501. trunnel_assert(idx < 32);
  502. inp->un_ed25519_id[idx] = elt;
  503. return 0;
  504. }
  505. uint8_t *
  506. link_specifier_getarray_un_ed25519_id(link_specifier_t *inp)
  507. {
  508. return inp->un_ed25519_id;
  509. }
  510. size_t
  511. link_specifier_getlen_un_unrecognized(const link_specifier_t *inp)
  512. {
  513. return TRUNNEL_DYNARRAY_LEN(&inp->un_unrecognized);
  514. }
  515. uint8_t
  516. link_specifier_get_un_unrecognized(link_specifier_t *inp, size_t idx)
  517. {
  518. return TRUNNEL_DYNARRAY_GET(&inp->un_unrecognized, idx);
  519. }
  520. int
  521. link_specifier_set_un_unrecognized(link_specifier_t *inp, size_t idx, uint8_t elt)
  522. {
  523. TRUNNEL_DYNARRAY_SET(&inp->un_unrecognized, idx, elt);
  524. return 0;
  525. }
  526. int
  527. link_specifier_add_un_unrecognized(link_specifier_t *inp, uint8_t elt)
  528. {
  529. TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->un_unrecognized, elt, {});
  530. return 0;
  531. trunnel_alloc_failed:
  532. TRUNNEL_SET_ERROR_CODE(inp);
  533. return -1;
  534. }
  535. uint8_t *
  536. link_specifier_getarray_un_unrecognized(link_specifier_t *inp)
  537. {
  538. return inp->un_unrecognized.elts_;
  539. }
  540. int
  541. link_specifier_setlen_un_unrecognized(link_specifier_t *inp, size_t newlen)
  542. {
  543. uint8_t *newptr;
  544. newptr = trunnel_dynarray_setlen(&inp->un_unrecognized.allocated_,
  545. &inp->un_unrecognized.n_, inp->un_unrecognized.elts_, newlen,
  546. sizeof(inp->un_unrecognized.elts_[0]), (trunnel_free_fn_t) NULL,
  547. &inp->trunnel_error_code_);
  548. if (newptr == NULL)
  549. goto trunnel_alloc_failed;
  550. inp->un_unrecognized.elts_ = newptr;
  551. return 0;
  552. trunnel_alloc_failed:
  553. TRUNNEL_SET_ERROR_CODE(inp);
  554. return -1;
  555. }
  556. const char *
  557. link_specifier_check(const link_specifier_t *obj)
  558. {
  559. if (obj == NULL)
  560. return "Object was NULL";
  561. if (obj->trunnel_error_code_)
  562. return "A set function failed on this object";
  563. switch (obj->ls_type) {
  564. case LS_IPV4:
  565. break;
  566. case LS_IPV6:
  567. break;
  568. case LS_LEGACY_ID:
  569. break;
  570. case LS_ED25519_ID:
  571. break;
  572. default:
  573. break;
  574. }
  575. return NULL;
  576. }
  577. ssize_t
  578. link_specifier_encoded_len(const link_specifier_t *obj)
  579. {
  580. ssize_t result = 0;
  581. if (NULL != link_specifier_check(obj))
  582. return -1;
  583. /* Length of u8 ls_type */
  584. result += 1;
  585. /* Length of u8 ls_len */
  586. result += 1;
  587. switch (obj->ls_type) {
  588. case LS_IPV4:
  589. /* Length of u32 un_ipv4_addr */
  590. result += 4;
  591. /* Length of u16 un_ipv4_port */
  592. result += 2;
  593. break;
  594. case LS_IPV6:
  595. /* Length of u8 un_ipv6_addr[16] */
  596. result += 16;
  597. /* Length of u16 un_ipv6_port */
  598. result += 2;
  599. break;
  600. case LS_LEGACY_ID:
  601. /* Length of u8 un_legacy_id[20] */
  602. result += 20;
  603. break;
  604. case LS_ED25519_ID:
  605. /* Length of u8 un_ed25519_id[32] */
  606. result += 32;
  607. break;
  608. default:
  609. /* Length of u8 un_unrecognized[] */
  610. result += TRUNNEL_DYNARRAY_LEN(&obj->un_unrecognized);
  611. break;
  612. }
  613. return result;
  614. }
  615. int
  616. link_specifier_clear_errors(link_specifier_t *obj)
  617. {
  618. int r = obj->trunnel_error_code_;
  619. obj->trunnel_error_code_ = 0;
  620. return r;
  621. }
  622. ssize_t
  623. link_specifier_encode(uint8_t *output, const size_t avail, const link_specifier_t *obj)
  624. {
  625. ssize_t result = 0;
  626. size_t written = 0;
  627. uint8_t *ptr = output;
  628. const char *msg;
  629. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  630. const ssize_t encoded_len = link_specifier_encoded_len(obj);
  631. #endif
  632. uint8_t *backptr_ls_len = NULL;
  633. if (NULL != (msg = link_specifier_check(obj)))
  634. goto check_failed;
  635. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  636. trunnel_assert(encoded_len >= 0);
  637. #endif
  638. /* Encode u8 ls_type */
  639. trunnel_assert(written <= avail);
  640. if (avail - written < 1)
  641. goto truncated;
  642. trunnel_set_uint8(ptr, (obj->ls_type));
  643. written += 1; ptr += 1;
  644. /* Encode u8 ls_len */
  645. backptr_ls_len = ptr;
  646. trunnel_assert(written <= avail);
  647. if (avail - written < 1)
  648. goto truncated;
  649. trunnel_set_uint8(ptr, (obj->ls_len));
  650. written += 1; ptr += 1;
  651. {
  652. size_t written_before_union = written;
  653. /* Encode union un[ls_type] */
  654. trunnel_assert(written <= avail);
  655. switch (obj->ls_type) {
  656. case LS_IPV4:
  657. /* Encode u32 un_ipv4_addr */
  658. trunnel_assert(written <= avail);
  659. if (avail - written < 4)
  660. goto truncated;
  661. trunnel_set_uint32(ptr, trunnel_htonl(obj->un_ipv4_addr));
  662. written += 4; ptr += 4;
  663. /* Encode u16 un_ipv4_port */
  664. trunnel_assert(written <= avail);
  665. if (avail - written < 2)
  666. goto truncated;
  667. trunnel_set_uint16(ptr, trunnel_htons(obj->un_ipv4_port));
  668. written += 2; ptr += 2;
  669. break;
  670. case LS_IPV6:
  671. /* Encode u8 un_ipv6_addr[16] */
  672. trunnel_assert(written <= avail);
  673. if (avail - written < 16)
  674. goto truncated;
  675. memcpy(ptr, obj->un_ipv6_addr, 16);
  676. written += 16; ptr += 16;
  677. /* Encode u16 un_ipv6_port */
  678. trunnel_assert(written <= avail);
  679. if (avail - written < 2)
  680. goto truncated;
  681. trunnel_set_uint16(ptr, trunnel_htons(obj->un_ipv6_port));
  682. written += 2; ptr += 2;
  683. break;
  684. case LS_LEGACY_ID:
  685. /* Encode u8 un_legacy_id[20] */
  686. trunnel_assert(written <= avail);
  687. if (avail - written < 20)
  688. goto truncated;
  689. memcpy(ptr, obj->un_legacy_id, 20);
  690. written += 20; ptr += 20;
  691. break;
  692. case LS_ED25519_ID:
  693. /* Encode u8 un_ed25519_id[32] */
  694. trunnel_assert(written <= avail);
  695. if (avail - written < 32)
  696. goto truncated;
  697. memcpy(ptr, obj->un_ed25519_id, 32);
  698. written += 32; ptr += 32;
  699. break;
  700. default:
  701. /* Encode u8 un_unrecognized[] */
  702. {
  703. size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->un_unrecognized);
  704. trunnel_assert(written <= avail);
  705. if (avail - written < elt_len)
  706. goto truncated;
  707. if (elt_len)
  708. memcpy(ptr, obj->un_unrecognized.elts_, elt_len);
  709. written += elt_len; ptr += elt_len;
  710. }
  711. break;
  712. }
  713. /* Write the length field back to ls_len */
  714. trunnel_assert(written >= written_before_union);
  715. #if UINT8_MAX < SIZE_MAX
  716. if (written - written_before_union > UINT8_MAX)
  717. goto check_failed;
  718. #endif
  719. trunnel_set_uint8(backptr_ls_len, (written - written_before_union));
  720. }
  721. trunnel_assert(ptr == output + written);
  722. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  723. {
  724. trunnel_assert(encoded_len >= 0);
  725. trunnel_assert((size_t)encoded_len == written);
  726. }
  727. #endif
  728. return written;
  729. truncated:
  730. result = -2;
  731. goto fail;
  732. check_failed:
  733. (void)msg;
  734. result = -1;
  735. goto fail;
  736. fail:
  737. trunnel_assert(result < 0);
  738. return result;
  739. }
  740. /** As link_specifier_parse(), but do not allocate the output object.
  741. */
  742. static ssize_t
  743. link_specifier_parse_into(link_specifier_t *obj, const uint8_t *input, const size_t len_in)
  744. {
  745. const uint8_t *ptr = input;
  746. size_t remaining = len_in;
  747. ssize_t result = 0;
  748. (void)result;
  749. /* Parse u8 ls_type */
  750. CHECK_REMAINING(1, truncated);
  751. obj->ls_type = (trunnel_get_uint8(ptr));
  752. remaining -= 1; ptr += 1;
  753. /* Parse u8 ls_len */
  754. CHECK_REMAINING(1, truncated);
  755. obj->ls_len = (trunnel_get_uint8(ptr));
  756. remaining -= 1; ptr += 1;
  757. {
  758. size_t remaining_after;
  759. CHECK_REMAINING(obj->ls_len, truncated);
  760. remaining_after = remaining - obj->ls_len;
  761. remaining = obj->ls_len;
  762. /* Parse union un[ls_type] */
  763. switch (obj->ls_type) {
  764. case LS_IPV4:
  765. /* Parse u32 un_ipv4_addr */
  766. CHECK_REMAINING(4, fail);
  767. obj->un_ipv4_addr = trunnel_ntohl(trunnel_get_uint32(ptr));
  768. remaining -= 4; ptr += 4;
  769. /* Parse u16 un_ipv4_port */
  770. CHECK_REMAINING(2, fail);
  771. obj->un_ipv4_port = trunnel_ntohs(trunnel_get_uint16(ptr));
  772. remaining -= 2; ptr += 2;
  773. break;
  774. case LS_IPV6:
  775. /* Parse u8 un_ipv6_addr[16] */
  776. CHECK_REMAINING(16, fail);
  777. memcpy(obj->un_ipv6_addr, ptr, 16);
  778. remaining -= 16; ptr += 16;
  779. /* Parse u16 un_ipv6_port */
  780. CHECK_REMAINING(2, fail);
  781. obj->un_ipv6_port = trunnel_ntohs(trunnel_get_uint16(ptr));
  782. remaining -= 2; ptr += 2;
  783. break;
  784. case LS_LEGACY_ID:
  785. /* Parse u8 un_legacy_id[20] */
  786. CHECK_REMAINING(20, fail);
  787. memcpy(obj->un_legacy_id, ptr, 20);
  788. remaining -= 20; ptr += 20;
  789. break;
  790. case LS_ED25519_ID:
  791. /* Parse u8 un_ed25519_id[32] */
  792. CHECK_REMAINING(32, fail);
  793. memcpy(obj->un_ed25519_id, ptr, 32);
  794. remaining -= 32; ptr += 32;
  795. break;
  796. default:
  797. /* Parse u8 un_unrecognized[] */
  798. TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->un_unrecognized, remaining, {});
  799. obj->un_unrecognized.n_ = remaining;
  800. if (remaining)
  801. memcpy(obj->un_unrecognized.elts_, ptr, remaining);
  802. ptr += remaining; remaining -= remaining;
  803. break;
  804. }
  805. if (remaining != 0)
  806. goto fail;
  807. remaining = remaining_after;
  808. }
  809. trunnel_assert(ptr + remaining == input + len_in);
  810. return len_in - remaining;
  811. truncated:
  812. return -2;
  813. trunnel_alloc_failed:
  814. return -1;
  815. fail:
  816. result = -1;
  817. return result;
  818. }
  819. ssize_t
  820. link_specifier_parse(link_specifier_t **output, const uint8_t *input, const size_t len_in)
  821. {
  822. ssize_t result;
  823. *output = link_specifier_new();
  824. if (NULL == *output)
  825. return -1;
  826. result = link_specifier_parse_into(*output, input, len_in);
  827. if (result < 0) {
  828. link_specifier_free(*output);
  829. *output = NULL;
  830. }
  831. return result;
  832. }
  833. ed25519_cert_t *
  834. ed25519_cert_new(void)
  835. {
  836. ed25519_cert_t *val = trunnel_calloc(1, sizeof(ed25519_cert_t));
  837. if (NULL == val)
  838. return NULL;
  839. val->version = 1;
  840. return val;
  841. }
  842. /** Release all storage held inside 'obj', but do not free 'obj'.
  843. */
  844. static void
  845. ed25519_cert_clear(ed25519_cert_t *obj)
  846. {
  847. (void) obj;
  848. {
  849. unsigned idx;
  850. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
  851. ed25519_cert_extension_free(TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
  852. }
  853. }
  854. TRUNNEL_DYNARRAY_WIPE(&obj->ext);
  855. TRUNNEL_DYNARRAY_CLEAR(&obj->ext);
  856. }
  857. void
  858. ed25519_cert_free(ed25519_cert_t *obj)
  859. {
  860. if (obj == NULL)
  861. return;
  862. ed25519_cert_clear(obj);
  863. trunnel_memwipe(obj, sizeof(ed25519_cert_t));
  864. trunnel_free_(obj);
  865. }
  866. uint8_t
  867. ed25519_cert_get_version(ed25519_cert_t *inp)
  868. {
  869. return inp->version;
  870. }
  871. int
  872. ed25519_cert_set_version(ed25519_cert_t *inp, uint8_t val)
  873. {
  874. if (! ((val == 1))) {
  875. TRUNNEL_SET_ERROR_CODE(inp);
  876. return -1;
  877. }
  878. inp->version = val;
  879. return 0;
  880. }
  881. uint8_t
  882. ed25519_cert_get_cert_type(ed25519_cert_t *inp)
  883. {
  884. return inp->cert_type;
  885. }
  886. int
  887. ed25519_cert_set_cert_type(ed25519_cert_t *inp, uint8_t val)
  888. {
  889. inp->cert_type = val;
  890. return 0;
  891. }
  892. uint32_t
  893. ed25519_cert_get_exp_field(ed25519_cert_t *inp)
  894. {
  895. return inp->exp_field;
  896. }
  897. int
  898. ed25519_cert_set_exp_field(ed25519_cert_t *inp, uint32_t val)
  899. {
  900. inp->exp_field = val;
  901. return 0;
  902. }
  903. uint8_t
  904. ed25519_cert_get_cert_key_type(ed25519_cert_t *inp)
  905. {
  906. return inp->cert_key_type;
  907. }
  908. int
  909. ed25519_cert_set_cert_key_type(ed25519_cert_t *inp, uint8_t val)
  910. {
  911. inp->cert_key_type = val;
  912. return 0;
  913. }
  914. size_t
  915. ed25519_cert_getlen_certified_key(const ed25519_cert_t *inp)
  916. {
  917. (void)inp; return 32;
  918. }
  919. uint8_t
  920. ed25519_cert_get_certified_key(const ed25519_cert_t *inp, size_t idx)
  921. {
  922. trunnel_assert(idx < 32);
  923. return inp->certified_key[idx];
  924. }
  925. int
  926. ed25519_cert_set_certified_key(ed25519_cert_t *inp, size_t idx, uint8_t elt)
  927. {
  928. trunnel_assert(idx < 32);
  929. inp->certified_key[idx] = elt;
  930. return 0;
  931. }
  932. uint8_t *
  933. ed25519_cert_getarray_certified_key(ed25519_cert_t *inp)
  934. {
  935. return inp->certified_key;
  936. }
  937. uint8_t
  938. ed25519_cert_get_n_extensions(ed25519_cert_t *inp)
  939. {
  940. return inp->n_extensions;
  941. }
  942. int
  943. ed25519_cert_set_n_extensions(ed25519_cert_t *inp, uint8_t val)
  944. {
  945. inp->n_extensions = val;
  946. return 0;
  947. }
  948. size_t
  949. ed25519_cert_getlen_ext(const ed25519_cert_t *inp)
  950. {
  951. return TRUNNEL_DYNARRAY_LEN(&inp->ext);
  952. }
  953. struct ed25519_cert_extension_st *
  954. ed25519_cert_get_ext(ed25519_cert_t *inp, size_t idx)
  955. {
  956. return TRUNNEL_DYNARRAY_GET(&inp->ext, idx);
  957. }
  958. int
  959. ed25519_cert_set_ext(ed25519_cert_t *inp, size_t idx, struct ed25519_cert_extension_st * elt)
  960. {
  961. ed25519_cert_extension_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->ext, idx);
  962. if (oldval && oldval != elt)
  963. ed25519_cert_extension_free(oldval);
  964. return ed25519_cert_set0_ext(inp, idx, elt);
  965. }
  966. int
  967. ed25519_cert_set0_ext(ed25519_cert_t *inp, size_t idx, struct ed25519_cert_extension_st * elt)
  968. {
  969. TRUNNEL_DYNARRAY_SET(&inp->ext, idx, elt);
  970. return 0;
  971. }
  972. int
  973. ed25519_cert_add_ext(ed25519_cert_t *inp, struct ed25519_cert_extension_st * elt)
  974. {
  975. #if SIZE_MAX >= UINT8_MAX
  976. if (inp->ext.n_ == UINT8_MAX)
  977. goto trunnel_alloc_failed;
  978. #endif
  979. TRUNNEL_DYNARRAY_ADD(struct ed25519_cert_extension_st *, &inp->ext, elt, {});
  980. return 0;
  981. trunnel_alloc_failed:
  982. TRUNNEL_SET_ERROR_CODE(inp);
  983. return -1;
  984. }
  985. struct ed25519_cert_extension_st * *
  986. ed25519_cert_getarray_ext(ed25519_cert_t *inp)
  987. {
  988. return inp->ext.elts_;
  989. }
  990. int
  991. ed25519_cert_setlen_ext(ed25519_cert_t *inp, size_t newlen)
  992. {
  993. struct ed25519_cert_extension_st * *newptr;
  994. #if UINT8_MAX < SIZE_MAX
  995. if (newlen > UINT8_MAX)
  996. goto trunnel_alloc_failed;
  997. #endif
  998. newptr = trunnel_dynarray_setlen(&inp->ext.allocated_,
  999. &inp->ext.n_, inp->ext.elts_, newlen,
  1000. sizeof(inp->ext.elts_[0]), (trunnel_free_fn_t) ed25519_cert_extension_free,
  1001. &inp->trunnel_error_code_);
  1002. if (newptr == NULL)
  1003. goto trunnel_alloc_failed;
  1004. inp->ext.elts_ = newptr;
  1005. return 0;
  1006. trunnel_alloc_failed:
  1007. TRUNNEL_SET_ERROR_CODE(inp);
  1008. return -1;
  1009. }
  1010. size_t
  1011. ed25519_cert_getlen_signature(const ed25519_cert_t *inp)
  1012. {
  1013. (void)inp; return 64;
  1014. }
  1015. uint8_t
  1016. ed25519_cert_get_signature(const ed25519_cert_t *inp, size_t idx)
  1017. {
  1018. trunnel_assert(idx < 64);
  1019. return inp->signature[idx];
  1020. }
  1021. int
  1022. ed25519_cert_set_signature(ed25519_cert_t *inp, size_t idx, uint8_t elt)
  1023. {
  1024. trunnel_assert(idx < 64);
  1025. inp->signature[idx] = elt;
  1026. return 0;
  1027. }
  1028. uint8_t *
  1029. ed25519_cert_getarray_signature(ed25519_cert_t *inp)
  1030. {
  1031. return inp->signature;
  1032. }
  1033. const char *
  1034. ed25519_cert_check(const ed25519_cert_t *obj)
  1035. {
  1036. if (obj == NULL)
  1037. return "Object was NULL";
  1038. if (obj->trunnel_error_code_)
  1039. return "A set function failed on this object";
  1040. if (! (obj->version == 1))
  1041. return "Integer out of bounds";
  1042. {
  1043. const char *msg;
  1044. unsigned idx;
  1045. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
  1046. if (NULL != (msg = ed25519_cert_extension_check(TRUNNEL_DYNARRAY_GET(&obj->ext, idx))))
  1047. return msg;
  1048. }
  1049. }
  1050. if (TRUNNEL_DYNARRAY_LEN(&obj->ext) != obj->n_extensions)
  1051. return "Length mismatch for ext";
  1052. return NULL;
  1053. }
  1054. ssize_t
  1055. ed25519_cert_encoded_len(const ed25519_cert_t *obj)
  1056. {
  1057. ssize_t result = 0;
  1058. if (NULL != ed25519_cert_check(obj))
  1059. return -1;
  1060. /* Length of u8 version IN [1] */
  1061. result += 1;
  1062. /* Length of u8 cert_type */
  1063. result += 1;
  1064. /* Length of u32 exp_field */
  1065. result += 4;
  1066. /* Length of u8 cert_key_type */
  1067. result += 1;
  1068. /* Length of u8 certified_key[32] */
  1069. result += 32;
  1070. /* Length of u8 n_extensions */
  1071. result += 1;
  1072. /* Length of struct ed25519_cert_extension ext[n_extensions] */
  1073. {
  1074. unsigned idx;
  1075. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
  1076. result += ed25519_cert_extension_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
  1077. }
  1078. }
  1079. /* Length of u8 signature[64] */
  1080. result += 64;
  1081. return result;
  1082. }
  1083. int
  1084. ed25519_cert_clear_errors(ed25519_cert_t *obj)
  1085. {
  1086. int r = obj->trunnel_error_code_;
  1087. obj->trunnel_error_code_ = 0;
  1088. return r;
  1089. }
  1090. ssize_t
  1091. ed25519_cert_encode(uint8_t *output, const size_t avail, const ed25519_cert_t *obj)
  1092. {
  1093. ssize_t result = 0;
  1094. size_t written = 0;
  1095. uint8_t *ptr = output;
  1096. const char *msg;
  1097. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  1098. const ssize_t encoded_len = ed25519_cert_encoded_len(obj);
  1099. #endif
  1100. if (NULL != (msg = ed25519_cert_check(obj)))
  1101. goto check_failed;
  1102. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  1103. trunnel_assert(encoded_len >= 0);
  1104. #endif
  1105. /* Encode u8 version IN [1] */
  1106. trunnel_assert(written <= avail);
  1107. if (avail - written < 1)
  1108. goto truncated;
  1109. trunnel_set_uint8(ptr, (obj->version));
  1110. written += 1; ptr += 1;
  1111. /* Encode u8 cert_type */
  1112. trunnel_assert(written <= avail);
  1113. if (avail - written < 1)
  1114. goto truncated;
  1115. trunnel_set_uint8(ptr, (obj->cert_type));
  1116. written += 1; ptr += 1;
  1117. /* Encode u32 exp_field */
  1118. trunnel_assert(written <= avail);
  1119. if (avail - written < 4)
  1120. goto truncated;
  1121. trunnel_set_uint32(ptr, trunnel_htonl(obj->exp_field));
  1122. written += 4; ptr += 4;
  1123. /* Encode u8 cert_key_type */
  1124. trunnel_assert(written <= avail);
  1125. if (avail - written < 1)
  1126. goto truncated;
  1127. trunnel_set_uint8(ptr, (obj->cert_key_type));
  1128. written += 1; ptr += 1;
  1129. /* Encode u8 certified_key[32] */
  1130. trunnel_assert(written <= avail);
  1131. if (avail - written < 32)
  1132. goto truncated;
  1133. memcpy(ptr, obj->certified_key, 32);
  1134. written += 32; ptr += 32;
  1135. /* Encode u8 n_extensions */
  1136. trunnel_assert(written <= avail);
  1137. if (avail - written < 1)
  1138. goto truncated;
  1139. trunnel_set_uint8(ptr, (obj->n_extensions));
  1140. written += 1; ptr += 1;
  1141. /* Encode struct ed25519_cert_extension ext[n_extensions] */
  1142. {
  1143. unsigned idx;
  1144. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
  1145. trunnel_assert(written <= avail);
  1146. result = ed25519_cert_extension_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
  1147. if (result < 0)
  1148. goto fail; /* XXXXXXX !*/
  1149. written += result; ptr += result;
  1150. }
  1151. }
  1152. /* Encode u8 signature[64] */
  1153. trunnel_assert(written <= avail);
  1154. if (avail - written < 64)
  1155. goto truncated;
  1156. memcpy(ptr, obj->signature, 64);
  1157. written += 64; ptr += 64;
  1158. trunnel_assert(ptr == output + written);
  1159. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  1160. {
  1161. trunnel_assert(encoded_len >= 0);
  1162. trunnel_assert((size_t)encoded_len == written);
  1163. }
  1164. #endif
  1165. return written;
  1166. truncated:
  1167. result = -2;
  1168. goto fail;
  1169. check_failed:
  1170. (void)msg;
  1171. result = -1;
  1172. goto fail;
  1173. fail:
  1174. trunnel_assert(result < 0);
  1175. return result;
  1176. }
  1177. /** As ed25519_cert_parse(), but do not allocate the output object.
  1178. */
  1179. static ssize_t
  1180. ed25519_cert_parse_into(ed25519_cert_t *obj, const uint8_t *input, const size_t len_in)
  1181. {
  1182. const uint8_t *ptr = input;
  1183. size_t remaining = len_in;
  1184. ssize_t result = 0;
  1185. (void)result;
  1186. /* Parse u8 version IN [1] */
  1187. CHECK_REMAINING(1, truncated);
  1188. obj->version = (trunnel_get_uint8(ptr));
  1189. remaining -= 1; ptr += 1;
  1190. if (! (obj->version == 1))
  1191. goto fail;
  1192. /* Parse u8 cert_type */
  1193. CHECK_REMAINING(1, truncated);
  1194. obj->cert_type = (trunnel_get_uint8(ptr));
  1195. remaining -= 1; ptr += 1;
  1196. /* Parse u32 exp_field */
  1197. CHECK_REMAINING(4, truncated);
  1198. obj->exp_field = trunnel_ntohl(trunnel_get_uint32(ptr));
  1199. remaining -= 4; ptr += 4;
  1200. /* Parse u8 cert_key_type */
  1201. CHECK_REMAINING(1, truncated);
  1202. obj->cert_key_type = (trunnel_get_uint8(ptr));
  1203. remaining -= 1; ptr += 1;
  1204. /* Parse u8 certified_key[32] */
  1205. CHECK_REMAINING(32, truncated);
  1206. memcpy(obj->certified_key, ptr, 32);
  1207. remaining -= 32; ptr += 32;
  1208. /* Parse u8 n_extensions */
  1209. CHECK_REMAINING(1, truncated);
  1210. obj->n_extensions = (trunnel_get_uint8(ptr));
  1211. remaining -= 1; ptr += 1;
  1212. /* Parse struct ed25519_cert_extension ext[n_extensions] */
  1213. TRUNNEL_DYNARRAY_EXPAND(ed25519_cert_extension_t *, &obj->ext, obj->n_extensions, {});
  1214. {
  1215. ed25519_cert_extension_t * elt;
  1216. unsigned idx;
  1217. for (idx = 0; idx < obj->n_extensions; ++idx) {
  1218. result = ed25519_cert_extension_parse(&elt, ptr, remaining);
  1219. if (result < 0)
  1220. goto relay_fail;
  1221. trunnel_assert((size_t)result <= remaining);
  1222. remaining -= result; ptr += result;
  1223. TRUNNEL_DYNARRAY_ADD(ed25519_cert_extension_t *, &obj->ext, elt, {ed25519_cert_extension_free(elt);});
  1224. }
  1225. }
  1226. /* Parse u8 signature[64] */
  1227. CHECK_REMAINING(64, truncated);
  1228. memcpy(obj->signature, ptr, 64);
  1229. remaining -= 64; ptr += 64;
  1230. trunnel_assert(ptr + remaining == input + len_in);
  1231. return len_in - remaining;
  1232. truncated:
  1233. return -2;
  1234. relay_fail:
  1235. trunnel_assert(result < 0);
  1236. return result;
  1237. trunnel_alloc_failed:
  1238. return -1;
  1239. fail:
  1240. result = -1;
  1241. return result;
  1242. }
  1243. ssize_t
  1244. ed25519_cert_parse(ed25519_cert_t **output, const uint8_t *input, const size_t len_in)
  1245. {
  1246. ssize_t result;
  1247. *output = ed25519_cert_new();
  1248. if (NULL == *output)
  1249. return -1;
  1250. result = ed25519_cert_parse_into(*output, input, len_in);
  1251. if (result < 0) {
  1252. ed25519_cert_free(*output);
  1253. *output = NULL;
  1254. }
  1255. return result;
  1256. }
  1257. link_specifier_list_t *
  1258. link_specifier_list_new(void)
  1259. {
  1260. link_specifier_list_t *val = trunnel_calloc(1, sizeof(link_specifier_list_t));
  1261. if (NULL == val)
  1262. return NULL;
  1263. return val;
  1264. }
  1265. /** Release all storage held inside 'obj', but do not free 'obj'.
  1266. */
  1267. static void
  1268. link_specifier_list_clear(link_specifier_list_t *obj)
  1269. {
  1270. (void) obj;
  1271. {
  1272. unsigned idx;
  1273. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
  1274. link_specifier_free(TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
  1275. }
  1276. }
  1277. TRUNNEL_DYNARRAY_WIPE(&obj->spec);
  1278. TRUNNEL_DYNARRAY_CLEAR(&obj->spec);
  1279. }
  1280. void
  1281. link_specifier_list_free(link_specifier_list_t *obj)
  1282. {
  1283. if (obj == NULL)
  1284. return;
  1285. link_specifier_list_clear(obj);
  1286. trunnel_memwipe(obj, sizeof(link_specifier_list_t));
  1287. trunnel_free_(obj);
  1288. }
  1289. uint8_t
  1290. link_specifier_list_get_n_spec(link_specifier_list_t *inp)
  1291. {
  1292. return inp->n_spec;
  1293. }
  1294. int
  1295. link_specifier_list_set_n_spec(link_specifier_list_t *inp, uint8_t val)
  1296. {
  1297. inp->n_spec = val;
  1298. return 0;
  1299. }
  1300. size_t
  1301. link_specifier_list_getlen_spec(const link_specifier_list_t *inp)
  1302. {
  1303. return TRUNNEL_DYNARRAY_LEN(&inp->spec);
  1304. }
  1305. struct link_specifier_st *
  1306. link_specifier_list_get_spec(link_specifier_list_t *inp, size_t idx)
  1307. {
  1308. return TRUNNEL_DYNARRAY_GET(&inp->spec, idx);
  1309. }
  1310. int
  1311. link_specifier_list_set_spec(link_specifier_list_t *inp, size_t idx, struct link_specifier_st * elt)
  1312. {
  1313. link_specifier_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->spec, idx);
  1314. if (oldval && oldval != elt)
  1315. link_specifier_free(oldval);
  1316. return link_specifier_list_set0_spec(inp, idx, elt);
  1317. }
  1318. int
  1319. link_specifier_list_set0_spec(link_specifier_list_t *inp, size_t idx, struct link_specifier_st * elt)
  1320. {
  1321. TRUNNEL_DYNARRAY_SET(&inp->spec, idx, elt);
  1322. return 0;
  1323. }
  1324. int
  1325. link_specifier_list_add_spec(link_specifier_list_t *inp, struct link_specifier_st * elt)
  1326. {
  1327. #if SIZE_MAX >= UINT8_MAX
  1328. if (inp->spec.n_ == UINT8_MAX)
  1329. goto trunnel_alloc_failed;
  1330. #endif
  1331. TRUNNEL_DYNARRAY_ADD(struct link_specifier_st *, &inp->spec, elt, {});
  1332. return 0;
  1333. trunnel_alloc_failed:
  1334. TRUNNEL_SET_ERROR_CODE(inp);
  1335. return -1;
  1336. }
  1337. struct link_specifier_st * *
  1338. link_specifier_list_getarray_spec(link_specifier_list_t *inp)
  1339. {
  1340. return inp->spec.elts_;
  1341. }
  1342. int
  1343. link_specifier_list_setlen_spec(link_specifier_list_t *inp, size_t newlen)
  1344. {
  1345. struct link_specifier_st * *newptr;
  1346. #if UINT8_MAX < SIZE_MAX
  1347. if (newlen > UINT8_MAX)
  1348. goto trunnel_alloc_failed;
  1349. #endif
  1350. newptr = trunnel_dynarray_setlen(&inp->spec.allocated_,
  1351. &inp->spec.n_, inp->spec.elts_, newlen,
  1352. sizeof(inp->spec.elts_[0]), (trunnel_free_fn_t) link_specifier_free,
  1353. &inp->trunnel_error_code_);
  1354. if (newptr == NULL)
  1355. goto trunnel_alloc_failed;
  1356. inp->spec.elts_ = newptr;
  1357. return 0;
  1358. trunnel_alloc_failed:
  1359. TRUNNEL_SET_ERROR_CODE(inp);
  1360. return -1;
  1361. }
  1362. const char *
  1363. link_specifier_list_check(const link_specifier_list_t *obj)
  1364. {
  1365. if (obj == NULL)
  1366. return "Object was NULL";
  1367. if (obj->trunnel_error_code_)
  1368. return "A set function failed on this object";
  1369. {
  1370. const char *msg;
  1371. unsigned idx;
  1372. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
  1373. if (NULL != (msg = link_specifier_check(TRUNNEL_DYNARRAY_GET(&obj->spec, idx))))
  1374. return msg;
  1375. }
  1376. }
  1377. if (TRUNNEL_DYNARRAY_LEN(&obj->spec) != obj->n_spec)
  1378. return "Length mismatch for spec";
  1379. return NULL;
  1380. }
  1381. ssize_t
  1382. link_specifier_list_encoded_len(const link_specifier_list_t *obj)
  1383. {
  1384. ssize_t result = 0;
  1385. if (NULL != link_specifier_list_check(obj))
  1386. return -1;
  1387. /* Length of u8 n_spec */
  1388. result += 1;
  1389. /* Length of struct link_specifier spec[n_spec] */
  1390. {
  1391. unsigned idx;
  1392. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
  1393. result += link_specifier_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
  1394. }
  1395. }
  1396. return result;
  1397. }
  1398. int
  1399. link_specifier_list_clear_errors(link_specifier_list_t *obj)
  1400. {
  1401. int r = obj->trunnel_error_code_;
  1402. obj->trunnel_error_code_ = 0;
  1403. return r;
  1404. }
  1405. ssize_t
  1406. link_specifier_list_encode(uint8_t *output, const size_t avail, const link_specifier_list_t *obj)
  1407. {
  1408. ssize_t result = 0;
  1409. size_t written = 0;
  1410. uint8_t *ptr = output;
  1411. const char *msg;
  1412. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  1413. const ssize_t encoded_len = link_specifier_list_encoded_len(obj);
  1414. #endif
  1415. if (NULL != (msg = link_specifier_list_check(obj)))
  1416. goto check_failed;
  1417. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  1418. trunnel_assert(encoded_len >= 0);
  1419. #endif
  1420. /* Encode u8 n_spec */
  1421. trunnel_assert(written <= avail);
  1422. if (avail - written < 1)
  1423. goto truncated;
  1424. trunnel_set_uint8(ptr, (obj->n_spec));
  1425. written += 1; ptr += 1;
  1426. /* Encode struct link_specifier spec[n_spec] */
  1427. {
  1428. unsigned idx;
  1429. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
  1430. trunnel_assert(written <= avail);
  1431. result = link_specifier_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
  1432. if (result < 0)
  1433. goto fail; /* XXXXXXX !*/
  1434. written += result; ptr += result;
  1435. }
  1436. }
  1437. trunnel_assert(ptr == output + written);
  1438. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  1439. {
  1440. trunnel_assert(encoded_len >= 0);
  1441. trunnel_assert((size_t)encoded_len == written);
  1442. }
  1443. #endif
  1444. return written;
  1445. truncated:
  1446. result = -2;
  1447. goto fail;
  1448. check_failed:
  1449. (void)msg;
  1450. result = -1;
  1451. goto fail;
  1452. fail:
  1453. trunnel_assert(result < 0);
  1454. return result;
  1455. }
  1456. /** As link_specifier_list_parse(), but do not allocate the output
  1457. * object.
  1458. */
  1459. static ssize_t
  1460. link_specifier_list_parse_into(link_specifier_list_t *obj, const uint8_t *input, const size_t len_in)
  1461. {
  1462. const uint8_t *ptr = input;
  1463. size_t remaining = len_in;
  1464. ssize_t result = 0;
  1465. (void)result;
  1466. /* Parse u8 n_spec */
  1467. CHECK_REMAINING(1, truncated);
  1468. obj->n_spec = (trunnel_get_uint8(ptr));
  1469. remaining -= 1; ptr += 1;
  1470. /* Parse struct link_specifier spec[n_spec] */
  1471. TRUNNEL_DYNARRAY_EXPAND(link_specifier_t *, &obj->spec, obj->n_spec, {});
  1472. {
  1473. link_specifier_t * elt;
  1474. unsigned idx;
  1475. for (idx = 0; idx < obj->n_spec; ++idx) {
  1476. result = link_specifier_parse(&elt, ptr, remaining);
  1477. if (result < 0)
  1478. goto relay_fail;
  1479. trunnel_assert((size_t)result <= remaining);
  1480. remaining -= result; ptr += result;
  1481. TRUNNEL_DYNARRAY_ADD(link_specifier_t *, &obj->spec, elt, {link_specifier_free(elt);});
  1482. }
  1483. }
  1484. trunnel_assert(ptr + remaining == input + len_in);
  1485. return len_in - remaining;
  1486. truncated:
  1487. return -2;
  1488. relay_fail:
  1489. trunnel_assert(result < 0);
  1490. return result;
  1491. trunnel_alloc_failed:
  1492. return -1;
  1493. }
  1494. ssize_t
  1495. link_specifier_list_parse(link_specifier_list_t **output, const uint8_t *input, const size_t len_in)
  1496. {
  1497. ssize_t result;
  1498. *output = link_specifier_list_new();
  1499. if (NULL == *output)
  1500. return -1;
  1501. result = link_specifier_list_parse_into(*output, input, len_in);
  1502. if (result < 0) {
  1503. link_specifier_list_free(*output);
  1504. *output = NULL;
  1505. }
  1506. return result;
  1507. }