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