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.
6 #include "trunnel-impl.h"
8 #include "ed25519_cert.h"
10 #define TRUNNEL_SET_ERROR_CODE(obj) \
12 (obj)->trunnel_error_code_ = 1; \
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__
21 #define OR_DEADCODE_DUMMY
24 #define CHECK_REMAINING(nbytes, label) \
26 if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
32 create2_cell_body_new(void)
34 create2_cell_body_t
*val
= trunnel_calloc(1, sizeof(create2_cell_body_t
));
40 /** Release all storage held inside 'obj', but do not free 'obj'.
43 create2_cell_body_clear(create2_cell_body_t
*obj
)
46 TRUNNEL_DYNARRAY_WIPE(&obj
->handshake_data
);
47 TRUNNEL_DYNARRAY_CLEAR(&obj
->handshake_data
);
51 create2_cell_body_free(create2_cell_body_t
*obj
)
55 create2_cell_body_clear(obj
);
56 trunnel_memwipe(obj
, sizeof(create2_cell_body_t
));
61 create2_cell_body_get_handshake_type(const create2_cell_body_t
*inp
)
63 return inp
->handshake_type
;
66 create2_cell_body_set_handshake_type(create2_cell_body_t
*inp
, uint16_t val
)
68 inp
->handshake_type
= val
;
72 create2_cell_body_get_handshake_len(const create2_cell_body_t
*inp
)
74 return inp
->handshake_len
;
77 create2_cell_body_set_handshake_len(create2_cell_body_t
*inp
, uint16_t val
)
79 inp
->handshake_len
= val
;
83 create2_cell_body_getlen_handshake_data(const create2_cell_body_t
*inp
)
85 return TRUNNEL_DYNARRAY_LEN(&inp
->handshake_data
);
89 create2_cell_body_get_handshake_data(create2_cell_body_t
*inp
, size_t idx
)
91 return TRUNNEL_DYNARRAY_GET(&inp
->handshake_data
, idx
);
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
);
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
);
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
;
112 TRUNNEL_DYNARRAY_ADD(uint8_t, &inp
->handshake_data
, elt
, {});
114 trunnel_alloc_failed
:
115 TRUNNEL_SET_ERROR_CODE(inp
);
120 create2_cell_body_getarray_handshake_data(create2_cell_body_t
*inp
)
122 return inp
->handshake_data
.elts_
;
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
)
133 #if UINT16_MAX < SIZE_MAX
134 if (newlen
> UINT16_MAX
)
135 goto trunnel_alloc_failed
;
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
;
145 trunnel_alloc_failed
:
146 TRUNNEL_SET_ERROR_CODE(inp
);
150 create2_cell_body_check(const create2_cell_body_t
*obj
)
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";
162 create2_cell_body_encoded_len(const create2_cell_body_t
*obj
)
166 if (NULL
!= create2_cell_body_check(obj
))
170 /* Length of u16 handshake_type */
173 /* Length of u16 handshake_len */
176 /* Length of u8 handshake_data[handshake_len] */
177 result
+= TRUNNEL_DYNARRAY_LEN(&obj
->handshake_data
);
181 create2_cell_body_clear_errors(create2_cell_body_t
*obj
)
183 int r
= obj
->trunnel_error_code_
;
184 obj
->trunnel_error_code_
= 0;
188 create2_cell_body_encode(uint8_t *output
, const size_t avail
, const create2_cell_body_t
*obj
)
192 uint8_t *ptr
= output
;
194 #ifdef TRUNNEL_CHECK_ENCODED_LEN
195 const ssize_t encoded_len
= create2_cell_body_encoded_len(obj
);
198 if (NULL
!= (msg
= create2_cell_body_check(obj
)))
201 #ifdef TRUNNEL_CHECK_ENCODED_LEN
202 trunnel_assert(encoded_len
>= 0);
205 /* Encode u16 handshake_type */
206 trunnel_assert(written
<= avail
);
207 if (avail
- written
< 2)
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)
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
)
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
);
251 trunnel_assert(result
< 0);
255 /** As create2_cell_body_parse(), but do not allocate the output
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
;
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
;
288 trunnel_alloc_failed
:
293 create2_cell_body_parse(create2_cell_body_t
**output
, const uint8_t *input
, const size_t len_in
)
296 *output
= create2_cell_body_new();
299 result
= create2_cell_body_parse_into(*output
, input
, len_in
);
301 create2_cell_body_free(*output
);
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
));
315 /** Release all storage held inside 'obj', but do not free 'obj'.
318 ed25519_cert_extension_clear(ed25519_cert_extension_t
*obj
)
321 TRUNNEL_DYNARRAY_WIPE(&obj
->un_unparsed
);
322 TRUNNEL_DYNARRAY_CLEAR(&obj
->un_unparsed
);
326 ed25519_cert_extension_free(ed25519_cert_extension_t
*obj
)
330 ed25519_cert_extension_clear(obj
);
331 trunnel_memwipe(obj
, sizeof(ed25519_cert_extension_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
;
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
)
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
;
369 ed25519_cert_extension_getlen_un_signing_key(const ed25519_cert_extension_t
*inp
)
371 (void)inp
; return 32;
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
];
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
;
395 ed25519_cert_extension_getarray_un_signing_key(ed25519_cert_extension_t
*inp
)
397 return inp
->un_signing_key
;
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
);
405 ed25519_cert_extension_getlen_un_unparsed(const ed25519_cert_extension_t
*inp
)
407 return TRUNNEL_DYNARRAY_LEN(&inp
->un_unparsed
);
411 ed25519_cert_extension_get_un_unparsed(ed25519_cert_extension_t
*inp
, size_t idx
)
413 return TRUNNEL_DYNARRAY_GET(&inp
->un_unparsed
, idx
);
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
);
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
, {});
432 trunnel_alloc_failed
:
433 TRUNNEL_SET_ERROR_CODE(inp
);
438 ed25519_cert_extension_getarray_un_unparsed(ed25519_cert_extension_t
*inp
)
440 return inp
->un_unparsed
.elts_
;
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
)
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
;
459 trunnel_alloc_failed
:
460 TRUNNEL_SET_ERROR_CODE(inp
);
464 ed25519_cert_extension_check(const ed25519_cert_extension_t
*obj
)
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
:
482 ed25519_cert_extension_encoded_len(const ed25519_cert_extension_t
*obj
)
486 if (NULL
!= ed25519_cert_extension_check(obj
))
490 /* Length of u16 ext_length */
493 /* Length of u8 ext_type */
496 /* Length of u8 ext_flags */
498 switch (obj
->ext_type
) {
500 case CERTEXT_SIGNED_WITH_KEY
:
502 /* Length of u8 un_signing_key[32] */
508 /* Length of u8 un_unparsed[] */
509 result
+= TRUNNEL_DYNARRAY_LEN(&obj
->un_unparsed
);
515 ed25519_cert_extension_clear_errors(ed25519_cert_extension_t
*obj
)
517 int r
= obj
->trunnel_error_code_
;
518 obj
->trunnel_error_code_
= 0;
522 ed25519_cert_extension_encode(uint8_t *output
, const size_t avail
, const ed25519_cert_extension_t
*obj
)
526 uint8_t *ptr
= output
;
528 #ifdef TRUNNEL_CHECK_ENCODED_LEN
529 const ssize_t encoded_len
= ed25519_cert_extension_encoded_len(obj
);
532 uint8_t *backptr_ext_length
= NULL
;
534 if (NULL
!= (msg
= ed25519_cert_extension_check(obj
)))
537 #ifdef TRUNNEL_CHECK_ENCODED_LEN
538 trunnel_assert(encoded_len
>= 0);
541 /* Encode u16 ext_length */
542 backptr_ext_length
= ptr
;
543 trunnel_assert(written
<= avail
);
544 if (avail
- written
< 2)
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)
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)
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)
575 memcpy(ptr
, obj
->un_signing_key
, 32);
576 written
+= 32; ptr
+= 32;
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
)
588 memcpy(ptr
, obj
->un_unparsed
.elts_
, elt_len
);
589 written
+= elt_len
; ptr
+= elt_len
;
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
)
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
);
622 trunnel_assert(result
< 0);
626 /** As ed25519_cert_extension_parse(), but do not allocate the output
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
;
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;
670 /* Parse u8 un_unparsed[] */
671 TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj
->un_unparsed
, remaining
, {});
672 obj
->un_unparsed
.n_
= remaining
;
674 memcpy(obj
->un_unparsed
.elts_
, ptr
, remaining
);
675 ptr
+= remaining
; remaining
-= remaining
;
680 remaining
= remaining_after
;
682 trunnel_assert(ptr
+ remaining
== input
+ len_in
);
683 return len_in
- remaining
;
687 trunnel_alloc_failed
:
695 ed25519_cert_extension_parse(ed25519_cert_extension_t
**output
, const uint8_t *input
, const size_t len_in
)
698 *output
= ed25519_cert_extension_new();
701 result
= ed25519_cert_extension_parse_into(*output
, input
, len_in
);
703 ed25519_cert_extension_free(*output
);
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
));
717 /** Release all storage held inside 'obj', but do not free 'obj'.
720 extend1_cell_body_clear(extend1_cell_body_t
*obj
)
726 extend1_cell_body_free(extend1_cell_body_t
*obj
)
730 extend1_cell_body_clear(obj
);
731 trunnel_memwipe(obj
, sizeof(extend1_cell_body_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
)
747 extend1_cell_body_get_port(const extend1_cell_body_t
*inp
)
752 extend1_cell_body_set_port(extend1_cell_body_t
*inp
, uint16_t val
)
758 extend1_cell_body_getlen_onionskin(const extend1_cell_body_t
*inp
)
760 (void)inp
; return 186;
764 extend1_cell_body_get_onionskin(extend1_cell_body_t
*inp
, size_t idx
)
766 trunnel_assert(idx
< 186);
767 return inp
->onionskin
[idx
];
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
;
784 extend1_cell_body_getarray_onionskin(extend1_cell_body_t
*inp
)
786 return inp
->onionskin
;
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
);
794 extend1_cell_body_getlen_identity(const extend1_cell_body_t
*inp
)
796 (void)inp
; return 20;
800 extend1_cell_body_get_identity(extend1_cell_body_t
*inp
, size_t idx
)
802 trunnel_assert(idx
< 20);
803 return inp
->identity
[idx
];
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
;
820 extend1_cell_body_getarray_identity(extend1_cell_body_t
*inp
)
822 return inp
->identity
;
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
);
830 extend1_cell_body_check(const extend1_cell_body_t
*obj
)
833 return "Object was NULL";
834 if (obj
->trunnel_error_code_
)
835 return "A set function failed on this object";
840 extend1_cell_body_encoded_len(const extend1_cell_body_t
*obj
)
844 if (NULL
!= extend1_cell_body_check(obj
))
848 /* Length of u32 ipv4addr */
851 /* Length of u16 port */
854 /* Length of u8 onionskin[186] */
857 /* Length of u8 identity[20] */
862 extend1_cell_body_clear_errors(extend1_cell_body_t
*obj
)
864 int r
= obj
->trunnel_error_code_
;
865 obj
->trunnel_error_code_
= 0;
869 extend1_cell_body_encode(uint8_t *output
, const size_t avail
, const extend1_cell_body_t
*obj
)
873 uint8_t *ptr
= output
;
875 #ifdef TRUNNEL_CHECK_ENCODED_LEN
876 const ssize_t encoded_len
= extend1_cell_body_encoded_len(obj
);
879 if (NULL
!= (msg
= extend1_cell_body_check(obj
)))
882 #ifdef TRUNNEL_CHECK_ENCODED_LEN
883 trunnel_assert(encoded_len
>= 0);
886 /* Encode u32 ipv4addr */
887 trunnel_assert(written
<= avail
);
888 if (avail
- written
< 4)
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)
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)
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)
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
);
934 trunnel_assert(result
< 0);
938 /** As extend1_cell_body_parse(), but do not allocate the output
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
;
949 /* Parse u32 ipv4addr */
950 CHECK_REMAINING(4, truncated
);
951 obj
->ipv4addr
= trunnel_ntohl(trunnel_get_uint32(ptr
));
952 remaining
-= 4; ptr
+= 4;
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
;
976 extend1_cell_body_parse(extend1_cell_body_t
**output
, const uint8_t *input
, const size_t len_in
)
979 *output
= extend1_cell_body_new();
982 result
= extend1_cell_body_parse_into(*output
, input
, len_in
);
984 extend1_cell_body_free(*output
);
990 link_specifier_new(void)
992 link_specifier_t
*val
= trunnel_calloc(1, sizeof(link_specifier_t
));
998 /** Release all storage held inside 'obj', but do not free 'obj'.
1001 link_specifier_clear(link_specifier_t
*obj
)
1004 TRUNNEL_DYNARRAY_WIPE(&obj
->un_unrecognized
);
1005 TRUNNEL_DYNARRAY_CLEAR(&obj
->un_unrecognized
);
1009 link_specifier_free(link_specifier_t
*obj
)
1013 link_specifier_clear(obj
);
1014 trunnel_memwipe(obj
, sizeof(link_specifier_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
)
1030 link_specifier_get_ls_len(const link_specifier_t
*inp
)
1035 link_specifier_set_ls_len(link_specifier_t
*inp
, uint8_t val
)
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
;
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
;
1063 link_specifier_getlen_un_ipv6_addr(const link_specifier_t
*inp
)
1065 (void)inp
; return 16;
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
];
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
;
1089 link_specifier_getarray_un_ipv6_addr(link_specifier_t
*inp
)
1091 return inp
->un_ipv6_addr
;
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
);
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
;
1110 link_specifier_getlen_un_legacy_id(const link_specifier_t
*inp
)
1112 (void)inp
; return 20;
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
];
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
;
1136 link_specifier_getarray_un_legacy_id(link_specifier_t
*inp
)
1138 return inp
->un_legacy_id
;
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
);
1146 link_specifier_getlen_un_ed25519_id(const link_specifier_t
*inp
)
1148 (void)inp
; return 32;
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
];
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
;
1172 link_specifier_getarray_un_ed25519_id(link_specifier_t
*inp
)
1174 return inp
->un_ed25519_id
;
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
);
1182 link_specifier_getlen_un_unrecognized(const link_specifier_t
*inp
)
1184 return TRUNNEL_DYNARRAY_LEN(&inp
->un_unrecognized
);
1188 link_specifier_get_un_unrecognized(link_specifier_t
*inp
, size_t idx
)
1190 return TRUNNEL_DYNARRAY_GET(&inp
->un_unrecognized
, idx
);
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
);
1205 link_specifier_add_un_unrecognized(link_specifier_t
*inp
, uint8_t elt
)
1207 TRUNNEL_DYNARRAY_ADD(uint8_t, &inp
->un_unrecognized
, elt
, {});
1209 trunnel_alloc_failed
:
1210 TRUNNEL_SET_ERROR_CODE(inp
);
1215 link_specifier_getarray_un_unrecognized(link_specifier_t
*inp
)
1217 return inp
->un_unrecognized
.elts_
;
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
)
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
;
1236 trunnel_alloc_failed
:
1237 TRUNNEL_SET_ERROR_CODE(inp
);
1241 link_specifier_check(const link_specifier_t
*obj
)
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
) {
1268 link_specifier_encoded_len(const link_specifier_t
*obj
)
1272 if (NULL
!= link_specifier_check(obj
))
1276 /* Length of u8 ls_type */
1279 /* Length of u8 ls_len */
1281 switch (obj
->ls_type
) {
1285 /* Length of u32 un_ipv4_addr */
1288 /* Length of u16 un_ipv4_port */
1294 /* Length of u8 un_ipv6_addr[16] */
1297 /* Length of u16 un_ipv6_port */
1303 /* Length of u8 un_legacy_id[20] */
1309 /* Length of u8 un_ed25519_id[32] */
1315 /* Length of u8 un_unrecognized[] */
1316 result
+= TRUNNEL_DYNARRAY_LEN(&obj
->un_unrecognized
);
1322 link_specifier_clear_errors(link_specifier_t
*obj
)
1324 int r
= obj
->trunnel_error_code_
;
1325 obj
->trunnel_error_code_
= 0;
1329 link_specifier_encode(uint8_t *output
, const size_t avail
, const link_specifier_t
*obj
)
1333 uint8_t *ptr
= output
;
1335 #ifdef TRUNNEL_CHECK_ENCODED_LEN
1336 const ssize_t encoded_len
= link_specifier_encoded_len(obj
);
1339 uint8_t *backptr_ls_len
= NULL
;
1341 if (NULL
!= (msg
= link_specifier_check(obj
)))
1344 #ifdef TRUNNEL_CHECK_ENCODED_LEN
1345 trunnel_assert(encoded_len
>= 0);
1348 /* Encode u8 ls_type */
1349 trunnel_assert(written
<= avail
);
1350 if (avail
- written
< 1)
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)
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
) {
1371 /* Encode u32 un_ipv4_addr */
1372 trunnel_assert(written
<= avail
);
1373 if (avail
- written
< 4)
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)
1382 trunnel_set_uint16(ptr
, trunnel_htons(obj
->un_ipv4_port
));
1383 written
+= 2; ptr
+= 2;
1388 /* Encode u8 un_ipv6_addr[16] */
1389 trunnel_assert(written
<= avail
);
1390 if (avail
- written
< 16)
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)
1399 trunnel_set_uint16(ptr
, trunnel_htons(obj
->un_ipv6_port
));
1400 written
+= 2; ptr
+= 2;
1405 /* Encode u8 un_legacy_id[20] */
1406 trunnel_assert(written
<= avail
);
1407 if (avail
- written
< 20)
1409 memcpy(ptr
, obj
->un_legacy_id
, 20);
1410 written
+= 20; ptr
+= 20;
1415 /* Encode u8 un_ed25519_id[32] */
1416 trunnel_assert(written
<= avail
);
1417 if (avail
- written
< 32)
1419 memcpy(ptr
, obj
->un_ed25519_id
, 32);
1420 written
+= 32; ptr
+= 32;
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
)
1432 memcpy(ptr
, obj
->un_unrecognized
.elts_
, elt_len
);
1433 written
+= elt_len
; ptr
+= elt_len
;
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
)
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
);
1466 trunnel_assert(result
< 0);
1470 /** As link_specifier_parse(), but do not allocate the output object.
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
;
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
) {
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;
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;
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;
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;
1542 /* Parse u8 un_unrecognized[] */
1543 TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj
->un_unrecognized
, remaining
, {});
1544 obj
->un_unrecognized
.n_
= remaining
;
1546 memcpy(obj
->un_unrecognized
.elts_
, ptr
, remaining
);
1547 ptr
+= remaining
; remaining
-= remaining
;
1552 remaining
= remaining_after
;
1554 trunnel_assert(ptr
+ remaining
== input
+ len_in
);
1555 return len_in
- remaining
;
1559 trunnel_alloc_failed
:
1567 link_specifier_parse(link_specifier_t
**output
, const uint8_t *input
, const size_t len_in
)
1570 *output
= link_specifier_new();
1571 if (NULL
== *output
)
1573 result
= link_specifier_parse_into(*output
, input
, len_in
);
1575 link_specifier_free(*output
);
1581 ed25519_cert_new(void)
1583 ed25519_cert_t
*val
= trunnel_calloc(1, sizeof(ed25519_cert_t
));
1590 /** Release all storage held inside 'obj', but do not free 'obj'.
1593 ed25519_cert_clear(ed25519_cert_t
*obj
)
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
);
1608 ed25519_cert_free(ed25519_cert_t
*obj
)
1612 ed25519_cert_clear(obj
);
1613 trunnel_memwipe(obj
, sizeof(ed25519_cert_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
);
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
;
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
;
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
;
1666 ed25519_cert_getlen_certified_key(const ed25519_cert_t
*inp
)
1668 (void)inp
; return 32;
1672 ed25519_cert_get_certified_key(ed25519_cert_t
*inp
, size_t idx
)
1674 trunnel_assert(idx
< 32);
1675 return inp
->certified_key
[idx
];
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
;
1692 ed25519_cert_getarray_certified_key(ed25519_cert_t
*inp
)
1694 return inp
->certified_key
;
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
);
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
;
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
);
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
;
1750 TRUNNEL_DYNARRAY_ADD(struct ed25519_cert_extension_st
*, &inp
->ext
, elt
, {});
1752 trunnel_alloc_failed
:
1753 TRUNNEL_SET_ERROR_CODE(inp
);
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
;
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
;
1783 trunnel_alloc_failed
:
1784 TRUNNEL_SET_ERROR_CODE(inp
);
1788 ed25519_cert_getlen_signature(const ed25519_cert_t
*inp
)
1790 (void)inp
; return 64;
1794 ed25519_cert_get_signature(ed25519_cert_t
*inp
, size_t idx
)
1796 trunnel_assert(idx
< 64);
1797 return inp
->signature
[idx
];
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
;
1814 ed25519_cert_getarray_signature(ed25519_cert_t
*inp
)
1816 return inp
->signature
;
1819 ed25519_cert_getconstarray_signature(const ed25519_cert_t
*inp
)
1821 return (const uint8_t *)ed25519_cert_getarray_signature((ed25519_cert_t
*)inp
);
1824 ed25519_cert_check(const ed25519_cert_t
*obj
)
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";
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
))))
1841 if (TRUNNEL_DYNARRAY_LEN(&obj
->ext
) != obj
->n_extensions
)
1842 return "Length mismatch for ext";
1847 ed25519_cert_encoded_len(const ed25519_cert_t
*obj
)
1851 if (NULL
!= ed25519_cert_check(obj
))
1855 /* Length of u8 version IN [1] */
1858 /* Length of u8 cert_type */
1861 /* Length of u32 exp_field */
1864 /* Length of u8 cert_key_type */
1867 /* Length of u8 certified_key[32] */
1870 /* Length of u8 n_extensions */
1873 /* Length of struct ed25519_cert_extension ext[n_extensions] */
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] */
1887 ed25519_cert_clear_errors(ed25519_cert_t
*obj
)
1889 int r
= obj
->trunnel_error_code_
;
1890 obj
->trunnel_error_code_
= 0;
1894 ed25519_cert_encode(uint8_t *output
, const size_t avail
, const ed25519_cert_t
*obj
)
1898 uint8_t *ptr
= output
;
1900 #ifdef TRUNNEL_CHECK_ENCODED_LEN
1901 const ssize_t encoded_len
= ed25519_cert_encoded_len(obj
);
1904 if (NULL
!= (msg
= ed25519_cert_check(obj
)))
1907 #ifdef TRUNNEL_CHECK_ENCODED_LEN
1908 trunnel_assert(encoded_len
>= 0);
1911 /* Encode u8 version IN [1] */
1912 trunnel_assert(written
<= avail
);
1913 if (avail
- written
< 1)
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)
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)
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)
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)
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)
1950 trunnel_set_uint8(ptr
, (obj
->n_extensions
));
1951 written
+= 1; ptr
+= 1;
1953 /* Encode struct ed25519_cert_extension ext[n_extensions] */
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
));
1961 goto fail
; /* XXXXXXX !*/
1962 written
+= result
; ptr
+= result
;
1966 /* Encode u8 signature[64] */
1967 trunnel_assert(written
<= avail
);
1968 if (avail
- written
< 64)
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
);
1993 trunnel_assert(result
< 0);
1997 /** As ed25519_cert_parse(), but do not allocate the output object.
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
;
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))
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
;
2044 for (idx
= 0; idx
< obj
->n_extensions
; ++idx
) {
2045 result
= ed25519_cert_extension_parse(&elt
, ptr
, remaining
);
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
;
2064 trunnel_assert(result
< 0);
2066 trunnel_alloc_failed
:
2074 ed25519_cert_parse(ed25519_cert_t
**output
, const uint8_t *input
, const size_t len_in
)
2077 *output
= ed25519_cert_new();
2078 if (NULL
== *output
)
2080 result
= ed25519_cert_parse_into(*output
, input
, len_in
);
2082 ed25519_cert_free(*output
);
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
));
2096 /** Release all storage held inside 'obj', but do not free 'obj'.
2099 extend2_cell_body_clear(extend2_cell_body_t
*obj
)
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
;
2116 extend2_cell_body_free(extend2_cell_body_t
*obj
)
2120 extend2_cell_body_clear(obj
);
2121 trunnel_memwipe(obj
, sizeof(extend2_cell_body_t
));
2126 extend2_cell_body_get_n_spec(const extend2_cell_body_t
*inp
)
2131 extend2_cell_body_set_n_spec(extend2_cell_body_t
*inp
, uint8_t val
)
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
);
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
;
2174 TRUNNEL_DYNARRAY_ADD(struct link_specifier_st
*, &inp
->ls
, elt
, {});
2176 trunnel_alloc_failed
:
2177 TRUNNEL_SET_ERROR_CODE(inp
);
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
;
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
;
2207 trunnel_alloc_failed
:
2208 TRUNNEL_SET_ERROR_CODE(inp
);
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
)
2235 extend2_cell_body_check(const extend2_cell_body_t
*obj
)
2238 return "Object was NULL";
2239 if (obj
->trunnel_error_code_
)
2240 return "A set function failed on this object";
2245 for (idx
= 0; idx
< TRUNNEL_DYNARRAY_LEN(&obj
->ls
); ++idx
) {
2246 if (NULL
!= (msg
= link_specifier_check(TRUNNEL_DYNARRAY_GET(&obj
->ls
, idx
))))
2250 if (TRUNNEL_DYNARRAY_LEN(&obj
->ls
) != obj
->n_spec
)
2251 return "Length mismatch for ls";
2254 if (NULL
!= (msg
= create2_cell_body_check(obj
->create2
)))
2261 extend2_cell_body_encoded_len(const extend2_cell_body_t
*obj
)
2265 if (NULL
!= extend2_cell_body_check(obj
))
2269 /* Length of u8 n_spec */
2272 /* Length of struct link_specifier ls[n_spec] */
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
);
2286 extend2_cell_body_clear_errors(extend2_cell_body_t
*obj
)
2288 int r
= obj
->trunnel_error_code_
;
2289 obj
->trunnel_error_code_
= 0;
2293 extend2_cell_body_encode(uint8_t *output
, const size_t avail
, const extend2_cell_body_t
*obj
)
2297 uint8_t *ptr
= output
;
2299 #ifdef TRUNNEL_CHECK_ENCODED_LEN
2300 const ssize_t encoded_len
= extend2_cell_body_encoded_len(obj
);
2303 if (NULL
!= (msg
= extend2_cell_body_check(obj
)))
2306 #ifdef TRUNNEL_CHECK_ENCODED_LEN
2307 trunnel_assert(encoded_len
>= 0);
2310 /* Encode u8 n_spec */
2311 trunnel_assert(written
<= avail
);
2312 if (avail
- written
< 1)
2314 trunnel_set_uint8(ptr
, (obj
->n_spec
));
2315 written
+= 1; ptr
+= 1;
2317 /* Encode struct link_specifier ls[n_spec] */
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
));
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
);
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
);
2357 trunnel_assert(result
< 0);
2361 /** As extend2_cell_body_parse(), but do not allocate the output
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
;
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
;
2382 for (idx
= 0; idx
< obj
->n_spec
; ++idx
) {
2383 result
= link_specifier_parse(&elt
, ptr
, remaining
);
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
);
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
;
2404 trunnel_assert(result
< 0);
2406 trunnel_alloc_failed
:
2411 extend2_cell_body_parse(extend2_cell_body_t
**output
, const uint8_t *input
, const size_t len_in
)
2414 *output
= extend2_cell_body_new();
2415 if (NULL
== *output
)
2417 result
= extend2_cell_body_parse_into(*output
, input
, len_in
);
2419 extend2_cell_body_free(*output
);
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
));
2433 /** Release all storage held inside 'obj', but do not free 'obj'.
2436 link_specifier_list_clear(link_specifier_list_t
*obj
)
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
);
2451 link_specifier_list_free(link_specifier_list_t
*obj
)
2455 link_specifier_list_clear(obj
);
2456 trunnel_memwipe(obj
, sizeof(link_specifier_list_t
));
2461 link_specifier_list_get_n_spec(const link_specifier_list_t
*inp
)
2466 link_specifier_list_set_n_spec(link_specifier_list_t
*inp
, uint8_t val
)
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
);
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
;
2509 TRUNNEL_DYNARRAY_ADD(struct link_specifier_st
*, &inp
->spec
, elt
, {});
2511 trunnel_alloc_failed
:
2512 TRUNNEL_SET_ERROR_CODE(inp
);
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
;
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
;
2542 trunnel_alloc_failed
:
2543 TRUNNEL_SET_ERROR_CODE(inp
);
2547 link_specifier_list_check(const link_specifier_list_t
*obj
)
2550 return "Object was NULL";
2551 if (obj
->trunnel_error_code_
)
2552 return "A set function failed on this object";
2557 for (idx
= 0; idx
< TRUNNEL_DYNARRAY_LEN(&obj
->spec
); ++idx
) {
2558 if (NULL
!= (msg
= link_specifier_check(TRUNNEL_DYNARRAY_GET(&obj
->spec
, idx
))))
2562 if (TRUNNEL_DYNARRAY_LEN(&obj
->spec
) != obj
->n_spec
)
2563 return "Length mismatch for spec";
2568 link_specifier_list_encoded_len(const link_specifier_list_t
*obj
)
2572 if (NULL
!= link_specifier_list_check(obj
))
2576 /* Length of u8 n_spec */
2579 /* Length of struct link_specifier spec[n_spec] */
2583 for (idx
= 0; idx
< TRUNNEL_DYNARRAY_LEN(&obj
->spec
); ++idx
) {
2584 result
+= link_specifier_encoded_len(TRUNNEL_DYNARRAY_GET(&obj
->spec
, idx
));
2590 link_specifier_list_clear_errors(link_specifier_list_t
*obj
)
2592 int r
= obj
->trunnel_error_code_
;
2593 obj
->trunnel_error_code_
= 0;
2597 link_specifier_list_encode(uint8_t *output
, const size_t avail
, const link_specifier_list_t
*obj
)
2601 uint8_t *ptr
= output
;
2603 #ifdef TRUNNEL_CHECK_ENCODED_LEN
2604 const ssize_t encoded_len
= link_specifier_list_encoded_len(obj
);
2607 if (NULL
!= (msg
= link_specifier_list_check(obj
)))
2610 #ifdef TRUNNEL_CHECK_ENCODED_LEN
2611 trunnel_assert(encoded_len
>= 0);
2614 /* Encode u8 n_spec */
2615 trunnel_assert(written
<= avail
);
2616 if (avail
- written
< 1)
2618 trunnel_set_uint8(ptr
, (obj
->n_spec
));
2619 written
+= 1; ptr
+= 1;
2621 /* Encode struct link_specifier spec[n_spec] */
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
));
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
);
2654 trunnel_assert(result
< 0);
2658 /** As link_specifier_list_parse(), but do not allocate the output
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
;
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
;
2679 for (idx
= 0; idx
< obj
->n_spec
; ++idx
) {
2680 result
= link_specifier_parse(&elt
, ptr
, remaining
);
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
;
2694 trunnel_assert(result
< 0);
2696 trunnel_alloc_failed
:
2701 link_specifier_list_parse(link_specifier_list_t
**output
, const uint8_t *input
, const size_t len_in
)
2704 *output
= link_specifier_list_new();
2705 if (NULL
== *output
)
2707 result
= link_specifier_list_parse_into(*output
, input
, len_in
);
2709 link_specifier_list_free(*output
);