1 /* $NetBSD: template.c,v 1.1.1.2 2014/04/24 12:45:28 pettai 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 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 #if 0
42 #define ABORT_ON_ERROR() abort()
43 #else
44 #define ABORT_ON_ERROR() do { } while(0)
45 #endif
46
47 #define DPOC(data,offset) ((const void *)(((const unsigned char *)data) + offset))
48 #define DPO(data,offset) ((void *)(((unsigned char *)data) + offset))
49
50
51 static struct asn1_type_func prim[] = {
52 #define el(name, type) { \
53 (asn1_type_encode)der_put_##name, \
54 (asn1_type_decode)der_get_##name, \
55 (asn1_type_length)der_length_##name, \
56 (asn1_type_copy)der_copy_##name, \
57 (asn1_type_release)der_free_##name, \
58 sizeof(type) \
59 }
60 #define elber(name, type) { \
61 (asn1_type_encode)der_put_##name, \
62 (asn1_type_decode)der_get_##name##_ber, \
63 (asn1_type_length)der_length_##name, \
64 (asn1_type_copy)der_copy_##name, \
65 (asn1_type_release)der_free_##name, \
66 sizeof(type) \
67 }
68 el(integer, int),
69 el(heim_integer, heim_integer),
70 el(integer, int),
71 el(unsigned, unsigned),
72 el(general_string, heim_general_string),
73 el(octet_string, heim_octet_string),
74 elber(octet_string, heim_octet_string),
75 el(ia5_string, heim_ia5_string),
76 el(bmp_string, heim_bmp_string),
77 el(universal_string, heim_universal_string),
78 el(printable_string, heim_printable_string),
79 el(visible_string, heim_visible_string),
80 el(utf8string, heim_utf8_string),
81 el(generalized_time, time_t),
82 el(utctime, time_t),
83 el(bit_string, heim_bit_string),
84 { (asn1_type_encode)der_put_boolean, (asn1_type_decode)der_get_boolean,
85 (asn1_type_length)der_length_boolean, (asn1_type_copy)der_copy_integer,
86 (asn1_type_release)der_free_integer, sizeof(int)
87 },
88 el(oid, heim_oid),
89 el(general_string, heim_general_string),
90 #undef el
91 #undef elber
92 };
93
94 static size_t
sizeofType(const struct asn1_template * t)95 sizeofType(const struct asn1_template *t)
96 {
97 return t->offset;
98 }
99
100 /*
101 * Here is abstraction to not so well evil fact of bit fields in C,
102 * they are endian dependent, so when getting and setting bits in the
103 * host local structure we need to know the endianness of the host.
104 *
105 * Its not the first time in Heimdal this have bitten us, and some day
106 * we'll grow up and use #defined constant, but bit fields are still
107 * so pretty and shiny.
108 */
109
110 static void
bmember_get_bit(const unsigned char * p,void * data,unsigned int bit,size_t size)111 bmember_get_bit(const unsigned char *p, void *data,
112 unsigned int bit, size_t size)
113 {
114 unsigned int localbit = bit % 8;
115 if ((*p >> (7 - localbit)) & 1) {
116 #ifdef WORDS_BIGENDIAN
117 *(unsigned int *)data |= (1 << ((size * 8) - bit - 1));
118 #else
119 *(unsigned int *)data |= (1 << bit);
120 #endif
121 }
122 }
123
124 static int
bmember_isset_bit(const void * data,unsigned int bit,size_t size)125 bmember_isset_bit(const void *data, unsigned int bit, size_t size)
126 {
127 #ifdef WORDS_BIGENDIAN
128 if ((*(unsigned int *)data) & (1 << ((size * 8) - bit - 1)))
129 return 1;
130 return 0;
131 #else
132 if ((*(unsigned int *)data) & (1 << bit))
133 return 1;
134 return 0;
135 #endif
136 }
137
138 static void
bmember_put_bit(unsigned char * p,const void * data,unsigned int bit,size_t size,unsigned int * bitset)139 bmember_put_bit(unsigned char *p, const void *data, unsigned int bit,
140 size_t size, unsigned int *bitset)
141 {
142 unsigned int localbit = bit % 8;
143
144 if (bmember_isset_bit(data, bit, size)) {
145 *p |= (1 << (7 - localbit));
146 if (*bitset == 0)
147 *bitset = (7 - localbit) + 1;
148 }
149 }
150
151 int
_asn1_decode(const struct asn1_template * t,unsigned flags,const unsigned char * p,size_t len,void * data,size_t * size)152 _asn1_decode(const struct asn1_template *t, unsigned flags,
153 const unsigned char *p, size_t len, void *data, size_t *size)
154 {
155 size_t elements = A1_HEADER_LEN(t);
156 size_t oldlen = len;
157 int ret = 0;
158 const unsigned char *startp = NULL;
159 unsigned int template_flags = t->tt;
160
161 /* skip over header */
162 t++;
163
164 if (template_flags & A1_HF_PRESERVE)
165 startp = p;
166
167 while (elements) {
168 switch (t->tt & A1_OP_MASK) {
169 case A1_OP_TYPE:
170 case A1_OP_TYPE_EXTERN: {
171 size_t newsize, size;
172 void *el = DPO(data, t->offset);
173 void **pel = (void **)el;
174
175 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
176 size = sizeofType(t->ptr);
177 } else {
178 const struct asn1_type_func *f = t->ptr;
179 size = f->size;
180 }
181
182 if (t->tt & A1_FLAG_OPTIONAL) {
183 *pel = calloc(1, size);
184 if (*pel == NULL)
185 return ENOMEM;
186 el = *pel;
187 }
188 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
189 ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize);
190 } else {
191 const struct asn1_type_func *f = t->ptr;
192 ret = (f->decode)(p, len, el, &newsize);
193 }
194 if (ret) {
195 if (t->tt & A1_FLAG_OPTIONAL) {
196 free(*pel);
197 *pel = NULL;
198 break;
199 }
200 return ret;
201 }
202 p += newsize; len -= newsize;
203
204 break;
205 }
206 case A1_OP_TAG: {
207 Der_type dertype;
208 size_t newsize;
209 size_t datalen, l;
210 void *olddata = data;
211 int is_indefinite = 0;
212 int subflags = flags;
213
214 ret = der_match_tag_and_length(p, len, A1_TAG_CLASS(t->tt),
215 &dertype, A1_TAG_TAG(t->tt),
216 &datalen, &l);
217 if (ret) {
218 if (t->tt & A1_FLAG_OPTIONAL)
219 break;
220 return ret;
221 }
222
223 p += l; len -= l;
224
225 /*
226 * Only allow indefinite encoding for OCTET STRING and BER
227 * for now. Should handle BIT STRING too.
228 */
229
230 if (dertype != A1_TAG_TYPE(t->tt) && (flags & A1_PF_ALLOW_BER)) {
231 const struct asn1_template *subtype = t->ptr;
232 subtype++; /* skip header */
233
234 if (((subtype->tt & A1_OP_MASK) == A1_OP_PARSE) &&
235 A1_PARSE_TYPE(subtype->tt) == A1T_OCTET_STRING)
236 subflags |= A1_PF_INDEFINTE;
237 }
238
239 if (datalen == ASN1_INDEFINITE) {
240 if ((flags & A1_PF_ALLOW_BER) == 0)
241 return ASN1_GOT_BER;
242 is_indefinite = 1;
243 datalen = len;
244 if (datalen < 2)
245 return ASN1_OVERRUN;
246 /* hide EndOfContent for sub-decoder, catching it below */
247 datalen -= 2;
248 } else if (datalen > len)
249 return ASN1_OVERRUN;
250
251 data = DPO(data, t->offset);
252
253 if (t->tt & A1_FLAG_OPTIONAL) {
254 void **el = (void **)data;
255 size_t ellen = sizeofType(t->ptr);
256
257 *el = calloc(1, ellen);
258 if (*el == NULL)
259 return ENOMEM;
260 data = *el;
261 }
262
263 ret = _asn1_decode(t->ptr, subflags, p, datalen, data, &newsize);
264 if (ret)
265 return ret;
266
267 if (newsize != datalen)
268 return ASN1_EXTRA_DATA;
269
270 len -= datalen;
271 p += datalen;
272
273 /*
274 * Indefinite encoding needs a trailing EndOfContent,
275 * check for that.
276 */
277 if (is_indefinite) {
278 ret = der_match_tag_and_length(p, len, ASN1_C_UNIV,
279 &dertype, UT_EndOfContent,
280 &datalen, &l);
281 if (ret)
282 return ret;
283 if (dertype != PRIM)
284 return ASN1_BAD_ID;
285 if (datalen != 0)
286 return ASN1_INDEF_EXTRA_DATA;
287 p += l; len -= l;
288 }
289 data = olddata;
290
291 break;
292 }
293 case A1_OP_PARSE: {
294 unsigned int type = A1_PARSE_TYPE(t->tt);
295 size_t newsize;
296 void *el = DPO(data, t->offset);
297
298 /*
299 * INDEFINITE primitive types are one element after the
300 * same type but non-INDEFINITE version.
301 */
302 if (flags & A1_PF_INDEFINTE)
303 type++;
304
305 if (type >= sizeof(prim)/sizeof(prim[0])) {
306 ABORT_ON_ERROR();
307 return ASN1_PARSE_ERROR;
308 }
309
310 ret = (prim[type].decode)(p, len, el, &newsize);
311 if (ret)
312 return ret;
313 p += newsize; len -= newsize;
314
315 break;
316 }
317 case A1_OP_SETOF:
318 case A1_OP_SEQOF: {
319 struct template_of *el = DPO(data, t->offset);
320 size_t newsize;
321 size_t ellen = sizeofType(t->ptr);
322 size_t vallength = 0;
323
324 while (len > 0) {
325 void *tmp;
326 size_t newlen = vallength + ellen;
327 if (vallength > newlen)
328 return ASN1_OVERFLOW;
329
330 tmp = realloc(el->val, newlen);
331 if (tmp == NULL)
332 return ENOMEM;
333
334 memset(DPO(tmp, vallength), 0, ellen);
335 el->val = tmp;
336
337 ret = _asn1_decode(t->ptr, flags & (~A1_PF_INDEFINTE), p, len,
338 DPO(el->val, vallength), &newsize);
339 if (ret)
340 return ret;
341 vallength = newlen;
342 el->len++;
343 p += newsize; len -= newsize;
344 }
345
346 break;
347 }
348 case A1_OP_BMEMBER: {
349 const struct asn1_template *bmember = t->ptr;
350 size_t size = bmember->offset;
351 size_t elements = A1_HEADER_LEN(bmember);
352 size_t pos = 0;
353
354 bmember++;
355
356 memset(data, 0, size);
357
358 if (len < 1)
359 return ASN1_OVERRUN;
360 p++; len--;
361
362 while (elements && len) {
363 while (bmember->offset / 8 > pos / 8) {
364 if (len < 1)
365 break;
366 p++; len--;
367 pos += 8;
368 }
369 if (len) {
370 bmember_get_bit(p, data, bmember->offset, size);
371 elements--; bmember++;
372 }
373 }
374 len = 0;
375 break;
376 }
377 case A1_OP_CHOICE: {
378 const struct asn1_template *choice = t->ptr;
379 unsigned int *element = DPO(data, choice->offset);
380 size_t datalen;
381 unsigned int i;
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(prim)/sizeof(prim[0])) {
519 ABORT_ON_ERROR();
520 return ASN1_PARSE_ERROR;
521 }
522
523 ret = (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 = sizeofType(t->ptr);
533 struct 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 = malloc(sizeof(val[0]) * el->len);
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 val[i].data = malloc(val[i].length);
553
554 ret = _asn1_encode(t->ptr, DPO(val[i].data, val[i].length - 1),
555 val[i].length, elptr, &l);
556 if (ret)
557 break;
558
559 next = elptr + ellen;
560 if (next < elptr) {
561 ret = ASN1_OVERFLOW;
562 break;
563 }
564 elptr = next;
565 totallen += val[i].length;
566 }
567 if (ret == 0 && totallen > len)
568 ret = ASN1_OVERFLOW;
569 if (ret) {
570 do {
571 free(val[i].data);
572 } while(i-- > 0);
573 free(val);
574 return ret;
575 }
576
577 len -= totallen;
578
579 qsort(val, el->len, sizeof(val[0]), _heim_der_set_sort);
580
581 i = el->len - 1;
582 do {
583 p -= val[i].length;
584 memcpy(p + 1, val[i].data, val[i].length);
585 free(val[i].data);
586 } while(i-- > 0);
587 free(val);
588
589 break;
590
591 }
592 case A1_OP_SEQOF: {
593 struct template_of *el = DPO(data, t->offset);
594 size_t ellen = sizeofType(t->ptr);
595 size_t newsize;
596 unsigned int i;
597 unsigned char *elptr = el->val;
598
599 if (el->len == 0)
600 break;
601
602 elptr += ellen * (el->len - 1);
603
604 for (i = 0; i < el->len; i++) {
605 ret = _asn1_encode(t->ptr, p, len,
606 elptr,
607 &newsize);
608 if (ret)
609 return ret;
610 p -= newsize; len -= newsize;
611 elptr -= ellen;
612 }
613
614 break;
615 }
616 case A1_OP_BMEMBER: {
617 const struct asn1_template *bmember = t->ptr;
618 size_t size = bmember->offset;
619 size_t elements = A1_HEADER_LEN(bmember);
620 size_t pos;
621 unsigned char c = 0;
622 unsigned int bitset = 0;
623 int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
624
625 bmember += elements;
626
627 if (rfc1510)
628 pos = 31;
629 else
630 pos = bmember->offset;
631
632 while (elements && len) {
633 while (bmember->offset / 8 < pos / 8) {
634 if (rfc1510 || bitset || c) {
635 if (len < 1)
636 return ASN1_OVERFLOW;
637 *p-- = c; len--;
638 }
639 c = 0;
640 pos -= 8;
641 }
642 bmember_put_bit(&c, data, bmember->offset, size, &bitset);
643 elements--; bmember--;
644 }
645 if (rfc1510 || bitset) {
646 if (len < 1)
647 return ASN1_OVERFLOW;
648 *p-- = c; len--;
649 }
650
651 if (len < 1)
652 return ASN1_OVERFLOW;
653 if (rfc1510 || bitset == 0)
654 *p-- = 0;
655 else
656 *p-- = bitset - 1;
657
658 len--;
659
660 break;
661 }
662 case A1_OP_CHOICE: {
663 const struct asn1_template *choice = t->ptr;
664 const unsigned int *element = DPOC(data, choice->offset);
665 size_t datalen;
666 const void *el;
667
668 if (*element > A1_HEADER_LEN(choice)) {
669 printf("element: %d\n", *element);
670 return ASN1_PARSE_ERROR;
671 }
672
673 if (*element == 0) {
674 ret += der_put_octet_string(p, len,
675 DPOC(data, choice->tt), &datalen);
676 } else {
677 choice += *element;
678 el = DPOC(data, choice->offset);
679 ret = _asn1_encode(choice->ptr, p, len, el, &datalen);
680 if (ret)
681 return ret;
682 }
683 len -= datalen; p -= datalen;
684
685 break;
686 }
687 default:
688 ABORT_ON_ERROR();
689 }
690 t--;
691 elements--;
692 }
693 if (size)
694 *size = oldlen - len;
695
696 return 0;
697 }
698
699 size_t
_asn1_length(const struct asn1_template * t,const void * data)700 _asn1_length(const struct asn1_template *t, const void *data)
701 {
702 size_t elements = A1_HEADER_LEN(t);
703 size_t ret = 0;
704
705 t += A1_HEADER_LEN(t);
706
707 while (elements) {
708 switch (t->tt & A1_OP_MASK) {
709 case A1_OP_TYPE:
710 case A1_OP_TYPE_EXTERN: {
711 const void *el = DPOC(data, t->offset);
712
713 if (t->tt & A1_FLAG_OPTIONAL) {
714 void **pel = (void **)el;
715 if (*pel == NULL)
716 break;
717 el = *pel;
718 }
719
720 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
721 ret += _asn1_length(t->ptr, el);
722 } else {
723 const struct asn1_type_func *f = t->ptr;
724 ret += (f->length)(el);
725 }
726 break;
727 }
728 case A1_OP_TAG: {
729 size_t datalen;
730 const void *olddata = data;
731
732 data = DPO(data, t->offset);
733
734 if (t->tt & A1_FLAG_OPTIONAL) {
735 void **el = (void **)data;
736 if (*el == NULL) {
737 data = olddata;
738 break;
739 }
740 data = *el;
741 }
742 datalen = _asn1_length(t->ptr, data);
743 ret += der_length_tag(A1_TAG_TAG(t->tt)) + der_length_len(datalen);
744 ret += datalen;
745 data = olddata;
746 break;
747 }
748 case A1_OP_PARSE: {
749 unsigned int type = A1_PARSE_TYPE(t->tt);
750 const void *el = DPOC(data, t->offset);
751
752 if (type > sizeof(prim)/sizeof(prim[0])) {
753 ABORT_ON_ERROR();
754 break;
755 }
756 ret += (prim[type].length)(el);
757 break;
758 }
759 case A1_OP_SETOF:
760 case A1_OP_SEQOF: {
761 const struct template_of *el = DPOC(data, t->offset);
762 size_t ellen = sizeofType(t->ptr);
763 const unsigned char *element = el->val;
764 unsigned int i;
765
766 for (i = 0; i < el->len; i++) {
767 ret += _asn1_length(t->ptr, element);
768 element += ellen;
769 }
770
771 break;
772 }
773 case A1_OP_BMEMBER: {
774 const struct asn1_template *bmember = t->ptr;
775 size_t size = bmember->offset;
776 size_t elements = A1_HEADER_LEN(bmember);
777 int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
778
779 if (rfc1510) {
780 ret += 5;
781 } else {
782
783 ret += 1;
784
785 bmember += elements;
786
787 while (elements) {
788 if (bmember_isset_bit(data, bmember->offset, size)) {
789 ret += (bmember->offset / 8) + 1;
790 break;
791 }
792 elements--; bmember--;
793 }
794 }
795 break;
796 }
797 case A1_OP_CHOICE: {
798 const struct asn1_template *choice = t->ptr;
799 const unsigned int *element = DPOC(data, choice->offset);
800
801 if (*element > A1_HEADER_LEN(choice))
802 break;
803
804 if (*element == 0) {
805 ret += der_length_octet_string(DPOC(data, choice->tt));
806 } else {
807 choice += *element;
808 ret += _asn1_length(choice->ptr, DPOC(data, choice->offset));
809 }
810 break;
811 }
812 default:
813 ABORT_ON_ERROR();
814 break;
815 }
816 elements--;
817 t--;
818 }
819 return ret;
820 }
821
822 void
_asn1_free(const struct asn1_template * t,void * data)823 _asn1_free(const struct asn1_template *t, void *data)
824 {
825 size_t elements = A1_HEADER_LEN(t);
826
827 if (t->tt & A1_HF_PRESERVE)
828 der_free_octet_string(data);
829
830 t++;
831
832 while (elements) {
833 switch (t->tt & A1_OP_MASK) {
834 case A1_OP_TYPE:
835 case A1_OP_TYPE_EXTERN: {
836 void *el = DPO(data, t->offset);
837
838 if (t->tt & A1_FLAG_OPTIONAL) {
839 void **pel = (void **)el;
840 if (*pel == NULL)
841 break;
842 el = *pel;
843 }
844
845 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
846 _asn1_free(t->ptr, el);
847 } else {
848 const struct asn1_type_func *f = t->ptr;
849 (f->release)(el);
850 }
851 if (t->tt & A1_FLAG_OPTIONAL)
852 free(el);
853
854 break;
855 }
856 case A1_OP_PARSE: {
857 unsigned int type = A1_PARSE_TYPE(t->tt);
858 void *el = DPO(data, t->offset);
859
860 if (type > sizeof(prim)/sizeof(prim[0])) {
861 ABORT_ON_ERROR();
862 break;
863 }
864 (prim[type].release)(el);
865 break;
866 }
867 case A1_OP_TAG: {
868 void *el = DPO(data, t->offset);
869
870 if (t->tt & A1_FLAG_OPTIONAL) {
871 void **pel = (void **)el;
872 if (*pel == NULL)
873 break;
874 el = *pel;
875 }
876
877 _asn1_free(t->ptr, el);
878
879 if (t->tt & A1_FLAG_OPTIONAL)
880 free(el);
881
882 break;
883 }
884 case A1_OP_SETOF:
885 case A1_OP_SEQOF: {
886 struct template_of *el = DPO(data, t->offset);
887 size_t ellen = sizeofType(t->ptr);
888 unsigned char *element = el->val;
889 unsigned int i;
890
891 for (i = 0; i < el->len; i++) {
892 _asn1_free(t->ptr, element);
893 element += ellen;
894 }
895 free(el->val);
896 el->val = NULL;
897 el->len = 0;
898
899 break;
900 }
901 case A1_OP_BMEMBER:
902 break;
903 case A1_OP_CHOICE: {
904 const struct asn1_template *choice = t->ptr;
905 const unsigned int *element = DPOC(data, choice->offset);
906
907 if (*element > A1_HEADER_LEN(choice))
908 break;
909
910 if (*element == 0) {
911 der_free_octet_string(DPO(data, choice->tt));
912 } else {
913 choice += *element;
914 _asn1_free(choice->ptr, DPO(data, choice->offset));
915 }
916 break;
917 }
918 default:
919 ABORT_ON_ERROR();
920 break;
921 }
922 t++;
923 elements--;
924 }
925 }
926
927 int
_asn1_copy(const struct asn1_template * t,const void * from,void * to)928 _asn1_copy(const struct asn1_template *t, const void *from, void *to)
929 {
930 size_t elements = A1_HEADER_LEN(t);
931 int ret = 0;
932 int preserve = (t->tt & A1_HF_PRESERVE);
933
934 t++;
935
936 if (preserve) {
937 ret = der_copy_octet_string(from, to);
938 if (ret)
939 return ret;
940 }
941
942 while (elements) {
943 switch (t->tt & A1_OP_MASK) {
944 case A1_OP_TYPE:
945 case A1_OP_TYPE_EXTERN: {
946 const void *fel = DPOC(from, t->offset);
947 void *tel = DPO(to, t->offset);
948 void **ptel = (void **)tel;
949 size_t size;
950
951 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
952 size = sizeofType(t->ptr);
953 } else {
954 const struct asn1_type_func *f = t->ptr;
955 size = f->size;
956 }
957
958 if (t->tt & A1_FLAG_OPTIONAL) {
959 void **pfel = (void **)fel;
960 if (*pfel == NULL)
961 break;
962 fel = *pfel;
963
964 tel = *ptel = calloc(1, size);
965 if (tel == NULL)
966 return ENOMEM;
967 }
968
969 if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
970 ret = _asn1_copy(t->ptr, fel, tel);
971 } else {
972 const struct asn1_type_func *f = t->ptr;
973 ret = (f->copy)(fel, tel);
974 }
975
976 if (ret) {
977 if (t->tt & A1_FLAG_OPTIONAL) {
978 free(*ptel);
979 *ptel = NULL;
980 }
981 return ret;
982 }
983 break;
984 }
985 case A1_OP_PARSE: {
986 unsigned int type = A1_PARSE_TYPE(t->tt);
987 const void *fel = DPOC(from, t->offset);
988 void *tel = DPO(to, t->offset);
989
990 if (type > sizeof(prim)/sizeof(prim[0])) {
991 ABORT_ON_ERROR();
992 return ASN1_PARSE_ERROR;
993 }
994 ret = (prim[type].copy)(fel, tel);
995 if (ret)
996 return ret;
997 break;
998 }
999 case A1_OP_TAG: {
1000 const void *oldfrom = from;
1001 void *oldto = to;
1002 void **tel = NULL;
1003
1004 from = DPOC(from, t->offset);
1005 to = DPO(to, t->offset);
1006
1007 if (t->tt & A1_FLAG_OPTIONAL) {
1008 void **fel = (void **)from;
1009 tel = (void **)to;
1010 if (*fel == NULL) {
1011 from = oldfrom;
1012 to = oldto;
1013 break;
1014 }
1015 from = *fel;
1016
1017 to = *tel = calloc(1, sizeofType(t->ptr));
1018 if (to == NULL)
1019 return ENOMEM;
1020 }
1021
1022 ret = _asn1_copy(t->ptr, from, to);
1023 if (ret) {
1024 if (t->tt & A1_FLAG_OPTIONAL) {
1025 free(*tel);
1026 *tel = NULL;
1027 }
1028 return ret;
1029 }
1030
1031 from = oldfrom;
1032 to = oldto;
1033
1034 break;
1035 }
1036 case A1_OP_SETOF:
1037 case A1_OP_SEQOF: {
1038 const struct template_of *fel = DPOC(from, t->offset);
1039 struct template_of *tel = DPO(to, t->offset);
1040 size_t ellen = sizeofType(t->ptr);
1041 unsigned int i;
1042
1043 tel->val = calloc(fel->len, ellen);
1044 if (tel->val == NULL)
1045 return ENOMEM;
1046
1047 tel->len = fel->len;
1048
1049 for (i = 0; i < fel->len; i++) {
1050 ret = _asn1_copy(t->ptr,
1051 DPOC(fel->val, (i * ellen)),
1052 DPO(tel->val, (i *ellen)));
1053 if (ret)
1054 return ret;
1055 }
1056 break;
1057 }
1058 case A1_OP_BMEMBER: {
1059 const struct asn1_template *bmember = t->ptr;
1060 size_t size = bmember->offset;
1061 memcpy(to, from, size);
1062 break;
1063 }
1064 case A1_OP_CHOICE: {
1065 const struct asn1_template *choice = t->ptr;
1066 const unsigned int *felement = DPOC(from, choice->offset);
1067 unsigned int *telement = DPO(to, choice->offset);
1068
1069 if (*felement > A1_HEADER_LEN(choice))
1070 return ASN1_PARSE_ERROR;
1071
1072 *telement = *felement;
1073
1074 if (*felement == 0) {
1075 ret = der_copy_octet_string(DPOC(from, choice->tt), DPO(to, choice->tt));
1076 } else {
1077 choice += *felement;
1078 ret = _asn1_copy(choice->ptr,
1079 DPOC(from, choice->offset),
1080 DPO(to, choice->offset));
1081 }
1082 if (ret)
1083 return ret;
1084 break;
1085 }
1086 default:
1087 ABORT_ON_ERROR();
1088 break;
1089 }
1090 t++;
1091 elements--;
1092 }
1093 return 0;
1094 }
1095
1096 int
_asn1_decode_top(const struct asn1_template * t,unsigned flags,const unsigned char * p,size_t len,void * data,size_t * size)1097 _asn1_decode_top(const struct asn1_template *t, unsigned flags, const unsigned char *p, size_t len, void *data, size_t *size)
1098 {
1099 int ret;
1100 memset(data, 0, t->offset);
1101 ret = _asn1_decode(t, flags, p, len, data, size);
1102 if (ret) {
1103 _asn1_free(t, data);
1104 memset(data, 0, t->offset);
1105 }
1106
1107 return ret;
1108 }
1109
1110 int
_asn1_copy_top(const struct asn1_template * t,const void * from,void * to)1111 _asn1_copy_top(const struct asn1_template *t, const void *from, void *to)
1112 {
1113 int ret;
1114 memset(to, 0, t->offset);
1115 ret = _asn1_copy(t, from, to);
1116 if (ret) {
1117 _asn1_free(t, to);
1118 memset(to, 0, t->offset);
1119 }
1120 return ret;
1121 }
1122