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