ed25519_cert.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  1. /* ed25519_cert.c -- generated by Trunnel v1.5.
  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(ed25519_cert_extension_t *inp, size_t idx)
  92. {
  93. trunnel_assert(idx < 32);
  94. return inp->un_signing_key[idx];
  95. }
  96. uint8_t
  97. ed25519_cert_extension_getconst_un_signing_key(const ed25519_cert_extension_t *inp, size_t idx)
  98. {
  99. return ed25519_cert_extension_get_un_signing_key((ed25519_cert_extension_t*)inp, idx);
  100. }
  101. int
  102. ed25519_cert_extension_set_un_signing_key(ed25519_cert_extension_t *inp, size_t idx, uint8_t elt)
  103. {
  104. trunnel_assert(idx < 32);
  105. inp->un_signing_key[idx] = elt;
  106. return 0;
  107. }
  108. uint8_t *
  109. ed25519_cert_extension_getarray_un_signing_key(ed25519_cert_extension_t *inp)
  110. {
  111. return inp->un_signing_key;
  112. }
  113. const uint8_t *
  114. ed25519_cert_extension_getconstarray_un_signing_key(const ed25519_cert_extension_t *inp)
  115. {
  116. return (const uint8_t *)ed25519_cert_extension_getarray_un_signing_key((ed25519_cert_extension_t*)inp);
  117. }
  118. size_t
  119. ed25519_cert_extension_getlen_un_unparsed(const ed25519_cert_extension_t *inp)
  120. {
  121. return TRUNNEL_DYNARRAY_LEN(&inp->un_unparsed);
  122. }
  123. uint8_t
  124. ed25519_cert_extension_get_un_unparsed(ed25519_cert_extension_t *inp, size_t idx)
  125. {
  126. return TRUNNEL_DYNARRAY_GET(&inp->un_unparsed, idx);
  127. }
  128. uint8_t
  129. ed25519_cert_extension_getconst_un_unparsed(const ed25519_cert_extension_t *inp, size_t idx)
  130. {
  131. return ed25519_cert_extension_get_un_unparsed((ed25519_cert_extension_t*)inp, idx);
  132. }
  133. int
  134. ed25519_cert_extension_set_un_unparsed(ed25519_cert_extension_t *inp, size_t idx, uint8_t elt)
  135. {
  136. TRUNNEL_DYNARRAY_SET(&inp->un_unparsed, idx, elt);
  137. return 0;
  138. }
  139. int
  140. ed25519_cert_extension_add_un_unparsed(ed25519_cert_extension_t *inp, uint8_t elt)
  141. {
  142. TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->un_unparsed, elt, {});
  143. return 0;
  144. trunnel_alloc_failed:
  145. TRUNNEL_SET_ERROR_CODE(inp);
  146. return -1;
  147. }
  148. uint8_t *
  149. ed25519_cert_extension_getarray_un_unparsed(ed25519_cert_extension_t *inp)
  150. {
  151. return inp->un_unparsed.elts_;
  152. }
  153. const uint8_t *
  154. ed25519_cert_extension_getconstarray_un_unparsed(const ed25519_cert_extension_t *inp)
  155. {
  156. return (const uint8_t *)ed25519_cert_extension_getarray_un_unparsed((ed25519_cert_extension_t*)inp);
  157. }
  158. int
  159. ed25519_cert_extension_setlen_un_unparsed(ed25519_cert_extension_t *inp, size_t newlen)
  160. {
  161. uint8_t *newptr;
  162. newptr = trunnel_dynarray_setlen(&inp->un_unparsed.allocated_,
  163. &inp->un_unparsed.n_, inp->un_unparsed.elts_, newlen,
  164. sizeof(inp->un_unparsed.elts_[0]), (trunnel_free_fn_t) NULL,
  165. &inp->trunnel_error_code_);
  166. if (newlen != 0 && newptr == NULL)
  167. goto trunnel_alloc_failed;
  168. inp->un_unparsed.elts_ = newptr;
  169. return 0;
  170. trunnel_alloc_failed:
  171. TRUNNEL_SET_ERROR_CODE(inp);
  172. return -1;
  173. }
  174. const char *
  175. ed25519_cert_extension_check(const ed25519_cert_extension_t *obj)
  176. {
  177. if (obj == NULL)
  178. return "Object was NULL";
  179. if (obj->trunnel_error_code_)
  180. return "A set function failed on this object";
  181. switch (obj->ext_type) {
  182. case CERTEXT_SIGNED_WITH_KEY:
  183. break;
  184. default:
  185. break;
  186. }
  187. return NULL;
  188. }
  189. ssize_t
  190. ed25519_cert_extension_encoded_len(const ed25519_cert_extension_t *obj)
  191. {
  192. ssize_t result = 0;
  193. if (NULL != ed25519_cert_extension_check(obj))
  194. return -1;
  195. /* Length of u16 ext_length */
  196. result += 2;
  197. /* Length of u8 ext_type */
  198. result += 1;
  199. /* Length of u8 ext_flags */
  200. result += 1;
  201. switch (obj->ext_type) {
  202. case CERTEXT_SIGNED_WITH_KEY:
  203. /* Length of u8 un_signing_key[32] */
  204. result += 32;
  205. break;
  206. default:
  207. /* Length of u8 un_unparsed[] */
  208. result += TRUNNEL_DYNARRAY_LEN(&obj->un_unparsed);
  209. break;
  210. }
  211. return result;
  212. }
  213. int
  214. ed25519_cert_extension_clear_errors(ed25519_cert_extension_t *obj)
  215. {
  216. int r = obj->trunnel_error_code_;
  217. obj->trunnel_error_code_ = 0;
  218. return r;
  219. }
  220. ssize_t
  221. ed25519_cert_extension_encode(uint8_t *output, const size_t avail, const ed25519_cert_extension_t *obj)
  222. {
  223. ssize_t result = 0;
  224. size_t written = 0;
  225. uint8_t *ptr = output;
  226. const char *msg;
  227. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  228. const ssize_t encoded_len = ed25519_cert_extension_encoded_len(obj);
  229. #endif
  230. uint8_t *backptr_ext_length = NULL;
  231. if (NULL != (msg = ed25519_cert_extension_check(obj)))
  232. goto check_failed;
  233. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  234. trunnel_assert(encoded_len >= 0);
  235. #endif
  236. /* Encode u16 ext_length */
  237. backptr_ext_length = ptr;
  238. trunnel_assert(written <= avail);
  239. if (avail - written < 2)
  240. goto truncated;
  241. trunnel_set_uint16(ptr, trunnel_htons(obj->ext_length));
  242. written += 2; ptr += 2;
  243. /* Encode u8 ext_type */
  244. trunnel_assert(written <= avail);
  245. if (avail - written < 1)
  246. goto truncated;
  247. trunnel_set_uint8(ptr, (obj->ext_type));
  248. written += 1; ptr += 1;
  249. /* Encode u8 ext_flags */
  250. trunnel_assert(written <= avail);
  251. if (avail - written < 1)
  252. goto truncated;
  253. trunnel_set_uint8(ptr, (obj->ext_flags));
  254. written += 1; ptr += 1;
  255. {
  256. size_t written_before_union = written;
  257. /* Encode union un[ext_type] */
  258. trunnel_assert(written <= avail);
  259. switch (obj->ext_type) {
  260. case CERTEXT_SIGNED_WITH_KEY:
  261. /* Encode u8 un_signing_key[32] */
  262. trunnel_assert(written <= avail);
  263. if (avail - written < 32)
  264. goto truncated;
  265. memcpy(ptr, obj->un_signing_key, 32);
  266. written += 32; ptr += 32;
  267. break;
  268. default:
  269. /* Encode u8 un_unparsed[] */
  270. {
  271. size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->un_unparsed);
  272. trunnel_assert(written <= avail);
  273. if (avail - written < elt_len)
  274. goto truncated;
  275. if (elt_len)
  276. memcpy(ptr, obj->un_unparsed.elts_, elt_len);
  277. written += elt_len; ptr += elt_len;
  278. }
  279. break;
  280. }
  281. /* Write the length field back to ext_length */
  282. trunnel_assert(written >= written_before_union);
  283. #if UINT16_MAX < SIZE_MAX
  284. if (written - written_before_union > UINT16_MAX)
  285. goto check_failed;
  286. #endif
  287. trunnel_set_uint16(backptr_ext_length, trunnel_htons(written - written_before_union));
  288. }
  289. trunnel_assert(ptr == output + written);
  290. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  291. {
  292. trunnel_assert(encoded_len >= 0);
  293. trunnel_assert((size_t)encoded_len == written);
  294. }
  295. #endif
  296. return written;
  297. truncated:
  298. result = -2;
  299. goto fail;
  300. check_failed:
  301. (void)msg;
  302. result = -1;
  303. goto fail;
  304. fail:
  305. trunnel_assert(result < 0);
  306. return result;
  307. }
  308. /** As ed25519_cert_extension_parse(), but do not allocate the output
  309. * object.
  310. */
  311. static ssize_t
  312. ed25519_cert_extension_parse_into(ed25519_cert_extension_t *obj, const uint8_t *input, const size_t len_in)
  313. {
  314. const uint8_t *ptr = input;
  315. size_t remaining = len_in;
  316. ssize_t result = 0;
  317. (void)result;
  318. /* Parse u16 ext_length */
  319. CHECK_REMAINING(2, truncated);
  320. obj->ext_length = trunnel_ntohs(trunnel_get_uint16(ptr));
  321. remaining -= 2; ptr += 2;
  322. /* Parse u8 ext_type */
  323. CHECK_REMAINING(1, truncated);
  324. obj->ext_type = (trunnel_get_uint8(ptr));
  325. remaining -= 1; ptr += 1;
  326. /* Parse u8 ext_flags */
  327. CHECK_REMAINING(1, truncated);
  328. obj->ext_flags = (trunnel_get_uint8(ptr));
  329. remaining -= 1; ptr += 1;
  330. {
  331. size_t remaining_after;
  332. CHECK_REMAINING(obj->ext_length, truncated);
  333. remaining_after = remaining - obj->ext_length;
  334. remaining = obj->ext_length;
  335. /* Parse union un[ext_type] */
  336. switch (obj->ext_type) {
  337. case CERTEXT_SIGNED_WITH_KEY:
  338. /* Parse u8 un_signing_key[32] */
  339. CHECK_REMAINING(32, fail);
  340. memcpy(obj->un_signing_key, ptr, 32);
  341. remaining -= 32; ptr += 32;
  342. break;
  343. default:
  344. /* Parse u8 un_unparsed[] */
  345. TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->un_unparsed, remaining, {});
  346. obj->un_unparsed.n_ = remaining;
  347. if (remaining)
  348. memcpy(obj->un_unparsed.elts_, ptr, remaining);
  349. ptr += remaining; remaining -= remaining;
  350. break;
  351. }
  352. if (remaining != 0)
  353. goto fail;
  354. remaining = remaining_after;
  355. }
  356. trunnel_assert(ptr + remaining == input + len_in);
  357. return len_in - remaining;
  358. truncated:
  359. return -2;
  360. trunnel_alloc_failed:
  361. return -1;
  362. fail:
  363. result = -1;
  364. return result;
  365. }
  366. ssize_t
  367. ed25519_cert_extension_parse(ed25519_cert_extension_t **output, const uint8_t *input, const size_t len_in)
  368. {
  369. ssize_t result;
  370. *output = ed25519_cert_extension_new();
  371. if (NULL == *output)
  372. return -1;
  373. result = ed25519_cert_extension_parse_into(*output, input, len_in);
  374. if (result < 0) {
  375. ed25519_cert_extension_free(*output);
  376. *output = NULL;
  377. }
  378. return result;
  379. }
  380. ed25519_cert_t *
  381. ed25519_cert_new(void)
  382. {
  383. ed25519_cert_t *val = trunnel_calloc(1, sizeof(ed25519_cert_t));
  384. if (NULL == val)
  385. return NULL;
  386. val->version = 1;
  387. return val;
  388. }
  389. /** Release all storage held inside 'obj', but do not free 'obj'.
  390. */
  391. static void
  392. ed25519_cert_clear(ed25519_cert_t *obj)
  393. {
  394. (void) obj;
  395. {
  396. unsigned idx;
  397. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
  398. ed25519_cert_extension_free(TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
  399. }
  400. }
  401. TRUNNEL_DYNARRAY_WIPE(&obj->ext);
  402. TRUNNEL_DYNARRAY_CLEAR(&obj->ext);
  403. }
  404. void
  405. ed25519_cert_free(ed25519_cert_t *obj)
  406. {
  407. if (obj == NULL)
  408. return;
  409. ed25519_cert_clear(obj);
  410. trunnel_memwipe(obj, sizeof(ed25519_cert_t));
  411. trunnel_free_(obj);
  412. }
  413. uint8_t
  414. ed25519_cert_get_version(ed25519_cert_t *inp)
  415. {
  416. return inp->version;
  417. }
  418. int
  419. ed25519_cert_set_version(ed25519_cert_t *inp, uint8_t val)
  420. {
  421. if (! ((val == 1))) {
  422. TRUNNEL_SET_ERROR_CODE(inp);
  423. return -1;
  424. }
  425. inp->version = val;
  426. return 0;
  427. }
  428. uint8_t
  429. ed25519_cert_get_cert_type(ed25519_cert_t *inp)
  430. {
  431. return inp->cert_type;
  432. }
  433. int
  434. ed25519_cert_set_cert_type(ed25519_cert_t *inp, uint8_t val)
  435. {
  436. inp->cert_type = val;
  437. return 0;
  438. }
  439. uint32_t
  440. ed25519_cert_get_exp_field(ed25519_cert_t *inp)
  441. {
  442. return inp->exp_field;
  443. }
  444. int
  445. ed25519_cert_set_exp_field(ed25519_cert_t *inp, uint32_t val)
  446. {
  447. inp->exp_field = val;
  448. return 0;
  449. }
  450. uint8_t
  451. ed25519_cert_get_cert_key_type(ed25519_cert_t *inp)
  452. {
  453. return inp->cert_key_type;
  454. }
  455. int
  456. ed25519_cert_set_cert_key_type(ed25519_cert_t *inp, uint8_t val)
  457. {
  458. inp->cert_key_type = val;
  459. return 0;
  460. }
  461. size_t
  462. ed25519_cert_getlen_certified_key(const ed25519_cert_t *inp)
  463. {
  464. (void)inp; return 32;
  465. }
  466. uint8_t
  467. ed25519_cert_get_certified_key(ed25519_cert_t *inp, size_t idx)
  468. {
  469. trunnel_assert(idx < 32);
  470. return inp->certified_key[idx];
  471. }
  472. uint8_t
  473. ed25519_cert_getconst_certified_key(const ed25519_cert_t *inp, size_t idx)
  474. {
  475. return ed25519_cert_get_certified_key((ed25519_cert_t*)inp, idx);
  476. }
  477. int
  478. ed25519_cert_set_certified_key(ed25519_cert_t *inp, size_t idx, uint8_t elt)
  479. {
  480. trunnel_assert(idx < 32);
  481. inp->certified_key[idx] = elt;
  482. return 0;
  483. }
  484. uint8_t *
  485. ed25519_cert_getarray_certified_key(ed25519_cert_t *inp)
  486. {
  487. return inp->certified_key;
  488. }
  489. const uint8_t *
  490. ed25519_cert_getconstarray_certified_key(const ed25519_cert_t *inp)
  491. {
  492. return (const uint8_t *)ed25519_cert_getarray_certified_key((ed25519_cert_t*)inp);
  493. }
  494. uint8_t
  495. ed25519_cert_get_n_extensions(ed25519_cert_t *inp)
  496. {
  497. return inp->n_extensions;
  498. }
  499. int
  500. ed25519_cert_set_n_extensions(ed25519_cert_t *inp, uint8_t val)
  501. {
  502. inp->n_extensions = val;
  503. return 0;
  504. }
  505. size_t
  506. ed25519_cert_getlen_ext(const ed25519_cert_t *inp)
  507. {
  508. return TRUNNEL_DYNARRAY_LEN(&inp->ext);
  509. }
  510. struct ed25519_cert_extension_st *
  511. ed25519_cert_get_ext(ed25519_cert_t *inp, size_t idx)
  512. {
  513. return TRUNNEL_DYNARRAY_GET(&inp->ext, idx);
  514. }
  515. const struct ed25519_cert_extension_st *
  516. ed25519_cert_getconst_ext(const ed25519_cert_t *inp, size_t idx)
  517. {
  518. return ed25519_cert_get_ext((ed25519_cert_t*)inp, idx);
  519. }
  520. int
  521. ed25519_cert_set_ext(ed25519_cert_t *inp, size_t idx, struct ed25519_cert_extension_st * elt)
  522. {
  523. ed25519_cert_extension_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->ext, idx);
  524. if (oldval && oldval != elt)
  525. ed25519_cert_extension_free(oldval);
  526. return ed25519_cert_set0_ext(inp, idx, elt);
  527. }
  528. int
  529. ed25519_cert_set0_ext(ed25519_cert_t *inp, size_t idx, struct ed25519_cert_extension_st * elt)
  530. {
  531. TRUNNEL_DYNARRAY_SET(&inp->ext, idx, elt);
  532. return 0;
  533. }
  534. int
  535. ed25519_cert_add_ext(ed25519_cert_t *inp, struct ed25519_cert_extension_st * elt)
  536. {
  537. #if SIZE_MAX >= UINT8_MAX
  538. if (inp->ext.n_ == UINT8_MAX)
  539. goto trunnel_alloc_failed;
  540. #endif
  541. TRUNNEL_DYNARRAY_ADD(struct ed25519_cert_extension_st *, &inp->ext, elt, {});
  542. return 0;
  543. trunnel_alloc_failed:
  544. TRUNNEL_SET_ERROR_CODE(inp);
  545. return -1;
  546. }
  547. struct ed25519_cert_extension_st * *
  548. ed25519_cert_getarray_ext(ed25519_cert_t *inp)
  549. {
  550. return inp->ext.elts_;
  551. }
  552. const struct ed25519_cert_extension_st * const *
  553. ed25519_cert_getconstarray_ext(const ed25519_cert_t *inp)
  554. {
  555. return (const struct ed25519_cert_extension_st * const *)ed25519_cert_getarray_ext((ed25519_cert_t*)inp);
  556. }
  557. int
  558. ed25519_cert_setlen_ext(ed25519_cert_t *inp, size_t newlen)
  559. {
  560. struct ed25519_cert_extension_st * *newptr;
  561. #if UINT8_MAX < SIZE_MAX
  562. if (newlen > UINT8_MAX)
  563. goto trunnel_alloc_failed;
  564. #endif
  565. newptr = trunnel_dynarray_setlen(&inp->ext.allocated_,
  566. &inp->ext.n_, inp->ext.elts_, newlen,
  567. sizeof(inp->ext.elts_[0]), (trunnel_free_fn_t) ed25519_cert_extension_free,
  568. &inp->trunnel_error_code_);
  569. if (newlen != 0 && newptr == NULL)
  570. goto trunnel_alloc_failed;
  571. inp->ext.elts_ = newptr;
  572. return 0;
  573. trunnel_alloc_failed:
  574. TRUNNEL_SET_ERROR_CODE(inp);
  575. return -1;
  576. }
  577. size_t
  578. ed25519_cert_getlen_signature(const ed25519_cert_t *inp)
  579. {
  580. (void)inp; return 64;
  581. }
  582. uint8_t
  583. ed25519_cert_get_signature(ed25519_cert_t *inp, size_t idx)
  584. {
  585. trunnel_assert(idx < 64);
  586. return inp->signature[idx];
  587. }
  588. uint8_t
  589. ed25519_cert_getconst_signature(const ed25519_cert_t *inp, size_t idx)
  590. {
  591. return ed25519_cert_get_signature((ed25519_cert_t*)inp, idx);
  592. }
  593. int
  594. ed25519_cert_set_signature(ed25519_cert_t *inp, size_t idx, uint8_t elt)
  595. {
  596. trunnel_assert(idx < 64);
  597. inp->signature[idx] = elt;
  598. return 0;
  599. }
  600. uint8_t *
  601. ed25519_cert_getarray_signature(ed25519_cert_t *inp)
  602. {
  603. return inp->signature;
  604. }
  605. const uint8_t *
  606. ed25519_cert_getconstarray_signature(const ed25519_cert_t *inp)
  607. {
  608. return (const uint8_t *)ed25519_cert_getarray_signature((ed25519_cert_t*)inp);
  609. }
  610. const char *
  611. ed25519_cert_check(const ed25519_cert_t *obj)
  612. {
  613. if (obj == NULL)
  614. return "Object was NULL";
  615. if (obj->trunnel_error_code_)
  616. return "A set function failed on this object";
  617. if (! (obj->version == 1))
  618. return "Integer out of bounds";
  619. {
  620. const char *msg;
  621. unsigned idx;
  622. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
  623. if (NULL != (msg = ed25519_cert_extension_check(TRUNNEL_DYNARRAY_GET(&obj->ext, idx))))
  624. return msg;
  625. }
  626. }
  627. if (TRUNNEL_DYNARRAY_LEN(&obj->ext) != obj->n_extensions)
  628. return "Length mismatch for ext";
  629. return NULL;
  630. }
  631. ssize_t
  632. ed25519_cert_encoded_len(const ed25519_cert_t *obj)
  633. {
  634. ssize_t result = 0;
  635. if (NULL != ed25519_cert_check(obj))
  636. return -1;
  637. /* Length of u8 version IN [1] */
  638. result += 1;
  639. /* Length of u8 cert_type */
  640. result += 1;
  641. /* Length of u32 exp_field */
  642. result += 4;
  643. /* Length of u8 cert_key_type */
  644. result += 1;
  645. /* Length of u8 certified_key[32] */
  646. result += 32;
  647. /* Length of u8 n_extensions */
  648. result += 1;
  649. /* Length of struct ed25519_cert_extension ext[n_extensions] */
  650. {
  651. unsigned idx;
  652. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
  653. result += ed25519_cert_extension_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
  654. }
  655. }
  656. /* Length of u8 signature[64] */
  657. result += 64;
  658. return result;
  659. }
  660. int
  661. ed25519_cert_clear_errors(ed25519_cert_t *obj)
  662. {
  663. int r = obj->trunnel_error_code_;
  664. obj->trunnel_error_code_ = 0;
  665. return r;
  666. }
  667. ssize_t
  668. ed25519_cert_encode(uint8_t *output, const size_t avail, const ed25519_cert_t *obj)
  669. {
  670. ssize_t result = 0;
  671. size_t written = 0;
  672. uint8_t *ptr = output;
  673. const char *msg;
  674. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  675. const ssize_t encoded_len = ed25519_cert_encoded_len(obj);
  676. #endif
  677. if (NULL != (msg = ed25519_cert_check(obj)))
  678. goto check_failed;
  679. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  680. trunnel_assert(encoded_len >= 0);
  681. #endif
  682. /* Encode u8 version IN [1] */
  683. trunnel_assert(written <= avail);
  684. if (avail - written < 1)
  685. goto truncated;
  686. trunnel_set_uint8(ptr, (obj->version));
  687. written += 1; ptr += 1;
  688. /* Encode u8 cert_type */
  689. trunnel_assert(written <= avail);
  690. if (avail - written < 1)
  691. goto truncated;
  692. trunnel_set_uint8(ptr, (obj->cert_type));
  693. written += 1; ptr += 1;
  694. /* Encode u32 exp_field */
  695. trunnel_assert(written <= avail);
  696. if (avail - written < 4)
  697. goto truncated;
  698. trunnel_set_uint32(ptr, trunnel_htonl(obj->exp_field));
  699. written += 4; ptr += 4;
  700. /* Encode u8 cert_key_type */
  701. trunnel_assert(written <= avail);
  702. if (avail - written < 1)
  703. goto truncated;
  704. trunnel_set_uint8(ptr, (obj->cert_key_type));
  705. written += 1; ptr += 1;
  706. /* Encode u8 certified_key[32] */
  707. trunnel_assert(written <= avail);
  708. if (avail - written < 32)
  709. goto truncated;
  710. memcpy(ptr, obj->certified_key, 32);
  711. written += 32; ptr += 32;
  712. /* Encode u8 n_extensions */
  713. trunnel_assert(written <= avail);
  714. if (avail - written < 1)
  715. goto truncated;
  716. trunnel_set_uint8(ptr, (obj->n_extensions));
  717. written += 1; ptr += 1;
  718. /* Encode struct ed25519_cert_extension ext[n_extensions] */
  719. {
  720. unsigned idx;
  721. for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
  722. trunnel_assert(written <= avail);
  723. result = ed25519_cert_extension_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
  724. if (result < 0)
  725. goto fail; /* XXXXXXX !*/
  726. written += result; ptr += result;
  727. }
  728. }
  729. /* Encode u8 signature[64] */
  730. trunnel_assert(written <= avail);
  731. if (avail - written < 64)
  732. goto truncated;
  733. memcpy(ptr, obj->signature, 64);
  734. written += 64; ptr += 64;
  735. trunnel_assert(ptr == output + written);
  736. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  737. {
  738. trunnel_assert(encoded_len >= 0);
  739. trunnel_assert((size_t)encoded_len == written);
  740. }
  741. #endif
  742. return written;
  743. truncated:
  744. result = -2;
  745. goto fail;
  746. check_failed:
  747. (void)msg;
  748. result = -1;
  749. goto fail;
  750. fail:
  751. trunnel_assert(result < 0);
  752. return result;
  753. }
  754. /** As ed25519_cert_parse(), but do not allocate the output object.
  755. */
  756. static ssize_t
  757. ed25519_cert_parse_into(ed25519_cert_t *obj, const uint8_t *input, const size_t len_in)
  758. {
  759. const uint8_t *ptr = input;
  760. size_t remaining = len_in;
  761. ssize_t result = 0;
  762. (void)result;
  763. /* Parse u8 version IN [1] */
  764. CHECK_REMAINING(1, truncated);
  765. obj->version = (trunnel_get_uint8(ptr));
  766. remaining -= 1; ptr += 1;
  767. if (! (obj->version == 1))
  768. goto fail;
  769. /* Parse u8 cert_type */
  770. CHECK_REMAINING(1, truncated);
  771. obj->cert_type = (trunnel_get_uint8(ptr));
  772. remaining -= 1; ptr += 1;
  773. /* Parse u32 exp_field */
  774. CHECK_REMAINING(4, truncated);
  775. obj->exp_field = trunnel_ntohl(trunnel_get_uint32(ptr));
  776. remaining -= 4; ptr += 4;
  777. /* Parse u8 cert_key_type */
  778. CHECK_REMAINING(1, truncated);
  779. obj->cert_key_type = (trunnel_get_uint8(ptr));
  780. remaining -= 1; ptr += 1;
  781. /* Parse u8 certified_key[32] */
  782. CHECK_REMAINING(32, truncated);
  783. memcpy(obj->certified_key, ptr, 32);
  784. remaining -= 32; ptr += 32;
  785. /* Parse u8 n_extensions */
  786. CHECK_REMAINING(1, truncated);
  787. obj->n_extensions = (trunnel_get_uint8(ptr));
  788. remaining -= 1; ptr += 1;
  789. /* Parse struct ed25519_cert_extension ext[n_extensions] */
  790. TRUNNEL_DYNARRAY_EXPAND(ed25519_cert_extension_t *, &obj->ext, obj->n_extensions, {});
  791. {
  792. ed25519_cert_extension_t * elt;
  793. unsigned idx;
  794. for (idx = 0; idx < obj->n_extensions; ++idx) {
  795. result = ed25519_cert_extension_parse(&elt, ptr, remaining);
  796. if (result < 0)
  797. goto relay_fail;
  798. trunnel_assert((size_t)result <= remaining);
  799. remaining -= result; ptr += result;
  800. TRUNNEL_DYNARRAY_ADD(ed25519_cert_extension_t *, &obj->ext, elt, {ed25519_cert_extension_free(elt);});
  801. }
  802. }
  803. /* Parse u8 signature[64] */
  804. CHECK_REMAINING(64, truncated);
  805. memcpy(obj->signature, ptr, 64);
  806. remaining -= 64; ptr += 64;
  807. trunnel_assert(ptr + remaining == input + len_in);
  808. return len_in - remaining;
  809. truncated:
  810. return -2;
  811. relay_fail:
  812. trunnel_assert(result < 0);
  813. return result;
  814. trunnel_alloc_failed:
  815. return -1;
  816. fail:
  817. result = -1;
  818. return result;
  819. }
  820. ssize_t
  821. ed25519_cert_parse(ed25519_cert_t **output, const uint8_t *input, const size_t len_in)
  822. {
  823. ssize_t result;
  824. *output = ed25519_cert_new();
  825. if (NULL == *output)
  826. return -1;
  827. result = ed25519_cert_parse_into(*output, input, len_in);
  828. if (result < 0) {
  829. ed25519_cert_free(*output);
  830. *output = NULL;
  831. }
  832. return result;
  833. }