Line data Source code
1 : /* cell_introduce1.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 "cell_introduce1.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 cellintroduce_deadcode_dummy__ = 0;
19 : #define OR_DEADCODE_DUMMY || cellintroduce_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 : typedef struct trn_cell_extension_st trn_cell_extension_t;
32 : trn_cell_extension_t *trn_cell_extension_new(void);
33 : void trn_cell_extension_free(trn_cell_extension_t *victim);
34 : ssize_t trn_cell_extension_parse(trn_cell_extension_t **output, const uint8_t *input, const size_t len_in);
35 : ssize_t trn_cell_extension_encoded_len(const trn_cell_extension_t *obj);
36 : ssize_t trn_cell_extension_encode(uint8_t *output, size_t avail, const trn_cell_extension_t *input);
37 : const char *trn_cell_extension_check(const trn_cell_extension_t *obj);
38 : int trn_cell_extension_clear_errors(trn_cell_extension_t *obj);
39 : typedef struct link_specifier_st link_specifier_t;
40 : link_specifier_t *link_specifier_new(void);
41 : void link_specifier_free(link_specifier_t *victim);
42 : ssize_t link_specifier_parse(link_specifier_t **output, const uint8_t *input, const size_t len_in);
43 : ssize_t link_specifier_encoded_len(const link_specifier_t *obj);
44 : ssize_t link_specifier_encode(uint8_t *output, size_t avail, const link_specifier_t *input);
45 : const char *link_specifier_check(const link_specifier_t *obj);
46 : int link_specifier_clear_errors(link_specifier_t *obj);
47 : trn_cell_introduce1_t *
48 16 : trn_cell_introduce1_new(void)
49 : {
50 16 : trn_cell_introduce1_t *val = trunnel_calloc(1, sizeof(trn_cell_introduce1_t));
51 16 : if (NULL == val)
52 : return NULL;
53 16 : val->auth_key_type = TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519;
54 16 : return val;
55 : }
56 :
57 : /** Release all storage held inside 'obj', but do not free 'obj'.
58 : */
59 : static void
60 16 : trn_cell_introduce1_clear(trn_cell_introduce1_t *obj)
61 : {
62 16 : (void) obj;
63 16 : TRUNNEL_DYNARRAY_WIPE(&obj->auth_key);
64 16 : TRUNNEL_DYNARRAY_CLEAR(&obj->auth_key);
65 16 : trn_cell_extension_free(obj->extensions);
66 16 : obj->extensions = NULL;
67 16 : TRUNNEL_DYNARRAY_WIPE(&obj->encrypted);
68 16 : TRUNNEL_DYNARRAY_CLEAR(&obj->encrypted);
69 16 : }
70 :
71 : void
72 17 : trn_cell_introduce1_free(trn_cell_introduce1_t *obj)
73 : {
74 17 : if (obj == NULL)
75 : return;
76 16 : trn_cell_introduce1_clear(obj);
77 16 : trunnel_memwipe(obj, sizeof(trn_cell_introduce1_t));
78 16 : trunnel_free_(obj);
79 : }
80 :
81 : size_t
82 10 : trn_cell_introduce1_getlen_legacy_key_id(const trn_cell_introduce1_t *inp)
83 : {
84 10 : (void)inp; return TRUNNEL_SHA1_LEN;
85 : }
86 :
87 : uint8_t
88 0 : trn_cell_introduce1_get_legacy_key_id(trn_cell_introduce1_t *inp, size_t idx)
89 : {
90 0 : trunnel_assert(idx < TRUNNEL_SHA1_LEN);
91 0 : return inp->legacy_key_id[idx];
92 : }
93 :
94 : uint8_t
95 0 : trn_cell_introduce1_getconst_legacy_key_id(const trn_cell_introduce1_t *inp, size_t idx)
96 : {
97 0 : return trn_cell_introduce1_get_legacy_key_id((trn_cell_introduce1_t*)inp, idx);
98 : }
99 : int
100 0 : trn_cell_introduce1_set_legacy_key_id(trn_cell_introduce1_t *inp, size_t idx, uint8_t elt)
101 : {
102 0 : trunnel_assert(idx < TRUNNEL_SHA1_LEN);
103 0 : inp->legacy_key_id[idx] = elt;
104 0 : return 0;
105 : }
106 :
107 : uint8_t *
108 10 : trn_cell_introduce1_getarray_legacy_key_id(trn_cell_introduce1_t *inp)
109 : {
110 10 : return inp->legacy_key_id;
111 : }
112 : const uint8_t *
113 10 : trn_cell_introduce1_getconstarray_legacy_key_id(const trn_cell_introduce1_t *inp)
114 : {
115 10 : return (const uint8_t *)trn_cell_introduce1_getarray_legacy_key_id((trn_cell_introduce1_t*)inp);
116 : }
117 : uint8_t
118 10 : trn_cell_introduce1_get_auth_key_type(const trn_cell_introduce1_t *inp)
119 : {
120 10 : return inp->auth_key_type;
121 : }
122 : int
123 6 : trn_cell_introduce1_set_auth_key_type(trn_cell_introduce1_t *inp, uint8_t val)
124 : {
125 6 : if (! ((val == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519 || val == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0 || val == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1))) {
126 0 : TRUNNEL_SET_ERROR_CODE(inp);
127 0 : return -1;
128 : }
129 6 : inp->auth_key_type = val;
130 6 : return 0;
131 : }
132 : uint16_t
133 9 : trn_cell_introduce1_get_auth_key_len(const trn_cell_introduce1_t *inp)
134 : {
135 9 : return inp->auth_key_len;
136 : }
137 : int
138 6 : trn_cell_introduce1_set_auth_key_len(trn_cell_introduce1_t *inp, uint16_t val)
139 : {
140 6 : inp->auth_key_len = val;
141 6 : return 0;
142 : }
143 : size_t
144 12 : trn_cell_introduce1_getlen_auth_key(const trn_cell_introduce1_t *inp)
145 : {
146 12 : return TRUNNEL_DYNARRAY_LEN(&inp->auth_key);
147 : }
148 :
149 : uint8_t
150 0 : trn_cell_introduce1_get_auth_key(trn_cell_introduce1_t *inp, size_t idx)
151 : {
152 0 : return TRUNNEL_DYNARRAY_GET(&inp->auth_key, idx);
153 : }
154 :
155 : uint8_t
156 0 : trn_cell_introduce1_getconst_auth_key(const trn_cell_introduce1_t *inp, size_t idx)
157 : {
158 0 : return trn_cell_introduce1_get_auth_key((trn_cell_introduce1_t*)inp, idx);
159 : }
160 : int
161 0 : trn_cell_introduce1_set_auth_key(trn_cell_introduce1_t *inp, size_t idx, uint8_t elt)
162 : {
163 0 : TRUNNEL_DYNARRAY_SET(&inp->auth_key, idx, elt);
164 0 : return 0;
165 : }
166 : int
167 0 : trn_cell_introduce1_add_auth_key(trn_cell_introduce1_t *inp, uint8_t elt)
168 : {
169 : #if SIZE_MAX >= UINT16_MAX
170 0 : if (inp->auth_key.n_ == UINT16_MAX)
171 0 : goto trunnel_alloc_failed;
172 : #endif
173 0 : TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->auth_key, elt, {});
174 0 : return 0;
175 0 : trunnel_alloc_failed:
176 0 : TRUNNEL_SET_ERROR_CODE(inp);
177 0 : return -1;
178 : }
179 :
180 : uint8_t *
181 8 : trn_cell_introduce1_getarray_auth_key(trn_cell_introduce1_t *inp)
182 : {
183 8 : return inp->auth_key.elts_;
184 : }
185 : const uint8_t *
186 2 : trn_cell_introduce1_getconstarray_auth_key(const trn_cell_introduce1_t *inp)
187 : {
188 2 : return (const uint8_t *)trn_cell_introduce1_getarray_auth_key((trn_cell_introduce1_t*)inp);
189 : }
190 : int
191 8 : trn_cell_introduce1_setlen_auth_key(trn_cell_introduce1_t *inp, size_t newlen)
192 : {
193 8 : uint8_t *newptr;
194 : #if UINT16_MAX < SIZE_MAX
195 8 : if (newlen > UINT16_MAX)
196 0 : goto trunnel_alloc_failed;
197 : #endif
198 16 : newptr = trunnel_dynarray_setlen(&inp->auth_key.allocated_,
199 8 : &inp->auth_key.n_, inp->auth_key.elts_, newlen,
200 : sizeof(inp->auth_key.elts_[0]), (trunnel_free_fn_t) NULL,
201 : &inp->trunnel_error_code_);
202 8 : if (newlen != 0 && newptr == NULL)
203 0 : goto trunnel_alloc_failed;
204 8 : inp->auth_key.elts_ = newptr;
205 8 : return 0;
206 0 : trunnel_alloc_failed:
207 0 : TRUNNEL_SET_ERROR_CODE(inp);
208 0 : return -1;
209 : }
210 : struct trn_cell_extension_st *
211 0 : trn_cell_introduce1_get_extensions(trn_cell_introduce1_t *inp)
212 : {
213 0 : return inp->extensions;
214 : }
215 : const struct trn_cell_extension_st *
216 0 : trn_cell_introduce1_getconst_extensions(const trn_cell_introduce1_t *inp)
217 : {
218 0 : return trn_cell_introduce1_get_extensions((trn_cell_introduce1_t*) inp);
219 : }
220 : int
221 6 : trn_cell_introduce1_set_extensions(trn_cell_introduce1_t *inp, struct trn_cell_extension_st *val)
222 : {
223 6 : if (inp->extensions && inp->extensions != val)
224 0 : trn_cell_extension_free(inp->extensions);
225 6 : return trn_cell_introduce1_set0_extensions(inp, val);
226 : }
227 : int
228 6 : trn_cell_introduce1_set0_extensions(trn_cell_introduce1_t *inp, struct trn_cell_extension_st *val)
229 : {
230 6 : inp->extensions = val;
231 6 : return 0;
232 : }
233 : size_t
234 14 : trn_cell_introduce1_getlen_encrypted(const trn_cell_introduce1_t *inp)
235 : {
236 14 : return TRUNNEL_DYNARRAY_LEN(&inp->encrypted);
237 : }
238 :
239 : uint8_t
240 0 : trn_cell_introduce1_get_encrypted(trn_cell_introduce1_t *inp, size_t idx)
241 : {
242 0 : return TRUNNEL_DYNARRAY_GET(&inp->encrypted, idx);
243 : }
244 :
245 : uint8_t
246 0 : trn_cell_introduce1_getconst_encrypted(const trn_cell_introduce1_t *inp, size_t idx)
247 : {
248 0 : return trn_cell_introduce1_get_encrypted((trn_cell_introduce1_t*)inp, idx);
249 : }
250 : int
251 0 : trn_cell_introduce1_set_encrypted(trn_cell_introduce1_t *inp, size_t idx, uint8_t elt)
252 : {
253 0 : TRUNNEL_DYNARRAY_SET(&inp->encrypted, idx, elt);
254 0 : return 0;
255 : }
256 : int
257 0 : trn_cell_introduce1_add_encrypted(trn_cell_introduce1_t *inp, uint8_t elt)
258 : {
259 0 : TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->encrypted, elt, {});
260 0 : return 0;
261 0 : trunnel_alloc_failed:
262 0 : TRUNNEL_SET_ERROR_CODE(inp);
263 0 : return -1;
264 : }
265 :
266 : uint8_t *
267 14 : trn_cell_introduce1_getarray_encrypted(trn_cell_introduce1_t *inp)
268 : {
269 14 : return inp->encrypted.elts_;
270 : }
271 : const uint8_t *
272 8 : trn_cell_introduce1_getconstarray_encrypted(const trn_cell_introduce1_t *inp)
273 : {
274 8 : return (const uint8_t *)trn_cell_introduce1_getarray_encrypted((trn_cell_introduce1_t*)inp);
275 : }
276 : int
277 8 : trn_cell_introduce1_setlen_encrypted(trn_cell_introduce1_t *inp, size_t newlen)
278 : {
279 8 : uint8_t *newptr;
280 16 : newptr = trunnel_dynarray_setlen(&inp->encrypted.allocated_,
281 8 : &inp->encrypted.n_, inp->encrypted.elts_, newlen,
282 : sizeof(inp->encrypted.elts_[0]), (trunnel_free_fn_t) NULL,
283 : &inp->trunnel_error_code_);
284 8 : if (newlen != 0 && newptr == NULL)
285 0 : goto trunnel_alloc_failed;
286 8 : inp->encrypted.elts_ = newptr;
287 8 : return 0;
288 0 : trunnel_alloc_failed:
289 0 : TRUNNEL_SET_ERROR_CODE(inp);
290 0 : return -1;
291 : }
292 : const char *
293 14 : trn_cell_introduce1_check(const trn_cell_introduce1_t *obj)
294 : {
295 14 : if (obj == NULL)
296 : return "Object was NULL";
297 14 : if (obj->trunnel_error_code_)
298 : return "A set function failed on this object";
299 14 : if (! (obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1))
300 : return "Integer out of bounds";
301 14 : if (TRUNNEL_DYNARRAY_LEN(&obj->auth_key) != obj->auth_key_len)
302 : return "Length mismatch for auth_key";
303 : {
304 14 : const char *msg;
305 14 : if (NULL != (msg = trn_cell_extension_check(obj->extensions)))
306 0 : return msg;
307 : }
308 : return NULL;
309 : }
310 :
311 : ssize_t
312 5 : trn_cell_introduce1_encoded_len(const trn_cell_introduce1_t *obj)
313 : {
314 5 : ssize_t result = 0;
315 :
316 5 : if (NULL != trn_cell_introduce1_check(obj))
317 : return -1;
318 :
319 :
320 : /* Length of u8 legacy_key_id[TRUNNEL_SHA1_LEN] */
321 5 : result += TRUNNEL_SHA1_LEN;
322 :
323 : /* Length of u8 auth_key_type IN [TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1] */
324 5 : result += 1;
325 :
326 : /* Length of u16 auth_key_len */
327 5 : result += 2;
328 :
329 : /* Length of u8 auth_key[auth_key_len] */
330 5 : result += TRUNNEL_DYNARRAY_LEN(&obj->auth_key);
331 :
332 : /* Length of struct trn_cell_extension extensions */
333 5 : result += trn_cell_extension_encoded_len(obj->extensions);
334 :
335 : /* Length of u8 encrypted[] */
336 5 : result += TRUNNEL_DYNARRAY_LEN(&obj->encrypted);
337 5 : return result;
338 : }
339 : int
340 0 : trn_cell_introduce1_clear_errors(trn_cell_introduce1_t *obj)
341 : {
342 0 : int r = obj->trunnel_error_code_;
343 0 : obj->trunnel_error_code_ = 0;
344 0 : return r;
345 : }
346 : ssize_t
347 9 : trn_cell_introduce1_encode(uint8_t *output, const size_t avail, const trn_cell_introduce1_t *obj)
348 : {
349 9 : ssize_t result = 0;
350 9 : size_t written = 0;
351 9 : uint8_t *ptr = output;
352 9 : const char *msg;
353 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
354 : const ssize_t encoded_len = trn_cell_introduce1_encoded_len(obj);
355 : #endif
356 :
357 9 : if (NULL != (msg = trn_cell_introduce1_check(obj)))
358 0 : goto check_failed;
359 :
360 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
361 : trunnel_assert(encoded_len >= 0);
362 : #endif
363 :
364 : /* Encode u8 legacy_key_id[TRUNNEL_SHA1_LEN] */
365 9 : trunnel_assert(written <= avail);
366 9 : if (avail - written < TRUNNEL_SHA1_LEN)
367 0 : goto truncated;
368 9 : memcpy(ptr, obj->legacy_key_id, TRUNNEL_SHA1_LEN);
369 9 : written += TRUNNEL_SHA1_LEN; ptr += TRUNNEL_SHA1_LEN;
370 :
371 : /* Encode u8 auth_key_type IN [TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1] */
372 9 : trunnel_assert(written <= avail);
373 9 : if (avail - written < 1)
374 0 : goto truncated;
375 9 : trunnel_set_uint8(ptr, (obj->auth_key_type));
376 9 : written += 1; ptr += 1;
377 :
378 : /* Encode u16 auth_key_len */
379 9 : trunnel_assert(written <= avail);
380 9 : if (avail - written < 2)
381 0 : goto truncated;
382 9 : trunnel_set_uint16(ptr, trunnel_htons(obj->auth_key_len));
383 9 : written += 2; ptr += 2;
384 :
385 : /* Encode u8 auth_key[auth_key_len] */
386 : {
387 9 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->auth_key);
388 9 : trunnel_assert(obj->auth_key_len == elt_len);
389 9 : trunnel_assert(written <= avail);
390 9 : if (avail - written < elt_len)
391 0 : goto truncated;
392 9 : if (elt_len)
393 9 : memcpy(ptr, obj->auth_key.elts_, elt_len);
394 9 : written += elt_len; ptr += elt_len;
395 : }
396 :
397 : /* Encode struct trn_cell_extension extensions */
398 9 : trunnel_assert(written <= avail);
399 9 : result = trn_cell_extension_encode(ptr, avail - written, obj->extensions);
400 9 : if (result < 0)
401 0 : goto fail; /* XXXXXXX !*/
402 9 : written += result; ptr += result;
403 :
404 : /* Encode u8 encrypted[] */
405 : {
406 9 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->encrypted);
407 9 : trunnel_assert(written <= avail);
408 9 : if (avail - written < elt_len)
409 0 : goto truncated;
410 9 : if (elt_len)
411 5 : memcpy(ptr, obj->encrypted.elts_, elt_len);
412 9 : written += elt_len; ptr += elt_len;
413 : }
414 :
415 :
416 9 : trunnel_assert(ptr == output + written);
417 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
418 : {
419 : trunnel_assert(encoded_len >= 0);
420 : trunnel_assert((size_t)encoded_len == written);
421 : }
422 :
423 : #endif
424 :
425 9 : return written;
426 :
427 0 : truncated:
428 0 : result = -2;
429 0 : goto fail;
430 0 : check_failed:
431 0 : (void)msg;
432 0 : result = -1;
433 0 : goto fail;
434 0 : fail:
435 0 : trunnel_assert(result < 0);
436 : return result;
437 : }
438 :
439 : /** As trn_cell_introduce1_parse(), but do not allocate the output
440 : * object.
441 : */
442 : static ssize_t
443 10 : trn_cell_introduce1_parse_into(trn_cell_introduce1_t *obj, const uint8_t *input, const size_t len_in)
444 : {
445 10 : const uint8_t *ptr = input;
446 10 : size_t remaining = len_in;
447 10 : ssize_t result = 0;
448 10 : (void)result;
449 :
450 : /* Parse u8 legacy_key_id[TRUNNEL_SHA1_LEN] */
451 10 : CHECK_REMAINING(TRUNNEL_SHA1_LEN, truncated);
452 9 : memcpy(obj->legacy_key_id, ptr, TRUNNEL_SHA1_LEN);
453 9 : remaining -= TRUNNEL_SHA1_LEN; ptr += TRUNNEL_SHA1_LEN;
454 :
455 : /* Parse u8 auth_key_type IN [TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0, TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1] */
456 9 : CHECK_REMAINING(1, truncated);
457 9 : obj->auth_key_type = (trunnel_get_uint8(ptr));
458 9 : remaining -= 1; ptr += 1;
459 9 : if (! (obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY0 || obj->auth_key_type == TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1))
460 0 : goto fail;
461 :
462 : /* Parse u16 auth_key_len */
463 9 : CHECK_REMAINING(2, truncated);
464 9 : obj->auth_key_len = trunnel_ntohs(trunnel_get_uint16(ptr));
465 9 : remaining -= 2; ptr += 2;
466 :
467 : /* Parse u8 auth_key[auth_key_len] */
468 9 : CHECK_REMAINING(obj->auth_key_len, truncated);
469 9 : TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->auth_key, obj->auth_key_len, {});
470 9 : obj->auth_key.n_ = obj->auth_key_len;
471 9 : if (obj->auth_key_len)
472 8 : memcpy(obj->auth_key.elts_, ptr, obj->auth_key_len);
473 9 : ptr += obj->auth_key_len; remaining -= obj->auth_key_len;
474 :
475 : /* Parse struct trn_cell_extension extensions */
476 9 : result = trn_cell_extension_parse(&obj->extensions, ptr, remaining);
477 9 : if (result < 0)
478 0 : goto relay_fail;
479 9 : trunnel_assert((size_t)result <= remaining);
480 9 : remaining -= result; ptr += result;
481 :
482 : /* Parse u8 encrypted[] */
483 9 : TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->encrypted, remaining, {});
484 9 : obj->encrypted.n_ = remaining;
485 9 : if (remaining)
486 9 : memcpy(obj->encrypted.elts_, ptr, remaining);
487 9 : ptr += remaining; remaining -= remaining;
488 9 : trunnel_assert(ptr + remaining == input + len_in);
489 9 : return len_in - remaining;
490 :
491 : truncated:
492 : return -2;
493 0 : relay_fail:
494 0 : trunnel_assert(result < 0);
495 : return result;
496 : trunnel_alloc_failed:
497 : return -1;
498 0 : fail:
499 0 : result = -1;
500 0 : return result;
501 : }
502 :
503 : ssize_t
504 10 : trn_cell_introduce1_parse(trn_cell_introduce1_t **output, const uint8_t *input, const size_t len_in)
505 : {
506 10 : ssize_t result;
507 10 : *output = trn_cell_introduce1_new();
508 10 : if (NULL == *output)
509 : return -1;
510 10 : result = trn_cell_introduce1_parse_into(*output, input, len_in);
511 10 : if (result < 0) {
512 1 : trn_cell_introduce1_free(*output);
513 1 : *output = NULL;
514 : }
515 : return result;
516 : }
517 : trn_cell_introduce_ack_t *
518 2 : trn_cell_introduce_ack_new(void)
519 : {
520 2 : trn_cell_introduce_ack_t *val = trunnel_calloc(1, sizeof(trn_cell_introduce_ack_t));
521 2 : if (NULL == val)
522 0 : return NULL;
523 : return val;
524 : }
525 :
526 : /** Release all storage held inside 'obj', but do not free 'obj'.
527 : */
528 : static void
529 2 : trn_cell_introduce_ack_clear(trn_cell_introduce_ack_t *obj)
530 : {
531 2 : (void) obj;
532 2 : trn_cell_extension_free(obj->extensions);
533 2 : obj->extensions = NULL;
534 2 : }
535 :
536 : void
537 2 : trn_cell_introduce_ack_free(trn_cell_introduce_ack_t *obj)
538 : {
539 2 : if (obj == NULL)
540 : return;
541 2 : trn_cell_introduce_ack_clear(obj);
542 2 : trunnel_memwipe(obj, sizeof(trn_cell_introduce_ack_t));
543 2 : trunnel_free_(obj);
544 : }
545 :
546 : uint16_t
547 0 : trn_cell_introduce_ack_get_status(const trn_cell_introduce_ack_t *inp)
548 : {
549 0 : return inp->status;
550 : }
551 : int
552 2 : trn_cell_introduce_ack_set_status(trn_cell_introduce_ack_t *inp, uint16_t val)
553 : {
554 2 : inp->status = val;
555 2 : return 0;
556 : }
557 : struct trn_cell_extension_st *
558 0 : trn_cell_introduce_ack_get_extensions(trn_cell_introduce_ack_t *inp)
559 : {
560 0 : return inp->extensions;
561 : }
562 : const struct trn_cell_extension_st *
563 0 : trn_cell_introduce_ack_getconst_extensions(const trn_cell_introduce_ack_t *inp)
564 : {
565 0 : return trn_cell_introduce_ack_get_extensions((trn_cell_introduce_ack_t*) inp);
566 : }
567 : int
568 2 : trn_cell_introduce_ack_set_extensions(trn_cell_introduce_ack_t *inp, struct trn_cell_extension_st *val)
569 : {
570 2 : if (inp->extensions && inp->extensions != val)
571 0 : trn_cell_extension_free(inp->extensions);
572 2 : return trn_cell_introduce_ack_set0_extensions(inp, val);
573 : }
574 : int
575 2 : trn_cell_introduce_ack_set0_extensions(trn_cell_introduce_ack_t *inp, struct trn_cell_extension_st *val)
576 : {
577 2 : inp->extensions = val;
578 2 : return 0;
579 : }
580 : const char *
581 4 : trn_cell_introduce_ack_check(const trn_cell_introduce_ack_t *obj)
582 : {
583 4 : if (obj == NULL)
584 : return "Object was NULL";
585 4 : if (obj->trunnel_error_code_)
586 : return "A set function failed on this object";
587 : {
588 4 : const char *msg;
589 4 : if (NULL != (msg = trn_cell_extension_check(obj->extensions)))
590 0 : return msg;
591 : }
592 : return NULL;
593 : }
594 :
595 : ssize_t
596 2 : trn_cell_introduce_ack_encoded_len(const trn_cell_introduce_ack_t *obj)
597 : {
598 2 : ssize_t result = 0;
599 :
600 2 : if (NULL != trn_cell_introduce_ack_check(obj))
601 : return -1;
602 :
603 :
604 : /* Length of u16 status */
605 2 : result += 2;
606 :
607 : /* Length of struct trn_cell_extension extensions */
608 2 : result += trn_cell_extension_encoded_len(obj->extensions);
609 2 : return result;
610 : }
611 : int
612 0 : trn_cell_introduce_ack_clear_errors(trn_cell_introduce_ack_t *obj)
613 : {
614 0 : int r = obj->trunnel_error_code_;
615 0 : obj->trunnel_error_code_ = 0;
616 0 : return r;
617 : }
618 : ssize_t
619 2 : trn_cell_introduce_ack_encode(uint8_t *output, const size_t avail, const trn_cell_introduce_ack_t *obj)
620 : {
621 2 : ssize_t result = 0;
622 2 : size_t written = 0;
623 2 : uint8_t *ptr = output;
624 2 : const char *msg;
625 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
626 : const ssize_t encoded_len = trn_cell_introduce_ack_encoded_len(obj);
627 : #endif
628 :
629 2 : if (NULL != (msg = trn_cell_introduce_ack_check(obj)))
630 0 : goto check_failed;
631 :
632 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
633 : trunnel_assert(encoded_len >= 0);
634 : #endif
635 :
636 : /* Encode u16 status */
637 2 : trunnel_assert(written <= avail);
638 2 : if (avail - written < 2)
639 0 : goto truncated;
640 2 : trunnel_set_uint16(ptr, trunnel_htons(obj->status));
641 2 : written += 2; ptr += 2;
642 :
643 : /* Encode struct trn_cell_extension extensions */
644 2 : trunnel_assert(written <= avail);
645 2 : result = trn_cell_extension_encode(ptr, avail - written, obj->extensions);
646 2 : if (result < 0)
647 0 : goto fail; /* XXXXXXX !*/
648 2 : written += result; ptr += result;
649 :
650 :
651 2 : trunnel_assert(ptr == output + written);
652 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
653 : {
654 : trunnel_assert(encoded_len >= 0);
655 : trunnel_assert((size_t)encoded_len == written);
656 : }
657 :
658 : #endif
659 :
660 2 : return written;
661 :
662 0 : truncated:
663 0 : result = -2;
664 0 : goto fail;
665 0 : check_failed:
666 0 : (void)msg;
667 0 : result = -1;
668 0 : goto fail;
669 0 : fail:
670 0 : trunnel_assert(result < 0);
671 : return result;
672 : }
673 :
674 : /** As trn_cell_introduce_ack_parse(), but do not allocate the output
675 : * object.
676 : */
677 : static ssize_t
678 0 : trn_cell_introduce_ack_parse_into(trn_cell_introduce_ack_t *obj, const uint8_t *input, const size_t len_in)
679 : {
680 0 : const uint8_t *ptr = input;
681 0 : size_t remaining = len_in;
682 0 : ssize_t result = 0;
683 0 : (void)result;
684 :
685 : /* Parse u16 status */
686 0 : CHECK_REMAINING(2, truncated);
687 0 : obj->status = trunnel_ntohs(trunnel_get_uint16(ptr));
688 0 : remaining -= 2; ptr += 2;
689 :
690 : /* Parse struct trn_cell_extension extensions */
691 0 : result = trn_cell_extension_parse(&obj->extensions, ptr, remaining);
692 0 : if (result < 0)
693 0 : goto relay_fail;
694 0 : trunnel_assert((size_t)result <= remaining);
695 0 : remaining -= result; ptr += result;
696 0 : trunnel_assert(ptr + remaining == input + len_in);
697 0 : return len_in - remaining;
698 :
699 0 : truncated:
700 0 : return -2;
701 0 : relay_fail:
702 0 : trunnel_assert(result < 0);
703 : return result;
704 : }
705 :
706 : ssize_t
707 0 : trn_cell_introduce_ack_parse(trn_cell_introduce_ack_t **output, const uint8_t *input, const size_t len_in)
708 : {
709 0 : ssize_t result;
710 0 : *output = trn_cell_introduce_ack_new();
711 0 : if (NULL == *output)
712 : return -1;
713 0 : result = trn_cell_introduce_ack_parse_into(*output, input, len_in);
714 0 : if (result < 0) {
715 0 : trn_cell_introduce_ack_free(*output);
716 0 : *output = NULL;
717 : }
718 : return result;
719 : }
720 : trn_cell_introduce_encrypted_t *
721 9 : trn_cell_introduce_encrypted_new(void)
722 : {
723 9 : trn_cell_introduce_encrypted_t *val = trunnel_calloc(1, sizeof(trn_cell_introduce_encrypted_t));
724 9 : if (NULL == val)
725 : return NULL;
726 9 : val->onion_key_type = TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR;
727 9 : return val;
728 : }
729 :
730 : /** Release all storage held inside 'obj', but do not free 'obj'.
731 : */
732 : static void
733 9 : trn_cell_introduce_encrypted_clear(trn_cell_introduce_encrypted_t *obj)
734 : {
735 9 : (void) obj;
736 9 : trn_cell_extension_free(obj->extensions);
737 9 : obj->extensions = NULL;
738 9 : TRUNNEL_DYNARRAY_WIPE(&obj->onion_key);
739 9 : TRUNNEL_DYNARRAY_CLEAR(&obj->onion_key);
740 : {
741 :
742 9 : unsigned idx;
743 18 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->nspecs); ++idx) {
744 9 : link_specifier_free(TRUNNEL_DYNARRAY_GET(&obj->nspecs, idx));
745 : }
746 : }
747 9 : TRUNNEL_DYNARRAY_WIPE(&obj->nspecs);
748 9 : TRUNNEL_DYNARRAY_CLEAR(&obj->nspecs);
749 9 : TRUNNEL_DYNARRAY_WIPE(&obj->pad);
750 9 : TRUNNEL_DYNARRAY_CLEAR(&obj->pad);
751 9 : }
752 :
753 : void
754 12 : trn_cell_introduce_encrypted_free(trn_cell_introduce_encrypted_t *obj)
755 : {
756 12 : if (obj == NULL)
757 : return;
758 9 : trn_cell_introduce_encrypted_clear(obj);
759 9 : trunnel_memwipe(obj, sizeof(trn_cell_introduce_encrypted_t));
760 9 : trunnel_free_(obj);
761 : }
762 :
763 : size_t
764 0 : trn_cell_introduce_encrypted_getlen_rend_cookie(const trn_cell_introduce_encrypted_t *inp)
765 : {
766 0 : (void)inp; return TRUNNEL_REND_COOKIE_LEN;
767 : }
768 :
769 : uint8_t
770 0 : trn_cell_introduce_encrypted_get_rend_cookie(trn_cell_introduce_encrypted_t *inp, size_t idx)
771 : {
772 0 : trunnel_assert(idx < TRUNNEL_REND_COOKIE_LEN);
773 0 : return inp->rend_cookie[idx];
774 : }
775 :
776 : uint8_t
777 0 : trn_cell_introduce_encrypted_getconst_rend_cookie(const trn_cell_introduce_encrypted_t *inp, size_t idx)
778 : {
779 0 : return trn_cell_introduce_encrypted_get_rend_cookie((trn_cell_introduce_encrypted_t*)inp, idx);
780 : }
781 : int
782 0 : trn_cell_introduce_encrypted_set_rend_cookie(trn_cell_introduce_encrypted_t *inp, size_t idx, uint8_t elt)
783 : {
784 0 : trunnel_assert(idx < TRUNNEL_REND_COOKIE_LEN);
785 0 : inp->rend_cookie[idx] = elt;
786 0 : return 0;
787 : }
788 :
789 : uint8_t *
790 9 : trn_cell_introduce_encrypted_getarray_rend_cookie(trn_cell_introduce_encrypted_t *inp)
791 : {
792 9 : return inp->rend_cookie;
793 : }
794 : const uint8_t *
795 5 : trn_cell_introduce_encrypted_getconstarray_rend_cookie(const trn_cell_introduce_encrypted_t *inp)
796 : {
797 5 : return (const uint8_t *)trn_cell_introduce_encrypted_getarray_rend_cookie((trn_cell_introduce_encrypted_t*)inp);
798 : }
799 : struct trn_cell_extension_st *
800 0 : trn_cell_introduce_encrypted_get_extensions(trn_cell_introduce_encrypted_t *inp)
801 : {
802 0 : return inp->extensions;
803 : }
804 : const struct trn_cell_extension_st *
805 0 : trn_cell_introduce_encrypted_getconst_extensions(const trn_cell_introduce_encrypted_t *inp)
806 : {
807 0 : return trn_cell_introduce_encrypted_get_extensions((trn_cell_introduce_encrypted_t*) inp);
808 : }
809 : int
810 4 : trn_cell_introduce_encrypted_set_extensions(trn_cell_introduce_encrypted_t *inp, struct trn_cell_extension_st *val)
811 : {
812 4 : if (inp->extensions && inp->extensions != val)
813 0 : trn_cell_extension_free(inp->extensions);
814 4 : return trn_cell_introduce_encrypted_set0_extensions(inp, val);
815 : }
816 : int
817 4 : trn_cell_introduce_encrypted_set0_extensions(trn_cell_introduce_encrypted_t *inp, struct trn_cell_extension_st *val)
818 : {
819 4 : inp->extensions = val;
820 4 : return 0;
821 : }
822 : uint8_t
823 5 : trn_cell_introduce_encrypted_get_onion_key_type(const trn_cell_introduce_encrypted_t *inp)
824 : {
825 5 : return inp->onion_key_type;
826 : }
827 : int
828 4 : trn_cell_introduce_encrypted_set_onion_key_type(trn_cell_introduce_encrypted_t *inp, uint8_t val)
829 : {
830 4 : if (! ((val == TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR))) {
831 0 : TRUNNEL_SET_ERROR_CODE(inp);
832 0 : return -1;
833 : }
834 4 : inp->onion_key_type = val;
835 4 : return 0;
836 : }
837 : uint16_t
838 0 : trn_cell_introduce_encrypted_get_onion_key_len(const trn_cell_introduce_encrypted_t *inp)
839 : {
840 0 : return inp->onion_key_len;
841 : }
842 : int
843 4 : trn_cell_introduce_encrypted_set_onion_key_len(trn_cell_introduce_encrypted_t *inp, uint16_t val)
844 : {
845 4 : inp->onion_key_len = val;
846 4 : return 0;
847 : }
848 : size_t
849 9 : trn_cell_introduce_encrypted_getlen_onion_key(const trn_cell_introduce_encrypted_t *inp)
850 : {
851 9 : return TRUNNEL_DYNARRAY_LEN(&inp->onion_key);
852 : }
853 :
854 : uint8_t
855 0 : trn_cell_introduce_encrypted_get_onion_key(trn_cell_introduce_encrypted_t *inp, size_t idx)
856 : {
857 0 : return TRUNNEL_DYNARRAY_GET(&inp->onion_key, idx);
858 : }
859 :
860 : uint8_t
861 0 : trn_cell_introduce_encrypted_getconst_onion_key(const trn_cell_introduce_encrypted_t *inp, size_t idx)
862 : {
863 0 : return trn_cell_introduce_encrypted_get_onion_key((trn_cell_introduce_encrypted_t*)inp, idx);
864 : }
865 : int
866 0 : trn_cell_introduce_encrypted_set_onion_key(trn_cell_introduce_encrypted_t *inp, size_t idx, uint8_t elt)
867 : {
868 0 : TRUNNEL_DYNARRAY_SET(&inp->onion_key, idx, elt);
869 0 : return 0;
870 : }
871 : int
872 0 : trn_cell_introduce_encrypted_add_onion_key(trn_cell_introduce_encrypted_t *inp, uint8_t elt)
873 : {
874 : #if SIZE_MAX >= UINT16_MAX
875 0 : if (inp->onion_key.n_ == UINT16_MAX)
876 0 : goto trunnel_alloc_failed;
877 : #endif
878 0 : TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->onion_key, elt, {});
879 0 : return 0;
880 0 : trunnel_alloc_failed:
881 0 : TRUNNEL_SET_ERROR_CODE(inp);
882 0 : return -1;
883 : }
884 :
885 : uint8_t *
886 9 : trn_cell_introduce_encrypted_getarray_onion_key(trn_cell_introduce_encrypted_t *inp)
887 : {
888 9 : return inp->onion_key.elts_;
889 : }
890 : const uint8_t *
891 5 : trn_cell_introduce_encrypted_getconstarray_onion_key(const trn_cell_introduce_encrypted_t *inp)
892 : {
893 5 : return (const uint8_t *)trn_cell_introduce_encrypted_getarray_onion_key((trn_cell_introduce_encrypted_t*)inp);
894 : }
895 : int
896 4 : trn_cell_introduce_encrypted_setlen_onion_key(trn_cell_introduce_encrypted_t *inp, size_t newlen)
897 : {
898 4 : uint8_t *newptr;
899 : #if UINT16_MAX < SIZE_MAX
900 4 : if (newlen > UINT16_MAX)
901 0 : goto trunnel_alloc_failed;
902 : #endif
903 8 : newptr = trunnel_dynarray_setlen(&inp->onion_key.allocated_,
904 4 : &inp->onion_key.n_, inp->onion_key.elts_, newlen,
905 : sizeof(inp->onion_key.elts_[0]), (trunnel_free_fn_t) NULL,
906 : &inp->trunnel_error_code_);
907 4 : if (newlen != 0 && newptr == NULL)
908 0 : goto trunnel_alloc_failed;
909 4 : inp->onion_key.elts_ = newptr;
910 4 : return 0;
911 0 : trunnel_alloc_failed:
912 0 : TRUNNEL_SET_ERROR_CODE(inp);
913 0 : return -1;
914 : }
915 : uint8_t
916 10 : trn_cell_introduce_encrypted_get_nspec(const trn_cell_introduce_encrypted_t *inp)
917 : {
918 10 : return inp->nspec;
919 : }
920 : int
921 4 : trn_cell_introduce_encrypted_set_nspec(trn_cell_introduce_encrypted_t *inp, uint8_t val)
922 : {
923 4 : inp->nspec = val;
924 4 : return 0;
925 : }
926 : size_t
927 0 : trn_cell_introduce_encrypted_getlen_nspecs(const trn_cell_introduce_encrypted_t *inp)
928 : {
929 0 : return TRUNNEL_DYNARRAY_LEN(&inp->nspecs);
930 : }
931 :
932 : struct link_specifier_st *
933 5 : trn_cell_introduce_encrypted_get_nspecs(trn_cell_introduce_encrypted_t *inp, size_t idx)
934 : {
935 5 : return TRUNNEL_DYNARRAY_GET(&inp->nspecs, idx);
936 : }
937 :
938 : const struct link_specifier_st *
939 0 : trn_cell_introduce_encrypted_getconst_nspecs(const trn_cell_introduce_encrypted_t *inp, size_t idx)
940 : {
941 0 : return trn_cell_introduce_encrypted_get_nspecs((trn_cell_introduce_encrypted_t*)inp, idx);
942 : }
943 : int
944 0 : trn_cell_introduce_encrypted_set_nspecs(trn_cell_introduce_encrypted_t *inp, size_t idx, struct link_specifier_st * elt)
945 : {
946 0 : link_specifier_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->nspecs, idx);
947 0 : if (oldval && oldval != elt)
948 0 : link_specifier_free(oldval);
949 0 : return trn_cell_introduce_encrypted_set0_nspecs(inp, idx, elt);
950 : }
951 : int
952 0 : trn_cell_introduce_encrypted_set0_nspecs(trn_cell_introduce_encrypted_t *inp, size_t idx, struct link_specifier_st * elt)
953 : {
954 0 : TRUNNEL_DYNARRAY_SET(&inp->nspecs, idx, elt);
955 0 : return 0;
956 : }
957 : int
958 4 : trn_cell_introduce_encrypted_add_nspecs(trn_cell_introduce_encrypted_t *inp, struct link_specifier_st * elt)
959 : {
960 : #if SIZE_MAX >= UINT8_MAX
961 4 : if (inp->nspecs.n_ == UINT8_MAX)
962 0 : goto trunnel_alloc_failed;
963 : #endif
964 4 : TRUNNEL_DYNARRAY_ADD(struct link_specifier_st *, &inp->nspecs, elt, {});
965 4 : return 0;
966 0 : trunnel_alloc_failed:
967 0 : TRUNNEL_SET_ERROR_CODE(inp);
968 0 : return -1;
969 : }
970 :
971 : struct link_specifier_st * *
972 0 : trn_cell_introduce_encrypted_getarray_nspecs(trn_cell_introduce_encrypted_t *inp)
973 : {
974 0 : return inp->nspecs.elts_;
975 : }
976 : const struct link_specifier_st * const *
977 0 : trn_cell_introduce_encrypted_getconstarray_nspecs(const trn_cell_introduce_encrypted_t *inp)
978 : {
979 0 : return (const struct link_specifier_st * const *)trn_cell_introduce_encrypted_getarray_nspecs((trn_cell_introduce_encrypted_t*)inp);
980 : }
981 : int
982 0 : trn_cell_introduce_encrypted_setlen_nspecs(trn_cell_introduce_encrypted_t *inp, size_t newlen)
983 : {
984 0 : struct link_specifier_st * *newptr;
985 : #if UINT8_MAX < SIZE_MAX
986 0 : if (newlen > UINT8_MAX)
987 0 : goto trunnel_alloc_failed;
988 : #endif
989 0 : newptr = trunnel_dynarray_setlen(&inp->nspecs.allocated_,
990 0 : &inp->nspecs.n_, inp->nspecs.elts_, newlen,
991 : sizeof(inp->nspecs.elts_[0]), (trunnel_free_fn_t) link_specifier_free,
992 : &inp->trunnel_error_code_);
993 0 : if (newlen != 0 && newptr == NULL)
994 0 : goto trunnel_alloc_failed;
995 0 : inp->nspecs.elts_ = newptr;
996 0 : return 0;
997 0 : trunnel_alloc_failed:
998 0 : TRUNNEL_SET_ERROR_CODE(inp);
999 0 : return -1;
1000 : }
1001 : size_t
1002 4 : trn_cell_introduce_encrypted_getlen_pad(const trn_cell_introduce_encrypted_t *inp)
1003 : {
1004 4 : return TRUNNEL_DYNARRAY_LEN(&inp->pad);
1005 : }
1006 :
1007 : uint8_t
1008 0 : trn_cell_introduce_encrypted_get_pad(trn_cell_introduce_encrypted_t *inp, size_t idx)
1009 : {
1010 0 : return TRUNNEL_DYNARRAY_GET(&inp->pad, idx);
1011 : }
1012 :
1013 : uint8_t
1014 0 : trn_cell_introduce_encrypted_getconst_pad(const trn_cell_introduce_encrypted_t *inp, size_t idx)
1015 : {
1016 0 : return trn_cell_introduce_encrypted_get_pad((trn_cell_introduce_encrypted_t*)inp, idx);
1017 : }
1018 : int
1019 0 : trn_cell_introduce_encrypted_set_pad(trn_cell_introduce_encrypted_t *inp, size_t idx, uint8_t elt)
1020 : {
1021 0 : TRUNNEL_DYNARRAY_SET(&inp->pad, idx, elt);
1022 0 : return 0;
1023 : }
1024 : int
1025 0 : trn_cell_introduce_encrypted_add_pad(trn_cell_introduce_encrypted_t *inp, uint8_t elt)
1026 : {
1027 0 : TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->pad, elt, {});
1028 0 : return 0;
1029 0 : trunnel_alloc_failed:
1030 0 : TRUNNEL_SET_ERROR_CODE(inp);
1031 0 : return -1;
1032 : }
1033 :
1034 : uint8_t *
1035 4 : trn_cell_introduce_encrypted_getarray_pad(trn_cell_introduce_encrypted_t *inp)
1036 : {
1037 4 : return inp->pad.elts_;
1038 : }
1039 : const uint8_t *
1040 0 : trn_cell_introduce_encrypted_getconstarray_pad(const trn_cell_introduce_encrypted_t *inp)
1041 : {
1042 0 : return (const uint8_t *)trn_cell_introduce_encrypted_getarray_pad((trn_cell_introduce_encrypted_t*)inp);
1043 : }
1044 : int
1045 4 : trn_cell_introduce_encrypted_setlen_pad(trn_cell_introduce_encrypted_t *inp, size_t newlen)
1046 : {
1047 4 : uint8_t *newptr;
1048 8 : newptr = trunnel_dynarray_setlen(&inp->pad.allocated_,
1049 4 : &inp->pad.n_, inp->pad.elts_, newlen,
1050 : sizeof(inp->pad.elts_[0]), (trunnel_free_fn_t) NULL,
1051 : &inp->trunnel_error_code_);
1052 4 : if (newlen != 0 && newptr == NULL)
1053 0 : goto trunnel_alloc_failed;
1054 4 : inp->pad.elts_ = newptr;
1055 4 : return 0;
1056 0 : trunnel_alloc_failed:
1057 0 : TRUNNEL_SET_ERROR_CODE(inp);
1058 0 : return -1;
1059 : }
1060 : const char *
1061 8 : trn_cell_introduce_encrypted_check(const trn_cell_introduce_encrypted_t *obj)
1062 : {
1063 8 : if (obj == NULL)
1064 : return "Object was NULL";
1065 8 : if (obj->trunnel_error_code_)
1066 : return "A set function failed on this object";
1067 : {
1068 8 : const char *msg;
1069 8 : if (NULL != (msg = trn_cell_extension_check(obj->extensions)))
1070 : return msg;
1071 : }
1072 8 : if (! (obj->onion_key_type == TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR))
1073 : return "Integer out of bounds";
1074 8 : if (TRUNNEL_DYNARRAY_LEN(&obj->onion_key) != obj->onion_key_len)
1075 : return "Length mismatch for onion_key";
1076 : {
1077 : const char *msg;
1078 :
1079 : unsigned idx;
1080 16 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->nspecs); ++idx) {
1081 8 : if (NULL != (msg = link_specifier_check(TRUNNEL_DYNARRAY_GET(&obj->nspecs, idx))))
1082 0 : return msg;
1083 : }
1084 : }
1085 8 : if (TRUNNEL_DYNARRAY_LEN(&obj->nspecs) != obj->nspec)
1086 0 : return "Length mismatch for nspecs";
1087 : return NULL;
1088 : }
1089 :
1090 : ssize_t
1091 4 : trn_cell_introduce_encrypted_encoded_len(const trn_cell_introduce_encrypted_t *obj)
1092 : {
1093 4 : ssize_t result = 0;
1094 :
1095 4 : if (NULL != trn_cell_introduce_encrypted_check(obj))
1096 : return -1;
1097 :
1098 :
1099 : /* Length of u8 rend_cookie[TRUNNEL_REND_COOKIE_LEN] */
1100 4 : result += TRUNNEL_REND_COOKIE_LEN;
1101 :
1102 : /* Length of struct trn_cell_extension extensions */
1103 4 : result += trn_cell_extension_encoded_len(obj->extensions);
1104 :
1105 : /* Length of u8 onion_key_type IN [TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR] */
1106 4 : result += 1;
1107 :
1108 : /* Length of u16 onion_key_len */
1109 4 : result += 2;
1110 :
1111 : /* Length of u8 onion_key[onion_key_len] */
1112 4 : result += TRUNNEL_DYNARRAY_LEN(&obj->onion_key);
1113 :
1114 : /* Length of u8 nspec */
1115 4 : result += 1;
1116 :
1117 : /* Length of struct link_specifier nspecs[nspec] */
1118 : {
1119 :
1120 4 : unsigned idx;
1121 8 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->nspecs); ++idx) {
1122 4 : result += link_specifier_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->nspecs, idx));
1123 : }
1124 : }
1125 :
1126 : /* Length of u8 pad[] */
1127 4 : result += TRUNNEL_DYNARRAY_LEN(&obj->pad);
1128 4 : return result;
1129 : }
1130 : int
1131 0 : trn_cell_introduce_encrypted_clear_errors(trn_cell_introduce_encrypted_t *obj)
1132 : {
1133 0 : int r = obj->trunnel_error_code_;
1134 0 : obj->trunnel_error_code_ = 0;
1135 0 : return r;
1136 : }
1137 : ssize_t
1138 4 : trn_cell_introduce_encrypted_encode(uint8_t *output, const size_t avail, const trn_cell_introduce_encrypted_t *obj)
1139 : {
1140 4 : ssize_t result = 0;
1141 4 : size_t written = 0;
1142 4 : uint8_t *ptr = output;
1143 4 : const char *msg;
1144 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1145 : const ssize_t encoded_len = trn_cell_introduce_encrypted_encoded_len(obj);
1146 : #endif
1147 :
1148 4 : if (NULL != (msg = trn_cell_introduce_encrypted_check(obj)))
1149 0 : goto check_failed;
1150 :
1151 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1152 : trunnel_assert(encoded_len >= 0);
1153 : #endif
1154 :
1155 : /* Encode u8 rend_cookie[TRUNNEL_REND_COOKIE_LEN] */
1156 4 : trunnel_assert(written <= avail);
1157 4 : if (avail - written < TRUNNEL_REND_COOKIE_LEN)
1158 0 : goto truncated;
1159 4 : memcpy(ptr, obj->rend_cookie, TRUNNEL_REND_COOKIE_LEN);
1160 4 : written += TRUNNEL_REND_COOKIE_LEN; ptr += TRUNNEL_REND_COOKIE_LEN;
1161 :
1162 : /* Encode struct trn_cell_extension extensions */
1163 4 : trunnel_assert(written <= avail);
1164 4 : result = trn_cell_extension_encode(ptr, avail - written, obj->extensions);
1165 4 : if (result < 0)
1166 0 : goto fail; /* XXXXXXX !*/
1167 4 : written += result; ptr += result;
1168 :
1169 : /* Encode u8 onion_key_type IN [TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR] */
1170 4 : trunnel_assert(written <= avail);
1171 4 : if (avail - written < 1)
1172 0 : goto truncated;
1173 4 : trunnel_set_uint8(ptr, (obj->onion_key_type));
1174 4 : written += 1; ptr += 1;
1175 :
1176 : /* Encode u16 onion_key_len */
1177 4 : trunnel_assert(written <= avail);
1178 4 : if (avail - written < 2)
1179 0 : goto truncated;
1180 4 : trunnel_set_uint16(ptr, trunnel_htons(obj->onion_key_len));
1181 4 : written += 2; ptr += 2;
1182 :
1183 : /* Encode u8 onion_key[onion_key_len] */
1184 : {
1185 4 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->onion_key);
1186 4 : trunnel_assert(obj->onion_key_len == elt_len);
1187 4 : trunnel_assert(written <= avail);
1188 4 : if (avail - written < elt_len)
1189 0 : goto truncated;
1190 4 : if (elt_len)
1191 4 : memcpy(ptr, obj->onion_key.elts_, elt_len);
1192 4 : written += elt_len; ptr += elt_len;
1193 : }
1194 :
1195 : /* Encode u8 nspec */
1196 4 : trunnel_assert(written <= avail);
1197 4 : if (avail - written < 1)
1198 0 : goto truncated;
1199 4 : trunnel_set_uint8(ptr, (obj->nspec));
1200 4 : written += 1; ptr += 1;
1201 :
1202 : /* Encode struct link_specifier nspecs[nspec] */
1203 : {
1204 :
1205 4 : unsigned idx;
1206 8 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->nspecs); ++idx) {
1207 4 : trunnel_assert(written <= avail);
1208 4 : result = link_specifier_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->nspecs, idx));
1209 4 : if (result < 0)
1210 0 : goto fail; /* XXXXXXX !*/
1211 4 : written += result; ptr += result;
1212 : }
1213 : }
1214 :
1215 : /* Encode u8 pad[] */
1216 : {
1217 4 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->pad);
1218 4 : trunnel_assert(written <= avail);
1219 4 : if (avail - written < elt_len)
1220 0 : goto truncated;
1221 4 : if (elt_len)
1222 4 : memcpy(ptr, obj->pad.elts_, elt_len);
1223 4 : written += elt_len; ptr += elt_len;
1224 : }
1225 :
1226 :
1227 4 : trunnel_assert(ptr == output + written);
1228 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
1229 : {
1230 : trunnel_assert(encoded_len >= 0);
1231 : trunnel_assert((size_t)encoded_len == written);
1232 : }
1233 :
1234 : #endif
1235 :
1236 4 : return written;
1237 :
1238 0 : truncated:
1239 0 : result = -2;
1240 0 : goto fail;
1241 0 : check_failed:
1242 0 : (void)msg;
1243 0 : result = -1;
1244 0 : goto fail;
1245 : fail:
1246 0 : trunnel_assert(result < 0);
1247 : return result;
1248 : }
1249 :
1250 : /** As trn_cell_introduce_encrypted_parse(), but do not allocate the
1251 : * output object.
1252 : */
1253 : static ssize_t
1254 5 : trn_cell_introduce_encrypted_parse_into(trn_cell_introduce_encrypted_t *obj, const uint8_t *input, const size_t len_in)
1255 : {
1256 5 : const uint8_t *ptr = input;
1257 5 : size_t remaining = len_in;
1258 5 : ssize_t result = 0;
1259 5 : (void)result;
1260 :
1261 : /* Parse u8 rend_cookie[TRUNNEL_REND_COOKIE_LEN] */
1262 5 : CHECK_REMAINING(TRUNNEL_REND_COOKIE_LEN, truncated);
1263 5 : memcpy(obj->rend_cookie, ptr, TRUNNEL_REND_COOKIE_LEN);
1264 5 : remaining -= TRUNNEL_REND_COOKIE_LEN; ptr += TRUNNEL_REND_COOKIE_LEN;
1265 :
1266 : /* Parse struct trn_cell_extension extensions */
1267 5 : result = trn_cell_extension_parse(&obj->extensions, ptr, remaining);
1268 5 : if (result < 0)
1269 0 : goto relay_fail;
1270 5 : trunnel_assert((size_t)result <= remaining);
1271 5 : remaining -= result; ptr += result;
1272 :
1273 : /* Parse u8 onion_key_type IN [TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR] */
1274 5 : CHECK_REMAINING(1, truncated);
1275 5 : obj->onion_key_type = (trunnel_get_uint8(ptr));
1276 5 : remaining -= 1; ptr += 1;
1277 5 : if (! (obj->onion_key_type == TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR))
1278 0 : goto fail;
1279 :
1280 : /* Parse u16 onion_key_len */
1281 5 : CHECK_REMAINING(2, truncated);
1282 5 : obj->onion_key_len = trunnel_ntohs(trunnel_get_uint16(ptr));
1283 5 : remaining -= 2; ptr += 2;
1284 :
1285 : /* Parse u8 onion_key[onion_key_len] */
1286 5 : CHECK_REMAINING(obj->onion_key_len, truncated);
1287 5 : TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->onion_key, obj->onion_key_len, {});
1288 5 : obj->onion_key.n_ = obj->onion_key_len;
1289 5 : if (obj->onion_key_len)
1290 5 : memcpy(obj->onion_key.elts_, ptr, obj->onion_key_len);
1291 5 : ptr += obj->onion_key_len; remaining -= obj->onion_key_len;
1292 :
1293 : /* Parse u8 nspec */
1294 5 : CHECK_REMAINING(1, truncated);
1295 5 : obj->nspec = (trunnel_get_uint8(ptr));
1296 5 : remaining -= 1; ptr += 1;
1297 :
1298 : /* Parse struct link_specifier nspecs[nspec] */
1299 5 : TRUNNEL_DYNARRAY_EXPAND(link_specifier_t *, &obj->nspecs, obj->nspec, {});
1300 : {
1301 5 : link_specifier_t * elt;
1302 5 : unsigned idx;
1303 10 : for (idx = 0; idx < obj->nspec; ++idx) {
1304 5 : result = link_specifier_parse(&elt, ptr, remaining);
1305 5 : if (result < 0)
1306 0 : goto relay_fail;
1307 5 : trunnel_assert((size_t)result <= remaining);
1308 5 : remaining -= result; ptr += result;
1309 5 : TRUNNEL_DYNARRAY_ADD(link_specifier_t *, &obj->nspecs, elt, {link_specifier_free(elt);});
1310 : }
1311 : }
1312 :
1313 : /* Parse u8 pad[] */
1314 5 : TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->pad, remaining, {});
1315 5 : obj->pad.n_ = remaining;
1316 5 : if (remaining)
1317 5 : memcpy(obj->pad.elts_, ptr, remaining);
1318 5 : ptr += remaining; remaining -= remaining;
1319 5 : trunnel_assert(ptr + remaining == input + len_in);
1320 5 : return len_in - remaining;
1321 :
1322 : truncated:
1323 : return -2;
1324 : relay_fail:
1325 : trunnel_assert(result < 0);
1326 : return result;
1327 : trunnel_alloc_failed:
1328 : return -1;
1329 0 : fail:
1330 0 : result = -1;
1331 0 : return result;
1332 : }
1333 :
1334 : ssize_t
1335 5 : trn_cell_introduce_encrypted_parse(trn_cell_introduce_encrypted_t **output, const uint8_t *input, const size_t len_in)
1336 : {
1337 5 : ssize_t result;
1338 5 : *output = trn_cell_introduce_encrypted_new();
1339 5 : if (NULL == *output)
1340 : return -1;
1341 5 : result = trn_cell_introduce_encrypted_parse_into(*output, input, len_in);
1342 5 : if (result < 0) {
1343 0 : trn_cell_introduce_encrypted_free(*output);
1344 0 : *output = NULL;
1345 : }
1346 : return result;
1347 : }
|