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