Line data Source code
1 : /* link_handshake.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 "link_handshake.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 linkhandshake_deadcode_dummy__ = 0;
19 : #define OR_DEADCODE_DUMMY || linkhandshake_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 : auth_challenge_cell_t *
32 8 : auth_challenge_cell_new(void)
33 : {
34 8 : auth_challenge_cell_t *val = trunnel_calloc(1, sizeof(auth_challenge_cell_t));
35 8 : 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 8 : auth_challenge_cell_clear(auth_challenge_cell_t *obj)
44 : {
45 8 : (void) obj;
46 8 : TRUNNEL_DYNARRAY_WIPE(&obj->methods);
47 8 : TRUNNEL_DYNARRAY_CLEAR(&obj->methods);
48 8 : }
49 :
50 : void
51 16 : auth_challenge_cell_free(auth_challenge_cell_t *obj)
52 : {
53 16 : if (obj == NULL)
54 : return;
55 8 : auth_challenge_cell_clear(obj);
56 8 : trunnel_memwipe(obj, sizeof(auth_challenge_cell_t));
57 8 : trunnel_free_(obj);
58 : }
59 :
60 : size_t
61 0 : auth_challenge_cell_getlen_challenge(const auth_challenge_cell_t *inp)
62 : {
63 0 : (void)inp; return 32;
64 : }
65 :
66 : uint8_t
67 0 : auth_challenge_cell_get_challenge(auth_challenge_cell_t *inp, size_t idx)
68 : {
69 0 : trunnel_assert(idx < 32);
70 0 : return inp->challenge[idx];
71 : }
72 :
73 : uint8_t
74 0 : auth_challenge_cell_getconst_challenge(const auth_challenge_cell_t *inp, size_t idx)
75 : {
76 0 : return auth_challenge_cell_get_challenge((auth_challenge_cell_t*)inp, idx);
77 : }
78 : int
79 0 : auth_challenge_cell_set_challenge(auth_challenge_cell_t *inp, size_t idx, uint8_t elt)
80 : {
81 0 : trunnel_assert(idx < 32);
82 0 : inp->challenge[idx] = elt;
83 0 : return 0;
84 : }
85 :
86 : uint8_t *
87 0 : auth_challenge_cell_getarray_challenge(auth_challenge_cell_t *inp)
88 : {
89 0 : return inp->challenge;
90 : }
91 : const uint8_t *
92 0 : auth_challenge_cell_getconstarray_challenge(const auth_challenge_cell_t *inp)
93 : {
94 0 : return (const uint8_t *)auth_challenge_cell_getarray_challenge((auth_challenge_cell_t*)inp);
95 : }
96 : uint16_t
97 0 : auth_challenge_cell_get_n_methods(const auth_challenge_cell_t *inp)
98 : {
99 0 : return inp->n_methods;
100 : }
101 : int
102 2 : auth_challenge_cell_set_n_methods(auth_challenge_cell_t *inp, uint16_t val)
103 : {
104 2 : inp->n_methods = val;
105 2 : return 0;
106 : }
107 : size_t
108 2 : auth_challenge_cell_getlen_methods(const auth_challenge_cell_t *inp)
109 : {
110 2 : return TRUNNEL_DYNARRAY_LEN(&inp->methods);
111 : }
112 :
113 : uint16_t
114 9 : auth_challenge_cell_get_methods(auth_challenge_cell_t *inp, size_t idx)
115 : {
116 9 : return TRUNNEL_DYNARRAY_GET(&inp->methods, idx);
117 : }
118 :
119 : uint16_t
120 0 : auth_challenge_cell_getconst_methods(const auth_challenge_cell_t *inp, size_t idx)
121 : {
122 0 : return auth_challenge_cell_get_methods((auth_challenge_cell_t*)inp, idx);
123 : }
124 : int
125 0 : auth_challenge_cell_set_methods(auth_challenge_cell_t *inp, size_t idx, uint16_t elt)
126 : {
127 0 : TRUNNEL_DYNARRAY_SET(&inp->methods, idx, elt);
128 0 : return 0;
129 : }
130 : int
131 4 : auth_challenge_cell_add_methods(auth_challenge_cell_t *inp, uint16_t elt)
132 : {
133 : #if SIZE_MAX >= UINT16_MAX
134 4 : if (inp->methods.n_ == UINT16_MAX)
135 0 : goto trunnel_alloc_failed;
136 : #endif
137 4 : TRUNNEL_DYNARRAY_ADD(uint16_t, &inp->methods, elt, {});
138 4 : return 0;
139 0 : trunnel_alloc_failed:
140 0 : TRUNNEL_SET_ERROR_CODE(inp);
141 0 : return -1;
142 : }
143 :
144 : uint16_t *
145 0 : auth_challenge_cell_getarray_methods(auth_challenge_cell_t *inp)
146 : {
147 0 : return inp->methods.elts_;
148 : }
149 : const uint16_t *
150 0 : auth_challenge_cell_getconstarray_methods(const auth_challenge_cell_t *inp)
151 : {
152 0 : return (const uint16_t *)auth_challenge_cell_getarray_methods((auth_challenge_cell_t*)inp);
153 : }
154 : int
155 0 : auth_challenge_cell_setlen_methods(auth_challenge_cell_t *inp, size_t newlen)
156 : {
157 0 : uint16_t *newptr;
158 : #if UINT16_MAX < SIZE_MAX
159 0 : if (newlen > UINT16_MAX)
160 0 : goto trunnel_alloc_failed;
161 : #endif
162 0 : newptr = trunnel_dynarray_setlen(&inp->methods.allocated_,
163 0 : &inp->methods.n_, inp->methods.elts_, newlen,
164 : sizeof(inp->methods.elts_[0]), (trunnel_free_fn_t) NULL,
165 : &inp->trunnel_error_code_);
166 0 : if (newlen != 0 && newptr == NULL)
167 0 : goto trunnel_alloc_failed;
168 0 : inp->methods.elts_ = newptr;
169 0 : return 0;
170 0 : trunnel_alloc_failed:
171 0 : TRUNNEL_SET_ERROR_CODE(inp);
172 0 : return -1;
173 : }
174 : const char *
175 4 : auth_challenge_cell_check(const auth_challenge_cell_t *obj)
176 : {
177 4 : if (obj == NULL)
178 : return "Object was NULL";
179 4 : if (obj->trunnel_error_code_)
180 : return "A set function failed on this object";
181 4 : if (TRUNNEL_DYNARRAY_LEN(&obj->methods) != obj->n_methods)
182 0 : return "Length mismatch for methods";
183 : return NULL;
184 : }
185 :
186 : ssize_t
187 2 : auth_challenge_cell_encoded_len(const auth_challenge_cell_t *obj)
188 : {
189 2 : ssize_t result = 0;
190 :
191 2 : if (NULL != auth_challenge_cell_check(obj))
192 : return -1;
193 :
194 :
195 : /* Length of u8 challenge[32] */
196 2 : result += 32;
197 :
198 : /* Length of u16 n_methods */
199 2 : result += 2;
200 :
201 : /* Length of u16 methods[n_methods] */
202 2 : result += 2 * TRUNNEL_DYNARRAY_LEN(&obj->methods);
203 2 : return result;
204 : }
205 : int
206 0 : auth_challenge_cell_clear_errors(auth_challenge_cell_t *obj)
207 : {
208 0 : int r = obj->trunnel_error_code_;
209 0 : obj->trunnel_error_code_ = 0;
210 0 : return r;
211 : }
212 : ssize_t
213 2 : auth_challenge_cell_encode(uint8_t *output, const size_t avail, const auth_challenge_cell_t *obj)
214 : {
215 2 : ssize_t result = 0;
216 2 : size_t written = 0;
217 2 : uint8_t *ptr = output;
218 2 : const char *msg;
219 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
220 : const ssize_t encoded_len = auth_challenge_cell_encoded_len(obj);
221 : #endif
222 :
223 2 : if (NULL != (msg = auth_challenge_cell_check(obj)))
224 0 : goto check_failed;
225 :
226 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
227 : trunnel_assert(encoded_len >= 0);
228 : #endif
229 :
230 : /* Encode u8 challenge[32] */
231 2 : trunnel_assert(written <= avail);
232 2 : if (avail - written < 32)
233 0 : goto truncated;
234 2 : memcpy(ptr, obj->challenge, 32);
235 2 : written += 32; ptr += 32;
236 :
237 : /* Encode u16 n_methods */
238 2 : trunnel_assert(written <= avail);
239 2 : if (avail - written < 2)
240 0 : goto truncated;
241 2 : trunnel_set_uint16(ptr, trunnel_htons(obj->n_methods));
242 2 : written += 2; ptr += 2;
243 :
244 : /* Encode u16 methods[n_methods] */
245 : {
246 :
247 2 : unsigned idx;
248 6 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->methods); ++idx) {
249 4 : trunnel_assert(written <= avail);
250 4 : if (avail - written < 2)
251 0 : goto truncated;
252 4 : trunnel_set_uint16(ptr, trunnel_htons(TRUNNEL_DYNARRAY_GET(&obj->methods, idx)));
253 4 : written += 2; ptr += 2;
254 : }
255 : }
256 :
257 :
258 2 : trunnel_assert(ptr == output + written);
259 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
260 : {
261 : trunnel_assert(encoded_len >= 0);
262 : trunnel_assert((size_t)encoded_len == written);
263 : }
264 :
265 : #endif
266 :
267 2 : return written;
268 :
269 0 : truncated:
270 0 : result = -2;
271 0 : goto fail;
272 0 : check_failed:
273 0 : (void)msg;
274 0 : result = -1;
275 0 : goto fail;
276 : fail:
277 : trunnel_assert(result < 0);
278 : return result;
279 : }
280 :
281 : /** As auth_challenge_cell_parse(), but do not allocate the output
282 : * object.
283 : */
284 : static ssize_t
285 6 : auth_challenge_cell_parse_into(auth_challenge_cell_t *obj, const uint8_t *input, const size_t len_in)
286 : {
287 6 : const uint8_t *ptr = input;
288 6 : size_t remaining = len_in;
289 6 : ssize_t result = 0;
290 6 : (void)result;
291 :
292 : /* Parse u8 challenge[32] */
293 6 : CHECK_REMAINING(32, truncated);
294 6 : memcpy(obj->challenge, ptr, 32);
295 6 : remaining -= 32; ptr += 32;
296 :
297 : /* Parse u16 n_methods */
298 6 : CHECK_REMAINING(2, truncated);
299 5 : obj->n_methods = trunnel_ntohs(trunnel_get_uint16(ptr));
300 5 : remaining -= 2; ptr += 2;
301 :
302 : /* Parse u16 methods[n_methods] */
303 5 : TRUNNEL_DYNARRAY_EXPAND(uint16_t, &obj->methods, obj->n_methods, {});
304 : {
305 5 : uint16_t elt;
306 5 : unsigned idx;
307 14 : for (idx = 0; idx < obj->n_methods; ++idx) {
308 10 : CHECK_REMAINING(2, truncated);
309 9 : elt = trunnel_ntohs(trunnel_get_uint16(ptr));
310 9 : remaining -= 2; ptr += 2;
311 9 : TRUNNEL_DYNARRAY_ADD(uint16_t, &obj->methods, elt, {});
312 : }
313 : }
314 4 : trunnel_assert(ptr + remaining == input + len_in);
315 4 : return len_in - remaining;
316 :
317 : truncated:
318 : return -2;
319 : trunnel_alloc_failed:
320 : return -1;
321 : }
322 :
323 : ssize_t
324 6 : auth_challenge_cell_parse(auth_challenge_cell_t **output, const uint8_t *input, const size_t len_in)
325 : {
326 6 : ssize_t result;
327 6 : *output = auth_challenge_cell_new();
328 6 : if (NULL == *output)
329 : return -1;
330 6 : result = auth_challenge_cell_parse_into(*output, input, len_in);
331 6 : if (result < 0) {
332 2 : auth_challenge_cell_free(*output);
333 2 : *output = NULL;
334 : }
335 : return result;
336 : }
337 : auth_ctx_t *
338 28 : auth_ctx_new(void)
339 : {
340 28 : auth_ctx_t *val = trunnel_calloc(1, sizeof(auth_ctx_t));
341 28 : if (NULL == val)
342 0 : return NULL;
343 : return val;
344 : }
345 :
346 : /** Release all storage held inside 'obj', but do not free 'obj'.
347 : */
348 : static void
349 : auth_ctx_clear(auth_ctx_t *obj)
350 : {
351 : (void) obj;
352 : }
353 :
354 : void
355 28 : auth_ctx_free(auth_ctx_t *obj)
356 : {
357 28 : if (obj == NULL)
358 : return;
359 28 : auth_ctx_clear(obj);
360 28 : trunnel_memwipe(obj, sizeof(auth_ctx_t));
361 28 : trunnel_free_(obj);
362 : }
363 :
364 : uint8_t
365 0 : auth_ctx_get_is_ed(const auth_ctx_t *inp)
366 : {
367 0 : return inp->is_ed;
368 : }
369 : int
370 0 : auth_ctx_set_is_ed(auth_ctx_t *inp, uint8_t val)
371 : {
372 0 : inp->is_ed = val;
373 0 : return 0;
374 : }
375 : certs_cell_cert_t *
376 338 : certs_cell_cert_new(void)
377 : {
378 338 : certs_cell_cert_t *val = trunnel_calloc(1, sizeof(certs_cell_cert_t));
379 338 : if (NULL == val)
380 0 : return NULL;
381 : return val;
382 : }
383 :
384 : /** Release all storage held inside 'obj', but do not free 'obj'.
385 : */
386 : static void
387 338 : certs_cell_cert_clear(certs_cell_cert_t *obj)
388 : {
389 338 : (void) obj;
390 338 : TRUNNEL_DYNARRAY_WIPE(&obj->body);
391 338 : TRUNNEL_DYNARRAY_CLEAR(&obj->body);
392 338 : }
393 :
394 : void
395 342 : certs_cell_cert_free(certs_cell_cert_t *obj)
396 : {
397 342 : if (obj == NULL)
398 : return;
399 338 : certs_cell_cert_clear(obj);
400 338 : trunnel_memwipe(obj, sizeof(certs_cell_cert_t));
401 338 : trunnel_free_(obj);
402 : }
403 :
404 : uint8_t
405 0 : certs_cell_cert_get_cert_type(const certs_cell_cert_t *inp)
406 : {
407 0 : return inp->cert_type;
408 : }
409 : int
410 0 : certs_cell_cert_set_cert_type(certs_cell_cert_t *inp, uint8_t val)
411 : {
412 0 : inp->cert_type = val;
413 0 : return 0;
414 : }
415 : uint16_t
416 0 : certs_cell_cert_get_cert_len(const certs_cell_cert_t *inp)
417 : {
418 0 : return inp->cert_len;
419 : }
420 : int
421 3 : certs_cell_cert_set_cert_len(certs_cell_cert_t *inp, uint16_t val)
422 : {
423 3 : inp->cert_len = val;
424 3 : return 0;
425 : }
426 : size_t
427 2 : certs_cell_cert_getlen_body(const certs_cell_cert_t *inp)
428 : {
429 2 : return TRUNNEL_DYNARRAY_LEN(&inp->body);
430 : }
431 :
432 : uint8_t
433 0 : certs_cell_cert_get_body(certs_cell_cert_t *inp, size_t idx)
434 : {
435 0 : return TRUNNEL_DYNARRAY_GET(&inp->body, idx);
436 : }
437 :
438 : uint8_t
439 0 : certs_cell_cert_getconst_body(const certs_cell_cert_t *inp, size_t idx)
440 : {
441 0 : return certs_cell_cert_get_body((certs_cell_cert_t*)inp, idx);
442 : }
443 : int
444 0 : certs_cell_cert_set_body(certs_cell_cert_t *inp, size_t idx, uint8_t elt)
445 : {
446 0 : TRUNNEL_DYNARRAY_SET(&inp->body, idx, elt);
447 0 : return 0;
448 : }
449 : int
450 0 : certs_cell_cert_add_body(certs_cell_cert_t *inp, uint8_t elt)
451 : {
452 : #if SIZE_MAX >= UINT16_MAX
453 0 : if (inp->body.n_ == UINT16_MAX)
454 0 : goto trunnel_alloc_failed;
455 : #endif
456 0 : TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->body, elt, {});
457 0 : return 0;
458 0 : trunnel_alloc_failed:
459 0 : TRUNNEL_SET_ERROR_CODE(inp);
460 0 : return -1;
461 : }
462 :
463 : uint8_t *
464 316 : certs_cell_cert_getarray_body(certs_cell_cert_t *inp)
465 : {
466 316 : return inp->body.elts_;
467 : }
468 : const uint8_t *
469 0 : certs_cell_cert_getconstarray_body(const certs_cell_cert_t *inp)
470 : {
471 0 : return (const uint8_t *)certs_cell_cert_getarray_body((certs_cell_cert_t*)inp);
472 : }
473 : int
474 179 : certs_cell_cert_setlen_body(certs_cell_cert_t *inp, size_t newlen)
475 : {
476 179 : uint8_t *newptr;
477 : #if UINT16_MAX < SIZE_MAX
478 179 : if (newlen > UINT16_MAX)
479 0 : goto trunnel_alloc_failed;
480 : #endif
481 358 : newptr = trunnel_dynarray_setlen(&inp->body.allocated_,
482 179 : &inp->body.n_, inp->body.elts_, newlen,
483 : sizeof(inp->body.elts_[0]), (trunnel_free_fn_t) NULL,
484 : &inp->trunnel_error_code_);
485 179 : if (newlen != 0 && newptr == NULL)
486 0 : goto trunnel_alloc_failed;
487 179 : inp->body.elts_ = newptr;
488 179 : return 0;
489 0 : trunnel_alloc_failed:
490 0 : TRUNNEL_SET_ERROR_CODE(inp);
491 0 : return -1;
492 : }
493 : const char *
494 679 : certs_cell_cert_check(const certs_cell_cert_t *obj)
495 : {
496 679 : if (obj == NULL)
497 : return "Object was NULL";
498 679 : if (obj->trunnel_error_code_)
499 : return "A set function failed on this object";
500 679 : if (TRUNNEL_DYNARRAY_LEN(&obj->body) != obj->cert_len)
501 0 : return "Length mismatch for body";
502 : return NULL;
503 : }
504 :
505 : ssize_t
506 14 : certs_cell_cert_encoded_len(const certs_cell_cert_t *obj)
507 : {
508 14 : ssize_t result = 0;
509 :
510 14 : if (NULL != certs_cell_cert_check(obj))
511 : return -1;
512 :
513 :
514 : /* Length of u8 cert_type */
515 14 : result += 1;
516 :
517 : /* Length of u16 cert_len */
518 14 : result += 2;
519 :
520 : /* Length of u8 body[cert_len] */
521 14 : result += TRUNNEL_DYNARRAY_LEN(&obj->body);
522 14 : return result;
523 : }
524 : int
525 0 : certs_cell_cert_clear_errors(certs_cell_cert_t *obj)
526 : {
527 0 : int r = obj->trunnel_error_code_;
528 0 : obj->trunnel_error_code_ = 0;
529 0 : return r;
530 : }
531 : ssize_t
532 274 : certs_cell_cert_encode(uint8_t *output, const size_t avail, const certs_cell_cert_t *obj)
533 : {
534 274 : ssize_t result = 0;
535 274 : size_t written = 0;
536 274 : uint8_t *ptr = output;
537 274 : const char *msg;
538 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
539 : const ssize_t encoded_len = certs_cell_cert_encoded_len(obj);
540 : #endif
541 :
542 274 : if (NULL != (msg = certs_cell_cert_check(obj)))
543 0 : goto check_failed;
544 :
545 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
546 : trunnel_assert(encoded_len >= 0);
547 : #endif
548 :
549 : /* Encode u8 cert_type */
550 274 : trunnel_assert(written <= avail);
551 274 : if (avail - written < 1)
552 0 : goto truncated;
553 274 : trunnel_set_uint8(ptr, (obj->cert_type));
554 274 : written += 1; ptr += 1;
555 :
556 : /* Encode u16 cert_len */
557 274 : trunnel_assert(written <= avail);
558 274 : if (avail - written < 2)
559 0 : goto truncated;
560 274 : trunnel_set_uint16(ptr, trunnel_htons(obj->cert_len));
561 274 : written += 2; ptr += 2;
562 :
563 : /* Encode u8 body[cert_len] */
564 : {
565 274 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->body);
566 274 : trunnel_assert(obj->cert_len == elt_len);
567 274 : trunnel_assert(written <= avail);
568 274 : if (avail - written < elt_len)
569 0 : goto truncated;
570 274 : if (elt_len)
571 274 : memcpy(ptr, obj->body.elts_, elt_len);
572 274 : written += elt_len; ptr += elt_len;
573 : }
574 :
575 :
576 274 : trunnel_assert(ptr == output + written);
577 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
578 : {
579 : trunnel_assert(encoded_len >= 0);
580 : trunnel_assert((size_t)encoded_len == written);
581 : }
582 :
583 : #endif
584 :
585 274 : return written;
586 :
587 0 : truncated:
588 0 : result = -2;
589 0 : goto fail;
590 0 : check_failed:
591 0 : (void)msg;
592 0 : result = -1;
593 0 : goto fail;
594 : fail:
595 : trunnel_assert(result < 0);
596 : return result;
597 : }
598 :
599 : /** As certs_cell_cert_parse(), but do not allocate the output object.
600 : */
601 : static ssize_t
602 167 : certs_cell_cert_parse_into(certs_cell_cert_t *obj, const uint8_t *input, const size_t len_in)
603 : {
604 167 : const uint8_t *ptr = input;
605 167 : size_t remaining = len_in;
606 167 : ssize_t result = 0;
607 167 : (void)result;
608 :
609 : /* Parse u8 cert_type */
610 167 : CHECK_REMAINING(1, truncated);
611 166 : obj->cert_type = (trunnel_get_uint8(ptr));
612 166 : remaining -= 1; ptr += 1;
613 :
614 : /* Parse u16 cert_len */
615 166 : CHECK_REMAINING(2, truncated);
616 166 : obj->cert_len = trunnel_ntohs(trunnel_get_uint16(ptr));
617 166 : remaining -= 2; ptr += 2;
618 :
619 : /* Parse u8 body[cert_len] */
620 166 : CHECK_REMAINING(obj->cert_len, truncated);
621 162 : TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->body, obj->cert_len, {});
622 162 : obj->body.n_ = obj->cert_len;
623 162 : if (obj->cert_len)
624 162 : memcpy(obj->body.elts_, ptr, obj->cert_len);
625 162 : ptr += obj->cert_len; remaining -= obj->cert_len;
626 162 : trunnel_assert(ptr + remaining == input + len_in);
627 162 : return len_in - remaining;
628 :
629 : truncated:
630 : return -2;
631 0 : trunnel_alloc_failed:
632 0 : return -1;
633 : }
634 :
635 : ssize_t
636 167 : certs_cell_cert_parse(certs_cell_cert_t **output, const uint8_t *input, const size_t len_in)
637 : {
638 167 : ssize_t result;
639 167 : *output = certs_cell_cert_new();
640 167 : if (NULL == *output)
641 : return -1;
642 167 : result = certs_cell_cert_parse_into(*output, input, len_in);
643 167 : if (result < 0) {
644 5 : certs_cell_cert_free(*output);
645 5 : *output = NULL;
646 : }
647 : return result;
648 : }
649 : rsa_ed_crosscert_t *
650 197 : rsa_ed_crosscert_new(void)
651 : {
652 197 : rsa_ed_crosscert_t *val = trunnel_calloc(1, sizeof(rsa_ed_crosscert_t));
653 197 : if (NULL == val)
654 0 : return NULL;
655 : return val;
656 : }
657 :
658 : /** Release all storage held inside 'obj', but do not free 'obj'.
659 : */
660 : static void
661 197 : rsa_ed_crosscert_clear(rsa_ed_crosscert_t *obj)
662 : {
663 197 : (void) obj;
664 197 : TRUNNEL_DYNARRAY_WIPE(&obj->sig);
665 197 : TRUNNEL_DYNARRAY_CLEAR(&obj->sig);
666 197 : }
667 :
668 : void
669 199 : rsa_ed_crosscert_free(rsa_ed_crosscert_t *obj)
670 : {
671 199 : if (obj == NULL)
672 : return;
673 197 : rsa_ed_crosscert_clear(obj);
674 197 : trunnel_memwipe(obj, sizeof(rsa_ed_crosscert_t));
675 197 : trunnel_free_(obj);
676 : }
677 :
678 : size_t
679 0 : rsa_ed_crosscert_getlen_ed_key(const rsa_ed_crosscert_t *inp)
680 : {
681 0 : (void)inp; return 32;
682 : }
683 :
684 : uint8_t
685 0 : rsa_ed_crosscert_get_ed_key(rsa_ed_crosscert_t *inp, size_t idx)
686 : {
687 0 : trunnel_assert(idx < 32);
688 0 : return inp->ed_key[idx];
689 : }
690 :
691 : uint8_t
692 0 : rsa_ed_crosscert_getconst_ed_key(const rsa_ed_crosscert_t *inp, size_t idx)
693 : {
694 0 : return rsa_ed_crosscert_get_ed_key((rsa_ed_crosscert_t*)inp, idx);
695 : }
696 : int
697 0 : rsa_ed_crosscert_set_ed_key(rsa_ed_crosscert_t *inp, size_t idx, uint8_t elt)
698 : {
699 0 : trunnel_assert(idx < 32);
700 0 : inp->ed_key[idx] = elt;
701 0 : return 0;
702 : }
703 :
704 : uint8_t *
705 84 : rsa_ed_crosscert_getarray_ed_key(rsa_ed_crosscert_t *inp)
706 : {
707 84 : return inp->ed_key;
708 : }
709 : const uint8_t *
710 0 : rsa_ed_crosscert_getconstarray_ed_key(const rsa_ed_crosscert_t *inp)
711 : {
712 0 : return (const uint8_t *)rsa_ed_crosscert_getarray_ed_key((rsa_ed_crosscert_t*)inp);
713 : }
714 : uint32_t
715 83 : rsa_ed_crosscert_get_expiration(const rsa_ed_crosscert_t *inp)
716 : {
717 83 : return inp->expiration;
718 : }
719 : int
720 0 : rsa_ed_crosscert_set_expiration(rsa_ed_crosscert_t *inp, uint32_t val)
721 : {
722 0 : inp->expiration = val;
723 0 : return 0;
724 : }
725 : const uint8_t *
726 81 : rsa_ed_crosscert_get_end_of_signed(const rsa_ed_crosscert_t *inp)
727 : {
728 81 : return inp->end_of_signed;
729 : }
730 : uint8_t
731 81 : rsa_ed_crosscert_get_sig_len(const rsa_ed_crosscert_t *inp)
732 : {
733 81 : return inp->sig_len;
734 : }
735 : int
736 0 : rsa_ed_crosscert_set_sig_len(rsa_ed_crosscert_t *inp, uint8_t val)
737 : {
738 0 : inp->sig_len = val;
739 0 : return 0;
740 : }
741 : size_t
742 192 : rsa_ed_crosscert_getlen_sig(const rsa_ed_crosscert_t *inp)
743 : {
744 192 : return TRUNNEL_DYNARRAY_LEN(&inp->sig);
745 : }
746 :
747 : uint8_t
748 0 : rsa_ed_crosscert_get_sig(rsa_ed_crosscert_t *inp, size_t idx)
749 : {
750 0 : return TRUNNEL_DYNARRAY_GET(&inp->sig, idx);
751 : }
752 :
753 : uint8_t
754 0 : rsa_ed_crosscert_getconst_sig(const rsa_ed_crosscert_t *inp, size_t idx)
755 : {
756 0 : return rsa_ed_crosscert_get_sig((rsa_ed_crosscert_t*)inp, idx);
757 : }
758 : int
759 0 : rsa_ed_crosscert_set_sig(rsa_ed_crosscert_t *inp, size_t idx, uint8_t elt)
760 : {
761 0 : TRUNNEL_DYNARRAY_SET(&inp->sig, idx, elt);
762 0 : return 0;
763 : }
764 : int
765 0 : rsa_ed_crosscert_add_sig(rsa_ed_crosscert_t *inp, uint8_t elt)
766 : {
767 : #if SIZE_MAX >= UINT8_MAX
768 0 : if (inp->sig.n_ == UINT8_MAX)
769 0 : goto trunnel_alloc_failed;
770 : #endif
771 0 : TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->sig, elt, {});
772 0 : return 0;
773 0 : trunnel_alloc_failed:
774 0 : TRUNNEL_SET_ERROR_CODE(inp);
775 0 : return -1;
776 : }
777 :
778 : uint8_t *
779 192 : rsa_ed_crosscert_getarray_sig(rsa_ed_crosscert_t *inp)
780 : {
781 192 : return inp->sig.elts_;
782 : }
783 : const uint8_t *
784 0 : rsa_ed_crosscert_getconstarray_sig(const rsa_ed_crosscert_t *inp)
785 : {
786 0 : return (const uint8_t *)rsa_ed_crosscert_getarray_sig((rsa_ed_crosscert_t*)inp);
787 : }
788 : int
789 222 : rsa_ed_crosscert_setlen_sig(rsa_ed_crosscert_t *inp, size_t newlen)
790 : {
791 222 : uint8_t *newptr;
792 : #if UINT8_MAX < SIZE_MAX
793 222 : if (newlen > UINT8_MAX)
794 0 : goto trunnel_alloc_failed;
795 : #endif
796 444 : newptr = trunnel_dynarray_setlen(&inp->sig.allocated_,
797 222 : &inp->sig.n_, inp->sig.elts_, newlen,
798 : sizeof(inp->sig.elts_[0]), (trunnel_free_fn_t) NULL,
799 : &inp->trunnel_error_code_);
800 222 : if (newlen != 0 && newptr == NULL)
801 0 : goto trunnel_alloc_failed;
802 222 : inp->sig.elts_ = newptr;
803 222 : return 0;
804 0 : trunnel_alloc_failed:
805 0 : TRUNNEL_SET_ERROR_CODE(inp);
806 0 : return -1;
807 : }
808 : const char *
809 333 : rsa_ed_crosscert_check(const rsa_ed_crosscert_t *obj)
810 : {
811 333 : if (obj == NULL)
812 : return "Object was NULL";
813 333 : if (obj->trunnel_error_code_)
814 : return "A set function failed on this object";
815 333 : if (TRUNNEL_DYNARRAY_LEN(&obj->sig) != obj->sig_len)
816 0 : return "Length mismatch for sig";
817 : return NULL;
818 : }
819 :
820 : ssize_t
821 111 : rsa_ed_crosscert_encoded_len(const rsa_ed_crosscert_t *obj)
822 : {
823 111 : ssize_t result = 0;
824 :
825 111 : if (NULL != rsa_ed_crosscert_check(obj))
826 : return -1;
827 :
828 :
829 : /* Length of u8 ed_key[32] */
830 111 : result += 32;
831 :
832 : /* Length of u32 expiration */
833 111 : result += 4;
834 :
835 : /* Length of u8 sig_len */
836 111 : result += 1;
837 :
838 : /* Length of u8 sig[sig_len] */
839 111 : result += TRUNNEL_DYNARRAY_LEN(&obj->sig);
840 111 : return result;
841 : }
842 : int
843 0 : rsa_ed_crosscert_clear_errors(rsa_ed_crosscert_t *obj)
844 : {
845 0 : int r = obj->trunnel_error_code_;
846 0 : obj->trunnel_error_code_ = 0;
847 0 : return r;
848 : }
849 : ssize_t
850 222 : rsa_ed_crosscert_encode(uint8_t *output, const size_t avail, const rsa_ed_crosscert_t *obj)
851 : {
852 222 : ssize_t result = 0;
853 222 : size_t written = 0;
854 222 : uint8_t *ptr = output;
855 222 : const char *msg;
856 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
857 : const ssize_t encoded_len = rsa_ed_crosscert_encoded_len(obj);
858 : #endif
859 :
860 222 : if (NULL != (msg = rsa_ed_crosscert_check(obj)))
861 0 : goto check_failed;
862 :
863 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
864 : trunnel_assert(encoded_len >= 0);
865 : #endif
866 :
867 : /* Encode u8 ed_key[32] */
868 222 : trunnel_assert(written <= avail);
869 222 : if (avail - written < 32)
870 0 : goto truncated;
871 222 : memcpy(ptr, obj->ed_key, 32);
872 222 : written += 32; ptr += 32;
873 :
874 : /* Encode u32 expiration */
875 222 : trunnel_assert(written <= avail);
876 222 : if (avail - written < 4)
877 0 : goto truncated;
878 222 : trunnel_set_uint32(ptr, trunnel_htonl(obj->expiration));
879 222 : written += 4; ptr += 4;
880 :
881 : /* Encode u8 sig_len */
882 222 : trunnel_assert(written <= avail);
883 222 : if (avail - written < 1)
884 0 : goto truncated;
885 222 : trunnel_set_uint8(ptr, (obj->sig_len));
886 222 : written += 1; ptr += 1;
887 :
888 : /* Encode u8 sig[sig_len] */
889 : {
890 222 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->sig);
891 222 : trunnel_assert(obj->sig_len == elt_len);
892 222 : trunnel_assert(written <= avail);
893 222 : if (avail - written < elt_len)
894 0 : goto truncated;
895 222 : if (elt_len)
896 222 : memcpy(ptr, obj->sig.elts_, elt_len);
897 222 : written += elt_len; ptr += elt_len;
898 : }
899 :
900 :
901 222 : trunnel_assert(ptr == output + written);
902 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
903 : {
904 : trunnel_assert(encoded_len >= 0);
905 : trunnel_assert((size_t)encoded_len == written);
906 : }
907 :
908 : #endif
909 :
910 222 : return written;
911 :
912 0 : truncated:
913 0 : result = -2;
914 0 : goto fail;
915 0 : check_failed:
916 0 : (void)msg;
917 0 : result = -1;
918 0 : goto fail;
919 : fail:
920 : trunnel_assert(result < 0);
921 : return result;
922 : }
923 :
924 : /** As rsa_ed_crosscert_parse(), but do not allocate the output
925 : * object.
926 : */
927 : static ssize_t
928 86 : rsa_ed_crosscert_parse_into(rsa_ed_crosscert_t *obj, const uint8_t *input, const size_t len_in)
929 : {
930 86 : const uint8_t *ptr = input;
931 86 : size_t remaining = len_in;
932 86 : ssize_t result = 0;
933 86 : (void)result;
934 :
935 : /* Parse u8 ed_key[32] */
936 86 : CHECK_REMAINING(32, truncated);
937 85 : memcpy(obj->ed_key, ptr, 32);
938 85 : remaining -= 32; ptr += 32;
939 :
940 : /* Parse u32 expiration */
941 85 : CHECK_REMAINING(4, truncated);
942 85 : obj->expiration = trunnel_ntohl(trunnel_get_uint32(ptr));
943 85 : remaining -= 4; ptr += 4;
944 85 : obj->end_of_signed = ptr;
945 :
946 : /* Parse u8 sig_len */
947 85 : CHECK_REMAINING(1, truncated);
948 85 : obj->sig_len = (trunnel_get_uint8(ptr));
949 85 : remaining -= 1; ptr += 1;
950 :
951 : /* Parse u8 sig[sig_len] */
952 85 : CHECK_REMAINING(obj->sig_len, truncated);
953 84 : TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->sig, obj->sig_len, {});
954 84 : obj->sig.n_ = obj->sig_len;
955 84 : if (obj->sig_len)
956 84 : memcpy(obj->sig.elts_, ptr, obj->sig_len);
957 84 : ptr += obj->sig_len; remaining -= obj->sig_len;
958 84 : trunnel_assert(ptr + remaining == input + len_in);
959 84 : return len_in - remaining;
960 :
961 : truncated:
962 : return -2;
963 0 : trunnel_alloc_failed:
964 0 : return -1;
965 : }
966 :
967 : ssize_t
968 86 : rsa_ed_crosscert_parse(rsa_ed_crosscert_t **output, const uint8_t *input, const size_t len_in)
969 : {
970 86 : ssize_t result;
971 86 : *output = rsa_ed_crosscert_new();
972 86 : if (NULL == *output)
973 : return -1;
974 86 : result = rsa_ed_crosscert_parse_into(*output, input, len_in);
975 86 : if (result < 0) {
976 2 : rsa_ed_crosscert_free(*output);
977 2 : *output = NULL;
978 : }
979 : return result;
980 : }
981 : auth1_t *
982 37 : auth1_new(void)
983 : {
984 37 : auth1_t *val = trunnel_calloc(1, sizeof(auth1_t));
985 37 : if (NULL == val)
986 0 : return NULL;
987 : return val;
988 : }
989 :
990 : /** Release all storage held inside 'obj', but do not free 'obj'.
991 : */
992 : static void
993 37 : auth1_clear(auth1_t *obj)
994 : {
995 37 : (void) obj;
996 37 : TRUNNEL_DYNARRAY_WIPE(&obj->sig);
997 37 : TRUNNEL_DYNARRAY_CLEAR(&obj->sig);
998 37 : }
999 :
1000 : void
1001 37 : auth1_free(auth1_t *obj)
1002 : {
1003 37 : if (obj == NULL)
1004 : return;
1005 37 : auth1_clear(obj);
1006 37 : trunnel_memwipe(obj, sizeof(auth1_t));
1007 37 : trunnel_free_(obj);
1008 : }
1009 :
1010 : size_t
1011 0 : auth1_getlen_type(const auth1_t *inp)
1012 : {
1013 0 : (void)inp; return 8;
1014 : }
1015 :
1016 : uint8_t
1017 0 : auth1_get_type(auth1_t *inp, size_t idx)
1018 : {
1019 0 : trunnel_assert(idx < 8);
1020 0 : return inp->type[idx];
1021 : }
1022 :
1023 : uint8_t
1024 0 : auth1_getconst_type(const auth1_t *inp, size_t idx)
1025 : {
1026 0 : return auth1_get_type((auth1_t*)inp, idx);
1027 : }
1028 : int
1029 0 : auth1_set_type(auth1_t *inp, size_t idx, uint8_t elt)
1030 : {
1031 0 : trunnel_assert(idx < 8);
1032 0 : inp->type[idx] = elt;
1033 0 : return 0;
1034 : }
1035 :
1036 : uint8_t *
1037 28 : auth1_getarray_type(auth1_t *inp)
1038 : {
1039 28 : return inp->type;
1040 : }
1041 : const uint8_t *
1042 0 : auth1_getconstarray_type(const auth1_t *inp)
1043 : {
1044 0 : return (const uint8_t *)auth1_getarray_type((auth1_t*)inp);
1045 : }
1046 : size_t
1047 0 : auth1_getlen_cid(const auth1_t *inp)
1048 : {
1049 0 : (void)inp; return 32;
1050 : }
1051 :
1052 : uint8_t
1053 0 : auth1_get_cid(auth1_t *inp, size_t idx)
1054 : {
1055 0 : trunnel_assert(idx < 32);
1056 0 : return inp->cid[idx];
1057 : }
1058 :
1059 : uint8_t
1060 0 : auth1_getconst_cid(const auth1_t *inp, size_t idx)
1061 : {
1062 0 : return auth1_get_cid((auth1_t*)inp, idx);
1063 : }
1064 : int
1065 0 : auth1_set_cid(auth1_t *inp, size_t idx, uint8_t elt)
1066 : {
1067 0 : trunnel_assert(idx < 32);
1068 0 : inp->cid[idx] = elt;
1069 0 : return 0;
1070 : }
1071 :
1072 : uint8_t *
1073 0 : auth1_getarray_cid(auth1_t *inp)
1074 : {
1075 0 : return inp->cid;
1076 : }
1077 : const uint8_t *
1078 0 : auth1_getconstarray_cid(const auth1_t *inp)
1079 : {
1080 0 : return (const uint8_t *)auth1_getarray_cid((auth1_t*)inp);
1081 : }
1082 : size_t
1083 0 : auth1_getlen_sid(const auth1_t *inp)
1084 : {
1085 0 : (void)inp; return 32;
1086 : }
1087 :
1088 : uint8_t
1089 0 : auth1_get_sid(auth1_t *inp, size_t idx)
1090 : {
1091 0 : trunnel_assert(idx < 32);
1092 0 : return inp->sid[idx];
1093 : }
1094 :
1095 : uint8_t
1096 0 : auth1_getconst_sid(const auth1_t *inp, size_t idx)
1097 : {
1098 0 : return auth1_get_sid((auth1_t*)inp, idx);
1099 : }
1100 : int
1101 0 : auth1_set_sid(auth1_t *inp, size_t idx, uint8_t elt)
1102 : {
1103 0 : trunnel_assert(idx < 32);
1104 0 : inp->sid[idx] = elt;
1105 0 : return 0;
1106 : }
1107 :
1108 : uint8_t *
1109 0 : auth1_getarray_sid(auth1_t *inp)
1110 : {
1111 0 : return inp->sid;
1112 : }
1113 : const uint8_t *
1114 0 : auth1_getconstarray_sid(const auth1_t *inp)
1115 : {
1116 0 : return (const uint8_t *)auth1_getarray_sid((auth1_t*)inp);
1117 : }
1118 : size_t
1119 0 : auth1_getlen_u1_cid_ed(const auth1_t *inp)
1120 : {
1121 0 : (void)inp; return 32;
1122 : }
1123 :
1124 : uint8_t
1125 0 : auth1_get_u1_cid_ed(auth1_t *inp, size_t idx)
1126 : {
1127 0 : trunnel_assert(idx < 32);
1128 0 : return inp->u1_cid_ed[idx];
1129 : }
1130 :
1131 : uint8_t
1132 0 : auth1_getconst_u1_cid_ed(const auth1_t *inp, size_t idx)
1133 : {
1134 0 : return auth1_get_u1_cid_ed((auth1_t*)inp, idx);
1135 : }
1136 : int
1137 0 : auth1_set_u1_cid_ed(auth1_t *inp, size_t idx, uint8_t elt)
1138 : {
1139 0 : trunnel_assert(idx < 32);
1140 0 : inp->u1_cid_ed[idx] = elt;
1141 0 : return 0;
1142 : }
1143 :
1144 : uint8_t *
1145 0 : auth1_getarray_u1_cid_ed(auth1_t *inp)
1146 : {
1147 0 : return inp->u1_cid_ed;
1148 : }
1149 : const uint8_t *
1150 0 : auth1_getconstarray_u1_cid_ed(const auth1_t *inp)
1151 : {
1152 0 : return (const uint8_t *)auth1_getarray_u1_cid_ed((auth1_t*)inp);
1153 : }
1154 : size_t
1155 0 : auth1_getlen_u1_sid_ed(const auth1_t *inp)
1156 : {
1157 0 : (void)inp; return 32;
1158 : }
1159 :
1160 : uint8_t
1161 0 : auth1_get_u1_sid_ed(auth1_t *inp, size_t idx)
1162 : {
1163 0 : trunnel_assert(idx < 32);
1164 0 : return inp->u1_sid_ed[idx];
1165 : }
1166 :
1167 : uint8_t
1168 0 : auth1_getconst_u1_sid_ed(const auth1_t *inp, size_t idx)
1169 : {
1170 0 : return auth1_get_u1_sid_ed((auth1_t*)inp, idx);
1171 : }
1172 : int
1173 0 : auth1_set_u1_sid_ed(auth1_t *inp, size_t idx, uint8_t elt)
1174 : {
1175 0 : trunnel_assert(idx < 32);
1176 0 : inp->u1_sid_ed[idx] = elt;
1177 0 : return 0;
1178 : }
1179 :
1180 : uint8_t *
1181 0 : auth1_getarray_u1_sid_ed(auth1_t *inp)
1182 : {
1183 0 : return inp->u1_sid_ed;
1184 : }
1185 : const uint8_t *
1186 0 : auth1_getconstarray_u1_sid_ed(const auth1_t *inp)
1187 : {
1188 0 : return (const uint8_t *)auth1_getarray_u1_sid_ed((auth1_t*)inp);
1189 : }
1190 : size_t
1191 0 : auth1_getlen_slog(const auth1_t *inp)
1192 : {
1193 0 : (void)inp; return 32;
1194 : }
1195 :
1196 : uint8_t
1197 0 : auth1_get_slog(auth1_t *inp, size_t idx)
1198 : {
1199 0 : trunnel_assert(idx < 32);
1200 0 : return inp->slog[idx];
1201 : }
1202 :
1203 : uint8_t
1204 0 : auth1_getconst_slog(const auth1_t *inp, size_t idx)
1205 : {
1206 0 : return auth1_get_slog((auth1_t*)inp, idx);
1207 : }
1208 : int
1209 0 : auth1_set_slog(auth1_t *inp, size_t idx, uint8_t elt)
1210 : {
1211 0 : trunnel_assert(idx < 32);
1212 0 : inp->slog[idx] = elt;
1213 0 : return 0;
1214 : }
1215 :
1216 : uint8_t *
1217 0 : auth1_getarray_slog(auth1_t *inp)
1218 : {
1219 0 : return inp->slog;
1220 : }
1221 : const uint8_t *
1222 0 : auth1_getconstarray_slog(const auth1_t *inp)
1223 : {
1224 0 : return (const uint8_t *)auth1_getarray_slog((auth1_t*)inp);
1225 : }
1226 : size_t
1227 0 : auth1_getlen_clog(const auth1_t *inp)
1228 : {
1229 0 : (void)inp; return 32;
1230 : }
1231 :
1232 : uint8_t
1233 0 : auth1_get_clog(auth1_t *inp, size_t idx)
1234 : {
1235 0 : trunnel_assert(idx < 32);
1236 0 : return inp->clog[idx];
1237 : }
1238 :
1239 : uint8_t
1240 0 : auth1_getconst_clog(const auth1_t *inp, size_t idx)
1241 : {
1242 0 : return auth1_get_clog((auth1_t*)inp, idx);
1243 : }
1244 : int
1245 0 : auth1_set_clog(auth1_t *inp, size_t idx, uint8_t elt)
1246 : {
1247 0 : trunnel_assert(idx < 32);
1248 0 : inp->clog[idx] = elt;
1249 0 : return 0;
1250 : }
1251 :
1252 : uint8_t *
1253 0 : auth1_getarray_clog(auth1_t *inp)
1254 : {
1255 0 : return inp->clog;
1256 : }
1257 : const uint8_t *
1258 0 : auth1_getconstarray_clog(const auth1_t *inp)
1259 : {
1260 0 : return (const uint8_t *)auth1_getarray_clog((auth1_t*)inp);
1261 : }
1262 : size_t
1263 0 : auth1_getlen_scert(const auth1_t *inp)
1264 : {
1265 0 : (void)inp; return 32;
1266 : }
1267 :
1268 : uint8_t
1269 0 : auth1_get_scert(auth1_t *inp, size_t idx)
1270 : {
1271 0 : trunnel_assert(idx < 32);
1272 0 : return inp->scert[idx];
1273 : }
1274 :
1275 : uint8_t
1276 0 : auth1_getconst_scert(const auth1_t *inp, size_t idx)
1277 : {
1278 0 : return auth1_get_scert((auth1_t*)inp, idx);
1279 : }
1280 : int
1281 0 : auth1_set_scert(auth1_t *inp, size_t idx, uint8_t elt)
1282 : {
1283 0 : trunnel_assert(idx < 32);
1284 0 : inp->scert[idx] = elt;
1285 0 : return 0;
1286 : }
1287 :
1288 : uint8_t *
1289 0 : auth1_getarray_scert(auth1_t *inp)
1290 : {
1291 0 : return inp->scert;
1292 : }
1293 : const uint8_t *
1294 0 : auth1_getconstarray_scert(const auth1_t *inp)
1295 : {
1296 0 : return (const uint8_t *)auth1_getarray_scert((auth1_t*)inp);
1297 : }
1298 : size_t
1299 0 : auth1_getlen_tlssecrets(const auth1_t *inp)
1300 : {
1301 0 : (void)inp; return 32;
1302 : }
1303 :
1304 : uint8_t
1305 0 : auth1_get_tlssecrets(auth1_t *inp, size_t idx)
1306 : {
1307 0 : trunnel_assert(idx < 32);
1308 0 : return inp->tlssecrets[idx];
1309 : }
1310 :
1311 : uint8_t
1312 0 : auth1_getconst_tlssecrets(const auth1_t *inp, size_t idx)
1313 : {
1314 0 : return auth1_get_tlssecrets((auth1_t*)inp, idx);
1315 : }
1316 : int
1317 0 : auth1_set_tlssecrets(auth1_t *inp, size_t idx, uint8_t elt)
1318 : {
1319 0 : trunnel_assert(idx < 32);
1320 0 : inp->tlssecrets[idx] = elt;
1321 0 : return 0;
1322 : }
1323 :
1324 : uint8_t *
1325 0 : auth1_getarray_tlssecrets(auth1_t *inp)
1326 : {
1327 0 : return inp->tlssecrets;
1328 : }
1329 : const uint8_t *
1330 0 : auth1_getconstarray_tlssecrets(const auth1_t *inp)
1331 : {
1332 0 : return (const uint8_t *)auth1_getarray_tlssecrets((auth1_t*)inp);
1333 : }
1334 : const uint8_t *
1335 0 : auth1_get_end_of_fixed_part(const auth1_t *inp)
1336 : {
1337 0 : return inp->end_of_fixed_part;
1338 : }
1339 : size_t
1340 0 : auth1_getlen_rand(const auth1_t *inp)
1341 : {
1342 0 : (void)inp; return 24;
1343 : }
1344 :
1345 : uint8_t
1346 0 : auth1_get_rand(auth1_t *inp, size_t idx)
1347 : {
1348 0 : trunnel_assert(idx < 24);
1349 0 : return inp->rand[idx];
1350 : }
1351 :
1352 : uint8_t
1353 0 : auth1_getconst_rand(const auth1_t *inp, size_t idx)
1354 : {
1355 0 : return auth1_get_rand((auth1_t*)inp, idx);
1356 : }
1357 : int
1358 0 : auth1_set_rand(auth1_t *inp, size_t idx, uint8_t elt)
1359 : {
1360 0 : trunnel_assert(idx < 24);
1361 0 : inp->rand[idx] = elt;
1362 0 : return 0;
1363 : }
1364 :
1365 : uint8_t *
1366 0 : auth1_getarray_rand(auth1_t *inp)
1367 : {
1368 0 : return inp->rand;
1369 : }
1370 : const uint8_t *
1371 0 : auth1_getconstarray_rand(const auth1_t *inp)
1372 : {
1373 0 : return (const uint8_t *)auth1_getarray_rand((auth1_t*)inp);
1374 : }
1375 : const uint8_t *
1376 0 : auth1_get_end_of_signed(const auth1_t *inp)
1377 : {
1378 0 : return inp->end_of_signed;
1379 : }
1380 : size_t
1381 19 : auth1_getlen_sig(const auth1_t *inp)
1382 : {
1383 19 : return TRUNNEL_DYNARRAY_LEN(&inp->sig);
1384 : }
1385 :
1386 : uint8_t
1387 0 : auth1_get_sig(auth1_t *inp, size_t idx)
1388 : {
1389 0 : return TRUNNEL_DYNARRAY_GET(&inp->sig, idx);
1390 : }
1391 :
1392 : uint8_t
1393 0 : auth1_getconst_sig(const auth1_t *inp, size_t idx)
1394 : {
1395 0 : return auth1_get_sig((auth1_t*)inp, idx);
1396 : }
1397 : int
1398 0 : auth1_set_sig(auth1_t *inp, size_t idx, uint8_t elt)
1399 : {
1400 0 : TRUNNEL_DYNARRAY_SET(&inp->sig, idx, elt);
1401 0 : return 0;
1402 : }
1403 : int
1404 0 : auth1_add_sig(auth1_t *inp, uint8_t elt)
1405 : {
1406 0 : TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->sig, elt, {});
1407 0 : return 0;
1408 0 : trunnel_alloc_failed:
1409 0 : TRUNNEL_SET_ERROR_CODE(inp);
1410 0 : return -1;
1411 : }
1412 :
1413 : uint8_t *
1414 22 : auth1_getarray_sig(auth1_t *inp)
1415 : {
1416 22 : return inp->sig.elts_;
1417 : }
1418 : const uint8_t *
1419 0 : auth1_getconstarray_sig(const auth1_t *inp)
1420 : {
1421 0 : return (const uint8_t *)auth1_getarray_sig((auth1_t*)inp);
1422 : }
1423 : int
1424 36 : auth1_setlen_sig(auth1_t *inp, size_t newlen)
1425 : {
1426 36 : uint8_t *newptr;
1427 72 : newptr = trunnel_dynarray_setlen(&inp->sig.allocated_,
1428 36 : &inp->sig.n_, inp->sig.elts_, newlen,
1429 : sizeof(inp->sig.elts_[0]), (trunnel_free_fn_t) NULL,
1430 : &inp->trunnel_error_code_);
1431 36 : if (newlen != 0 && newptr == NULL)
1432 0 : goto trunnel_alloc_failed;
1433 36 : inp->sig.elts_ = newptr;
1434 36 : return 0;
1435 0 : trunnel_alloc_failed:
1436 0 : TRUNNEL_SET_ERROR_CODE(inp);
1437 0 : return -1;
1438 : }
1439 : const char *
1440 74 : auth1_check(const auth1_t *obj, const auth_ctx_t *auth_ctx_ctx)
1441 : {
1442 74 : if (obj == NULL)
1443 : return "Object was NULL";
1444 74 : if (obj->trunnel_error_code_)
1445 : return "A set function failed on this object";
1446 74 : if (auth_ctx_ctx == NULL)
1447 : return "Context was NULL";
1448 74 : switch (auth_ctx_ctx->is_ed) {
1449 :
1450 : case 0:
1451 : break;
1452 :
1453 : case 1:
1454 : break;
1455 :
1456 : default:
1457 : return "Bad tag for union";
1458 74 : break;
1459 : }
1460 74 : return NULL;
1461 : }
1462 :
1463 : ssize_t
1464 27 : auth1_encoded_len(const auth1_t *obj, const auth_ctx_t *auth_ctx_ctx)
1465 : {
1466 27 : ssize_t result = 0;
1467 :
1468 27 : if (NULL != auth1_check(obj, auth_ctx_ctx))
1469 : return -1;
1470 :
1471 :
1472 : /* Length of u8 type[8] */
1473 27 : result += 8;
1474 :
1475 : /* Length of u8 cid[32] */
1476 27 : result += 32;
1477 :
1478 : /* Length of u8 sid[32] */
1479 27 : result += 32;
1480 27 : switch (auth_ctx_ctx->is_ed) {
1481 :
1482 : case 0:
1483 : break;
1484 :
1485 7 : case 1:
1486 :
1487 : /* Length of u8 u1_cid_ed[32] */
1488 7 : result += 32;
1489 :
1490 : /* Length of u8 u1_sid_ed[32] */
1491 7 : result += 32;
1492 7 : break;
1493 :
1494 : default:
1495 0 : trunnel_assert(0);
1496 : break;
1497 : }
1498 :
1499 : /* Length of u8 slog[32] */
1500 27 : result += 32;
1501 :
1502 : /* Length of u8 clog[32] */
1503 27 : result += 32;
1504 :
1505 : /* Length of u8 scert[32] */
1506 27 : result += 32;
1507 :
1508 : /* Length of u8 tlssecrets[32] */
1509 27 : result += 32;
1510 :
1511 : /* Length of u8 rand[24] */
1512 27 : result += 24;
1513 :
1514 : /* Length of u8 sig[] */
1515 27 : result += TRUNNEL_DYNARRAY_LEN(&obj->sig);
1516 27 : return result;
1517 : }
1518 : int
1519 0 : auth1_clear_errors(auth1_t *obj)
1520 : {
1521 0 : int r = obj->trunnel_error_code_;
1522 0 : obj->trunnel_error_code_ = 0;
1523 0 : return r;
1524 : }
1525 : ssize_t
1526 47 : auth1_encode(uint8_t *output, const size_t avail, const auth1_t *obj, const auth_ctx_t *auth_ctx_ctx)
1527 : {
1528 47 : ssize_t result = 0;
1529 47 : size_t written = 0;
1530 47 : uint8_t *ptr = output;
1531 47 : const char *msg;
1532 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1533 : const ssize_t encoded_len = auth1_encoded_len(obj, auth_ctx_ctx);
1534 : #endif
1535 :
1536 47 : if (NULL != (msg = auth1_check(obj, auth_ctx_ctx)))
1537 0 : goto check_failed;
1538 :
1539 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1540 : trunnel_assert(encoded_len >= 0);
1541 : #endif
1542 :
1543 : /* Encode u8 type[8] */
1544 47 : trunnel_assert(written <= avail);
1545 47 : if (avail - written < 8)
1546 0 : goto truncated;
1547 47 : memcpy(ptr, obj->type, 8);
1548 47 : written += 8; ptr += 8;
1549 :
1550 : /* Encode u8 cid[32] */
1551 47 : trunnel_assert(written <= avail);
1552 47 : if (avail - written < 32)
1553 0 : goto truncated;
1554 47 : memcpy(ptr, obj->cid, 32);
1555 47 : written += 32; ptr += 32;
1556 :
1557 : /* Encode u8 sid[32] */
1558 47 : trunnel_assert(written <= avail);
1559 47 : if (avail - written < 32)
1560 0 : goto truncated;
1561 47 : memcpy(ptr, obj->sid, 32);
1562 47 : written += 32; ptr += 32;
1563 :
1564 : /* Encode union u1[auth_ctx.is_ed] */
1565 47 : trunnel_assert(written <= avail);
1566 47 : switch (auth_ctx_ctx->is_ed) {
1567 :
1568 : case 0:
1569 : break;
1570 :
1571 : case 1:
1572 :
1573 : /* Encode u8 u1_cid_ed[32] */
1574 11 : trunnel_assert(written <= avail);
1575 11 : if (avail - written < 32)
1576 0 : goto truncated;
1577 11 : memcpy(ptr, obj->u1_cid_ed, 32);
1578 11 : written += 32; ptr += 32;
1579 :
1580 : /* Encode u8 u1_sid_ed[32] */
1581 11 : trunnel_assert(written <= avail);
1582 11 : if (avail - written < 32)
1583 0 : goto truncated;
1584 11 : memcpy(ptr, obj->u1_sid_ed, 32);
1585 11 : written += 32; ptr += 32;
1586 11 : break;
1587 :
1588 : default:
1589 0 : trunnel_assert(0);
1590 : break;
1591 : }
1592 :
1593 : /* Encode u8 slog[32] */
1594 47 : trunnel_assert(written <= avail);
1595 47 : if (avail - written < 32)
1596 0 : goto truncated;
1597 47 : memcpy(ptr, obj->slog, 32);
1598 47 : written += 32; ptr += 32;
1599 :
1600 : /* Encode u8 clog[32] */
1601 47 : trunnel_assert(written <= avail);
1602 47 : if (avail - written < 32)
1603 0 : goto truncated;
1604 47 : memcpy(ptr, obj->clog, 32);
1605 47 : written += 32; ptr += 32;
1606 :
1607 : /* Encode u8 scert[32] */
1608 47 : trunnel_assert(written <= avail);
1609 47 : if (avail - written < 32)
1610 0 : goto truncated;
1611 47 : memcpy(ptr, obj->scert, 32);
1612 47 : written += 32; ptr += 32;
1613 :
1614 : /* Encode u8 tlssecrets[32] */
1615 47 : trunnel_assert(written <= avail);
1616 47 : if (avail - written < 32)
1617 0 : goto truncated;
1618 47 : memcpy(ptr, obj->tlssecrets, 32);
1619 47 : written += 32; ptr += 32;
1620 :
1621 : /* Encode u8 rand[24] */
1622 47 : trunnel_assert(written <= avail);
1623 47 : if (avail - written < 24)
1624 0 : goto truncated;
1625 47 : memcpy(ptr, obj->rand, 24);
1626 47 : written += 24; ptr += 24;
1627 :
1628 : /* Encode u8 sig[] */
1629 : {
1630 47 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->sig);
1631 47 : trunnel_assert(written <= avail);
1632 47 : if (avail - written < elt_len)
1633 0 : goto truncated;
1634 47 : if (elt_len)
1635 20 : memcpy(ptr, obj->sig.elts_, elt_len);
1636 47 : written += elt_len; ptr += elt_len;
1637 : }
1638 :
1639 :
1640 47 : trunnel_assert(ptr == output + written);
1641 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1642 : {
1643 : trunnel_assert(encoded_len >= 0);
1644 : trunnel_assert((size_t)encoded_len == written);
1645 : }
1646 :
1647 : #endif
1648 :
1649 47 : return written;
1650 :
1651 0 : truncated:
1652 0 : result = -2;
1653 0 : goto fail;
1654 0 : check_failed:
1655 0 : (void)msg;
1656 0 : result = -1;
1657 0 : goto fail;
1658 : fail:
1659 : trunnel_assert(result < 0);
1660 : return result;
1661 : }
1662 :
1663 : /** As auth1_parse(), but do not allocate the output object.
1664 : */
1665 : static ssize_t
1666 9 : auth1_parse_into(auth1_t *obj, const uint8_t *input, const size_t len_in, const auth_ctx_t *auth_ctx_ctx)
1667 : {
1668 9 : const uint8_t *ptr = input;
1669 9 : size_t remaining = len_in;
1670 9 : ssize_t result = 0;
1671 9 : (void)result;
1672 9 : if (auth_ctx_ctx == NULL)
1673 : return -1;
1674 :
1675 : /* Parse u8 type[8] */
1676 9 : CHECK_REMAINING(8, truncated);
1677 9 : memcpy(obj->type, ptr, 8);
1678 9 : remaining -= 8; ptr += 8;
1679 :
1680 : /* Parse u8 cid[32] */
1681 9 : CHECK_REMAINING(32, truncated);
1682 9 : memcpy(obj->cid, ptr, 32);
1683 9 : remaining -= 32; ptr += 32;
1684 :
1685 : /* Parse u8 sid[32] */
1686 9 : CHECK_REMAINING(32, truncated);
1687 9 : memcpy(obj->sid, ptr, 32);
1688 9 : remaining -= 32; ptr += 32;
1689 :
1690 : /* Parse union u1[auth_ctx.is_ed] */
1691 9 : switch (auth_ctx_ctx->is_ed) {
1692 :
1693 : case 0:
1694 : break;
1695 :
1696 4 : case 1:
1697 :
1698 : /* Parse u8 u1_cid_ed[32] */
1699 4 : CHECK_REMAINING(32, truncated);
1700 4 : memcpy(obj->u1_cid_ed, ptr, 32);
1701 4 : remaining -= 32; ptr += 32;
1702 :
1703 : /* Parse u8 u1_sid_ed[32] */
1704 4 : CHECK_REMAINING(32, truncated);
1705 4 : memcpy(obj->u1_sid_ed, ptr, 32);
1706 4 : remaining -= 32; ptr += 32;
1707 4 : break;
1708 :
1709 0 : default:
1710 0 : goto fail;
1711 9 : break;
1712 : }
1713 :
1714 : /* Parse u8 slog[32] */
1715 9 : CHECK_REMAINING(32, truncated);
1716 9 : memcpy(obj->slog, ptr, 32);
1717 9 : remaining -= 32; ptr += 32;
1718 :
1719 : /* Parse u8 clog[32] */
1720 9 : CHECK_REMAINING(32, truncated);
1721 9 : memcpy(obj->clog, ptr, 32);
1722 9 : remaining -= 32; ptr += 32;
1723 :
1724 : /* Parse u8 scert[32] */
1725 9 : CHECK_REMAINING(32, truncated);
1726 9 : memcpy(obj->scert, ptr, 32);
1727 9 : remaining -= 32; ptr += 32;
1728 :
1729 : /* Parse u8 tlssecrets[32] */
1730 9 : CHECK_REMAINING(32, truncated);
1731 9 : memcpy(obj->tlssecrets, ptr, 32);
1732 9 : remaining -= 32; ptr += 32;
1733 9 : obj->end_of_fixed_part = ptr;
1734 :
1735 : /* Parse u8 rand[24] */
1736 9 : CHECK_REMAINING(24, truncated);
1737 9 : memcpy(obj->rand, ptr, 24);
1738 9 : remaining -= 24; ptr += 24;
1739 9 : obj->end_of_signed = ptr;
1740 :
1741 : /* Parse u8 sig[] */
1742 9 : TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->sig, remaining, {});
1743 9 : obj->sig.n_ = remaining;
1744 9 : if (remaining)
1745 2 : memcpy(obj->sig.elts_, ptr, remaining);
1746 9 : ptr += remaining; remaining -= remaining;
1747 9 : trunnel_assert(ptr + remaining == input + len_in);
1748 9 : return len_in - remaining;
1749 :
1750 : truncated:
1751 : return -2;
1752 0 : trunnel_alloc_failed:
1753 0 : return -1;
1754 0 : fail:
1755 0 : result = -1;
1756 0 : return result;
1757 : }
1758 :
1759 : ssize_t
1760 9 : auth1_parse(auth1_t **output, const uint8_t *input, const size_t len_in, const auth_ctx_t *auth_ctx_ctx)
1761 : {
1762 9 : ssize_t result;
1763 9 : *output = auth1_new();
1764 9 : if (NULL == *output)
1765 : return -1;
1766 9 : result = auth1_parse_into(*output, input, len_in, auth_ctx_ctx);
1767 9 : if (result < 0) {
1768 0 : auth1_free(*output);
1769 0 : *output = NULL;
1770 : }
1771 : return result;
1772 : }
1773 : certs_cell_t *
1774 94 : certs_cell_new(void)
1775 : {
1776 94 : certs_cell_t *val = trunnel_calloc(1, sizeof(certs_cell_t));
1777 94 : if (NULL == val)
1778 0 : return NULL;
1779 : return val;
1780 : }
1781 :
1782 : /** Release all storage held inside 'obj', but do not free 'obj'.
1783 : */
1784 : static void
1785 94 : certs_cell_clear(certs_cell_t *obj)
1786 : {
1787 94 : (void) obj;
1788 : {
1789 :
1790 94 : unsigned idx;
1791 422 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->certs); ++idx) {
1792 328 : certs_cell_cert_free(TRUNNEL_DYNARRAY_GET(&obj->certs, idx));
1793 : }
1794 : }
1795 94 : TRUNNEL_DYNARRAY_WIPE(&obj->certs);
1796 94 : TRUNNEL_DYNARRAY_CLEAR(&obj->certs);
1797 94 : }
1798 :
1799 : void
1800 105 : certs_cell_free(certs_cell_t *obj)
1801 : {
1802 105 : if (obj == NULL)
1803 : return;
1804 94 : certs_cell_clear(obj);
1805 94 : trunnel_memwipe(obj, sizeof(certs_cell_t));
1806 94 : trunnel_free_(obj);
1807 : }
1808 :
1809 : uint8_t
1810 0 : certs_cell_get_n_certs(const certs_cell_t *inp)
1811 : {
1812 0 : return inp->n_certs;
1813 : }
1814 : int
1815 0 : certs_cell_set_n_certs(certs_cell_t *inp, uint8_t val)
1816 : {
1817 0 : inp->n_certs = val;
1818 0 : return 0;
1819 : }
1820 : size_t
1821 10 : certs_cell_getlen_certs(const certs_cell_t *inp)
1822 : {
1823 10 : return TRUNNEL_DYNARRAY_LEN(&inp->certs);
1824 : }
1825 :
1826 : struct certs_cell_cert_st *
1827 189 : certs_cell_get_certs(certs_cell_t *inp, size_t idx)
1828 : {
1829 189 : return TRUNNEL_DYNARRAY_GET(&inp->certs, idx);
1830 : }
1831 :
1832 : const struct certs_cell_cert_st *
1833 0 : certs_cell_getconst_certs(const certs_cell_t *inp, size_t idx)
1834 : {
1835 0 : return certs_cell_get_certs((certs_cell_t*)inp, idx);
1836 : }
1837 : int
1838 4 : certs_cell_set_certs(certs_cell_t *inp, size_t idx, struct certs_cell_cert_st * elt)
1839 : {
1840 4 : certs_cell_cert_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->certs, idx);
1841 4 : if (oldval && oldval != elt)
1842 4 : certs_cell_cert_free(oldval);
1843 4 : return certs_cell_set0_certs(inp, idx, elt);
1844 : }
1845 : int
1846 8 : certs_cell_set0_certs(certs_cell_t *inp, size_t idx, struct certs_cell_cert_st * elt)
1847 : {
1848 8 : TRUNNEL_DYNARRAY_SET(&inp->certs, idx, elt);
1849 8 : return 0;
1850 : }
1851 : int
1852 171 : certs_cell_add_certs(certs_cell_t *inp, struct certs_cell_cert_st * elt)
1853 : {
1854 : #if SIZE_MAX >= UINT8_MAX
1855 171 : if (inp->certs.n_ == UINT8_MAX)
1856 0 : goto trunnel_alloc_failed;
1857 : #endif
1858 171 : TRUNNEL_DYNARRAY_ADD(struct certs_cell_cert_st *, &inp->certs, elt, {});
1859 171 : return 0;
1860 0 : trunnel_alloc_failed:
1861 0 : TRUNNEL_SET_ERROR_CODE(inp);
1862 0 : return -1;
1863 : }
1864 :
1865 : struct certs_cell_cert_st * *
1866 0 : certs_cell_getarray_certs(certs_cell_t *inp)
1867 : {
1868 0 : return inp->certs.elts_;
1869 : }
1870 : const struct certs_cell_cert_st * const *
1871 0 : certs_cell_getconstarray_certs(const certs_cell_t *inp)
1872 : {
1873 0 : return (const struct certs_cell_cert_st * const *)certs_cell_getarray_certs((certs_cell_t*)inp);
1874 : }
1875 : int
1876 5 : certs_cell_setlen_certs(certs_cell_t *inp, size_t newlen)
1877 : {
1878 5 : struct certs_cell_cert_st * *newptr;
1879 : #if UINT8_MAX < SIZE_MAX
1880 5 : if (newlen > UINT8_MAX)
1881 0 : goto trunnel_alloc_failed;
1882 : #endif
1883 10 : newptr = trunnel_dynarray_setlen(&inp->certs.allocated_,
1884 5 : &inp->certs.n_, inp->certs.elts_, newlen,
1885 : sizeof(inp->certs.elts_[0]), (trunnel_free_fn_t) certs_cell_cert_free,
1886 : &inp->trunnel_error_code_);
1887 5 : if (newlen != 0 && newptr == NULL)
1888 0 : goto trunnel_alloc_failed;
1889 5 : inp->certs.elts_ = newptr;
1890 5 : return 0;
1891 0 : trunnel_alloc_failed:
1892 0 : TRUNNEL_SET_ERROR_CODE(inp);
1893 0 : return -1;
1894 : }
1895 : const char *
1896 106 : certs_cell_check(const certs_cell_t *obj)
1897 : {
1898 106 : if (obj == NULL)
1899 : return "Object was NULL";
1900 106 : if (obj->trunnel_error_code_)
1901 : return "A set function failed on this object";
1902 : {
1903 : const char *msg;
1904 :
1905 : unsigned idx;
1906 497 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->certs); ++idx) {
1907 391 : if (NULL != (msg = certs_cell_cert_check(TRUNNEL_DYNARRAY_GET(&obj->certs, idx))))
1908 0 : return msg;
1909 : }
1910 : }
1911 106 : if (TRUNNEL_DYNARRAY_LEN(&obj->certs) != obj->n_certs)
1912 0 : return "Length mismatch for certs";
1913 : return NULL;
1914 : }
1915 :
1916 : ssize_t
1917 4 : certs_cell_encoded_len(const certs_cell_t *obj)
1918 : {
1919 4 : ssize_t result = 0;
1920 :
1921 4 : if (NULL != certs_cell_check(obj))
1922 : return -1;
1923 :
1924 :
1925 : /* Length of u8 n_certs */
1926 : result += 1;
1927 :
1928 : /* Length of struct certs_cell_cert certs[n_certs] */
1929 : {
1930 :
1931 : unsigned idx;
1932 18 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->certs); ++idx) {
1933 14 : result += certs_cell_cert_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->certs, idx));
1934 : }
1935 : }
1936 : return result;
1937 : }
1938 : int
1939 0 : certs_cell_clear_errors(certs_cell_t *obj)
1940 : {
1941 0 : int r = obj->trunnel_error_code_;
1942 0 : obj->trunnel_error_code_ = 0;
1943 0 : return r;
1944 : }
1945 : ssize_t
1946 75 : certs_cell_encode(uint8_t *output, const size_t avail, const certs_cell_t *obj)
1947 : {
1948 75 : ssize_t result = 0;
1949 75 : size_t written = 0;
1950 75 : uint8_t *ptr = output;
1951 75 : const char *msg;
1952 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1953 : const ssize_t encoded_len = certs_cell_encoded_len(obj);
1954 : #endif
1955 :
1956 75 : if (NULL != (msg = certs_cell_check(obj)))
1957 0 : goto check_failed;
1958 :
1959 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1960 : trunnel_assert(encoded_len >= 0);
1961 : #endif
1962 :
1963 : /* Encode u8 n_certs */
1964 75 : trunnel_assert(written <= avail);
1965 75 : if (avail - written < 1)
1966 0 : goto truncated;
1967 75 : trunnel_set_uint8(ptr, (obj->n_certs));
1968 75 : written += 1; ptr += 1;
1969 :
1970 : /* Encode struct certs_cell_cert certs[n_certs] */
1971 : {
1972 :
1973 75 : unsigned idx;
1974 349 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->certs); ++idx) {
1975 274 : trunnel_assert(written <= avail);
1976 274 : result = certs_cell_cert_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->certs, idx));
1977 274 : if (result < 0)
1978 0 : goto fail; /* XXXXXXX !*/
1979 274 : written += result; ptr += result;
1980 : }
1981 : }
1982 :
1983 :
1984 75 : trunnel_assert(ptr == output + written);
1985 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1986 : {
1987 : trunnel_assert(encoded_len >= 0);
1988 : trunnel_assert((size_t)encoded_len == written);
1989 : }
1990 :
1991 : #endif
1992 :
1993 75 : return written;
1994 :
1995 0 : truncated:
1996 0 : result = -2;
1997 0 : goto fail;
1998 0 : check_failed:
1999 0 : (void)msg;
2000 0 : result = -1;
2001 0 : goto fail;
2002 0 : fail:
2003 0 : trunnel_assert(result < 0);
2004 : return result;
2005 : }
2006 :
2007 : /** As certs_cell_parse(), but do not allocate the output object.
2008 : */
2009 : static ssize_t
2010 46 : certs_cell_parse_into(certs_cell_t *obj, const uint8_t *input, const size_t len_in)
2011 : {
2012 46 : const uint8_t *ptr = input;
2013 46 : size_t remaining = len_in;
2014 46 : ssize_t result = 0;
2015 46 : (void)result;
2016 :
2017 : /* Parse u8 n_certs */
2018 46 : CHECK_REMAINING(1, truncated);
2019 46 : obj->n_certs = (trunnel_get_uint8(ptr));
2020 46 : remaining -= 1; ptr += 1;
2021 :
2022 : /* Parse struct certs_cell_cert certs[n_certs] */
2023 46 : TRUNNEL_DYNARRAY_EXPAND(certs_cell_cert_t *, &obj->certs, obj->n_certs, {});
2024 : {
2025 46 : certs_cell_cert_t * elt;
2026 46 : unsigned idx;
2027 208 : for (idx = 0; idx < obj->n_certs; ++idx) {
2028 167 : result = certs_cell_cert_parse(&elt, ptr, remaining);
2029 167 : if (result < 0)
2030 5 : goto relay_fail;
2031 162 : trunnel_assert((size_t)result <= remaining);
2032 162 : remaining -= result; ptr += result;
2033 162 : TRUNNEL_DYNARRAY_ADD(certs_cell_cert_t *, &obj->certs, elt, {certs_cell_cert_free(elt);});
2034 : }
2035 : }
2036 41 : trunnel_assert(ptr + remaining == input + len_in);
2037 41 : return len_in - remaining;
2038 :
2039 0 : truncated:
2040 0 : return -2;
2041 5 : relay_fail:
2042 5 : trunnel_assert(result < 0);
2043 : return result;
2044 : trunnel_alloc_failed:
2045 : return -1;
2046 : }
2047 :
2048 : ssize_t
2049 46 : certs_cell_parse(certs_cell_t **output, const uint8_t *input, const size_t len_in)
2050 : {
2051 46 : ssize_t result;
2052 46 : *output = certs_cell_new();
2053 46 : if (NULL == *output)
2054 : return -1;
2055 46 : result = certs_cell_parse_into(*output, input, len_in);
2056 46 : if (result < 0) {
2057 5 : certs_cell_free(*output);
2058 5 : *output = NULL;
2059 : }
2060 : return result;
2061 : }
|