1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/asn.1/asn1_encode.c */
4 * Copyright 1994, 2008 by the Massachusetts Institute of Technology.
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.
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.
27 #include "asn1_encode.h"
29 /**** Functions for encoding primitive types ****/
32 k5_asn1_encode_bool(asn1buf *buf, intmax_t val, size_t *len_out)
34 asn1_octet bval = val ? 0xFF : 0x00;
37 return asn1buf_insert_octet(buf, bval);
41 k5_asn1_encode_int(asn1buf *buf, intmax_t val, size_t *len_out)
50 digit = valcopy & 0xFF;
51 ret = asn1buf_insert_octet(buf, digit);
55 valcopy = valcopy >> 8;
56 } while (valcopy != 0 && valcopy != ~0);
58 if (val > 0 && (digit & 0x80) == 0x80) { /* make sure the high bit is */
59 ret = asn1buf_insert_octet(buf, 0); /* of the proper signed-ness */
63 } else if (val < 0 && (digit & 0x80) != 0x80) {
64 ret = asn1buf_insert_octet(buf, 0xFF);
76 k5_asn1_encode_uint(asn1buf *buf, uintmax_t val, size_t *len_out)
85 digit = valcopy & 0xFF;
86 ret = asn1buf_insert_octet(buf, digit);
90 valcopy = valcopy >> 8;
91 } while (valcopy != 0);
93 if (digit & 0x80) { /* make sure the high bit is */
94 ret = asn1buf_insert_octet(buf, 0); /* of the proper signed-ness */
105 k5_asn1_encode_bytestring(asn1buf *buf, unsigned char *const *val, size_t len,
108 if (len > 0 && val == NULL)
109 return ASN1_MISSING_FIELD;
111 return asn1buf_insert_octetstring(buf, len, *val);
115 k5_asn1_encode_generaltime(asn1buf *buf, time_t val, size_t *len_out)
117 struct tm *gtime, gtimebuf;
120 time_t gmt_time = val;
124 * Time encoding: YYYYMMDDhhmmssZ
127 sp = (unsigned char *)"19700101000000Z";
130 * Sanity check this just to be paranoid, as gmtime can return NULL,
131 * and some bogus implementations might overrun on the sprintf.
134 #ifdef GMTIME_R_RETURNS_INT
135 if (gmtime_r(&gmt_time, >imebuf) != 0)
136 return ASN1_BAD_GMTIME;
138 if (gmtime_r(&gmt_time, >imebuf) == NULL)
139 return ASN1_BAD_GMTIME;
141 #else /* HAVE_GMTIME_R */
142 gtime = gmtime(&gmt_time);
144 return ASN1_BAD_GMTIME;
145 memcpy(>imebuf, gtime, sizeof(gtimebuf));
146 #endif /* HAVE_GMTIME_R */
149 if (gtime->tm_year > 8099 || gtime->tm_mon > 11 ||
150 gtime->tm_mday > 31 || gtime->tm_hour > 23 ||
151 gtime->tm_min > 59 || gtime->tm_sec > 59)
152 return ASN1_BAD_GMTIME;
153 len = snprintf(s, sizeof(s), "%04d%02d%02d%02d%02d%02dZ",
154 1900 + gtime->tm_year, gtime->tm_mon + 1,
155 gtime->tm_mday, gtime->tm_hour,
156 gtime->tm_min, gtime->tm_sec);
157 if (SNPRINTF_OVERFLOW(len, sizeof(s)))
158 /* Shouldn't be possible given above tests. */
159 return ASN1_BAD_GMTIME;
160 sp = (unsigned char *)s;
163 return k5_asn1_encode_bytestring(buf, &sp, 15, len_out);
167 k5_asn1_encode_bitstring(asn1buf *buf, unsigned char *const *val, size_t len,
172 ret = asn1buf_insert_octetstring(buf, len, *val);
176 return asn1buf_insert_octet(buf, '\0');
179 /**** Functions for decoding primitive types ****/
182 k5_asn1_decode_bool(const unsigned char *asn1, size_t len, intmax_t *val)
185 return ASN1_BAD_LENGTH;
190 /* Decode asn1/len as the contents of a DER integer, placing the signed result
193 k5_asn1_decode_int(const unsigned char *asn1, size_t len, intmax_t *val)
199 return ASN1_BAD_LENGTH;
200 n = (asn1[0] & 0x80) ? -1 : 0;
201 /* Check length; allow extra octet if first octet is 0. */
202 if (len > sizeof(intmax_t) + (asn1[0] == 0))
203 return ASN1_OVERFLOW;
204 for (i = 0; i < len; i++)
205 n = (n << 8) | asn1[i];
210 /* Decode asn1/len as the contents of a DER integer, placing the unsigned
213 k5_asn1_decode_uint(const unsigned char *asn1, size_t len, uintmax_t *val)
219 return ASN1_BAD_LENGTH;
220 /* Check for negative values and check length. */
221 if ((asn1[0] & 0x80) || len > sizeof(uintmax_t) + (asn1[0] == 0))
222 return ASN1_OVERFLOW;
223 for (i = 0, n = 0; i < len; i++)
224 n = (n << 8) | asn1[i];
230 k5_asn1_decode_bytestring(const unsigned char *asn1, size_t len,
231 unsigned char **str_out, size_t *len_out)
242 memcpy(str, asn1, len);
249 k5_asn1_decode_generaltime(const unsigned char *asn1, size_t len,
252 const char *s = (char *)asn1;
258 return ASN1_BAD_LENGTH;
259 /* Time encoding: YYYYMMDDhhmmssZ */
261 return ASN1_BAD_FORMAT;
262 if (memcmp(s, "19700101000000Z", 15) == 0) {
266 #define c2i(c) ((c) - '0')
267 ts.tm_year = 1000 * c2i(s[0]) + 100 * c2i(s[1]) + 10 * c2i(s[2]) +
269 ts.tm_mon = 10 * c2i(s[4]) + c2i(s[5]) - 1;
270 ts.tm_mday = 10 * c2i(s[6]) + c2i(s[7]);
271 ts.tm_hour = 10 * c2i(s[8]) + c2i(s[9]);
272 ts.tm_min = 10 * c2i(s[10]) + c2i(s[11]);
273 ts.tm_sec = 10 * c2i(s[12]) + c2i(s[13]);
275 t = krb5int_gmt_mktime(&ts);
277 return ASN1_BAD_TIMEFORMAT;
283 * Note: we return the number of bytes, not bits, in the bit string. If the
284 * number of bits is not a multiple of 8 we effectively round up to the next
288 k5_asn1_decode_bitstring(const unsigned char *asn1, size_t len,
289 unsigned char **bits_out, size_t *len_out)
291 unsigned char unused, *bits;
296 return ASN1_BAD_LENGTH;
300 return ASN1_BAD_FORMAT;
305 memcpy(bits, asn1, len);
307 bits[len - 1] &= (0xff << unused);
314 /**** Functions for encoding and decoding tags ****/
316 /* Encode a DER tag into buf with the tag parameters in t and the content
317 * length len. Place the length of the encoded tag in *retlen. */
318 static asn1_error_code
319 make_tag(asn1buf *buf, const taginfo *t, size_t len, size_t *retlen)
322 asn1_tagnum tag_copy;
323 size_t sum = 0, length, len_copy;
325 if (t->tagnum > ASN1_TAGNUM_MAX)
326 return ASN1_OVERFLOW;
328 /* Encode the length of the content within the tag. */
330 ret = asn1buf_insert_octet(buf, len & 0x7F);
336 for (len_copy = len; len_copy != 0; len_copy >>= 8) {
337 ret = asn1buf_insert_octet(buf, len_copy & 0xFF);
342 ret = asn1buf_insert_octet(buf, 0x80 | (length & 0x7F));
349 /* Encode the tag and construction bit. */
350 if (t->tagnum < 31) {
351 ret = asn1buf_insert_octet(buf,
352 t->asn1class | t->construction | t->tagnum);
357 tag_copy = t->tagnum;
359 ret = asn1buf_insert_octet(buf, tag_copy & 0x7F);
365 for (; tag_copy != 0; tag_copy >>= 7) {
366 ret = asn1buf_insert_octet(buf, 0x80 | (tag_copy & 0x7F));
372 ret = asn1buf_insert_octet(buf, t->asn1class | t->construction | 0x1F);
384 * Read a BER tag and length from asn1/len. Place the tag parameters in
385 * tag_out. Set contents_out/clen_out to the octet range of the tag's
386 * contents, and remainder_out/rlen_out to the octet range after the end of the
389 * (krb5 ASN.1 encodings should be in DER, but for compatibility with some
390 * really ancient implementations we handle the indefinite length form in tags.
391 * However, we still insist on the primitive form of string types.)
393 static asn1_error_code
394 get_tag(const unsigned char *asn1, size_t len, taginfo *tag_out,
395 const unsigned char **contents_out, size_t *clen_out,
396 const unsigned char **remainder_out, size_t *rlen_out)
400 const unsigned char *c, *p, *tag_start = asn1;
401 size_t clen, llen, i;
404 *contents_out = *remainder_out = NULL;
405 *clen_out = *rlen_out = 0;
410 tag_out->asn1class = o & 0xC0;
411 tag_out->construction = o & 0x20;
412 if ((o & 0x1F) != 0x1F) {
413 tag_out->tagnum = o & 0x1F;
421 tag_out->tagnum = (tag_out->tagnum << 7) | (o & 0x7F);
431 /* Indefinite form (should not be present in DER, but we accept it). */
432 if (tag_out->construction != CONSTRUCTED)
433 return ASN1_MISMATCH_INDEF;
435 while (!(len >= 2 && p[0] == 0 && p[1] == 0)) {
436 ret = get_tag(p, len, &t, &c, &clen, &p, &len);
440 tag_out->tag_end_len = 2;
441 *contents_out = asn1;
442 *clen_out = p - asn1;
443 *remainder_out = p + 2;
445 } else if ((o & 0x80) == 0) {
446 /* Short form (first octet gives content length). */
449 tag_out->tag_end_len = 0;
450 *contents_out = asn1;
452 *remainder_out = asn1 + *clen_out;
453 *rlen_out = len - (*remainder_out - asn1);
455 /* Long form (first octet gives number of base-256 length octets). */
459 if (llen > sizeof(*clen_out))
460 return ASN1_OVERFLOW;
461 for (i = 0, clen = 0; i < llen; i++)
462 clen = (clen << 8) | asn1[i];
463 if (clen > len - llen)
465 tag_out->tag_end_len = 0;
466 *contents_out = asn1 + llen;
468 *remainder_out = *contents_out + clen;
469 *rlen_out = len - (*remainder_out - asn1);
471 tag_out->tag_len = *contents_out - tag_start;
475 #ifdef POINTERS_ARE_ALL_THE_SAME
476 #define LOADPTR(PTR, TYPE) (*(const void *const *)(PTR))
477 #define STOREPTR(PTR, TYPE, VAL) (*(void **)(VAL) = (PTR))
479 #define LOADPTR(PTR, PTRINFO) \
480 (assert((PTRINFO)->loadptr != NULL), (PTRINFO)->loadptr(PTR))
481 #define STOREPTR(PTR, PTRINFO, VAL) \
482 (assert((PTRINFO)->storeptr != NULL), (PTRINFO)->storeptr(PTR, VAL))
486 get_nullterm_sequence_len(const void *valp, const struct atype_info *seq)
489 const struct atype_info *a;
490 const struct ptr_info *ptr;
491 const void *elt, *eltptr;
495 assert(a->type == atype_ptr);
496 assert(seq->size != 0);
500 eltptr = (const char *)valp + i * seq->size;
501 elt = LOADPTR(eltptr, ptr);
508 static asn1_error_code
509 encode_sequence_of(asn1buf *buf, size_t seqlen, const void *val,
510 const struct atype_info *eltinfo, size_t *len_out);
512 static asn1_error_code
513 encode_nullterm_sequence_of(asn1buf *buf, const void *val,
514 const struct atype_info *type,
515 int can_be_empty, size_t *len_out)
517 size_t len = get_nullterm_sequence_len(val, type);
519 if (!can_be_empty && len == 0)
520 return ASN1_MISSING_FIELD;
521 return encode_sequence_of(buf, len, val, type, len_out);
525 load_int(const void *val, size_t size)
528 case 1: return *(signed char *)val;
529 case 2: return *(krb5_int16 *)val;
530 case 4: return *(krb5_int32 *)val;
531 case 8: return *(int64_t *)val;
537 load_uint(const void *val, size_t size)
540 case 1: return *(unsigned char *)val;
541 case 2: return *(krb5_ui_2 *)val;
542 case 4: return *(krb5_ui_4 *)val;
543 case 8: return *(uint64_t *)val;
548 static asn1_error_code
549 load_count(const void *val, const struct counted_info *counted,
552 const void *countptr = (const char *)val + counted->lenoff;
554 assert(sizeof(size_t) <= sizeof(uintmax_t));
555 if (counted->lensigned) {
556 intmax_t xlen = load_int(countptr, counted->lensize);
557 if (xlen < 0 || (uintmax_t)xlen > SIZE_MAX)
561 uintmax_t xlen = load_uint(countptr, counted->lensize);
562 if ((size_t)xlen != xlen || xlen > SIZE_MAX)
569 static asn1_error_code
570 store_int(intmax_t intval, size_t size, void *val)
574 if ((signed char)intval != intval)
575 return ASN1_OVERFLOW;
576 *(signed char *)val = intval;
579 if ((krb5_int16)intval != intval)
580 return ASN1_OVERFLOW;
581 *(krb5_int16 *)val = intval;
584 if ((krb5_int32)intval != intval)
585 return ASN1_OVERFLOW;
586 *(krb5_int32 *)val = intval;
589 if ((int64_t)intval != intval)
590 return ASN1_OVERFLOW;
591 *(int64_t *)val = intval;
598 static asn1_error_code
599 store_uint(uintmax_t intval, size_t size, void *val)
603 if ((unsigned char)intval != intval)
604 return ASN1_OVERFLOW;
605 *(unsigned char *)val = intval;
608 if ((krb5_ui_2)intval != intval)
609 return ASN1_OVERFLOW;
610 *(krb5_ui_2 *)val = intval;
613 if ((krb5_ui_4)intval != intval)
614 return ASN1_OVERFLOW;
615 *(krb5_ui_4 *)val = intval;
618 if ((uint64_t)intval != intval)
619 return ASN1_OVERFLOW;
620 *(uint64_t *)val = intval;
627 /* Store a count value in an integer field of a structure. If count is
628 * SIZE_MAX and the target is a signed field, store -1. */
629 static asn1_error_code
630 store_count(size_t count, const struct counted_info *counted, void *val)
632 void *countptr = (char *)val + counted->lenoff;
634 if (counted->lensigned) {
635 if (count == SIZE_MAX)
636 return store_int(-1, counted->lensize, countptr);
637 else if ((intmax_t)count < 0)
638 return ASN1_OVERFLOW;
640 return store_int(count, counted->lensize, countptr);
642 return store_uint(count, counted->lensize, countptr);
645 /* Split a DER encoding into tag and contents. Insert the contents into buf,
646 * then return the length of the contents and the tag. */
647 static asn1_error_code
648 split_der(asn1buf *buf, unsigned char *const *der, size_t len,
649 taginfo *tag_out, size_t *len_out)
652 const unsigned char *contents, *remainder;
655 ret = get_tag(*der, len, tag_out, &contents, &clen, &remainder, &rlen);
659 return ASN1_BAD_LENGTH;
661 return asn1buf_insert_bytestring(buf, clen, contents);
665 * Store the DER encoding given by t and asn1/len into the char * or
666 * unsigned char * pointed to by val. Set *count_out to the length of the
669 static asn1_error_code
670 store_der(const taginfo *t, const unsigned char *asn1, size_t len, void *val,
677 der_len = t->tag_len + len + t->tag_end_len;
678 der = malloc(der_len);
681 memcpy(der, asn1 - t->tag_len, der_len);
682 *(unsigned char **)val = der;
683 *count_out = der_len;
687 static asn1_error_code
688 encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq,
690 static asn1_error_code
691 encode_cntype(asn1buf *buf, const void *val, size_t len,
692 const struct cntype_info *c, taginfo *tag_out, size_t *len_out);
694 /* Encode a value (contents only, no outer tag) according to a type, and return
695 * its encoded tag information. */
696 static asn1_error_code
697 encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
698 taginfo *tag_out, size_t *len_out)
703 return ASN1_MISSING_FIELD;
707 const struct fn_info *fn = a->tinfo;
708 assert(fn->enc != NULL);
709 return fn->enc(buf, val, tag_out, len_out);
712 assert(a->tinfo != NULL);
713 ret = encode_sequence(buf, val, a->tinfo, len_out);
716 tag_out->asn1class = UNIVERSAL;
717 tag_out->construction = CONSTRUCTED;
718 tag_out->tagnum = ASN1_SEQUENCE;
721 const struct ptr_info *ptr = a->tinfo;
722 assert(ptr->basetype != NULL);
723 return encode_atype(buf, LOADPTR(val, ptr), ptr->basetype, tag_out,
727 const struct offset_info *off = a->tinfo;
728 assert(off->basetype != NULL);
729 return encode_atype(buf, (const char *)val + off->dataoff,
730 off->basetype, tag_out, len_out);
732 case atype_optional: {
733 const struct optional_info *opt = a->tinfo;
734 assert(opt->is_present != NULL);
735 if (opt->is_present(val))
736 return encode_atype(buf, val, opt->basetype, tag_out, len_out);
740 case atype_counted: {
741 const struct counted_info *counted = a->tinfo;
742 const void *dataptr = (const char *)val + counted->dataoff;
744 assert(counted->basetype != NULL);
745 ret = load_count(val, counted, &count);
748 return encode_cntype(buf, dataptr, count, counted->basetype, tag_out,
751 case atype_nullterm_sequence_of:
752 case atype_nonempty_nullterm_sequence_of:
753 assert(a->tinfo != NULL);
754 ret = encode_nullterm_sequence_of(buf, val, a->tinfo,
756 atype_nullterm_sequence_of,
760 tag_out->asn1class = UNIVERSAL;
761 tag_out->construction = CONSTRUCTED;
762 tag_out->tagnum = ASN1_SEQUENCE;
764 case atype_tagged_thing: {
765 const struct tagged_info *tag = a->tinfo;
766 ret = encode_atype(buf, val, tag->basetype, tag_out, len_out);
769 if (!tag->implicit) {
771 ret = make_tag(buf, tag_out, *len_out, &tlen);
775 tag_out->construction = tag->construction;
777 tag_out->asn1class = tag->tagtype;
778 tag_out->tagnum = tag->tagval;
782 ret = k5_asn1_encode_bool(buf, load_int(val, a->size), len_out);
785 tag_out->asn1class = UNIVERSAL;
786 tag_out->construction = PRIMITIVE;
787 tag_out->tagnum = ASN1_BOOLEAN;
790 ret = k5_asn1_encode_int(buf, load_int(val, a->size), len_out);
793 tag_out->asn1class = UNIVERSAL;
794 tag_out->construction = PRIMITIVE;
795 tag_out->tagnum = ASN1_INTEGER;
798 ret = k5_asn1_encode_uint(buf, load_uint(val, a->size), len_out);
801 tag_out->asn1class = UNIVERSAL;
802 tag_out->construction = PRIMITIVE;
803 tag_out->tagnum = ASN1_INTEGER;
805 case atype_int_immediate: {
806 const struct immediate_info *imm = a->tinfo;
807 ret = k5_asn1_encode_int(buf, imm->val, len_out);
810 tag_out->asn1class = UNIVERSAL;
811 tag_out->construction = PRIMITIVE;
812 tag_out->tagnum = ASN1_INTEGER;
816 assert(a->type > atype_min);
817 assert(a->type < atype_max);
824 static asn1_error_code
825 encode_atype_and_tag(asn1buf *buf, const void *val, const struct atype_info *a,
832 ret = encode_atype(buf, val, a, &t, &clen);
835 ret = make_tag(buf, &t, clen, &tlen);
838 *len_out = clen + tlen;
843 * Encode an object and count according to a cntype_info structure. val is a
844 * pointer to the object being encoded, which in most cases is itself a
845 * pointer (but is a union in the cntype_choice case).
847 static asn1_error_code
848 encode_cntype(asn1buf *buf, const void *val, size_t count,
849 const struct cntype_info *c, taginfo *tag_out, size_t *len_out)
854 case cntype_string: {
855 const struct string_info *string = c->tinfo;
856 assert(string->enc != NULL);
857 ret = string->enc(buf, val, count, len_out);
860 tag_out->asn1class = UNIVERSAL;
861 tag_out->construction = PRIMITIVE;
862 tag_out->tagnum = string->tagval;
866 return split_der(buf, val, count, tag_out, len_out);
868 const struct atype_info *a = c->tinfo;
869 const struct ptr_info *ptr = a->tinfo;
870 assert(a->type == atype_ptr);
871 val = LOADPTR(val, ptr);
872 ret = encode_sequence_of(buf, count, val, ptr->basetype, len_out);
875 tag_out->asn1class = UNIVERSAL;
876 tag_out->construction = CONSTRUCTED;
877 tag_out->tagnum = ASN1_SEQUENCE;
880 case cntype_choice: {
881 const struct choice_info *choice = c->tinfo;
882 if (count >= choice->n_options)
883 return ASN1_MISSING_FIELD;
884 return encode_atype(buf, val, choice->options[count], tag_out,
889 assert(c->type > cntype_min);
890 assert(c->type < cntype_max);
897 static asn1_error_code
898 encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq,
902 size_t i, len, sum = 0;
904 for (i = seq->n_fields; i > 0; i--) {
905 ret = encode_atype_and_tag(buf, val, seq->fields[i - 1], &len);
906 if (ret == ASN1_OMITTED)
916 static asn1_error_code
917 encode_sequence_of(asn1buf *buf, size_t seqlen, const void *val,
918 const struct atype_info *eltinfo, size_t *len_out)
921 size_t sum = 0, i, len;
924 assert(eltinfo->size != 0);
925 for (i = seqlen; i > 0; i--) {
926 eltptr = (const char *)val + (i - 1) * eltinfo->size;
927 ret = encode_atype_and_tag(buf, eltptr, eltinfo, &len);
936 /**** Functions for freeing C objects based on type info ****/
938 static void free_atype_ptr(const struct atype_info *a, void *val);
939 static void free_sequence(const struct seq_info *seq, void *val);
940 static void free_sequence_of(const struct atype_info *eltinfo, void *val,
942 static void free_cntype(const struct cntype_info *a, void *val, size_t count);
945 * Free a C object according to a type description. Do not free pointers at
946 * the first level; they may be referenced by other fields of a sequence, and
947 * will be freed by free_atype_ptr in a second pass.
950 free_atype(const struct atype_info *a, void *val)
954 const struct fn_info *fn = a->tinfo;
955 if (fn->free_func != NULL)
960 free_sequence(a->tinfo, val);
963 const struct ptr_info *ptrinfo = a->tinfo;
964 void *ptr = LOADPTR(val, ptrinfo);
966 free_atype(ptrinfo->basetype, ptr);
967 free_atype_ptr(ptrinfo->basetype, ptr);
972 const struct offset_info *off = a->tinfo;
973 assert(off->basetype != NULL);
974 free_atype(off->basetype, (char *)val + off->dataoff);
977 case atype_optional: {
978 const struct optional_info *opt = a->tinfo;
979 free_atype(opt->basetype, val);
982 case atype_counted: {
983 const struct counted_info *counted = a->tinfo;
984 void *dataptr = (char *)val + counted->dataoff;
986 if (load_count(val, counted, &count) == 0)
987 free_cntype(counted->basetype, dataptr, count);
990 case atype_nullterm_sequence_of:
991 case atype_nonempty_nullterm_sequence_of: {
992 size_t count = get_nullterm_sequence_len(val, a->tinfo);
993 free_sequence_of(a->tinfo, val, count);
996 case atype_tagged_thing: {
997 const struct tagged_info *tag = a->tinfo;
998 free_atype(tag->basetype, val);
1004 case atype_int_immediate:
1012 free_atype_ptr(const struct atype_info *a, void *val)
1016 case atype_sequence:
1018 case atype_nullterm_sequence_of:
1019 case atype_nonempty_nullterm_sequence_of:
1023 case atype_int_immediate:
1026 const struct ptr_info *ptrinfo = a->tinfo;
1027 void *ptr = LOADPTR(val, ptrinfo);
1029 STOREPTR(NULL, ptrinfo, val);
1032 case atype_offset: {
1033 const struct offset_info *off = a->tinfo;
1034 assert(off->basetype != NULL);
1035 free_atype_ptr(off->basetype, (char *)val + off->dataoff);
1038 case atype_optional: {
1039 const struct optional_info *opt = a->tinfo;
1040 free_atype_ptr(opt->basetype, val);
1043 case atype_tagged_thing: {
1044 const struct tagged_info *tag = a->tinfo;
1045 free_atype_ptr(tag->basetype, val);
1054 free_cntype(const struct cntype_info *c, void *val, size_t count)
1059 free(*(char **)val);
1060 *(char **)val = NULL;
1062 case cntype_seqof: {
1063 const struct atype_info *a = c->tinfo;
1064 const struct ptr_info *ptrinfo = a->tinfo;
1065 void *seqptr = LOADPTR(val, ptrinfo);
1066 free_sequence_of(ptrinfo->basetype, seqptr, count);
1068 STOREPTR(NULL, ptrinfo, val);
1071 case cntype_choice: {
1072 const struct choice_info *choice = c->tinfo;
1073 if (count < choice->n_options) {
1074 free_atype(choice->options[count], val);
1075 free_atype_ptr(choice->options[count], val);
1085 free_sequence(const struct seq_info *seq, void *val)
1089 for (i = 0; i < seq->n_fields; i++)
1090 free_atype(seq->fields[i], val);
1091 for (i = 0; i < seq->n_fields; i++)
1092 free_atype_ptr(seq->fields[i], val);
1096 free_sequence_of(const struct atype_info *eltinfo, void *val, size_t count)
1100 assert(eltinfo->size != 0);
1101 while (count-- > 0) {
1102 eltptr = (char *)val + count * eltinfo->size;
1103 free_atype(eltinfo, eltptr);
1104 free_atype_ptr(eltinfo, eltptr);
1108 /**** Functions for decoding objects based on type info ****/
1110 /* Return nonzero if t is an expected tag for an ASN.1 object of type a. */
1112 check_atype_tag(const struct atype_info *a, const taginfo *t)
1116 const struct fn_info *fn = a->tinfo;
1117 assert(fn->check_tag != NULL);
1118 return fn->check_tag(t);
1120 case atype_sequence:
1121 case atype_nullterm_sequence_of:
1122 case atype_nonempty_nullterm_sequence_of:
1123 return (t->asn1class == UNIVERSAL && t->construction == CONSTRUCTED &&
1124 t->tagnum == ASN1_SEQUENCE);
1126 const struct ptr_info *ptrinfo = a->tinfo;
1127 return check_atype_tag(ptrinfo->basetype, t);
1129 case atype_offset: {
1130 const struct offset_info *off = a->tinfo;
1131 return check_atype_tag(off->basetype, t);
1133 case atype_optional: {
1134 const struct optional_info *opt = a->tinfo;
1135 return check_atype_tag(opt->basetype, t);
1137 case atype_counted: {
1138 const struct counted_info *counted = a->tinfo;
1139 switch (counted->basetype->type) {
1140 case cntype_string: {
1141 const struct string_info *string = counted->basetype->tinfo;
1142 return (t->asn1class == UNIVERSAL &&
1143 t->construction == PRIMITIVE &&
1144 t->tagnum == string->tagval);
1147 return (t->asn1class == UNIVERSAL &&
1148 t->construction == CONSTRUCTED &&
1149 t->tagnum == ASN1_SEQUENCE);
1152 * We treat any tag as matching a stored DER encoding. In some
1153 * cases we know what the tag should be; in others, we truly want
1154 * to accept any tag. If it ever becomes an issue, we could add
1155 * optional tag info to the type and check it here.
1160 * ASN.1 choices may or may not be extensible. For now, we treat
1161 * all choices as extensible and match any tag. We should consider
1162 * modeling whether choices are extensible before making the
1163 * encoder visible to plugins.
1170 case atype_tagged_thing: {
1171 const struct tagged_info *tag = a->tinfo;
1172 /* NOTE: Doesn't check construction bit for implicit tags. */
1173 if (!tag->implicit && t->construction != tag->construction)
1175 return (t->asn1class == tag->tagtype && t->tagnum == tag->tagval);
1178 return (t->asn1class == UNIVERSAL && t->construction == PRIMITIVE &&
1179 t->tagnum == ASN1_BOOLEAN);
1182 case atype_int_immediate:
1183 return (t->asn1class == UNIVERSAL && t->construction == PRIMITIVE &&
1184 t->tagnum == ASN1_INTEGER);
1190 static asn1_error_code
1191 decode_cntype(const taginfo *t, const unsigned char *asn1, size_t len,
1192 const struct cntype_info *c, void *val, size_t *count_out);
1193 static asn1_error_code
1194 decode_atype_to_ptr(const taginfo *t, const unsigned char *asn1, size_t len,
1195 const struct atype_info *basetype, void **ptr_out);
1196 static asn1_error_code
1197 decode_sequence(const unsigned char *asn1, size_t len,
1198 const struct seq_info *seq, void *val);
1199 static asn1_error_code
1200 decode_sequence_of(const unsigned char *asn1, size_t len,
1201 const struct atype_info *elemtype, void **seq_out,
1204 /* Given the enclosing tag t, decode from asn1/len the contents of the ASN.1
1205 * type specified by a, placing the result into val (caller-allocated). */
1206 static asn1_error_code
1207 decode_atype(const taginfo *t, const unsigned char *asn1,
1208 size_t len, const struct atype_info *a, void *val)
1210 asn1_error_code ret;
1214 const struct fn_info *fn = a->tinfo;
1215 assert(fn->dec != NULL);
1216 return fn->dec(t, asn1, len, val);
1218 case atype_sequence:
1219 return decode_sequence(asn1, len, a->tinfo, val);
1221 const struct ptr_info *ptrinfo = a->tinfo;
1222 void *ptr = LOADPTR(val, ptrinfo);
1223 assert(ptrinfo->basetype != NULL);
1225 /* Container was already allocated by a previous sequence field. */
1226 return decode_atype(t, asn1, len, ptrinfo->basetype, ptr);
1228 ret = decode_atype_to_ptr(t, asn1, len, ptrinfo->basetype, &ptr);
1231 STOREPTR(ptr, ptrinfo, val);
1235 case atype_offset: {
1236 const struct offset_info *off = a->tinfo;
1237 assert(off->basetype != NULL);
1238 return decode_atype(t, asn1, len, off->basetype,
1239 (char *)val + off->dataoff);
1241 case atype_optional: {
1242 const struct optional_info *opt = a->tinfo;
1243 return decode_atype(t, asn1, len, opt->basetype, val);
1245 case atype_counted: {
1246 const struct counted_info *counted = a->tinfo;
1247 void *dataptr = (char *)val + counted->dataoff;
1249 assert(counted->basetype != NULL);
1250 ret = decode_cntype(t, asn1, len, counted->basetype, dataptr, &count);
1253 return store_count(count, counted, val);
1255 case atype_tagged_thing: {
1256 const struct tagged_info *tag = a->tinfo;
1258 const taginfo *tp = t;
1259 const unsigned char *rem;
1261 if (!tag->implicit) {
1262 ret = get_tag(asn1, len, &inner_tag, &asn1, &len, &rem, &rlen);
1265 /* Note: we don't check rlen (it should be 0). */
1267 if (!check_atype_tag(tag->basetype, tp))
1270 return decode_atype(tp, asn1, len, tag->basetype, val);
1274 ret = k5_asn1_decode_bool(asn1, len, &intval);
1277 return store_int(intval, a->size, val);
1281 ret = k5_asn1_decode_int(asn1, len, &intval);
1284 return store_int(intval, a->size, val);
1288 ret = k5_asn1_decode_uint(asn1, len, &intval);
1291 return store_uint(intval, a->size, val);
1293 case atype_int_immediate: {
1294 const struct immediate_info *imm = a->tinfo;
1296 ret = k5_asn1_decode_int(asn1, len, &intval);
1299 if (intval != imm->val && imm->err != 0)
1304 /* Null-terminated sequence types are handled in decode_atype_to_ptr,
1305 * since they create variable-sized objects. */
1306 assert(a->type != atype_nullterm_sequence_of);
1307 assert(a->type != atype_nonempty_nullterm_sequence_of);
1308 assert(a->type > atype_min);
1309 assert(a->type < atype_max);
1316 * Given the enclosing tag t, decode from asn1/len the contents of the
1317 * ASN.1 type described by c, placing the counted result into val/count_out.
1318 * If the resulting count should be -1 (for an unknown union distinguisher),
1319 * set *count_out to SIZE_MAX.
1321 static asn1_error_code
1322 decode_cntype(const taginfo *t, const unsigned char *asn1, size_t len,
1323 const struct cntype_info *c, void *val, size_t *count_out)
1325 asn1_error_code ret;
1328 case cntype_string: {
1329 const struct string_info *string = c->tinfo;
1330 assert(string->dec != NULL);
1331 return string->dec(asn1, len, val, count_out);
1334 return store_der(t, asn1, len, val, count_out);
1335 case cntype_seqof: {
1336 const struct atype_info *a = c->tinfo;
1337 const struct ptr_info *ptrinfo = a->tinfo;
1339 assert(a->type == atype_ptr);
1340 ret = decode_sequence_of(asn1, len, ptrinfo->basetype, &seq,
1344 STOREPTR(seq, ptrinfo, val);
1347 case cntype_choice: {
1348 const struct choice_info *choice = c->tinfo;
1350 for (i = 0; i < choice->n_options; i++) {
1351 if (check_atype_tag(choice->options[i], t)) {
1352 ret = decode_atype(t, asn1, len, choice->options[i], val);
1359 /* SIZE_MAX will be stored as -1 in the distinguisher. If we start
1360 * modeling non-extensible choices we should check that here. */
1361 *count_out = SIZE_MAX;
1365 assert(c->type > cntype_min);
1366 assert(c->type < cntype_max);
1372 /* Add a null pointer to the end of a sequence. ptr is consumed on success
1373 * (to be replaced by *ptr_out), left alone on failure. */
1374 static asn1_error_code
1375 null_terminate(const struct atype_info *eltinfo, void *ptr, size_t count,
1378 const struct ptr_info *ptrinfo = eltinfo->tinfo;
1381 assert(eltinfo->type == atype_ptr);
1382 ptr = realloc(ptr, (count + 1) * eltinfo->size);
1385 endptr = (char *)ptr + count * eltinfo->size;
1386 STOREPTR(NULL, ptrinfo, endptr);
1391 static asn1_error_code
1392 decode_atype_to_ptr(const taginfo *t, const unsigned char *asn1,
1393 size_t len, const struct atype_info *a,
1396 asn1_error_code ret;
1402 case atype_nullterm_sequence_of:
1403 case atype_nonempty_nullterm_sequence_of:
1404 ret = decode_sequence_of(asn1, len, a->tinfo, &ptr, &count);
1407 ret = null_terminate(a->tinfo, ptr, count, &ptr);
1409 free_sequence_of(a->tinfo, ptr, count);
1412 /* Historically we do not enforce non-emptiness of sequences when
1413 * decoding, even when it is required by the ASN.1 type. */
1416 ptr = calloc(a->size, 1);
1419 ret = decode_atype(t, asn1, len, a, ptr);
1430 /* Initialize a C object when the corresponding ASN.1 type was omitted within a
1431 * sequence. If the ASN.1 type is not optional, return ASN1_MISSING_FIELD. */
1432 static asn1_error_code
1433 omit_atype(const struct atype_info *a, void *val)
1438 case atype_sequence:
1439 case atype_nullterm_sequence_of:
1440 case atype_nonempty_nullterm_sequence_of:
1445 case atype_int_immediate:
1446 return ASN1_MISSING_FIELD;
1448 const struct ptr_info *ptrinfo = a->tinfo;
1449 return omit_atype(ptrinfo->basetype, val);
1451 case atype_offset: {
1452 const struct offset_info *off = a->tinfo;
1453 return omit_atype(off->basetype, (char *)val + off->dataoff);
1455 case atype_tagged_thing: {
1456 const struct tagged_info *tag = a->tinfo;
1457 return omit_atype(tag->basetype, val);
1459 case atype_optional: {
1460 const struct optional_info *opt = a->tinfo;
1461 if (opt->init != NULL)
1470 /* Decode an ASN.1 sequence into a C object. */
1471 static asn1_error_code
1472 decode_sequence(const unsigned char *asn1, size_t len,
1473 const struct seq_info *seq, void *val)
1475 asn1_error_code ret;
1476 const unsigned char *contents;
1480 assert(seq->n_fields > 0);
1481 for (i = 0; i < seq->n_fields; i++) {
1484 ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len);
1488 * Find the applicable sequence field. This logic is a little
1489 * oversimplified; we could match an element to an optional extensible
1490 * choice or optional stored-DER type when we ought to match a
1491 * subsequent non-optional field. But it's unwise and (hopefully) very
1492 * rare for ASN.1 modules to require such precision.
1494 for (; i < seq->n_fields; i++) {
1495 if (check_atype_tag(seq->fields[i], &t))
1497 ret = omit_atype(seq->fields[i], val);
1501 /* We currently model all sequences as extensible. We should consider
1502 * changing this before making the encoder visible to plugins. */
1503 if (i == seq->n_fields)
1505 ret = decode_atype(&t, contents, clen, seq->fields[i], val);
1509 /* Initialize any fields in the C object which were not accounted for in
1510 * the sequence. Error out if any of them aren't optional. */
1511 for (; i < seq->n_fields; i++) {
1512 ret = omit_atype(seq->fields[i], val);
1519 /* Free what we've decoded so far. Free pointers in a second pass in
1520 * case multiple fields refer to the same pointer. */
1521 for (j = 0; j < i; j++)
1522 free_atype(seq->fields[j], val);
1523 for (j = 0; j < i; j++)
1524 free_atype_ptr(seq->fields[j], val);
1528 static asn1_error_code
1529 decode_sequence_of(const unsigned char *asn1, size_t len,
1530 const struct atype_info *elemtype, void **seq_out,
1533 asn1_error_code ret;
1534 void *seq = NULL, *elem, *newseq;
1535 const unsigned char *contents;
1536 size_t clen, count = 0;
1542 ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len);
1545 if (!check_atype_tag(elemtype, &t)) {
1549 newseq = realloc(seq, (count + 1) * elemtype->size);
1550 if (newseq == NULL) {
1555 elem = (char *)seq + count * elemtype->size;
1556 memset(elem, 0, elemtype->size);
1557 ret = decode_atype(&t, contents, clen, elemtype, elem);
1567 free_sequence_of(elemtype, seq, count);
1572 /* These three entry points are only needed for the kdc_req_body hack and may
1573 * go away at some point. Define them here so we can use short names above. */
1576 k5_asn1_encode_atype(asn1buf *buf, const void *val, const struct atype_info *a,
1577 taginfo *tag_out, size_t *len_out)
1579 return encode_atype(buf, val, a, tag_out, len_out);
1583 k5_asn1_decode_atype(const taginfo *t, const unsigned char *asn1,
1584 size_t len, const struct atype_info *a, void *val)
1586 return decode_atype(t, asn1, len, a, val);
1590 k5_asn1_full_encode(const void *rep, const struct atype_info *a,
1591 krb5_data **code_out)
1594 asn1_error_code ret;
1595 asn1buf *buf = NULL;
1601 return ASN1_MISSING_FIELD;
1602 ret = asn1buf_create(&buf);
1605 ret = encode_atype_and_tag(buf, rep, a, &len);
1608 ret = asn12krb5_buf(buf, &d);
1613 asn1buf_destroy(&buf);
1618 k5_asn1_full_decode(const krb5_data *code, const struct atype_info *a,
1621 asn1_error_code ret;
1622 const unsigned char *contents, *remainder;
1627 ret = get_tag((unsigned char *)code->data, code->length, &t, &contents,
1628 &clen, &remainder, &rlen);
1631 /* rlen should be 0, but we don't check it (and due to padding in
1632 * non-length-preserving enctypes, it will sometimes be nonzero). */
1633 if (!check_atype_tag(a, &t))
1635 return decode_atype_to_ptr(&t, contents, clen, a, retrep);