1226031Sstas/* 2226031Sstas * Copyright (c) 2009 Kungliga Tekniska H��gskolan 3226031Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4226031Sstas * All rights reserved. 5226031Sstas * 6226031Sstas * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 7226031Sstas * 8226031Sstas * Redistribution and use in source and binary forms, with or without 9226031Sstas * modification, are permitted provided that the following conditions 10226031Sstas * are met: 11226031Sstas * 12226031Sstas * 1. Redistributions of source code must retain the above copyright 13226031Sstas * notice, this list of conditions and the following disclaimer. 14226031Sstas * 15226031Sstas * 2. Redistributions in binary form must reproduce the above copyright 16226031Sstas * notice, this list of conditions and the following disclaimer in the 17226031Sstas * documentation and/or other materials provided with the distribution. 18226031Sstas * 19226031Sstas * 3. Neither the name of the Institute nor the names of its contributors 20226031Sstas * may be used to endorse or promote products derived from this software 21226031Sstas * without specific prior written permission. 22226031Sstas * 23226031Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24226031Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25226031Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26226031Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27226031Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28226031Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29226031Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30226031Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31226031Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32226031Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33226031Sstas * SUCH DAMAGE. 34226031Sstas */ 35226031Sstas 36226031Sstas#include "der_locl.h" 37226031Sstas#include <com_err.h> 38226031Sstas 39226031Sstas#if 0 40226031Sstas#define ABORT_ON_ERROR() abort() 41226031Sstas#else 42226031Sstas#define ABORT_ON_ERROR() do { } while(0) 43226031Sstas#endif 44226031Sstas 45226031Sstas#define DPOC(data,offset) ((const void *)(((const unsigned char *)data) + offset)) 46226031Sstas#define DPO(data,offset) ((void *)(((unsigned char *)data) + offset)) 47226031Sstas 48226031Sstas 49226031Sstasstatic struct asn1_type_func prim[] = { 50226031Sstas#define el(name, type) { \ 51226031Sstas (asn1_type_encode)der_put_##name, \ 52226031Sstas (asn1_type_decode)der_get_##name, \ 53226031Sstas (asn1_type_length)der_length_##name, \ 54226031Sstas (asn1_type_copy)der_copy_##name, \ 55226031Sstas (asn1_type_release)der_free_##name, \ 56226031Sstas sizeof(type) \ 57226031Sstas } 58226031Sstas#define elber(name, type) { \ 59226031Sstas (asn1_type_encode)der_put_##name, \ 60226031Sstas (asn1_type_decode)der_get_##name##_ber, \ 61226031Sstas (asn1_type_length)der_length_##name, \ 62226031Sstas (asn1_type_copy)der_copy_##name, \ 63226031Sstas (asn1_type_release)der_free_##name, \ 64226031Sstas sizeof(type) \ 65226031Sstas } 66226031Sstas el(integer, int), 67226031Sstas el(heim_integer, heim_integer), 68226031Sstas el(integer, int), 69226031Sstas el(unsigned, unsigned), 70226031Sstas el(general_string, heim_general_string), 71226031Sstas el(octet_string, heim_octet_string), 72226031Sstas elber(octet_string, heim_octet_string), 73226031Sstas el(ia5_string, heim_ia5_string), 74226031Sstas el(bmp_string, heim_bmp_string), 75226031Sstas el(universal_string, heim_universal_string), 76226031Sstas el(printable_string, heim_printable_string), 77226031Sstas el(visible_string, heim_visible_string), 78226031Sstas el(utf8string, heim_utf8_string), 79226031Sstas el(generalized_time, time_t), 80226031Sstas el(utctime, time_t), 81226031Sstas el(bit_string, heim_bit_string), 82226031Sstas { (asn1_type_encode)der_put_boolean, (asn1_type_decode)der_get_boolean, 83226031Sstas (asn1_type_length)der_length_boolean, (asn1_type_copy)der_copy_integer, 84226031Sstas (asn1_type_release)der_free_integer, sizeof(int) 85226031Sstas }, 86226031Sstas el(oid, heim_oid), 87226031Sstas el(general_string, heim_general_string), 88226031Sstas#undef el 89226031Sstas#undef elber 90226031Sstas}; 91226031Sstas 92226031Sstasstatic size_t 93226031SstassizeofType(const struct asn1_template *t) 94226031Sstas{ 95226031Sstas return t->offset; 96226031Sstas} 97226031Sstas 98226031Sstas/* 99226031Sstas * Here is abstraction to not so well evil fact of bit fields in C, 100226031Sstas * they are endian dependent, so when getting and setting bits in the 101226031Sstas * host local structure we need to know the endianness of the host. 102226031Sstas * 103226031Sstas * Its not the first time in Heimdal this have bitten us, and some day 104226031Sstas * we'll grow up and use #defined constant, but bit fields are still 105226031Sstas * so pretty and shiny. 106226031Sstas */ 107226031Sstas 108226031Sstasstatic void 109226031Sstasbmember_get_bit(const unsigned char *p, void *data, 110226031Sstas unsigned int bit, size_t size) 111226031Sstas{ 112226031Sstas unsigned int localbit = bit % 8; 113226031Sstas if ((*p >> (7 - localbit)) & 1) { 114226031Sstas#ifdef WORDS_BIGENDIAN 115226031Sstas *(unsigned int *)data |= (1 << ((size * 8) - bit - 1)); 116226031Sstas#else 117226031Sstas *(unsigned int *)data |= (1 << bit); 118226031Sstas#endif 119226031Sstas } 120226031Sstas} 121226031Sstas 122226031Sstasstatic int 123226031Sstasbmember_isset_bit(const void *data, unsigned int bit, size_t size) 124226031Sstas{ 125226031Sstas#ifdef WORDS_BIGENDIAN 126226031Sstas if ((*(unsigned int *)data) & (1 << ((size * 8) - bit - 1))) 127226031Sstas return 1; 128226031Sstas return 0; 129226031Sstas#else 130226031Sstas if ((*(unsigned int *)data) & (1 << bit)) 131226031Sstas return 1; 132226031Sstas return 0; 133226031Sstas#endif 134226031Sstas} 135226031Sstas 136226031Sstasstatic void 137226031Sstasbmember_put_bit(unsigned char *p, const void *data, unsigned int bit, 138226031Sstas size_t size, unsigned int *bitset) 139226031Sstas{ 140226031Sstas unsigned int localbit = bit % 8; 141226031Sstas 142226031Sstas if (bmember_isset_bit(data, bit, size)) { 143226031Sstas *p |= (1 << (7 - localbit)); 144226031Sstas if (*bitset == 0) 145226031Sstas *bitset = (7 - localbit) + 1; 146226031Sstas } 147226031Sstas} 148226031Sstas 149226031Sstasint 150226031Sstas_asn1_decode(const struct asn1_template *t, unsigned flags, 151226031Sstas const unsigned char *p, size_t len, void *data, size_t *size) 152226031Sstas{ 153226031Sstas size_t elements = A1_HEADER_LEN(t); 154226031Sstas size_t oldlen = len; 155226031Sstas int ret = 0; 156226031Sstas const unsigned char *startp = NULL; 157226031Sstas unsigned int template_flags = t->tt; 158226031Sstas 159226031Sstas /* skip over header */ 160226031Sstas t++; 161226031Sstas 162226031Sstas if (template_flags & A1_HF_PRESERVE) 163226031Sstas startp = p; 164226031Sstas 165226031Sstas while (elements) { 166226031Sstas switch (t->tt & A1_OP_MASK) { 167226031Sstas case A1_OP_TYPE: 168226031Sstas case A1_OP_TYPE_EXTERN: { 169226031Sstas size_t newsize, size; 170226031Sstas void *el = DPO(data, t->offset); 171226031Sstas void **pel = (void **)el; 172226031Sstas 173226031Sstas if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 174226031Sstas size = sizeofType(t->ptr); 175226031Sstas } else { 176226031Sstas const struct asn1_type_func *f = t->ptr; 177226031Sstas size = f->size; 178226031Sstas } 179226031Sstas 180226031Sstas if (t->tt & A1_FLAG_OPTIONAL) { 181226031Sstas *pel = calloc(1, size); 182226031Sstas if (*pel == NULL) 183226031Sstas return ENOMEM; 184226031Sstas el = *pel; 185226031Sstas } 186226031Sstas if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 187226031Sstas ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize); 188226031Sstas } else { 189226031Sstas const struct asn1_type_func *f = t->ptr; 190226031Sstas ret = (f->decode)(p, len, el, &newsize); 191226031Sstas } 192226031Sstas if (ret) { 193226031Sstas if (t->tt & A1_FLAG_OPTIONAL) { 194226031Sstas free(*pel); 195226031Sstas *pel = NULL; 196226031Sstas break; 197226031Sstas } 198226031Sstas return ret; 199226031Sstas } 200226031Sstas p += newsize; len -= newsize; 201226031Sstas 202226031Sstas break; 203226031Sstas } 204226031Sstas case A1_OP_TAG: { 205226031Sstas Der_type dertype; 206226031Sstas size_t newsize; 207226031Sstas size_t datalen, l; 208226031Sstas void *olddata = data; 209226031Sstas int is_indefinite = 0; 210226031Sstas int subflags = flags; 211226031Sstas 212226031Sstas ret = der_match_tag_and_length(p, len, A1_TAG_CLASS(t->tt), 213226031Sstas &dertype, A1_TAG_TAG(t->tt), 214226031Sstas &datalen, &l); 215226031Sstas if (ret) { 216226031Sstas if (t->tt & A1_FLAG_OPTIONAL) 217226031Sstas break; 218226031Sstas return ret; 219226031Sstas } 220226031Sstas 221226031Sstas p += l; len -= l; 222226031Sstas 223226031Sstas /* 224226031Sstas * Only allow indefinite encoding for OCTET STRING and BER 225226031Sstas * for now. Should handle BIT STRING too. 226226031Sstas */ 227226031Sstas 228226031Sstas if (dertype != A1_TAG_TYPE(t->tt) && (flags & A1_PF_ALLOW_BER)) { 229226031Sstas const struct asn1_template *subtype = t->ptr; 230226031Sstas subtype++; /* skip header */ 231226031Sstas 232226031Sstas if (((subtype->tt & A1_OP_MASK) == A1_OP_PARSE) && 233226031Sstas A1_PARSE_TYPE(subtype->tt) == A1T_OCTET_STRING) 234226031Sstas subflags |= A1_PF_INDEFINTE; 235226031Sstas } 236226031Sstas 237226031Sstas if (datalen == ASN1_INDEFINITE) { 238226031Sstas if ((flags & A1_PF_ALLOW_BER) == 0) 239226031Sstas return ASN1_GOT_BER; 240226031Sstas is_indefinite = 1; 241226031Sstas datalen = len; 242226031Sstas if (datalen < 2) 243226031Sstas return ASN1_OVERRUN; 244226031Sstas /* hide EndOfContent for sub-decoder, catching it below */ 245226031Sstas datalen -= 2; 246226031Sstas } else if (datalen > len) 247226031Sstas return ASN1_OVERRUN; 248226031Sstas 249226031Sstas data = DPO(data, t->offset); 250226031Sstas 251226031Sstas if (t->tt & A1_FLAG_OPTIONAL) { 252226031Sstas void **el = (void **)data; 253226031Sstas size_t ellen = sizeofType(t->ptr); 254226031Sstas 255226031Sstas *el = calloc(1, ellen); 256226031Sstas if (*el == NULL) 257226031Sstas return ENOMEM; 258226031Sstas data = *el; 259226031Sstas } 260226031Sstas 261226031Sstas ret = _asn1_decode(t->ptr, subflags, p, datalen, data, &newsize); 262226031Sstas if (ret) 263226031Sstas return ret; 264226031Sstas 265226031Sstas if (newsize != datalen) 266226031Sstas return ASN1_EXTRA_DATA; 267226031Sstas 268226031Sstas len -= datalen; 269226031Sstas p += datalen; 270226031Sstas 271226031Sstas /* 272226031Sstas * Indefinite encoding needs a trailing EndOfContent, 273226031Sstas * check for that. 274226031Sstas */ 275226031Sstas if (is_indefinite) { 276226031Sstas ret = der_match_tag_and_length(p, len, ASN1_C_UNIV, 277226031Sstas &dertype, UT_EndOfContent, 278226031Sstas &datalen, &l); 279226031Sstas if (ret) 280226031Sstas return ret; 281226031Sstas if (dertype != PRIM) 282226031Sstas return ASN1_BAD_ID; 283226031Sstas if (datalen != 0) 284226031Sstas return ASN1_INDEF_EXTRA_DATA; 285226031Sstas p += l; len -= l; 286226031Sstas } 287226031Sstas data = olddata; 288226031Sstas 289226031Sstas break; 290226031Sstas } 291226031Sstas case A1_OP_PARSE: { 292226031Sstas unsigned int type = A1_PARSE_TYPE(t->tt); 293226031Sstas size_t newsize; 294226031Sstas void *el = DPO(data, t->offset); 295226031Sstas 296226031Sstas /* 297226031Sstas * INDEFINITE primitive types are one element after the 298226031Sstas * same type but non-INDEFINITE version. 299226031Sstas */ 300226031Sstas if (flags & A1_PF_INDEFINTE) 301226031Sstas type++; 302226031Sstas 303226031Sstas if (type >= sizeof(prim)/sizeof(prim[0])) { 304226031Sstas ABORT_ON_ERROR(); 305226031Sstas return ASN1_PARSE_ERROR; 306226031Sstas } 307226031Sstas 308226031Sstas ret = (prim[type].decode)(p, len, el, &newsize); 309226031Sstas if (ret) 310226031Sstas return ret; 311226031Sstas p += newsize; len -= newsize; 312226031Sstas 313226031Sstas break; 314226031Sstas } 315226031Sstas case A1_OP_SETOF: 316226031Sstas case A1_OP_SEQOF: { 317226031Sstas struct template_of *el = DPO(data, t->offset); 318226031Sstas size_t newsize; 319226031Sstas size_t ellen = sizeofType(t->ptr); 320226031Sstas size_t vallength = 0; 321226031Sstas 322226031Sstas while (len > 0) { 323226031Sstas void *tmp; 324226031Sstas size_t newlen = vallength + ellen; 325226031Sstas if (vallength > newlen) 326226031Sstas return ASN1_OVERFLOW; 327226031Sstas 328226031Sstas tmp = realloc(el->val, newlen); 329226031Sstas if (tmp == NULL) 330226031Sstas return ENOMEM; 331226031Sstas 332226031Sstas memset(DPO(tmp, vallength), 0, ellen); 333226031Sstas el->val = tmp; 334226031Sstas 335226031Sstas ret = _asn1_decode(t->ptr, flags & (~A1_PF_INDEFINTE), p, len, 336226031Sstas DPO(el->val, vallength), &newsize); 337226031Sstas if (ret) 338226031Sstas return ret; 339226031Sstas vallength = newlen; 340226031Sstas el->len++; 341226031Sstas p += newsize; len -= newsize; 342226031Sstas } 343226031Sstas 344226031Sstas break; 345226031Sstas } 346226031Sstas case A1_OP_BMEMBER: { 347226031Sstas const struct asn1_template *bmember = t->ptr; 348226031Sstas size_t size = bmember->offset; 349226031Sstas size_t elements = A1_HEADER_LEN(bmember); 350226031Sstas size_t pos = 0; 351226031Sstas 352226031Sstas bmember++; 353226031Sstas 354226031Sstas memset(data, 0, size); 355226031Sstas 356226031Sstas if (len < 1) 357226031Sstas return ASN1_OVERRUN; 358226031Sstas p++; len--; 359226031Sstas 360226031Sstas while (elements && len) { 361226031Sstas while (bmember->offset / 8 > pos / 8) { 362226031Sstas if (len < 1) 363226031Sstas break; 364226031Sstas p++; len--; 365226031Sstas pos += 8; 366226031Sstas } 367226031Sstas if (len) { 368226031Sstas bmember_get_bit(p, data, bmember->offset, size); 369226031Sstas elements--; bmember++; 370226031Sstas } 371226031Sstas } 372226031Sstas len = 0; 373226031Sstas break; 374226031Sstas } 375226031Sstas case A1_OP_CHOICE: { 376226031Sstas const struct asn1_template *choice = t->ptr; 377226031Sstas unsigned int *element = DPO(data, choice->offset); 378226031Sstas size_t datalen; 379226031Sstas unsigned int i; 380226031Sstas 381226031Sstas for (i = 1; i < A1_HEADER_LEN(choice) + 1; i++) { 382226031Sstas /* should match first tag instead, store it in choice.tt */ 383226031Sstas ret = _asn1_decode(choice[i].ptr, 0, p, len, 384226031Sstas DPO(data, choice[i].offset), &datalen); 385226031Sstas if (ret == 0) { 386226031Sstas *element = i; 387226031Sstas p += datalen; len -= datalen; 388226031Sstas break; 389226031Sstas } else if (ret != ASN1_BAD_ID && ret != ASN1_MISPLACED_FIELD && ret != ASN1_MISSING_FIELD) { 390226031Sstas return ret; 391226031Sstas } 392226031Sstas } 393226031Sstas if (i >= A1_HEADER_LEN(choice) + 1) { 394226031Sstas if (choice->tt == 0) 395226031Sstas return ASN1_BAD_ID; 396226031Sstas 397226031Sstas *element = 0; 398226031Sstas ret = der_get_octet_string(p, len, 399226031Sstas DPO(data, choice->tt), &datalen); 400226031Sstas if (ret) 401226031Sstas return ret; 402226031Sstas p += datalen; len -= datalen; 403226031Sstas } 404226031Sstas 405226031Sstas break; 406226031Sstas } 407226031Sstas default: 408226031Sstas ABORT_ON_ERROR(); 409226031Sstas return ASN1_PARSE_ERROR; 410226031Sstas } 411226031Sstas t++; 412226031Sstas elements--; 413226031Sstas } 414226031Sstas /* if we are using padding, eat up read of context */ 415226031Sstas if (template_flags & A1_HF_ELLIPSIS) 416226031Sstas len = 0; 417226031Sstas 418226031Sstas oldlen -= len; 419226031Sstas 420226031Sstas if (size) 421226031Sstas *size = oldlen; 422226031Sstas 423226031Sstas /* 424226031Sstas * saved the raw bits if asked for it, useful for signature 425226031Sstas * verification. 426226031Sstas */ 427226031Sstas if (startp) { 428226031Sstas heim_octet_string *save = data; 429226031Sstas 430226031Sstas save->data = malloc(oldlen); 431226031Sstas if (save->data == NULL) 432226031Sstas return ENOMEM; 433226031Sstas else { 434226031Sstas save->length = oldlen; 435226031Sstas memcpy(save->data, startp, oldlen); 436226031Sstas } 437226031Sstas } 438226031Sstas return 0; 439226031Sstas} 440226031Sstas 441226031Sstasint 442226031Sstas_asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const void *data, size_t *size) 443226031Sstas{ 444226031Sstas size_t elements = A1_HEADER_LEN(t); 445226031Sstas int ret = 0; 446226031Sstas size_t oldlen = len; 447226031Sstas 448226031Sstas t += A1_HEADER_LEN(t); 449226031Sstas 450226031Sstas while (elements) { 451226031Sstas switch (t->tt & A1_OP_MASK) { 452226031Sstas case A1_OP_TYPE: 453226031Sstas case A1_OP_TYPE_EXTERN: { 454226031Sstas size_t newsize; 455226031Sstas const void *el = DPOC(data, t->offset); 456226031Sstas 457226031Sstas if (t->tt & A1_FLAG_OPTIONAL) { 458226031Sstas void **pel = (void **)el; 459226031Sstas if (*pel == NULL) 460226031Sstas break; 461226031Sstas el = *pel; 462226031Sstas } 463226031Sstas 464226031Sstas if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 465226031Sstas ret = _asn1_encode(t->ptr, p, len, el, &newsize); 466226031Sstas } else { 467226031Sstas const struct asn1_type_func *f = t->ptr; 468226031Sstas ret = (f->encode)(p, len, el, &newsize); 469226031Sstas } 470226031Sstas 471226031Sstas if (ret) 472226031Sstas return ret; 473226031Sstas p -= newsize; len -= newsize; 474226031Sstas 475226031Sstas break; 476226031Sstas } 477226031Sstas case A1_OP_TAG: { 478226031Sstas const void *olddata = data; 479226031Sstas size_t l, datalen; 480226031Sstas 481226031Sstas data = DPOC(data, t->offset); 482226031Sstas 483226031Sstas if (t->tt & A1_FLAG_OPTIONAL) { 484226031Sstas void **el = (void **)data; 485226031Sstas if (*el == NULL) { 486226031Sstas data = olddata; 487226031Sstas break; 488226031Sstas } 489226031Sstas data = *el; 490226031Sstas } 491226031Sstas 492226031Sstas ret = _asn1_encode(t->ptr, p, len, data, &datalen); 493226031Sstas if (ret) 494226031Sstas return ret; 495226031Sstas 496226031Sstas len -= datalen; p -= datalen; 497226031Sstas 498226031Sstas ret = der_put_length_and_tag(p, len, datalen, 499226031Sstas A1_TAG_CLASS(t->tt), 500226031Sstas A1_TAG_TYPE(t->tt), 501226031Sstas A1_TAG_TAG(t->tt), &l); 502226031Sstas if (ret) 503226031Sstas return ret; 504226031Sstas 505226031Sstas p -= l; len -= l; 506226031Sstas 507226031Sstas data = olddata; 508226031Sstas 509226031Sstas break; 510226031Sstas } 511226031Sstas case A1_OP_PARSE: { 512226031Sstas unsigned int type = A1_PARSE_TYPE(t->tt); 513226031Sstas size_t newsize; 514226031Sstas const void *el = DPOC(data, t->offset); 515226031Sstas 516226031Sstas if (type > sizeof(prim)/sizeof(prim[0])) { 517226031Sstas ABORT_ON_ERROR(); 518226031Sstas return ASN1_PARSE_ERROR; 519226031Sstas } 520226031Sstas 521226031Sstas ret = (prim[type].encode)(p, len, el, &newsize); 522226031Sstas if (ret) 523226031Sstas return ret; 524226031Sstas p -= newsize; len -= newsize; 525226031Sstas 526226031Sstas break; 527226031Sstas } 528226031Sstas case A1_OP_SETOF: { 529226031Sstas const struct template_of *el = DPOC(data, t->offset); 530226031Sstas size_t ellen = sizeofType(t->ptr); 531226031Sstas struct heim_octet_string *val; 532226031Sstas unsigned char *elptr = el->val; 533226031Sstas size_t i, totallen; 534226031Sstas 535226031Sstas if (el->len == 0) 536226031Sstas break; 537226031Sstas 538226031Sstas if (el->len > UINT_MAX/sizeof(val[0])) 539226031Sstas return ERANGE; 540226031Sstas 541226031Sstas val = malloc(sizeof(val[0]) * el->len); 542226031Sstas if (val == NULL) 543226031Sstas return ENOMEM; 544226031Sstas 545226031Sstas for(totallen = 0, i = 0; i < el->len; i++) { 546226031Sstas unsigned char *next; 547226031Sstas size_t l; 548226031Sstas 549226031Sstas val[i].length = _asn1_length(t->ptr, elptr); 550226031Sstas val[i].data = malloc(val[i].length); 551226031Sstas 552226031Sstas ret = _asn1_encode(t->ptr, DPO(val[i].data, val[i].length - 1), 553226031Sstas val[i].length, elptr, &l); 554226031Sstas if (ret) 555226031Sstas break; 556226031Sstas 557226031Sstas next = elptr + ellen; 558226031Sstas if (next < elptr) { 559226031Sstas ret = ASN1_OVERFLOW; 560226031Sstas break; 561226031Sstas } 562226031Sstas elptr = next; 563226031Sstas totallen += val[i].length; 564226031Sstas } 565226031Sstas if (ret == 0 && totallen > len) 566226031Sstas ret = ASN1_OVERFLOW; 567226031Sstas if (ret) { 568226031Sstas do { 569226031Sstas free(val[i].data); 570226031Sstas } while(i-- > 0); 571226031Sstas free(val); 572226031Sstas return ret; 573226031Sstas } 574226031Sstas 575226031Sstas len -= totallen; 576226031Sstas 577226031Sstas qsort(val, el->len, sizeof(val[0]), _heim_der_set_sort); 578226031Sstas 579226031Sstas i = el->len - 1; 580226031Sstas do { 581226031Sstas p -= val[i].length; 582226031Sstas memcpy(p + 1, val[i].data, val[i].length); 583226031Sstas free(val[i].data); 584226031Sstas } while(i-- > 0); 585226031Sstas free(val); 586226031Sstas 587226031Sstas break; 588226031Sstas 589226031Sstas } 590226031Sstas case A1_OP_SEQOF: { 591226031Sstas struct template_of *el = DPO(data, t->offset); 592226031Sstas size_t ellen = sizeofType(t->ptr); 593226031Sstas size_t newsize; 594226031Sstas unsigned int i; 595226031Sstas unsigned char *elptr = el->val; 596226031Sstas 597226031Sstas if (el->len == 0) 598226031Sstas break; 599226031Sstas 600226031Sstas elptr += ellen * (el->len - 1); 601226031Sstas 602226031Sstas for (i = 0; i < el->len; i++) { 603226031Sstas ret = _asn1_encode(t->ptr, p, len, 604226031Sstas elptr, 605226031Sstas &newsize); 606226031Sstas if (ret) 607226031Sstas return ret; 608226031Sstas p -= newsize; len -= newsize; 609226031Sstas elptr -= ellen; 610226031Sstas } 611226031Sstas 612226031Sstas break; 613226031Sstas } 614226031Sstas case A1_OP_BMEMBER: { 615226031Sstas const struct asn1_template *bmember = t->ptr; 616226031Sstas size_t size = bmember->offset; 617226031Sstas size_t elements = A1_HEADER_LEN(bmember); 618226031Sstas size_t pos; 619226031Sstas unsigned char c = 0; 620226031Sstas unsigned int bitset = 0; 621226031Sstas int rfc1510 = (bmember->tt & A1_HBF_RFC1510); 622226031Sstas 623226031Sstas bmember += elements; 624226031Sstas 625226031Sstas if (rfc1510) 626226031Sstas pos = 31; 627226031Sstas else 628226031Sstas pos = bmember->offset; 629226031Sstas 630226031Sstas while (elements && len) { 631226031Sstas while (bmember->offset / 8 < pos / 8) { 632226031Sstas if (rfc1510 || bitset || c) { 633226031Sstas if (len < 1) 634226031Sstas return ASN1_OVERFLOW; 635226031Sstas *p-- = c; len--; 636226031Sstas } 637226031Sstas c = 0; 638226031Sstas pos -= 8; 639226031Sstas } 640226031Sstas bmember_put_bit(&c, data, bmember->offset, size, &bitset); 641226031Sstas elements--; bmember--; 642226031Sstas } 643226031Sstas if (rfc1510 || bitset) { 644226031Sstas if (len < 1) 645226031Sstas return ASN1_OVERFLOW; 646226031Sstas *p-- = c; len--; 647226031Sstas } 648226031Sstas 649226031Sstas if (len < 1) 650226031Sstas return ASN1_OVERFLOW; 651226031Sstas if (rfc1510 || bitset == 0) 652226031Sstas *p-- = 0; 653226031Sstas else 654226031Sstas *p-- = bitset - 1; 655226031Sstas 656226031Sstas len--; 657226031Sstas 658226031Sstas break; 659226031Sstas } 660226031Sstas case A1_OP_CHOICE: { 661226031Sstas const struct asn1_template *choice = t->ptr; 662226031Sstas const unsigned int *element = DPOC(data, choice->offset); 663226031Sstas size_t datalen; 664226031Sstas const void *el; 665226031Sstas 666226031Sstas if (*element > A1_HEADER_LEN(choice)) { 667226031Sstas printf("element: %d\n", *element); 668226031Sstas return ASN1_PARSE_ERROR; 669226031Sstas } 670226031Sstas 671226031Sstas if (*element == 0) { 672226031Sstas ret += der_put_octet_string(p, len, 673226031Sstas DPOC(data, choice->tt), &datalen); 674226031Sstas } else { 675226031Sstas choice += *element; 676226031Sstas el = DPOC(data, choice->offset); 677226031Sstas ret = _asn1_encode(choice->ptr, p, len, el, &datalen); 678226031Sstas if (ret) 679226031Sstas return ret; 680226031Sstas } 681226031Sstas len -= datalen; p -= datalen; 682226031Sstas 683226031Sstas break; 684226031Sstas } 685226031Sstas default: 686226031Sstas ABORT_ON_ERROR(); 687226031Sstas } 688226031Sstas t--; 689226031Sstas elements--; 690226031Sstas } 691226031Sstas if (size) 692226031Sstas *size = oldlen - len; 693226031Sstas 694226031Sstas return 0; 695226031Sstas} 696226031Sstas 697226031Sstassize_t 698226031Sstas_asn1_length(const struct asn1_template *t, const void *data) 699226031Sstas{ 700226031Sstas size_t elements = A1_HEADER_LEN(t); 701226031Sstas size_t ret = 0; 702226031Sstas 703226031Sstas t += A1_HEADER_LEN(t); 704226031Sstas 705226031Sstas while (elements) { 706226031Sstas switch (t->tt & A1_OP_MASK) { 707226031Sstas case A1_OP_TYPE: 708226031Sstas case A1_OP_TYPE_EXTERN: { 709226031Sstas const void *el = DPOC(data, t->offset); 710226031Sstas 711226031Sstas if (t->tt & A1_FLAG_OPTIONAL) { 712226031Sstas void **pel = (void **)el; 713226031Sstas if (*pel == NULL) 714226031Sstas break; 715226031Sstas el = *pel; 716226031Sstas } 717226031Sstas 718226031Sstas if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 719226031Sstas ret += _asn1_length(t->ptr, el); 720226031Sstas } else { 721226031Sstas const struct asn1_type_func *f = t->ptr; 722226031Sstas ret += (f->length)(el); 723226031Sstas } 724226031Sstas break; 725226031Sstas } 726226031Sstas case A1_OP_TAG: { 727226031Sstas size_t datalen; 728226031Sstas const void *olddata = data; 729226031Sstas 730226031Sstas data = DPO(data, t->offset); 731226031Sstas 732226031Sstas if (t->tt & A1_FLAG_OPTIONAL) { 733226031Sstas void **el = (void **)data; 734226031Sstas if (*el == NULL) { 735226031Sstas data = olddata; 736226031Sstas break; 737226031Sstas } 738226031Sstas data = *el; 739226031Sstas } 740226031Sstas datalen = _asn1_length(t->ptr, data); 741226031Sstas ret += der_length_tag(A1_TAG_TAG(t->tt)) + der_length_len(datalen); 742226031Sstas ret += datalen; 743226031Sstas data = olddata; 744226031Sstas break; 745226031Sstas } 746226031Sstas case A1_OP_PARSE: { 747226031Sstas unsigned int type = A1_PARSE_TYPE(t->tt); 748226031Sstas const void *el = DPOC(data, t->offset); 749226031Sstas 750226031Sstas if (type > sizeof(prim)/sizeof(prim[0])) { 751226031Sstas ABORT_ON_ERROR(); 752226031Sstas break; 753226031Sstas } 754226031Sstas ret += (prim[type].length)(el); 755226031Sstas break; 756226031Sstas } 757226031Sstas case A1_OP_SETOF: 758226031Sstas case A1_OP_SEQOF: { 759226031Sstas const struct template_of *el = DPOC(data, t->offset); 760226031Sstas size_t ellen = sizeofType(t->ptr); 761226031Sstas const unsigned char *element = el->val; 762226031Sstas unsigned int i; 763226031Sstas 764226031Sstas for (i = 0; i < el->len; i++) { 765226031Sstas ret += _asn1_length(t->ptr, element); 766226031Sstas element += ellen; 767226031Sstas } 768226031Sstas 769226031Sstas break; 770226031Sstas } 771226031Sstas case A1_OP_BMEMBER: { 772226031Sstas const struct asn1_template *bmember = t->ptr; 773226031Sstas size_t size = bmember->offset; 774226031Sstas size_t elements = A1_HEADER_LEN(bmember); 775226031Sstas int rfc1510 = (bmember->tt & A1_HBF_RFC1510); 776226031Sstas 777226031Sstas if (rfc1510) { 778226031Sstas ret += 5; 779226031Sstas } else { 780226031Sstas 781226031Sstas ret += 1; 782226031Sstas 783226031Sstas bmember += elements; 784226031Sstas 785226031Sstas while (elements) { 786226031Sstas if (bmember_isset_bit(data, bmember->offset, size)) { 787226031Sstas ret += (bmember->offset / 8) + 1; 788226031Sstas break; 789226031Sstas } 790226031Sstas elements--; bmember--; 791226031Sstas } 792226031Sstas } 793226031Sstas break; 794226031Sstas } 795226031Sstas case A1_OP_CHOICE: { 796226031Sstas const struct asn1_template *choice = t->ptr; 797226031Sstas const unsigned int *element = DPOC(data, choice->offset); 798226031Sstas 799226031Sstas if (*element > A1_HEADER_LEN(choice)) 800226031Sstas break; 801226031Sstas 802226031Sstas if (*element == 0) { 803226031Sstas ret += der_length_octet_string(DPOC(data, choice->tt)); 804226031Sstas } else { 805226031Sstas choice += *element; 806226031Sstas ret += _asn1_length(choice->ptr, DPOC(data, choice->offset)); 807226031Sstas } 808226031Sstas break; 809226031Sstas } 810226031Sstas default: 811226031Sstas ABORT_ON_ERROR(); 812226031Sstas break; 813226031Sstas } 814226031Sstas elements--; 815226031Sstas t--; 816226031Sstas } 817226031Sstas return ret; 818226031Sstas} 819226031Sstas 820226031Sstasvoid 821226031Sstas_asn1_free(const struct asn1_template *t, void *data) 822226031Sstas{ 823226031Sstas size_t elements = A1_HEADER_LEN(t); 824226031Sstas 825226031Sstas if (t->tt & A1_HF_PRESERVE) 826226031Sstas der_free_octet_string(data); 827226031Sstas 828226031Sstas t++; 829226031Sstas 830226031Sstas while (elements) { 831226031Sstas switch (t->tt & A1_OP_MASK) { 832226031Sstas case A1_OP_TYPE: 833226031Sstas case A1_OP_TYPE_EXTERN: { 834226031Sstas void *el = DPO(data, t->offset); 835226031Sstas 836226031Sstas if (t->tt & A1_FLAG_OPTIONAL) { 837226031Sstas void **pel = (void **)el; 838226031Sstas if (*pel == NULL) 839226031Sstas break; 840226031Sstas el = *pel; 841226031Sstas } 842226031Sstas 843226031Sstas if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 844226031Sstas _asn1_free(t->ptr, el); 845226031Sstas } else { 846226031Sstas const struct asn1_type_func *f = t->ptr; 847226031Sstas (f->release)(el); 848226031Sstas } 849226031Sstas if (t->tt & A1_FLAG_OPTIONAL) 850226031Sstas free(el); 851226031Sstas 852226031Sstas break; 853226031Sstas } 854226031Sstas case A1_OP_PARSE: { 855226031Sstas unsigned int type = A1_PARSE_TYPE(t->tt); 856226031Sstas void *el = DPO(data, t->offset); 857226031Sstas 858226031Sstas if (type > sizeof(prim)/sizeof(prim[0])) { 859226031Sstas ABORT_ON_ERROR(); 860226031Sstas break; 861226031Sstas } 862226031Sstas (prim[type].release)(el); 863226031Sstas break; 864226031Sstas } 865226031Sstas case A1_OP_TAG: { 866226031Sstas void *el = DPO(data, t->offset); 867226031Sstas 868226031Sstas if (t->tt & A1_FLAG_OPTIONAL) { 869226031Sstas void **pel = (void **)el; 870226031Sstas if (*pel == NULL) 871226031Sstas break; 872226031Sstas el = *pel; 873226031Sstas } 874226031Sstas 875226031Sstas _asn1_free(t->ptr, el); 876226031Sstas 877226031Sstas if (t->tt & A1_FLAG_OPTIONAL) 878226031Sstas free(el); 879226031Sstas 880226031Sstas break; 881226031Sstas } 882226031Sstas case A1_OP_SETOF: 883226031Sstas case A1_OP_SEQOF: { 884226031Sstas struct template_of *el = DPO(data, t->offset); 885226031Sstas size_t ellen = sizeofType(t->ptr); 886226031Sstas unsigned char *element = el->val; 887226031Sstas unsigned int i; 888226031Sstas 889226031Sstas for (i = 0; i < el->len; i++) { 890226031Sstas _asn1_free(t->ptr, element); 891226031Sstas element += ellen; 892226031Sstas } 893226031Sstas free(el->val); 894226031Sstas el->val = NULL; 895226031Sstas el->len = 0; 896226031Sstas 897226031Sstas break; 898226031Sstas } 899226031Sstas case A1_OP_BMEMBER: 900226031Sstas break; 901226031Sstas case A1_OP_CHOICE: { 902226031Sstas const struct asn1_template *choice = t->ptr; 903226031Sstas const unsigned int *element = DPOC(data, choice->offset); 904226031Sstas 905226031Sstas if (*element > A1_HEADER_LEN(choice)) 906226031Sstas break; 907226031Sstas 908226031Sstas if (*element == 0) { 909226031Sstas der_free_octet_string(DPO(data, choice->tt)); 910226031Sstas } else { 911226031Sstas choice += *element; 912226031Sstas _asn1_free(choice->ptr, DPO(data, choice->offset)); 913226031Sstas } 914226031Sstas break; 915226031Sstas } 916226031Sstas default: 917226031Sstas ABORT_ON_ERROR(); 918226031Sstas break; 919226031Sstas } 920226031Sstas t++; 921226031Sstas elements--; 922226031Sstas } 923226031Sstas} 924226031Sstas 925226031Sstasint 926226031Sstas_asn1_copy(const struct asn1_template *t, const void *from, void *to) 927226031Sstas{ 928226031Sstas size_t elements = A1_HEADER_LEN(t); 929226031Sstas int ret = 0; 930226031Sstas int preserve = (t->tt & A1_HF_PRESERVE); 931226031Sstas 932226031Sstas t++; 933226031Sstas 934226031Sstas if (preserve) { 935226031Sstas ret = der_copy_octet_string(from, to); 936226031Sstas if (ret) 937226031Sstas return ret; 938226031Sstas } 939226031Sstas 940226031Sstas while (elements) { 941226031Sstas switch (t->tt & A1_OP_MASK) { 942226031Sstas case A1_OP_TYPE: 943226031Sstas case A1_OP_TYPE_EXTERN: { 944226031Sstas const void *fel = DPOC(from, t->offset); 945226031Sstas void *tel = DPO(to, t->offset); 946226031Sstas void **ptel = (void **)tel; 947226031Sstas size_t size; 948226031Sstas 949226031Sstas if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 950226031Sstas size = sizeofType(t->ptr); 951226031Sstas } else { 952226031Sstas const struct asn1_type_func *f = t->ptr; 953226031Sstas size = f->size; 954226031Sstas } 955226031Sstas 956226031Sstas if (t->tt & A1_FLAG_OPTIONAL) { 957226031Sstas void **pfel = (void **)fel; 958226031Sstas if (*pfel == NULL) 959226031Sstas break; 960226031Sstas fel = *pfel; 961226031Sstas 962226031Sstas tel = *ptel = calloc(1, size); 963226031Sstas if (tel == NULL) 964226031Sstas return ENOMEM; 965226031Sstas } 966226031Sstas 967226031Sstas if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) { 968226031Sstas ret = _asn1_copy(t->ptr, fel, tel); 969226031Sstas } else { 970226031Sstas const struct asn1_type_func *f = t->ptr; 971226031Sstas ret = (f->copy)(fel, tel); 972226031Sstas } 973226031Sstas 974226031Sstas if (ret) { 975226031Sstas if (t->tt & A1_FLAG_OPTIONAL) { 976226031Sstas free(*ptel); 977226031Sstas *ptel = NULL; 978226031Sstas } 979226031Sstas return ret; 980226031Sstas } 981226031Sstas break; 982226031Sstas } 983226031Sstas case A1_OP_PARSE: { 984226031Sstas unsigned int type = A1_PARSE_TYPE(t->tt); 985226031Sstas const void *fel = DPOC(from, t->offset); 986226031Sstas void *tel = DPO(to, t->offset); 987226031Sstas 988226031Sstas if (type > sizeof(prim)/sizeof(prim[0])) { 989226031Sstas ABORT_ON_ERROR(); 990226031Sstas return ASN1_PARSE_ERROR; 991226031Sstas } 992226031Sstas ret = (prim[type].copy)(fel, tel); 993226031Sstas if (ret) 994226031Sstas return ret; 995226031Sstas break; 996226031Sstas } 997226031Sstas case A1_OP_TAG: { 998226031Sstas const void *oldfrom = from; 999226031Sstas void *oldto = to; 1000226031Sstas void **tel = NULL; 1001226031Sstas 1002226031Sstas from = DPOC(from, t->offset); 1003226031Sstas to = DPO(to, t->offset); 1004226031Sstas 1005226031Sstas if (t->tt & A1_FLAG_OPTIONAL) { 1006226031Sstas void **fel = (void **)from; 1007226031Sstas tel = (void **)to; 1008226031Sstas if (*fel == NULL) { 1009226031Sstas from = oldfrom; 1010226031Sstas to = oldto; 1011226031Sstas break; 1012226031Sstas } 1013226031Sstas from = *fel; 1014226031Sstas 1015226031Sstas to = *tel = calloc(1, sizeofType(t->ptr)); 1016226031Sstas if (to == NULL) 1017226031Sstas return ENOMEM; 1018226031Sstas } 1019226031Sstas 1020226031Sstas ret = _asn1_copy(t->ptr, from, to); 1021226031Sstas if (ret) { 1022226031Sstas if (t->tt & A1_FLAG_OPTIONAL) { 1023226031Sstas free(*tel); 1024226031Sstas *tel = NULL; 1025226031Sstas } 1026226031Sstas return ret; 1027226031Sstas } 1028226031Sstas 1029226031Sstas from = oldfrom; 1030226031Sstas to = oldto; 1031226031Sstas 1032226031Sstas break; 1033226031Sstas } 1034226031Sstas case A1_OP_SETOF: 1035226031Sstas case A1_OP_SEQOF: { 1036226031Sstas const struct template_of *fel = DPOC(from, t->offset); 1037226031Sstas struct template_of *tel = DPO(to, t->offset); 1038226031Sstas size_t ellen = sizeofType(t->ptr); 1039226031Sstas unsigned int i; 1040226031Sstas 1041226031Sstas tel->val = calloc(fel->len, ellen); 1042226031Sstas if (tel->val == NULL) 1043226031Sstas return ENOMEM; 1044226031Sstas 1045226031Sstas tel->len = fel->len; 1046226031Sstas 1047226031Sstas for (i = 0; i < fel->len; i++) { 1048226031Sstas ret = _asn1_copy(t->ptr, 1049226031Sstas DPOC(fel->val, (i * ellen)), 1050226031Sstas DPO(tel->val, (i *ellen))); 1051226031Sstas if (ret) 1052226031Sstas return ret; 1053226031Sstas } 1054226031Sstas break; 1055226031Sstas } 1056226031Sstas case A1_OP_BMEMBER: { 1057226031Sstas const struct asn1_template *bmember = t->ptr; 1058226031Sstas size_t size = bmember->offset; 1059226031Sstas memcpy(to, from, size); 1060226031Sstas break; 1061226031Sstas } 1062226031Sstas case A1_OP_CHOICE: { 1063226031Sstas const struct asn1_template *choice = t->ptr; 1064226031Sstas const unsigned int *felement = DPOC(from, choice->offset); 1065226031Sstas unsigned int *telement = DPO(to, choice->offset); 1066226031Sstas 1067226031Sstas if (*felement > A1_HEADER_LEN(choice)) 1068226031Sstas return ASN1_PARSE_ERROR; 1069226031Sstas 1070226031Sstas *telement = *felement; 1071226031Sstas 1072226031Sstas if (*felement == 0) { 1073226031Sstas ret = der_copy_octet_string(DPOC(from, choice->tt), DPO(to, choice->tt)); 1074226031Sstas } else { 1075226031Sstas choice += *felement; 1076226031Sstas ret = _asn1_copy(choice->ptr, 1077226031Sstas DPOC(from, choice->offset), 1078226031Sstas DPO(to, choice->offset)); 1079226031Sstas } 1080226031Sstas if (ret) 1081226031Sstas return ret; 1082226031Sstas break; 1083226031Sstas } 1084226031Sstas default: 1085226031Sstas ABORT_ON_ERROR(); 1086226031Sstas break; 1087226031Sstas } 1088226031Sstas t++; 1089226031Sstas elements--; 1090226031Sstas } 1091226031Sstas return 0; 1092226031Sstas} 1093226031Sstas 1094226031Sstasint 1095226031Sstas_asn1_decode_top(const struct asn1_template *t, unsigned flags, const unsigned char *p, size_t len, void *data, size_t *size) 1096226031Sstas{ 1097226031Sstas int ret; 1098226031Sstas memset(data, 0, t->offset); 1099226031Sstas ret = _asn1_decode(t, flags, p, len, data, size); 1100226031Sstas if (ret) { 1101226031Sstas _asn1_free(t, data); 1102226031Sstas memset(data, 0, t->offset); 1103226031Sstas } 1104226031Sstas 1105226031Sstas return ret; 1106226031Sstas} 1107226031Sstas 1108226031Sstasint 1109226031Sstas_asn1_copy_top(const struct asn1_template *t, const void *from, void *to) 1110226031Sstas{ 1111226031Sstas int ret; 1112226031Sstas memset(to, 0, t->offset); 1113226031Sstas ret = _asn1_copy(t, from, to); 1114226031Sstas if (ret) { 1115226031Sstas _asn1_free(t, to); 1116226031Sstas memset(to, 0, t->offset); 1117226031Sstas } 1118226031Sstas return ret; 1119226031Sstas} 1120