Line data Source code
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"
7 :
8 : #include "ed25519_cert.h"
9 :
10 : #define TRUNNEL_SET_ERROR_CODE(obj) \
11 : do { \
12 : (obj)->trunnel_error_code_ = 1; \
13 : } while (0)
14 :
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
23 :
24 : #define CHECK_REMAINING(nbytes, label) \
25 : do { \
26 : if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
27 : goto label; \
28 : } \
29 : } while (0)
30 :
31 : create2_cell_body_t *
32 113 : create2_cell_body_new(void)
33 : {
34 113 : create2_cell_body_t *val = trunnel_calloc(1, sizeof(create2_cell_body_t));
35 113 : if (NULL == val)
36 0 : return NULL;
37 : return val;
38 : }
39 :
40 : /** Release all storage held inside 'obj', but do not free 'obj'.
41 : */
42 : static void
43 113 : create2_cell_body_clear(create2_cell_body_t *obj)
44 : {
45 113 : (void) obj;
46 113 : TRUNNEL_DYNARRAY_WIPE(&obj->handshake_data);
47 113 : TRUNNEL_DYNARRAY_CLEAR(&obj->handshake_data);
48 113 : }
49 :
50 : void
51 10119 : create2_cell_body_free(create2_cell_body_t *obj)
52 : {
53 10119 : if (obj == NULL)
54 : return;
55 113 : create2_cell_body_clear(obj);
56 113 : trunnel_memwipe(obj, sizeof(create2_cell_body_t));
57 113 : trunnel_free_(obj);
58 : }
59 :
60 : uint16_t
61 0 : create2_cell_body_get_handshake_type(const create2_cell_body_t *inp)
62 : {
63 0 : return inp->handshake_type;
64 : }
65 : int
66 0 : create2_cell_body_set_handshake_type(create2_cell_body_t *inp, uint16_t val)
67 : {
68 0 : inp->handshake_type = val;
69 0 : return 0;
70 : }
71 : uint16_t
72 0 : create2_cell_body_get_handshake_len(const create2_cell_body_t *inp)
73 : {
74 0 : return inp->handshake_len;
75 : }
76 : int
77 0 : create2_cell_body_set_handshake_len(create2_cell_body_t *inp, uint16_t val)
78 : {
79 0 : inp->handshake_len = val;
80 0 : return 0;
81 : }
82 : size_t
83 0 : create2_cell_body_getlen_handshake_data(const create2_cell_body_t *inp)
84 : {
85 0 : return TRUNNEL_DYNARRAY_LEN(&inp->handshake_data);
86 : }
87 :
88 : uint8_t
89 0 : create2_cell_body_get_handshake_data(create2_cell_body_t *inp, size_t idx)
90 : {
91 0 : return TRUNNEL_DYNARRAY_GET(&inp->handshake_data, idx);
92 : }
93 :
94 : uint8_t
95 0 : create2_cell_body_getconst_handshake_data(const create2_cell_body_t *inp, size_t idx)
96 : {
97 0 : return create2_cell_body_get_handshake_data((create2_cell_body_t*)inp, idx);
98 : }
99 : int
100 0 : create2_cell_body_set_handshake_data(create2_cell_body_t *inp, size_t idx, uint8_t elt)
101 : {
102 0 : TRUNNEL_DYNARRAY_SET(&inp->handshake_data, idx, elt);
103 0 : return 0;
104 : }
105 : int
106 0 : create2_cell_body_add_handshake_data(create2_cell_body_t *inp, uint8_t elt)
107 : {
108 : #if SIZE_MAX >= UINT16_MAX
109 0 : if (inp->handshake_data.n_ == UINT16_MAX)
110 0 : goto trunnel_alloc_failed;
111 : #endif
112 0 : TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->handshake_data, elt, {});
113 0 : return 0;
114 0 : trunnel_alloc_failed:
115 0 : TRUNNEL_SET_ERROR_CODE(inp);
116 0 : return -1;
117 : }
118 :
119 : uint8_t *
120 9 : create2_cell_body_getarray_handshake_data(create2_cell_body_t *inp)
121 : {
122 9 : return inp->handshake_data.elts_;
123 : }
124 : const uint8_t *
125 4 : create2_cell_body_getconstarray_handshake_data(const create2_cell_body_t *inp)
126 : {
127 4 : return (const uint8_t *)create2_cell_body_getarray_handshake_data((create2_cell_body_t*)inp);
128 : }
129 : int
130 5 : create2_cell_body_setlen_handshake_data(create2_cell_body_t *inp, size_t newlen)
131 : {
132 5 : uint8_t *newptr;
133 : #if UINT16_MAX < SIZE_MAX
134 5 : if (newlen > UINT16_MAX)
135 0 : goto trunnel_alloc_failed;
136 : #endif
137 10 : newptr = trunnel_dynarray_setlen(&inp->handshake_data.allocated_,
138 5 : &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 5 : if (newlen != 0 && newptr == NULL)
142 0 : goto trunnel_alloc_failed;
143 5 : inp->handshake_data.elts_ = newptr;
144 5 : return 0;
145 0 : trunnel_alloc_failed:
146 0 : TRUNNEL_SET_ERROR_CODE(inp);
147 0 : return -1;
148 : }
149 : const char *
150 10 : create2_cell_body_check(const create2_cell_body_t *obj)
151 : {
152 10 : if (obj == NULL)
153 : return "Object was NULL";
154 10 : if (obj->trunnel_error_code_)
155 : return "A set function failed on this object";
156 10 : if (TRUNNEL_DYNARRAY_LEN(&obj->handshake_data) != obj->handshake_len)
157 0 : return "Length mismatch for handshake_data";
158 : return NULL;
159 : }
160 :
161 : ssize_t
162 0 : create2_cell_body_encoded_len(const create2_cell_body_t *obj)
163 : {
164 0 : ssize_t result = 0;
165 :
166 0 : if (NULL != create2_cell_body_check(obj))
167 : return -1;
168 :
169 :
170 : /* Length of u16 handshake_type */
171 0 : result += 2;
172 :
173 : /* Length of u16 handshake_len */
174 0 : result += 2;
175 :
176 : /* Length of u8 handshake_data[handshake_len] */
177 0 : result += TRUNNEL_DYNARRAY_LEN(&obj->handshake_data);
178 0 : return result;
179 : }
180 : int
181 0 : create2_cell_body_clear_errors(create2_cell_body_t *obj)
182 : {
183 0 : int r = obj->trunnel_error_code_;
184 0 : obj->trunnel_error_code_ = 0;
185 0 : return r;
186 : }
187 : ssize_t
188 5 : create2_cell_body_encode(uint8_t *output, const size_t avail, const create2_cell_body_t *obj)
189 : {
190 5 : ssize_t result = 0;
191 5 : size_t written = 0;
192 5 : uint8_t *ptr = output;
193 5 : const char *msg;
194 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
195 : const ssize_t encoded_len = create2_cell_body_encoded_len(obj);
196 : #endif
197 :
198 5 : if (NULL != (msg = create2_cell_body_check(obj)))
199 0 : goto check_failed;
200 :
201 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
202 : trunnel_assert(encoded_len >= 0);
203 : #endif
204 :
205 : /* Encode u16 handshake_type */
206 5 : trunnel_assert(written <= avail);
207 5 : if (avail - written < 2)
208 0 : goto truncated;
209 5 : trunnel_set_uint16(ptr, trunnel_htons(obj->handshake_type));
210 5 : written += 2; ptr += 2;
211 :
212 : /* Encode u16 handshake_len */
213 5 : trunnel_assert(written <= avail);
214 5 : if (avail - written < 2)
215 0 : goto truncated;
216 5 : trunnel_set_uint16(ptr, trunnel_htons(obj->handshake_len));
217 5 : written += 2; ptr += 2;
218 :
219 : /* Encode u8 handshake_data[handshake_len] */
220 : {
221 5 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->handshake_data);
222 5 : trunnel_assert(obj->handshake_len == elt_len);
223 5 : trunnel_assert(written <= avail);
224 5 : if (avail - written < elt_len)
225 0 : goto truncated;
226 5 : if (elt_len)
227 5 : memcpy(ptr, obj->handshake_data.elts_, elt_len);
228 5 : written += elt_len; ptr += elt_len;
229 : }
230 :
231 :
232 5 : trunnel_assert(ptr == output + written);
233 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
234 : {
235 : trunnel_assert(encoded_len >= 0);
236 : trunnel_assert((size_t)encoded_len == written);
237 : }
238 :
239 : #endif
240 :
241 5 : return written;
242 :
243 0 : truncated:
244 0 : result = -2;
245 0 : goto fail;
246 0 : check_failed:
247 0 : (void)msg;
248 0 : result = -1;
249 0 : goto fail;
250 : fail:
251 : trunnel_assert(result < 0);
252 : return result;
253 : }
254 :
255 : /** As create2_cell_body_parse(), but do not allocate the output
256 : * object.
257 : */
258 : static ssize_t
259 108 : create2_cell_body_parse_into(create2_cell_body_t *obj, const uint8_t *input, const size_t len_in)
260 : {
261 108 : const uint8_t *ptr = input;
262 108 : size_t remaining = len_in;
263 108 : ssize_t result = 0;
264 108 : (void)result;
265 :
266 : /* Parse u16 handshake_type */
267 108 : CHECK_REMAINING(2, truncated);
268 108 : obj->handshake_type = trunnel_ntohs(trunnel_get_uint16(ptr));
269 108 : remaining -= 2; ptr += 2;
270 :
271 : /* Parse u16 handshake_len */
272 108 : CHECK_REMAINING(2, truncated);
273 108 : obj->handshake_len = trunnel_ntohs(trunnel_get_uint16(ptr));
274 108 : remaining -= 2; ptr += 2;
275 :
276 : /* Parse u8 handshake_data[handshake_len] */
277 108 : CHECK_REMAINING(obj->handshake_len, truncated);
278 6 : TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->handshake_data, obj->handshake_len, {});
279 6 : obj->handshake_data.n_ = obj->handshake_len;
280 6 : if (obj->handshake_len)
281 5 : memcpy(obj->handshake_data.elts_, ptr, obj->handshake_len);
282 6 : ptr += obj->handshake_len; remaining -= obj->handshake_len;
283 6 : trunnel_assert(ptr + remaining == input + len_in);
284 6 : return len_in - remaining;
285 :
286 : truncated:
287 : return -2;
288 0 : trunnel_alloc_failed:
289 0 : return -1;
290 : }
291 :
292 : ssize_t
293 108 : create2_cell_body_parse(create2_cell_body_t **output, const uint8_t *input, const size_t len_in)
294 : {
295 108 : ssize_t result;
296 108 : *output = create2_cell_body_new();
297 108 : if (NULL == *output)
298 : return -1;
299 108 : result = create2_cell_body_parse_into(*output, input, len_in);
300 108 : if (result < 0) {
301 102 : create2_cell_body_free(*output);
302 102 : *output = NULL;
303 : }
304 : return result;
305 : }
306 : ed25519_cert_extension_t *
307 2154 : ed25519_cert_extension_new(void)
308 : {
309 2154 : ed25519_cert_extension_t *val = trunnel_calloc(1, sizeof(ed25519_cert_extension_t));
310 2154 : if (NULL == val)
311 0 : return NULL;
312 : return val;
313 : }
314 :
315 : /** Release all storage held inside 'obj', but do not free 'obj'.
316 : */
317 : static void
318 2154 : ed25519_cert_extension_clear(ed25519_cert_extension_t *obj)
319 : {
320 2154 : (void) obj;
321 2154 : TRUNNEL_DYNARRAY_WIPE(&obj->un_unparsed);
322 2154 : TRUNNEL_DYNARRAY_CLEAR(&obj->un_unparsed);
323 2154 : }
324 :
325 : void
326 2154 : ed25519_cert_extension_free(ed25519_cert_extension_t *obj)
327 : {
328 2154 : if (obj == NULL)
329 : return;
330 2154 : ed25519_cert_extension_clear(obj);
331 2154 : trunnel_memwipe(obj, sizeof(ed25519_cert_extension_t));
332 2154 : trunnel_free_(obj);
333 : }
334 :
335 : uint16_t
336 0 : ed25519_cert_extension_get_ext_length(const ed25519_cert_extension_t *inp)
337 : {
338 0 : return inp->ext_length;
339 : }
340 : int
341 0 : ed25519_cert_extension_set_ext_length(ed25519_cert_extension_t *inp, uint16_t val)
342 : {
343 0 : inp->ext_length = val;
344 0 : return 0;
345 : }
346 : uint8_t
347 0 : ed25519_cert_extension_get_ext_type(const ed25519_cert_extension_t *inp)
348 : {
349 0 : return inp->ext_type;
350 : }
351 : int
352 0 : ed25519_cert_extension_set_ext_type(ed25519_cert_extension_t *inp, uint8_t val)
353 : {
354 0 : inp->ext_type = val;
355 0 : return 0;
356 : }
357 : uint8_t
358 0 : ed25519_cert_extension_get_ext_flags(const ed25519_cert_extension_t *inp)
359 : {
360 0 : return inp->ext_flags;
361 : }
362 : int
363 0 : ed25519_cert_extension_set_ext_flags(ed25519_cert_extension_t *inp, uint8_t val)
364 : {
365 0 : inp->ext_flags = val;
366 0 : return 0;
367 : }
368 : size_t
369 0 : ed25519_cert_extension_getlen_un_signing_key(const ed25519_cert_extension_t *inp)
370 : {
371 0 : (void)inp; return 32;
372 : }
373 :
374 : uint8_t
375 0 : ed25519_cert_extension_get_un_signing_key(ed25519_cert_extension_t *inp, size_t idx)
376 : {
377 0 : trunnel_assert(idx < 32);
378 0 : return inp->un_signing_key[idx];
379 : }
380 :
381 : uint8_t
382 0 : ed25519_cert_extension_getconst_un_signing_key(const ed25519_cert_extension_t *inp, size_t idx)
383 : {
384 0 : return ed25519_cert_extension_get_un_signing_key((ed25519_cert_extension_t*)inp, idx);
385 : }
386 : int
387 0 : ed25519_cert_extension_set_un_signing_key(ed25519_cert_extension_t *inp, size_t idx, uint8_t elt)
388 : {
389 0 : trunnel_assert(idx < 32);
390 0 : inp->un_signing_key[idx] = elt;
391 0 : return 0;
392 : }
393 :
394 : uint8_t *
395 0 : ed25519_cert_extension_getarray_un_signing_key(ed25519_cert_extension_t *inp)
396 : {
397 0 : return inp->un_signing_key;
398 : }
399 : const uint8_t *
400 0 : ed25519_cert_extension_getconstarray_un_signing_key(const ed25519_cert_extension_t *inp)
401 : {
402 0 : return (const uint8_t *)ed25519_cert_extension_getarray_un_signing_key((ed25519_cert_extension_t*)inp);
403 : }
404 : size_t
405 0 : ed25519_cert_extension_getlen_un_unparsed(const ed25519_cert_extension_t *inp)
406 : {
407 0 : return TRUNNEL_DYNARRAY_LEN(&inp->un_unparsed);
408 : }
409 :
410 : uint8_t
411 0 : ed25519_cert_extension_get_un_unparsed(ed25519_cert_extension_t *inp, size_t idx)
412 : {
413 0 : return TRUNNEL_DYNARRAY_GET(&inp->un_unparsed, idx);
414 : }
415 :
416 : uint8_t
417 0 : ed25519_cert_extension_getconst_un_unparsed(const ed25519_cert_extension_t *inp, size_t idx)
418 : {
419 0 : return ed25519_cert_extension_get_un_unparsed((ed25519_cert_extension_t*)inp, idx);
420 : }
421 : int
422 0 : ed25519_cert_extension_set_un_unparsed(ed25519_cert_extension_t *inp, size_t idx, uint8_t elt)
423 : {
424 0 : TRUNNEL_DYNARRAY_SET(&inp->un_unparsed, idx, elt);
425 0 : return 0;
426 : }
427 : int
428 0 : ed25519_cert_extension_add_un_unparsed(ed25519_cert_extension_t *inp, uint8_t elt)
429 : {
430 0 : TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->un_unparsed, elt, {});
431 0 : return 0;
432 0 : trunnel_alloc_failed:
433 0 : TRUNNEL_SET_ERROR_CODE(inp);
434 0 : return -1;
435 : }
436 :
437 : uint8_t *
438 0 : ed25519_cert_extension_getarray_un_unparsed(ed25519_cert_extension_t *inp)
439 : {
440 0 : return inp->un_unparsed.elts_;
441 : }
442 : const uint8_t *
443 0 : ed25519_cert_extension_getconstarray_un_unparsed(const ed25519_cert_extension_t *inp)
444 : {
445 0 : return (const uint8_t *)ed25519_cert_extension_getarray_un_unparsed((ed25519_cert_extension_t*)inp);
446 : }
447 : int
448 0 : ed25519_cert_extension_setlen_un_unparsed(ed25519_cert_extension_t *inp, size_t newlen)
449 : {
450 0 : uint8_t *newptr;
451 0 : newptr = trunnel_dynarray_setlen(&inp->un_unparsed.allocated_,
452 0 : &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 0 : if (newlen != 0 && newptr == NULL)
456 0 : goto trunnel_alloc_failed;
457 0 : inp->un_unparsed.elts_ = newptr;
458 0 : return 0;
459 0 : trunnel_alloc_failed:
460 0 : TRUNNEL_SET_ERROR_CODE(inp);
461 0 : return -1;
462 : }
463 : const char *
464 1276 : ed25519_cert_extension_check(const ed25519_cert_extension_t *obj)
465 : {
466 1276 : if (obj == NULL)
467 : return "Object was NULL";
468 1276 : if (obj->trunnel_error_code_)
469 0 : return "A set function failed on this object";
470 : switch (obj->ext_type) {
471 :
472 : case CERTEXT_SIGNED_WITH_KEY:
473 : break;
474 :
475 : default:
476 : break;
477 : }
478 : return NULL;
479 : }
480 :
481 : ssize_t
482 319 : ed25519_cert_extension_encoded_len(const ed25519_cert_extension_t *obj)
483 : {
484 319 : ssize_t result = 0;
485 :
486 319 : if (NULL != ed25519_cert_extension_check(obj))
487 : return -1;
488 :
489 :
490 : /* Length of u16 ext_length */
491 319 : result += 2;
492 :
493 : /* Length of u8 ext_type */
494 319 : result += 1;
495 :
496 : /* Length of u8 ext_flags */
497 319 : result += 1;
498 319 : switch (obj->ext_type) {
499 :
500 : case CERTEXT_SIGNED_WITH_KEY:
501 :
502 : /* Length of u8 un_signing_key[32] */
503 : result += 32;
504 : break;
505 :
506 0 : default:
507 :
508 : /* Length of u8 un_unparsed[] */
509 0 : result += TRUNNEL_DYNARRAY_LEN(&obj->un_unparsed);
510 0 : break;
511 : }
512 : return result;
513 : }
514 : int
515 0 : ed25519_cert_extension_clear_errors(ed25519_cert_extension_t *obj)
516 : {
517 0 : int r = obj->trunnel_error_code_;
518 0 : obj->trunnel_error_code_ = 0;
519 0 : return r;
520 : }
521 : ssize_t
522 319 : ed25519_cert_extension_encode(uint8_t *output, const size_t avail, const ed25519_cert_extension_t *obj)
523 : {
524 319 : ssize_t result = 0;
525 319 : size_t written = 0;
526 319 : uint8_t *ptr = output;
527 319 : const char *msg;
528 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
529 : const ssize_t encoded_len = ed25519_cert_extension_encoded_len(obj);
530 : #endif
531 :
532 319 : uint8_t *backptr_ext_length = NULL;
533 :
534 319 : if (NULL != (msg = ed25519_cert_extension_check(obj)))
535 0 : goto check_failed;
536 :
537 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
538 : trunnel_assert(encoded_len >= 0);
539 : #endif
540 :
541 : /* Encode u16 ext_length */
542 319 : backptr_ext_length = ptr;
543 319 : trunnel_assert(written <= avail);
544 319 : if (avail - written < 2)
545 0 : goto truncated;
546 319 : trunnel_set_uint16(ptr, trunnel_htons(obj->ext_length));
547 319 : written += 2; ptr += 2;
548 :
549 : /* Encode u8 ext_type */
550 319 : trunnel_assert(written <= avail);
551 319 : if (avail - written < 1)
552 0 : goto truncated;
553 319 : trunnel_set_uint8(ptr, (obj->ext_type));
554 319 : written += 1; ptr += 1;
555 :
556 : /* Encode u8 ext_flags */
557 319 : trunnel_assert(written <= avail);
558 319 : if (avail - written < 1)
559 0 : goto truncated;
560 319 : trunnel_set_uint8(ptr, (obj->ext_flags));
561 319 : written += 1; ptr += 1;
562 : {
563 319 : size_t written_before_union = written;
564 :
565 : /* Encode union un[ext_type] */
566 319 : trunnel_assert(written <= avail);
567 319 : switch (obj->ext_type) {
568 :
569 : case CERTEXT_SIGNED_WITH_KEY:
570 :
571 : /* Encode u8 un_signing_key[32] */
572 319 : trunnel_assert(written <= avail);
573 319 : if (avail - written < 32)
574 0 : goto truncated;
575 319 : memcpy(ptr, obj->un_signing_key, 32);
576 319 : written += 32; ptr += 32;
577 319 : break;
578 :
579 0 : default:
580 :
581 : /* Encode u8 un_unparsed[] */
582 : {
583 0 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->un_unparsed);
584 0 : trunnel_assert(written <= avail);
585 0 : if (avail - written < elt_len)
586 0 : goto truncated;
587 0 : if (elt_len)
588 0 : memcpy(ptr, obj->un_unparsed.elts_, elt_len);
589 0 : written += elt_len; ptr += elt_len;
590 : }
591 0 : break;
592 : }
593 : /* Write the length field back to ext_length */
594 319 : trunnel_assert(written >= written_before_union);
595 : #if UINT16_MAX < SIZE_MAX
596 319 : if (written - written_before_union > UINT16_MAX)
597 0 : goto check_failed;
598 : #endif
599 319 : trunnel_set_uint16(backptr_ext_length, trunnel_htons(written - written_before_union));
600 : }
601 :
602 :
603 319 : trunnel_assert(ptr == output + written);
604 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
605 : {
606 : trunnel_assert(encoded_len >= 0);
607 : trunnel_assert((size_t)encoded_len == written);
608 : }
609 :
610 : #endif
611 :
612 319 : return written;
613 :
614 0 : truncated:
615 0 : result = -2;
616 0 : goto fail;
617 0 : check_failed:
618 0 : (void)msg;
619 0 : result = -1;
620 0 : goto fail;
621 : fail:
622 : trunnel_assert(result < 0);
623 : return result;
624 : }
625 :
626 : /** As ed25519_cert_extension_parse(), but do not allocate the output
627 : * object.
628 : */
629 : static ssize_t
630 1835 : ed25519_cert_extension_parse_into(ed25519_cert_extension_t *obj, const uint8_t *input, const size_t len_in)
631 : {
632 1835 : const uint8_t *ptr = input;
633 1835 : size_t remaining = len_in;
634 1835 : ssize_t result = 0;
635 1835 : (void)result;
636 :
637 : /* Parse u16 ext_length */
638 1835 : CHECK_REMAINING(2, truncated);
639 1829 : obj->ext_length = trunnel_ntohs(trunnel_get_uint16(ptr));
640 1829 : remaining -= 2; ptr += 2;
641 :
642 : /* Parse u8 ext_type */
643 1829 : CHECK_REMAINING(1, truncated);
644 1826 : obj->ext_type = (trunnel_get_uint8(ptr));
645 1826 : remaining -= 1; ptr += 1;
646 :
647 : /* Parse u8 ext_flags */
648 1826 : CHECK_REMAINING(1, truncated);
649 1823 : obj->ext_flags = (trunnel_get_uint8(ptr));
650 1823 : remaining -= 1; ptr += 1;
651 : {
652 1823 : size_t remaining_after;
653 1823 : CHECK_REMAINING(obj->ext_length, truncated);
654 1821 : remaining_after = remaining - obj->ext_length;
655 1821 : remaining = obj->ext_length;
656 :
657 : /* Parse union un[ext_type] */
658 1821 : switch (obj->ext_type) {
659 :
660 1113 : case CERTEXT_SIGNED_WITH_KEY:
661 :
662 : /* Parse u8 un_signing_key[32] */
663 1113 : CHECK_REMAINING(32, fail);
664 1111 : memcpy(obj->un_signing_key, ptr, 32);
665 1111 : remaining -= 32; ptr += 32;
666 1111 : break;
667 :
668 708 : default:
669 :
670 : /* Parse u8 un_unparsed[] */
671 708 : TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->un_unparsed, remaining, {});
672 708 : obj->un_unparsed.n_ = remaining;
673 708 : if (remaining)
674 81 : memcpy(obj->un_unparsed.elts_, ptr, remaining);
675 708 : ptr += remaining; remaining -= remaining;
676 708 : break;
677 : }
678 1819 : if (remaining != 0)
679 1 : goto fail;
680 1818 : remaining = remaining_after;
681 : }
682 1818 : trunnel_assert(ptr + remaining == input + len_in);
683 1818 : return len_in - remaining;
684 :
685 : truncated:
686 : return -2;
687 0 : trunnel_alloc_failed:
688 0 : return -1;
689 : fail:
690 1835 : result = -1;
691 : return result;
692 : }
693 :
694 : ssize_t
695 1835 : ed25519_cert_extension_parse(ed25519_cert_extension_t **output, const uint8_t *input, const size_t len_in)
696 : {
697 1835 : ssize_t result;
698 1835 : *output = ed25519_cert_extension_new();
699 1835 : if (NULL == *output)
700 : return -1;
701 1835 : result = ed25519_cert_extension_parse_into(*output, input, len_in);
702 1835 : if (result < 0) {
703 17 : ed25519_cert_extension_free(*output);
704 17 : *output = NULL;
705 : }
706 : return result;
707 : }
708 : extend1_cell_body_t *
709 2 : extend1_cell_body_new(void)
710 : {
711 2 : extend1_cell_body_t *val = trunnel_calloc(1, sizeof(extend1_cell_body_t));
712 2 : if (NULL == val)
713 0 : return NULL;
714 : return val;
715 : }
716 :
717 : /** Release all storage held inside 'obj', but do not free 'obj'.
718 : */
719 : static void
720 : extend1_cell_body_clear(extend1_cell_body_t *obj)
721 : {
722 : (void) obj;
723 : }
724 :
725 : void
726 2 : extend1_cell_body_free(extend1_cell_body_t *obj)
727 : {
728 2 : if (obj == NULL)
729 : return;
730 2 : extend1_cell_body_clear(obj);
731 2 : trunnel_memwipe(obj, sizeof(extend1_cell_body_t));
732 2 : trunnel_free_(obj);
733 : }
734 :
735 : uint32_t
736 0 : extend1_cell_body_get_ipv4addr(const extend1_cell_body_t *inp)
737 : {
738 0 : return inp->ipv4addr;
739 : }
740 : int
741 0 : extend1_cell_body_set_ipv4addr(extend1_cell_body_t *inp, uint32_t val)
742 : {
743 0 : inp->ipv4addr = val;
744 0 : return 0;
745 : }
746 : uint16_t
747 0 : extend1_cell_body_get_port(const extend1_cell_body_t *inp)
748 : {
749 0 : return inp->port;
750 : }
751 : int
752 0 : extend1_cell_body_set_port(extend1_cell_body_t *inp, uint16_t val)
753 : {
754 0 : inp->port = val;
755 0 : return 0;
756 : }
757 : size_t
758 0 : extend1_cell_body_getlen_onionskin(const extend1_cell_body_t *inp)
759 : {
760 0 : (void)inp; return 186;
761 : }
762 :
763 : uint8_t
764 0 : extend1_cell_body_get_onionskin(extend1_cell_body_t *inp, size_t idx)
765 : {
766 0 : trunnel_assert(idx < 186);
767 0 : return inp->onionskin[idx];
768 : }
769 :
770 : uint8_t
771 0 : extend1_cell_body_getconst_onionskin(const extend1_cell_body_t *inp, size_t idx)
772 : {
773 0 : return extend1_cell_body_get_onionskin((extend1_cell_body_t*)inp, idx);
774 : }
775 : int
776 0 : extend1_cell_body_set_onionskin(extend1_cell_body_t *inp, size_t idx, uint8_t elt)
777 : {
778 0 : trunnel_assert(idx < 186);
779 0 : inp->onionskin[idx] = elt;
780 0 : return 0;
781 : }
782 :
783 : uint8_t *
784 0 : extend1_cell_body_getarray_onionskin(extend1_cell_body_t *inp)
785 : {
786 0 : return inp->onionskin;
787 : }
788 : const uint8_t *
789 0 : extend1_cell_body_getconstarray_onionskin(const extend1_cell_body_t *inp)
790 : {
791 0 : return (const uint8_t *)extend1_cell_body_getarray_onionskin((extend1_cell_body_t*)inp);
792 : }
793 : size_t
794 0 : extend1_cell_body_getlen_identity(const extend1_cell_body_t *inp)
795 : {
796 0 : (void)inp; return 20;
797 : }
798 :
799 : uint8_t
800 0 : extend1_cell_body_get_identity(extend1_cell_body_t *inp, size_t idx)
801 : {
802 0 : trunnel_assert(idx < 20);
803 0 : return inp->identity[idx];
804 : }
805 :
806 : uint8_t
807 0 : extend1_cell_body_getconst_identity(const extend1_cell_body_t *inp, size_t idx)
808 : {
809 0 : return extend1_cell_body_get_identity((extend1_cell_body_t*)inp, idx);
810 : }
811 : int
812 0 : extend1_cell_body_set_identity(extend1_cell_body_t *inp, size_t idx, uint8_t elt)
813 : {
814 0 : trunnel_assert(idx < 20);
815 0 : inp->identity[idx] = elt;
816 0 : return 0;
817 : }
818 :
819 : uint8_t *
820 0 : extend1_cell_body_getarray_identity(extend1_cell_body_t *inp)
821 : {
822 0 : return inp->identity;
823 : }
824 : const uint8_t *
825 0 : extend1_cell_body_getconstarray_identity(const extend1_cell_body_t *inp)
826 : {
827 0 : return (const uint8_t *)extend1_cell_body_getarray_identity((extend1_cell_body_t*)inp);
828 : }
829 : const char *
830 0 : extend1_cell_body_check(const extend1_cell_body_t *obj)
831 : {
832 0 : if (obj == NULL)
833 : return "Object was NULL";
834 0 : if (obj->trunnel_error_code_)
835 0 : return "A set function failed on this object";
836 : return NULL;
837 : }
838 :
839 : ssize_t
840 0 : extend1_cell_body_encoded_len(const extend1_cell_body_t *obj)
841 : {
842 0 : ssize_t result = 0;
843 :
844 0 : if (NULL != extend1_cell_body_check(obj))
845 0 : return -1;
846 :
847 :
848 : /* Length of u32 ipv4addr */
849 : result += 4;
850 :
851 : /* Length of u16 port */
852 : result += 2;
853 :
854 : /* Length of u8 onionskin[186] */
855 : result += 186;
856 :
857 : /* Length of u8 identity[20] */
858 0 : result += 20;
859 : return result;
860 : }
861 : int
862 0 : extend1_cell_body_clear_errors(extend1_cell_body_t *obj)
863 : {
864 0 : int r = obj->trunnel_error_code_;
865 0 : obj->trunnel_error_code_ = 0;
866 0 : return r;
867 : }
868 : ssize_t
869 0 : extend1_cell_body_encode(uint8_t *output, const size_t avail, const extend1_cell_body_t *obj)
870 : {
871 0 : ssize_t result = 0;
872 0 : size_t written = 0;
873 0 : uint8_t *ptr = output;
874 0 : const char *msg;
875 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
876 : const ssize_t encoded_len = extend1_cell_body_encoded_len(obj);
877 : #endif
878 :
879 0 : if (NULL != (msg = extend1_cell_body_check(obj)))
880 0 : goto check_failed;
881 :
882 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
883 : trunnel_assert(encoded_len >= 0);
884 : #endif
885 :
886 : /* Encode u32 ipv4addr */
887 0 : trunnel_assert(written <= avail);
888 0 : if (avail - written < 4)
889 0 : goto truncated;
890 0 : trunnel_set_uint32(ptr, trunnel_htonl(obj->ipv4addr));
891 0 : written += 4; ptr += 4;
892 :
893 : /* Encode u16 port */
894 0 : trunnel_assert(written <= avail);
895 0 : if (avail - written < 2)
896 0 : goto truncated;
897 0 : trunnel_set_uint16(ptr, trunnel_htons(obj->port));
898 0 : written += 2; ptr += 2;
899 :
900 : /* Encode u8 onionskin[186] */
901 0 : trunnel_assert(written <= avail);
902 0 : if (avail - written < 186)
903 0 : goto truncated;
904 0 : memcpy(ptr, obj->onionskin, 186);
905 0 : written += 186; ptr += 186;
906 :
907 : /* Encode u8 identity[20] */
908 0 : trunnel_assert(written <= avail);
909 0 : if (avail - written < 20)
910 0 : goto truncated;
911 0 : memcpy(ptr, obj->identity, 20);
912 0 : written += 20; ptr += 20;
913 :
914 :
915 0 : trunnel_assert(ptr == output + written);
916 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
917 : {
918 : trunnel_assert(encoded_len >= 0);
919 : trunnel_assert((size_t)encoded_len == written);
920 : }
921 :
922 : #endif
923 :
924 : return written;
925 :
926 0 : truncated:
927 0 : result = -2;
928 0 : goto fail;
929 0 : check_failed:
930 0 : (void)msg;
931 0 : result = -1;
932 0 : goto fail;
933 : fail:
934 : trunnel_assert(result < 0);
935 : return result;
936 : }
937 :
938 : /** As extend1_cell_body_parse(), but do not allocate the output
939 : * object.
940 : */
941 : static ssize_t
942 2 : extend1_cell_body_parse_into(extend1_cell_body_t *obj, const uint8_t *input, const size_t len_in)
943 : {
944 2 : const uint8_t *ptr = input;
945 2 : size_t remaining = len_in;
946 2 : ssize_t result = 0;
947 2 : (void)result;
948 :
949 : /* Parse u32 ipv4addr */
950 2 : CHECK_REMAINING(4, truncated);
951 2 : obj->ipv4addr = trunnel_ntohl(trunnel_get_uint32(ptr));
952 2 : remaining -= 4; ptr += 4;
953 :
954 : /* Parse u16 port */
955 2 : CHECK_REMAINING(2, truncated);
956 2 : obj->port = trunnel_ntohs(trunnel_get_uint16(ptr));
957 2 : remaining -= 2; ptr += 2;
958 :
959 : /* Parse u8 onionskin[186] */
960 2 : CHECK_REMAINING(186, truncated);
961 2 : memcpy(obj->onionskin, ptr, 186);
962 2 : remaining -= 186; ptr += 186;
963 :
964 : /* Parse u8 identity[20] */
965 2 : CHECK_REMAINING(20, truncated);
966 2 : memcpy(obj->identity, ptr, 20);
967 2 : remaining -= 20; ptr += 20;
968 2 : trunnel_assert(ptr + remaining == input + len_in);
969 : return len_in - remaining;
970 :
971 : truncated:
972 : return -2;
973 : }
974 :
975 : ssize_t
976 2 : extend1_cell_body_parse(extend1_cell_body_t **output, const uint8_t *input, const size_t len_in)
977 : {
978 2 : ssize_t result;
979 2 : *output = extend1_cell_body_new();
980 2 : if (NULL == *output)
981 : return -1;
982 2 : result = extend1_cell_body_parse_into(*output, input, len_in);
983 2 : if (result < 0) {
984 0 : extend1_cell_body_free(*output);
985 0 : *output = NULL;
986 : }
987 : return result;
988 : }
989 : link_specifier_t *
990 26563 : link_specifier_new(void)
991 : {
992 26563 : link_specifier_t *val = trunnel_calloc(1, sizeof(link_specifier_t));
993 26563 : if (NULL == val)
994 0 : return NULL;
995 : return val;
996 : }
997 :
998 : /** Release all storage held inside 'obj', but do not free 'obj'.
999 : */
1000 : static void
1001 26547 : link_specifier_clear(link_specifier_t *obj)
1002 : {
1003 26547 : (void) obj;
1004 26547 : TRUNNEL_DYNARRAY_WIPE(&obj->un_unrecognized);
1005 26547 : TRUNNEL_DYNARRAY_CLEAR(&obj->un_unrecognized);
1006 26547 : }
1007 :
1008 : void
1009 26547 : link_specifier_free(link_specifier_t *obj)
1010 : {
1011 26547 : if (obj == NULL)
1012 : return;
1013 26547 : link_specifier_clear(obj);
1014 26547 : trunnel_memwipe(obj, sizeof(link_specifier_t));
1015 26547 : trunnel_free_(obj);
1016 : }
1017 :
1018 : uint8_t
1019 335 : link_specifier_get_ls_type(const link_specifier_t *inp)
1020 : {
1021 335 : return inp->ls_type;
1022 : }
1023 : int
1024 207 : link_specifier_set_ls_type(link_specifier_t *inp, uint8_t val)
1025 : {
1026 207 : inp->ls_type = val;
1027 207 : return 0;
1028 : }
1029 : uint8_t
1030 0 : link_specifier_get_ls_len(const link_specifier_t *inp)
1031 : {
1032 0 : return inp->ls_len;
1033 : }
1034 : int
1035 9 : link_specifier_set_ls_len(link_specifier_t *inp, uint8_t val)
1036 : {
1037 9 : inp->ls_len = val;
1038 9 : return 0;
1039 : }
1040 : uint32_t
1041 109 : link_specifier_get_un_ipv4_addr(const link_specifier_t *inp)
1042 : {
1043 109 : return inp->un_ipv4_addr;
1044 : }
1045 : int
1046 70 : link_specifier_set_un_ipv4_addr(link_specifier_t *inp, uint32_t val)
1047 : {
1048 70 : inp->un_ipv4_addr = val;
1049 70 : return 0;
1050 : }
1051 : uint16_t
1052 109 : link_specifier_get_un_ipv4_port(const link_specifier_t *inp)
1053 : {
1054 109 : return inp->un_ipv4_port;
1055 : }
1056 : int
1057 70 : link_specifier_set_un_ipv4_port(link_specifier_t *inp, uint16_t val)
1058 : {
1059 70 : inp->un_ipv4_port = val;
1060 70 : return 0;
1061 : }
1062 : size_t
1063 32 : link_specifier_getlen_un_ipv6_addr(const link_specifier_t *inp)
1064 : {
1065 32 : (void)inp; return 16;
1066 : }
1067 :
1068 : uint8_t
1069 0 : link_specifier_get_un_ipv6_addr(link_specifier_t *inp, size_t idx)
1070 : {
1071 0 : trunnel_assert(idx < 16);
1072 0 : return inp->un_ipv6_addr[idx];
1073 : }
1074 :
1075 : uint8_t
1076 0 : link_specifier_getconst_un_ipv6_addr(const link_specifier_t *inp, size_t idx)
1077 : {
1078 0 : return link_specifier_get_un_ipv6_addr((link_specifier_t*)inp, idx);
1079 : }
1080 : int
1081 0 : link_specifier_set_un_ipv6_addr(link_specifier_t *inp, size_t idx, uint8_t elt)
1082 : {
1083 0 : trunnel_assert(idx < 16);
1084 0 : inp->un_ipv6_addr[idx] = elt;
1085 0 : return 0;
1086 : }
1087 :
1088 : uint8_t *
1089 44 : link_specifier_getarray_un_ipv6_addr(link_specifier_t *inp)
1090 : {
1091 44 : return inp->un_ipv6_addr;
1092 : }
1093 : const uint8_t *
1094 21 : link_specifier_getconstarray_un_ipv6_addr(const link_specifier_t *inp)
1095 : {
1096 21 : return (const uint8_t *)link_specifier_getarray_un_ipv6_addr((link_specifier_t*)inp);
1097 : }
1098 : uint16_t
1099 21 : link_specifier_get_un_ipv6_port(const link_specifier_t *inp)
1100 : {
1101 21 : return inp->un_ipv6_port;
1102 : }
1103 : int
1104 23 : link_specifier_set_un_ipv6_port(link_specifier_t *inp, uint16_t val)
1105 : {
1106 23 : inp->un_ipv6_port = val;
1107 23 : return 0;
1108 : }
1109 : size_t
1110 230 : link_specifier_getlen_un_legacy_id(const link_specifier_t *inp)
1111 : {
1112 230 : (void)inp; return 20;
1113 : }
1114 :
1115 : uint8_t
1116 0 : link_specifier_get_un_legacy_id(link_specifier_t *inp, size_t idx)
1117 : {
1118 0 : trunnel_assert(idx < 20);
1119 0 : return inp->un_legacy_id[idx];
1120 : }
1121 :
1122 : uint8_t
1123 0 : link_specifier_getconst_un_legacy_id(const link_specifier_t *inp, size_t idx)
1124 : {
1125 0 : return link_specifier_get_un_legacy_id((link_specifier_t*)inp, idx);
1126 : }
1127 : int
1128 0 : link_specifier_set_un_legacy_id(link_specifier_t *inp, size_t idx, uint8_t elt)
1129 : {
1130 0 : trunnel_assert(idx < 20);
1131 0 : inp->un_legacy_id[idx] = elt;
1132 0 : return 0;
1133 : }
1134 :
1135 : uint8_t *
1136 230 : link_specifier_getarray_un_legacy_id(link_specifier_t *inp)
1137 : {
1138 230 : return inp->un_legacy_id;
1139 : }
1140 : const uint8_t *
1141 127 : link_specifier_getconstarray_un_legacy_id(const link_specifier_t *inp)
1142 : {
1143 127 : return (const uint8_t *)link_specifier_getarray_un_legacy_id((link_specifier_t*)inp);
1144 : }
1145 : size_t
1146 4 : link_specifier_getlen_un_ed25519_id(const link_specifier_t *inp)
1147 : {
1148 4 : (void)inp; return 32;
1149 : }
1150 :
1151 : uint8_t
1152 0 : link_specifier_get_un_ed25519_id(link_specifier_t *inp, size_t idx)
1153 : {
1154 0 : trunnel_assert(idx < 32);
1155 0 : return inp->un_ed25519_id[idx];
1156 : }
1157 :
1158 : uint8_t
1159 0 : link_specifier_getconst_un_ed25519_id(const link_specifier_t *inp, size_t idx)
1160 : {
1161 0 : return link_specifier_get_un_ed25519_id((link_specifier_t*)inp, idx);
1162 : }
1163 : int
1164 0 : link_specifier_set_un_ed25519_id(link_specifier_t *inp, size_t idx, uint8_t elt)
1165 : {
1166 0 : trunnel_assert(idx < 32);
1167 0 : inp->un_ed25519_id[idx] = elt;
1168 0 : return 0;
1169 : }
1170 :
1171 : uint8_t *
1172 2 : link_specifier_getarray_un_ed25519_id(link_specifier_t *inp)
1173 : {
1174 2 : return inp->un_ed25519_id;
1175 : }
1176 : const uint8_t *
1177 0 : link_specifier_getconstarray_un_ed25519_id(const link_specifier_t *inp)
1178 : {
1179 0 : return (const uint8_t *)link_specifier_getarray_un_ed25519_id((link_specifier_t*)inp);
1180 : }
1181 : size_t
1182 0 : link_specifier_getlen_un_unrecognized(const link_specifier_t *inp)
1183 : {
1184 0 : return TRUNNEL_DYNARRAY_LEN(&inp->un_unrecognized);
1185 : }
1186 :
1187 : uint8_t
1188 0 : link_specifier_get_un_unrecognized(link_specifier_t *inp, size_t idx)
1189 : {
1190 0 : return TRUNNEL_DYNARRAY_GET(&inp->un_unrecognized, idx);
1191 : }
1192 :
1193 : uint8_t
1194 0 : link_specifier_getconst_un_unrecognized(const link_specifier_t *inp, size_t idx)
1195 : {
1196 0 : return link_specifier_get_un_unrecognized((link_specifier_t*)inp, idx);
1197 : }
1198 : int
1199 0 : link_specifier_set_un_unrecognized(link_specifier_t *inp, size_t idx, uint8_t elt)
1200 : {
1201 0 : TRUNNEL_DYNARRAY_SET(&inp->un_unrecognized, idx, elt);
1202 0 : return 0;
1203 : }
1204 : int
1205 0 : link_specifier_add_un_unrecognized(link_specifier_t *inp, uint8_t elt)
1206 : {
1207 0 : TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->un_unrecognized, elt, {});
1208 0 : return 0;
1209 0 : trunnel_alloc_failed:
1210 0 : TRUNNEL_SET_ERROR_CODE(inp);
1211 0 : return -1;
1212 : }
1213 :
1214 : uint8_t *
1215 0 : link_specifier_getarray_un_unrecognized(link_specifier_t *inp)
1216 : {
1217 0 : return inp->un_unrecognized.elts_;
1218 : }
1219 : const uint8_t *
1220 0 : link_specifier_getconstarray_un_unrecognized(const link_specifier_t *inp)
1221 : {
1222 0 : return (const uint8_t *)link_specifier_getarray_un_unrecognized((link_specifier_t*)inp);
1223 : }
1224 : int
1225 0 : link_specifier_setlen_un_unrecognized(link_specifier_t *inp, size_t newlen)
1226 : {
1227 0 : uint8_t *newptr;
1228 0 : newptr = trunnel_dynarray_setlen(&inp->un_unrecognized.allocated_,
1229 0 : &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 0 : if (newlen != 0 && newptr == NULL)
1233 0 : goto trunnel_alloc_failed;
1234 0 : inp->un_unrecognized.elts_ = newptr;
1235 0 : return 0;
1236 0 : trunnel_alloc_failed:
1237 0 : TRUNNEL_SET_ERROR_CODE(inp);
1238 0 : return -1;
1239 : }
1240 : const char *
1241 1878 : link_specifier_check(const link_specifier_t *obj)
1242 : {
1243 1878 : if (obj == NULL)
1244 : return "Object was NULL";
1245 1878 : if (obj->trunnel_error_code_)
1246 0 : return "A set function failed on this object";
1247 : switch (obj->ls_type) {
1248 :
1249 : case LS_IPV4:
1250 : break;
1251 :
1252 : case LS_IPV6:
1253 : break;
1254 :
1255 : case LS_LEGACY_ID:
1256 : break;
1257 :
1258 : case LS_ED25519_ID:
1259 : break;
1260 :
1261 : default:
1262 : break;
1263 : }
1264 : return NULL;
1265 : }
1266 :
1267 : ssize_t
1268 713 : link_specifier_encoded_len(const link_specifier_t *obj)
1269 : {
1270 713 : ssize_t result = 0;
1271 :
1272 713 : if (NULL != link_specifier_check(obj))
1273 : return -1;
1274 :
1275 :
1276 : /* Length of u8 ls_type */
1277 713 : result += 1;
1278 :
1279 : /* Length of u8 ls_len */
1280 713 : result += 1;
1281 713 : switch (obj->ls_type) {
1282 :
1283 : case LS_IPV4:
1284 :
1285 : /* Length of u32 un_ipv4_addr */
1286 : result += 4;
1287 :
1288 : /* Length of u16 un_ipv4_port */
1289 : result += 2;
1290 : break;
1291 :
1292 : case LS_IPV6:
1293 :
1294 : /* Length of u8 un_ipv6_addr[16] */
1295 : result += 16;
1296 :
1297 : /* Length of u16 un_ipv6_port */
1298 : result += 2;
1299 : break;
1300 :
1301 : case LS_LEGACY_ID:
1302 :
1303 : /* Length of u8 un_legacy_id[20] */
1304 : result += 20;
1305 : break;
1306 :
1307 : case LS_ED25519_ID:
1308 :
1309 : /* Length of u8 un_ed25519_id[32] */
1310 : result += 32;
1311 : break;
1312 :
1313 0 : default:
1314 :
1315 : /* Length of u8 un_unrecognized[] */
1316 0 : result += TRUNNEL_DYNARRAY_LEN(&obj->un_unrecognized);
1317 0 : break;
1318 : }
1319 : return result;
1320 : }
1321 : int
1322 0 : link_specifier_clear_errors(link_specifier_t *obj)
1323 : {
1324 0 : int r = obj->trunnel_error_code_;
1325 0 : obj->trunnel_error_code_ = 0;
1326 0 : return r;
1327 : }
1328 : ssize_t
1329 727 : link_specifier_encode(uint8_t *output, const size_t avail, const link_specifier_t *obj)
1330 : {
1331 727 : ssize_t result = 0;
1332 727 : size_t written = 0;
1333 727 : uint8_t *ptr = output;
1334 727 : const char *msg;
1335 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1336 : const ssize_t encoded_len = link_specifier_encoded_len(obj);
1337 : #endif
1338 :
1339 727 : uint8_t *backptr_ls_len = NULL;
1340 :
1341 727 : if (NULL != (msg = link_specifier_check(obj)))
1342 0 : goto check_failed;
1343 :
1344 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1345 : trunnel_assert(encoded_len >= 0);
1346 : #endif
1347 :
1348 : /* Encode u8 ls_type */
1349 727 : trunnel_assert(written <= avail);
1350 727 : if (avail - written < 1)
1351 0 : goto truncated;
1352 727 : trunnel_set_uint8(ptr, (obj->ls_type));
1353 727 : written += 1; ptr += 1;
1354 :
1355 : /* Encode u8 ls_len */
1356 727 : backptr_ls_len = ptr;
1357 727 : trunnel_assert(written <= avail);
1358 727 : if (avail - written < 1)
1359 0 : goto truncated;
1360 727 : trunnel_set_uint8(ptr, (obj->ls_len));
1361 727 : written += 1; ptr += 1;
1362 : {
1363 727 : size_t written_before_union = written;
1364 :
1365 : /* Encode union un[ls_type] */
1366 727 : trunnel_assert(written <= avail);
1367 727 : switch (obj->ls_type) {
1368 :
1369 : case LS_IPV4:
1370 :
1371 : /* Encode u32 un_ipv4_addr */
1372 277 : trunnel_assert(written <= avail);
1373 277 : if (avail - written < 4)
1374 0 : goto truncated;
1375 277 : trunnel_set_uint32(ptr, trunnel_htonl(obj->un_ipv4_addr));
1376 277 : written += 4; ptr += 4;
1377 :
1378 : /* Encode u16 un_ipv4_port */
1379 277 : trunnel_assert(written <= avail);
1380 277 : if (avail - written < 2)
1381 0 : goto truncated;
1382 277 : trunnel_set_uint16(ptr, trunnel_htons(obj->un_ipv4_port));
1383 277 : written += 2; ptr += 2;
1384 277 : break;
1385 :
1386 : case LS_IPV6:
1387 :
1388 : /* Encode u8 un_ipv6_addr[16] */
1389 92 : trunnel_assert(written <= avail);
1390 92 : if (avail - written < 16)
1391 0 : goto truncated;
1392 92 : memcpy(ptr, obj->un_ipv6_addr, 16);
1393 92 : written += 16; ptr += 16;
1394 :
1395 : /* Encode u16 un_ipv6_port */
1396 92 : trunnel_assert(written <= avail);
1397 92 : if (avail - written < 2)
1398 0 : goto truncated;
1399 92 : trunnel_set_uint16(ptr, trunnel_htons(obj->un_ipv6_port));
1400 92 : written += 2; ptr += 2;
1401 92 : break;
1402 :
1403 : case LS_LEGACY_ID:
1404 :
1405 : /* Encode u8 un_legacy_id[20] */
1406 357 : trunnel_assert(written <= avail);
1407 357 : if (avail - written < 20)
1408 0 : goto truncated;
1409 357 : memcpy(ptr, obj->un_legacy_id, 20);
1410 357 : written += 20; ptr += 20;
1411 357 : break;
1412 :
1413 : case LS_ED25519_ID:
1414 :
1415 : /* Encode u8 un_ed25519_id[32] */
1416 1 : trunnel_assert(written <= avail);
1417 1 : if (avail - written < 32)
1418 0 : goto truncated;
1419 1 : memcpy(ptr, obj->un_ed25519_id, 32);
1420 1 : written += 32; ptr += 32;
1421 1 : break;
1422 :
1423 0 : default:
1424 :
1425 : /* Encode u8 un_unrecognized[] */
1426 : {
1427 0 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->un_unrecognized);
1428 0 : trunnel_assert(written <= avail);
1429 0 : if (avail - written < elt_len)
1430 0 : goto truncated;
1431 0 : if (elt_len)
1432 0 : memcpy(ptr, obj->un_unrecognized.elts_, elt_len);
1433 0 : written += elt_len; ptr += elt_len;
1434 : }
1435 0 : break;
1436 : }
1437 : /* Write the length field back to ls_len */
1438 727 : trunnel_assert(written >= written_before_union);
1439 : #if UINT8_MAX < SIZE_MAX
1440 727 : if (written - written_before_union > UINT8_MAX)
1441 0 : goto check_failed;
1442 : #endif
1443 727 : trunnel_set_uint8(backptr_ls_len, (written - written_before_union));
1444 : }
1445 :
1446 :
1447 727 : trunnel_assert(ptr == output + written);
1448 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1449 : {
1450 : trunnel_assert(encoded_len >= 0);
1451 : trunnel_assert((size_t)encoded_len == written);
1452 : }
1453 :
1454 : #endif
1455 :
1456 727 : return written;
1457 :
1458 0 : truncated:
1459 0 : result = -2;
1460 0 : goto fail;
1461 0 : check_failed:
1462 0 : (void)msg;
1463 0 : result = -1;
1464 0 : goto fail;
1465 : fail:
1466 : trunnel_assert(result < 0);
1467 : return result;
1468 : }
1469 :
1470 : /** As link_specifier_parse(), but do not allocate the output object.
1471 : */
1472 : static ssize_t
1473 26337 : link_specifier_parse_into(link_specifier_t *obj, const uint8_t *input, const size_t len_in)
1474 : {
1475 26337 : const uint8_t *ptr = input;
1476 26337 : size_t remaining = len_in;
1477 26337 : ssize_t result = 0;
1478 26337 : (void)result;
1479 :
1480 : /* Parse u8 ls_type */
1481 26337 : CHECK_REMAINING(1, truncated);
1482 26241 : obj->ls_type = (trunnel_get_uint8(ptr));
1483 26241 : remaining -= 1; ptr += 1;
1484 :
1485 : /* Parse u8 ls_len */
1486 26241 : CHECK_REMAINING(1, truncated);
1487 26157 : obj->ls_len = (trunnel_get_uint8(ptr));
1488 26157 : remaining -= 1; ptr += 1;
1489 : {
1490 26157 : size_t remaining_after;
1491 26157 : CHECK_REMAINING(obj->ls_len, truncated);
1492 16692 : remaining_after = remaining - obj->ls_len;
1493 16692 : remaining = obj->ls_len;
1494 :
1495 : /* Parse union un[ls_type] */
1496 16692 : switch (obj->ls_type) {
1497 :
1498 380 : case LS_IPV4:
1499 :
1500 : /* Parse u32 un_ipv4_addr */
1501 380 : CHECK_REMAINING(4, fail);
1502 376 : obj->un_ipv4_addr = trunnel_ntohl(trunnel_get_uint32(ptr));
1503 376 : remaining -= 4; ptr += 4;
1504 :
1505 : /* Parse u16 un_ipv4_port */
1506 376 : CHECK_REMAINING(2, fail);
1507 375 : obj->un_ipv4_port = trunnel_ntohs(trunnel_get_uint16(ptr));
1508 375 : remaining -= 2; ptr += 2;
1509 375 : break;
1510 :
1511 153 : case LS_IPV6:
1512 :
1513 : /* Parse u8 un_ipv6_addr[16] */
1514 153 : CHECK_REMAINING(16, fail);
1515 147 : memcpy(obj->un_ipv6_addr, ptr, 16);
1516 147 : remaining -= 16; ptr += 16;
1517 :
1518 : /* Parse u16 un_ipv6_port */
1519 147 : CHECK_REMAINING(2, fail);
1520 146 : obj->un_ipv6_port = trunnel_ntohs(trunnel_get_uint16(ptr));
1521 146 : remaining -= 2; ptr += 2;
1522 146 : break;
1523 :
1524 459 : case LS_LEGACY_ID:
1525 :
1526 : /* Parse u8 un_legacy_id[20] */
1527 459 : CHECK_REMAINING(20, fail);
1528 451 : memcpy(obj->un_legacy_id, ptr, 20);
1529 451 : remaining -= 20; ptr += 20;
1530 451 : break;
1531 :
1532 63 : case LS_ED25519_ID:
1533 :
1534 : /* Parse u8 un_ed25519_id[32] */
1535 63 : CHECK_REMAINING(32, fail);
1536 54 : memcpy(obj->un_ed25519_id, ptr, 32);
1537 54 : remaining -= 32; ptr += 32;
1538 54 : break;
1539 :
1540 15637 : default:
1541 :
1542 : /* Parse u8 un_unrecognized[] */
1543 15637 : TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->un_unrecognized, remaining, {});
1544 15637 : obj->un_unrecognized.n_ = remaining;
1545 15637 : if (remaining)
1546 15552 : memcpy(obj->un_unrecognized.elts_, ptr, remaining);
1547 15637 : ptr += remaining; remaining -= remaining;
1548 15637 : break;
1549 : }
1550 16663 : if (remaining != 0)
1551 211 : goto fail;
1552 16452 : remaining = remaining_after;
1553 : }
1554 16452 : trunnel_assert(ptr + remaining == input + len_in);
1555 16452 : return len_in - remaining;
1556 :
1557 : truncated:
1558 : return -2;
1559 0 : trunnel_alloc_failed:
1560 0 : return -1;
1561 : fail:
1562 26337 : result = -1;
1563 : return result;
1564 : }
1565 :
1566 : ssize_t
1567 26337 : link_specifier_parse(link_specifier_t **output, const uint8_t *input, const size_t len_in)
1568 : {
1569 26337 : ssize_t result;
1570 26337 : *output = link_specifier_new();
1571 26337 : if (NULL == *output)
1572 : return -1;
1573 26337 : result = link_specifier_parse_into(*output, input, len_in);
1574 26337 : if (result < 0) {
1575 9885 : link_specifier_free(*output);
1576 9885 : *output = NULL;
1577 : }
1578 : return result;
1579 : }
1580 : ed25519_cert_t *
1581 1747 : ed25519_cert_new(void)
1582 : {
1583 1747 : ed25519_cert_t *val = trunnel_calloc(1, sizeof(ed25519_cert_t));
1584 1747 : if (NULL == val)
1585 : return NULL;
1586 1747 : val->version = 1;
1587 1747 : return val;
1588 : }
1589 :
1590 : /** Release all storage held inside 'obj', but do not free 'obj'.
1591 : */
1592 : static void
1593 1747 : ed25519_cert_clear(ed25519_cert_t *obj)
1594 : {
1595 1747 : (void) obj;
1596 : {
1597 :
1598 1747 : unsigned idx;
1599 3884 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
1600 2137 : ed25519_cert_extension_free(TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
1601 : }
1602 : }
1603 1747 : TRUNNEL_DYNARRAY_WIPE(&obj->ext);
1604 1747 : TRUNNEL_DYNARRAY_CLEAR(&obj->ext);
1605 1747 : }
1606 :
1607 : void
1608 1783 : ed25519_cert_free(ed25519_cert_t *obj)
1609 : {
1610 1783 : if (obj == NULL)
1611 : return;
1612 1747 : ed25519_cert_clear(obj);
1613 1747 : trunnel_memwipe(obj, sizeof(ed25519_cert_t));
1614 1747 : trunnel_free_(obj);
1615 : }
1616 :
1617 : uint8_t
1618 0 : ed25519_cert_get_version(const ed25519_cert_t *inp)
1619 : {
1620 0 : return inp->version;
1621 : }
1622 : int
1623 0 : ed25519_cert_set_version(ed25519_cert_t *inp, uint8_t val)
1624 : {
1625 0 : if (! ((val == 1))) {
1626 0 : TRUNNEL_SET_ERROR_CODE(inp);
1627 0 : return -1;
1628 : }
1629 0 : inp->version = val;
1630 0 : return 0;
1631 : }
1632 : uint8_t
1633 0 : ed25519_cert_get_cert_type(const ed25519_cert_t *inp)
1634 : {
1635 0 : return inp->cert_type;
1636 : }
1637 : int
1638 0 : ed25519_cert_set_cert_type(ed25519_cert_t *inp, uint8_t val)
1639 : {
1640 0 : inp->cert_type = val;
1641 0 : return 0;
1642 : }
1643 : uint32_t
1644 0 : ed25519_cert_get_exp_field(const ed25519_cert_t *inp)
1645 : {
1646 0 : return inp->exp_field;
1647 : }
1648 : int
1649 0 : ed25519_cert_set_exp_field(ed25519_cert_t *inp, uint32_t val)
1650 : {
1651 0 : inp->exp_field = val;
1652 0 : return 0;
1653 : }
1654 : uint8_t
1655 0 : ed25519_cert_get_cert_key_type(const ed25519_cert_t *inp)
1656 : {
1657 0 : return inp->cert_key_type;
1658 : }
1659 : int
1660 0 : ed25519_cert_set_cert_key_type(ed25519_cert_t *inp, uint8_t val)
1661 : {
1662 0 : inp->cert_key_type = val;
1663 0 : return 0;
1664 : }
1665 : size_t
1666 0 : ed25519_cert_getlen_certified_key(const ed25519_cert_t *inp)
1667 : {
1668 0 : (void)inp; return 32;
1669 : }
1670 :
1671 : uint8_t
1672 0 : ed25519_cert_get_certified_key(ed25519_cert_t *inp, size_t idx)
1673 : {
1674 0 : trunnel_assert(idx < 32);
1675 0 : return inp->certified_key[idx];
1676 : }
1677 :
1678 : uint8_t
1679 0 : ed25519_cert_getconst_certified_key(const ed25519_cert_t *inp, size_t idx)
1680 : {
1681 0 : return ed25519_cert_get_certified_key((ed25519_cert_t*)inp, idx);
1682 : }
1683 : int
1684 0 : ed25519_cert_set_certified_key(ed25519_cert_t *inp, size_t idx, uint8_t elt)
1685 : {
1686 0 : trunnel_assert(idx < 32);
1687 0 : inp->certified_key[idx] = elt;
1688 0 : return 0;
1689 : }
1690 :
1691 : uint8_t *
1692 0 : ed25519_cert_getarray_certified_key(ed25519_cert_t *inp)
1693 : {
1694 0 : return inp->certified_key;
1695 : }
1696 : const uint8_t *
1697 0 : ed25519_cert_getconstarray_certified_key(const ed25519_cert_t *inp)
1698 : {
1699 0 : return (const uint8_t *)ed25519_cert_getarray_certified_key((ed25519_cert_t*)inp);
1700 : }
1701 : uint8_t
1702 0 : ed25519_cert_get_n_extensions(const ed25519_cert_t *inp)
1703 : {
1704 0 : return inp->n_extensions;
1705 : }
1706 : int
1707 0 : ed25519_cert_set_n_extensions(ed25519_cert_t *inp, uint8_t val)
1708 : {
1709 0 : inp->n_extensions = val;
1710 0 : return 0;
1711 : }
1712 : size_t
1713 2362 : ed25519_cert_getlen_ext(const ed25519_cert_t *inp)
1714 : {
1715 2362 : return TRUNNEL_DYNARRAY_LEN(&inp->ext);
1716 : }
1717 :
1718 : struct ed25519_cert_extension_st *
1719 1160 : ed25519_cert_get_ext(ed25519_cert_t *inp, size_t idx)
1720 : {
1721 1160 : return TRUNNEL_DYNARRAY_GET(&inp->ext, idx);
1722 : }
1723 :
1724 : const struct ed25519_cert_extension_st *
1725 0 : ed25519_cert_getconst_ext(const ed25519_cert_t *inp, size_t idx)
1726 : {
1727 0 : return ed25519_cert_get_ext((ed25519_cert_t*)inp, idx);
1728 : }
1729 : int
1730 0 : ed25519_cert_set_ext(ed25519_cert_t *inp, size_t idx, struct ed25519_cert_extension_st * elt)
1731 : {
1732 0 : ed25519_cert_extension_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->ext, idx);
1733 0 : if (oldval && oldval != elt)
1734 0 : ed25519_cert_extension_free(oldval);
1735 0 : return ed25519_cert_set0_ext(inp, idx, elt);
1736 : }
1737 : int
1738 0 : ed25519_cert_set0_ext(ed25519_cert_t *inp, size_t idx, struct ed25519_cert_extension_st * elt)
1739 : {
1740 0 : TRUNNEL_DYNARRAY_SET(&inp->ext, idx, elt);
1741 0 : return 0;
1742 : }
1743 : int
1744 319 : ed25519_cert_add_ext(ed25519_cert_t *inp, struct ed25519_cert_extension_st * elt)
1745 : {
1746 : #if SIZE_MAX >= UINT8_MAX
1747 319 : if (inp->ext.n_ == UINT8_MAX)
1748 0 : goto trunnel_alloc_failed;
1749 : #endif
1750 319 : TRUNNEL_DYNARRAY_ADD(struct ed25519_cert_extension_st *, &inp->ext, elt, {});
1751 319 : return 0;
1752 0 : trunnel_alloc_failed:
1753 0 : TRUNNEL_SET_ERROR_CODE(inp);
1754 0 : return -1;
1755 : }
1756 :
1757 : struct ed25519_cert_extension_st * *
1758 0 : ed25519_cert_getarray_ext(ed25519_cert_t *inp)
1759 : {
1760 0 : return inp->ext.elts_;
1761 : }
1762 : const struct ed25519_cert_extension_st * const *
1763 0 : ed25519_cert_getconstarray_ext(const ed25519_cert_t *inp)
1764 : {
1765 0 : return (const struct ed25519_cert_extension_st * const *)ed25519_cert_getarray_ext((ed25519_cert_t*)inp);
1766 : }
1767 : int
1768 0 : ed25519_cert_setlen_ext(ed25519_cert_t *inp, size_t newlen)
1769 : {
1770 0 : struct ed25519_cert_extension_st * *newptr;
1771 : #if UINT8_MAX < SIZE_MAX
1772 0 : if (newlen > UINT8_MAX)
1773 0 : goto trunnel_alloc_failed;
1774 : #endif
1775 0 : newptr = trunnel_dynarray_setlen(&inp->ext.allocated_,
1776 0 : &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 0 : if (newlen != 0 && newptr == NULL)
1780 0 : goto trunnel_alloc_failed;
1781 0 : inp->ext.elts_ = newptr;
1782 0 : return 0;
1783 0 : trunnel_alloc_failed:
1784 0 : TRUNNEL_SET_ERROR_CODE(inp);
1785 0 : return -1;
1786 : }
1787 : size_t
1788 0 : ed25519_cert_getlen_signature(const ed25519_cert_t *inp)
1789 : {
1790 0 : (void)inp; return 64;
1791 : }
1792 :
1793 : uint8_t
1794 0 : ed25519_cert_get_signature(ed25519_cert_t *inp, size_t idx)
1795 : {
1796 0 : trunnel_assert(idx < 64);
1797 0 : return inp->signature[idx];
1798 : }
1799 :
1800 : uint8_t
1801 0 : ed25519_cert_getconst_signature(const ed25519_cert_t *inp, size_t idx)
1802 : {
1803 0 : return ed25519_cert_get_signature((ed25519_cert_t*)inp, idx);
1804 : }
1805 : int
1806 0 : ed25519_cert_set_signature(ed25519_cert_t *inp, size_t idx, uint8_t elt)
1807 : {
1808 0 : trunnel_assert(idx < 64);
1809 0 : inp->signature[idx] = elt;
1810 0 : return 0;
1811 : }
1812 :
1813 : uint8_t *
1814 0 : ed25519_cert_getarray_signature(ed25519_cert_t *inp)
1815 : {
1816 0 : return inp->signature;
1817 : }
1818 : const uint8_t *
1819 0 : ed25519_cert_getconstarray_signature(const ed25519_cert_t *inp)
1820 : {
1821 0 : return (const uint8_t *)ed25519_cert_getarray_signature((ed25519_cert_t*)inp);
1822 : }
1823 : const char *
1824 998 : ed25519_cert_check(const ed25519_cert_t *obj)
1825 : {
1826 998 : if (obj == NULL)
1827 : return "Object was NULL";
1828 998 : if (obj->trunnel_error_code_)
1829 : return "A set function failed on this object";
1830 998 : if (! (obj->version == 1))
1831 : return "Integer out of bounds";
1832 : {
1833 : const char *msg;
1834 :
1835 : unsigned idx;
1836 1636 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
1837 638 : if (NULL != (msg = ed25519_cert_extension_check(TRUNNEL_DYNARRAY_GET(&obj->ext, idx))))
1838 0 : return msg;
1839 : }
1840 : }
1841 998 : if (TRUNNEL_DYNARRAY_LEN(&obj->ext) != obj->n_extensions)
1842 0 : return "Length mismatch for ext";
1843 : return NULL;
1844 : }
1845 :
1846 : ssize_t
1847 499 : ed25519_cert_encoded_len(const ed25519_cert_t *obj)
1848 : {
1849 499 : ssize_t result = 0;
1850 :
1851 499 : if (NULL != ed25519_cert_check(obj))
1852 : return -1;
1853 :
1854 :
1855 : /* Length of u8 version IN [1] */
1856 : result += 1;
1857 :
1858 : /* Length of u8 cert_type */
1859 : result += 1;
1860 :
1861 : /* Length of u32 exp_field */
1862 : result += 4;
1863 :
1864 : /* Length of u8 cert_key_type */
1865 : result += 1;
1866 :
1867 : /* Length of u8 certified_key[32] */
1868 : result += 32;
1869 :
1870 : /* Length of u8 n_extensions */
1871 : result += 1;
1872 :
1873 : /* Length of struct ed25519_cert_extension ext[n_extensions] */
1874 : {
1875 :
1876 : unsigned idx;
1877 818 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
1878 319 : result += ed25519_cert_extension_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
1879 : }
1880 : }
1881 :
1882 : /* Length of u8 signature[64] */
1883 499 : result += 64;
1884 499 : return result;
1885 : }
1886 : int
1887 0 : ed25519_cert_clear_errors(ed25519_cert_t *obj)
1888 : {
1889 0 : int r = obj->trunnel_error_code_;
1890 0 : obj->trunnel_error_code_ = 0;
1891 0 : return r;
1892 : }
1893 : ssize_t
1894 499 : ed25519_cert_encode(uint8_t *output, const size_t avail, const ed25519_cert_t *obj)
1895 : {
1896 499 : ssize_t result = 0;
1897 499 : size_t written = 0;
1898 499 : uint8_t *ptr = output;
1899 499 : const char *msg;
1900 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1901 : const ssize_t encoded_len = ed25519_cert_encoded_len(obj);
1902 : #endif
1903 :
1904 499 : if (NULL != (msg = ed25519_cert_check(obj)))
1905 0 : goto check_failed;
1906 :
1907 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1908 : trunnel_assert(encoded_len >= 0);
1909 : #endif
1910 :
1911 : /* Encode u8 version IN [1] */
1912 499 : trunnel_assert(written <= avail);
1913 499 : if (avail - written < 1)
1914 0 : goto truncated;
1915 499 : trunnel_set_uint8(ptr, (obj->version));
1916 499 : written += 1; ptr += 1;
1917 :
1918 : /* Encode u8 cert_type */
1919 499 : trunnel_assert(written <= avail);
1920 499 : if (avail - written < 1)
1921 0 : goto truncated;
1922 499 : trunnel_set_uint8(ptr, (obj->cert_type));
1923 499 : written += 1; ptr += 1;
1924 :
1925 : /* Encode u32 exp_field */
1926 499 : trunnel_assert(written <= avail);
1927 499 : if (avail - written < 4)
1928 0 : goto truncated;
1929 499 : trunnel_set_uint32(ptr, trunnel_htonl(obj->exp_field));
1930 499 : written += 4; ptr += 4;
1931 :
1932 : /* Encode u8 cert_key_type */
1933 499 : trunnel_assert(written <= avail);
1934 499 : if (avail - written < 1)
1935 0 : goto truncated;
1936 499 : trunnel_set_uint8(ptr, (obj->cert_key_type));
1937 499 : written += 1; ptr += 1;
1938 :
1939 : /* Encode u8 certified_key[32] */
1940 499 : trunnel_assert(written <= avail);
1941 499 : if (avail - written < 32)
1942 0 : goto truncated;
1943 499 : memcpy(ptr, obj->certified_key, 32);
1944 499 : written += 32; ptr += 32;
1945 :
1946 : /* Encode u8 n_extensions */
1947 499 : trunnel_assert(written <= avail);
1948 499 : if (avail - written < 1)
1949 0 : goto truncated;
1950 499 : trunnel_set_uint8(ptr, (obj->n_extensions));
1951 499 : written += 1; ptr += 1;
1952 :
1953 : /* Encode struct ed25519_cert_extension ext[n_extensions] */
1954 : {
1955 :
1956 499 : unsigned idx;
1957 818 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ext); ++idx) {
1958 319 : trunnel_assert(written <= avail);
1959 319 : result = ed25519_cert_extension_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->ext, idx));
1960 319 : if (result < 0)
1961 0 : goto fail; /* XXXXXXX !*/
1962 319 : written += result; ptr += result;
1963 : }
1964 : }
1965 :
1966 : /* Encode u8 signature[64] */
1967 499 : trunnel_assert(written <= avail);
1968 499 : if (avail - written < 64)
1969 0 : goto truncated;
1970 499 : memcpy(ptr, obj->signature, 64);
1971 499 : written += 64; ptr += 64;
1972 :
1973 :
1974 499 : trunnel_assert(ptr == output + written);
1975 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1976 : {
1977 : trunnel_assert(encoded_len >= 0);
1978 : trunnel_assert((size_t)encoded_len == written);
1979 : }
1980 :
1981 : #endif
1982 :
1983 499 : return written;
1984 :
1985 0 : truncated:
1986 0 : result = -2;
1987 0 : goto fail;
1988 0 : check_failed:
1989 0 : (void)msg;
1990 0 : result = -1;
1991 0 : goto fail;
1992 0 : fail:
1993 0 : trunnel_assert(result < 0);
1994 : return result;
1995 : }
1996 :
1997 : /** As ed25519_cert_parse(), but do not allocate the output object.
1998 : */
1999 : static ssize_t
2000 1248 : ed25519_cert_parse_into(ed25519_cert_t *obj, const uint8_t *input, const size_t len_in)
2001 : {
2002 1248 : const uint8_t *ptr = input;
2003 1248 : size_t remaining = len_in;
2004 1248 : ssize_t result = 0;
2005 1248 : (void)result;
2006 :
2007 : /* Parse u8 version IN [1] */
2008 1248 : CHECK_REMAINING(1, truncated);
2009 1246 : obj->version = (trunnel_get_uint8(ptr));
2010 1246 : remaining -= 1; ptr += 1;
2011 1246 : if (! (obj->version == 1))
2012 2 : goto fail;
2013 :
2014 : /* Parse u8 cert_type */
2015 1244 : CHECK_REMAINING(1, truncated);
2016 1241 : obj->cert_type = (trunnel_get_uint8(ptr));
2017 1241 : remaining -= 1; ptr += 1;
2018 :
2019 : /* Parse u32 exp_field */
2020 1241 : CHECK_REMAINING(4, truncated);
2021 1239 : obj->exp_field = trunnel_ntohl(trunnel_get_uint32(ptr));
2022 1239 : remaining -= 4; ptr += 4;
2023 :
2024 : /* Parse u8 cert_key_type */
2025 1239 : CHECK_REMAINING(1, truncated);
2026 1237 : obj->cert_key_type = (trunnel_get_uint8(ptr));
2027 1237 : remaining -= 1; ptr += 1;
2028 :
2029 : /* Parse u8 certified_key[32] */
2030 1237 : CHECK_REMAINING(32, truncated);
2031 1234 : memcpy(obj->certified_key, ptr, 32);
2032 1234 : remaining -= 32; ptr += 32;
2033 :
2034 : /* Parse u8 n_extensions */
2035 1234 : CHECK_REMAINING(1, truncated);
2036 1232 : obj->n_extensions = (trunnel_get_uint8(ptr));
2037 1232 : remaining -= 1; ptr += 1;
2038 :
2039 : /* Parse struct ed25519_cert_extension ext[n_extensions] */
2040 1232 : TRUNNEL_DYNARRAY_EXPAND(ed25519_cert_extension_t *, &obj->ext, obj->n_extensions, {});
2041 : {
2042 1232 : ed25519_cert_extension_t * elt;
2043 1232 : unsigned idx;
2044 3050 : for (idx = 0; idx < obj->n_extensions; ++idx) {
2045 1835 : result = ed25519_cert_extension_parse(&elt, ptr, remaining);
2046 1835 : if (result < 0)
2047 17 : goto relay_fail;
2048 1818 : trunnel_assert((size_t)result <= remaining);
2049 1818 : remaining -= result; ptr += result;
2050 1818 : TRUNNEL_DYNARRAY_ADD(ed25519_cert_extension_t *, &obj->ext, elt, {ed25519_cert_extension_free(elt);});
2051 : }
2052 : }
2053 :
2054 : /* Parse u8 signature[64] */
2055 1215 : CHECK_REMAINING(64, truncated);
2056 1212 : memcpy(obj->signature, ptr, 64);
2057 1212 : remaining -= 64; ptr += 64;
2058 1212 : trunnel_assert(ptr + remaining == input + len_in);
2059 1212 : return len_in - remaining;
2060 :
2061 : truncated:
2062 : return -2;
2063 17 : relay_fail:
2064 17 : trunnel_assert(result < 0);
2065 : return result;
2066 : trunnel_alloc_failed:
2067 : return -1;
2068 2 : fail:
2069 2 : result = -1;
2070 2 : return result;
2071 : }
2072 :
2073 : ssize_t
2074 1248 : ed25519_cert_parse(ed25519_cert_t **output, const uint8_t *input, const size_t len_in)
2075 : {
2076 1248 : ssize_t result;
2077 1248 : *output = ed25519_cert_new();
2078 1248 : if (NULL == *output)
2079 : return -1;
2080 1248 : result = ed25519_cert_parse_into(*output, input, len_in);
2081 1248 : if (result < 0) {
2082 36 : ed25519_cert_free(*output);
2083 36 : *output = NULL;
2084 : }
2085 : return result;
2086 : }
2087 : extend2_cell_body_t *
2088 10017 : extend2_cell_body_new(void)
2089 : {
2090 10017 : extend2_cell_body_t *val = trunnel_calloc(1, sizeof(extend2_cell_body_t));
2091 10017 : if (NULL == val)
2092 0 : return NULL;
2093 : return val;
2094 : }
2095 :
2096 : /** Release all storage held inside 'obj', but do not free 'obj'.
2097 : */
2098 : static void
2099 10017 : extend2_cell_body_clear(extend2_cell_body_t *obj)
2100 : {
2101 10017 : (void) obj;
2102 : {
2103 :
2104 10017 : unsigned idx;
2105 25689 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
2106 15672 : link_specifier_free(TRUNNEL_DYNARRAY_GET(&obj->ls, idx));
2107 : }
2108 : }
2109 10017 : TRUNNEL_DYNARRAY_WIPE(&obj->ls);
2110 10017 : TRUNNEL_DYNARRAY_CLEAR(&obj->ls);
2111 10017 : create2_cell_body_free(obj->create2);
2112 10017 : obj->create2 = NULL;
2113 10017 : }
2114 :
2115 : void
2116 10017 : extend2_cell_body_free(extend2_cell_body_t *obj)
2117 : {
2118 10017 : if (obj == NULL)
2119 : return;
2120 10017 : extend2_cell_body_clear(obj);
2121 10017 : trunnel_memwipe(obj, sizeof(extend2_cell_body_t));
2122 10017 : trunnel_free_(obj);
2123 : }
2124 :
2125 : uint8_t
2126 0 : extend2_cell_body_get_n_spec(const extend2_cell_body_t *inp)
2127 : {
2128 0 : return inp->n_spec;
2129 : }
2130 : int
2131 0 : extend2_cell_body_set_n_spec(extend2_cell_body_t *inp, uint8_t val)
2132 : {
2133 0 : inp->n_spec = val;
2134 0 : return 0;
2135 : }
2136 : size_t
2137 0 : extend2_cell_body_getlen_ls(const extend2_cell_body_t *inp)
2138 : {
2139 0 : return TRUNNEL_DYNARRAY_LEN(&inp->ls);
2140 : }
2141 :
2142 : struct link_specifier_st *
2143 16 : extend2_cell_body_get_ls(extend2_cell_body_t *inp, size_t idx)
2144 : {
2145 16 : return TRUNNEL_DYNARRAY_GET(&inp->ls, idx);
2146 : }
2147 :
2148 : const struct link_specifier_st *
2149 16 : extend2_cell_body_getconst_ls(const extend2_cell_body_t *inp, size_t idx)
2150 : {
2151 16 : return extend2_cell_body_get_ls((extend2_cell_body_t*)inp, idx);
2152 : }
2153 : int
2154 0 : extend2_cell_body_set_ls(extend2_cell_body_t *inp, size_t idx, struct link_specifier_st * elt)
2155 : {
2156 0 : link_specifier_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->ls, idx);
2157 0 : if (oldval && oldval != elt)
2158 0 : link_specifier_free(oldval);
2159 0 : return extend2_cell_body_set0_ls(inp, idx, elt);
2160 : }
2161 : int
2162 0 : extend2_cell_body_set0_ls(extend2_cell_body_t *inp, size_t idx, struct link_specifier_st * elt)
2163 : {
2164 0 : TRUNNEL_DYNARRAY_SET(&inp->ls, idx, elt);
2165 0 : return 0;
2166 : }
2167 : int
2168 14 : extend2_cell_body_add_ls(extend2_cell_body_t *inp, struct link_specifier_st * elt)
2169 : {
2170 : #if SIZE_MAX >= UINT8_MAX
2171 14 : if (inp->ls.n_ == UINT8_MAX)
2172 0 : goto trunnel_alloc_failed;
2173 : #endif
2174 14 : TRUNNEL_DYNARRAY_ADD(struct link_specifier_st *, &inp->ls, elt, {});
2175 14 : return 0;
2176 0 : trunnel_alloc_failed:
2177 0 : TRUNNEL_SET_ERROR_CODE(inp);
2178 0 : return -1;
2179 : }
2180 :
2181 : struct link_specifier_st * *
2182 0 : extend2_cell_body_getarray_ls(extend2_cell_body_t *inp)
2183 : {
2184 0 : return inp->ls.elts_;
2185 : }
2186 : const struct link_specifier_st * const *
2187 0 : extend2_cell_body_getconstarray_ls(const extend2_cell_body_t *inp)
2188 : {
2189 0 : return (const struct link_specifier_st * const *)extend2_cell_body_getarray_ls((extend2_cell_body_t*)inp);
2190 : }
2191 : int
2192 0 : extend2_cell_body_setlen_ls(extend2_cell_body_t *inp, size_t newlen)
2193 : {
2194 0 : struct link_specifier_st * *newptr;
2195 : #if UINT8_MAX < SIZE_MAX
2196 0 : if (newlen > UINT8_MAX)
2197 0 : goto trunnel_alloc_failed;
2198 : #endif
2199 0 : newptr = trunnel_dynarray_setlen(&inp->ls.allocated_,
2200 0 : &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 0 : if (newlen != 0 && newptr == NULL)
2204 0 : goto trunnel_alloc_failed;
2205 0 : inp->ls.elts_ = newptr;
2206 0 : return 0;
2207 0 : trunnel_alloc_failed:
2208 0 : TRUNNEL_SET_ERROR_CODE(inp);
2209 0 : return -1;
2210 : }
2211 : struct create2_cell_body_st *
2212 0 : extend2_cell_body_get_create2(extend2_cell_body_t *inp)
2213 : {
2214 0 : return inp->create2;
2215 : }
2216 : const struct create2_cell_body_st *
2217 0 : extend2_cell_body_getconst_create2(const extend2_cell_body_t *inp)
2218 : {
2219 0 : return extend2_cell_body_get_create2((extend2_cell_body_t*) inp);
2220 : }
2221 : int
2222 0 : extend2_cell_body_set_create2(extend2_cell_body_t *inp, struct create2_cell_body_st *val)
2223 : {
2224 0 : if (inp->create2 && inp->create2 != val)
2225 0 : create2_cell_body_free(inp->create2);
2226 0 : return extend2_cell_body_set0_create2(inp, val);
2227 : }
2228 : int
2229 0 : extend2_cell_body_set0_create2(extend2_cell_body_t *inp, struct create2_cell_body_st *val)
2230 : {
2231 0 : inp->create2 = val;
2232 0 : return 0;
2233 : }
2234 : const char *
2235 5 : extend2_cell_body_check(const extend2_cell_body_t *obj)
2236 : {
2237 5 : if (obj == NULL)
2238 : return "Object was NULL";
2239 5 : if (obj->trunnel_error_code_)
2240 : return "A set function failed on this object";
2241 : {
2242 : const char *msg;
2243 :
2244 : unsigned idx;
2245 19 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
2246 14 : if (NULL != (msg = link_specifier_check(TRUNNEL_DYNARRAY_GET(&obj->ls, idx))))
2247 0 : return msg;
2248 : }
2249 : }
2250 5 : if (TRUNNEL_DYNARRAY_LEN(&obj->ls) != obj->n_spec)
2251 : return "Length mismatch for ls";
2252 : {
2253 5 : const char *msg;
2254 5 : if (NULL != (msg = create2_cell_body_check(obj->create2)))
2255 0 : return msg;
2256 : }
2257 : return NULL;
2258 : }
2259 :
2260 : ssize_t
2261 0 : extend2_cell_body_encoded_len(const extend2_cell_body_t *obj)
2262 : {
2263 0 : ssize_t result = 0;
2264 :
2265 0 : if (NULL != extend2_cell_body_check(obj))
2266 : return -1;
2267 :
2268 :
2269 : /* Length of u8 n_spec */
2270 : result += 1;
2271 :
2272 : /* Length of struct link_specifier ls[n_spec] */
2273 : {
2274 :
2275 : unsigned idx;
2276 0 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
2277 0 : result += link_specifier_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->ls, idx));
2278 : }
2279 : }
2280 :
2281 : /* Length of struct create2_cell_body create2 */
2282 0 : result += create2_cell_body_encoded_len(obj->create2);
2283 0 : return result;
2284 : }
2285 : int
2286 0 : extend2_cell_body_clear_errors(extend2_cell_body_t *obj)
2287 : {
2288 0 : int r = obj->trunnel_error_code_;
2289 0 : obj->trunnel_error_code_ = 0;
2290 0 : return r;
2291 : }
2292 : ssize_t
2293 5 : extend2_cell_body_encode(uint8_t *output, const size_t avail, const extend2_cell_body_t *obj)
2294 : {
2295 5 : ssize_t result = 0;
2296 5 : size_t written = 0;
2297 5 : uint8_t *ptr = output;
2298 5 : const char *msg;
2299 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2300 : const ssize_t encoded_len = extend2_cell_body_encoded_len(obj);
2301 : #endif
2302 :
2303 5 : if (NULL != (msg = extend2_cell_body_check(obj)))
2304 0 : goto check_failed;
2305 :
2306 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2307 : trunnel_assert(encoded_len >= 0);
2308 : #endif
2309 :
2310 : /* Encode u8 n_spec */
2311 5 : trunnel_assert(written <= avail);
2312 5 : if (avail - written < 1)
2313 0 : goto truncated;
2314 5 : trunnel_set_uint8(ptr, (obj->n_spec));
2315 5 : written += 1; ptr += 1;
2316 :
2317 : /* Encode struct link_specifier ls[n_spec] */
2318 : {
2319 :
2320 5 : unsigned idx;
2321 19 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->ls); ++idx) {
2322 14 : trunnel_assert(written <= avail);
2323 14 : result = link_specifier_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->ls, idx));
2324 14 : if (result < 0)
2325 0 : goto fail; /* XXXXXXX !*/
2326 14 : written += result; ptr += result;
2327 : }
2328 : }
2329 :
2330 : /* Encode struct create2_cell_body create2 */
2331 5 : trunnel_assert(written <= avail);
2332 5 : result = create2_cell_body_encode(ptr, avail - written, obj->create2);
2333 5 : if (result < 0)
2334 0 : goto fail; /* XXXXXXX !*/
2335 5 : written += result; ptr += result;
2336 :
2337 :
2338 5 : trunnel_assert(ptr == output + written);
2339 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2340 : {
2341 : trunnel_assert(encoded_len >= 0);
2342 : trunnel_assert((size_t)encoded_len == written);
2343 : }
2344 :
2345 : #endif
2346 :
2347 5 : return written;
2348 :
2349 0 : truncated:
2350 0 : result = -2;
2351 0 : goto fail;
2352 0 : check_failed:
2353 0 : (void)msg;
2354 0 : result = -1;
2355 0 : goto fail;
2356 : fail:
2357 0 : trunnel_assert(result < 0);
2358 : return result;
2359 : }
2360 :
2361 : /** As extend2_cell_body_parse(), but do not allocate the output
2362 : * object.
2363 : */
2364 : static ssize_t
2365 10012 : extend2_cell_body_parse_into(extend2_cell_body_t *obj, const uint8_t *input, const size_t len_in)
2366 : {
2367 10012 : const uint8_t *ptr = input;
2368 10012 : size_t remaining = len_in;
2369 10012 : ssize_t result = 0;
2370 10012 : (void)result;
2371 :
2372 : /* Parse u8 n_spec */
2373 10012 : CHECK_REMAINING(1, truncated);
2374 9993 : obj->n_spec = (trunnel_get_uint8(ptr));
2375 9993 : remaining -= 1; ptr += 1;
2376 :
2377 : /* Parse struct link_specifier ls[n_spec] */
2378 9993 : TRUNNEL_DYNARRAY_EXPAND(link_specifier_t *, &obj->ls, obj->n_spec, {});
2379 : {
2380 9993 : link_specifier_t * elt;
2381 9993 : unsigned idx;
2382 25651 : for (idx = 0; idx < obj->n_spec; ++idx) {
2383 25543 : result = link_specifier_parse(&elt, ptr, remaining);
2384 25543 : if (result < 0)
2385 9885 : goto relay_fail;
2386 15658 : trunnel_assert((size_t)result <= remaining);
2387 15658 : remaining -= result; ptr += result;
2388 15658 : TRUNNEL_DYNARRAY_ADD(link_specifier_t *, &obj->ls, elt, {link_specifier_free(elt);});
2389 : }
2390 : }
2391 :
2392 : /* Parse struct create2_cell_body create2 */
2393 108 : result = create2_cell_body_parse(&obj->create2, ptr, remaining);
2394 108 : if (result < 0)
2395 102 : goto relay_fail;
2396 6 : trunnel_assert((size_t)result <= remaining);
2397 6 : remaining -= result; ptr += result;
2398 6 : trunnel_assert(ptr + remaining == input + len_in);
2399 6 : return len_in - remaining;
2400 :
2401 19 : truncated:
2402 19 : return -2;
2403 : relay_fail:
2404 : trunnel_assert(result < 0);
2405 : return result;
2406 : trunnel_alloc_failed:
2407 : return -1;
2408 : }
2409 :
2410 : ssize_t
2411 10012 : extend2_cell_body_parse(extend2_cell_body_t **output, const uint8_t *input, const size_t len_in)
2412 : {
2413 10012 : ssize_t result;
2414 10012 : *output = extend2_cell_body_new();
2415 10012 : if (NULL == *output)
2416 : return -1;
2417 10012 : result = extend2_cell_body_parse_into(*output, input, len_in);
2418 10012 : if (result < 0) {
2419 10006 : extend2_cell_body_free(*output);
2420 10006 : *output = NULL;
2421 : }
2422 : return result;
2423 : }
2424 : link_specifier_list_t *
2425 248 : link_specifier_list_new(void)
2426 : {
2427 248 : link_specifier_list_t *val = trunnel_calloc(1, sizeof(link_specifier_list_t));
2428 248 : if (NULL == val)
2429 0 : return NULL;
2430 : return val;
2431 : }
2432 :
2433 : /** Release all storage held inside 'obj', but do not free 'obj'.
2434 : */
2435 : static void
2436 248 : link_specifier_list_clear(link_specifier_list_t *obj)
2437 : {
2438 248 : (void) obj;
2439 : {
2440 :
2441 248 : unsigned idx;
2442 744 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
2443 496 : link_specifier_free(TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
2444 : }
2445 : }
2446 248 : TRUNNEL_DYNARRAY_WIPE(&obj->spec);
2447 248 : TRUNNEL_DYNARRAY_CLEAR(&obj->spec);
2448 248 : }
2449 :
2450 : void
2451 248 : link_specifier_list_free(link_specifier_list_t *obj)
2452 : {
2453 248 : if (obj == NULL)
2454 : return;
2455 248 : link_specifier_list_clear(obj);
2456 248 : trunnel_memwipe(obj, sizeof(link_specifier_list_t));
2457 248 : trunnel_free_(obj);
2458 : }
2459 :
2460 : uint8_t
2461 0 : link_specifier_list_get_n_spec(const link_specifier_list_t *inp)
2462 : {
2463 0 : return inp->n_spec;
2464 : }
2465 : int
2466 104 : link_specifier_list_set_n_spec(link_specifier_list_t *inp, uint8_t val)
2467 : {
2468 104 : inp->n_spec = val;
2469 104 : return 0;
2470 : }
2471 : size_t
2472 432 : link_specifier_list_getlen_spec(const link_specifier_list_t *inp)
2473 : {
2474 432 : return TRUNNEL_DYNARRAY_LEN(&inp->spec);
2475 : }
2476 :
2477 : struct link_specifier_st *
2478 288 : link_specifier_list_get_spec(link_specifier_list_t *inp, size_t idx)
2479 : {
2480 288 : return TRUNNEL_DYNARRAY_GET(&inp->spec, idx);
2481 : }
2482 :
2483 : const struct link_specifier_st *
2484 0 : link_specifier_list_getconst_spec(const link_specifier_list_t *inp, size_t idx)
2485 : {
2486 0 : return link_specifier_list_get_spec((link_specifier_list_t*)inp, idx);
2487 : }
2488 : int
2489 0 : link_specifier_list_set_spec(link_specifier_list_t *inp, size_t idx, struct link_specifier_st * elt)
2490 : {
2491 0 : link_specifier_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->spec, idx);
2492 0 : if (oldval && oldval != elt)
2493 0 : link_specifier_free(oldval);
2494 0 : return link_specifier_list_set0_spec(inp, idx, elt);
2495 : }
2496 : int
2497 0 : link_specifier_list_set0_spec(link_specifier_list_t *inp, size_t idx, struct link_specifier_st * elt)
2498 : {
2499 0 : TRUNNEL_DYNARRAY_SET(&inp->spec, idx, elt);
2500 0 : return 0;
2501 : }
2502 : int
2503 208 : link_specifier_list_add_spec(link_specifier_list_t *inp, struct link_specifier_st * elt)
2504 : {
2505 : #if SIZE_MAX >= UINT8_MAX
2506 208 : if (inp->spec.n_ == UINT8_MAX)
2507 0 : goto trunnel_alloc_failed;
2508 : #endif
2509 208 : TRUNNEL_DYNARRAY_ADD(struct link_specifier_st *, &inp->spec, elt, {});
2510 208 : return 0;
2511 0 : trunnel_alloc_failed:
2512 0 : TRUNNEL_SET_ERROR_CODE(inp);
2513 0 : return -1;
2514 : }
2515 :
2516 : struct link_specifier_st * *
2517 0 : link_specifier_list_getarray_spec(link_specifier_list_t *inp)
2518 : {
2519 0 : return inp->spec.elts_;
2520 : }
2521 : const struct link_specifier_st * const *
2522 0 : link_specifier_list_getconstarray_spec(const link_specifier_list_t *inp)
2523 : {
2524 0 : return (const struct link_specifier_st * const *)link_specifier_list_getarray_spec((link_specifier_list_t*)inp);
2525 : }
2526 : int
2527 0 : link_specifier_list_setlen_spec(link_specifier_list_t *inp, size_t newlen)
2528 : {
2529 0 : struct link_specifier_st * *newptr;
2530 : #if UINT8_MAX < SIZE_MAX
2531 0 : if (newlen > UINT8_MAX)
2532 0 : goto trunnel_alloc_failed;
2533 : #endif
2534 0 : newptr = trunnel_dynarray_setlen(&inp->spec.allocated_,
2535 0 : &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 0 : if (newlen != 0 && newptr == NULL)
2539 0 : goto trunnel_alloc_failed;
2540 0 : inp->spec.elts_ = newptr;
2541 0 : return 0;
2542 0 : trunnel_alloc_failed:
2543 0 : TRUNNEL_SET_ERROR_CODE(inp);
2544 0 : return -1;
2545 : }
2546 : const char *
2547 208 : link_specifier_list_check(const link_specifier_list_t *obj)
2548 : {
2549 208 : if (obj == NULL)
2550 : return "Object was NULL";
2551 208 : if (obj->trunnel_error_code_)
2552 : return "A set function failed on this object";
2553 : {
2554 : const char *msg;
2555 :
2556 : unsigned idx;
2557 624 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
2558 416 : if (NULL != (msg = link_specifier_check(TRUNNEL_DYNARRAY_GET(&obj->spec, idx))))
2559 0 : return msg;
2560 : }
2561 : }
2562 208 : if (TRUNNEL_DYNARRAY_LEN(&obj->spec) != obj->n_spec)
2563 0 : return "Length mismatch for spec";
2564 : return NULL;
2565 : }
2566 :
2567 : ssize_t
2568 104 : link_specifier_list_encoded_len(const link_specifier_list_t *obj)
2569 : {
2570 104 : ssize_t result = 0;
2571 :
2572 104 : if (NULL != link_specifier_list_check(obj))
2573 : return -1;
2574 :
2575 :
2576 : /* Length of u8 n_spec */
2577 : result += 1;
2578 :
2579 : /* Length of struct link_specifier spec[n_spec] */
2580 : {
2581 :
2582 : unsigned idx;
2583 312 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
2584 208 : result += link_specifier_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
2585 : }
2586 : }
2587 : return result;
2588 : }
2589 : int
2590 0 : link_specifier_list_clear_errors(link_specifier_list_t *obj)
2591 : {
2592 0 : int r = obj->trunnel_error_code_;
2593 0 : obj->trunnel_error_code_ = 0;
2594 0 : return r;
2595 : }
2596 : ssize_t
2597 104 : link_specifier_list_encode(uint8_t *output, const size_t avail, const link_specifier_list_t *obj)
2598 : {
2599 104 : ssize_t result = 0;
2600 104 : size_t written = 0;
2601 104 : uint8_t *ptr = output;
2602 104 : const char *msg;
2603 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2604 : const ssize_t encoded_len = link_specifier_list_encoded_len(obj);
2605 : #endif
2606 :
2607 104 : if (NULL != (msg = link_specifier_list_check(obj)))
2608 0 : goto check_failed;
2609 :
2610 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2611 : trunnel_assert(encoded_len >= 0);
2612 : #endif
2613 :
2614 : /* Encode u8 n_spec */
2615 104 : trunnel_assert(written <= avail);
2616 104 : if (avail - written < 1)
2617 0 : goto truncated;
2618 104 : trunnel_set_uint8(ptr, (obj->n_spec));
2619 104 : written += 1; ptr += 1;
2620 :
2621 : /* Encode struct link_specifier spec[n_spec] */
2622 : {
2623 :
2624 104 : unsigned idx;
2625 312 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->spec); ++idx) {
2626 208 : trunnel_assert(written <= avail);
2627 208 : result = link_specifier_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->spec, idx));
2628 208 : if (result < 0)
2629 0 : goto fail; /* XXXXXXX !*/
2630 208 : written += result; ptr += result;
2631 : }
2632 : }
2633 :
2634 :
2635 104 : trunnel_assert(ptr == output + written);
2636 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
2637 : {
2638 : trunnel_assert(encoded_len >= 0);
2639 : trunnel_assert((size_t)encoded_len == written);
2640 : }
2641 :
2642 : #endif
2643 :
2644 104 : return written;
2645 :
2646 0 : truncated:
2647 0 : result = -2;
2648 0 : goto fail;
2649 0 : check_failed:
2650 0 : (void)msg;
2651 0 : result = -1;
2652 0 : goto fail;
2653 0 : fail:
2654 0 : trunnel_assert(result < 0);
2655 : return result;
2656 : }
2657 :
2658 : /** As link_specifier_list_parse(), but do not allocate the output
2659 : * object.
2660 : */
2661 : static ssize_t
2662 144 : link_specifier_list_parse_into(link_specifier_list_t *obj, const uint8_t *input, const size_t len_in)
2663 : {
2664 144 : const uint8_t *ptr = input;
2665 144 : size_t remaining = len_in;
2666 144 : ssize_t result = 0;
2667 144 : (void)result;
2668 :
2669 : /* Parse u8 n_spec */
2670 144 : CHECK_REMAINING(1, truncated);
2671 144 : obj->n_spec = (trunnel_get_uint8(ptr));
2672 144 : remaining -= 1; ptr += 1;
2673 :
2674 : /* Parse struct link_specifier spec[n_spec] */
2675 144 : TRUNNEL_DYNARRAY_EXPAND(link_specifier_t *, &obj->spec, obj->n_spec, {});
2676 : {
2677 144 : link_specifier_t * elt;
2678 144 : unsigned idx;
2679 432 : for (idx = 0; idx < obj->n_spec; ++idx) {
2680 288 : result = link_specifier_parse(&elt, ptr, remaining);
2681 288 : if (result < 0)
2682 0 : goto relay_fail;
2683 288 : trunnel_assert((size_t)result <= remaining);
2684 288 : remaining -= result; ptr += result;
2685 288 : TRUNNEL_DYNARRAY_ADD(link_specifier_t *, &obj->spec, elt, {link_specifier_free(elt);});
2686 : }
2687 : }
2688 144 : trunnel_assert(ptr + remaining == input + len_in);
2689 144 : return len_in - remaining;
2690 :
2691 0 : truncated:
2692 0 : return -2;
2693 0 : relay_fail:
2694 0 : trunnel_assert(result < 0);
2695 : return result;
2696 : trunnel_alloc_failed:
2697 : return -1;
2698 : }
2699 :
2700 : ssize_t
2701 144 : link_specifier_list_parse(link_specifier_list_t **output, const uint8_t *input, const size_t len_in)
2702 : {
2703 144 : ssize_t result;
2704 144 : *output = link_specifier_list_new();
2705 144 : if (NULL == *output)
2706 : return -1;
2707 144 : result = link_specifier_list_parse_into(*output, input, len_in);
2708 144 : if (result < 0) {
2709 0 : link_specifier_list_free(*output);
2710 0 : *output = NULL;
2711 : }
2712 : return result;
2713 : }
|