1 /* 2 * Copyright (c) 2009 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "der_locl.h" 37 #include <com_err.h> 38 39 #if 0 40 #define ABORT_ON_ERROR() abort() 41 #else 42 #define ABORT_ON_ERROR() do { } while(0) 43 #endif 44 45 #define DPOC(data,offset) ((const void *)(((const unsigned char *)data) + offset)) 46 #define DPO(data,offset) ((void *)(((unsigned char *)data) + offset)) 47 48 49 static struct asn1_type_func prim[] = { 50 #define el(name, type) { \ 51 (asn1_type_encode)der_put_##name, \ 52 (asn1_type_decode)der_get_##name, \ 53 (asn1_type_length)der_length_##name, \ 54 (asn1_type_copy)der_copy_##name, \ 55 (asn1_type_release)der_free_##name, \ 56 sizeof(type) \ 57 } 58 #define elber(name, type) { \ 59 (asn1_type_encode)der_put_##name, \ 60 (asn1_type_decode)der_get_##name##_ber, \ 61 (asn1_type_length)der_length_##name, \ 62 (asn1_type_copy)der_copy_##name, \ 63 (asn1_type_release)der_free_##name, \ 64 sizeof(type) \ 65 } 66 el(integer, int), 67 el(heim_integer, heim_integer), 68 el(integer, int), 69 el(unsigned, unsigned), 70 el(general_string, heim_general_string), 71 el(octet_string, heim_octet_string), 72 elber(octet_string, heim_octet_string), 73 el(ia5_string, heim_ia5_string), 74 el(bmp_string, heim_bmp_string), 75 el(universal_string, heim_universal_string), 76 el(printable_string, heim_printable_string), 77 el(visible_string, heim_visible_string), 78 el(utf8string, heim_utf8_string), 79 el(generalized_time, time_t), 80 el(utctime, time_t), 81 el(bit_string, heim_bit_string), 82 { (asn1_type_encode)der_put_boolean, (asn1_type_decode)der_get_boolean, 83 (asn1_type_length)der_length_boolean, (asn1_type_copy)der_copy_integer, 84 (asn1_type_release)der_free_integer, sizeof(int) 85 }, 86 el(oid, heim_oid), 87 el(general_string, heim_general_string), 88 #undef el 89 #undef elber 90 }; 91 92 static size_t 93 sizeofType(const struct asn1_template *t) 94 { 95 return t->offset; 96 } 97 98 /* 99 * Here is abstraction to not so well evil fact of bit fields in C, 100 * they are endian dependent, so when getting and setting bits in the 101 * host local structure we need to know the endianness of the host. 102 * 103 * Its not the first time in Heimdal this have bitten us, and some day 104 * we'll grow up and use #defined constant, but bit fields are still 105 * so pretty and shiny. 106 */ 107 108 static void 109 bmember_get_bit(const unsigned char *p, void *data, 110 unsigned int bit, size_t size) 111 { 112 unsigned int localbit = bit % 8; 113 if ((*p >> (7 - localbit)) & 1) { 114 #ifdef WORDS_BIGENDIAN 115 *(unsigned int *)data |= (1 << ((size * 8) - bit - 1)); 116 #else 117 *(unsigned int *)data |= (1 << bit); 118 #endif 119 } 120 } 121 122 static int 123 bmember_isset_bit(const void *data, unsigned int bit, size_t size) 124 { 125 #ifdef WORDS_BIGENDIAN 126 if ((*(unsigned int *)data) & (1 << ((size * 8) - bit - 1))) 127 return 1; 128 return 0; 129 #else 130 if ((*(unsigned int *)data) & (1 << bit)) 131 return 1; 132 return 0; 133 #endif 134 } 135 136 static void 137 bmember_put_bit(unsigned char *p, const void *data, unsigned int bit, 138 size_t size, unsigned int *bitset) 139 { 140 unsigned int localbit = bit % 8; 141 142 if (bmember_isset_bit(data, bit, size)) { 143 *p |= (1 << (7 - localbit)); 144 if (*bitset == 0) 145 *bitset = (7 - localbit) + 1; 146 } 147 } 148 149 int 150 _asn1_decode(const struct asn1_template *t, unsigned flags, 151 const unsigned char *p, size_t len, void *data, size_t *size) 152 { 153 size_t elements = A1_HEADER_LEN(t); 154 size_t oldlen = len; 155 int ret = 0; 156 const unsigned char *startp = NULL; 157 unsigned int template_flags = t->tt; 158 159 /* skip over header */ 160 t++; 161 162 if (template_flags & A1_HF_PRESERVE) 163 startp = p; 164 165 while (elements) { 166 switch (t->tt & A1_OP_MASK) { 167 case A1_OP_TYPE: 168 case A1_OP_TYPE_EXTERN: { 169 size_t newsize, size; 170 void *el = DPO(data, t->offset); 171 void **pel = (void **)el; 172 173 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 174 size = sizeofType(t->ptr); 175 } else { 176 const struct asn1_type_func *f = t->ptr; 177 size = f->size; 178 } 179 180 if (t->tt & A1_FLAG_OPTIONAL) { 181 *pel = calloc(1, size); 182 if (*pel == NULL) 183 return ENOMEM; 184 el = *pel; 185 } 186 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 187 ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize); 188 } else { 189 const struct asn1_type_func *f = t->ptr; 190 ret = (f->decode)(p, len, el, &newsize); 191 } 192 if (ret) { 193 if (t->tt & A1_FLAG_OPTIONAL) { 194 free(*pel); 195 *pel = NULL; 196 break; 197 } 198 return ret; 199 } 200 p += newsize; len -= newsize; 201 202 break; 203 } 204 case A1_OP_TAG: { 205 Der_type dertype; 206 size_t newsize; 207 size_t datalen, l; 208 void *olddata = data; 209 int is_indefinite = 0; 210 int subflags = flags; 211 212 ret = der_match_tag_and_length(p, len, A1_TAG_CLASS(t->tt), 213 &dertype, A1_TAG_TAG(t->tt), 214 &datalen, &l); 215 if (ret) { 216 if (t->tt & A1_FLAG_OPTIONAL) 217 break; 218 return ret; 219 } 220 221 p += l; len -= l; 222 223 /* 224 * Only allow indefinite encoding for OCTET STRING and BER 225 * for now. Should handle BIT STRING too. 226 */ 227 228 if (dertype != A1_TAG_TYPE(t->tt) && (flags & A1_PF_ALLOW_BER)) { 229 const struct asn1_template *subtype = t->ptr; 230 subtype++; /* skip header */ 231 232 if (((subtype->tt & A1_OP_MASK) == A1_OP_PARSE) && 233 A1_PARSE_TYPE(subtype->tt) == A1T_OCTET_STRING) 234 subflags |= A1_PF_INDEFINTE; 235 } 236 237 if (datalen == ASN1_INDEFINITE) { 238 if ((flags & A1_PF_ALLOW_BER) == 0) 239 return ASN1_GOT_BER; 240 is_indefinite = 1; 241 datalen = len; 242 if (datalen < 2) 243 return ASN1_OVERRUN; 244 /* hide EndOfContent for sub-decoder, catching it below */ 245 datalen -= 2; 246 } else if (datalen > len) 247 return ASN1_OVERRUN; 248 249 data = DPO(data, t->offset); 250 251 if (t->tt & A1_FLAG_OPTIONAL) { 252 void **el = (void **)data; 253 size_t ellen = sizeofType(t->ptr); 254 255 *el = calloc(1, ellen); 256 if (*el == NULL) 257 return ENOMEM; 258 data = *el; 259 } 260 261 ret = _asn1_decode(t->ptr, subflags, p, datalen, data, &newsize); 262 if (ret) 263 return ret; 264 265 if (newsize != datalen) 266 return ASN1_EXTRA_DATA; 267 268 len -= datalen; 269 p += datalen; 270 271 /* 272 * Indefinite encoding needs a trailing EndOfContent, 273 * check for that. 274 */ 275 if (is_indefinite) { 276 ret = der_match_tag_and_length(p, len, ASN1_C_UNIV, 277 &dertype, UT_EndOfContent, 278 &datalen, &l); 279 if (ret) 280 return ret; 281 if (dertype != PRIM) 282 return ASN1_BAD_ID; 283 if (datalen != 0) 284 return ASN1_INDEF_EXTRA_DATA; 285 p += l; len -= l; 286 } 287 data = olddata; 288 289 break; 290 } 291 case A1_OP_PARSE: { 292 unsigned int type = A1_PARSE_TYPE(t->tt); 293 size_t newsize; 294 void *el = DPO(data, t->offset); 295 296 /* 297 * INDEFINITE primitive types are one element after the 298 * same type but non-INDEFINITE version. 299 */ 300 if (flags & A1_PF_INDEFINTE) 301 type++; 302 303 if (type >= sizeof(prim)/sizeof(prim[0])) { 304 ABORT_ON_ERROR(); 305 return ASN1_PARSE_ERROR; 306 } 307 308 ret = (prim[type].decode)(p, len, el, &newsize); 309 if (ret) 310 return ret; 311 p += newsize; len -= newsize; 312 313 break; 314 } 315 case A1_OP_SETOF: 316 case A1_OP_SEQOF: { 317 struct template_of *el = DPO(data, t->offset); 318 size_t newsize; 319 size_t ellen = sizeofType(t->ptr); 320 size_t vallength = 0; 321 322 while (len > 0) { 323 void *tmp; 324 size_t newlen = vallength + ellen; 325 if (vallength > newlen) 326 return ASN1_OVERFLOW; 327 328 tmp = realloc(el->val, newlen); 329 if (tmp == NULL) 330 return ENOMEM; 331 332 memset(DPO(tmp, vallength), 0, ellen); 333 el->val = tmp; 334 335 ret = _asn1_decode(t->ptr, flags & (~A1_PF_INDEFINTE), p, len, 336 DPO(el->val, vallength), &newsize); 337 if (ret) 338 return ret; 339 vallength = newlen; 340 el->len++; 341 p += newsize; len -= newsize; 342 } 343 344 break; 345 } 346 case A1_OP_BMEMBER: { 347 const struct asn1_template *bmember = t->ptr; 348 size_t size = bmember->offset; 349 size_t elements = A1_HEADER_LEN(bmember); 350 size_t pos = 0; 351 352 bmember++; 353 354 memset(data, 0, size); 355 356 if (len < 1) 357 return ASN1_OVERRUN; 358 p++; len--; 359 360 while (elements && len) { 361 while (bmember->offset / 8 > pos / 8) { 362 if (len < 1) 363 break; 364 p++; len--; 365 pos += 8; 366 } 367 if (len) { 368 bmember_get_bit(p, data, bmember->offset, size); 369 elements--; bmember++; 370 } 371 } 372 len = 0; 373 break; 374 } 375 case A1_OP_CHOICE: { 376 const struct asn1_template *choice = t->ptr; 377 unsigned int *element = DPO(data, choice->offset); 378 size_t datalen; 379 unsigned int i; 380 381 for (i = 1; i < A1_HEADER_LEN(choice) + 1; i++) { 382 /* should match first tag instead, store it in choice.tt */ 383 ret = _asn1_decode(choice[i].ptr, 0, p, len, 384 DPO(data, choice[i].offset), &datalen); 385 if (ret == 0) { 386 *element = i; 387 p += datalen; len -= datalen; 388 break; 389 } else if (ret != ASN1_BAD_ID && ret != ASN1_MISPLACED_FIELD && ret != ASN1_MISSING_FIELD) { 390 return ret; 391 } 392 } 393 if (i >= A1_HEADER_LEN(choice) + 1) { 394 if (choice->tt == 0) 395 return ASN1_BAD_ID; 396 397 *element = 0; 398 ret = der_get_octet_string(p, len, 399 DPO(data, choice->tt), &datalen); 400 if (ret) 401 return ret; 402 p += datalen; len -= datalen; 403 } 404 405 break; 406 } 407 default: 408 ABORT_ON_ERROR(); 409 return ASN1_PARSE_ERROR; 410 } 411 t++; 412 elements--; 413 } 414 /* if we are using padding, eat up read of context */ 415 if (template_flags & A1_HF_ELLIPSIS) 416 len = 0; 417 418 oldlen -= len; 419 420 if (size) 421 *size = oldlen; 422 423 /* 424 * saved the raw bits if asked for it, useful for signature 425 * verification. 426 */ 427 if (startp) { 428 heim_octet_string *save = data; 429 430 save->data = malloc(oldlen); 431 if (save->data == NULL) 432 return ENOMEM; 433 else { 434 save->length = oldlen; 435 memcpy(save->data, startp, oldlen); 436 } 437 } 438 return 0; 439 } 440 441 int 442 _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const void *data, size_t *size) 443 { 444 size_t elements = A1_HEADER_LEN(t); 445 int ret = 0; 446 size_t oldlen = len; 447 448 t += A1_HEADER_LEN(t); 449 450 while (elements) { 451 switch (t->tt & A1_OP_MASK) { 452 case A1_OP_TYPE: 453 case A1_OP_TYPE_EXTERN: { 454 size_t newsize; 455 const void *el = DPOC(data, t->offset); 456 457 if (t->tt & A1_FLAG_OPTIONAL) { 458 void **pel = (void **)el; 459 if (*pel == NULL) 460 break; 461 el = *pel; 462 } 463 464 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 465 ret = _asn1_encode(t->ptr, p, len, el, &newsize); 466 } else { 467 const struct asn1_type_func *f = t->ptr; 468 ret = (f->encode)(p, len, el, &newsize); 469 } 470 471 if (ret) 472 return ret; 473 p -= newsize; len -= newsize; 474 475 break; 476 } 477 case A1_OP_TAG: { 478 const void *olddata = data; 479 size_t l, datalen; 480 481 data = DPOC(data, t->offset); 482 483 if (t->tt & A1_FLAG_OPTIONAL) { 484 void **el = (void **)data; 485 if (*el == NULL) { 486 data = olddata; 487 break; 488 } 489 data = *el; 490 } 491 492 ret = _asn1_encode(t->ptr, p, len, data, &datalen); 493 if (ret) 494 return ret; 495 496 len -= datalen; p -= datalen; 497 498 ret = der_put_length_and_tag(p, len, datalen, 499 A1_TAG_CLASS(t->tt), 500 A1_TAG_TYPE(t->tt), 501 A1_TAG_TAG(t->tt), &l); 502 if (ret) 503 return ret; 504 505 p -= l; len -= l; 506 507 data = olddata; 508 509 break; 510 } 511 case A1_OP_PARSE: { 512 unsigned int type = A1_PARSE_TYPE(t->tt); 513 size_t newsize; 514 const void *el = DPOC(data, t->offset); 515 516 if (type > sizeof(prim)/sizeof(prim[0])) { 517 ABORT_ON_ERROR(); 518 return ASN1_PARSE_ERROR; 519 } 520 521 ret = (prim[type].encode)(p, len, el, &newsize); 522 if (ret) 523 return ret; 524 p -= newsize; len -= newsize; 525 526 break; 527 } 528 case A1_OP_SETOF: { 529 const struct template_of *el = DPOC(data, t->offset); 530 size_t ellen = sizeofType(t->ptr); 531 struct heim_octet_string *val; 532 unsigned char *elptr = el->val; 533 size_t i, totallen; 534 535 if (el->len == 0) 536 break; 537 538 if (el->len > UINT_MAX/sizeof(val[0])) 539 return ERANGE; 540 541 val = malloc(sizeof(val[0]) * el->len); 542 if (val == NULL) 543 return ENOMEM; 544 545 for(totallen = 0, i = 0; i < el->len; i++) { 546 unsigned char *next; 547 size_t l; 548 549 val[i].length = _asn1_length(t->ptr, elptr); 550 val[i].data = malloc(val[i].length); 551 552 ret = _asn1_encode(t->ptr, DPO(val[i].data, val[i].length - 1), 553 val[i].length, elptr, &l); 554 if (ret) 555 break; 556 557 next = elptr + ellen; 558 if (next < elptr) { 559 ret = ASN1_OVERFLOW; 560 break; 561 } 562 elptr = next; 563 totallen += val[i].length; 564 } 565 if (ret == 0 && totallen > len) 566 ret = ASN1_OVERFLOW; 567 if (ret) { 568 do { 569 free(val[i].data); 570 } while(i-- > 0); 571 free(val); 572 return ret; 573 } 574 575 len -= totallen; 576 577 qsort(val, el->len, sizeof(val[0]), _heim_der_set_sort); 578 579 i = el->len - 1; 580 do { 581 p -= val[i].length; 582 memcpy(p + 1, val[i].data, val[i].length); 583 free(val[i].data); 584 } while(i-- > 0); 585 free(val); 586 587 break; 588 589 } 590 case A1_OP_SEQOF: { 591 struct template_of *el = DPO(data, t->offset); 592 size_t ellen = sizeofType(t->ptr); 593 size_t newsize; 594 unsigned int i; 595 unsigned char *elptr = el->val; 596 597 if (el->len == 0) 598 break; 599 600 elptr += ellen * (el->len - 1); 601 602 for (i = 0; i < el->len; i++) { 603 ret = _asn1_encode(t->ptr, p, len, 604 elptr, 605 &newsize); 606 if (ret) 607 return ret; 608 p -= newsize; len -= newsize; 609 elptr -= ellen; 610 } 611 612 break; 613 } 614 case A1_OP_BMEMBER: { 615 const struct asn1_template *bmember = t->ptr; 616 size_t size = bmember->offset; 617 size_t elements = A1_HEADER_LEN(bmember); 618 size_t pos; 619 unsigned char c = 0; 620 unsigned int bitset = 0; 621 int rfc1510 = (bmember->tt & A1_HBF_RFC1510); 622 623 bmember += elements; 624 625 if (rfc1510) 626 pos = 31; 627 else 628 pos = bmember->offset; 629 630 while (elements && len) { 631 while (bmember->offset / 8 < pos / 8) { 632 if (rfc1510 || bitset || c) { 633 if (len < 1) 634 return ASN1_OVERFLOW; 635 *p-- = c; len--; 636 } 637 c = 0; 638 pos -= 8; 639 } 640 bmember_put_bit(&c, data, bmember->offset, size, &bitset); 641 elements--; bmember--; 642 } 643 if (rfc1510 || bitset) { 644 if (len < 1) 645 return ASN1_OVERFLOW; 646 *p-- = c; len--; 647 } 648 649 if (len < 1) 650 return ASN1_OVERFLOW; 651 if (rfc1510 || bitset == 0) 652 *p-- = 0; 653 else 654 *p-- = bitset - 1; 655 656 len--; 657 658 break; 659 } 660 case A1_OP_CHOICE: { 661 const struct asn1_template *choice = t->ptr; 662 const unsigned int *element = DPOC(data, choice->offset); 663 size_t datalen; 664 const void *el; 665 666 if (*element > A1_HEADER_LEN(choice)) { 667 printf("element: %d\n", *element); 668 return ASN1_PARSE_ERROR; 669 } 670 671 if (*element == 0) { 672 ret += der_put_octet_string(p, len, 673 DPOC(data, choice->tt), &datalen); 674 } else { 675 choice += *element; 676 el = DPOC(data, choice->offset); 677 ret = _asn1_encode(choice->ptr, p, len, el, &datalen); 678 if (ret) 679 return ret; 680 } 681 len -= datalen; p -= datalen; 682 683 break; 684 } 685 default: 686 ABORT_ON_ERROR(); 687 } 688 t--; 689 elements--; 690 } 691 if (size) 692 *size = oldlen - len; 693 694 return 0; 695 } 696 697 size_t 698 _asn1_length(const struct asn1_template *t, const void *data) 699 { 700 size_t elements = A1_HEADER_LEN(t); 701 size_t ret = 0; 702 703 t += A1_HEADER_LEN(t); 704 705 while (elements) { 706 switch (t->tt & A1_OP_MASK) { 707 case A1_OP_TYPE: 708 case A1_OP_TYPE_EXTERN: { 709 const void *el = DPOC(data, t->offset); 710 711 if (t->tt & A1_FLAG_OPTIONAL) { 712 void **pel = (void **)el; 713 if (*pel == NULL) 714 break; 715 el = *pel; 716 } 717 718 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 719 ret += _asn1_length(t->ptr, el); 720 } else { 721 const struct asn1_type_func *f = t->ptr; 722 ret += (f->length)(el); 723 } 724 break; 725 } 726 case A1_OP_TAG: { 727 size_t datalen; 728 const void *olddata = data; 729 730 data = DPO(data, t->offset); 731 732 if (t->tt & A1_FLAG_OPTIONAL) { 733 void **el = (void **)data; 734 if (*el == NULL) { 735 data = olddata; 736 break; 737 } 738 data = *el; 739 } 740 datalen = _asn1_length(t->ptr, data); 741 ret += der_length_tag(A1_TAG_TAG(t->tt)) + der_length_len(datalen); 742 ret += datalen; 743 data = olddata; 744 break; 745 } 746 case A1_OP_PARSE: { 747 unsigned int type = A1_PARSE_TYPE(t->tt); 748 const void *el = DPOC(data, t->offset); 749 750 if (type > sizeof(prim)/sizeof(prim[0])) { 751 ABORT_ON_ERROR(); 752 break; 753 } 754 ret += (prim[type].length)(el); 755 break; 756 } 757 case A1_OP_SETOF: 758 case A1_OP_SEQOF: { 759 const struct template_of *el = DPOC(data, t->offset); 760 size_t ellen = sizeofType(t->ptr); 761 const unsigned char *element = el->val; 762 unsigned int i; 763 764 for (i = 0; i < el->len; i++) { 765 ret += _asn1_length(t->ptr, element); 766 element += ellen; 767 } 768 769 break; 770 } 771 case A1_OP_BMEMBER: { 772 const struct asn1_template *bmember = t->ptr; 773 size_t size = bmember->offset; 774 size_t elements = A1_HEADER_LEN(bmember); 775 int rfc1510 = (bmember->tt & A1_HBF_RFC1510); 776 777 if (rfc1510) { 778 ret += 5; 779 } else { 780 781 ret += 1; 782 783 bmember += elements; 784 785 while (elements) { 786 if (bmember_isset_bit(data, bmember->offset, size)) { 787 ret += (bmember->offset / 8) + 1; 788 break; 789 } 790 elements--; bmember--; 791 } 792 } 793 break; 794 } 795 case A1_OP_CHOICE: { 796 const struct asn1_template *choice = t->ptr; 797 const unsigned int *element = DPOC(data, choice->offset); 798 799 if (*element > A1_HEADER_LEN(choice)) 800 break; 801 802 if (*element == 0) { 803 ret += der_length_octet_string(DPOC(data, choice->tt)); 804 } else { 805 choice += *element; 806 ret += _asn1_length(choice->ptr, DPOC(data, choice->offset)); 807 } 808 break; 809 } 810 default: 811 ABORT_ON_ERROR(); 812 break; 813 } 814 elements--; 815 t--; 816 } 817 return ret; 818 } 819 820 void 821 _asn1_free(const struct asn1_template *t, void *data) 822 { 823 size_t elements = A1_HEADER_LEN(t); 824 825 if (t->tt & A1_HF_PRESERVE) 826 der_free_octet_string(data); 827 828 t++; 829 830 while (elements) { 831 switch (t->tt & A1_OP_MASK) { 832 case A1_OP_TYPE: 833 case A1_OP_TYPE_EXTERN: { 834 void *el = DPO(data, t->offset); 835 836 if (t->tt & A1_FLAG_OPTIONAL) { 837 void **pel = (void **)el; 838 if (*pel == NULL) 839 break; 840 el = *pel; 841 } 842 843 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 844 _asn1_free(t->ptr, el); 845 } else { 846 const struct asn1_type_func *f = t->ptr; 847 (f->release)(el); 848 } 849 if (t->tt & A1_FLAG_OPTIONAL) 850 free(el); 851 852 break; 853 } 854 case A1_OP_PARSE: { 855 unsigned int type = A1_PARSE_TYPE(t->tt); 856 void *el = DPO(data, t->offset); 857 858 if (type > sizeof(prim)/sizeof(prim[0])) { 859 ABORT_ON_ERROR(); 860 break; 861 } 862 (prim[type].release)(el); 863 break; 864 } 865 case A1_OP_TAG: { 866 void *el = DPO(data, t->offset); 867 868 if (t->tt & A1_FLAG_OPTIONAL) { 869 void **pel = (void **)el; 870 if (*pel == NULL) 871 break; 872 el = *pel; 873 } 874 875 _asn1_free(t->ptr, el); 876 877 if (t->tt & A1_FLAG_OPTIONAL) 878 free(el); 879 880 break; 881 } 882 case A1_OP_SETOF: 883 case A1_OP_SEQOF: { 884 struct template_of *el = DPO(data, t->offset); 885 size_t ellen = sizeofType(t->ptr); 886 unsigned char *element = el->val; 887 unsigned int i; 888 889 for (i = 0; i < el->len; i++) { 890 _asn1_free(t->ptr, element); 891 element += ellen; 892 } 893 free(el->val); 894 el->val = NULL; 895 el->len = 0; 896 897 break; 898 } 899 case A1_OP_BMEMBER: 900 break; 901 case A1_OP_CHOICE: { 902 const struct asn1_template *choice = t->ptr; 903 const unsigned int *element = DPOC(data, choice->offset); 904 905 if (*element > A1_HEADER_LEN(choice)) 906 break; 907 908 if (*element == 0) { 909 der_free_octet_string(DPO(data, choice->tt)); 910 } else { 911 choice += *element; 912 _asn1_free(choice->ptr, DPO(data, choice->offset)); 913 } 914 break; 915 } 916 default: 917 ABORT_ON_ERROR(); 918 break; 919 } 920 t++; 921 elements--; 922 } 923 } 924 925 int 926 _asn1_copy(const struct asn1_template *t, const void *from, void *to) 927 { 928 size_t elements = A1_HEADER_LEN(t); 929 int ret = 0; 930 int preserve = (t->tt & A1_HF_PRESERVE); 931 932 t++; 933 934 if (preserve) { 935 ret = der_copy_octet_string(from, to); 936 if (ret) 937 return ret; 938 } 939 940 while (elements) { 941 switch (t->tt & A1_OP_MASK) { 942 case A1_OP_TYPE: 943 case A1_OP_TYPE_EXTERN: { 944 const void *fel = DPOC(from, t->offset); 945 void *tel = DPO(to, t->offset); 946 void **ptel = (void **)tel; 947 size_t size; 948 949 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 950 size = sizeofType(t->ptr); 951 } else { 952 const struct asn1_type_func *f = t->ptr; 953 size = f->size; 954 } 955 956 if (t->tt & A1_FLAG_OPTIONAL) { 957 void **pfel = (void **)fel; 958 if (*pfel == NULL) 959 break; 960 fel = *pfel; 961 962 tel = *ptel = calloc(1, size); 963 if (tel == NULL) 964 return ENOMEM; 965 } 966 967 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 968 ret = _asn1_copy(t->ptr, fel, tel); 969 } else { 970 const struct asn1_type_func *f = t->ptr; 971 ret = (f->copy)(fel, tel); 972 } 973 974 if (ret) { 975 if (t->tt & A1_FLAG_OPTIONAL) { 976 free(*ptel); 977 *ptel = NULL; 978 } 979 return ret; 980 } 981 break; 982 } 983 case A1_OP_PARSE: { 984 unsigned int type = A1_PARSE_TYPE(t->tt); 985 const void *fel = DPOC(from, t->offset); 986 void *tel = DPO(to, t->offset); 987 988 if (type > sizeof(prim)/sizeof(prim[0])) { 989 ABORT_ON_ERROR(); 990 return ASN1_PARSE_ERROR; 991 } 992 ret = (prim[type].copy)(fel, tel); 993 if (ret) 994 return ret; 995 break; 996 } 997 case A1_OP_TAG: { 998 const void *oldfrom = from; 999 void *oldto = to; 1000 void **tel = NULL; 1001 1002 from = DPOC(from, t->offset); 1003 to = DPO(to, t->offset); 1004 1005 if (t->tt & A1_FLAG_OPTIONAL) { 1006 void **fel = (void **)from; 1007 tel = (void **)to; 1008 if (*fel == NULL) { 1009 from = oldfrom; 1010 to = oldto; 1011 break; 1012 } 1013 from = *fel; 1014 1015 to = *tel = calloc(1, sizeofType(t->ptr)); 1016 if (to == NULL) 1017 return ENOMEM; 1018 } 1019 1020 ret = _asn1_copy(t->ptr, from, to); 1021 if (ret) { 1022 if (t->tt & A1_FLAG_OPTIONAL) { 1023 free(*tel); 1024 *tel = NULL; 1025 } 1026 return ret; 1027 } 1028 1029 from = oldfrom; 1030 to = oldto; 1031 1032 break; 1033 } 1034 case A1_OP_SETOF: 1035 case A1_OP_SEQOF: { 1036 const struct template_of *fel = DPOC(from, t->offset); 1037 struct template_of *tel = DPO(to, t->offset); 1038 size_t ellen = sizeofType(t->ptr); 1039 unsigned int i; 1040 1041 tel->val = calloc(fel->len, ellen); 1042 if (tel->val == NULL) 1043 return ENOMEM; 1044 1045 tel->len = fel->len; 1046 1047 for (i = 0; i < fel->len; i++) { 1048 ret = _asn1_copy(t->ptr, 1049 DPOC(fel->val, (i * ellen)), 1050 DPO(tel->val, (i *ellen))); 1051 if (ret) 1052 return ret; 1053 } 1054 break; 1055 } 1056 case A1_OP_BMEMBER: { 1057 const struct asn1_template *bmember = t->ptr; 1058 size_t size = bmember->offset; 1059 memcpy(to, from, size); 1060 break; 1061 } 1062 case A1_OP_CHOICE: { 1063 const struct asn1_template *choice = t->ptr; 1064 const unsigned int *felement = DPOC(from, choice->offset); 1065 unsigned int *telement = DPO(to, choice->offset); 1066 1067 if (*felement > A1_HEADER_LEN(choice)) 1068 return ASN1_PARSE_ERROR; 1069 1070 *telement = *felement; 1071 1072 if (*felement == 0) { 1073 ret = der_copy_octet_string(DPOC(from, choice->tt), DPO(to, choice->tt)); 1074 } else { 1075 choice += *felement; 1076 ret = _asn1_copy(choice->ptr, 1077 DPOC(from, choice->offset), 1078 DPO(to, choice->offset)); 1079 } 1080 if (ret) 1081 return ret; 1082 break; 1083 } 1084 default: 1085 ABORT_ON_ERROR(); 1086 break; 1087 } 1088 t++; 1089 elements--; 1090 } 1091 return 0; 1092 } 1093 1094 int 1095 _asn1_decode_top(const struct asn1_template *t, unsigned flags, const unsigned char *p, size_t len, void *data, size_t *size) 1096 { 1097 int ret; 1098 memset(data, 0, t->offset); 1099 ret = _asn1_decode(t, flags, p, len, data, size); 1100 if (ret) { 1101 _asn1_free(t, data); 1102 memset(data, 0, t->offset); 1103 } 1104 1105 return ret; 1106 } 1107 1108 int 1109 _asn1_copy_top(const struct asn1_template *t, const void *from, void *to) 1110 { 1111 int ret; 1112 memset(to, 0, t->offset); 1113 ret = _asn1_copy(t, from, to); 1114 if (ret) { 1115 _asn1_free(t, to); 1116 memset(to, 0, t->offset); 1117 } 1118 return ret; 1119 } 1120