Merge branch 'maint-0.4.5' into maint-0.4.6
[tor.git] / src / trunnel / ed25519_cert.c
blob86b79ef9b6970e4ad930b73feedb03ad000f15d2
1 /* ed25519_cert.c -- generated by Trunnel v1.5.3.
2 * https://gitweb.torproject.org/trunnel.git
3 * You probably shouldn't edit this file.
4 */
5 #include <stdlib.h>
6 #include "trunnel-impl.h"
8 #include "ed25519_cert.h"
10 #define TRUNNEL_SET_ERROR_CODE(obj) \
11 do { \
12 (obj)->trunnel_error_code_ = 1; \
13 } while (0)
15 #if defined(__COVERITY__) || defined(__clang_analyzer__)
16 /* If we're running a static analysis tool, we don't want it to complain
17 * that some of our remaining-bytes checks are dead-code. */
18 int edcert_deadcode_dummy__ = 0;
19 #define OR_DEADCODE_DUMMY || edcert_deadcode_dummy__
20 #else
21 #define OR_DEADCODE_DUMMY
22 #endif
24 #define CHECK_REMAINING(nbytes, label) \
25 do { \
26 if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
27 goto label; \
28 } \
29 } while (0)
31 create2_cell_body_t *
32 create2_cell_body_new(void)
34 create2_cell_body_t *val = trunnel_calloc(1, sizeof(create2_cell_body_t));
35 if (NULL == val)
36 return NULL;
37 return val;
40 /** Release all storage held inside 'obj', but do not free 'obj'.
42 static void
43 create2_cell_body_clear(create2_cell_body_t *obj)
45 (void) obj;
46 TRUNNEL_DYNARRAY_WIPE(&obj->handshake_data);
47 TRUNNEL_DYNARRAY_CLEAR(&obj->handshake_data);
50 void
51 create2_cell_body_free(create2_cell_body_t *obj)
53 if (obj == NULL)
54 return;
55 create2_cell_body_clear(obj);
56 trunnel_memwipe(obj, sizeof(create2_cell_body_t));
57 trunnel_free_(obj);
60 uint16_t
61 create2_cell_body_get_handshake_type(const create2_cell_body_t *inp)
63 return inp->handshake_type;
65 int
66 create2_cell_body_set_handshake_type(create2_cell_body_t *inp, uint16_t val)
68 inp->handshake_type = val;
69 return 0;
71 uint16_t
72 create2_cell_body_get_handshake_len(const create2_cell_body_t *inp)
74 return inp->handshake_len;
76 int
77 create2_cell_body_set_handshake_len(create2_cell_body_t *inp, uint16_t val)
79 inp->handshake_len = val;
80 return 0;
82 size_t
83 create2_cell_body_getlen_handshake_data(const create2_cell_body_t *inp)
85 return TRUNNEL_DYNARRAY_LEN(&inp->handshake_data);
88 uint8_t
89 create2_cell_body_get_handshake_data(create2_cell_body_t *inp, size_t idx)
91 return TRUNNEL_DYNARRAY_GET(&inp->handshake_data, idx);
94 uint8_t
95 create2_cell_body_getconst_handshake_data(const create2_cell_body_t *inp, size_t idx)
97 return create2_cell_body_get_handshake_data((create2_cell_body_t*)inp, idx);
99 int
100 create2_cell_body_set_handshake_data(create2_cell_body_t *inp, size_t idx, uint8_t elt)
102 TRUNNEL_DYNARRAY_SET(&inp->handshake_data, idx, elt);
103 return 0;
106 create2_cell_body_add_handshake_data(create2_cell_body_t *inp, uint8_t elt)
108 #if SIZE_MAX >= UINT16_MAX
109 if (inp->handshake_data.n_ == UINT16_MAX)
110 goto trunnel_alloc_failed;
111 #endif
112 TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->handshake_data, elt, {});
113 return 0;
114 trunnel_alloc_failed:
115 TRUNNEL_SET_ERROR_CODE(inp);
116 return -1;
119 uint8_t *
120 create2_cell_body_getarray_handshake_data(create2_cell_body_t *inp)
122 return inp->handshake_data.elts_;
124 const uint8_t *
125 create2_cell_body_getconstarray_handshake_data(const create2_cell_body_t *inp)
127 return (const uint8_t *)create2_cell_body_getarray_handshake_data((create2_cell_body_t*)inp);
130 create2_cell_body_setlen_handshake_data(create2_cell_body_t *inp, size_t newlen)
132 uint8_t *newptr;
133 #if UINT16_MAX < SIZE_MAX
134 if (newlen > UINT16_MAX)
135 goto trunnel_alloc_failed;
136 #endif
137 newptr = trunnel_dynarray_setlen(&inp->handshake_data.allocated_,
138 &inp->handshake_data.n_, inp->handshake_data.elts_, newlen,
139 sizeof(inp->handshake_data.elts_[0]), (trunnel_free_fn_t) NULL,
140 &inp->trunnel_error_code_);
141 if (newlen != 0 && newptr == NULL)
142 goto trunnel_alloc_failed;
143 inp->handshake_data.elts_ = newptr;
144 return 0;
145 trunnel_alloc_failed:
146 TRUNNEL_SET_ERROR_CODE(inp);
147 return -1;
149 const char *
150 create2_cell_body_check(const create2_cell_body_t *obj)
152 if (obj == NULL)
153 return "Object was NULL";
154 if (obj->trunnel_error_code_)
155 return "A set function failed on this object";
156 if (TRUNNEL_DYNARRAY_LEN(&obj->handshake_data) != obj->handshake_len)
157 return "Length mismatch for handshake_data";
158 return NULL;
161 ssize_t
162 create2_cell_body_encoded_len(const create2_cell_body_t *obj)
164 ssize_t result = 0;
166 if (NULL != create2_cell_body_check(obj))
167 return -1;
170 /* Length of u16 handshake_type */
171 result += 2;
173 /* Length of u16 handshake_len */
174 result += 2;
176 /* Length of u8 handshake_data[handshake_len] */
177 result += TRUNNEL_DYNARRAY_LEN(&obj->handshake_data);
178 return result;
181 create2_cell_body_clear_errors(create2_cell_body_t *obj)
183 int r = obj->trunnel_error_code_;
184 obj->trunnel_error_code_ = 0;
185 return r;
187 ssize_t
188 create2_cell_body_encode(uint8_t *output, const size_t avail, const create2_cell_body_t *obj)
190 ssize_t result = 0;
191 size_t written = 0;
192 uint8_t *ptr = output;
193 const char *msg;
194 #ifdef TRUNNEL_CHECK_ENCODED_LEN
195 const ssize_t encoded_len = create2_cell_body_encoded_len(obj);
196 #endif
198 if (NULL != (msg = create2_cell_body_check(obj)))
199 goto check_failed;
201 #ifdef TRUNNEL_CHECK_ENCODED_LEN
202 trunnel_assert(encoded_len >= 0);
203 #endif
205 /* Encode u16 handshake_type */
206 trunnel_assert(written <= avail);
207 if (avail - written < 2)
208 goto truncated;
209 trunnel_set_uint16(ptr, trunnel_htons(obj->handshake_type));
210 written += 2; ptr += 2;
212 /* Encode u16 handshake_len */
213 trunnel_assert(written <= avail);
214 if (avail - written < 2)
215 goto truncated;
216 trunnel_set_uint16(ptr, trunnel_htons(obj->handshake_len));
217 written += 2; ptr += 2;
219 /* Encode u8 handshake_data[handshake_len] */
221 size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->handshake_data);
222 trunnel_assert(obj->handshake_len == elt_len);
223 trunnel_assert(written <= avail);
224 if (avail - written < elt_len)
225 goto truncated;
226 if (elt_len)
227 memcpy(ptr, obj->handshake_data.elts_, elt_len);
228 written += elt_len; ptr += elt_len;
232 trunnel_assert(ptr == output + written);
233 #ifdef TRUNNEL_CHECK_ENCODED_LEN
235 trunnel_assert(encoded_len >= 0);
236 trunnel_assert((size_t)encoded_len == written);
239 #endif
241 return written;
243 truncated:
244 result = -2;
245 goto fail;
246 check_failed:
247 (void)msg;
248 result = -1;
249 goto fail;
250 fail:
251 trunnel_assert(result < 0);
252 return result;
255 /** As create2_cell_body_parse(), but do not allocate the output
256 * object.
258 static ssize_t
259 create2_cell_body_parse_into(create2_cell_body_t *obj, const uint8_t *input, const size_t len_in)
261 const uint8_t *ptr = input;
262 size_t remaining = len_in;
263 ssize_t result = 0;
264 (void)result;
266 /* Parse u16 handshake_type */
267 CHECK_REMAINING(2, truncated);
268 obj->handshake_type = trunnel_ntohs(trunnel_get_uint16(ptr));
269 remaining -= 2; ptr += 2;
271 /* Parse u16 handshake_len */
272 CHECK_REMAINING(2, truncated);
273 obj->handshake_len = trunnel_ntohs(trunnel_get_uint16(ptr));
274 remaining -= 2; ptr += 2;
276 /* Parse u8 handshake_data[handshake_len] */
277 CHECK_REMAINING(obj->handshake_len, truncated);
278 TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->handshake_data, obj->handshake_len, {});
279 obj->handshake_data.n_ = obj->handshake_len;
280 if (obj->handshake_len)
281 memcpy(obj->handshake_data.elts_, ptr, obj->handshake_len);
282 ptr += obj->handshake_len; remaining -= obj->handshake_len;
283 trunnel_assert(ptr + remaining == input + len_in);
284 return len_in - remaining;
286 truncated:
287 return -2;
288 trunnel_alloc_failed:
289 return -1;
292 ssize_t
293 create2_cell_body_parse(create2_cell_body_t **output, const uint8_t *input, const size_t len_in)
295 ssize_t result;
296 *output = create2_cell_body_new();
297 if (NULL == *output)
298 return -1;
299 result = create2_cell_body_parse_into(*output, input, len_in);
300 if (result < 0) {
301 create2_cell_body_free(*output);
302 *output = NULL;
304 return result;
306 ed25519_cert_extension_t *
307 ed25519_cert_extension_new(void)
309 ed25519_cert_extension_t *val = trunnel_calloc(1, sizeof(ed25519_cert_extension_t));
310 if (NULL == val)
311 return NULL;
312 return val;
315 /** Release all storage held inside 'obj', but do not free 'obj'.
317 static void
318 ed25519_cert_extension_clear(ed25519_cert_extension_t *obj)
320 (void) obj;
321 TRUNNEL_DYNARRAY_WIPE(&obj->un_unparsed);
322 TRUNNEL_DYNARRAY_CLEAR(&obj->un_unparsed);
325 void
326 ed25519_cert_extension_free(ed25519_cert_extension_t *obj)
328 if (obj == NULL)
329 return;
330 ed25519_cert_extension_clear(obj);
331 trunnel_memwipe(obj, sizeof(ed25519_cert_extension_t));
332 trunnel_free_(obj);
335 uint16_t
336 ed25519_cert_extension_get_ext_length(const ed25519_cert_extension_t *inp)
338 return inp->ext_length;
341 ed25519_cert_extension_set_ext_length(ed25519_cert_extension_t *inp, uint16_t val)
343 inp->ext_length = val;
344 return 0;
346 uint8_t
347 ed25519_cert_extension_get_ext_type(const ed25519_cert_extension_t *inp)
349 return inp->ext_type;
352 ed25519_cert_extension_set_ext_type(ed25519_cert_extension_t *inp, uint8_t val)
354 inp->ext_type = val;
355 return 0;
357 uint8_t
358 ed25519_cert_extension_get_ext_flags(const ed25519_cert_extension_t *inp)
360 return inp->ext_flags;
363 ed25519_cert_extension_set_ext_flags(ed25519_cert_extension_t *inp, uint8_t val)
365 inp->ext_flags = val;
366 return 0;
368 size_t
369 ed25519_cert_extension_getlen_un_signing_key(const ed25519_cert_extension_t *inp)
371 (void)inp; return 32;
374 uint8_t
375 ed25519_cert_extension_get_un_signing_key(ed25519_cert_extension_t *inp, size_t idx)
377 trunnel_assert(idx < 32);
378 return inp->un_signing_key[idx];
381 uint8_t
382 ed25519_cert_extension_getconst_un_signing_key(const ed25519_cert_extension_t *inp, size_t idx)
384 return ed25519_cert_extension_get_un_signing_key((ed25519_cert_extension_t*)inp, idx);
387 ed25519_cert_extension_set_un_signing_key(ed25519_cert_extension_t *inp, size_t idx, uint8_t elt)
389 trunnel_assert(idx < 32);
390 inp->un_signing_key[idx] = elt;
391 return 0;
394 uint8_t *
395 ed25519_cert_extension_getarray_un_signing_key(ed25519_cert_extension_t *inp)
397 return inp->un_signing_key;
399 const uint8_t *
400 ed25519_cert_extension_getconstarray_un_signing_key(const ed25519_cert_extension_t *inp)
402 return (const uint8_t *)ed25519_cert_extension_getarray_un_signing_key((ed25519_cert_extension_t*)inp);
404 size_t
405 ed25519_cert_extension_getlen_un_unparsed(const ed25519_cert_extension_t *inp)
407 return TRUNNEL_DYNARRAY_LEN(&inp->un_unparsed);
410 uint8_t
411 ed25519_cert_extension_get_un_unparsed(ed25519_cert_extension_t *inp, size_t idx)
413 return TRUNNEL_DYNARRAY_GET(&inp->un_unparsed, idx);
416 uint8_t
417 ed25519_cert_extension_getconst_un_unparsed(const ed25519_cert_extension_t *inp, size_t idx)
419 return ed25519_cert_extension_get_un_unparsed((ed25519_cert_extension_t*)inp, idx);
422 ed25519_cert_extension_set_un_unparsed(ed25519_cert_extension_t *inp, size_t idx, uint8_t elt)
424 TRUNNEL_DYNARRAY_SET(&inp->un_unparsed, idx, elt);
425 return 0;
428 ed25519_cert_extension_add_un_unparsed(ed25519_cert_extension_t *inp, uint8_t elt)
430 TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->un_unparsed, elt, {});
431 return 0;
432 trunnel_alloc_failed:
433 TRUNNEL_SET_ERROR_CODE(inp);
434 return -1;
437 uint8_t *
438 ed25519_cert_extension_getarray_un_unparsed(ed25519_cert_extension_t *inp)
440 return inp->un_unparsed.elts_;
442 const uint8_t *
443 ed25519_cert_extension_getconstarray_un_unparsed(const ed25519_cert_extension_t *inp)
445 return (const uint8_t *)ed25519_cert_extension_getarray_un_unparsed((ed25519_cert_extension_t*)inp);
448 ed25519_cert_extension_setlen_un_unparsed(ed25519_cert_extension_t *inp, size_t newlen)
450 uint8_t *newptr;
451 newptr = trunnel_dynarray_setlen(&inp->un_unparsed.allocated_,
452 &inp->un_unparsed.n_, inp->un_unparsed.elts_, newlen,
453 sizeof(inp->un_unparsed.elts_[0]), (trunnel_free_fn_t) NULL,
454 &inp->trunnel_error_code_);
455 if (newlen != 0 && newptr == NULL)
456 goto trunnel_alloc_failed;
457 inp->un_unparsed.elts_ = newptr;
458 return 0;
459 trunnel_alloc_failed:
460 TRUNNEL_SET_ERROR_CODE(inp);
461 return -1;
463 const char *
464 ed25519_cert_extension_check(const ed25519_cert_extension_t *obj)
466 if (obj == NULL)
467 return "Object was NULL";
468 if (obj->trunnel_error_code_)
469 return "A set function failed on this object";
470 switch (obj->ext_type) {
472 case CERTEXT_SIGNED_WITH_KEY:
473 break;
475 default:
476 break;
478 return NULL;
481 ssize_t
482 ed25519_cert_extension_encoded_len(const ed25519_cert_extension_t *obj)
484 ssize_t result = 0;
486 if (NULL != ed25519_cert_extension_check(obj))
487 return -1;
490 /* Length of u16 ext_length */
491 result += 2;
493 /* Length of u8 ext_type */
494 result += 1;
496 /* Length of u8 ext_flags */
497 result += 1;
498 switch (obj->ext_type) {
500 case CERTEXT_SIGNED_WITH_KEY:
502 /* Length of u8 un_signing_key[32] */
503 result += 32;
504 break;
506 default:
508 /* Length of u8 un_unparsed[] */
509 result += TRUNNEL_DYNARRAY_LEN(&obj->un_unparsed);
510 break;
512 return result;
515 ed25519_cert_extension_clear_errors(ed25519_cert_extension_t *obj)
517 int r = obj->trunnel_error_code_;
518 obj->trunnel_error_code_ = 0;
519 return r;
521 ssize_t
522 ed25519_cert_extension_encode(uint8_t *output, const size_t avail, const ed25519_cert_extension_t *obj)
524 ssize_t result = 0;
525 size_t written = 0;
526 uint8_t *ptr = output;
527 const char *msg;
528 #ifdef TRUNNEL_CHECK_ENCODED_LEN
529 const ssize_t encoded_len = ed25519_cert_extension_encoded_len(obj);
530 #endif
532 uint8_t *backptr_ext_length = NULL;
534 if (NULL != (msg = ed25519_cert_extension_check(obj)))
535 goto check_failed;
537 #ifdef TRUNNEL_CHECK_ENCODED_LEN
538 trunnel_assert(encoded_len >= 0);
539 #endif
541 /* Encode u16 ext_length */
542 backptr_ext_length = ptr;
543 trunnel_assert(written <= avail);
544 if (avail - written < 2)
545 goto truncated;
546 trunnel_set_uint16(ptr, trunnel_htons(obj->ext_length));
547 written += 2; ptr += 2;
549 /* Encode u8 ext_type */
550 trunnel_assert(written <= avail);
551 if (avail - written < 1)
552 goto truncated;
553 trunnel_set_uint8(ptr, (obj->ext_type));
554 written += 1; ptr += 1;
556 /* Encode u8 ext_flags */
557 trunnel_assert(written <= avail);
558 if (avail - written < 1)
559 goto truncated;
560 trunnel_set_uint8(ptr, (obj->ext_flags));
561 written += 1; ptr += 1;
563 size_t written_before_union = written;
565 /* Encode union un[ext_type] */
566 trunnel_assert(written <= avail);
567 switch (obj->ext_type) {
569 case CERTEXT_SIGNED_WITH_KEY:
571 /* Encode u8 un_signing_key[32] */
572 trunnel_assert(written <= avail);
573 if (avail - written < 32)
574 goto truncated;
575 memcpy(ptr, obj->un_signing_key, 32);
576 written += 32; ptr += 32;
577 break;
579 default:
581 /* Encode u8 un_unparsed[] */
583 size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->un_unparsed);
584 trunnel_assert(written <= avail);
585 if (avail - written < elt_len)
586 goto truncated;
587 if (elt_len)
588 memcpy(ptr, obj->un_unparsed.elts_, elt_len);
589 written += elt_len; ptr += elt_len;
591 break;
593 /* Write the length field back to ext_length */
594 trunnel_assert(written >= written_before_union);
595 #if UINT16_MAX < SIZE_MAX
596 if (written - written_before_union > UINT16_MAX)
597 goto check_failed;
598 #endif
599 trunnel_set_uint16(backptr_ext_length, trunnel_htons(written - written_before_union));
603 trunnel_assert(ptr == output + written);
604 #ifdef TRUNNEL_CHECK_ENCODED_LEN
606 trunnel_assert(encoded_len >= 0);
607 trunnel_assert((size_t)encoded_len == written);
610 #endif
612 return written;
614 truncated:
615 result = -2;
616 goto fail;
617 check_failed:
618 (void)msg;
619 result = -1;
620 goto fail;
621 fail:
622 trunnel_assert(result < 0);
623 return result;
626 /** As ed25519_cert_extension_parse(), but do not allocate the output
627 * object.
629 static ssize_t
630 ed25519_cert_extension_parse_into(ed25519_cert_extension_t *obj, const uint8_t *input, const size_t len_in)
632 const uint8_t *ptr = input;
633 size_t remaining = len_in;
634 ssize_t result = 0;
635 (void)result;
637 /* Parse u16 ext_length */
638 CHECK_REMAINING(2, truncated);
639 obj->ext_length = trunnel_ntohs(trunnel_get_uint16(ptr));
640 remaining -= 2; ptr += 2;
642 /* Parse u8 ext_type */
643 CHECK_REMAINING(1, truncated);
644 obj->ext_type = (trunnel_get_uint8(ptr));
645 remaining -= 1; ptr += 1;
647 /* Parse u8 ext_flags */
648 CHECK_REMAINING(1, truncated);
649 obj->ext_flags = (trunnel_get_uint8(ptr));
650 remaining -= 1; ptr += 1;
652 size_t remaining_after;
653 CHECK_REMAINING(obj->ext_length, truncated);
654 remaining_after = remaining - obj->ext_length;
655 remaining = obj->ext_length;
657 /* Parse union un[ext_type] */
658 switch (obj->ext_type) {
660 case CERTEXT_SIGNED_WITH_KEY:
662 /* Parse u8 un_signing_key[32] */
663 CHECK_REMAINING(32, fail);
664 memcpy(obj->un_signing_key, ptr, 32);
665 remaining -= 32; ptr += 32;
666 break;
668 default:
670 /* Parse u8 un_unparsed[] */
671 TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->un_unparsed, remaining, {});
672 obj->un_unparsed.n_ = remaining;
673 if (remaining)
674 memcpy(obj->un_unparsed.elts_, ptr, remaining);
675 ptr += remaining; remaining -= remaining;
676 break;
678 if (remaining != 0)
679 goto fail;
680 remaining = remaining_after;
682 trunnel_assert(ptr + remaining == input + len_in);
683 return len_in - remaining;
685 truncated:
686 return -2;
687 trunnel_alloc_failed:
688 return -1;
689 fail:
690 result = -1;
691 return result;
694 ssize_t
695 ed25519_cert_extension_parse(ed25519_cert_extension_t **output, const uint8_t *input, const size_t len_in)
697 ssize_t result;
698 *output = ed25519_cert_extension_new();
699 if (NULL == *output)
700 return -1;
701 result = ed25519_cert_extension_parse_into(*output, input, len_in);
702 if (result < 0) {
703 ed25519_cert_extension_free(*output);
704 *output = NULL;
706 return result;
708 extend1_cell_body_t *
709 extend1_cell_body_new(void)
711 extend1_cell_body_t *val = trunnel_calloc(1, sizeof(extend1_cell_body_t));
712 if (NULL == val)
713 return NULL;
714 return val;
717 /** Release all storage held inside 'obj', but do not free 'obj'.
719 static void
720 extend1_cell_body_clear(extend1_cell_body_t *obj)
722 (void) obj;
725 void
726 extend1_cell_body_free(extend1_cell_body_t *obj)
728 if (obj == NULL)
729 return;
730 extend1_cell_body_clear(obj);
731 trunnel_memwipe(obj, sizeof(extend1_cell_body_t));
732 trunnel_free_(obj);
735 uint32_t
736 extend1_cell_body_get_ipv4addr(const extend1_cell_body_t *inp)
738 return inp->ipv4addr;
741 extend1_cell_body_set_ipv4addr(extend1_cell_body_t *inp, uint32_t val)
743 inp->ipv4addr = val;
744 return 0;
746 uint16_t
747 extend1_cell_body_get_port(const extend1_cell_body_t *inp)
749 return inp->port;
752 extend1_cell_body_set_port(extend1_cell_body_t *inp, uint16_t val)
754 inp->port = val;
755 return 0;
757 size_t
758 extend1_cell_body_getlen_onionskin(const extend1_cell_body_t *inp)
760 (void)inp; return 186;
763 uint8_t
764 extend1_cell_body_get_onionskin(extend1_cell_body_t *inp, size_t idx)
766 trunnel_assert(idx < 186);
767 return inp->onionskin[idx];
770 uint8_t
771 extend1_cell_body_getconst_onionskin(const extend1_cell_body_t *inp, size_t idx)
773 return extend1_cell_body_get_onionskin((extend1_cell_body_t*)inp, idx);
776 extend1_cell_body_set_onionskin(extend1_cell_body_t *inp, size_t idx, uint8_t elt)
778 trunnel_assert(idx < 186);
779 inp->onionskin[idx] = elt;
780 return 0;
783 uint8_t *
784 extend1_cell_body_getarray_onionskin(extend1_cell_body_t *inp)
786 return inp->onionskin;
788 const uint8_t *
789 extend1_cell_body_getconstarray_onionskin(const extend1_cell_body_t *inp)
791 return (const uint8_t *)extend1_cell_body_getarray_onionskin((extend1_cell_body_t*)inp);
793 size_t
794 extend1_cell_body_getlen_identity(const extend1_cell_body_t *inp)
796 (void)inp; return 20;
799 uint8_t
800 extend1_cell_body_get_identity(extend1_cell_body_t *inp, size_t idx)
802 trunnel_assert(idx < 20);
803 return inp->identity[idx];
806 uint8_t
807 extend1_cell_body_getconst_identity(const extend1_cell_body_t *inp, size_t idx)
809 return extend1_cell_body_get_identity((extend1_cell_body_t*)inp, idx);
812 extend1_cell_body_set_identity(extend1_cell_body_t *inp, size_t idx, uint8_t elt)
814 trunnel_assert(idx < 20);
815 inp->identity[idx] = elt;
816 return 0;
819 uint8_t *
820 extend1_cell_body_getarray_identity(extend1_cell_body_t *inp)
822 return inp->identity;
824 const uint8_t *
825 extend1_cell_body_getconstarray_identity(const extend1_cell_body_t *inp)
827 return (const uint8_t *)extend1_cell_body_getarray_identity((extend1_cell_body_t*)inp);
829 const char *
830 extend1_cell_body_check(const extend1_cell_body_t *obj)
832 if (obj == NULL)
833 return "Object was NULL";
834 if (obj->trunnel_error_code_)
835 return "A set function failed on this object";
836 return NULL;
839 ssize_t
840 extend1_cell_body_encoded_len(const extend1_cell_body_t *obj)
842 ssize_t result = 0;
844 if (NULL != extend1_cell_body_check(obj))
845 return -1;
848 /* Length of u32 ipv4addr */
849 result += 4;
851 /* Length of u16 port */
852 result += 2;
854 /* Length of u8 onionskin[186] */
855 result += 186;
857 /* Length of u8 identity[20] */
858 result += 20;
859 return result;
862 extend1_cell_body_clear_errors(extend1_cell_body_t *obj)
864 int r = obj->trunnel_error_code_;
865 obj->trunnel_error_code_ = 0;
866 return r;
868 ssize_t
869 extend1_cell_body_encode(uint8_t *output, const size_t avail, const extend1_cell_body_t *obj)
871 ssize_t result = 0;
872 size_t written = 0;
873 uint8_t *ptr = output;
874 const char *msg;
875 #ifdef TRUNNEL_CHECK_ENCODED_LEN
876 const ssize_t encoded_len = extend1_cell_body_encoded_len(obj);
877 #endif
879 if (NULL != (msg = extend1_cell_body_check(obj)))
880 goto check_failed;
882 #ifdef TRUNNEL_CHECK_ENCODED_LEN
883 trunnel_assert(encoded_len >= 0);
884 #endif
886 /* Encode u32 ipv4addr */
887 trunnel_assert(written <= avail);
888 if (avail - written < 4)
889 goto truncated;
890 trunnel_set_uint32(ptr, trunnel_htonl(obj->ipv4addr));
891 written += 4; ptr += 4;
893 /* Encode u16 port */
894 trunnel_assert(written <= avail);
895 if (avail - written < 2)
896 goto truncated;
897 trunnel_set_uint16(ptr, trunnel_htons(obj->port));
898 written += 2; ptr += 2;
900 /* Encode u8 onionskin[186] */
901 trunnel_assert(written <= avail);
902 if (avail - written < 186)
903 goto truncated;
904 memcpy(ptr, obj->onionskin, 186);
905 written += 186; ptr += 186;
907 /* Encode u8 identity[20] */
908 trunnel_assert(written <= avail);
909 if (avail - written < 20)
910 goto truncated;
911 memcpy(ptr, obj->identity, 20);
912 written += 20; ptr += 20;
915 trunnel_assert(ptr == output + written);
916 #ifdef TRUNNEL_CHECK_ENCODED_LEN
918 trunnel_assert(encoded_len >= 0);
919 trunnel_assert((size_t)encoded_len == written);
922 #endif
924 return written;
926 truncated:
927 result = -2;
928 goto fail;
929 check_failed:
930 (void)msg;
931 result = -1;
932 goto fail;
933 fail:
934 trunnel_assert(result < 0);
935 return result;
938 /** As extend1_cell_body_parse(), but do not allocate the output
939 * object.
941 static ssize_t
942 extend1_cell_body_parse_into(extend1_cell_body_t *obj, const uint8_t *input, const size_t len_in)
944 const uint8_t *ptr = input;
945 size_t remaining = len_in;
946 ssize_t result = 0;
947 (void)result;
949 /* Parse u32 ipv4addr */
950 CHECK_REMAINING(4, truncated);
951 obj->ipv4addr = trunnel_ntohl(trunnel_get_uint32(ptr));
952 remaining -= 4; ptr += 4;
954 /* Parse u16 port */
955 CHECK_REMAINING(2, truncated);
956 obj->port = trunnel_ntohs(trunnel_get_uint16(ptr));
957 remaining -= 2; ptr += 2;
959 /* Parse u8 onionskin[186] */
960 CHECK_REMAINING(186, truncated);
961 memcpy(obj->onionskin, ptr, 186);
962 remaining -= 186; ptr += 186;
964 /* Parse u8 identity[20] */
965 CHECK_REMAINING(20, truncated);
966 memcpy(obj->identity, ptr, 20);
967 remaining -= 20; ptr += 20;
968 trunnel_assert(ptr + remaining == input + len_in);
969 return len_in - remaining;
971 truncated:
972 return -2;
975 ssize_t
976 extend1_cell_body_parse(extend1_cell_body_t **output, const uint8_t *input, const size_t len_in)
978 ssize_t result;
979 *output = extend1_cell_body_new();
980 if (NULL == *output)
981 return -1;
982 result = extend1_cell_body_parse_into(*output, input, len_in);
983 if (result < 0) {
984 extend1_cell_body_free(*output);
985 *output = NULL;
987 return result;
989 link_specifier_t *
990 link_specifier_new(void)
992 link_specifier_t *val = trunnel_calloc(1, sizeof(link_specifier_t));
993 if (NULL == val)
994 return NULL;
995 return val;
998 /** Release all storage held inside 'obj', but do not free 'obj'.
1000 static void
1001 link_specifier_clear(link_specifier_t *obj)
1003 (void) obj;
1004 TRUNNEL_DYNARRAY_WIPE(&obj->un_unrecognized);
1005 TRUNNEL_DYNARRAY_CLEAR(&obj->un_unrecognized);
1008 void
1009 link_specifier_free(link_specifier_t *obj)
1011 if (obj == NULL)
1012 return;
1013 link_specifier_clear(obj);
1014 trunnel_memwipe(obj, sizeof(link_specifier_t));
1015 trunnel_free_(obj);
1018 uint8_t
1019 link_specifier_get_ls_type(const link_specifier_t *inp)
1021 return inp->ls_type;
1024 link_specifier_set_ls_type(link_specifier_t *inp, uint8_t val)
1026 inp->ls_type = val;
1027 return 0;
1029 uint8_t
1030 link_specifier_get_ls_len(const link_specifier_t *inp)
1032 return inp->ls_len;
1035 link_specifier_set_ls_len(link_specifier_t *inp, uint8_t val)
1037 inp->ls_len = val;
1038 return 0;
1040 uint32_t
1041 link_specifier_get_un_ipv4_addr(const link_specifier_t *inp)
1043 return inp->un_ipv4_addr;
1046 link_specifier_set_un_ipv4_addr(link_specifier_t *inp, uint32_t val)
1048 inp->un_ipv4_addr = val;
1049 return 0;
1051 uint16_t
1052 link_specifier_get_un_ipv4_port(const link_specifier_t *inp)
1054 return inp->un_ipv4_port;
1057 link_specifier_set_un_ipv4_port(link_specifier_t *inp, uint16_t val)
1059 inp->un_ipv4_port = val;
1060 return 0;
1062 size_t
1063 link_specifier_getlen_un_ipv6_addr(const link_specifier_t *inp)
1065 (void)inp; return 16;
1068 uint8_t
1069 link_specifier_get_un_ipv6_addr(link_specifier_t *inp, size_t idx)
1071 trunnel_assert(idx < 16);
1072 return inp->un_ipv6_addr[idx];
1075 uint8_t
1076 link_specifier_getconst_un_ipv6_addr(const link_specifier_t *inp, size_t idx)
1078 return link_specifier_get_un_ipv6_addr((link_specifier_t*)inp, idx);
1081 link_specifier_set_un_ipv6_addr(link_specifier_t *inp, size_t idx, uint8_t elt)
1083 trunnel_assert(idx < 16);
1084 inp->un_ipv6_addr[idx] = elt;
1085 return 0;
1088 uint8_t *
1089 link_specifier_getarray_un_ipv6_addr(link_specifier_t *inp)
1091 return inp->un_ipv6_addr;
1093 const uint8_t *
1094 link_specifier_getconstarray_un_ipv6_addr(const link_specifier_t *inp)
1096 return (const uint8_t *)link_specifier_getarray_un_ipv6_addr((link_specifier_t*)inp);
1098 uint16_t
1099 link_specifier_get_un_ipv6_port(const link_specifier_t *inp)
1101 return inp->un_ipv6_port;
1104 link_specifier_set_un_ipv6_port(link_specifier_t *inp, uint16_t val)
1106 inp->un_ipv6_port = val;
1107 return 0;
1109 size_t
1110 link_specifier_getlen_un_legacy_id(const link_specifier_t *inp)
1112 (void)inp; return 20;
1115 uint8_t
1116 link_specifier_get_un_legacy_id(link_specifier_t *inp, size_t idx)
1118 trunnel_assert(idx < 20);
1119 return inp->un_legacy_id[idx];
1122 uint8_t
1123 link_specifier_getconst_un_legacy_id(const link_specifier_t *inp, size_t idx)
1125 return link_specifier_get_un_legacy_id((link_specifier_t*)inp, idx);
1128 link_specifier_set_un_legacy_id(link_specifier_t *inp, size_t idx, uint8_t elt)
1130 trunnel_assert(idx < 20);
1131 inp->un_legacy_id[idx] = elt;
1132 return 0;
1135 uint8_t *
1136 link_specifier_getarray_un_legacy_id(link_specifier_t *inp)
1138 return inp->un_legacy_id;
1140 const uint8_t *
1141 link_specifier_getconstarray_un_legacy_id(const link_specifier_t *inp)
1143 return (const uint8_t *)link_specifier_getarray_un_legacy_id((link_specifier_t*)inp);
1145 size_t
1146 link_specifier_getlen_un_ed25519_id(const link_specifier_t *inp)
1148 (void)inp; return 32;
1151 uint8_t
1152 link_specifier_get_un_ed25519_id(link_specifier_t *inp, size_t idx)
1154 trunnel_assert(idx < 32);
1155 return inp->un_ed25519_id[idx];
1158 uint8_t
1159 link_specifier_getconst_un_ed25519_id(const link_specifier_t *inp, size_t idx)
1161 return link_specifier_get_un_ed25519_id((link_specifier_t*)inp, idx);
1164 link_specifier_set_un_ed25519_id(link_specifier_t *inp, size_t idx, uint8_t elt)
1166 trunnel_assert(idx < 32);
1167 inp->un_ed25519_id[idx] = elt;
1168 return 0;
1171 uint8_t *
1172 link_specifier_getarray_un_ed25519_id(link_specifier_t *inp)
1174 return inp->un_ed25519_id;
1176 const uint8_t *
1177 link_specifier_getconstarray_un_ed25519_id(const link_specifier_t *inp)
1179 return (const uint8_t *)link_specifier_getarray_un_ed25519_id((link_specifier_t*)inp);
1181 size_t
1182 link_specifier_getlen_un_unrecognized(const link_specifier_t *inp)
1184 return TRUNNEL_DYNARRAY_LEN(&inp->un_unrecognized);
1187 uint8_t
1188 link_specifier_get_un_unrecognized(link_specifier_t *inp, size_t idx)
1190 return TRUNNEL_DYNARRAY_GET(&inp->un_unrecognized, idx);
1193 uint8_t
1194 link_specifier_getconst_un_unrecognized(const link_specifier_t *inp, size_t idx)
1196 return link_specifier_get_un_unrecognized((link_specifier_t*)inp, idx);
1199 link_specifier_set_un_unrecognized(link_specifier_t *inp, size_t idx, uint8_t elt)
1201 TRUNNEL_DYNARRAY_SET(&inp->un_unrecognized, idx, elt);
1202 return 0;
1205 link_specifier_add_un_unrecognized(link_specifier_t *inp, uint8_t elt)
1207 TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->un_unrecognized, elt, {});
1208 return 0;
1209 trunnel_alloc_failed:
1210 TRUNNEL_SET_ERROR_CODE(inp);
1211 return -1;
1214 uint8_t *
1215 link_specifier_getarray_un_unrecognized(link_specifier_t *inp)
1217 return inp->un_unrecognized.elts_;
1219 const uint8_t *
1220 link_specifier_getconstarray_un_unrecognized(const link_specifier_t *inp)
1222 return (const uint8_t *)link_specifier_getarray_un_unrecognized((link_specifier_t*)inp);
1225 link_specifier_setlen_un_unrecognized(link_specifier_t *inp, size_t newlen)
1227 uint8_t *newptr;
1228 newptr = trunnel_dynarray_setlen(&inp->un_unrecognized.allocated_,
1229 &inp->un_unrecognized.n_, inp->un_unrecognized.elts_, newlen,
1230 sizeof(inp->un_unrecognized.elts_[0]), (trunnel_free_fn_t) NULL,
1231 &inp->trunnel_error_code_);
1232 if (newlen != 0 && newptr == NULL)
1233 goto trunnel_alloc_failed;
1234 inp->un_unrecognized.elts_ = newptr;
1235 return 0;
1236 trunnel_alloc_failed:
1237 TRUNNEL_SET_ERROR_CODE(inp);
1238 return -1;
1240 const char *
1241 link_specifier_check(const link_specifier_t *obj)
1243 if (obj == NULL)
1244 return "Object was NULL";
1245 if (obj->trunnel_error_code_)
1246 return "A set function failed on this object";
1247 switch (obj->ls_type) {
1249 case LS_IPV4:
1250 break;
1252 case LS_IPV6:
1253 break;
1255 case LS_LEGACY_ID:
1256 break;
1258 case LS_ED25519_ID:
1259 break;
1261 default:
1262 break;
1264 return NULL;
1267 ssize_t
1268 link_specifier_encoded_len(const link_specifier_t *obj)
1270 ssize_t result = 0;
1272 if (NULL != link_specifier_check(obj))
1273 return -1;
1276 /* Length of u8 ls_type */
1277 result += 1;
1279 /* Length of u8 ls_len */
1280 result += 1;
1281 switch (obj->ls_type) {
1283 case LS_IPV4:
1285 /* Length of u32 un_ipv4_addr */
1286 result += 4;
1288 /* Length of u16 un_ipv4_port */
1289 result += 2;
1290 break;
1292 case LS_IPV6:
1294 /* Length of u8 un_ipv6_addr[16] */
1295 result += 16;
1297 /* Length of u16 un_ipv6_port */
1298 result += 2;
1299 break;
1301 case LS_LEGACY_ID:
1303 /* Length of u8 un_legacy_id[20] */
1304 result += 20;
1305 break;
1307 case LS_ED25519_ID:
1309 /* Length of u8 un_ed25519_id[32] */
1310 result += 32;
1311 break;
1313 default:
1315 /* Length of u8 un_unrecognized[] */
1316 result += TRUNNEL_DYNARRAY_LEN(&obj->un_unrecognized);
1317 break;
1319 return result;
1322 link_specifier_clear_errors(link_specifier_t *obj)
1324 int r = obj->trunnel_error_code_;
1325 obj->trunnel_error_code_ = 0;
1326 return r;
1328 ssize_t
1329 link_specifier_encode(uint8_t *output, const size_t avail, const link_specifier_t *obj)
1331 ssize_t result = 0;
1332 size_t written = 0;
1333 uint8_t *ptr = output;
1334 const char *msg;
1335 #ifdef TRUNNEL_CHECK_ENCODED_LEN
1336 const ssize_t encoded_len = link_specifier_encoded_len(obj);
1337 #endif
1339 uint8_t *backptr_ls_len = NULL;
1341 if (NULL != (msg = link_specifier_check(obj)))
1342 goto check_failed;
1344 #ifdef TRUNNEL_CHECK_ENCODED_LEN
1345 trunnel_assert(encoded_len >= 0);
1346 #endif
1348 /* Encode u8 ls_type */
1349 trunnel_assert(written <= avail);
1350 if (avail - written < 1)
1351 goto truncated;
1352 trunnel_set_uint8(ptr, (obj->ls_type));
1353 written += 1; ptr += 1;
1355 /* Encode u8 ls_len */
1356 backptr_ls_len = ptr;
1357 trunnel_assert(written <= avail);
1358 if (avail - written < 1)
1359 goto truncated;
1360 trunnel_set_uint8(ptr, (obj->ls_len));
1361 written += 1; ptr += 1;
1363 size_t written_before_union = written;
1365 /* Encode union un[ls_type] */
1366 trunnel_assert(written <= avail);
1367 switch (obj->ls_type) {
1369 case LS_IPV4:
1371 /* Encode u32 un_ipv4_addr */
1372 trunnel_assert(written <= avail);
1373 if (avail - written < 4)
1374 goto truncated;
1375 trunnel_set_uint32(ptr, trunnel_htonl(obj->un_ipv4_addr));
1376 written += 4; ptr += 4;
1378 /* Encode u16 un_ipv4_port */
1379 trunnel_assert(written <= avail);
1380 if (avail - written < 2)
1381 goto truncated;
1382 trunnel_set_uint16(ptr, trunnel_htons(obj->un_ipv4_port));
1383 written += 2; ptr += 2;
1384 break;
1386 case LS_IPV6:
1388 /* Encode u8 un_ipv6_addr[16] */
1389 trunnel_assert(written <= avail);
1390 if (avail - written < 16)
1391 goto truncated;
1392 memcpy(ptr, obj->un_ipv6_addr, 16);
1393 written += 16; ptr += 16;
1395 /* Encode u16 un_ipv6_port */
1396 trunnel_assert(written <= avail);
1397 if (avail - written < 2)
1398 goto truncated;
1399 trunnel_set_uint16(ptr, trunnel_htons(obj->un_ipv6_port));
1400 written += 2; ptr += 2;
1401 break;
1403 case LS_LEGACY_ID:
1405 /* Encode u8 un_legacy_id[20] */
1406 trunnel_assert(written <= avail);
1407 if (avail - written < 20)
1408 goto truncated;
1409 memcpy(ptr, obj->un_legacy_id, 20);
1410 written += 20; ptr += 20;
1411 break;
1413 case LS_ED25519_ID:
1415 /* Encode u8 un_ed25519_id[32] */
1416 trunnel_assert(written <= avail);
1417 if (avail - written < 32)
1418 goto truncated;
1419 memcpy(ptr, obj->un_ed25519_id, 32);
1420 written += 32; ptr += 32;
1421 break;
1423 default:
1425 /* Encode u8 un_unrecognized[] */
1427 size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->un_unrecognized);
1428 trunnel_assert(written <= avail);
1429 if (avail - written < elt_len)
1430 goto truncated;
1431 if (elt_len)
1432 memcpy(ptr, obj->un_unrecognized.elts_, elt_len);
1433 written += elt_len; ptr += elt_len;
1435 break;
1437 /* Write the length field back to ls_len */
1438 trunnel_assert(written >= written_before_union);
1439 #if UINT8_MAX < SIZE_MAX
1440 if (written - written_before_union > UINT8_MAX)
1441 goto check_failed;
1442 #endif
1443 trunnel_set_uint8(backptr_ls_len, (written - written_before_union));
1447 trunnel_assert(ptr == output + written);
1448 #ifdef TRUNNEL_CHECK_ENCODED_LEN
1450 trunnel_assert(encoded_len >= 0);
1451 trunnel_assert((size_t)encoded_len == written);
1454 #endif
1456 return written;
1458 truncated:
1459 result = -2;
1460 goto fail;
1461 check_failed:
1462 (void)msg;
1463 result = -1;
1464 goto fail;
1465 fail:
1466 trunnel_assert(result < 0);
1467 return result;
1470 /** As link_specifier_parse(), but do not allocate the output object.
1472 static ssize_t
1473 link_specifier_parse_into(link_specifier_t *obj, const uint8_t *input, const size_t len_in)
1475 const uint8_t *ptr = input;
1476 size_t remaining = len_in;
1477 ssize_t result = 0;
1478 (void)result;
1480 /* Parse u8 ls_type */
1481 CHECK_REMAINING(1, truncated);
1482 obj->ls_type = (trunnel_get_uint8(ptr));
1483 remaining -= 1; ptr += 1;
1485 /* Parse u8 ls_len */
1486 CHECK_REMAINING(1, truncated);
1487 obj->ls_len = (trunnel_get_uint8(ptr));
1488 remaining -= 1; ptr += 1;
1490 size_t remaining_after;
1491 CHECK_REMAINING(obj->ls_len, truncated);
1492 remaining_after = remaining - obj->ls_len;
1493 remaining = obj->ls_len;
1495 /* Parse union un[ls_type] */
1496 switch (obj->ls_type) {
1498 case LS_IPV4:
1500 /* Parse u32 un_ipv4_addr */
1501 CHECK_REMAINING(4, fail);
1502 obj->un_ipv4_addr = trunnel_ntohl(trunnel_get_uint32(ptr));
1503 remaining -= 4; ptr += 4;
1505 /* Parse u16 un_ipv4_port */
1506 CHECK_REMAINING(2, fail);
1507 obj->un_ipv4_port = trunnel_ntohs(trunnel_get_uint16(ptr));
1508 remaining -= 2; ptr += 2;
1509 break;
1511 case LS_IPV6:
1513 /* Parse u8 un_ipv6_addr[16] */
1514 CHECK_REMAINING(16, fail);
1515 memcpy(obj->un_ipv6_addr, ptr, 16);
1516 remaining -= 16; ptr += 16;
1518 /* Parse u16 un_ipv6_port */
1519 CHECK_REMAINING(2, fail);
1520 obj->un_ipv6_port = trunnel_ntohs(trunnel_get_uint16(ptr));
1521 remaining -= 2; ptr += 2;
1522 break;
1524 case LS_LEGACY_ID:
1526 /* Parse u8 un_legacy_id[20] */
1527 CHECK_REMAINING(20, fail);
1528 memcpy(obj->un_legacy_id, ptr, 20);
1529 remaining -= 20; ptr += 20;
1530 break;
1532 case LS_ED25519_ID:
1534 /* Parse u8 un_ed25519_id[32] */
1535 CHECK_REMAINING(32, fail);
1536 memcpy(obj->un_ed25519_id, ptr, 32);
1537 remaining -= 32; ptr += 32;
1538 break;
1540 default:
1542 /* Parse u8 un_unrecognized[] */
1543 TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->un_unrecognized, remaining, {});
1544 obj->un_unrecognized.n_ = remaining;
1545 if (remaining)
1546 memcpy(obj->un_unrecognized.elts_, ptr, remaining);
1547 ptr += remaining; remaining -= remaining;
1548 break;
1550 if (remaining != 0)
1551 goto fail;
1552 remaining = remaining_after;
1554 trunnel_assert(ptr + remaining == input + len_in);
1555 return len_in - remaining;
1557 truncated:
1558 return -2;
1559 trunnel_alloc_failed:
1560 return -1;
1561 fail:
1562 result = -1;
1563 return result;
1566 ssize_t
1567 link_specifier_parse(link_specifier_t **output, const uint8_t *input, const size_t len_in)
1569 ssize_t result;
1570 *output = link_specifier_new();
1571 if (NULL == *output)
1572 return -1;
1573 result = link_specifier_parse_into(*output, input, len_in);
1574 if (result < 0) {
1575 link_specifier_free(*output);
1576 *output = NULL;
1578 return result;
1580 ed25519_cert_t *
1581 ed25519_cert_new(void)
1583 ed25519_cert_t *val = trunnel_calloc(1, sizeof(ed25519_cert_t));
1584 if (NULL == val)
1585 return NULL;
1586 val->version = 1;
1587 return val;
1590 /** Release all storage held inside 'obj', but do not free 'obj'.
1592 static void
1593 ed25519_cert_clear(ed25519_cert_t *obj)
1595 (void) obj;
1598 unsigned idx;
1599 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
1600 ed25519_cert_extension_free(TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
1603 TRUNNEL_DYNARRAY_WIPE(&obj->ext);
1604 TRUNNEL_DYNARRAY_CLEAR(&obj->ext);
1607 void
1608 ed25519_cert_free(ed25519_cert_t *obj)
1610 if (obj == NULL)
1611 return;
1612 ed25519_cert_clear(obj);
1613 trunnel_memwipe(obj, sizeof(ed25519_cert_t));
1614 trunnel_free_(obj);
1617 uint8_t
1618 ed25519_cert_get_version(const ed25519_cert_t *inp)
1620 return inp->version;
1623 ed25519_cert_set_version(ed25519_cert_t *inp, uint8_t val)
1625 if (! ((val == 1))) {
1626 TRUNNEL_SET_ERROR_CODE(inp);
1627 return -1;
1629 inp->version = val;
1630 return 0;
1632 uint8_t
1633 ed25519_cert_get_cert_type(const ed25519_cert_t *inp)
1635 return inp->cert_type;
1638 ed25519_cert_set_cert_type(ed25519_cert_t *inp, uint8_t val)
1640 inp->cert_type = val;
1641 return 0;
1643 uint32_t
1644 ed25519_cert_get_exp_field(const ed25519_cert_t *inp)
1646 return inp->exp_field;
1649 ed25519_cert_set_exp_field(ed25519_cert_t *inp, uint32_t val)
1651 inp->exp_field = val;
1652 return 0;
1654 uint8_t
1655 ed25519_cert_get_cert_key_type(const ed25519_cert_t *inp)
1657 return inp->cert_key_type;
1660 ed25519_cert_set_cert_key_type(ed25519_cert_t *inp, uint8_t val)
1662 inp->cert_key_type = val;
1663 return 0;
1665 size_t
1666 ed25519_cert_getlen_certified_key(const ed25519_cert_t *inp)
1668 (void)inp; return 32;
1671 uint8_t
1672 ed25519_cert_get_certified_key(ed25519_cert_t *inp, size_t idx)
1674 trunnel_assert(idx < 32);
1675 return inp->certified_key[idx];
1678 uint8_t
1679 ed25519_cert_getconst_certified_key(const ed25519_cert_t *inp, size_t idx)
1681 return ed25519_cert_get_certified_key((ed25519_cert_t*)inp, idx);
1684 ed25519_cert_set_certified_key(ed25519_cert_t *inp, size_t idx, uint8_t elt)
1686 trunnel_assert(idx < 32);
1687 inp->certified_key[idx] = elt;
1688 return 0;
1691 uint8_t *
1692 ed25519_cert_getarray_certified_key(ed25519_cert_t *inp)
1694 return inp->certified_key;
1696 const uint8_t *
1697 ed25519_cert_getconstarray_certified_key(const ed25519_cert_t *inp)
1699 return (const uint8_t *)ed25519_cert_getarray_certified_key((ed25519_cert_t*)inp);
1701 uint8_t
1702 ed25519_cert_get_n_extensions(const ed25519_cert_t *inp)
1704 return inp->n_extensions;
1707 ed25519_cert_set_n_extensions(ed25519_cert_t *inp, uint8_t val)
1709 inp->n_extensions = val;
1710 return 0;
1712 size_t
1713 ed25519_cert_getlen_ext(const ed25519_cert_t *inp)
1715 return TRUNNEL_DYNARRAY_LEN(&inp->ext);
1718 struct ed25519_cert_extension_st *
1719 ed25519_cert_get_ext(ed25519_cert_t *inp, size_t idx)
1721 return TRUNNEL_DYNARRAY_GET(&inp->ext, idx);
1724 const struct ed25519_cert_extension_st *
1725 ed25519_cert_getconst_ext(const ed25519_cert_t *inp, size_t idx)
1727 return ed25519_cert_get_ext((ed25519_cert_t*)inp, idx);
1730 ed25519_cert_set_ext(ed25519_cert_t *inp, size_t idx, struct ed25519_cert_extension_st * elt)
1732 ed25519_cert_extension_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->ext, idx);
1733 if (oldval && oldval != elt)
1734 ed25519_cert_extension_free(oldval);
1735 return ed25519_cert_set0_ext(inp, idx, elt);
1738 ed25519_cert_set0_ext(ed25519_cert_t *inp, size_t idx, struct ed25519_cert_extension_st * elt)
1740 TRUNNEL_DYNARRAY_SET(&inp->ext, idx, elt);
1741 return 0;
1744 ed25519_cert_add_ext(ed25519_cert_t *inp, struct ed25519_cert_extension_st * elt)
1746 #if SIZE_MAX >= UINT8_MAX
1747 if (inp->ext.n_ == UINT8_MAX)
1748 goto trunnel_alloc_failed;
1749 #endif
1750 TRUNNEL_DYNARRAY_ADD(struct ed25519_cert_extension_st *, &inp->ext, elt, {});
1751 return 0;
1752 trunnel_alloc_failed:
1753 TRUNNEL_SET_ERROR_CODE(inp);
1754 return -1;
1757 struct ed25519_cert_extension_st * *
1758 ed25519_cert_getarray_ext(ed25519_cert_t *inp)
1760 return inp->ext.elts_;
1762 const struct ed25519_cert_extension_st * const *
1763 ed25519_cert_getconstarray_ext(const ed25519_cert_t *inp)
1765 return (const struct ed25519_cert_extension_st * const *)ed25519_cert_getarray_ext((ed25519_cert_t*)inp);
1768 ed25519_cert_setlen_ext(ed25519_cert_t *inp, size_t newlen)
1770 struct ed25519_cert_extension_st * *newptr;
1771 #if UINT8_MAX < SIZE_MAX
1772 if (newlen > UINT8_MAX)
1773 goto trunnel_alloc_failed;
1774 #endif
1775 newptr = trunnel_dynarray_setlen(&inp->ext.allocated_,
1776 &inp->ext.n_, inp->ext.elts_, newlen,
1777 sizeof(inp->ext.elts_[0]), (trunnel_free_fn_t) ed25519_cert_extension_free,
1778 &inp->trunnel_error_code_);
1779 if (newlen != 0 && newptr == NULL)
1780 goto trunnel_alloc_failed;
1781 inp->ext.elts_ = newptr;
1782 return 0;
1783 trunnel_alloc_failed:
1784 TRUNNEL_SET_ERROR_CODE(inp);
1785 return -1;
1787 size_t
1788 ed25519_cert_getlen_signature(const ed25519_cert_t *inp)
1790 (void)inp; return 64;
1793 uint8_t
1794 ed25519_cert_get_signature(ed25519_cert_t *inp, size_t idx)
1796 trunnel_assert(idx < 64);
1797 return inp->signature[idx];
1800 uint8_t
1801 ed25519_cert_getconst_signature(const ed25519_cert_t *inp, size_t idx)
1803 return ed25519_cert_get_signature((ed25519_cert_t*)inp, idx);
1806 ed25519_cert_set_signature(ed25519_cert_t *inp, size_t idx, uint8_t elt)
1808 trunnel_assert(idx < 64);
1809 inp->signature[idx] = elt;
1810 return 0;
1813 uint8_t *
1814 ed25519_cert_getarray_signature(ed25519_cert_t *inp)
1816 return inp->signature;
1818 const uint8_t *
1819 ed25519_cert_getconstarray_signature(const ed25519_cert_t *inp)
1821 return (const uint8_t *)ed25519_cert_getarray_signature((ed25519_cert_t*)inp);
1823 const char *
1824 ed25519_cert_check(const ed25519_cert_t *obj)
1826 if (obj == NULL)
1827 return "Object was NULL";
1828 if (obj->trunnel_error_code_)
1829 return "A set function failed on this object";
1830 if (! (obj->version == 1))
1831 return "Integer out of bounds";
1833 const char *msg;
1835 unsigned idx;
1836 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
1837 if (NULL != (msg = ed25519_cert_extension_check(TRUNNEL_DYNARRAY_GET(&obj->ext, idx))))
1838 return msg;
1841 if (TRUNNEL_DYNARRAY_LEN(&obj->ext) != obj->n_extensions)
1842 return "Length mismatch for ext";
1843 return NULL;
1846 ssize_t
1847 ed25519_cert_encoded_len(const ed25519_cert_t *obj)
1849 ssize_t result = 0;
1851 if (NULL != ed25519_cert_check(obj))
1852 return -1;
1855 /* Length of u8 version IN [1] */
1856 result += 1;
1858 /* Length of u8 cert_type */
1859 result += 1;
1861 /* Length of u32 exp_field */
1862 result += 4;
1864 /* Length of u8 cert_key_type */
1865 result += 1;
1867 /* Length of u8 certified_key[32] */
1868 result += 32;
1870 /* Length of u8 n_extensions */
1871 result += 1;
1873 /* Length of struct ed25519_cert_extension ext[n_extensions] */
1876 unsigned idx;
1877 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
1878 result += ed25519_cert_extension_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
1882 /* Length of u8 signature[64] */
1883 result += 64;
1884 return result;
1887 ed25519_cert_clear_errors(ed25519_cert_t *obj)
1889 int r = obj->trunnel_error_code_;
1890 obj->trunnel_error_code_ = 0;
1891 return r;
1893 ssize_t
1894 ed25519_cert_encode(uint8_t *output, const size_t avail, const ed25519_cert_t *obj)
1896 ssize_t result = 0;
1897 size_t written = 0;
1898 uint8_t *ptr = output;
1899 const char *msg;
1900 #ifdef TRUNNEL_CHECK_ENCODED_LEN
1901 const ssize_t encoded_len = ed25519_cert_encoded_len(obj);
1902 #endif
1904 if (NULL != (msg = ed25519_cert_check(obj)))
1905 goto check_failed;
1907 #ifdef TRUNNEL_CHECK_ENCODED_LEN
1908 trunnel_assert(encoded_len >= 0);
1909 #endif
1911 /* Encode u8 version IN [1] */
1912 trunnel_assert(written <= avail);
1913 if (avail - written < 1)
1914 goto truncated;
1915 trunnel_set_uint8(ptr, (obj->version));
1916 written += 1; ptr += 1;
1918 /* Encode u8 cert_type */
1919 trunnel_assert(written <= avail);
1920 if (avail - written < 1)
1921 goto truncated;
1922 trunnel_set_uint8(ptr, (obj->cert_type));
1923 written += 1; ptr += 1;
1925 /* Encode u32 exp_field */
1926 trunnel_assert(written <= avail);
1927 if (avail - written < 4)
1928 goto truncated;
1929 trunnel_set_uint32(ptr, trunnel_htonl(obj->exp_field));
1930 written += 4; ptr += 4;
1932 /* Encode u8 cert_key_type */
1933 trunnel_assert(written <= avail);
1934 if (avail - written < 1)
1935 goto truncated;
1936 trunnel_set_uint8(ptr, (obj->cert_key_type));
1937 written += 1; ptr += 1;
1939 /* Encode u8 certified_key[32] */
1940 trunnel_assert(written <= avail);
1941 if (avail - written < 32)
1942 goto truncated;
1943 memcpy(ptr, obj->certified_key, 32);
1944 written += 32; ptr += 32;
1946 /* Encode u8 n_extensions */
1947 trunnel_assert(written <= avail);
1948 if (avail - written < 1)
1949 goto truncated;
1950 trunnel_set_uint8(ptr, (obj->n_extensions));
1951 written += 1; ptr += 1;
1953 /* Encode struct ed25519_cert_extension ext[n_extensions] */
1956 unsigned idx;
1957 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
1958 trunnel_assert(written <= avail);
1959 result = ed25519_cert_extension_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
1960 if (result < 0)
1961 goto fail; /* XXXXXXX !*/
1962 written += result; ptr += result;
1966 /* Encode u8 signature[64] */
1967 trunnel_assert(written <= avail);
1968 if (avail - written < 64)
1969 goto truncated;
1970 memcpy(ptr, obj->signature, 64);
1971 written += 64; ptr += 64;
1974 trunnel_assert(ptr == output + written);
1975 #ifdef TRUNNEL_CHECK_ENCODED_LEN
1977 trunnel_assert(encoded_len >= 0);
1978 trunnel_assert((size_t)encoded_len == written);
1981 #endif
1983 return written;
1985 truncated:
1986 result = -2;
1987 goto fail;
1988 check_failed:
1989 (void)msg;
1990 result = -1;
1991 goto fail;
1992 fail:
1993 trunnel_assert(result < 0);
1994 return result;
1997 /** As ed25519_cert_parse(), but do not allocate the output object.
1999 static ssize_t
2000 ed25519_cert_parse_into(ed25519_cert_t *obj, const uint8_t *input, const size_t len_in)
2002 const uint8_t *ptr = input;
2003 size_t remaining = len_in;
2004 ssize_t result = 0;
2005 (void)result;
2007 /* Parse u8 version IN [1] */
2008 CHECK_REMAINING(1, truncated);
2009 obj->version = (trunnel_get_uint8(ptr));
2010 remaining -= 1; ptr += 1;
2011 if (! (obj->version == 1))
2012 goto fail;
2014 /* Parse u8 cert_type */
2015 CHECK_REMAINING(1, truncated);
2016 obj->cert_type = (trunnel_get_uint8(ptr));
2017 remaining -= 1; ptr += 1;
2019 /* Parse u32 exp_field */
2020 CHECK_REMAINING(4, truncated);
2021 obj->exp_field = trunnel_ntohl(trunnel_get_uint32(ptr));
2022 remaining -= 4; ptr += 4;
2024 /* Parse u8 cert_key_type */
2025 CHECK_REMAINING(1, truncated);
2026 obj->cert_key_type = (trunnel_get_uint8(ptr));
2027 remaining -= 1; ptr += 1;
2029 /* Parse u8 certified_key[32] */
2030 CHECK_REMAINING(32, truncated);
2031 memcpy(obj->certified_key, ptr, 32);
2032 remaining -= 32; ptr += 32;
2034 /* Parse u8 n_extensions */
2035 CHECK_REMAINING(1, truncated);
2036 obj->n_extensions = (trunnel_get_uint8(ptr));
2037 remaining -= 1; ptr += 1;
2039 /* Parse struct ed25519_cert_extension ext[n_extensions] */
2040 TRUNNEL_DYNARRAY_EXPAND(ed25519_cert_extension_t *, &obj->ext, obj->n_extensions, {});
2042 ed25519_cert_extension_t * elt;
2043 unsigned idx;
2044 for (idx = 0; idx < obj->n_extensions; ++idx) {
2045 result = ed25519_cert_extension_parse(&elt, ptr, remaining);
2046 if (result < 0)
2047 goto relay_fail;
2048 trunnel_assert((size_t)result <= remaining);
2049 remaining -= result; ptr += result;
2050 TRUNNEL_DYNARRAY_ADD(ed25519_cert_extension_t *, &obj->ext, elt, {ed25519_cert_extension_free(elt);});
2054 /* Parse u8 signature[64] */
2055 CHECK_REMAINING(64, truncated);
2056 memcpy(obj->signature, ptr, 64);
2057 remaining -= 64; ptr += 64;
2058 trunnel_assert(ptr + remaining == input + len_in);
2059 return len_in - remaining;
2061 truncated:
2062 return -2;
2063 relay_fail:
2064 trunnel_assert(result < 0);
2065 return result;
2066 trunnel_alloc_failed:
2067 return -1;
2068 fail:
2069 result = -1;
2070 return result;
2073 ssize_t
2074 ed25519_cert_parse(ed25519_cert_t **output, const uint8_t *input, const size_t len_in)
2076 ssize_t result;
2077 *output = ed25519_cert_new();
2078 if (NULL == *output)
2079 return -1;
2080 result = ed25519_cert_parse_into(*output, input, len_in);
2081 if (result < 0) {
2082 ed25519_cert_free(*output);
2083 *output = NULL;
2085 return result;
2087 extend2_cell_body_t *
2088 extend2_cell_body_new(void)
2090 extend2_cell_body_t *val = trunnel_calloc(1, sizeof(extend2_cell_body_t));
2091 if (NULL == val)
2092 return NULL;
2093 return val;
2096 /** Release all storage held inside 'obj', but do not free 'obj'.
2098 static void
2099 extend2_cell_body_clear(extend2_cell_body_t *obj)
2101 (void) obj;
2104 unsigned idx;
2105 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
2106 link_specifier_free(TRUNNEL_DYNARRAY_GET(&obj->ls, idx));
2109 TRUNNEL_DYNARRAY_WIPE(&obj->ls);
2110 TRUNNEL_DYNARRAY_CLEAR(&obj->ls);
2111 create2_cell_body_free(obj->create2);
2112 obj->create2 = NULL;
2115 void
2116 extend2_cell_body_free(extend2_cell_body_t *obj)
2118 if (obj == NULL)
2119 return;
2120 extend2_cell_body_clear(obj);
2121 trunnel_memwipe(obj, sizeof(extend2_cell_body_t));
2122 trunnel_free_(obj);
2125 uint8_t
2126 extend2_cell_body_get_n_spec(const extend2_cell_body_t *inp)
2128 return inp->n_spec;
2131 extend2_cell_body_set_n_spec(extend2_cell_body_t *inp, uint8_t val)
2133 inp->n_spec = val;
2134 return 0;
2136 size_t
2137 extend2_cell_body_getlen_ls(const extend2_cell_body_t *inp)
2139 return TRUNNEL_DYNARRAY_LEN(&inp->ls);
2142 struct link_specifier_st *
2143 extend2_cell_body_get_ls(extend2_cell_body_t *inp, size_t idx)
2145 return TRUNNEL_DYNARRAY_GET(&inp->ls, idx);
2148 const struct link_specifier_st *
2149 extend2_cell_body_getconst_ls(const extend2_cell_body_t *inp, size_t idx)
2151 return extend2_cell_body_get_ls((extend2_cell_body_t*)inp, idx);
2154 extend2_cell_body_set_ls(extend2_cell_body_t *inp, size_t idx, struct link_specifier_st * elt)
2156 link_specifier_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->ls, idx);
2157 if (oldval && oldval != elt)
2158 link_specifier_free(oldval);
2159 return extend2_cell_body_set0_ls(inp, idx, elt);
2162 extend2_cell_body_set0_ls(extend2_cell_body_t *inp, size_t idx, struct link_specifier_st * elt)
2164 TRUNNEL_DYNARRAY_SET(&inp->ls, idx, elt);
2165 return 0;
2168 extend2_cell_body_add_ls(extend2_cell_body_t *inp, struct link_specifier_st * elt)
2170 #if SIZE_MAX >= UINT8_MAX
2171 if (inp->ls.n_ == UINT8_MAX)
2172 goto trunnel_alloc_failed;
2173 #endif
2174 TRUNNEL_DYNARRAY_ADD(struct link_specifier_st *, &inp->ls, elt, {});
2175 return 0;
2176 trunnel_alloc_failed:
2177 TRUNNEL_SET_ERROR_CODE(inp);
2178 return -1;
2181 struct link_specifier_st * *
2182 extend2_cell_body_getarray_ls(extend2_cell_body_t *inp)
2184 return inp->ls.elts_;
2186 const struct link_specifier_st * const *
2187 extend2_cell_body_getconstarray_ls(const extend2_cell_body_t *inp)
2189 return (const struct link_specifier_st * const *)extend2_cell_body_getarray_ls((extend2_cell_body_t*)inp);
2192 extend2_cell_body_setlen_ls(extend2_cell_body_t *inp, size_t newlen)
2194 struct link_specifier_st * *newptr;
2195 #if UINT8_MAX < SIZE_MAX
2196 if (newlen > UINT8_MAX)
2197 goto trunnel_alloc_failed;
2198 #endif
2199 newptr = trunnel_dynarray_setlen(&inp->ls.allocated_,
2200 &inp->ls.n_, inp->ls.elts_, newlen,
2201 sizeof(inp->ls.elts_[0]), (trunnel_free_fn_t) link_specifier_free,
2202 &inp->trunnel_error_code_);
2203 if (newlen != 0 && newptr == NULL)
2204 goto trunnel_alloc_failed;
2205 inp->ls.elts_ = newptr;
2206 return 0;
2207 trunnel_alloc_failed:
2208 TRUNNEL_SET_ERROR_CODE(inp);
2209 return -1;
2211 struct create2_cell_body_st *
2212 extend2_cell_body_get_create2(extend2_cell_body_t *inp)
2214 return inp->create2;
2216 const struct create2_cell_body_st *
2217 extend2_cell_body_getconst_create2(const extend2_cell_body_t *inp)
2219 return extend2_cell_body_get_create2((extend2_cell_body_t*) inp);
2222 extend2_cell_body_set_create2(extend2_cell_body_t *inp, struct create2_cell_body_st *val)
2224 if (inp->create2 && inp->create2 != val)
2225 create2_cell_body_free(inp->create2);
2226 return extend2_cell_body_set0_create2(inp, val);
2229 extend2_cell_body_set0_create2(extend2_cell_body_t *inp, struct create2_cell_body_st *val)
2231 inp->create2 = val;
2232 return 0;
2234 const char *
2235 extend2_cell_body_check(const extend2_cell_body_t *obj)
2237 if (obj == NULL)
2238 return "Object was NULL";
2239 if (obj->trunnel_error_code_)
2240 return "A set function failed on this object";
2242 const char *msg;
2244 unsigned idx;
2245 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
2246 if (NULL != (msg = link_specifier_check(TRUNNEL_DYNARRAY_GET(&obj->ls, idx))))
2247 return msg;
2250 if (TRUNNEL_DYNARRAY_LEN(&obj->ls) != obj->n_spec)
2251 return "Length mismatch for ls";
2253 const char *msg;
2254 if (NULL != (msg = create2_cell_body_check(obj->create2)))
2255 return msg;
2257 return NULL;
2260 ssize_t
2261 extend2_cell_body_encoded_len(const extend2_cell_body_t *obj)
2263 ssize_t result = 0;
2265 if (NULL != extend2_cell_body_check(obj))
2266 return -1;
2269 /* Length of u8 n_spec */
2270 result += 1;
2272 /* Length of struct link_specifier ls[n_spec] */
2275 unsigned idx;
2276 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
2277 result += link_specifier_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->ls, idx));
2281 /* Length of struct create2_cell_body create2 */
2282 result += create2_cell_body_encoded_len(obj->create2);
2283 return result;
2286 extend2_cell_body_clear_errors(extend2_cell_body_t *obj)
2288 int r = obj->trunnel_error_code_;
2289 obj->trunnel_error_code_ = 0;
2290 return r;
2292 ssize_t
2293 extend2_cell_body_encode(uint8_t *output, const size_t avail, const extend2_cell_body_t *obj)
2295 ssize_t result = 0;
2296 size_t written = 0;
2297 uint8_t *ptr = output;
2298 const char *msg;
2299 #ifdef TRUNNEL_CHECK_ENCODED_LEN
2300 const ssize_t encoded_len = extend2_cell_body_encoded_len(obj);
2301 #endif
2303 if (NULL != (msg = extend2_cell_body_check(obj)))
2304 goto check_failed;
2306 #ifdef TRUNNEL_CHECK_ENCODED_LEN
2307 trunnel_assert(encoded_len >= 0);
2308 #endif
2310 /* Encode u8 n_spec */
2311 trunnel_assert(written <= avail);
2312 if (avail - written < 1)
2313 goto truncated;
2314 trunnel_set_uint8(ptr, (obj->n_spec));
2315 written += 1; ptr += 1;
2317 /* Encode struct link_specifier ls[n_spec] */
2320 unsigned idx;
2321 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
2322 trunnel_assert(written <= avail);
2323 result = link_specifier_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->ls, idx));
2324 if (result < 0)
2325 goto fail; /* XXXXXXX !*/
2326 written += result; ptr += result;
2330 /* Encode struct create2_cell_body create2 */
2331 trunnel_assert(written <= avail);
2332 result = create2_cell_body_encode(ptr, avail - written, obj->create2);
2333 if (result < 0)
2334 goto fail; /* XXXXXXX !*/
2335 written += result; ptr += result;
2338 trunnel_assert(ptr == output + written);
2339 #ifdef TRUNNEL_CHECK_ENCODED_LEN
2341 trunnel_assert(encoded_len >= 0);
2342 trunnel_assert((size_t)encoded_len == written);
2345 #endif
2347 return written;
2349 truncated:
2350 result = -2;
2351 goto fail;
2352 check_failed:
2353 (void)msg;
2354 result = -1;
2355 goto fail;
2356 fail:
2357 trunnel_assert(result < 0);
2358 return result;
2361 /** As extend2_cell_body_parse(), but do not allocate the output
2362 * object.
2364 static ssize_t
2365 extend2_cell_body_parse_into(extend2_cell_body_t *obj, const uint8_t *input, const size_t len_in)
2367 const uint8_t *ptr = input;
2368 size_t remaining = len_in;
2369 ssize_t result = 0;
2370 (void)result;
2372 /* Parse u8 n_spec */
2373 CHECK_REMAINING(1, truncated);
2374 obj->n_spec = (trunnel_get_uint8(ptr));
2375 remaining -= 1; ptr += 1;
2377 /* Parse struct link_specifier ls[n_spec] */
2378 TRUNNEL_DYNARRAY_EXPAND(link_specifier_t *, &obj->ls, obj->n_spec, {});
2380 link_specifier_t * elt;
2381 unsigned idx;
2382 for (idx = 0; idx < obj->n_spec; ++idx) {
2383 result = link_specifier_parse(&elt, ptr, remaining);
2384 if (result < 0)
2385 goto relay_fail;
2386 trunnel_assert((size_t)result <= remaining);
2387 remaining -= result; ptr += result;
2388 TRUNNEL_DYNARRAY_ADD(link_specifier_t *, &obj->ls, elt, {link_specifier_free(elt);});
2392 /* Parse struct create2_cell_body create2 */
2393 result = create2_cell_body_parse(&obj->create2, ptr, remaining);
2394 if (result < 0)
2395 goto relay_fail;
2396 trunnel_assert((size_t)result <= remaining);
2397 remaining -= result; ptr += result;
2398 trunnel_assert(ptr + remaining == input + len_in);
2399 return len_in - remaining;
2401 truncated:
2402 return -2;
2403 relay_fail:
2404 trunnel_assert(result < 0);
2405 return result;
2406 trunnel_alloc_failed:
2407 return -1;
2410 ssize_t
2411 extend2_cell_body_parse(extend2_cell_body_t **output, const uint8_t *input, const size_t len_in)
2413 ssize_t result;
2414 *output = extend2_cell_body_new();
2415 if (NULL == *output)
2416 return -1;
2417 result = extend2_cell_body_parse_into(*output, input, len_in);
2418 if (result < 0) {
2419 extend2_cell_body_free(*output);
2420 *output = NULL;
2422 return result;
2424 link_specifier_list_t *
2425 link_specifier_list_new(void)
2427 link_specifier_list_t *val = trunnel_calloc(1, sizeof(link_specifier_list_t));
2428 if (NULL == val)
2429 return NULL;
2430 return val;
2433 /** Release all storage held inside 'obj', but do not free 'obj'.
2435 static void
2436 link_specifier_list_clear(link_specifier_list_t *obj)
2438 (void) obj;
2441 unsigned idx;
2442 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
2443 link_specifier_free(TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
2446 TRUNNEL_DYNARRAY_WIPE(&obj->spec);
2447 TRUNNEL_DYNARRAY_CLEAR(&obj->spec);
2450 void
2451 link_specifier_list_free(link_specifier_list_t *obj)
2453 if (obj == NULL)
2454 return;
2455 link_specifier_list_clear(obj);
2456 trunnel_memwipe(obj, sizeof(link_specifier_list_t));
2457 trunnel_free_(obj);
2460 uint8_t
2461 link_specifier_list_get_n_spec(const link_specifier_list_t *inp)
2463 return inp->n_spec;
2466 link_specifier_list_set_n_spec(link_specifier_list_t *inp, uint8_t val)
2468 inp->n_spec = val;
2469 return 0;
2471 size_t
2472 link_specifier_list_getlen_spec(const link_specifier_list_t *inp)
2474 return TRUNNEL_DYNARRAY_LEN(&inp->spec);
2477 struct link_specifier_st *
2478 link_specifier_list_get_spec(link_specifier_list_t *inp, size_t idx)
2480 return TRUNNEL_DYNARRAY_GET(&inp->spec, idx);
2483 const struct link_specifier_st *
2484 link_specifier_list_getconst_spec(const link_specifier_list_t *inp, size_t idx)
2486 return link_specifier_list_get_spec((link_specifier_list_t*)inp, idx);
2489 link_specifier_list_set_spec(link_specifier_list_t *inp, size_t idx, struct link_specifier_st * elt)
2491 link_specifier_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->spec, idx);
2492 if (oldval && oldval != elt)
2493 link_specifier_free(oldval);
2494 return link_specifier_list_set0_spec(inp, idx, elt);
2497 link_specifier_list_set0_spec(link_specifier_list_t *inp, size_t idx, struct link_specifier_st * elt)
2499 TRUNNEL_DYNARRAY_SET(&inp->spec, idx, elt);
2500 return 0;
2503 link_specifier_list_add_spec(link_specifier_list_t *inp, struct link_specifier_st * elt)
2505 #if SIZE_MAX >= UINT8_MAX
2506 if (inp->spec.n_ == UINT8_MAX)
2507 goto trunnel_alloc_failed;
2508 #endif
2509 TRUNNEL_DYNARRAY_ADD(struct link_specifier_st *, &inp->spec, elt, {});
2510 return 0;
2511 trunnel_alloc_failed:
2512 TRUNNEL_SET_ERROR_CODE(inp);
2513 return -1;
2516 struct link_specifier_st * *
2517 link_specifier_list_getarray_spec(link_specifier_list_t *inp)
2519 return inp->spec.elts_;
2521 const struct link_specifier_st * const *
2522 link_specifier_list_getconstarray_spec(const link_specifier_list_t *inp)
2524 return (const struct link_specifier_st * const *)link_specifier_list_getarray_spec((link_specifier_list_t*)inp);
2527 link_specifier_list_setlen_spec(link_specifier_list_t *inp, size_t newlen)
2529 struct link_specifier_st * *newptr;
2530 #if UINT8_MAX < SIZE_MAX
2531 if (newlen > UINT8_MAX)
2532 goto trunnel_alloc_failed;
2533 #endif
2534 newptr = trunnel_dynarray_setlen(&inp->spec.allocated_,
2535 &inp->spec.n_, inp->spec.elts_, newlen,
2536 sizeof(inp->spec.elts_[0]), (trunnel_free_fn_t) link_specifier_free,
2537 &inp->trunnel_error_code_);
2538 if (newlen != 0 && newptr == NULL)
2539 goto trunnel_alloc_failed;
2540 inp->spec.elts_ = newptr;
2541 return 0;
2542 trunnel_alloc_failed:
2543 TRUNNEL_SET_ERROR_CODE(inp);
2544 return -1;
2546 const char *
2547 link_specifier_list_check(const link_specifier_list_t *obj)
2549 if (obj == NULL)
2550 return "Object was NULL";
2551 if (obj->trunnel_error_code_)
2552 return "A set function failed on this object";
2554 const char *msg;
2556 unsigned idx;
2557 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
2558 if (NULL != (msg = link_specifier_check(TRUNNEL_DYNARRAY_GET(&obj->spec, idx))))
2559 return msg;
2562 if (TRUNNEL_DYNARRAY_LEN(&obj->spec) != obj->n_spec)
2563 return "Length mismatch for spec";
2564 return NULL;
2567 ssize_t
2568 link_specifier_list_encoded_len(const link_specifier_list_t *obj)
2570 ssize_t result = 0;
2572 if (NULL != link_specifier_list_check(obj))
2573 return -1;
2576 /* Length of u8 n_spec */
2577 result += 1;
2579 /* Length of struct link_specifier spec[n_spec] */
2582 unsigned idx;
2583 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
2584 result += link_specifier_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
2587 return result;
2590 link_specifier_list_clear_errors(link_specifier_list_t *obj)
2592 int r = obj->trunnel_error_code_;
2593 obj->trunnel_error_code_ = 0;
2594 return r;
2596 ssize_t
2597 link_specifier_list_encode(uint8_t *output, const size_t avail, const link_specifier_list_t *obj)
2599 ssize_t result = 0;
2600 size_t written = 0;
2601 uint8_t *ptr = output;
2602 const char *msg;
2603 #ifdef TRUNNEL_CHECK_ENCODED_LEN
2604 const ssize_t encoded_len = link_specifier_list_encoded_len(obj);
2605 #endif
2607 if (NULL != (msg = link_specifier_list_check(obj)))
2608 goto check_failed;
2610 #ifdef TRUNNEL_CHECK_ENCODED_LEN
2611 trunnel_assert(encoded_len >= 0);
2612 #endif
2614 /* Encode u8 n_spec */
2615 trunnel_assert(written <= avail);
2616 if (avail - written < 1)
2617 goto truncated;
2618 trunnel_set_uint8(ptr, (obj->n_spec));
2619 written += 1; ptr += 1;
2621 /* Encode struct link_specifier spec[n_spec] */
2624 unsigned idx;
2625 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
2626 trunnel_assert(written <= avail);
2627 result = link_specifier_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
2628 if (result < 0)
2629 goto fail; /* XXXXXXX !*/
2630 written += result; ptr += result;
2635 trunnel_assert(ptr == output + written);
2636 #ifdef TRUNNEL_CHECK_ENCODED_LEN
2638 trunnel_assert(encoded_len >= 0);
2639 trunnel_assert((size_t)encoded_len == written);
2642 #endif
2644 return written;
2646 truncated:
2647 result = -2;
2648 goto fail;
2649 check_failed:
2650 (void)msg;
2651 result = -1;
2652 goto fail;
2653 fail:
2654 trunnel_assert(result < 0);
2655 return result;
2658 /** As link_specifier_list_parse(), but do not allocate the output
2659 * object.
2661 static ssize_t
2662 link_specifier_list_parse_into(link_specifier_list_t *obj, const uint8_t *input, const size_t len_in)
2664 const uint8_t *ptr = input;
2665 size_t remaining = len_in;
2666 ssize_t result = 0;
2667 (void)result;
2669 /* Parse u8 n_spec */
2670 CHECK_REMAINING(1, truncated);
2671 obj->n_spec = (trunnel_get_uint8(ptr));
2672 remaining -= 1; ptr += 1;
2674 /* Parse struct link_specifier spec[n_spec] */
2675 TRUNNEL_DYNARRAY_EXPAND(link_specifier_t *, &obj->spec, obj->n_spec, {});
2677 link_specifier_t * elt;
2678 unsigned idx;
2679 for (idx = 0; idx < obj->n_spec; ++idx) {
2680 result = link_specifier_parse(&elt, ptr, remaining);
2681 if (result < 0)
2682 goto relay_fail;
2683 trunnel_assert((size_t)result <= remaining);
2684 remaining -= result; ptr += result;
2685 TRUNNEL_DYNARRAY_ADD(link_specifier_t *, &obj->spec, elt, {link_specifier_free(elt);});
2688 trunnel_assert(ptr + remaining == input + len_in);
2689 return len_in - remaining;
2691 truncated:
2692 return -2;
2693 relay_fail:
2694 trunnel_assert(result < 0);
2695 return result;
2696 trunnel_alloc_failed:
2697 return -1;
2700 ssize_t
2701 link_specifier_list_parse(link_specifier_list_t **output, const uint8_t *input, const size_t len_in)
2703 ssize_t result;
2704 *output = link_specifier_list_new();
2705 if (NULL == *output)
2706 return -1;
2707 result = link_specifier_list_parse_into(*output, input, len_in);
2708 if (result < 0) {
2709 link_specifier_list_free(*output);
2710 *output = NULL;
2712 return result;