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
insert_byte(asn1buf * buf,uint8_t o)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
insert_bytes(asn1buf * buf,const void * bytes,size_t len)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
k5_asn1_encode_bool(asn1buf * buf,intmax_t val)60 k5_asn1_encode_bool(asn1buf *buf, intmax_t val)
61 {
62 insert_byte(buf, val ? 0xFF : 0x00);
63 }
64
65 void
k5_asn1_encode_int(asn1buf * buf,intmax_t val)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
k5_asn1_encode_uint(asn1buf * buf,uintmax_t val)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
k5_asn1_encode_bytestring(asn1buf * buf,uint8_t * const * val,size_t len)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
k5_asn1_encode_generaltime(asn1buf * buf,time_t val)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, >imebuf) != 0)
133 return ASN1_BAD_GMTIME;
134 #else
135 if (gmtime_r(&gmt_time, >imebuf) == 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(>imebuf, gtime, sizeof(gtimebuf));
143 #endif /* HAVE_GMTIME_R */
144 gtime = >imebuf;
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
k5_asn1_encode_bitstring(asn1buf * buf,uint8_t * const * val,size_t len)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
k5_asn1_decode_bool(const uint8_t * asn1,size_t len,intmax_t * val)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
k5_asn1_decode_int(const uint8_t * asn1,size_t len,intmax_t * val)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
k5_asn1_decode_uint(const uint8_t * asn1,size_t len,uintmax_t * val)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
k5_asn1_decode_bytestring(const uint8_t * asn1,size_t len,uint8_t ** str_out,size_t * len_out)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
k5_asn1_decode_generaltime(const uint8_t * asn1,size_t len,time_t * time_out)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
k5_asn1_decode_bitstring(const uint8_t * asn1,size_t len,uint8_t ** bits_out,size_t * len_out)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
make_tag(asn1buf * buf,const taginfo * t,size_t len)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
get_tag(const uint8_t * asn1,size_t len,taginfo * tag_out,const uint8_t ** contents_out,size_t * clen_out,const uint8_t ** remainder_out,size_t * rlen_out)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
get_nullterm_sequence_len(const void * valp,const struct atype_info * seq)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
encode_nullterm_sequence_of(asn1buf * buf,const void * val,const struct atype_info * type,int can_be_empty)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
load_int(const void * val,size_t size)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
load_uint(const void * val,size_t size)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
load_count(const void * val,const struct counted_info * counted,size_t * count_out)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
store_int(intmax_t intval,size_t size,void * val)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
store_uint(uintmax_t intval,size_t size,void * val)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
store_count(size_t count,const struct counted_info * counted,void * val)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
split_der(asn1buf * buf,uint8_t * const * der,size_t len,taginfo * tag_out)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
store_der(const taginfo * t,const uint8_t * asn1,size_t len,void * val,size_t * count_out)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
encode_atype(asn1buf * buf,const void * val,const struct atype_info * a,taginfo * tag_out)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
encode_atype_and_tag(asn1buf * buf,const void * val,const struct atype_info * a)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
encode_cntype(asn1buf * buf,const void * val,size_t count,const struct cntype_info * c,taginfo * tag_out)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
encode_sequence(asn1buf * buf,const void * val,const struct seq_info * seq)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
encode_sequence_of(asn1buf * buf,size_t seqlen,const void * val,const struct atype_info * eltinfo)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
free_atype(const struct atype_info * a,void * val)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
free_atype_ptr(const struct atype_info * a,void * val)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
free_cntype(const struct cntype_info * c,void * val,size_t count)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
free_sequence(const struct seq_info * seq,void * val)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
free_sequence_of(const struct atype_info * eltinfo,void * val,size_t count)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
check_atype_tag(const struct atype_info * a,const taginfo * t)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
decode_atype(const taginfo * t,const uint8_t * asn1,size_t len,const struct atype_info * a,void * val)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
decode_cntype(const taginfo * t,const uint8_t * asn1,size_t len,const struct cntype_info * c,void * val,size_t * count_out)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
null_terminate(const struct atype_info * eltinfo,void * ptr,size_t count,void ** ptr_out)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
decode_atype_to_ptr(const taginfo * t,const uint8_t * asn1,size_t len,const struct atype_info * a,void ** ptr_out)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
omit_atype(const struct atype_info * a,void * val)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
decode_sequence(const uint8_t * asn1,size_t len,const struct seq_info * seq,void * val)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
decode_sequence_of(const uint8_t * asn1,size_t len,const struct atype_info * elemtype,void ** seq_out,size_t * count_out)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
k5_asn1_encode_atype(asn1buf * buf,const void * val,const struct atype_info * a,taginfo * tag_out)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
k5_asn1_decode_atype(const taginfo * t,const uint8_t * asn1,size_t len,const struct atype_info * a,void * val)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
k5_asn1_full_encode(const void * rep,const struct atype_info * a,krb5_data ** code_out)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
k5_asn1_full_decode(const krb5_data * code,const struct atype_info * a,void ** retrep)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 }
1586