2 * Copyright (c) 2009 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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.
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.
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
40 #define ABORT_ON_ERROR() abort()
42 #define ABORT_ON_ERROR() do { } while(0)
45 #define DPOC(data,offset) ((const void *)(((const unsigned char *)data) + offset))
46 #define DPO(data,offset) ((void *)(((unsigned char *)data) + offset))
49 static struct asn1_type_func prim[] = {
50 #define el(name, type) { \
51 (asn1_type_encode)der_put_##name, \
52 (asn1_type_decode)der_get_##name, \
53 (asn1_type_length)der_length_##name, \
54 (asn1_type_copy)der_copy_##name, \
55 (asn1_type_release)der_free_##name, \
58 #define elber(name, type) { \
59 (asn1_type_encode)der_put_##name, \
60 (asn1_type_decode)der_get_##name##_ber, \
61 (asn1_type_length)der_length_##name, \
62 (asn1_type_copy)der_copy_##name, \
63 (asn1_type_release)der_free_##name, \
67 el(heim_integer, heim_integer),
69 el(unsigned, unsigned),
70 el(general_string, heim_general_string),
71 el(octet_string, heim_octet_string),
72 elber(octet_string, heim_octet_string),
73 el(ia5_string, heim_ia5_string),
74 el(bmp_string, heim_bmp_string),
75 el(universal_string, heim_universal_string),
76 el(printable_string, heim_printable_string),
77 el(visible_string, heim_visible_string),
78 el(utf8string, heim_utf8_string),
79 el(generalized_time, time_t),
81 el(bit_string, heim_bit_string),
82 { (asn1_type_encode)der_put_boolean, (asn1_type_decode)der_get_boolean,
83 (asn1_type_length)der_length_boolean, (asn1_type_copy)der_copy_integer,
84 (asn1_type_release)der_free_integer, sizeof(int)
87 el(general_string, heim_general_string),
93 sizeofType(const struct asn1_template *t)
99 * Here is abstraction to not so well evil fact of bit fields in C,
100 * they are endian dependent, so when getting and setting bits in the
101 * host local structure we need to know the endianness of the host.
103 * Its not the first time in Heimdal this have bitten us, and some day
104 * we'll grow up and use #defined constant, but bit fields are still
105 * so pretty and shiny.
109 bmember_get_bit(const unsigned char *p, void *data,
110 unsigned int bit, size_t size)
112 unsigned int localbit = bit % 8;
113 if ((*p >> (7 - localbit)) & 1) {
114 #ifdef WORDS_BIGENDIAN
115 *(unsigned int *)data |= (1 << ((size * 8) - bit - 1));
117 *(unsigned int *)data |= (1 << bit);
123 bmember_isset_bit(const void *data, unsigned int bit, size_t size)
125 #ifdef WORDS_BIGENDIAN
126 if ((*(unsigned int *)data) & (1 << ((size * 8) - bit - 1)))
130 if ((*(unsigned int *)data) & (1 << bit))
137 bmember_put_bit(unsigned char *p, const void *data, unsigned int bit,
138 size_t size, unsigned int *bitset)
140 unsigned int localbit = bit % 8;
142 if (bmember_isset_bit(data, bit, size)) {
143 *p |= (1 << (7 - localbit));
145 *bitset = (7 - localbit) + 1;
150 _asn1_decode(const struct asn1_template *t, unsigned flags,
151 const unsigned char *p, size_t len, void *data, size_t *size)
153 size_t elements = A1_HEADER_LEN(t);
156 const unsigned char *startp = NULL;
157 unsigned int template_flags = t->tt;
159 /* skip over header */
162 if (template_flags & A1_HF_PRESERVE)
166 switch (t->tt & A1_OP_MASK) {
168 case A1_OP_TYPE_EXTERN: {
169 size_t newsize, size;
170 void *el = DPO(data, t->offset);
171 void **pel = (void **)el;
173 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
174 size = sizeofType(t->ptr);
176 const struct asn1_type_func *f = t->ptr;
180 if (t->tt & A1_FLAG_OPTIONAL) {
181 *pel = calloc(1, size);
186 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
187 ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize);
189 const struct asn1_type_func *f = t->ptr;
190 ret = (f->decode)(p, len, el, &newsize);
193 if (t->tt & A1_FLAG_OPTIONAL) {
200 p += newsize; len -= newsize;
208 void *olddata = data;
209 int is_indefinite = 0;
210 int subflags = flags;
212 ret = der_match_tag_and_length(p, len, A1_TAG_CLASS(t->tt),
213 &dertype, A1_TAG_TAG(t->tt),
216 if (t->tt & A1_FLAG_OPTIONAL)
224 * Only allow indefinite encoding for OCTET STRING and BER
225 * for now. Should handle BIT STRING too.
228 if (dertype != A1_TAG_TYPE(t->tt) && (flags & A1_PF_ALLOW_BER)) {
229 const struct asn1_template *subtype = t->ptr;
230 subtype++; /* skip header */
232 if (((subtype->tt & A1_OP_MASK) == A1_OP_PARSE) &&
233 A1_PARSE_TYPE(subtype->tt) == A1T_OCTET_STRING)
234 subflags |= A1_PF_INDEFINTE;
237 if (datalen == ASN1_INDEFINITE) {
238 if ((flags & A1_PF_ALLOW_BER) == 0)
244 /* hide EndOfContent for sub-decoder, catching it below */
246 } else if (datalen > len)
249 data = DPO(data, t->offset);
251 if (t->tt & A1_FLAG_OPTIONAL) {
252 void **el = (void **)data;
253 size_t ellen = sizeofType(t->ptr);
255 *el = calloc(1, ellen);
261 ret = _asn1_decode(t->ptr, subflags, p, datalen, data, &newsize);
265 if (newsize != datalen)
266 return ASN1_EXTRA_DATA;
272 * Indefinite encoding needs a trailing EndOfContent,
276 ret = der_match_tag_and_length(p, len, ASN1_C_UNIV,
277 &dertype, UT_EndOfContent,
284 return ASN1_INDEF_EXTRA_DATA;
292 unsigned int type = A1_PARSE_TYPE(t->tt);
294 void *el = DPO(data, t->offset);
297 * INDEFINITE primitive types are one element after the
298 * same type but non-INDEFINITE version.
300 if (flags & A1_PF_INDEFINTE)
303 if (type >= sizeof(prim)/sizeof(prim[0])) {
305 return ASN1_PARSE_ERROR;
308 ret = (prim[type].decode)(p, len, el, &newsize);
311 p += newsize; len -= newsize;
317 struct template_of *el = DPO(data, t->offset);
319 size_t ellen = sizeofType(t->ptr);
320 size_t vallength = 0;
324 size_t newlen = vallength + ellen;
325 if (vallength > newlen)
326 return ASN1_OVERFLOW;
328 tmp = realloc(el->val, newlen);
332 memset(DPO(tmp, vallength), 0, ellen);
335 ret = _asn1_decode(t->ptr, flags & (~A1_PF_INDEFINTE), p, len,
336 DPO(el->val, vallength), &newsize);
341 p += newsize; len -= newsize;
346 case A1_OP_BMEMBER: {
347 const struct asn1_template *bmember = t->ptr;
348 size_t size = bmember->offset;
349 size_t elements = A1_HEADER_LEN(bmember);
354 memset(data, 0, size);
360 while (elements && len) {
361 while (bmember->offset / 8 > pos / 8) {
368 bmember_get_bit(p, data, bmember->offset, size);
369 elements--; bmember++;
376 const struct asn1_template *choice = t->ptr;
377 unsigned int *element = DPO(data, choice->offset);
381 for (i = 1; i < A1_HEADER_LEN(choice) + 1; i++) {
382 /* should match first tag instead, store it in choice.tt */
383 ret = _asn1_decode(choice[i].ptr, 0, p, len,
384 DPO(data, choice[i].offset), &datalen);
387 p += datalen; len -= datalen;
389 } else if (ret != ASN1_BAD_ID && ret != ASN1_MISPLACED_FIELD && ret != ASN1_MISSING_FIELD) {
393 if (i >= A1_HEADER_LEN(choice) + 1) {
398 ret = der_get_octet_string(p, len,
399 DPO(data, choice->tt), &datalen);
402 p += datalen; len -= datalen;
409 return ASN1_PARSE_ERROR;
414 /* if we are using padding, eat up read of context */
415 if (template_flags & A1_HF_ELLIPSIS)
424 * saved the raw bits if asked for it, useful for signature
428 heim_octet_string *save = data;
430 save->data = malloc(oldlen);
431 if (save->data == NULL)
434 save->length = oldlen;
435 memcpy(save->data, startp, oldlen);
442 _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const void *data, size_t *size)
444 size_t elements = A1_HEADER_LEN(t);
448 t += A1_HEADER_LEN(t);
451 switch (t->tt & A1_OP_MASK) {
453 case A1_OP_TYPE_EXTERN: {
455 const void *el = DPOC(data, t->offset);
457 if (t->tt & A1_FLAG_OPTIONAL) {
458 void **pel = (void **)el;
464 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
465 ret = _asn1_encode(t->ptr, p, len, el, &newsize);
467 const struct asn1_type_func *f = t->ptr;
468 ret = (f->encode)(p, len, el, &newsize);
473 p -= newsize; len -= newsize;
478 const void *olddata = data;
481 data = DPOC(data, t->offset);
483 if (t->tt & A1_FLAG_OPTIONAL) {
484 void **el = (void **)data;
492 ret = _asn1_encode(t->ptr, p, len, data, &datalen);
496 len -= datalen; p -= datalen;
498 ret = der_put_length_and_tag(p, len, datalen,
501 A1_TAG_TAG(t->tt), &l);
512 unsigned int type = A1_PARSE_TYPE(t->tt);
514 const void *el = DPOC(data, t->offset);
516 if (type > sizeof(prim)/sizeof(prim[0])) {
518 return ASN1_PARSE_ERROR;
521 ret = (prim[type].encode)(p, len, el, &newsize);
524 p -= newsize; len -= newsize;
529 const struct template_of *el = DPOC(data, t->offset);
530 size_t ellen = sizeofType(t->ptr);
531 struct heim_octet_string *val;
532 unsigned char *elptr = el->val;
538 if (el->len > UINT_MAX/sizeof(val[0]))
541 val = malloc(sizeof(val[0]) * el->len);
545 for(totallen = 0, i = 0; i < el->len; i++) {
549 val[i].length = _asn1_length(t->ptr, elptr);
550 val[i].data = malloc(val[i].length);
552 ret = _asn1_encode(t->ptr, DPO(val[i].data, val[i].length - 1),
553 val[i].length, elptr, &l);
557 next = elptr + ellen;
563 totallen += val[i].length;
565 if (ret == 0 && totallen > len)
577 qsort(val, el->len, sizeof(val[0]), _heim_der_set_sort);
582 memcpy(p + 1, val[i].data, val[i].length);
591 struct template_of *el = DPO(data, t->offset);
592 size_t ellen = sizeofType(t->ptr);
595 unsigned char *elptr = el->val;
600 elptr += ellen * (el->len - 1);
602 for (i = 0; i < el->len; i++) {
603 ret = _asn1_encode(t->ptr, p, len,
608 p -= newsize; len -= newsize;
614 case A1_OP_BMEMBER: {
615 const struct asn1_template *bmember = t->ptr;
616 size_t size = bmember->offset;
617 size_t elements = A1_HEADER_LEN(bmember);
620 unsigned int bitset = 0;
621 int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
628 pos = bmember->offset;
630 while (elements && len) {
631 while (bmember->offset / 8 < pos / 8) {
632 if (rfc1510 || bitset || c) {
634 return ASN1_OVERFLOW;
640 bmember_put_bit(&c, data, bmember->offset, size, &bitset);
641 elements--; bmember--;
643 if (rfc1510 || bitset) {
645 return ASN1_OVERFLOW;
650 return ASN1_OVERFLOW;
651 if (rfc1510 || bitset == 0)
661 const struct asn1_template *choice = t->ptr;
662 const unsigned int *element = DPOC(data, choice->offset);
666 if (*element > A1_HEADER_LEN(choice)) {
667 printf("element: %d\n", *element);
668 return ASN1_PARSE_ERROR;
672 ret += der_put_octet_string(p, len,
673 DPOC(data, choice->tt), &datalen);
676 el = DPOC(data, choice->offset);
677 ret = _asn1_encode(choice->ptr, p, len, el, &datalen);
681 len -= datalen; p -= datalen;
692 *size = oldlen - len;
698 _asn1_length(const struct asn1_template *t, const void *data)
700 size_t elements = A1_HEADER_LEN(t);
703 t += A1_HEADER_LEN(t);
706 switch (t->tt & A1_OP_MASK) {
708 case A1_OP_TYPE_EXTERN: {
709 const void *el = DPOC(data, t->offset);
711 if (t->tt & A1_FLAG_OPTIONAL) {
712 void **pel = (void **)el;
718 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
719 ret += _asn1_length(t->ptr, el);
721 const struct asn1_type_func *f = t->ptr;
722 ret += (f->length)(el);
728 const void *olddata = data;
730 data = DPO(data, t->offset);
732 if (t->tt & A1_FLAG_OPTIONAL) {
733 void **el = (void **)data;
740 datalen = _asn1_length(t->ptr, data);
741 ret += der_length_tag(A1_TAG_TAG(t->tt)) + der_length_len(datalen);
747 unsigned int type = A1_PARSE_TYPE(t->tt);
748 const void *el = DPOC(data, t->offset);
750 if (type > sizeof(prim)/sizeof(prim[0])) {
754 ret += (prim[type].length)(el);
759 const struct template_of *el = DPOC(data, t->offset);
760 size_t ellen = sizeofType(t->ptr);
761 const unsigned char *element = el->val;
764 for (i = 0; i < el->len; i++) {
765 ret += _asn1_length(t->ptr, element);
771 case A1_OP_BMEMBER: {
772 const struct asn1_template *bmember = t->ptr;
773 size_t size = bmember->offset;
774 size_t elements = A1_HEADER_LEN(bmember);
775 int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
786 if (bmember_isset_bit(data, bmember->offset, size)) {
787 ret += (bmember->offset / 8) + 1;
790 elements--; bmember--;
796 const struct asn1_template *choice = t->ptr;
797 const unsigned int *element = DPOC(data, choice->offset);
799 if (*element > A1_HEADER_LEN(choice))
803 ret += der_length_octet_string(DPOC(data, choice->tt));
806 ret += _asn1_length(choice->ptr, DPOC(data, choice->offset));
821 _asn1_free(const struct asn1_template *t, void *data)
823 size_t elements = A1_HEADER_LEN(t);
825 if (t->tt & A1_HF_PRESERVE)
826 der_free_octet_string(data);
831 switch (t->tt & A1_OP_MASK) {
833 case A1_OP_TYPE_EXTERN: {
834 void *el = DPO(data, t->offset);
836 if (t->tt & A1_FLAG_OPTIONAL) {
837 void **pel = (void **)el;
843 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
844 _asn1_free(t->ptr, el);
846 const struct asn1_type_func *f = t->ptr;
849 if (t->tt & A1_FLAG_OPTIONAL)
855 unsigned int type = A1_PARSE_TYPE(t->tt);
856 void *el = DPO(data, t->offset);
858 if (type > sizeof(prim)/sizeof(prim[0])) {
862 (prim[type].release)(el);
866 void *el = DPO(data, t->offset);
868 if (t->tt & A1_FLAG_OPTIONAL) {
869 void **pel = (void **)el;
875 _asn1_free(t->ptr, el);
877 if (t->tt & A1_FLAG_OPTIONAL)
884 struct template_of *el = DPO(data, t->offset);
885 size_t ellen = sizeofType(t->ptr);
886 unsigned char *element = el->val;
889 for (i = 0; i < el->len; i++) {
890 _asn1_free(t->ptr, element);
902 const struct asn1_template *choice = t->ptr;
903 const unsigned int *element = DPOC(data, choice->offset);
905 if (*element > A1_HEADER_LEN(choice))
909 der_free_octet_string(DPO(data, choice->tt));
912 _asn1_free(choice->ptr, DPO(data, choice->offset));
926 _asn1_copy(const struct asn1_template *t, const void *from, void *to)
928 size_t elements = A1_HEADER_LEN(t);
930 int preserve = (t->tt & A1_HF_PRESERVE);
935 ret = der_copy_octet_string(from, to);
941 switch (t->tt & A1_OP_MASK) {
943 case A1_OP_TYPE_EXTERN: {
944 const void *fel = DPOC(from, t->offset);
945 void *tel = DPO(to, t->offset);
946 void **ptel = (void **)tel;
949 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
950 size = sizeofType(t->ptr);
952 const struct asn1_type_func *f = t->ptr;
956 if (t->tt & A1_FLAG_OPTIONAL) {
957 void **pfel = (void **)fel;
962 tel = *ptel = calloc(1, size);
967 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
968 ret = _asn1_copy(t->ptr, fel, tel);
970 const struct asn1_type_func *f = t->ptr;
971 ret = (f->copy)(fel, tel);
975 if (t->tt & A1_FLAG_OPTIONAL) {
984 unsigned int type = A1_PARSE_TYPE(t->tt);
985 const void *fel = DPOC(from, t->offset);
986 void *tel = DPO(to, t->offset);
988 if (type > sizeof(prim)/sizeof(prim[0])) {
990 return ASN1_PARSE_ERROR;
992 ret = (prim[type].copy)(fel, tel);
998 const void *oldfrom = from;
1002 from = DPOC(from, t->offset);
1003 to = DPO(to, t->offset);
1005 if (t->tt & A1_FLAG_OPTIONAL) {
1006 void **fel = (void **)from;
1015 to = *tel = calloc(1, sizeofType(t->ptr));
1020 ret = _asn1_copy(t->ptr, from, to);
1022 if (t->tt & A1_FLAG_OPTIONAL) {
1036 const struct template_of *fel = DPOC(from, t->offset);
1037 struct template_of *tel = DPO(to, t->offset);
1038 size_t ellen = sizeofType(t->ptr);
1041 tel->val = calloc(fel->len, ellen);
1042 if (tel->val == NULL)
1045 tel->len = fel->len;
1047 for (i = 0; i < fel->len; i++) {
1048 ret = _asn1_copy(t->ptr,
1049 DPOC(fel->val, (i * ellen)),
1050 DPO(tel->val, (i *ellen)));
1056 case A1_OP_BMEMBER: {
1057 const struct asn1_template *bmember = t->ptr;
1058 size_t size = bmember->offset;
1059 memcpy(to, from, size);
1062 case A1_OP_CHOICE: {
1063 const struct asn1_template *choice = t->ptr;
1064 const unsigned int *felement = DPOC(from, choice->offset);
1065 unsigned int *telement = DPO(to, choice->offset);
1067 if (*felement > A1_HEADER_LEN(choice))
1068 return ASN1_PARSE_ERROR;
1070 *telement = *felement;
1072 if (*felement == 0) {
1073 ret = der_copy_octet_string(DPOC(from, choice->tt), DPO(to, choice->tt));
1075 choice += *felement;
1076 ret = _asn1_copy(choice->ptr,
1077 DPOC(from, choice->offset),
1078 DPO(to, choice->offset));
1095 _asn1_decode_top(const struct asn1_template *t, unsigned flags, const unsigned char *p, size_t len, void *data, size_t *size)
1098 memset(data, 0, t->offset);
1099 ret = _asn1_decode(t, flags, p, len, data, size);
1101 _asn1_free(t, data);
1102 memset(data, 0, t->offset);
1109 _asn1_copy_top(const struct asn1_template *t, const void *from, void *to)
1112 memset(to, 0, t->offset);
1113 ret = _asn1_copy(t, from, to);
1116 memset(to, 0, t->offset);