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