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