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