Merge branch 'fix-changelogs' into 'main'
[tor.git] / src / trunnel / pwbox.c
blobc159a5e6871e373c49c5aa05dd22e4d0201a1390
1 /* pwbox.c -- generated by Trunnel v1.5.3.
2 * https://gitweb.torproject.org/trunnel.git
3 * You probably shouldn't edit this file.
4 */
5 #include <stdlib.h>
6 #include "trunnel-impl.h"
8 #include "pwbox.h"
10 #define TRUNNEL_SET_ERROR_CODE(obj) \
11 do { \
12 (obj)->trunnel_error_code_ = 1; \
13 } while (0)
15 #if defined(__COVERITY__) || defined(__clang_analyzer__)
16 /* If we're running a static analysis tool, we don't want it to complain
17 * that some of our remaining-bytes checks are dead-code. */
18 int pwbox_deadcode_dummy__ = 0;
19 #define OR_DEADCODE_DUMMY || pwbox_deadcode_dummy__
20 #else
21 #define OR_DEADCODE_DUMMY
22 #endif
24 #define CHECK_REMAINING(nbytes, label) \
25 do { \
26 if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
27 goto label; \
28 } \
29 } while (0)
31 pwbox_encoded_t *
32 pwbox_encoded_new(void)
34 pwbox_encoded_t *val = trunnel_calloc(1, sizeof(pwbox_encoded_t));
35 if (NULL == val)
36 return NULL;
37 val->fixedbytes0 = PWBOX0_CONST0;
38 val->fixedbytes1 = PWBOX0_CONST1;
39 return val;
42 /** Release all storage held inside 'obj', but do not free 'obj'.
44 static void
45 pwbox_encoded_clear(pwbox_encoded_t *obj)
47 (void) obj;
48 TRUNNEL_DYNARRAY_WIPE(&obj->skey_header);
49 TRUNNEL_DYNARRAY_CLEAR(&obj->skey_header);
50 TRUNNEL_DYNARRAY_WIPE(&obj->data);
51 TRUNNEL_DYNARRAY_CLEAR(&obj->data);
54 void
55 pwbox_encoded_free(pwbox_encoded_t *obj)
57 if (obj == NULL)
58 return;
59 pwbox_encoded_clear(obj);
60 trunnel_memwipe(obj, sizeof(pwbox_encoded_t));
61 trunnel_free_(obj);
64 uint32_t
65 pwbox_encoded_get_fixedbytes0(const pwbox_encoded_t *inp)
67 return inp->fixedbytes0;
69 int
70 pwbox_encoded_set_fixedbytes0(pwbox_encoded_t *inp, uint32_t val)
72 if (! ((val == PWBOX0_CONST0))) {
73 TRUNNEL_SET_ERROR_CODE(inp);
74 return -1;
76 inp->fixedbytes0 = val;
77 return 0;
79 uint32_t
80 pwbox_encoded_get_fixedbytes1(const pwbox_encoded_t *inp)
82 return inp->fixedbytes1;
84 int
85 pwbox_encoded_set_fixedbytes1(pwbox_encoded_t *inp, uint32_t val)
87 if (! ((val == PWBOX0_CONST1))) {
88 TRUNNEL_SET_ERROR_CODE(inp);
89 return -1;
91 inp->fixedbytes1 = val;
92 return 0;
94 uint8_t
95 pwbox_encoded_get_header_len(const pwbox_encoded_t *inp)
97 return inp->header_len;
99 int
100 pwbox_encoded_set_header_len(pwbox_encoded_t *inp, uint8_t val)
102 inp->header_len = val;
103 return 0;
105 size_t
106 pwbox_encoded_getlen_skey_header(const pwbox_encoded_t *inp)
108 return TRUNNEL_DYNARRAY_LEN(&inp->skey_header);
111 uint8_t
112 pwbox_encoded_get_skey_header(pwbox_encoded_t *inp, size_t idx)
114 return TRUNNEL_DYNARRAY_GET(&inp->skey_header, idx);
117 uint8_t
118 pwbox_encoded_getconst_skey_header(const pwbox_encoded_t *inp, size_t idx)
120 return pwbox_encoded_get_skey_header((pwbox_encoded_t*)inp, idx);
123 pwbox_encoded_set_skey_header(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
125 TRUNNEL_DYNARRAY_SET(&inp->skey_header, idx, elt);
126 return 0;
129 pwbox_encoded_add_skey_header(pwbox_encoded_t *inp, uint8_t elt)
131 #if SIZE_MAX >= UINT8_MAX
132 if (inp->skey_header.n_ == UINT8_MAX)
133 goto trunnel_alloc_failed;
134 #endif
135 TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->skey_header, elt, {});
136 return 0;
137 trunnel_alloc_failed:
138 TRUNNEL_SET_ERROR_CODE(inp);
139 return -1;
142 uint8_t *
143 pwbox_encoded_getarray_skey_header(pwbox_encoded_t *inp)
145 return inp->skey_header.elts_;
147 const uint8_t *
148 pwbox_encoded_getconstarray_skey_header(const pwbox_encoded_t *inp)
150 return (const uint8_t *)pwbox_encoded_getarray_skey_header((pwbox_encoded_t*)inp);
153 pwbox_encoded_setlen_skey_header(pwbox_encoded_t *inp, size_t newlen)
155 uint8_t *newptr;
156 #if UINT8_MAX < SIZE_MAX
157 if (newlen > UINT8_MAX)
158 goto trunnel_alloc_failed;
159 #endif
160 newptr = trunnel_dynarray_setlen(&inp->skey_header.allocated_,
161 &inp->skey_header.n_, inp->skey_header.elts_, newlen,
162 sizeof(inp->skey_header.elts_[0]), (trunnel_free_fn_t) NULL,
163 &inp->trunnel_error_code_);
164 if (newlen != 0 && newptr == NULL)
165 goto trunnel_alloc_failed;
166 inp->skey_header.elts_ = newptr;
167 return 0;
168 trunnel_alloc_failed:
169 TRUNNEL_SET_ERROR_CODE(inp);
170 return -1;
172 size_t
173 pwbox_encoded_getlen_iv(const pwbox_encoded_t *inp)
175 (void)inp; return 16;
178 uint8_t
179 pwbox_encoded_get_iv(pwbox_encoded_t *inp, size_t idx)
181 trunnel_assert(idx < 16);
182 return inp->iv[idx];
185 uint8_t
186 pwbox_encoded_getconst_iv(const pwbox_encoded_t *inp, size_t idx)
188 return pwbox_encoded_get_iv((pwbox_encoded_t*)inp, idx);
191 pwbox_encoded_set_iv(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
193 trunnel_assert(idx < 16);
194 inp->iv[idx] = elt;
195 return 0;
198 uint8_t *
199 pwbox_encoded_getarray_iv(pwbox_encoded_t *inp)
201 return inp->iv;
203 const uint8_t *
204 pwbox_encoded_getconstarray_iv(const pwbox_encoded_t *inp)
206 return (const uint8_t *)pwbox_encoded_getarray_iv((pwbox_encoded_t*)inp);
208 size_t
209 pwbox_encoded_getlen_data(const pwbox_encoded_t *inp)
211 return TRUNNEL_DYNARRAY_LEN(&inp->data);
214 uint8_t
215 pwbox_encoded_get_data(pwbox_encoded_t *inp, size_t idx)
217 return TRUNNEL_DYNARRAY_GET(&inp->data, idx);
220 uint8_t
221 pwbox_encoded_getconst_data(const pwbox_encoded_t *inp, size_t idx)
223 return pwbox_encoded_get_data((pwbox_encoded_t*)inp, idx);
226 pwbox_encoded_set_data(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
228 TRUNNEL_DYNARRAY_SET(&inp->data, idx, elt);
229 return 0;
232 pwbox_encoded_add_data(pwbox_encoded_t *inp, uint8_t elt)
234 TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->data, elt, {});
235 return 0;
236 trunnel_alloc_failed:
237 TRUNNEL_SET_ERROR_CODE(inp);
238 return -1;
241 uint8_t *
242 pwbox_encoded_getarray_data(pwbox_encoded_t *inp)
244 return inp->data.elts_;
246 const uint8_t *
247 pwbox_encoded_getconstarray_data(const pwbox_encoded_t *inp)
249 return (const uint8_t *)pwbox_encoded_getarray_data((pwbox_encoded_t*)inp);
252 pwbox_encoded_setlen_data(pwbox_encoded_t *inp, size_t newlen)
254 uint8_t *newptr;
255 newptr = trunnel_dynarray_setlen(&inp->data.allocated_,
256 &inp->data.n_, inp->data.elts_, newlen,
257 sizeof(inp->data.elts_[0]), (trunnel_free_fn_t) NULL,
258 &inp->trunnel_error_code_);
259 if (newlen != 0 && newptr == NULL)
260 goto trunnel_alloc_failed;
261 inp->data.elts_ = newptr;
262 return 0;
263 trunnel_alloc_failed:
264 TRUNNEL_SET_ERROR_CODE(inp);
265 return -1;
267 size_t
268 pwbox_encoded_getlen_hmac(const pwbox_encoded_t *inp)
270 (void)inp; return 32;
273 uint8_t
274 pwbox_encoded_get_hmac(pwbox_encoded_t *inp, size_t idx)
276 trunnel_assert(idx < 32);
277 return inp->hmac[idx];
280 uint8_t
281 pwbox_encoded_getconst_hmac(const pwbox_encoded_t *inp, size_t idx)
283 return pwbox_encoded_get_hmac((pwbox_encoded_t*)inp, idx);
286 pwbox_encoded_set_hmac(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
288 trunnel_assert(idx < 32);
289 inp->hmac[idx] = elt;
290 return 0;
293 uint8_t *
294 pwbox_encoded_getarray_hmac(pwbox_encoded_t *inp)
296 return inp->hmac;
298 const uint8_t *
299 pwbox_encoded_getconstarray_hmac(const pwbox_encoded_t *inp)
301 return (const uint8_t *)pwbox_encoded_getarray_hmac((pwbox_encoded_t*)inp);
303 const char *
304 pwbox_encoded_check(const pwbox_encoded_t *obj)
306 if (obj == NULL)
307 return "Object was NULL";
308 if (obj->trunnel_error_code_)
309 return "A set function failed on this object";
310 if (! (obj->fixedbytes0 == PWBOX0_CONST0))
311 return "Integer out of bounds";
312 if (! (obj->fixedbytes1 == PWBOX0_CONST1))
313 return "Integer out of bounds";
314 if (TRUNNEL_DYNARRAY_LEN(&obj->skey_header) != obj->header_len)
315 return "Length mismatch for skey_header";
316 return NULL;
319 ssize_t
320 pwbox_encoded_encoded_len(const pwbox_encoded_t *obj)
322 ssize_t result = 0;
324 if (NULL != pwbox_encoded_check(obj))
325 return -1;
328 /* Length of u32 fixedbytes0 IN [PWBOX0_CONST0] */
329 result += 4;
331 /* Length of u32 fixedbytes1 IN [PWBOX0_CONST1] */
332 result += 4;
334 /* Length of u8 header_len */
335 result += 1;
337 /* Length of u8 skey_header[header_len] */
338 result += TRUNNEL_DYNARRAY_LEN(&obj->skey_header);
340 /* Length of u8 iv[16] */
341 result += 16;
343 /* Length of u8 data[] */
344 result += TRUNNEL_DYNARRAY_LEN(&obj->data);
346 /* Length of u8 hmac[32] */
347 result += 32;
348 return result;
351 pwbox_encoded_clear_errors(pwbox_encoded_t *obj)
353 int r = obj->trunnel_error_code_;
354 obj->trunnel_error_code_ = 0;
355 return r;
357 ssize_t
358 pwbox_encoded_encode(uint8_t *output, size_t avail, const pwbox_encoded_t *obj)
360 ssize_t result = 0;
361 size_t written = 0;
362 uint8_t *ptr = output;
363 const char *msg;
364 #ifdef TRUNNEL_CHECK_ENCODED_LEN
365 const ssize_t encoded_len = pwbox_encoded_encoded_len(obj);
366 #endif
367 int enforce_avail = 0;
368 const size_t avail_orig = avail;
370 if (NULL != (msg = pwbox_encoded_check(obj)))
371 goto check_failed;
373 #ifdef TRUNNEL_CHECK_ENCODED_LEN
374 trunnel_assert(encoded_len >= 0);
375 #endif
377 /* Encode u32 fixedbytes0 IN [PWBOX0_CONST0] */
378 trunnel_assert(written <= avail);
379 if (avail - written < 4)
380 goto truncated;
381 trunnel_set_uint32(ptr, trunnel_htonl(obj->fixedbytes0));
382 written += 4; ptr += 4;
384 /* Encode u32 fixedbytes1 IN [PWBOX0_CONST1] */
385 trunnel_assert(written <= avail);
386 if (avail - written < 4)
387 goto truncated;
388 trunnel_set_uint32(ptr, trunnel_htonl(obj->fixedbytes1));
389 written += 4; ptr += 4;
391 /* Encode u8 header_len */
392 trunnel_assert(written <= avail);
393 if (avail - written < 1)
394 goto truncated;
395 trunnel_set_uint8(ptr, (obj->header_len));
396 written += 1; ptr += 1;
398 /* Encode u8 skey_header[header_len] */
400 size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->skey_header);
401 trunnel_assert(obj->header_len == elt_len);
402 trunnel_assert(written <= avail);
403 if (avail - written < elt_len)
404 goto truncated;
405 if (elt_len)
406 memcpy(ptr, obj->skey_header.elts_, elt_len);
407 written += elt_len; ptr += elt_len;
410 /* Encode u8 iv[16] */
411 trunnel_assert(written <= avail);
412 if (avail - written < 16)
413 goto truncated;
414 memcpy(ptr, obj->iv, 16);
415 written += 16; ptr += 16;
418 /* Encode u8 data[] */
420 size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->data);
421 trunnel_assert(written <= avail);
422 if (avail - written < elt_len)
423 goto truncated;
424 if (elt_len)
425 memcpy(ptr, obj->data.elts_, elt_len);
426 written += elt_len; ptr += elt_len;
428 trunnel_assert(written <= avail);
429 if (avail - written < 32)
430 goto truncated;
431 avail = written + 32;
432 enforce_avail = 1;
435 /* Encode u8 hmac[32] */
436 trunnel_assert(written <= avail);
437 if (avail - written < 32) {
438 if (avail_orig - written < 32)
439 goto truncated;
440 else
441 goto check_failed;
443 memcpy(ptr, obj->hmac, 32);
444 written += 32; ptr += 32;
447 trunnel_assert(ptr == output + written);
448 if (enforce_avail && avail != written)
449 goto check_failed;
450 #ifdef TRUNNEL_CHECK_ENCODED_LEN
452 trunnel_assert(encoded_len >= 0);
453 trunnel_assert((size_t)encoded_len == written);
456 #endif
458 return written;
460 truncated:
461 result = -2;
462 goto fail;
463 check_failed:
464 (void)msg;
465 result = -1;
466 goto fail;
467 fail:
468 trunnel_assert(result < 0);
469 return result;
472 /** As pwbox_encoded_parse(), but do not allocate the output object.
474 static ssize_t
475 pwbox_encoded_parse_into(pwbox_encoded_t *obj, const uint8_t *input, const size_t len_in)
477 const uint8_t *ptr = input;
478 size_t remaining = len_in;
479 ssize_t result = 0;
480 (void)result;
482 /* Parse u32 fixedbytes0 IN [PWBOX0_CONST0] */
483 CHECK_REMAINING(4, truncated);
484 obj->fixedbytes0 = trunnel_ntohl(trunnel_get_uint32(ptr));
485 remaining -= 4; ptr += 4;
486 if (! (obj->fixedbytes0 == PWBOX0_CONST0))
487 goto fail;
489 /* Parse u32 fixedbytes1 IN [PWBOX0_CONST1] */
490 CHECK_REMAINING(4, truncated);
491 obj->fixedbytes1 = trunnel_ntohl(trunnel_get_uint32(ptr));
492 remaining -= 4; ptr += 4;
493 if (! (obj->fixedbytes1 == PWBOX0_CONST1))
494 goto fail;
496 /* Parse u8 header_len */
497 CHECK_REMAINING(1, truncated);
498 obj->header_len = (trunnel_get_uint8(ptr));
499 remaining -= 1; ptr += 1;
501 /* Parse u8 skey_header[header_len] */
502 CHECK_REMAINING(obj->header_len, truncated);
503 TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->skey_header, obj->header_len, {});
504 obj->skey_header.n_ = obj->header_len;
505 if (obj->header_len)
506 memcpy(obj->skey_header.elts_, ptr, obj->header_len);
507 ptr += obj->header_len; remaining -= obj->header_len;
509 /* Parse u8 iv[16] */
510 CHECK_REMAINING(16, truncated);
511 memcpy(obj->iv, ptr, 16);
512 remaining -= 16; ptr += 16;
514 size_t remaining_after;
515 CHECK_REMAINING(32, truncated);
516 remaining_after = 32;
517 remaining = remaining - 32;
519 /* Parse u8 data[] */
520 TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->data, remaining, {});
521 obj->data.n_ = remaining;
522 if (remaining)
523 memcpy(obj->data.elts_, ptr, remaining);
524 ptr += remaining; remaining -= remaining;
525 if (remaining != 0)
526 goto fail;
527 remaining = remaining_after;
530 /* Parse u8 hmac[32] */
531 CHECK_REMAINING(32, truncated);
532 memcpy(obj->hmac, ptr, 32);
533 remaining -= 32; ptr += 32;
534 trunnel_assert(ptr + remaining == input + len_in);
535 return len_in - remaining;
537 truncated:
538 return -2;
539 trunnel_alloc_failed:
540 return -1;
541 fail:
542 result = -1;
543 return result;
546 ssize_t
547 pwbox_encoded_parse(pwbox_encoded_t **output, const uint8_t *input, const size_t len_in)
549 ssize_t result;
550 *output = pwbox_encoded_new();
551 if (NULL == *output)
552 return -1;
553 result = pwbox_encoded_parse_into(*output, input, len_in);
554 if (result < 0) {
555 pwbox_encoded_free(*output);
556 *output = NULL;
558 return result;