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