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