Line data Source code
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"
7 :
8 : #include "pwbox.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 pwbox_deadcode_dummy__ = 0;
19 : #define OR_DEADCODE_DUMMY || pwbox_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 : pwbox_encoded_t *
32 27 : pwbox_encoded_new(void)
33 : {
34 27 : pwbox_encoded_t *val = trunnel_calloc(1, sizeof(pwbox_encoded_t));
35 27 : if (NULL == val)
36 : return NULL;
37 27 : val->fixedbytes0 = PWBOX0_CONST0;
38 27 : val->fixedbytes1 = PWBOX0_CONST1;
39 27 : return val;
40 : }
41 :
42 : /** Release all storage held inside 'obj', but do not free 'obj'.
43 : */
44 : static void
45 27 : pwbox_encoded_clear(pwbox_encoded_t *obj)
46 : {
47 27 : (void) obj;
48 27 : TRUNNEL_DYNARRAY_WIPE(&obj->skey_header);
49 27 : TRUNNEL_DYNARRAY_CLEAR(&obj->skey_header);
50 27 : TRUNNEL_DYNARRAY_WIPE(&obj->data);
51 27 : TRUNNEL_DYNARRAY_CLEAR(&obj->data);
52 27 : }
53 :
54 : void
55 32 : pwbox_encoded_free(pwbox_encoded_t *obj)
56 : {
57 32 : if (obj == NULL)
58 : return;
59 27 : pwbox_encoded_clear(obj);
60 27 : trunnel_memwipe(obj, sizeof(pwbox_encoded_t));
61 27 : trunnel_free_(obj);
62 : }
63 :
64 : uint32_t
65 0 : pwbox_encoded_get_fixedbytes0(const pwbox_encoded_t *inp)
66 : {
67 0 : return inp->fixedbytes0;
68 : }
69 : int
70 0 : pwbox_encoded_set_fixedbytes0(pwbox_encoded_t *inp, uint32_t val)
71 : {
72 0 : if (! ((val == PWBOX0_CONST0))) {
73 0 : TRUNNEL_SET_ERROR_CODE(inp);
74 0 : return -1;
75 : }
76 0 : inp->fixedbytes0 = val;
77 0 : return 0;
78 : }
79 : uint32_t
80 0 : pwbox_encoded_get_fixedbytes1(const pwbox_encoded_t *inp)
81 : {
82 0 : return inp->fixedbytes1;
83 : }
84 : int
85 0 : pwbox_encoded_set_fixedbytes1(pwbox_encoded_t *inp, uint32_t val)
86 : {
87 0 : if (! ((val == PWBOX0_CONST1))) {
88 0 : TRUNNEL_SET_ERROR_CODE(inp);
89 0 : return -1;
90 : }
91 0 : inp->fixedbytes1 = val;
92 0 : return 0;
93 : }
94 : uint8_t
95 0 : pwbox_encoded_get_header_len(const pwbox_encoded_t *inp)
96 : {
97 0 : return inp->header_len;
98 : }
99 : int
100 0 : pwbox_encoded_set_header_len(pwbox_encoded_t *inp, uint8_t val)
101 : {
102 0 : inp->header_len = val;
103 0 : return 0;
104 : }
105 : size_t
106 16 : pwbox_encoded_getlen_skey_header(const pwbox_encoded_t *inp)
107 : {
108 16 : return TRUNNEL_DYNARRAY_LEN(&inp->skey_header);
109 : }
110 :
111 : uint8_t
112 0 : pwbox_encoded_get_skey_header(pwbox_encoded_t *inp, size_t idx)
113 : {
114 0 : return TRUNNEL_DYNARRAY_GET(&inp->skey_header, idx);
115 : }
116 :
117 : uint8_t
118 0 : pwbox_encoded_getconst_skey_header(const pwbox_encoded_t *inp, size_t idx)
119 : {
120 0 : return pwbox_encoded_get_skey_header((pwbox_encoded_t*)inp, idx);
121 : }
122 : int
123 0 : pwbox_encoded_set_skey_header(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
124 : {
125 0 : TRUNNEL_DYNARRAY_SET(&inp->skey_header, idx, elt);
126 0 : return 0;
127 : }
128 : int
129 0 : pwbox_encoded_add_skey_header(pwbox_encoded_t *inp, uint8_t elt)
130 : {
131 : #if SIZE_MAX >= UINT8_MAX
132 0 : if (inp->skey_header.n_ == UINT8_MAX)
133 0 : goto trunnel_alloc_failed;
134 : #endif
135 0 : TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->skey_header, elt, {});
136 0 : return 0;
137 0 : trunnel_alloc_failed:
138 0 : TRUNNEL_SET_ERROR_CODE(inp);
139 0 : return -1;
140 : }
141 :
142 : uint8_t *
143 28 : pwbox_encoded_getarray_skey_header(pwbox_encoded_t *inp)
144 : {
145 28 : return inp->skey_header.elts_;
146 : }
147 : const uint8_t *
148 0 : pwbox_encoded_getconstarray_skey_header(const pwbox_encoded_t *inp)
149 : {
150 0 : return (const uint8_t *)pwbox_encoded_getarray_skey_header((pwbox_encoded_t*)inp);
151 : }
152 : int
153 12 : pwbox_encoded_setlen_skey_header(pwbox_encoded_t *inp, size_t newlen)
154 : {
155 12 : uint8_t *newptr;
156 : #if UINT8_MAX < SIZE_MAX
157 12 : if (newlen > UINT8_MAX)
158 0 : goto trunnel_alloc_failed;
159 : #endif
160 24 : newptr = trunnel_dynarray_setlen(&inp->skey_header.allocated_,
161 12 : &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 12 : if (newlen != 0 && newptr == NULL)
165 0 : goto trunnel_alloc_failed;
166 12 : inp->skey_header.elts_ = newptr;
167 12 : return 0;
168 0 : trunnel_alloc_failed:
169 0 : TRUNNEL_SET_ERROR_CODE(inp);
170 0 : return -1;
171 : }
172 : size_t
173 0 : pwbox_encoded_getlen_iv(const pwbox_encoded_t *inp)
174 : {
175 0 : (void)inp; return 16;
176 : }
177 :
178 : uint8_t
179 0 : pwbox_encoded_get_iv(pwbox_encoded_t *inp, size_t idx)
180 : {
181 0 : trunnel_assert(idx < 16);
182 0 : return inp->iv[idx];
183 : }
184 :
185 : uint8_t
186 0 : pwbox_encoded_getconst_iv(const pwbox_encoded_t *inp, size_t idx)
187 : {
188 0 : return pwbox_encoded_get_iv((pwbox_encoded_t*)inp, idx);
189 : }
190 : int
191 0 : pwbox_encoded_set_iv(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
192 : {
193 0 : trunnel_assert(idx < 16);
194 0 : inp->iv[idx] = elt;
195 0 : return 0;
196 : }
197 :
198 : uint8_t *
199 0 : pwbox_encoded_getarray_iv(pwbox_encoded_t *inp)
200 : {
201 0 : return inp->iv;
202 : }
203 : const uint8_t *
204 0 : pwbox_encoded_getconstarray_iv(const pwbox_encoded_t *inp)
205 : {
206 0 : return (const uint8_t *)pwbox_encoded_getarray_iv((pwbox_encoded_t*)inp);
207 : }
208 : size_t
209 6 : pwbox_encoded_getlen_data(const pwbox_encoded_t *inp)
210 : {
211 6 : return TRUNNEL_DYNARRAY_LEN(&inp->data);
212 : }
213 :
214 : uint8_t
215 0 : pwbox_encoded_get_data(pwbox_encoded_t *inp, size_t idx)
216 : {
217 0 : return TRUNNEL_DYNARRAY_GET(&inp->data, idx);
218 : }
219 :
220 : uint8_t
221 0 : pwbox_encoded_getconst_data(const pwbox_encoded_t *inp, size_t idx)
222 : {
223 0 : return pwbox_encoded_get_data((pwbox_encoded_t*)inp, idx);
224 : }
225 : int
226 0 : pwbox_encoded_set_data(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
227 : {
228 0 : TRUNNEL_DYNARRAY_SET(&inp->data, idx, elt);
229 0 : return 0;
230 : }
231 : int
232 0 : pwbox_encoded_add_data(pwbox_encoded_t *inp, uint8_t elt)
233 : {
234 0 : TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->data, elt, {});
235 0 : return 0;
236 0 : trunnel_alloc_failed:
237 0 : TRUNNEL_SET_ERROR_CODE(inp);
238 0 : return -1;
239 : }
240 :
241 : uint8_t *
242 12 : pwbox_encoded_getarray_data(pwbox_encoded_t *inp)
243 : {
244 12 : return inp->data.elts_;
245 : }
246 : const uint8_t *
247 0 : pwbox_encoded_getconstarray_data(const pwbox_encoded_t *inp)
248 : {
249 0 : return (const uint8_t *)pwbox_encoded_getarray_data((pwbox_encoded_t*)inp);
250 : }
251 : int
252 6 : pwbox_encoded_setlen_data(pwbox_encoded_t *inp, size_t newlen)
253 : {
254 6 : uint8_t *newptr;
255 12 : newptr = trunnel_dynarray_setlen(&inp->data.allocated_,
256 6 : &inp->data.n_, inp->data.elts_, newlen,
257 : sizeof(inp->data.elts_[0]), (trunnel_free_fn_t) NULL,
258 : &inp->trunnel_error_code_);
259 6 : if (newlen != 0 && newptr == NULL)
260 0 : goto trunnel_alloc_failed;
261 6 : inp->data.elts_ = newptr;
262 6 : return 0;
263 0 : trunnel_alloc_failed:
264 0 : TRUNNEL_SET_ERROR_CODE(inp);
265 0 : return -1;
266 : }
267 : size_t
268 0 : pwbox_encoded_getlen_hmac(const pwbox_encoded_t *inp)
269 : {
270 0 : (void)inp; return 32;
271 : }
272 :
273 : uint8_t
274 0 : pwbox_encoded_get_hmac(pwbox_encoded_t *inp, size_t idx)
275 : {
276 0 : trunnel_assert(idx < 32);
277 0 : return inp->hmac[idx];
278 : }
279 :
280 : uint8_t
281 0 : pwbox_encoded_getconst_hmac(const pwbox_encoded_t *inp, size_t idx)
282 : {
283 0 : return pwbox_encoded_get_hmac((pwbox_encoded_t*)inp, idx);
284 : }
285 : int
286 0 : pwbox_encoded_set_hmac(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
287 : {
288 0 : trunnel_assert(idx < 32);
289 0 : inp->hmac[idx] = elt;
290 0 : return 0;
291 : }
292 :
293 : uint8_t *
294 0 : pwbox_encoded_getarray_hmac(pwbox_encoded_t *inp)
295 : {
296 0 : return inp->hmac;
297 : }
298 : const uint8_t *
299 0 : pwbox_encoded_getconstarray_hmac(const pwbox_encoded_t *inp)
300 : {
301 0 : return (const uint8_t *)pwbox_encoded_getarray_hmac((pwbox_encoded_t*)inp);
302 : }
303 : const char *
304 12 : pwbox_encoded_check(const pwbox_encoded_t *obj)
305 : {
306 12 : if (obj == NULL)
307 : return "Object was NULL";
308 12 : if (obj->trunnel_error_code_)
309 : return "A set function failed on this object";
310 12 : if (! (obj->fixedbytes0 == PWBOX0_CONST0))
311 : return "Integer out of bounds";
312 12 : if (! (obj->fixedbytes1 == PWBOX0_CONST1))
313 : return "Integer out of bounds";
314 12 : if (TRUNNEL_DYNARRAY_LEN(&obj->skey_header) != obj->header_len)
315 0 : return "Length mismatch for skey_header";
316 : return NULL;
317 : }
318 :
319 : ssize_t
320 6 : pwbox_encoded_encoded_len(const pwbox_encoded_t *obj)
321 : {
322 6 : ssize_t result = 0;
323 :
324 6 : if (NULL != pwbox_encoded_check(obj))
325 : return -1;
326 :
327 :
328 : /* Length of u32 fixedbytes0 IN [PWBOX0_CONST0] */
329 6 : result += 4;
330 :
331 : /* Length of u32 fixedbytes1 IN [PWBOX0_CONST1] */
332 6 : result += 4;
333 :
334 : /* Length of u8 header_len */
335 6 : result += 1;
336 :
337 : /* Length of u8 skey_header[header_len] */
338 6 : result += TRUNNEL_DYNARRAY_LEN(&obj->skey_header);
339 :
340 : /* Length of u8 iv[16] */
341 6 : result += 16;
342 :
343 : /* Length of u8 data[] */
344 6 : result += TRUNNEL_DYNARRAY_LEN(&obj->data);
345 :
346 : /* Length of u8 hmac[32] */
347 6 : result += 32;
348 6 : return result;
349 : }
350 : int
351 0 : pwbox_encoded_clear_errors(pwbox_encoded_t *obj)
352 : {
353 0 : int r = obj->trunnel_error_code_;
354 0 : obj->trunnel_error_code_ = 0;
355 0 : return r;
356 : }
357 : ssize_t
358 6 : pwbox_encoded_encode(uint8_t *output, size_t avail, const pwbox_encoded_t *obj)
359 : {
360 6 : ssize_t result = 0;
361 6 : size_t written = 0;
362 6 : uint8_t *ptr = output;
363 6 : const char *msg;
364 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
365 : const ssize_t encoded_len = pwbox_encoded_encoded_len(obj);
366 : #endif
367 6 : int enforce_avail = 0;
368 6 : const size_t avail_orig = avail;
369 :
370 6 : if (NULL != (msg = pwbox_encoded_check(obj)))
371 0 : goto check_failed;
372 :
373 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
374 : trunnel_assert(encoded_len >= 0);
375 : #endif
376 :
377 : /* Encode u32 fixedbytes0 IN [PWBOX0_CONST0] */
378 6 : trunnel_assert(written <= avail);
379 6 : if (avail - written < 4)
380 0 : goto truncated;
381 6 : trunnel_set_uint32(ptr, trunnel_htonl(obj->fixedbytes0));
382 6 : written += 4; ptr += 4;
383 :
384 : /* Encode u32 fixedbytes1 IN [PWBOX0_CONST1] */
385 6 : trunnel_assert(written <= avail);
386 6 : if (avail - written < 4)
387 0 : goto truncated;
388 6 : trunnel_set_uint32(ptr, trunnel_htonl(obj->fixedbytes1));
389 6 : written += 4; ptr += 4;
390 :
391 : /* Encode u8 header_len */
392 6 : trunnel_assert(written <= avail);
393 6 : if (avail - written < 1)
394 0 : goto truncated;
395 6 : trunnel_set_uint8(ptr, (obj->header_len));
396 6 : written += 1; ptr += 1;
397 :
398 : /* Encode u8 skey_header[header_len] */
399 : {
400 6 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->skey_header);
401 6 : trunnel_assert(obj->header_len == elt_len);
402 6 : trunnel_assert(written <= avail);
403 6 : if (avail - written < elt_len)
404 0 : goto truncated;
405 6 : if (elt_len)
406 6 : memcpy(ptr, obj->skey_header.elts_, elt_len);
407 6 : written += elt_len; ptr += elt_len;
408 : }
409 :
410 : /* Encode u8 iv[16] */
411 6 : trunnel_assert(written <= avail);
412 6 : if (avail - written < 16)
413 0 : goto truncated;
414 6 : memcpy(ptr, obj->iv, 16);
415 6 : written += 16; ptr += 16;
416 : {
417 :
418 : /* Encode u8 data[] */
419 : {
420 6 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->data);
421 6 : trunnel_assert(written <= avail);
422 6 : if (avail - written < elt_len)
423 0 : goto truncated;
424 6 : if (elt_len)
425 6 : memcpy(ptr, obj->data.elts_, elt_len);
426 6 : written += elt_len; ptr += elt_len;
427 : }
428 6 : trunnel_assert(written <= avail);
429 6 : if (avail - written < 32)
430 0 : goto truncated;
431 6 : avail = written + 32;
432 6 : enforce_avail = 1;
433 : }
434 :
435 : /* Encode u8 hmac[32] */
436 6 : trunnel_assert(written <= avail);
437 6 : if (avail - written < 32) {
438 : if (avail_orig - written < 32)
439 : goto truncated;
440 : else
441 : goto check_failed;
442 : }
443 6 : memcpy(ptr, obj->hmac, 32);
444 6 : written += 32; ptr += 32;
445 :
446 :
447 6 : trunnel_assert(ptr == output + written);
448 6 : if (enforce_avail && avail != written)
449 : goto check_failed;
450 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
451 : {
452 : trunnel_assert(encoded_len >= 0);
453 : trunnel_assert((size_t)encoded_len == written);
454 : }
455 :
456 : #endif
457 :
458 6 : return written;
459 :
460 0 : truncated:
461 0 : result = -2;
462 0 : goto fail;
463 0 : check_failed:
464 0 : (void)msg;
465 0 : result = -1;
466 0 : goto fail;
467 : fail:
468 : trunnel_assert(result < 0);
469 : return result;
470 : }
471 :
472 : /** As pwbox_encoded_parse(), but do not allocate the output object.
473 : */
474 : static ssize_t
475 21 : pwbox_encoded_parse_into(pwbox_encoded_t *obj, const uint8_t *input, const size_t len_in)
476 : {
477 21 : const uint8_t *ptr = input;
478 21 : size_t remaining = len_in;
479 21 : ssize_t result = 0;
480 21 : (void)result;
481 :
482 : /* Parse u32 fixedbytes0 IN [PWBOX0_CONST0] */
483 21 : CHECK_REMAINING(4, truncated);
484 21 : obj->fixedbytes0 = trunnel_ntohl(trunnel_get_uint32(ptr));
485 21 : remaining -= 4; ptr += 4;
486 21 : if (! (obj->fixedbytes0 == PWBOX0_CONST0))
487 5 : goto fail;
488 :
489 : /* Parse u32 fixedbytes1 IN [PWBOX0_CONST1] */
490 16 : CHECK_REMAINING(4, truncated);
491 16 : obj->fixedbytes1 = trunnel_ntohl(trunnel_get_uint32(ptr));
492 16 : remaining -= 4; ptr += 4;
493 16 : if (! (obj->fixedbytes1 == PWBOX0_CONST1))
494 0 : goto fail;
495 :
496 : /* Parse u8 header_len */
497 16 : CHECK_REMAINING(1, truncated);
498 16 : obj->header_len = (trunnel_get_uint8(ptr));
499 16 : remaining -= 1; ptr += 1;
500 :
501 : /* Parse u8 skey_header[header_len] */
502 16 : CHECK_REMAINING(obj->header_len, truncated);
503 16 : TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->skey_header, obj->header_len, {});
504 16 : obj->skey_header.n_ = obj->header_len;
505 16 : if (obj->header_len)
506 16 : memcpy(obj->skey_header.elts_, ptr, obj->header_len);
507 16 : ptr += obj->header_len; remaining -= obj->header_len;
508 :
509 : /* Parse u8 iv[16] */
510 16 : CHECK_REMAINING(16, truncated);
511 16 : memcpy(obj->iv, ptr, 16);
512 16 : remaining -= 16; ptr += 16;
513 : {
514 16 : size_t remaining_after;
515 16 : CHECK_REMAINING(32, truncated);
516 16 : remaining_after = 32;
517 16 : remaining = remaining - 32;
518 :
519 : /* Parse u8 data[] */
520 16 : TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->data, remaining, {});
521 16 : obj->data.n_ = remaining;
522 16 : if (remaining)
523 16 : memcpy(obj->data.elts_, ptr, remaining);
524 16 : ptr += remaining; remaining -= remaining;
525 16 : if (remaining != 0)
526 : goto fail;
527 16 : remaining = remaining_after;
528 : }
529 :
530 : /* Parse u8 hmac[32] */
531 16 : CHECK_REMAINING(32, truncated);
532 16 : memcpy(obj->hmac, ptr, 32);
533 16 : remaining -= 32; ptr += 32;
534 16 : trunnel_assert(ptr + remaining == input + len_in);
535 16 : return len_in - remaining;
536 :
537 : truncated:
538 : return -2;
539 : trunnel_alloc_failed:
540 : return -1;
541 : fail:
542 21 : result = -1;
543 : return result;
544 : }
545 :
546 : ssize_t
547 21 : pwbox_encoded_parse(pwbox_encoded_t **output, const uint8_t *input, const size_t len_in)
548 : {
549 21 : ssize_t result;
550 21 : *output = pwbox_encoded_new();
551 21 : if (NULL == *output)
552 : return -1;
553 21 : result = pwbox_encoded_parse_into(*output, input, len_in);
554 21 : if (result < 0) {
555 5 : pwbox_encoded_free(*output);
556 5 : *output = NULL;
557 : }
558 : return result;
559 : }
|