Imported Upstream version 1.15.1
[platform/upstream/krb5.git] / src / lib / krb5 / asn.1 / asn1_encode.c
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/asn.1/asn1_encode.c */
3 /*
4  * Copyright 1994, 2008 by the Massachusetts Institute of Technology.
5  * All Rights Reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  Furthermore if you modify this software you must label
20  * your software as modified software and not distribute it in such a
21  * fashion that it might be confused with the original M.I.T. software.
22  * M.I.T. makes no representations about the suitability of
23  * this software for any purpose.  It is provided "as is" without express
24  * or implied warranty.
25  */
26
27 #include "asn1_encode.h"
28
29 /**** Functions for encoding primitive types ****/
30
31 asn1_error_code
32 k5_asn1_encode_bool(asn1buf *buf, intmax_t val, size_t *len_out)
33 {
34     asn1_octet bval = val ? 0xFF : 0x00;
35
36     *len_out = 1;
37     return asn1buf_insert_octet(buf, bval);
38 }
39
40 asn1_error_code
41 k5_asn1_encode_int(asn1buf *buf, intmax_t val, size_t *len_out)
42 {
43     asn1_error_code ret;
44     size_t len = 0;
45     long valcopy;
46     int digit;
47
48     valcopy = val;
49     do {
50         digit = valcopy & 0xFF;
51         ret = asn1buf_insert_octet(buf, digit);
52         if (ret)
53             return ret;
54         len++;
55         valcopy = valcopy >> 8;
56     } while (valcopy != 0 && valcopy != ~0);
57
58     if (val > 0 && (digit & 0x80) == 0x80) { /* make sure the high bit is */
59         ret = asn1buf_insert_octet(buf, 0);  /* of the proper signed-ness */
60         if (ret)
61             return ret;
62         len++;
63     } else if (val < 0 && (digit & 0x80) != 0x80) {
64         ret = asn1buf_insert_octet(buf, 0xFF);
65         if (ret)
66             return ret;
67         len++;
68     }
69
70
71     *len_out = len;
72     return 0;
73 }
74
75 asn1_error_code
76 k5_asn1_encode_uint(asn1buf *buf, uintmax_t val, size_t *len_out)
77 {
78     asn1_error_code ret;
79     size_t len = 0;
80     uintmax_t valcopy;
81     int digit;
82
83     valcopy = val;
84     do {
85         digit = valcopy & 0xFF;
86         ret = asn1buf_insert_octet(buf, digit);
87         if (ret)
88             return ret;
89         len++;
90         valcopy = valcopy >> 8;
91     } while (valcopy != 0);
92
93     if (digit & 0x80) {                     /* make sure the high bit is */
94         ret = asn1buf_insert_octet(buf, 0); /* of the proper signed-ness */
95         if (ret)
96             return ret;
97         len++;
98     }
99
100     *len_out = len;
101     return 0;
102 }
103
104 asn1_error_code
105 k5_asn1_encode_bytestring(asn1buf *buf, unsigned char *const *val, size_t len,
106                           size_t *len_out)
107 {
108     if (len > 0 && val == NULL)
109         return ASN1_MISSING_FIELD;
110     *len_out = len;
111     return asn1buf_insert_octetstring(buf, len, *val);
112 }
113
114 asn1_error_code
115 k5_asn1_encode_generaltime(asn1buf *buf, time_t val, size_t *len_out)
116 {
117     struct tm *gtime, gtimebuf;
118     char s[16];
119     unsigned char *sp;
120     time_t gmt_time = val;
121     int len;
122
123     /*
124      * Time encoding: YYYYMMDDhhmmssZ
125      */
126     if (gmt_time == 0) {
127         sp = (unsigned char *)"19700101000000Z";
128     } else {
129         /*
130          * Sanity check this just to be paranoid, as gmtime can return NULL,
131          * and some bogus implementations might overrun on the sprintf.
132          */
133 #ifdef HAVE_GMTIME_R
134 #ifdef GMTIME_R_RETURNS_INT
135         if (gmtime_r(&gmt_time, &gtimebuf) != 0)
136             return ASN1_BAD_GMTIME;
137 #else
138         if (gmtime_r(&gmt_time, &gtimebuf) == NULL)
139             return ASN1_BAD_GMTIME;
140 #endif
141 #else /* HAVE_GMTIME_R */
142         gtime = gmtime(&gmt_time);
143         if (gtime == NULL)
144             return ASN1_BAD_GMTIME;
145         memcpy(&gtimebuf, gtime, sizeof(gtimebuf));
146 #endif /* HAVE_GMTIME_R */
147         gtime = &gtimebuf;
148
149         if (gtime->tm_year > 8099 || gtime->tm_mon > 11 ||
150             gtime->tm_mday > 31 || gtime->tm_hour > 23 ||
151             gtime->tm_min > 59 || gtime->tm_sec > 59)
152             return ASN1_BAD_GMTIME;
153         len = snprintf(s, sizeof(s), "%04d%02d%02d%02d%02d%02dZ",
154                        1900 + gtime->tm_year, gtime->tm_mon + 1,
155                        gtime->tm_mday, gtime->tm_hour,
156                        gtime->tm_min, gtime->tm_sec);
157         if (SNPRINTF_OVERFLOW(len, sizeof(s)))
158             /* Shouldn't be possible given above tests.  */
159             return ASN1_BAD_GMTIME;
160         sp = (unsigned char *)s;
161     }
162
163     return k5_asn1_encode_bytestring(buf, &sp, 15, len_out);
164 }
165
166 asn1_error_code
167 k5_asn1_encode_bitstring(asn1buf *buf, unsigned char *const *val, size_t len,
168                          size_t *len_out)
169 {
170     asn1_error_code ret;
171
172     ret = asn1buf_insert_octetstring(buf, len, *val);
173     if (ret)
174         return ret;
175     *len_out = len + 1;
176     return asn1buf_insert_octet(buf, '\0');
177 }
178
179 /**** Functions for decoding primitive types ****/
180
181 asn1_error_code
182 k5_asn1_decode_bool(const unsigned char *asn1, size_t len, intmax_t *val)
183 {
184     if (len != 1)
185         return ASN1_BAD_LENGTH;
186     *val = (*asn1 != 0);
187     return 0;
188 }
189
190 /* Decode asn1/len as the contents of a DER integer, placing the signed result
191  * in val. */
192 asn1_error_code
193 k5_asn1_decode_int(const unsigned char *asn1, size_t len, intmax_t *val)
194 {
195     intmax_t n;
196     size_t i;
197
198     if (len == 0)
199         return ASN1_BAD_LENGTH;
200     n = (asn1[0] & 0x80) ? -1 : 0;
201     /* Check length; allow extra octet if first octet is 0. */
202     if (len > sizeof(intmax_t) + (asn1[0] == 0))
203         return ASN1_OVERFLOW;
204     for (i = 0; i < len; i++)
205         n = (n << 8) | asn1[i];
206     *val = n;
207     return 0;
208 }
209
210 /* Decode asn1/len as the contents of a DER integer, placing the unsigned
211  * result in val. */
212 asn1_error_code
213 k5_asn1_decode_uint(const unsigned char *asn1, size_t len, uintmax_t *val)
214 {
215     uintmax_t n;
216     size_t i;
217
218     if (len == 0)
219         return ASN1_BAD_LENGTH;
220     /* Check for negative values and check length. */
221     if ((asn1[0] & 0x80) || len > sizeof(uintmax_t) + (asn1[0] == 0))
222         return ASN1_OVERFLOW;
223     for (i = 0, n = 0; i < len; i++)
224         n = (n << 8) | asn1[i];
225     *val = n;
226     return 0;
227 }
228
229 asn1_error_code
230 k5_asn1_decode_bytestring(const unsigned char *asn1, size_t len,
231                           unsigned char **str_out, size_t *len_out)
232 {
233     unsigned char *str;
234
235     *str_out = NULL;
236     *len_out = 0;
237     if (len == 0)
238         return 0;
239     str = malloc(len);
240     if (str == NULL)
241         return ENOMEM;
242     memcpy(str, asn1, len);
243     *str_out = str;
244     *len_out = len;
245     return 0;
246 }
247
248 asn1_error_code
249 k5_asn1_decode_generaltime(const unsigned char *asn1, size_t len,
250                            time_t *time_out)
251 {
252     const char *s = (char *)asn1;
253     struct tm ts;
254     time_t t;
255
256     *time_out = 0;
257     if (len != 15)
258         return ASN1_BAD_LENGTH;
259     /* Time encoding: YYYYMMDDhhmmssZ */
260     if (s[14] != 'Z')
261         return ASN1_BAD_FORMAT;
262     if (memcmp(s, "19700101000000Z", 15) == 0) {
263         *time_out = 0;
264         return 0;
265     }
266 #define c2i(c) ((c) - '0')
267     ts.tm_year = 1000 * c2i(s[0]) + 100 * c2i(s[1]) + 10 * c2i(s[2]) +
268         c2i(s[3]) - 1900;
269     ts.tm_mon = 10 * c2i(s[4]) + c2i(s[5]) - 1;
270     ts.tm_mday = 10 * c2i(s[6]) + c2i(s[7]);
271     ts.tm_hour = 10 * c2i(s[8]) + c2i(s[9]);
272     ts.tm_min = 10 * c2i(s[10]) + c2i(s[11]);
273     ts.tm_sec = 10 * c2i(s[12]) + c2i(s[13]);
274     ts.tm_isdst = -1;
275     t = krb5int_gmt_mktime(&ts);
276     if (t == -1)
277         return ASN1_BAD_TIMEFORMAT;
278     *time_out = t;
279     return 0;
280 }
281
282 /*
283  * Note: we return the number of bytes, not bits, in the bit string.  If the
284  * number of bits is not a multiple of 8 we effectively round up to the next
285  * multiple of 8.
286  */
287 asn1_error_code
288 k5_asn1_decode_bitstring(const unsigned char *asn1, size_t len,
289                          unsigned char **bits_out, size_t *len_out)
290 {
291     unsigned char unused, *bits;
292
293     *bits_out = NULL;
294     *len_out = 0;
295     if (len == 0)
296         return ASN1_BAD_LENGTH;
297     unused = *asn1++;
298     len--;
299     if (unused > 7)
300         return ASN1_BAD_FORMAT;
301
302     bits = malloc(len);
303     if (bits == NULL)
304         return ENOMEM;
305     memcpy(bits, asn1, len);
306     if (len > 1)
307         bits[len - 1] &= (0xff << unused);
308
309     *bits_out = bits;
310     *len_out = len;
311     return 0;
312 }
313
314 /**** Functions for encoding and decoding tags ****/
315
316 /* Encode a DER tag into buf with the tag parameters in t and the content
317  * length len.  Place the length of the encoded tag in *retlen. */
318 static asn1_error_code
319 make_tag(asn1buf *buf, const taginfo *t, size_t len, size_t *retlen)
320 {
321     asn1_error_code ret;
322     asn1_tagnum tag_copy;
323     size_t sum = 0, length, len_copy;
324
325     if (t->tagnum > ASN1_TAGNUM_MAX)
326         return ASN1_OVERFLOW;
327
328     /* Encode the length of the content within the tag. */
329     if (len < 128) {
330         ret = asn1buf_insert_octet(buf, len & 0x7F);
331         if (ret)
332             return ret;
333         length = 1;
334     } else {
335         length = 0;
336         for (len_copy = len; len_copy != 0; len_copy >>= 8) {
337             ret = asn1buf_insert_octet(buf, len_copy & 0xFF);
338             if (ret)
339                 return ret;
340             length++;
341         }
342         ret = asn1buf_insert_octet(buf, 0x80 | (length & 0x7F));
343         if (ret)
344             return ret;
345         length++;
346     }
347     sum += length;
348
349     /* Encode the tag and construction bit. */
350     if (t->tagnum < 31) {
351         ret = asn1buf_insert_octet(buf,
352                                    t->asn1class | t->construction | t->tagnum);
353         if (ret)
354             return ret;
355         length = 1;
356     } else {
357         tag_copy = t->tagnum;
358         length = 0;
359         ret = asn1buf_insert_octet(buf, tag_copy & 0x7F);
360         if (ret)
361             return ret;
362         tag_copy >>= 7;
363         length++;
364
365         for (; tag_copy != 0; tag_copy >>= 7) {
366             ret = asn1buf_insert_octet(buf, 0x80 | (tag_copy & 0x7F));
367             if (ret)
368                 return ret;
369             length++;
370         }
371
372         ret = asn1buf_insert_octet(buf, t->asn1class | t->construction | 0x1F);
373         if (ret)
374             return ret;
375         length++;
376     }
377     sum += length;
378
379     *retlen = sum;
380     return 0;
381 }
382
383 /*
384  * Read a BER tag and length from asn1/len.  Place the tag parameters in
385  * tag_out.  Set contents_out/clen_out to the octet range of the tag's
386  * contents, and remainder_out/rlen_out to the octet range after the end of the
387  * BER encoding.
388  *
389  * (krb5 ASN.1 encodings should be in DER, but for compatibility with some
390  * really ancient implementations we handle the indefinite length form in tags.
391  * However, we still insist on the primitive form of string types.)
392  */
393 static asn1_error_code
394 get_tag(const unsigned char *asn1, size_t len, taginfo *tag_out,
395         const unsigned char **contents_out, size_t *clen_out,
396         const unsigned char **remainder_out, size_t *rlen_out)
397 {
398     asn1_error_code ret;
399     unsigned char o;
400     const unsigned char *c, *p, *tag_start = asn1;
401     size_t clen, llen, i;
402     taginfo t;
403
404     *contents_out = *remainder_out = NULL;
405     *clen_out = *rlen_out = 0;
406     if (len == 0)
407         return ASN1_OVERRUN;
408     o = *asn1++;
409     len--;
410     tag_out->asn1class = o & 0xC0;
411     tag_out->construction = o & 0x20;
412     if ((o & 0x1F) != 0x1F) {
413         tag_out->tagnum = o & 0x1F;
414     } else {
415         tag_out->tagnum = 0;
416         do {
417             if (len == 0)
418                 return ASN1_OVERRUN;
419             o = *asn1++;
420             len--;
421             tag_out->tagnum = (tag_out->tagnum << 7) | (o & 0x7F);
422         } while (o & 0x80);
423     }
424
425     if (len == 0)
426         return ASN1_OVERRUN;
427     o = *asn1++;
428     len--;
429
430     if (o == 0x80) {
431         /* Indefinite form (should not be present in DER, but we accept it). */
432         if (tag_out->construction != CONSTRUCTED)
433             return ASN1_MISMATCH_INDEF;
434         p = asn1;
435         while (!(len >= 2 && p[0] == 0 && p[1] == 0)) {
436             ret = get_tag(p, len, &t, &c, &clen, &p, &len);
437             if (ret)
438                 return ret;
439         }
440         tag_out->tag_end_len = 2;
441         *contents_out = asn1;
442         *clen_out = p - asn1;
443         *remainder_out = p + 2;
444         *rlen_out = len - 2;
445     } else if ((o & 0x80) == 0) {
446         /* Short form (first octet gives content length). */
447         if (o > len)
448             return ASN1_OVERRUN;
449         tag_out->tag_end_len = 0;
450         *contents_out = asn1;
451         *clen_out = o;
452         *remainder_out = asn1 + *clen_out;
453         *rlen_out = len - (*remainder_out - asn1);
454     } else {
455         /* Long form (first octet gives number of base-256 length octets). */
456         llen = o & 0x7F;
457         if (llen > len)
458             return ASN1_OVERRUN;
459         if (llen > sizeof(*clen_out))
460             return ASN1_OVERFLOW;
461         for (i = 0, clen = 0; i < llen; i++)
462             clen = (clen << 8) | asn1[i];
463         if (clen > len - llen)
464             return ASN1_OVERRUN;
465         tag_out->tag_end_len = 0;
466         *contents_out = asn1 + llen;
467         *clen_out = clen;
468         *remainder_out = *contents_out + clen;
469         *rlen_out = len - (*remainder_out - asn1);
470     }
471     tag_out->tag_len = *contents_out - tag_start;
472     return 0;
473 }
474
475 #ifdef POINTERS_ARE_ALL_THE_SAME
476 #define LOADPTR(PTR, TYPE) (*(const void *const *)(PTR))
477 #define STOREPTR(PTR, TYPE, VAL) (*(void **)(VAL) = (PTR))
478 #else
479 #define LOADPTR(PTR, PTRINFO)                                           \
480     (assert((PTRINFO)->loadptr != NULL), (PTRINFO)->loadptr(PTR))
481 #define STOREPTR(PTR, PTRINFO, VAL)                                     \
482     (assert((PTRINFO)->storeptr != NULL), (PTRINFO)->storeptr(PTR, VAL))
483 #endif
484
485 static size_t
486 get_nullterm_sequence_len(const void *valp, const struct atype_info *seq)
487 {
488     size_t i;
489     const struct atype_info *a;
490     const struct ptr_info *ptr;
491     const void *elt, *eltptr;
492
493     a = seq;
494     i = 0;
495     assert(a->type == atype_ptr);
496     assert(seq->size != 0);
497     ptr = a->tinfo;
498
499     while (1) {
500         eltptr = (const char *)valp + i * seq->size;
501         elt = LOADPTR(eltptr, ptr);
502         if (elt == NULL)
503             break;
504         i++;
505     }
506     return i;
507 }
508 static asn1_error_code
509 encode_sequence_of(asn1buf *buf, size_t seqlen, const void *val,
510                    const struct atype_info *eltinfo, size_t *len_out);
511
512 static asn1_error_code
513 encode_nullterm_sequence_of(asn1buf *buf, const void *val,
514                             const struct atype_info *type,
515                             int can_be_empty, size_t *len_out)
516 {
517     size_t len = get_nullterm_sequence_len(val, type);
518
519     if (!can_be_empty && len == 0)
520         return ASN1_MISSING_FIELD;
521     return encode_sequence_of(buf, len, val, type, len_out);
522 }
523
524 static intmax_t
525 load_int(const void *val, size_t size)
526 {
527     switch (size) {
528     case 1: return *(signed char *)val;
529     case 2: return *(krb5_int16 *)val;
530     case 4: return *(krb5_int32 *)val;
531     case 8: return *(int64_t *)val;
532     default: abort();
533     }
534 }
535
536 static uintmax_t
537 load_uint(const void *val, size_t size)
538 {
539     switch (size) {
540     case 1: return *(unsigned char *)val;
541     case 2: return *(krb5_ui_2 *)val;
542     case 4: return *(krb5_ui_4 *)val;
543     case 8: return *(uint64_t *)val;
544     default: abort();
545     }
546 }
547
548 static asn1_error_code
549 load_count(const void *val, const struct counted_info *counted,
550            size_t *count_out)
551 {
552     const void *countptr = (const char *)val + counted->lenoff;
553
554     assert(sizeof(size_t) <= sizeof(uintmax_t));
555     if (counted->lensigned) {
556         intmax_t xlen = load_int(countptr, counted->lensize);
557         if (xlen < 0 || (uintmax_t)xlen > SIZE_MAX)
558             return EINVAL;
559         *count_out = xlen;
560     } else {
561         uintmax_t xlen = load_uint(countptr, counted->lensize);
562         if ((size_t)xlen != xlen || xlen > SIZE_MAX)
563             return EINVAL;
564         *count_out = xlen;
565     }
566     return 0;
567 }
568
569 static asn1_error_code
570 store_int(intmax_t intval, size_t size, void *val)
571 {
572     switch (size) {
573     case 1:
574         if ((signed char)intval != intval)
575             return ASN1_OVERFLOW;
576         *(signed char *)val = intval;
577         return 0;
578     case 2:
579         if ((krb5_int16)intval != intval)
580             return ASN1_OVERFLOW;
581         *(krb5_int16 *)val = intval;
582         return 0;
583     case 4:
584         if ((krb5_int32)intval != intval)
585             return ASN1_OVERFLOW;
586         *(krb5_int32 *)val = intval;
587         return 0;
588     case 8:
589         if ((int64_t)intval != intval)
590             return ASN1_OVERFLOW;
591         *(int64_t *)val = intval;
592         return 0;
593     default:
594         abort();
595     }
596 }
597
598 static asn1_error_code
599 store_uint(uintmax_t intval, size_t size, void *val)
600 {
601     switch (size) {
602     case 1:
603         if ((unsigned char)intval != intval)
604             return ASN1_OVERFLOW;
605         *(unsigned char *)val = intval;
606         return 0;
607     case 2:
608         if ((krb5_ui_2)intval != intval)
609             return ASN1_OVERFLOW;
610         *(krb5_ui_2 *)val = intval;
611         return 0;
612     case 4:
613         if ((krb5_ui_4)intval != intval)
614             return ASN1_OVERFLOW;
615         *(krb5_ui_4 *)val = intval;
616         return 0;
617     case 8:
618         if ((uint64_t)intval != intval)
619             return ASN1_OVERFLOW;
620         *(uint64_t *)val = intval;
621         return 0;
622     default:
623         abort();
624     }
625 }
626
627 /* Store a count value in an integer field of a structure.  If count is
628  * SIZE_MAX and the target is a signed field, store -1. */
629 static asn1_error_code
630 store_count(size_t count, const struct counted_info *counted, void *val)
631 {
632     void *countptr = (char *)val + counted->lenoff;
633
634     if (counted->lensigned) {
635         if (count == SIZE_MAX)
636             return store_int(-1, counted->lensize, countptr);
637         else if ((intmax_t)count < 0)
638             return ASN1_OVERFLOW;
639         else
640             return store_int(count, counted->lensize, countptr);
641     } else
642         return store_uint(count, counted->lensize, countptr);
643 }
644
645 /* Split a DER encoding into tag and contents.  Insert the contents into buf,
646  * then return the length of the contents and the tag. */
647 static asn1_error_code
648 split_der(asn1buf *buf, unsigned char *const *der, size_t len,
649           taginfo *tag_out, size_t *len_out)
650 {
651     asn1_error_code ret;
652     const unsigned char *contents, *remainder;
653     size_t clen, rlen;
654
655     ret = get_tag(*der, len, tag_out, &contents, &clen, &remainder, &rlen);
656     if (ret)
657         return ret;
658     if (rlen != 0)
659         return ASN1_BAD_LENGTH;
660     *len_out = clen;
661     return asn1buf_insert_bytestring(buf, clen, contents);
662 }
663
664 /*
665  * Store the DER encoding given by t and asn1/len into the char * or
666  * unsigned char * pointed to by val.  Set *count_out to the length of the
667  * DER encoding.
668  */
669 static asn1_error_code
670 store_der(const taginfo *t, const unsigned char *asn1, size_t len, void *val,
671           size_t *count_out)
672 {
673     unsigned char *der;
674     size_t der_len;
675
676     *count_out = 0;
677     der_len = t->tag_len + len + t->tag_end_len;
678     der = malloc(der_len);
679     if (der == NULL)
680         return ENOMEM;
681     memcpy(der, asn1 - t->tag_len, der_len);
682     *(unsigned char **)val = der;
683     *count_out = der_len;
684     return 0;
685 }
686
687 static asn1_error_code
688 encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq,
689                 size_t *len_out);
690 static asn1_error_code
691 encode_cntype(asn1buf *buf, const void *val, size_t len,
692               const struct cntype_info *c, taginfo *tag_out, size_t *len_out);
693
694 /* Encode a value (contents only, no outer tag) according to a type, and return
695  * its encoded tag information. */
696 static asn1_error_code
697 encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
698              taginfo *tag_out, size_t *len_out)
699 {
700     asn1_error_code ret;
701
702     if (val == NULL)
703         return ASN1_MISSING_FIELD;
704
705     switch (a->type) {
706     case atype_fn: {
707         const struct fn_info *fn = a->tinfo;
708         assert(fn->enc != NULL);
709         return fn->enc(buf, val, tag_out, len_out);
710     }
711     case atype_sequence:
712         assert(a->tinfo != NULL);
713         ret = encode_sequence(buf, val, a->tinfo, len_out);
714         if (ret)
715             return ret;
716         tag_out->asn1class = UNIVERSAL;
717         tag_out->construction = CONSTRUCTED;
718         tag_out->tagnum = ASN1_SEQUENCE;
719         break;
720     case atype_ptr: {
721         const struct ptr_info *ptr = a->tinfo;
722         assert(ptr->basetype != NULL);
723         return encode_atype(buf, LOADPTR(val, ptr), ptr->basetype, tag_out,
724                             len_out);
725     }
726     case atype_offset: {
727         const struct offset_info *off = a->tinfo;
728         assert(off->basetype != NULL);
729         return encode_atype(buf, (const char *)val + off->dataoff,
730                             off->basetype, tag_out, len_out);
731     }
732     case atype_optional: {
733         const struct optional_info *opt = a->tinfo;
734         assert(opt->is_present != NULL);
735         if (opt->is_present(val))
736             return encode_atype(buf, val, opt->basetype, tag_out, len_out);
737         else
738             return ASN1_OMITTED;
739     }
740     case atype_counted: {
741         const struct counted_info *counted = a->tinfo;
742         const void *dataptr = (const char *)val + counted->dataoff;
743         size_t count;
744         assert(counted->basetype != NULL);
745         ret = load_count(val, counted, &count);
746         if (ret)
747             return ret;
748         return encode_cntype(buf, dataptr, count, counted->basetype, tag_out,
749                              len_out);
750     }
751     case atype_nullterm_sequence_of:
752     case atype_nonempty_nullterm_sequence_of:
753         assert(a->tinfo != NULL);
754         ret = encode_nullterm_sequence_of(buf, val, a->tinfo,
755                                           a->type ==
756                                           atype_nullterm_sequence_of,
757                                           len_out);
758         if (ret)
759             return ret;
760         tag_out->asn1class = UNIVERSAL;
761         tag_out->construction = CONSTRUCTED;
762         tag_out->tagnum = ASN1_SEQUENCE;
763         break;
764     case atype_tagged_thing: {
765         const struct tagged_info *tag = a->tinfo;
766         ret = encode_atype(buf, val, tag->basetype, tag_out, len_out);
767         if (ret)
768             return ret;
769         if (!tag->implicit) {
770             size_t tlen;
771             ret = make_tag(buf, tag_out, *len_out, &tlen);
772             if (ret)
773                 return ret;
774             *len_out += tlen;
775             tag_out->construction = tag->construction;
776         }
777         tag_out->asn1class = tag->tagtype;
778         tag_out->tagnum = tag->tagval;
779         break;
780     }
781     case atype_bool:
782         ret = k5_asn1_encode_bool(buf, load_int(val, a->size), len_out);
783         if (ret)
784             return ret;
785         tag_out->asn1class = UNIVERSAL;
786         tag_out->construction = PRIMITIVE;
787         tag_out->tagnum = ASN1_BOOLEAN;
788         break;
789     case atype_int:
790         ret = k5_asn1_encode_int(buf, load_int(val, a->size), len_out);
791         if (ret)
792             return ret;
793         tag_out->asn1class = UNIVERSAL;
794         tag_out->construction = PRIMITIVE;
795         tag_out->tagnum = ASN1_INTEGER;
796         break;
797     case atype_uint:
798         ret = k5_asn1_encode_uint(buf, load_uint(val, a->size), len_out);
799         if (ret)
800             return ret;
801         tag_out->asn1class = UNIVERSAL;
802         tag_out->construction = PRIMITIVE;
803         tag_out->tagnum = ASN1_INTEGER;
804         break;
805     case atype_int_immediate: {
806         const struct immediate_info *imm = a->tinfo;
807         ret = k5_asn1_encode_int(buf, imm->val, len_out);
808         if (ret)
809             return ret;
810         tag_out->asn1class = UNIVERSAL;
811         tag_out->construction = PRIMITIVE;
812         tag_out->tagnum = ASN1_INTEGER;
813         break;
814     }
815     default:
816         assert(a->type > atype_min);
817         assert(a->type < atype_max);
818         abort();
819     }
820
821     return 0;
822 }
823
824 static asn1_error_code
825 encode_atype_and_tag(asn1buf *buf, const void *val, const struct atype_info *a,
826                      size_t *len_out)
827 {
828     taginfo t;
829     asn1_error_code ret;
830     size_t clen, tlen;
831
832     ret = encode_atype(buf, val, a, &t, &clen);
833     if (ret)
834         return ret;
835     ret = make_tag(buf, &t, clen, &tlen);
836     if (ret)
837         return ret;
838     *len_out = clen + tlen;
839     return 0;
840 }
841
842 /*
843  * Encode an object and count according to a cntype_info structure.  val is a
844  * pointer to the object being encoded, which in most cases is itself a
845  * pointer (but is a union in the cntype_choice case).
846  */
847 static asn1_error_code
848 encode_cntype(asn1buf *buf, const void *val, size_t count,
849               const struct cntype_info *c, taginfo *tag_out, size_t *len_out)
850 {
851     asn1_error_code ret;
852
853     switch (c->type) {
854     case cntype_string: {
855         const struct string_info *string = c->tinfo;
856         assert(string->enc != NULL);
857         ret = string->enc(buf, val, count, len_out);
858         if (ret)
859             return ret;
860         tag_out->asn1class = UNIVERSAL;
861         tag_out->construction = PRIMITIVE;
862         tag_out->tagnum = string->tagval;
863         break;
864     }
865     case cntype_der:
866         return split_der(buf, val, count, tag_out, len_out);
867     case cntype_seqof: {
868         const struct atype_info *a = c->tinfo;
869         const struct ptr_info *ptr = a->tinfo;
870         assert(a->type == atype_ptr);
871         val = LOADPTR(val, ptr);
872         ret = encode_sequence_of(buf, count, val, ptr->basetype, len_out);
873         if (ret)
874             return ret;
875         tag_out->asn1class = UNIVERSAL;
876         tag_out->construction = CONSTRUCTED;
877         tag_out->tagnum = ASN1_SEQUENCE;
878         break;
879     }
880     case cntype_choice: {
881         const struct choice_info *choice = c->tinfo;
882         if (count >= choice->n_options)
883             return ASN1_MISSING_FIELD;
884         return encode_atype(buf, val, choice->options[count], tag_out,
885                             len_out);
886     }
887
888     default:
889         assert(c->type > cntype_min);
890         assert(c->type < cntype_max);
891         abort();
892     }
893
894     return 0;
895 }
896
897 static asn1_error_code
898 encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq,
899                 size_t *len_out)
900 {
901     asn1_error_code ret;
902     size_t i, len, sum = 0;
903
904     for (i = seq->n_fields; i > 0; i--) {
905         ret = encode_atype_and_tag(buf, val, seq->fields[i - 1], &len);
906         if (ret == ASN1_OMITTED)
907             continue;
908         else if (ret != 0)
909             return ret;
910         sum += len;
911     }
912     *len_out = sum;
913     return 0;
914 }
915
916 static asn1_error_code
917 encode_sequence_of(asn1buf *buf, size_t seqlen, const void *val,
918                    const struct atype_info *eltinfo, size_t *len_out)
919 {
920     asn1_error_code ret;
921     size_t sum = 0, i, len;
922     const void *eltptr;
923
924     assert(eltinfo->size != 0);
925     for (i = seqlen; i > 0; i--) {
926         eltptr = (const char *)val + (i - 1) * eltinfo->size;
927         ret = encode_atype_and_tag(buf, eltptr, eltinfo, &len);
928         if (ret)
929             return ret;
930         sum += len;
931     }
932     *len_out = sum;
933     return 0;
934 }
935
936 /**** Functions for freeing C objects based on type info ****/
937
938 static void free_atype_ptr(const struct atype_info *a, void *val);
939 static void free_sequence(const struct seq_info *seq, void *val);
940 static void free_sequence_of(const struct atype_info *eltinfo, void *val,
941                              size_t count);
942 static void free_cntype(const struct cntype_info *a, void *val, size_t count);
943
944 /*
945  * Free a C object according to a type description.  Do not free pointers at
946  * the first level; they may be referenced by other fields of a sequence, and
947  * will be freed by free_atype_ptr in a second pass.
948  */
949 static void
950 free_atype(const struct atype_info *a, void *val)
951 {
952     switch (a->type) {
953     case atype_fn: {
954         const struct fn_info *fn = a->tinfo;
955         if (fn->free_func != NULL)
956             fn->free_func(val);
957         break;
958     }
959     case atype_sequence:
960         free_sequence(a->tinfo, val);
961         break;
962     case atype_ptr: {
963         const struct ptr_info *ptrinfo = a->tinfo;
964         void *ptr = LOADPTR(val, ptrinfo);
965         if (ptr != NULL) {
966             free_atype(ptrinfo->basetype, ptr);
967             free_atype_ptr(ptrinfo->basetype, ptr);
968         }
969         break;
970     }
971     case atype_offset: {
972         const struct offset_info *off = a->tinfo;
973         assert(off->basetype != NULL);
974         free_atype(off->basetype, (char *)val + off->dataoff);
975         break;
976     }
977     case atype_optional: {
978         const struct optional_info *opt = a->tinfo;
979         free_atype(opt->basetype, val);
980         break;
981     }
982     case atype_counted: {
983         const struct counted_info *counted = a->tinfo;
984         void *dataptr = (char *)val + counted->dataoff;
985         size_t count;
986         if (load_count(val, counted, &count) == 0)
987             free_cntype(counted->basetype, dataptr, count);
988         break;
989     }
990     case atype_nullterm_sequence_of:
991     case atype_nonempty_nullterm_sequence_of: {
992         size_t count = get_nullterm_sequence_len(val, a->tinfo);
993         free_sequence_of(a->tinfo, val, count);
994         break;
995     }
996     case atype_tagged_thing: {
997         const struct tagged_info *tag = a->tinfo;
998         free_atype(tag->basetype, val);
999         break;
1000     }
1001     case atype_bool:
1002     case atype_int:
1003     case atype_uint:
1004     case atype_int_immediate:
1005         break;
1006     default:
1007         abort();
1008     }
1009 }
1010
1011 static void
1012 free_atype_ptr(const struct atype_info *a, void *val)
1013 {
1014     switch (a->type) {
1015     case atype_fn:
1016     case atype_sequence:
1017     case atype_counted:
1018     case atype_nullterm_sequence_of:
1019     case atype_nonempty_nullterm_sequence_of:
1020     case atype_bool:
1021     case atype_int:
1022     case atype_uint:
1023     case atype_int_immediate:
1024          break;
1025     case atype_ptr: {
1026         const struct ptr_info *ptrinfo = a->tinfo;
1027         void *ptr = LOADPTR(val, ptrinfo);
1028         free(ptr);
1029         STOREPTR(NULL, ptrinfo, val);
1030         break;
1031     }
1032     case atype_offset: {
1033         const struct offset_info *off = a->tinfo;
1034         assert(off->basetype != NULL);
1035         free_atype_ptr(off->basetype, (char *)val + off->dataoff);
1036         break;
1037     }
1038     case atype_optional: {
1039         const struct optional_info *opt = a->tinfo;
1040         free_atype_ptr(opt->basetype, val);
1041         break;
1042     }
1043     case atype_tagged_thing: {
1044         const struct tagged_info *tag = a->tinfo;
1045         free_atype_ptr(tag->basetype, val);
1046         break;
1047     }
1048     default:
1049         abort();
1050     }
1051 }
1052
1053 static void
1054 free_cntype(const struct cntype_info *c, void *val, size_t count)
1055 {
1056     switch (c->type) {
1057     case cntype_string:
1058     case cntype_der:
1059         free(*(char **)val);
1060         *(char **)val = NULL;
1061         break;
1062     case cntype_seqof: {
1063         const struct atype_info *a = c->tinfo;
1064         const struct ptr_info *ptrinfo = a->tinfo;
1065         void *seqptr = LOADPTR(val, ptrinfo);
1066         free_sequence_of(ptrinfo->basetype, seqptr, count);
1067         free(seqptr);
1068         STOREPTR(NULL, ptrinfo, val);
1069         break;
1070     }
1071     case cntype_choice: {
1072         const struct choice_info *choice = c->tinfo;
1073         if (count < choice->n_options) {
1074             free_atype(choice->options[count], val);
1075             free_atype_ptr(choice->options[count], val);
1076         }
1077         break;
1078     }
1079     default:
1080         abort();
1081     }
1082 }
1083
1084 static void
1085 free_sequence(const struct seq_info *seq, void *val)
1086 {
1087     size_t i;
1088
1089     for (i = 0; i < seq->n_fields; i++)
1090         free_atype(seq->fields[i], val);
1091     for (i = 0; i < seq->n_fields; i++)
1092         free_atype_ptr(seq->fields[i], val);
1093 }
1094
1095 static void
1096 free_sequence_of(const struct atype_info *eltinfo, void *val, size_t count)
1097 {
1098     void *eltptr;
1099
1100     assert(eltinfo->size != 0);
1101     while (count-- > 0) {
1102         eltptr = (char *)val + count * eltinfo->size;
1103         free_atype(eltinfo, eltptr);
1104         free_atype_ptr(eltinfo, eltptr);
1105     }
1106 }
1107
1108 /**** Functions for decoding objects based on type info ****/
1109
1110 /* Return nonzero if t is an expected tag for an ASN.1 object of type a. */
1111 static int
1112 check_atype_tag(const struct atype_info *a, const taginfo *t)
1113 {
1114     switch (a->type) {
1115     case atype_fn: {
1116         const struct fn_info *fn = a->tinfo;
1117         assert(fn->check_tag != NULL);
1118         return fn->check_tag(t);
1119     }
1120     case atype_sequence:
1121     case atype_nullterm_sequence_of:
1122     case atype_nonempty_nullterm_sequence_of:
1123         return (t->asn1class == UNIVERSAL && t->construction == CONSTRUCTED &&
1124                 t->tagnum == ASN1_SEQUENCE);
1125     case atype_ptr: {
1126         const struct ptr_info *ptrinfo = a->tinfo;
1127         return check_atype_tag(ptrinfo->basetype, t);
1128     }
1129     case atype_offset: {
1130         const struct offset_info *off = a->tinfo;
1131         return check_atype_tag(off->basetype, t);
1132     }
1133     case atype_optional: {
1134         const struct optional_info *opt = a->tinfo;
1135         return check_atype_tag(opt->basetype, t);
1136     }
1137     case atype_counted: {
1138         const struct counted_info *counted = a->tinfo;
1139         switch (counted->basetype->type) {
1140         case cntype_string: {
1141             const struct string_info *string = counted->basetype->tinfo;
1142             return (t->asn1class == UNIVERSAL &&
1143                     t->construction == PRIMITIVE &&
1144                     t->tagnum == string->tagval);
1145         }
1146         case cntype_seqof:
1147             return (t->asn1class == UNIVERSAL &&
1148                     t->construction == CONSTRUCTED &&
1149                     t->tagnum == ASN1_SEQUENCE);
1150         case cntype_der:
1151             /*
1152              * We treat any tag as matching a stored DER encoding.  In some
1153              * cases we know what the tag should be; in others, we truly want
1154              * to accept any tag.  If it ever becomes an issue, we could add
1155              * optional tag info to the type and check it here.
1156              */
1157             return 1;
1158         case cntype_choice:
1159             /*
1160              * ASN.1 choices may or may not be extensible.  For now, we treat
1161              * all choices as extensible and match any tag.  We should consider
1162              * modeling whether choices are extensible before making the
1163              * encoder visible to plugins.
1164              */
1165             return 1;
1166         default:
1167             abort();
1168         }
1169     }
1170     case atype_tagged_thing: {
1171         const struct tagged_info *tag = a->tinfo;
1172         /* NOTE: Doesn't check construction bit for implicit tags. */
1173         if (!tag->implicit && t->construction != tag->construction)
1174             return 0;
1175         return (t->asn1class == tag->tagtype && t->tagnum == tag->tagval);
1176     }
1177     case atype_bool:
1178         return (t->asn1class == UNIVERSAL && t->construction == PRIMITIVE &&
1179                 t->tagnum == ASN1_BOOLEAN);
1180     case atype_int:
1181     case atype_uint:
1182     case atype_int_immediate:
1183         return (t->asn1class == UNIVERSAL && t->construction == PRIMITIVE &&
1184                 t->tagnum == ASN1_INTEGER);
1185     default:
1186         abort();
1187     }
1188 }
1189
1190 static asn1_error_code
1191 decode_cntype(const taginfo *t, const unsigned char *asn1, size_t len,
1192               const struct cntype_info *c, void *val, size_t *count_out);
1193 static asn1_error_code
1194 decode_atype_to_ptr(const taginfo *t, const unsigned char *asn1, size_t len,
1195                     const struct atype_info *basetype, void **ptr_out);
1196 static asn1_error_code
1197 decode_sequence(const unsigned char *asn1, size_t len,
1198                 const struct seq_info *seq, void *val);
1199 static asn1_error_code
1200 decode_sequence_of(const unsigned char *asn1, size_t len,
1201                    const struct atype_info *elemtype, void **seq_out,
1202                    size_t *count_out);
1203
1204 /* Given the enclosing tag t, decode from asn1/len the contents of the ASN.1
1205  * type specified by a, placing the result into val (caller-allocated). */
1206 static asn1_error_code
1207 decode_atype(const taginfo *t, const unsigned char *asn1,
1208              size_t len, const struct atype_info *a, void *val)
1209 {
1210     asn1_error_code ret;
1211
1212     switch (a->type) {
1213     case atype_fn: {
1214         const struct fn_info *fn = a->tinfo;
1215         assert(fn->dec != NULL);
1216         return fn->dec(t, asn1, len, val);
1217     }
1218     case atype_sequence:
1219         return decode_sequence(asn1, len, a->tinfo, val);
1220     case atype_ptr: {
1221         const struct ptr_info *ptrinfo = a->tinfo;
1222         void *ptr = LOADPTR(val, ptrinfo);
1223         assert(ptrinfo->basetype != NULL);
1224         if (ptr != NULL) {
1225             /* Container was already allocated by a previous sequence field. */
1226             return decode_atype(t, asn1, len, ptrinfo->basetype, ptr);
1227         } else {
1228             ret = decode_atype_to_ptr(t, asn1, len, ptrinfo->basetype, &ptr);
1229             if (ret)
1230                 return ret;
1231             STOREPTR(ptr, ptrinfo, val);
1232             break;
1233         }
1234     }
1235     case atype_offset: {
1236         const struct offset_info *off = a->tinfo;
1237         assert(off->basetype != NULL);
1238         return decode_atype(t, asn1, len, off->basetype,
1239                             (char *)val + off->dataoff);
1240     }
1241     case atype_optional: {
1242         const struct optional_info *opt = a->tinfo;
1243         return decode_atype(t, asn1, len, opt->basetype, val);
1244     }
1245     case atype_counted: {
1246         const struct counted_info *counted = a->tinfo;
1247         void *dataptr = (char *)val + counted->dataoff;
1248         size_t count;
1249         assert(counted->basetype != NULL);
1250         ret = decode_cntype(t, asn1, len, counted->basetype, dataptr, &count);
1251         if (ret)
1252             return ret;
1253         return store_count(count, counted, val);
1254     }
1255     case atype_tagged_thing: {
1256         const struct tagged_info *tag = a->tinfo;
1257         taginfo inner_tag;
1258         const taginfo *tp = t;
1259         const unsigned char *rem;
1260         size_t rlen;
1261         if (!tag->implicit) {
1262             ret = get_tag(asn1, len, &inner_tag, &asn1, &len, &rem, &rlen);
1263             if (ret)
1264                 return ret;
1265             /* Note: we don't check rlen (it should be 0). */
1266             tp = &inner_tag;
1267             if (!check_atype_tag(tag->basetype, tp))
1268                 return ASN1_BAD_ID;
1269         }
1270         return decode_atype(tp, asn1, len, tag->basetype, val);
1271     }
1272     case atype_bool: {
1273         intmax_t intval;
1274         ret = k5_asn1_decode_bool(asn1, len, &intval);
1275         if (ret)
1276             return ret;
1277         return store_int(intval, a->size, val);
1278     }
1279     case atype_int: {
1280         intmax_t intval;
1281         ret = k5_asn1_decode_int(asn1, len, &intval);
1282         if (ret)
1283             return ret;
1284         return store_int(intval, a->size, val);
1285     }
1286     case atype_uint: {
1287         uintmax_t intval;
1288         ret = k5_asn1_decode_uint(asn1, len, &intval);
1289         if (ret)
1290             return ret;
1291         return store_uint(intval, a->size, val);
1292     }
1293     case atype_int_immediate: {
1294         const struct immediate_info *imm = a->tinfo;
1295         intmax_t intval;
1296         ret = k5_asn1_decode_int(asn1, len, &intval);
1297         if (ret)
1298             return ret;
1299         if (intval != imm->val && imm->err != 0)
1300             return imm->err;
1301         break;
1302     }
1303     default:
1304         /* Null-terminated sequence types are handled in decode_atype_to_ptr,
1305          * since they create variable-sized objects. */
1306         assert(a->type != atype_nullterm_sequence_of);
1307         assert(a->type != atype_nonempty_nullterm_sequence_of);
1308         assert(a->type > atype_min);
1309         assert(a->type < atype_max);
1310         abort();
1311     }
1312     return 0;
1313 }
1314
1315 /*
1316  * Given the enclosing tag t, decode from asn1/len the contents of the
1317  * ASN.1 type described by c, placing the counted result into val/count_out.
1318  * If the resulting count should be -1 (for an unknown union distinguisher),
1319  * set *count_out to SIZE_MAX.
1320  */
1321 static asn1_error_code
1322 decode_cntype(const taginfo *t, const unsigned char *asn1, size_t len,
1323               const struct cntype_info *c, void *val, size_t *count_out)
1324 {
1325     asn1_error_code ret;
1326
1327     switch (c->type) {
1328     case cntype_string: {
1329         const struct string_info *string = c->tinfo;
1330         assert(string->dec != NULL);
1331         return string->dec(asn1, len, val, count_out);
1332     }
1333     case cntype_der:
1334         return store_der(t, asn1, len, val, count_out);
1335     case cntype_seqof: {
1336         const struct atype_info *a = c->tinfo;
1337         const struct ptr_info *ptrinfo = a->tinfo;
1338         void *seq;
1339         assert(a->type == atype_ptr);
1340         ret = decode_sequence_of(asn1, len, ptrinfo->basetype, &seq,
1341                                  count_out);
1342         if (ret)
1343             return ret;
1344         STOREPTR(seq, ptrinfo, val);
1345         break;
1346     }
1347     case cntype_choice: {
1348         const struct choice_info *choice = c->tinfo;
1349         size_t i;
1350         for (i = 0; i < choice->n_options; i++) {
1351             if (check_atype_tag(choice->options[i], t)) {
1352                 ret = decode_atype(t, asn1, len, choice->options[i], val);
1353                 if (ret)
1354                     return ret;
1355                 *count_out = i;
1356                 return 0;
1357             }
1358         }
1359         /* SIZE_MAX will be stored as -1 in the distinguisher.  If we start
1360          * modeling non-extensible choices we should check that here. */
1361         *count_out = SIZE_MAX;
1362         break;
1363     }
1364     default:
1365         assert(c->type > cntype_min);
1366         assert(c->type < cntype_max);
1367         abort();
1368     }
1369     return 0;
1370 }
1371
1372 /* Add a null pointer to the end of a sequence.  ptr is consumed on success
1373  * (to be replaced by *ptr_out), left alone on failure. */
1374 static asn1_error_code
1375 null_terminate(const struct atype_info *eltinfo, void *ptr, size_t count,
1376                void **ptr_out)
1377 {
1378     const struct ptr_info *ptrinfo = eltinfo->tinfo;
1379     void *endptr;
1380
1381     assert(eltinfo->type == atype_ptr);
1382     ptr = realloc(ptr, (count + 1) * eltinfo->size);
1383     if (ptr == NULL)
1384         return ENOMEM;
1385     endptr = (char *)ptr + count * eltinfo->size;
1386     STOREPTR(NULL, ptrinfo, endptr);
1387     *ptr_out = ptr;
1388     return 0;
1389 }
1390
1391 static asn1_error_code
1392 decode_atype_to_ptr(const taginfo *t, const unsigned char *asn1,
1393                     size_t len, const struct atype_info *a,
1394                     void **ptr_out)
1395 {
1396     asn1_error_code ret;
1397     void *ptr;
1398     size_t count;
1399
1400     *ptr_out = NULL;
1401     switch (a->type) {
1402     case atype_nullterm_sequence_of:
1403     case atype_nonempty_nullterm_sequence_of:
1404         ret = decode_sequence_of(asn1, len, a->tinfo, &ptr, &count);
1405         if (ret)
1406             return ret;
1407         ret = null_terminate(a->tinfo, ptr, count, &ptr);
1408         if (ret) {
1409             free_sequence_of(a->tinfo, ptr, count);
1410             return ret;
1411         }
1412         /* Historically we do not enforce non-emptiness of sequences when
1413          * decoding, even when it is required by the ASN.1 type. */
1414         break;
1415     default:
1416         ptr = calloc(a->size, 1);
1417         if (ptr == NULL)
1418             return ENOMEM;
1419         ret = decode_atype(t, asn1, len, a, ptr);
1420         if (ret) {
1421             free(ptr);
1422             return ret;
1423         }
1424         break;
1425     }
1426     *ptr_out = ptr;
1427     return 0;
1428 }
1429
1430 /* Initialize a C object when the corresponding ASN.1 type was omitted within a
1431  * sequence.  If the ASN.1 type is not optional, return ASN1_MISSING_FIELD. */
1432 static asn1_error_code
1433 omit_atype(const struct atype_info *a, void *val)
1434 {
1435     switch (a->type)
1436     {
1437     case atype_fn:
1438     case atype_sequence:
1439     case atype_nullterm_sequence_of:
1440     case atype_nonempty_nullterm_sequence_of:
1441     case atype_counted:
1442     case atype_bool:
1443     case atype_int:
1444     case atype_uint:
1445     case atype_int_immediate:
1446         return ASN1_MISSING_FIELD;
1447     case atype_ptr: {
1448         const struct ptr_info *ptrinfo = a->tinfo;
1449         return omit_atype(ptrinfo->basetype, val);
1450     }
1451     case atype_offset: {
1452         const struct offset_info *off = a->tinfo;
1453         return omit_atype(off->basetype, (char *)val + off->dataoff);
1454     }
1455     case atype_tagged_thing: {
1456         const struct tagged_info *tag = a->tinfo;
1457         return omit_atype(tag->basetype, val);
1458     }
1459     case atype_optional: {
1460         const struct optional_info *opt = a->tinfo;
1461         if (opt->init != NULL)
1462             opt->init(val);
1463         return 0;
1464     }
1465     default:
1466         abort();
1467     }
1468 }
1469
1470 /* Decode an ASN.1 sequence into a C object. */
1471 static asn1_error_code
1472 decode_sequence(const unsigned char *asn1, size_t len,
1473                 const struct seq_info *seq, void *val)
1474 {
1475     asn1_error_code ret;
1476     const unsigned char *contents;
1477     size_t i, j, clen;
1478     taginfo t;
1479
1480     assert(seq->n_fields > 0);
1481     for (i = 0; i < seq->n_fields; i++) {
1482         if (len == 0)
1483             break;
1484         ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len);
1485         if (ret)
1486             goto error;
1487         /*
1488          * Find the applicable sequence field.  This logic is a little
1489          * oversimplified; we could match an element to an optional extensible
1490          * choice or optional stored-DER type when we ought to match a
1491          * subsequent non-optional field.  But it's unwise and (hopefully) very
1492          * rare for ASN.1 modules to require such precision.
1493          */
1494         for (; i < seq->n_fields; i++) {
1495             if (check_atype_tag(seq->fields[i], &t))
1496                 break;
1497             ret = omit_atype(seq->fields[i], val);
1498             if (ret)
1499                 goto error;
1500         }
1501         /* We currently model all sequences as extensible.  We should consider
1502          * changing this before making the encoder visible to plugins. */
1503         if (i == seq->n_fields)
1504             break;
1505         ret = decode_atype(&t, contents, clen, seq->fields[i], val);
1506         if (ret)
1507             goto error;
1508     }
1509     /* Initialize any fields in the C object which were not accounted for in
1510      * the sequence.  Error out if any of them aren't optional. */
1511     for (; i < seq->n_fields; i++) {
1512         ret = omit_atype(seq->fields[i], val);
1513         if (ret)
1514             goto error;
1515     }
1516     return 0;
1517
1518 error:
1519     /* Free what we've decoded so far.  Free pointers in a second pass in
1520      * case multiple fields refer to the same pointer. */
1521     for (j = 0; j < i; j++)
1522         free_atype(seq->fields[j], val);
1523     for (j = 0; j < i; j++)
1524         free_atype_ptr(seq->fields[j], val);
1525     return ret;
1526 }
1527
1528 static asn1_error_code
1529 decode_sequence_of(const unsigned char *asn1, size_t len,
1530                    const struct atype_info *elemtype, void **seq_out,
1531                    size_t *count_out)
1532 {
1533     asn1_error_code ret;
1534     void *seq = NULL, *elem, *newseq;
1535     const unsigned char *contents;
1536     size_t clen, count = 0;
1537     taginfo t;
1538
1539     *seq_out = NULL;
1540     *count_out = 0;
1541     while (len > 0) {
1542         ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len);
1543         if (ret)
1544             goto error;
1545         if (!check_atype_tag(elemtype, &t)) {
1546             ret = ASN1_BAD_ID;
1547             goto error;
1548         }
1549         newseq = realloc(seq, (count + 1) * elemtype->size);
1550         if (newseq == NULL) {
1551             ret = ENOMEM;
1552             goto error;
1553         }
1554         seq = newseq;
1555         elem = (char *)seq + count * elemtype->size;
1556         memset(elem, 0, elemtype->size);
1557         ret = decode_atype(&t, contents, clen, elemtype, elem);
1558         if (ret)
1559             goto error;
1560         count++;
1561     }
1562     *seq_out = seq;
1563     *count_out = count;
1564     return 0;
1565
1566 error:
1567     free_sequence_of(elemtype, seq, count);
1568     free(seq);
1569     return ret;
1570 }
1571
1572 /* These three entry points are only needed for the kdc_req_body hack and may
1573  * go away at some point.  Define them here so we can use short names above. */
1574
1575 asn1_error_code
1576 k5_asn1_encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
1577                      taginfo *tag_out, size_t *len_out)
1578 {
1579     return encode_atype(buf, val, a, tag_out, len_out);
1580 }
1581
1582 asn1_error_code
1583 k5_asn1_decode_atype(const taginfo *t, const unsigned char *asn1,
1584                      size_t len, const struct atype_info *a, void *val)
1585 {
1586     return decode_atype(t, asn1, len, a, val);
1587 }
1588
1589 krb5_error_code
1590 k5_asn1_full_encode(const void *rep, const struct atype_info *a,
1591                     krb5_data **code_out)
1592 {
1593     size_t len;
1594     asn1_error_code ret;
1595     asn1buf *buf = NULL;
1596     krb5_data *d;
1597
1598     *code_out = NULL;
1599
1600     if (rep == NULL)
1601         return ASN1_MISSING_FIELD;
1602     ret = asn1buf_create(&buf);
1603     if (ret)
1604         return ret;
1605     ret = encode_atype_and_tag(buf, rep, a, &len);
1606     if (ret)
1607         goto cleanup;
1608     ret = asn12krb5_buf(buf, &d);
1609     if (ret)
1610         goto cleanup;
1611     *code_out = d;
1612 cleanup:
1613     asn1buf_destroy(&buf);
1614     return ret;
1615 }
1616
1617 asn1_error_code
1618 k5_asn1_full_decode(const krb5_data *code, const struct atype_info *a,
1619                     void **retrep)
1620 {
1621     asn1_error_code ret;
1622     const unsigned char *contents, *remainder;
1623     size_t clen, rlen;
1624     taginfo t;
1625
1626     *retrep = NULL;
1627     ret = get_tag((unsigned char *)code->data, code->length, &t, &contents,
1628                   &clen, &remainder, &rlen);
1629     if (ret)
1630         return ret;
1631     /* rlen should be 0, but we don't check it (and due to padding in
1632      * non-length-preserving enctypes, it will sometimes be nonzero). */
1633     if (!check_atype_tag(a, &t))
1634         return ASN1_BAD_ID;
1635     return decode_atype_to_ptr(&t, contents, clen, a, retrep);
1636 }