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 - 2010 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 39struct asn1_type_func asn1_template_prim[A1T_NUM_ENTRY] = { 40#define el(name, type) { \ 41 (asn1_type_encode)der_put_##name, \ 42 (asn1_type_decode)der_get_##name, \ 43 (asn1_type_length)der_length_##name, \ 44 (asn1_type_copy)der_copy_##name, \ 45 (asn1_type_release)der_free_##name, \ 46 sizeof(type) \ 47 } 48#define elber(name, type) { \ 49 (asn1_type_encode)der_put_##name, \ 50 (asn1_type_decode)der_get_##name##_ber, \ 51 (asn1_type_length)der_length_##name, \ 52 (asn1_type_copy)der_copy_##name, \ 53 (asn1_type_release)der_free_##name, \ 54 sizeof(type) \ 55 } 56 el(integer, int), 57 el(heim_integer, heim_integer), 58 el(integer, int), 59 el(unsigned, unsigned), 60 el(general_string, heim_general_string), 61 el(octet_string, heim_octet_string), 62 elber(octet_string, heim_octet_string), 63 el(ia5_string, heim_ia5_string), 64 el(bmp_string, heim_bmp_string), 65 el(universal_string, heim_universal_string), 66 el(printable_string, heim_printable_string), 67 el(visible_string, heim_visible_string), 68 el(utf8string, heim_utf8_string), 69 el(generalized_time, time_t), 70 el(utctime, time_t), 71 el(bit_string, heim_bit_string), 72 { (asn1_type_encode)der_put_boolean, (asn1_type_decode)der_get_boolean, 73 (asn1_type_length)der_length_boolean, (asn1_type_copy)der_copy_integer, 74 (asn1_type_release)der_free_integer, sizeof(int) 75 }, 76 el(oid, heim_oid), 77 el(general_string, heim_general_string), 78#undef el 79#undef elber 80}; 81 82size_t 83_asn1_sizeofType(const struct asn1_template *t) 84{ 85 return t->offset; 86} 87 88/* 89 * Here is abstraction to not so well evil fact of bit fields in C, 90 * they are endian dependent, so when getting and setting bits in the 91 * host local structure we need to know the endianness of the host. 92 * 93 * Its not the first time in Heimdal this have bitten us, and some day 94 * we'll grow up and use #defined constant, but bit fields are still 95 * so pretty and shiny. 96 */ 97 98static void 99_asn1_bmember_get_bit(const unsigned char *p, void *data, 100 unsigned int bit, size_t size) 101{ 102 unsigned int localbit = bit % 8; 103 if ((*p >> (7 - localbit)) & 1) { 104#ifdef WORDS_BIGENDIAN 105 *(unsigned int *)data |= (1 << ((size * 8) - bit - 1)); 106#else 107 *(unsigned int *)data |= (1 << bit); 108#endif 109 } 110} 111 112int 113_asn1_bmember_isset_bit(const void *data, unsigned int bit, size_t size) 114{ 115#ifdef WORDS_BIGENDIAN 116 if ((*(unsigned int *)data) & (1 << ((size * 8) - bit - 1))) 117 return 1; 118 return 0; 119#else 120 if ((*(unsigned int *)data) & (1 << bit)) 121 return 1; 122 return 0; 123#endif 124} 125 126void 127_asn1_bmember_put_bit(unsigned char *p, const void *data, unsigned int bit, 128 size_t size, unsigned int *bitset) 129{ 130 unsigned int localbit = bit % 8; 131 132 if (_asn1_bmember_isset_bit(data, bit, size)) { 133 *p |= (1 << (7 - localbit)); 134 if (*bitset == 0) 135 *bitset = (7 - localbit) + 1; 136 } 137} 138 139int 140_asn1_decode(const struct asn1_template *t, unsigned flags, 141 const unsigned char *p, size_t len, void *data, size_t *size) 142{ 143 size_t elements = A1_HEADER_LEN(t); 144 size_t oldlen = len; 145 int ret = 0; 146 const unsigned char *startp = NULL; 147 unsigned int template_flags = t->tt; 148 149 /* skip over header */ 150 t++; 151 152 if (template_flags & A1_HF_PRESERVE) 153 startp = p; 154 155 while (elements) { 156 switch (t->tt & A1_OP_MASK) { 157 case A1_OP_TYPE: 158 case A1_OP_TYPE_EXTERN: { 159 size_t newsize, elsize; 160 void *el = DPO(data, t->offset); 161 void **pel = (void **)el; 162 163 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 164 elsize = _asn1_sizeofType(t->ptr); 165 } else { 166 const struct asn1_type_func *f = t->ptr; 167 elsize = f->size; 168 } 169 170 if (t->tt & A1_FLAG_OPTIONAL) { 171 *pel = calloc(1, elsize); 172 if (*pel == NULL) 173 return ENOMEM; 174 el = *pel; 175 } 176 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 177 ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize); 178 } else { 179 const struct asn1_type_func *f = t->ptr; 180 ret = (f->decode)(p, len, el, &newsize); 181 } 182 if (ret) { 183 if (t->tt & A1_FLAG_OPTIONAL) { 184 free(*pel); 185 *pel = NULL; 186 break; 187 } 188 return ret; 189 } 190 p += newsize; len -= newsize; 191 192 break; 193 } 194 case A1_OP_TAG: { 195 Der_type dertype; 196 size_t newsize; 197 size_t datalen, l; 198 void *olddata = data; 199 int is_indefinite = 0; 200 int subflags = flags; 201 202 ret = der_match_tag_and_length(p, len, A1_TAG_CLASS(t->tt), 203 &dertype, A1_TAG_TAG(t->tt), 204 &datalen, &l); 205 if (ret) { 206 if (t->tt & A1_FLAG_OPTIONAL) 207 break; 208 return ret; 209 } 210 211 p += l; len -= l; 212 213 /* 214 * Only allow indefinite encoding for OCTET STRING and BER 215 * for now. Should handle BIT STRING too. 216 */ 217 218 if (dertype != A1_TAG_TYPE(t->tt) && (flags & A1_PF_ALLOW_BER)) { 219 const struct asn1_template *subtype = t->ptr; 220 subtype++; /* skip header */ 221 222 if (((subtype->tt & A1_OP_MASK) == A1_OP_PARSE) && 223 A1_PARSE_TYPE(subtype->tt) == A1T_OCTET_STRING) 224 subflags |= A1_PF_INDEFINTE; 225 } 226 227 if (datalen == ASN1_INDEFINITE) { 228 if ((flags & A1_PF_ALLOW_BER) == 0) 229 return ASN1_GOT_BER; 230 is_indefinite = 1; 231 datalen = len; 232 if (datalen < 2) 233 return ASN1_OVERRUN; 234 /* hide EndOfContent for sub-decoder, catching it below */ 235 datalen -= 2; 236 } else if (datalen > len) 237 return ASN1_OVERRUN; 238 239 data = DPO(data, t->offset); 240 241 if (t->tt & A1_FLAG_OPTIONAL) { 242 void **el = (void **)data; 243 size_t ellen = _asn1_sizeofType(t->ptr); 244 245 *el = calloc(1, ellen); 246 if (*el == NULL) 247 return ENOMEM; 248 data = *el; 249 } 250 251 ret = _asn1_decode(t->ptr, subflags, p, datalen, data, &newsize); 252 if (ret) 253 return ret; 254 255 if (is_indefinite) { 256 /* If we use indefinite encoding, the newsize is the datasize. */ 257 datalen = newsize; 258 } else if (newsize != datalen) { 259 /* Check for hidden data that might be after the real tag */ 260 return ASN1_EXTRA_DATA; 261 } 262 263 len -= datalen; 264 p += datalen; 265 266 /* 267 * Indefinite encoding needs a trailing EndOfContent, 268 * check for that. 269 */ 270 if (is_indefinite) { 271 ret = der_match_tag_and_length(p, len, ASN1_C_UNIV, 272 &dertype, UT_EndOfContent, 273 &datalen, &l); 274 if (ret) 275 return ret; 276 if (dertype != PRIM) 277 return ASN1_BAD_ID; 278 if (datalen != 0) 279 return ASN1_INDEF_EXTRA_DATA; 280 p += l; len -= l; 281 } 282 data = olddata; 283 284 break; 285 } 286 case A1_OP_PARSE: { 287 unsigned int type = A1_PARSE_TYPE(t->tt); 288 size_t newsize; 289 void *el = DPO(data, t->offset); 290 291 /* 292 * INDEFINITE primitive types are one element after the 293 * same type but non-INDEFINITE version. 294 */ 295 if (flags & A1_PF_INDEFINTE) 296 type++; 297 298 if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) { 299 ABORT_ON_ERROR(); 300 return ASN1_PARSE_ERROR; 301 } 302 303 ret = (asn1_template_prim[type].decode)(p, len, el, &newsize); 304 if (ret) 305 return ret; 306 p += newsize; len -= newsize; 307 308 break; 309 } 310 case A1_OP_SETOF: 311 case A1_OP_SEQOF: { 312 struct template_of *el = DPO(data, t->offset); 313 size_t newsize; 314 size_t ellen = _asn1_sizeofType(t->ptr); 315 size_t vallength = 0; 316 317 while (len > 0) { 318 void *tmp; 319 size_t newlen = vallength + ellen; 320 if (vallength > newlen) 321 return ASN1_OVERFLOW; 322 323 tmp = realloc(el->val, newlen); 324 if (tmp == NULL) 325 return ENOMEM; 326 327 memset(DPO(tmp, vallength), 0, ellen); 328 el->val = tmp; 329 el->len++; 330 331 ret = _asn1_decode(t->ptr, flags & (~A1_PF_INDEFINTE), p, len, 332 DPO(el->val, vallength), &newsize); 333 if (ret) 334 return ret; 335 vallength = newlen; 336 p += newsize; len -= newsize; 337 } 338 339 break; 340 } 341 case A1_OP_BMEMBER: { 342 const struct asn1_template *bmember = t->ptr; 343 size_t bsize = bmember->offset; 344 size_t belements = A1_HEADER_LEN(bmember); 345 size_t pos = 0; 346 347 bmember++; 348 349 memset(data, 0, bsize); 350 351 if (len < 1) 352 return ASN1_OVERRUN; 353 p++; len--; 354 355 while (belements && len) { 356 while (bmember->offset / 8 > pos / 8) { 357 if (len < 1) 358 break; 359 p++; len--; 360 pos += 8; 361 } 362 if (len) { 363 _asn1_bmember_get_bit(p, data, bmember->offset, bsize); 364 belements--; bmember++; 365 } 366 } 367 len = 0; 368 break; 369 } 370 case A1_OP_CHOICE: { 371 const struct asn1_template *choice = t->ptr; 372 int *element = DPO(data, choice->offset); 373 size_t datalen; 374 unsigned int i; 375 376 /* provide a invalid value as default (0, so same as memset) */ 377 *element = ASN1_CHOICE_INVALID; 378 379 for (i = 1; i < A1_HEADER_LEN(choice) + 1; i++) { 380 /* should match first tag instead, store it in choice.tt */ 381 ret = _asn1_decode(choice[i].ptr, 0, p, len, 382 DPO(data, choice[i].offset), &datalen); 383 if (ret == 0) { 384 *element = i; 385 p += datalen; len -= datalen; 386 break; 387 } else if (ret != ASN1_BAD_ID && ret != ASN1_MISPLACED_FIELD && ret != ASN1_MISSING_FIELD) { 388 _asn1_free_top(choice[i].ptr, DPO(data, choice[i].offset)); 389 return ret; 390 } 391 _asn1_free_top(choice[i].ptr, DPO(data, choice[i].offset)); 392 } 393 if (i >= A1_HEADER_LEN(choice) + 1) { 394 if (choice->tt == 0) 395 return ASN1_BAD_ID; 396 397 *element = ASN1_CHOICE_ELLIPSIS; 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 441int 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(asn1_template_prim)/sizeof(asn1_template_prim[0])) { 517 ABORT_ON_ERROR(); 518 return ASN1_PARSE_ERROR; 519 } 520 521 ret = (asn1_template_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 = _asn1_sizeofType(t->ptr); 531 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 = calloc(el->len, sizeof(val[0])); 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 if (val[i].length) { 551 val[i].data = malloc(val[i].length); 552 if (val[i].data == NULL) { 553 ret = ENOMEM; 554 break; 555 } 556 } 557 558 ret = _asn1_encode(t->ptr, DPO(val[i].data, val[i].length - 1), 559 val[i].length, elptr, &l); 560 if (ret) 561 break; 562 563 next = elptr + ellen; 564 if (next < elptr) { 565 ret = ASN1_OVERFLOW; 566 break; 567 } 568 elptr = next; 569 totallen += val[i].length; 570 } 571 if (ret == 0 && totallen > len) 572 ret = ASN1_OVERFLOW; 573 if (ret) { 574 for (i = 0; i < el->len; i++) 575 free(val[i].data); 576 free(val); 577 return ret; 578 } 579 580 len -= totallen; 581 582 qsort(val, el->len, sizeof(val[0]), _heim_der_set_sort); 583 584 i = el->len - 1; 585 do { 586 p -= val[i].length; 587 memcpy(p + 1, val[i].data, val[i].length); 588 free(val[i].data); 589 } while(i-- > 0); 590 free(val); 591 592 break; 593 594 } 595 case A1_OP_SEQOF: { 596 struct template_of *el = DPO(data, t->offset); 597 size_t ellen = _asn1_sizeofType(t->ptr); 598 size_t newsize; 599 unsigned int i; 600 unsigned char *elptr = el->val; 601 602 if (el->len == 0) 603 break; 604 605 elptr += ellen * (el->len - 1); 606 607 for (i = 0; i < el->len; i++) { 608 ret = _asn1_encode(t->ptr, p, len, 609 elptr, 610 &newsize); 611 if (ret) 612 return ret; 613 p -= newsize; len -= newsize; 614 elptr -= ellen; 615 } 616 617 break; 618 } 619 case A1_OP_BMEMBER: { 620 const struct asn1_template *bmember = t->ptr; 621 size_t bsize = bmember->offset; 622 size_t belements = A1_HEADER_LEN(bmember); 623 size_t pos; 624 unsigned char c = 0; 625 unsigned int bitset = 0; 626 int rfc1510 = (bmember->tt & A1_HBF_RFC1510); 627 628 bmember += belements; 629 630 if (rfc1510) 631 pos = 31; 632 else 633 pos = bmember->offset; 634 635 while (belements && len) { 636 while (bmember->offset / 8 < pos / 8) { 637 if (rfc1510 || bitset || c) { 638 if (len < 1) 639 return ASN1_OVERFLOW; 640 *p-- = c; len--; 641 } 642 c = 0; 643 pos -= 8; 644 } 645 _asn1_bmember_put_bit(&c, data, bmember->offset, bsize, &bitset); 646 belements--; bmember--; 647 } 648 if (rfc1510 || bitset) { 649 if (len < 1) 650 return ASN1_OVERFLOW; 651 *p-- = c; len--; 652 } 653 654 if (len < 1) 655 return ASN1_OVERFLOW; 656 if (rfc1510 || bitset == 0) 657 *p-- = 0; 658 else 659 *p-- = bitset - 1; 660 661 len--; 662 663 break; 664 } 665 case A1_OP_CHOICE: { 666 const struct asn1_template *choice = t->ptr; 667 const int *element = DPOC(data, choice->offset); 668 size_t datalen; 669 const void *el; 670 671 if (*element == ASN1_CHOICE_INVALID || *element > (int)A1_HEADER_LEN(choice)) { 672 ABORT_ON_ERROR(); 673 return ASN1_PARSE_ERROR; 674 } 675 676 if (*element == ASN1_CHOICE_ELLIPSIS) { 677 ret += der_put_octet_string(p, len, 678 DPOC(data, choice->tt), &datalen); 679 } else { 680 choice += *element; 681 el = DPOC(data, choice->offset); 682 ret = _asn1_encode(choice->ptr, p, len, el, &datalen); 683 if (ret) 684 return ret; 685 } 686 len -= datalen; p -= datalen; 687 688 break; 689 } 690 default: 691 ABORT_ON_ERROR(); 692 } 693 t--; 694 elements--; 695 } 696 if (size) 697 *size = oldlen - len; 698 699 return 0; 700} 701 702size_t 703_asn1_length(const struct asn1_template *t, const void *data) 704{ 705 size_t elements = A1_HEADER_LEN(t); 706 size_t ret = 0; 707 708 t += A1_HEADER_LEN(t); 709 710 while (elements) { 711 switch (t->tt & A1_OP_MASK) { 712 case A1_OP_TYPE: 713 case A1_OP_TYPE_EXTERN: { 714 const void *el = DPOC(data, t->offset); 715 716 if (t->tt & A1_FLAG_OPTIONAL) { 717 void **pel = (void **)el; 718 if (*pel == NULL) 719 break; 720 el = *pel; 721 } 722 723 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 724 ret += _asn1_length(t->ptr, el); 725 } else { 726 const struct asn1_type_func *f = t->ptr; 727 ret += (f->length)(el); 728 } 729 break; 730 } 731 case A1_OP_TAG: { 732 size_t datalen; 733 const void *olddata = data; 734 735 data = DPO(data, t->offset); 736 737 if (t->tt & A1_FLAG_OPTIONAL) { 738 void **el = (void **)data; 739 if (*el == NULL) { 740 data = olddata; 741 break; 742 } 743 data = *el; 744 } 745 datalen = _asn1_length(t->ptr, data); 746 ret += der_length_tag(A1_TAG_TAG(t->tt)) + der_length_len(datalen); 747 ret += datalen; 748 data = olddata; 749 break; 750 } 751 case A1_OP_PARSE: { 752 unsigned int type = A1_PARSE_TYPE(t->tt); 753 const void *el = DPOC(data, t->offset); 754 755 if (type > sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) { 756 ABORT_ON_ERROR(); 757 break; 758 } 759 ret += (asn1_template_prim[type].length)(el); 760 break; 761 } 762 case A1_OP_SETOF: 763 case A1_OP_SEQOF: { 764 const struct template_of *el = DPOC(data, t->offset); 765 size_t ellen = _asn1_sizeofType(t->ptr); 766 const unsigned char *element = el->val; 767 unsigned int i; 768 769 for (i = 0; i < el->len; i++) { 770 ret += _asn1_length(t->ptr, element); 771 element += ellen; 772 } 773 774 break; 775 } 776 case A1_OP_BMEMBER: { 777 const struct asn1_template *bmember = t->ptr; 778 size_t size = bmember->offset; 779 size_t belements = A1_HEADER_LEN(bmember); 780 int rfc1510 = (bmember->tt & A1_HBF_RFC1510); 781 782 if (rfc1510) { 783 ret += 5; 784 } else { 785 786 ret += 1; 787 788 bmember += belements; 789 790 while (belements) { 791 if (_asn1_bmember_isset_bit(data, bmember->offset, size)) { 792 ret += (bmember->offset / 8) + 1; 793 break; 794 } 795 belements--; bmember--; 796 } 797 } 798 break; 799 } 800 case A1_OP_CHOICE: { 801 const struct asn1_template *choice = t->ptr; 802 const int *element = DPOC(data, choice->offset); 803 804 if (*element == ASN1_CHOICE_INVALID || *element > (int)A1_HEADER_LEN(choice)) { 805 ABORT_ON_ERROR(); 806 break; 807 } 808 809 if (*element == ASN1_CHOICE_ELLIPSIS) { 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 827void 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 int *element = DPOC(data, choice->offset); 911 912 if (*element == ASN1_CHOICE_INVALID) 913 break; 914 915 if (*element > (int)A1_HEADER_LEN(choice)) { 916 ABORT_ON_ERROR(); 917 break; 918 } 919 920 if (*element == ASN1_CHOICE_ELLIPSIS) { 921 der_free_octet_string(DPO(data, choice->tt)); 922 } else { 923 choice += *element; 924 _asn1_free(choice->ptr, DPO(data, choice->offset)); 925 } 926 break; 927 } 928 default: 929 ABORT_ON_ERROR(); 930 break; 931 } 932 t++; 933 elements--; 934 } 935} 936 937int 938_asn1_copy(const struct asn1_template *t, const void *from, void *to) 939{ 940 size_t elements = A1_HEADER_LEN(t); 941 int ret = 0; 942 int preserve = (t->tt & A1_HF_PRESERVE); 943 944 t++; 945 946 if (preserve) { 947 ret = der_copy_octet_string(from, to); 948 if (ret) 949 return ret; 950 } 951 952 while (elements) { 953 switch (t->tt & A1_OP_MASK) { 954 case A1_OP_TYPE: 955 case A1_OP_TYPE_EXTERN: { 956 const void *fel = DPOC(from, t->offset); 957 void *tel = DPO(to, t->offset); 958 void **ptel = (void **)tel; 959 size_t size; 960 961 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 962 size = _asn1_sizeofType(t->ptr); 963 } else { 964 const struct asn1_type_func *f = t->ptr; 965 size = f->size; 966 } 967 968 if (t->tt & A1_FLAG_OPTIONAL) { 969 void **pfel = (void **)fel; 970 if (*pfel == NULL) 971 break; 972 fel = *pfel; 973 974 tel = *ptel = calloc(1, size); 975 if (tel == NULL) 976 return ENOMEM; 977 } 978 979 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 980 ret = _asn1_copy(t->ptr, fel, tel); 981 } else { 982 const struct asn1_type_func *f = t->ptr; 983 ret = (f->copy)(fel, tel); 984 } 985 986 if (ret) { 987 if (t->tt & A1_FLAG_OPTIONAL) { 988 free(*ptel); 989 *ptel = NULL; 990 } 991 return ret; 992 } 993 break; 994 } 995 case A1_OP_PARSE: { 996 unsigned int type = A1_PARSE_TYPE(t->tt); 997 const void *fel = DPOC(from, t->offset); 998 void *tel = DPO(to, t->offset); 999 1000 if (type > sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) { 1001 ABORT_ON_ERROR(); 1002 return ASN1_PARSE_ERROR; 1003 } 1004 ret = (asn1_template_prim[type].copy)(fel, tel); 1005 if (ret) 1006 return ret; 1007 break; 1008 } 1009 case A1_OP_TAG: { 1010 const void *oldfrom = from; 1011 void *oldto = to; 1012 void **tel = NULL; 1013 1014 from = DPOC(from, t->offset); 1015 to = DPO(to, t->offset); 1016 1017 if (t->tt & A1_FLAG_OPTIONAL) { 1018 void **fel = (void **)from; 1019 tel = (void **)to; 1020 if (*fel == NULL) { 1021 from = oldfrom; 1022 to = oldto; 1023 break; 1024 } 1025 from = *fel; 1026 1027 to = *tel = calloc(1, _asn1_sizeofType(t->ptr)); 1028 if (to == NULL) 1029 return ENOMEM; 1030 } 1031 1032 ret = _asn1_copy(t->ptr, from, to); 1033 if (ret) { 1034 if (tel) { 1035 free(*tel); 1036 *tel = NULL; 1037 } 1038 return ret; 1039 } 1040 1041 from = oldfrom; 1042 to = oldto; 1043 1044 break; 1045 } 1046 case A1_OP_SETOF: 1047 case A1_OP_SEQOF: { 1048 const struct template_of *fel = DPOC(from, t->offset); 1049 struct template_of *tel = DPO(to, t->offset); 1050 size_t ellen = _asn1_sizeofType(t->ptr); 1051 unsigned int i; 1052 1053 tel->val = calloc(fel->len, ellen); 1054 if (tel->val == NULL) 1055 return ENOMEM; 1056 1057 tel->len = fel->len; 1058 1059 for (i = 0; i < fel->len; i++) { 1060 ret = _asn1_copy(t->ptr, 1061 DPOC(fel->val, (i * ellen)), 1062 DPO(tel->val, (i *ellen))); 1063 if (ret) 1064 return ret; 1065 } 1066 break; 1067 } 1068 case A1_OP_BMEMBER: { 1069 const struct asn1_template *bmember = t->ptr; 1070 size_t size = bmember->offset; 1071 memcpy(to, from, size); 1072 break; 1073 } 1074 case A1_OP_CHOICE: { 1075 const struct asn1_template *choice = t->ptr; 1076 const int *felement = DPOC(from, choice->offset); 1077 int *telement = DPO(to, choice->offset); 1078 1079 if (*felement == ASN1_CHOICE_INVALID || *felement > (int)A1_HEADER_LEN(choice)) 1080 return ASN1_INVALID_CHOICE; 1081 1082 *telement = *felement; 1083 1084 if (*felement == ASN1_CHOICE_ELLIPSIS) { 1085 ret = der_copy_octet_string(DPOC(from, choice->tt), DPO(to, choice->tt)); 1086 } else { 1087 choice += *felement; 1088 ret = _asn1_copy(choice->ptr, 1089 DPOC(from, choice->offset), 1090 DPO(to, choice->offset)); 1091 } 1092 if (ret) 1093 return ret; 1094 break; 1095 } 1096 default: 1097 ABORT_ON_ERROR(); 1098 break; 1099 } 1100 t++; 1101 elements--; 1102 } 1103 return 0; 1104} 1105 1106int 1107_asn1_decode_top(const struct asn1_template *t, unsigned flags, const unsigned char *p, size_t len, void *data, size_t *size) 1108{ 1109 int ret; 1110 memset(data, 0, t->offset); 1111 ret = _asn1_decode(t, flags, p, len, data, size); 1112 if (ret) 1113 _asn1_free_top(t, data); 1114 1115 return ret; 1116} 1117 1118int 1119_asn1_copy_top(const struct asn1_template *t, const void *from, void *to) 1120{ 1121 int ret; 1122 memset(to, 0, t->offset); 1123 ret = _asn1_copy(t, from, to); 1124 if (ret) 1125 _asn1_free_top(t, to); 1126 1127 return ret; 1128} 1129 1130void 1131_asn1_free_top(const struct asn1_template *t, void *data) 1132{ 1133 _asn1_free(t, data); 1134 memset(data, 0, t->offset); 1135} 1136 1137#ifdef ASN1_CAPTURE_DATA 1138 1139void 1140_asn1_capture_data(const char *type, const unsigned char *p, size_t len) 1141{ 1142 static unsigned long count = 0; 1143 char *filename = NULL; 1144 int fd; 1145 1146 asprintf(&filename, "/tmp/asn1/heimdal-%s-%s-%d-%lu", getprogname(), type, getpid(), count++); 1147 if (filename == NULL) 1148 return; 1149 1150 fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0644); 1151 free(filename); 1152 if (fd < 0) 1153 return; 1154 write(fd, type, strlen(type) + 1); 1155 write(fd, p, len); 1156 close(fd); 1157} 1158 1159#endif 1160