summaryrefslogtreecommitdiffstats
path: root/third_party/heimdal/lib/asn1
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
commit8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch)
tree4099e8021376c7d8c05bdf8503093d80e9c7bad0 /third_party/heimdal/lib/asn1
parentInitial commit. (diff)
downloadsamba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz
samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/heimdal/lib/asn1')
-rw-r--r--third_party/heimdal/lib/asn1/ChangeLog1665
-rw-r--r--third_party/heimdal/lib/asn1/MANUAL.md1287
-rw-r--r--third_party/heimdal/lib/asn1/Makefile.am567
-rw-r--r--third_party/heimdal/lib/asn1/NTMakefile548
-rw-r--r--third_party/heimdal/lib/asn1/README-X681.md1124
-rw-r--r--third_party/heimdal/lib/asn1/README-template.md278
-rw-r--r--third_party/heimdal/lib/asn1/README.md1327
-rw-r--r--third_party/heimdal/lib/asn1/asn1-common.h90
-rw-r--r--third_party/heimdal/lib/asn1/asn1-template.h305
-rw-r--r--third_party/heimdal/lib/asn1/asn1_compile-version.rc36
-rw-r--r--third_party/heimdal/lib/asn1/asn1_compile.1355
-rw-r--r--third_party/heimdal/lib/asn1/asn1_err.et29
-rw-r--r--third_party/heimdal/lib/asn1/asn1_gen.c187
-rw-r--r--third_party/heimdal/lib/asn1/asn1_print.1135
-rw-r--r--third_party/heimdal/lib/asn1/asn1_print.c692
-rw-r--r--third_party/heimdal/lib/asn1/asn1parse.y2036
-rw-r--r--third_party/heimdal/lib/asn1/canthandle.asn115
-rw-r--r--third_party/heimdal/lib/asn1/check-ber.c280
-rw-r--r--third_party/heimdal/lib/asn1/check-common.c422
-rw-r--r--third_party/heimdal/lib/asn1/check-common.h92
-rw-r--r--third_party/heimdal/lib/asn1/check-der.c1215
-rw-r--r--third_party/heimdal/lib/asn1/check-gen.c2758
-rw-r--r--third_party/heimdal/lib/asn1/check-gen.h9
-rw-r--r--third_party/heimdal/lib/asn1/check-template.c532
-rw-r--r--third_party/heimdal/lib/asn1/check-timegm.c81
-rw-r--r--third_party/heimdal/lib/asn1/cms.asn1149
-rw-r--r--third_party/heimdal/lib/asn1/cms.opt2
-rw-r--r--third_party/heimdal/lib/asn1/crmf.asn1110
-rw-r--r--third_party/heimdal/lib/asn1/crmf.opt0
-rw-r--r--third_party/heimdal/lib/asn1/der.c142
-rw-r--r--third_party/heimdal/lib/asn1/der.h107
-rw-r--r--third_party/heimdal/lib/asn1/der_cmp.c247
-rw-r--r--third_party/heimdal/lib/asn1/der_copy.c249
-rw-r--r--third_party/heimdal/lib/asn1/der_format.c170
-rw-r--r--third_party/heimdal/lib/asn1/der_free.c156
-rw-r--r--third_party/heimdal/lib/asn1/der_get.c842
-rw-r--r--third_party/heimdal/lib/asn1/der_length.c307
-rw-r--r--third_party/heimdal/lib/asn1/der_locl.h63
-rw-r--r--third_party/heimdal/lib/asn1/der_print.c229
-rw-r--r--third_party/heimdal/lib/asn1/der_put.c717
-rw-r--r--third_party/heimdal/lib/asn1/digest.asn1179
-rw-r--r--third_party/heimdal/lib/asn1/extra.c285
-rw-r--r--third_party/heimdal/lib/asn1/fuzz-inputs/KrbFastArmoredReqbin0 -> 55 bytes
-rw-r--r--third_party/heimdal/lib/asn1/fuzz-inputs/minimal-ek.crtbin0 -> 643 bytes
-rw-r--r--third_party/heimdal/lib/asn1/fuzz-inputs/x690sample.der5
-rw-r--r--third_party/heimdal/lib/asn1/fuzzer.c742
-rw-r--r--third_party/heimdal/lib/asn1/gen.c2090
-rw-r--r--third_party/heimdal/lib/asn1/gen_copy.c290
-rw-r--r--third_party/heimdal/lib/asn1/gen_decode.c841
-rw-r--r--third_party/heimdal/lib/asn1/gen_encode.c747
-rw-r--r--third_party/heimdal/lib/asn1/gen_free.c239
-rw-r--r--third_party/heimdal/lib/asn1/gen_glue.c162
-rw-r--r--third_party/heimdal/lib/asn1/gen_length.c309
-rw-r--r--third_party/heimdal/lib/asn1/gen_locl.h192
-rw-r--r--third_party/heimdal/lib/asn1/gen_print.c43
-rw-r--r--third_party/heimdal/lib/asn1/gen_seq.c127
-rw-r--r--third_party/heimdal/lib/asn1/gen_template.c1675
-rw-r--r--third_party/heimdal/lib/asn1/hash.c206
-rw-r--r--third_party/heimdal/lib/asn1/hash.h87
-rw-r--r--third_party/heimdal/lib/asn1/heim_asn1.h71
-rw-r--r--third_party/heimdal/lib/asn1/krb5.asn11066
-rw-r--r--third_party/heimdal/lib/asn1/krb5.opt9
-rw-r--r--third_party/heimdal/lib/asn1/kx509.asn1204
-rw-r--r--third_party/heimdal/lib/asn1/lex.h42
-rw-r--r--third_party/heimdal/lib/asn1/lex.l310
-rw-r--r--third_party/heimdal/lib/asn1/libasn1-exports.def2655
-rw-r--r--third_party/heimdal/lib/asn1/main.c495
-rw-r--r--third_party/heimdal/lib/asn1/ocsp.asn1113
-rw-r--r--third_party/heimdal/lib/asn1/ocsp.opt2
-rw-r--r--third_party/heimdal/lib/asn1/oid_resolution.c341
-rw-r--r--third_party/heimdal/lib/asn1/pkcs10.asn164
-rw-r--r--third_party/heimdal/lib/asn1/pkcs10.opt1
-rw-r--r--third_party/heimdal/lib/asn1/pkcs12.asn181
-rw-r--r--third_party/heimdal/lib/asn1/pkcs8.asn129
-rw-r--r--third_party/heimdal/lib/asn1/pkcs9.asn129
-rw-r--r--third_party/heimdal/lib/asn1/pkinit.asn1201
-rw-r--r--third_party/heimdal/lib/asn1/pku2u.asn130
-rw-r--r--third_party/heimdal/lib/asn1/rfc2459.asn11210
-rw-r--r--third_party/heimdal/lib/asn1/rfc2459.opt12
-rw-r--r--third_party/heimdal/lib/asn1/rfc4108.asn1207
-rw-r--r--third_party/heimdal/lib/asn1/roken_rename.h46
-rw-r--r--third_party/heimdal/lib/asn1/setchgpw2.asn1193
-rw-r--r--third_party/heimdal/lib/asn1/symbol.c179
-rw-r--r--third_party/heimdal/lib/asn1/symbol.h268
-rw-r--r--third_party/heimdal/lib/asn1/tcg.asn142
-rw-r--r--third_party/heimdal/lib/asn1/template.c3104
-rw-r--r--third_party/heimdal/lib/asn1/test.asn1309
-rw-r--r--third_party/heimdal/lib/asn1/test.gen14
-rw-r--r--third_party/heimdal/lib/asn1/test.opt7
-rw-r--r--third_party/heimdal/lib/asn1/timegm.c136
-rw-r--r--third_party/heimdal/lib/asn1/version-script.map6
-rw-r--r--third_party/heimdal/lib/asn1/x690sample.asn1181
92 files changed, 39431 insertions, 0 deletions
diff --git a/third_party/heimdal/lib/asn1/ChangeLog b/third_party/heimdal/lib/asn1/ChangeLog
new file mode 100644
index 0000000..523e24b
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/ChangeLog
@@ -0,0 +1,1665 @@
+2008-04-09 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * pkinit.asn1: add id-pkinit-kdf
+
+ * pkinit.asn1: add PkinitSP80056AOtherInfo
+
+2008-04-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen.c: Use unsigned where appropriate.
+
+2008-03-22 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * k5.asn1: Match name in ClientCanonicalizedNames with -10
+
+ * k5.asn1: add referral-valid-until
+
+2008-01-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * asn1-common.h gen.c der.c gen_encode.c: add and use der_{malloc,free}
+
+2007-12-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * libasn1.h: remove, not used.
+
+2007-12-04 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add DigestTypes, add --seq to antoher type.
+
+ * digest.asn1: Add supportedMechs request.
+
+2007-10-18 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * k5.asn1: Some "old" windows enctypes. From Andy Polyakov.
+
+2007-07-23 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Fold in pk-init-alg-agilty.
+
+ * pkinit.asn1: Fold in pk-init-alg-agilty.
+
+2007-07-16 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * parse.y: Passe object id is its part of the module defintion
+ statement.
+
+2007-07-14 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-gen.c: test SEQ OF SIZE (...)
+
+ * Makefile.am: Include more sizeof tests.
+
+2007-07-12 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * try to avoid aliasing of pointers enum {} vs int
+
+2007-07-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * test.asn1: Test SIZE attribute for SEQ and OCTET STRING
+
+ * parse.y (OctetStringType): add SIZE to OCTET STRING.
+
+ * Makefile.am: New library version.
+
+2007-07-02 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * rfc2459.asn1: Re-add size limits.
+
+ * k5.asn1: Add size limits from RFC 4120.
+
+ * gen_decode.c: Check range on SEQ OF and OCTET STRING.
+
+ * asn1_err.et (min|max|exact) constraints.
+
+ * parse.y: Parse size limitations to SEQ OF.
+
+2007-06-28 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add AuthorityInfoAccessSyntax.
+
+ * rfc2459.asn1: Add AuthorityInfoAccessSyntax.
+
+ * rfc2459.asn1: Add authorityInfoAccess, rename proxyCertInfo.
+
+ * Makefile.am: Add authorityInfoAccess, rename proxyCertInfo.
+
+2007-06-27 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * der_get.c (der_get_time): avoid using wrapping of octet_string
+ and realloc.
+
+ * der_get.c: No need to undef timetm, we don't use it any more.
+
+ * timegm.c: Fix spelling caused by too much query-replace.
+
+ * gen.c: Include <limits.h> for UINT_MAX.
+
+ * gen_decode.c: Check for multipication overrun.
+
+ * gen_encode.c: Paranoia check in buffer overun in output
+ function.
+
+ * check-der.c: Test boolean.
+
+ * check-der.c: test universal strings.
+
+ * check-der.c: Test failure cases for der_get_tag.
+
+ * check-der.c: test dates from last century.
+
+ * check-der.c: Move zero length integercheck to a better place.
+
+ * check-der.c: Test zero length integer.
+
+2007-06-18 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-der.c: Init data to something.
+
+2007-06-15 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * k5.asn1: Add KRB5-AUTHDATA-INITIAL-VERIFIED-CAS.
+
+2007-06-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * pkinit.asn1: Make the pkinit nonce signed (like the kerberos
+ nonce).
+
+2007-06-03 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-der.c: Free more memory.
+
+ * der_format.c: Don't accect zero length hex numbers.
+
+ * check-der.c: Also free right memory.
+
+ * main.c: Close asn1 file when done.
+
+ * check-der.c: more check for der_parse_hex_heim_integer
+
+ * der_format.c (der_parse_hex_heim_integer): check length before
+ reading data.
+
+ * check-gen.c (test_authenticator): free memory
+
+2007-05-31 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add MS-UPN-SAN
+
+ * pkinit.asn1: add MS-UPN-SAN
+
+ * rfc2459.asn1: Do evil things to handle IMPLICIT encoded
+ structures. Add id-ms-client-authentication.
+
+2007-05-30 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add asn1_id_ms_cert_enroll_domaincontroller.x
+
+2007-05-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen.c: Add struct units; as a forward declaration. Pointed out
+ by Marcus Watts.
+
+ * rfc2459.asn1: Netscape extentions
+
+ * Makefile.am: add U.S. Federal PKI Common Policy Framework
+
+ * rfc2459.asn1: add U.S. Federal PKI Common Policy Framework
+
+2007-04-24 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_seq.c: Handle the case of resize to 0 and realloc that
+ returns NULL.
+
+ * check-gen.c (check_seq): free seq.
+
+2007-04-19 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-der.c (test_heim_oid_format_same): avoid leaking memory in
+ the non failure case too
+
+2007-04-16 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: remove extra ^Q
+
+2007-04-11 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * der_get.c: Allow trailing NULs. We allow this since MIT Kerberos
+ sends an strings in the NEED_PREAUTH case that includes a trailing
+ NUL.
+
+2007-02-17 Love Hörnquist Åstrand <lha@it.su.se>
+
+
+ * Makefile.am: Add PA-ClientCanonicalized and friends.
+
+ * k5.asn1: Add PA-ClientCanonicalized and friends.
+
+2007-02-08 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-der.c: Drop one over INT_MAX test-case.
+
+2007-02-05 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * pkinit.asn1: add id-pkinit-ms-eku
+
+ * pkinit.asn1: fill in more bits of id-pkinit-ms-san
+
+2007-02-02 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * digest.asn1: rename hash-a1 to session key
+
+2007-02-01 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * digest.asn1: Add elements to send in requestResponse to KDC and
+ get status of the request.
+
+2007-01-31 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: seq rules for CRLDistributionPoints
+
+2007-01-30 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add CRLDistributionPoints and friends
+
+2007-01-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-der.c: check BMPstring oddlength more
+
+ * check-der.c: Test for NUL char in string in GENERAL STRING.
+
+ * der_get.c: Check for NUL characters in string and return
+ ASN1_BAD_CHARACTER error-code if we find them.
+
+ * asn1_err.et: Add BAD_CHARACTER error.
+
+2007-01-16 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add id-at-streetAddress.
+
+ * rfc2459.asn1: Add id-at-streetAddress.
+
+2007-01-12 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * rfc2459.asn1: Add PKIXXmppAddr and id-pkix-on-xmppAddr.
+
+2006-12-30 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add id-pkix-kp oids.
+
+ * rfc2459.asn1: Add id-pkix-kp oids.
+
+2006-12-29 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_encode.c: Named bit strings have this horrible, disgusting,
+ compress bits until they are no longer really there but stuff in
+ an initial octet anyway encoding scheme. Try to get it right and
+ calculate the initial octet runtime instead of compiletime.
+
+ * check-gen.c: Check all other silly bitstring combinations.
+
+ * Makefile.am: Add --sequence=Extensions to rfc2459.
+
+2006-12-28 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * kx509.asn1: Add kx509.
+
+ * Makefile.am: Add kx509.
+
+ * Add VisibleString parsing
+
+2006-12-15 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add ntlm files.
+
+ * digest.asn1: Add bits for handling NTLM.
+
+2006-12-08 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add pkix proxy cert policy lang oids
+
+ * rfc2459.asn1: add pkix proxy cert policy lang oids
+
+2006-12-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * rfc2459.asn1: unbreak id-pe-proxyCertInfo
+
+ * rfc2459.asn1: Add id-pkix-on-dnsSRV and related oids
+
+2006-11-28 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add explicit depenency to LIB_roken for libasn1.la,
+ make AIX happy.
+
+2006-11-27 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * der_format.c (der_print_heim_oid): oid with zero length is
+ invalid, fail to print.
+
+2006-11-24 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * der_format.c (der_print_heim_oid): use delim when printing.
+
+2006-11-21 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * k5.asn1: Make KRB5-PADATA-S4U2SELF pa type 129.
+
+2006-10-24 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * asn1_err.et: add EXTRA_DATA
+
+2006-10-21 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-gen.c: avoid leaking memory
+
+ * check-der.c: avoid leaking memory
+
+ * der_format.c (der_parse_heim_oid): avoid leaking memory
+
+ * check-common.c: Print size_t as (unsigned long) and cast.
+
+ * check-common.c: Try to align data, IA64's gets upset if its
+ unaligned.
+
+ * lex.l: add missing */
+
+ * lex.c: need %e for hpux lex
+
+2006-10-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: remove dups from gen_files_test, add check-timegm.
+
+ * Makefile.am: include more test.asn1 built files
+
+ * Makefile.am: More files, now for make check.
+
+2006-10-19 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add missing files
+
+ * Makefile.am (asn1_compile_SOURCES): add gen_locl.h
+
+ * check-timegm.c: Add check for _der_timegm.
+
+ * der_get.c (generalizedtime2time): always use _der_timegm.
+
+ * timegm.c: make more strict
+
+ * der_locl.h: Rename timegm to _der_timegm.
+
+2006-10-17 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * timegm.c: vJust fail if tm_mon is out of range for now XXXX this
+ is wrong.
+
+2006-10-16 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: extra depencies on der-protos.h
+
+2006-10-14 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-der.c: Prefix primitive types with der_.
+
+ * timegm.c: rename the buildin timegm to _der_timegm
+
+ * heim_asn1.h: move prototype away from here.
+
+ * der_format.c: Add der_parse_heim_oid
+
+ * gen_free.c: prefix primitive types with der_
+
+ * der_copy.c: prefix primitive types with der_
+
+ * gen_length.c: prefix primitive types with der_
+
+ * der_length.c: prefix primitive types with der_
+
+ * der_cmp.c: prefix primitive types with der_
+
+ * gen_free.c: prefix primitive types with der_
+
+ * der_free.c: prefix primitive types with der_
+
+ * gen_copy.c: prefix primitive types with der_
+
+ * der_copy.c: rename copy_ to der_copy_
+
+ * Makefile.am: Add der-protos.h to nodist_include_HEADERS.
+
+ * der.h: use newly built <der-protos.h>
+
+ * Makefile.am: Generate der prototypes.
+
+ * gen.c: move any definitions here.
+
+ * asn1-common.h: move any definitions here.
+
+ * der.h: remove der_parse_oid prototype, it was never implemented.
+
+ * der.h: New der_print_heim_oid signature. Test
+ der_parse_heim_oid
+
+ * check-der.c: New der_print_heim_oid signature. Test
+ der_parse_heim_oid
+
+2006-10-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * lex.l: Grow an even larger output table size.
+
+ * Makefile.am: split build files into dist_ and noinst_ SOURCES
+
+2006-10-04 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_seq.c: In generation of remove_TYPE: if you just removed the
+ last element, you must not memmove memory beyond the array. From
+ Andrew Bartlett
+
+2006-10-01 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * lex.l: Grow (%p, %a, %n) tables for Solaris 10 lex. From Harald
+ Barth.
+
+2006-09-24 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_decode.c (decode_type): drop unused variable realtype.
+
+2006-09-11 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add KRB5SignedPath and friends.
+
+ * k5.asn1: Add KRB5SignedPath and friends.
+
+ * Makefile.am: Add new sequence generation for GeneralNames.
+
+2006-09-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * CMS.asn1 (CMSVersion): rename versions from v0 to CMSVersion_v0,
+ ...
+
+2006-09-05 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add TESTSeqOf for testing sequence generation code.
+
+ * check-gen.c: Add sequence tests.
+
+ * test.asn1: Add TESTSeqOf for testing sequence generation code.
+
+ * gen_seq.c: fix warning.
+
+ * gen_seq.c: make generated data work
+
+ * setchgpw2.asn1: enctype is part of the krb5 module now, use that
+ instead of locally defining it.
+
+ * Makefile.am: asn1_compile += gen_seq.c
+
+ * gen_locl.h: add new prototypes, remove unused ones.
+
+ * gen.c: Generate sequence function.
+
+ * main.c: add --sequence
+
+ * gen_seq.c: Add generated add_ and remove_ for "SEQUENCE OF
+ TType". I'm tried of writing realloc(foo->data,
+ sizeof(foo->data[0]) + (foo->len + 1)); Only generated for those
+ type that is enabled by the command flag --sequence.
+
+2006-08-25 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * digest.asn1 (DigestRequest): add authid
+
+ * digest.asn1: Comment describing on how to communicate the sasl
+ int/conf mode.
+
+2006-08-23 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * digest.asn1: Add some missing fields needed for digest.
+
+2006-08-21 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * digest.asn1: Tweak to make consisten and more easier to use.
+
+2006-07-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Remove CMS symmetric encryption support. Add
+ DigestProtocol.
+
+ * digest.asn1: DigestProtocol
+
+ * k5.asn1: Remove CMS symmetric encryption support.
+
+2006-06-22 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-der.c (check_fail_heim_integer): disable test
+
+ * der_get.c (der_get_heim_integer): revert part of previous
+
+ * der_get.c (der_get_heim_integer): Add more checks
+
+ * asn1_print.c: Add printing of bignums and use der_print_heim_oid
+
+ * check-der.c (test_heim_oid_format_same): add printing on failure
+
+ * check-der.c: Add one check for heim_int, add checking for oid
+ printing
+
+2006-06-06 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Impersonation support bits (and sort)
+
+ * k5.asn1: Impersonation support bits.
+
+2006-05-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * der_format.c (der_parse_hex_heim_integer): avoid shadowing.
+
+2006-04-29 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add ExternalPrincipalIdentifiers, shared between
+ several elements.
+
+ * pkinit.asn1: Add ExternalPrincipalIdentifiers, shared between
+ several elements.
+
+2006-04-28 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * parse.y: Add missing ;'s, found by bison on a SuSE 8.2 machine.
+
+2006-04-26 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add definitions from RFC 3820, Proxy Certificate
+ Profile.
+
+ * rfc2459.asn1: Add definitions from RFC 3820, Proxy Certificate
+ Profile.
+
+2006-04-24 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * rfc2459.asn1: Add id-Userid
+
+ * Makefile.am: Add UID and email
+
+ * pkcs9.asn1: Add id-pkcs9-emailAddress
+
+ * Makefile.am: Add attribute type oids from X520 and RFC 2247 DC
+ oid
+
+ * rfc2459.asn1: Add attribute type oids from X520 and RFC 2247 DC
+ oid
+
+2006-04-21 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add sha-1 and sha-2
+
+ * rfc2459.asn1: add sha-1 and sha-2
+
+2006-04-15 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add id-pkcs1-sha256WithRSAEncryption and friends
+
+ * rfc2459.asn1: Add id-pkcs1-sha256WithRSAEncryption and friends
+
+ * CMS.asn1: Turn CMSRC2CBCParameter.rc2ParameterVersion into a
+ constrained integer
+
+2006-04-08 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * hash.c (hashtabnew): check for NULL before setting structure.
+ Coverity, NetBSD CID#4
+
+2006-03-31 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: gen_files_rfc2459 += asn1_ExtKeyUsage.x
+
+ * rfc2459.asn1: Add ExtKeyUsage.
+
+ * gen.c (generate_header_of_codefile): remove unused variable.
+
+2006-03-30 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen.c: Put all the IMPORTed headers into the headerfile to avoid
+ hidden depencies.
+
+2006-03-27 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add id-pkinit-ms-san.
+
+ * pkinit.asn1: Add id-pkinit-ms-san.
+
+ * k5.asn1 (PADATA-TYPE): Add KRB5-PADATA-PA-PK-OCSP-RESPONSE
+
+2006-03-26 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add pkinit-san.
+
+ * pkinit.asn1: Rename id-pksan to id-pkinit-san
+
+2006-03-08 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen.c (init_generate): Nothing in the generated files needs
+ timegm(), so no need to provide a prototype for it.
+
+2006-02-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * pkinit.asn1: paChecksum is now OPTIONAL so it can be upgraded to
+ something better then SHA1
+
+2006-01-31 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * extra.c: Stub-generator now generates alloc statements for
+ tagless ANY OPTIONAL, remove workaround.
+
+ * check-gen.c: check for "tagless ANY OPTIONAL"
+
+ * test.asn1: check for "tagless ANY OPTIONAL"
+
+2006-01-30 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * der.h: UniversalString and BMPString are both implemented.
+
+ * der.h: Remove , after the last element of enum.
+
+ * asn1_gen.c: Spelling.
+
+2006-01-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * der_length.c (length_heim_integer): Try handle negative length
+ of integers better.
+
+ * der_get.c (der_get_heim_integer): handle negative integers.
+
+ * check-der.c: check heim_integer.
+
+2006-01-18 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Its cRLReason, not cRLReasons
+
+ * canthandle.asn1: "Allocation is done on CONTEXT tags" works just
+ fine.
+
+ * rfc2459.asn1: Add CRL structures and OIDs.
+
+ * Makefile.am: Add CRL and TESTAlloc structures and OIDs.
+
+ * check-gen.c: Check OPTIONAL context-tagless elements.
+
+ * test.asn1: Check OPTIONAL context-tagless elements.
+
+ * der_cmp.c (heim_integer_cmp): make it work with negative
+ numbers.
+
+2006-01-17 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-der.c: check that der_parse_hex_heim_integer() handles odd
+ length numbers.
+
+ * der_format.c (der_parse_hex_heim_integer): make more resiliant
+ to errors, handle odd length numbers.
+
+2006-01-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add RSAPrivateKey
+
+ * rfc2459.asn1: Add RSAPrivateKey.
+
+2006-01-05 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * der_copy.c (copy_heim_integer): copy the negative flag
+
+2005-12-14 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * parse.y: Drop ExceptionSpec for now, its not used.
+
+2005-12-06 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * test.asn1: Add test string for constraints.
+
+ * symbol.h: Add support for part of the Constraint-s
+
+ * gen.c: Set new constraints pointer in Type to NULL for inline
+ constructed types.
+
+ * parse.y: Add support for parsing part of the Constraint-s
+
+2005-10-29 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add some X9.57 (DSA) oids, sort lines
+
+ * rfc2459.asn1: Add some X9.57 (DSA) oids.
+
+2005-10-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Remove pk-init-19 support.
+
+ * pkinit.asn1: Fix comment
+
+ * check-der.c: Add tests for parse and print functions for
+ heim_integer.
+
+ * Makefile.am: Add parse and print functions for heim_integer.
+
+ * der_format.c: Add parse and print functions for heim_integer.
+
+ * der.h: Add parse and print functions for heim_integer.
+
+2005-09-22 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am (gen_files_rfc2459) += asn1_DHPublicKey.x
+
+ * rfc2459.asn1: Add DHPublicKey, and INTEGER to for storing the DH
+ public key in the SubjectPublicKeyInfo.subjectPublicKey BIT
+ STRING.
+
+2005-09-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_decode.c: TSequenceOf/TSetOf: Increase the length of the
+ array after successful decoding the next element, so that the
+ array don't contain heap-data.
+
+2005-09-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-der.c: Avoid empty array initiators.
+
+ * pkcs8.asn1 (PKCS8PrivateKeyInfo): Inline SET OF to avoid
+ compiler "feature"
+
+ * check-common.c: Avoid signedness warnings.
+
+ * check-common.h: Makes bytes native platform signed to avoid
+ casting everywhere
+
+ * check-der.c: Don't depend on malloc(very-very-larger-value) will
+ fail. Cast to unsigned long before printing size_t.
+
+ * check-gen.c: Don't depend on malloc(very-very-larger-value) will
+ fail.
+
+ * check-gen.c: Fix signedness warnings.
+
+ * lex.l: unput() have to hanppen in actions for flex 2.5.31, can
+ do them in user code sesction, so move up handle_comment and
+ handle_string into action, not much sharing was done anyway.
+
+2005-09-09 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-der.c (test_one_int): len and len_len is size_t
+
+2005-08-23 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_encode.c: Change name of oldret for each instance its used
+ to avoid shadow warning. From: Stefan Metzmacher
+ <metze@samba.org>.
+
+ * gen_length.c: Change name of oldret for each instance its used
+ to avoid shadow warning. From: Stefan Metzmacher
+ <metze@samba.org>.
+
+ * gen_decode.c: Change name of oldret for each instance its used
+ to avoid shadow warning. From: Stefan Metzmacher
+ <metze@samba.org>.
+
+ * parse.y: Const poision yyerror.
+
+ * gen.c: Const poision.
+
+2005-08-22 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * k5.asn1: Add KRB5-PADATA-PK-AS-09-BINDING, client send
+ this (with an empty pa-data.padata-value) to tell the KDC that the
+ client support the binding the PA-REP to the AS-REQ packet. This
+ is to fix the problem lack of binding the AS-REQ to the PK-AS-REP
+ in pre PK-INIT-27. The nonce is replaced with a asCheckSum.
+
+2005-08-11 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * canthandle.asn1: Allocation is done on CONTEXT tags.
+
+ * asn1_gen.c: rename optind to optidx to avoid shadow warnings
+
+2005-07-28 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * rfc2459.asn1: add id-rsadsi-rc2-cbc
+
+ * Makefile.am: add another oid for rc2
+
+2005-07-27 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-der.c: Make variable initiation constant by moving them to
+ global context
+
+ * check-gen.c: change to c89 comment
+
+2005-07-27 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: remove duplicate asn1_CMSAttributes.x
+
+2005-07-26 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * asn1_print.c: rename optind to optidx
+
+ * Makefile.am: Update to pkinit-27
+
+ * pkinit.asn1: Update to pkinit-27
+
+2005-07-25 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-der.c: make it work for non c99 compilers too
+
+ * check-der.c: start testing BIT STRING
+
+ * der_cmp.c (heim_bit_string_cmp): try handle corner cases better
+
+ * gen_free.c (free_type): free bignum integers
+
+2005-07-23 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add PKCS12-OctetString
+
+ * pkcs12.asn1: add PKCS12-OctetString
+
+ * Makefile.am: add new files
+
+ * rfc2459.asn1: include SET OF in Attribute to make the type more
+ useful
+
+ * CMS.asn1: handle IMPLICIT and share some common structures
+
+2005-07-21 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * rfc2459.asn1: Include enough workarounds that this even might
+ work.
+
+ * check-gen.c: Two implicit tests, one with all structures inlined
+
+ * test.asn1: fix workaround for IMPLICIT CONS case
+
+ * canthandle.asn1: fix workaround for IMPLICIT CONS case
+
+ * asn1_print.c: hint that there are IMPLICIT content when we find
+ it
+
+ * check-gen.c: Added #ifdef out test for IMPLICIT tagging.
+
+ * Makefile.am: test several IMPLICIT tag level deep
+
+ * test.asn1: test several IMPLICIT tag level deep
+
+ * test.asn1: tests for IMPLICIT
+
+ * Makefile.am: tests for IMPLICIT
+
+ * canthandle.asn1: Expand on what is wrong with the IMPLICIT
+ tagging
+
+ * rfc2459.asn1: some of the structure are in the IMPLICIT TAGS
+ module
+
+2005-07-19 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * asn1_print.c: print size_t by casting to unsigned long and use
+ right printf format tags are unsigned integers
+
+ * gen.c (generate_constant): oid elements are unsigned
+
+ * gen_decode.c (decode_type): tagdatalen should be an size_t.
+
+ * extra.c (decode_heim_any): tag is unsigned int.
+
+ * der_get.c (der_match_tag): tag is unsigned int.
+
+ * gen_length.c (length_type): cast size_t argument to unsigned
+ long and use appropriate printf format
+
+ * check-der.c (check_fail_bitstring): check for length overflow
+
+ * der_get.c: rewrite integer overflow tests w/o SIZE_T_MAX
+
+ * check-common.c (generic_decode_fail): only copy in if checklen
+ its less then 0xffffff and larger than 0.
+
+ * gen_decode.c (find_tag): find external references, we can't
+ handle those, so tell user that instead of crashing
+
+2005-07-18 Dave Love <fx@gnu.org>
+
+ * extra.c (free_heim_any_set): Fix return.
+
+ * gen_decode.c (find_tag): Fix return in TType case.
+
+2005-07-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_encode.c (TChoice): add () to make sure variable expression
+ is evaluated correctly
+
+ * gen_length.c (TChoice): add () to make sure variable expression
+ is evaluated correctly
+
+ * k5.asn1: reapply 1.43 that got lost in the merge: rename pvno to
+ krb5-pvno
+
+2005-07-12 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_decode.c (decode_type): TChoice: set the label
+
+ * check-gen.c (cmp_Name): do at least some checking
+
+ * gen_locl.h: rename function filename() to get_filename() to
+ avoid shadowing
+
+ * lex.l: rename function filename() to get_filename() to avoid
+ shadowing
+
+ * gen.c: rename function filename() to get_filename() to avoid
+ shadowing
+
+ * check-der.c: add failure checks for large oid elements
+
+ * check-gen.c: add failure checks for tag (and large tags)
+
+ * der_get.c: Check for integer overflows in tags and oid elements.
+
+2005-07-10 Assar Westerlund <assar@kth.se>
+
+ * gen_decode.c: Fix decoding of choices to select which branch to
+ try based on the tag and return an error if that branch fails.
+
+ * check-gen.c: Fix short choice test cases.
+
+2005-07-09 Assar Westerlund <assar@kth.se>
+
+ * symbol.c:
+ * parse.y:
+ * main.c:
+ * lex.l:
+ * gen_length.c:
+ * gen_free.c:
+ * gen_encode.c:
+ * gen_decode.c:
+ * gen_copy.c:
+ * gen.c:
+ * extra.c:
+ * check-gen.c:
+ * check-der.c:
+ * check-common.c:
+ * asn1_print.c:
+ * asn1_gen.c:
+ Use emalloc, ecalloc, and estrdup.
+ Check return value from asprintf.
+ Make sure that malloc(0) returning NULL is not treated as an
+ error.
+
+2005-07-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-gen.c: test cases for CHOICE, its too liberal right now,
+ it don't fail hard on failure on after it successfully decoded the
+ first tag in a choice branch
+
+ * asn1_gen.c: calculate the basename for the output file,
+ pretty-print tag number
+
+ * test.gen: sample for asn1_gen
+
+ * check-gen.c: check errors in SEQUENCE
+
+ * Makefile.am: build asn1_gen, TESTSeq and new, and class/type/tag
+ string<->num converter.
+
+ * test.asn1: TESTSeq, for testing SEQUENCE
+
+ * asn1_gen.c: generator for asn1 data
+
+ * asn1_print.c: use class/type/tag string<->num converter.
+
+ * der.c: Add class/type/tag string<->num converter.
+
+ * der.h: Add class/type/tag string<->num converter.
+ Prototypes/structures for new time bits.
+
+2005-07-09 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * der_get.c (der_get_unsigned) check for length overflow
+ (der_get_integer) ditto
+ (der_get_general_string) ditto
+
+ * der_get.c: check for overruns using SIZE_T_MAX
+
+ * check-der.c: check BIT STRING and OBJECT IDENTIFIER error cases
+
+ * check-common.c (generic_decode_fail): allocate 4K for the over
+ sized memory test
+
+ * der_get.c (der_get_oid): check for integer overruns and
+ unterminated oid correctly
+
+ * check-common.h (map_alloc, generic_decode_fail): prototypes
+
+ * check-common.c (map_alloc): make input buffer const
+ (generic_decode_fail): verify decoding failures
+
+2005-07-05 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_encode.c: split up the printf for SET OF, also use the
+ generate name for the symbol in the SET OF, if not, the name might
+ contain non valid variable name characters (like -)
+
+2005-07-04 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: move pkcs12 defines into their own namespace
+
+ * pkcs12.asn1: move pkcs12 defines into their own namespace
+
+ * pkcs9.asn1: add PKCS9-friendlyName with workaround for SET OF
+ bug
+
+ * heim_asn1.h: reuse heim_octet_string for heim_any types
+
+ * main.c: use optidx, handle the case where name is missing and
+ use base of filename then
+
+ * asn1-common.h: include ASN1_MALLOC_ENCODE
+
+ * gen_decode.c: use less context so lower indentention level, add
+ missing {} where needed
+
+2005-07-02 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_copy.c: Use a global variable to keep track of if the 'goto
+ fail' was used, and use that to only generate the label if needed.
+
+ * asn1_print.c: do indefinite form loop detection and stop after
+ 10000 recursive indefinite forms, stops crashing due to running
+ out of stack
+
+ * asn1_print.c: catch badly formated indefinite length data
+ (missing EndOfContent tag) add (negative) indent flag to speed up
+ testing
+
+2005-07-01 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * canthandle.asn1: Can't handle primitives in CHOICE
+
+ * gen_decode.c: Check if malloc failes
+
+ * gen_copy.c: Make sure to free memory on failure
+
+ * gen_decode.c: Check if malloc failes, rename "reallen" to
+ tagdatalen since that is what it is.
+
+2005-05-29 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * prefix Der_class with ASN1_C_ to avoid problems with system
+ headerfiles that pollute the name space
+
+2005-05-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * pkcs12.asn1: add PKCS12CertBag
+
+ * pkcs9.asn1: add pkcs9 certtype x509 certificate
+
+ * Makefile.am: add pkcs12 certbag and pkcs9 certtype x509
+ certificate
+
+ * pkcs12.asn1: split off PKCS12Attributes from SafeBag so it can
+ be reused
+
+ * Makefile.am: add PKCS12Attributes
+
+2005-05-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * canthandle.asn1: fix tags in example
+
+2005-05-02 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * pkinit.asn1: Let the Windows nonce be an int32 (signed), if not
+ it will fail when using Windows PK-INIT.
+
+2005-05-01 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add pkcs12-PBEParams
+
+ * pkcs12.asn1: add pkcs12-PBEParams
+
+ * parse.y: objid_element: exit when the condition fails
+
+2005-04-26 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_glue.c: 1.8: switch the units variable to a
+ function. gcc-4.1 needs the size of the structure if its defined
+ as extern struct units foo_units[] an we don't want to include
+ <parse_units.h> in the generate headerfile
+
+2005-03-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add the des-ede3-cbc oid that ansi x9.52 uses
+
+ * rfc2459.asn1: add the des-ede3-cbc oid that ansi x9.52 uses
+
+ * Makefile.am: add oids for x509
+
+ * rfc2459.asn1: add oids now when the compiler can handle them
+
+2005-03-19 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add pkcs9 files
+
+ * pkcs9.asn1: add small number of oids from pkcs9
+
+2005-03-14 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add a bunch of pkcs1/pkcs2/pkcs3/aes oids
+
+ * rfc2459.asn1: add a bunch of pkcs1/pkcs2/pkcs3/aes oids
+
+2005-03-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * k5.asn1: merge pa-numbers
+
+2005-03-09 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add oid's
+
+ * rfc2459.asn1: add encryption oids
+
+ * CMS.asn1: add signedAndEnvelopedData oid
+
+ * pkcs12.asn1: add pkcs12 oids
+
+ * CMS.asn1: add pkcs7 oids
+
+2005-03-08 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen.c (generate_header_of_codefile): break out the header
+ section generation
+ (generate_constant): generate a function that return the oid
+ inside a heim_oid
+
+ * parse.y: fix the ordering of the oid's
+
+ * parse.y: handle OBJECT IDENTIFIER as value construct
+
+2005-02-24 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Preserve content of CHOICE element that is unknown if ellipsis
+ was used when defining the structure
+
+2005-02-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * parse.y: use ANS1_TAILQ macros
+
+ * *.[ch]: use ASN1_TAILQ macros
+
+ * asn1_queue.h: inline bsd sys/queue.h and rename TAILQ to
+ ASN1_TAILQ to avoid problems with name polluting headerfiles
+
+2005-01-19 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen.c: pull in <krb5-types.h>
+
+2005-01-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Add BMPString and UniversalString
+
+ * k5.asn1 (EtypeList): make INTEGER constrained (use krb5int32)
+
+2005-01-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * rfc2459.asn1: add GeneralNames
+
+2004-11-21 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen.c: use unsigned integer for len of SequenceOf/SetOf and
+ bitstring names
+
+2004-11-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: switch to krb5int32 and krb5uint32
+
+ * Unify that three integer types TInteger TUInteger and TBigInteger.
+ Start to use constrained integers where appropriate.
+
+2004-10-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * CMS.asn1: remove no longer used commented out elements
+
+ * gen_glue.c: make units structures const
+
+2004-10-12 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * lex.l: handle hex number with [a-fA-F] in them
+
+2004-10-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_free.c: free _save for CHOICE too
+
+ * rfc2459.asn1: use Name and not heim_any
+
+ * gen_decode.c: if malloc for _save failes, goto fail so we free
+ the structure
+
+ * gen_copy.c: copy _save for CHOICE too
+
+ * gen.c: add _save for CHOICE too
+
+ * CMS.asn1: RecipientIdentifier and SignerIdentifier is the same
+ name is CMSIdentifier and add glue for that so we can share code
+ use Name and not heim_any
+
+2004-10-03 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: drop AlgorithmIdentifierNonOpt add
+ {RC2CBC,}CBCParameter here where they belong
+
+ * CMS.asn1: add {RC2CBC,}CBCParameter here where they belong
+
+ * rfc2459.asn1: drop AlgorithmIdentifierNonOpt
+
+ * rfc2459.asn1: stop using AlgorithmIdentifierNonOpt hint that we
+ really want to use Name and some MS stuff
+
+2004-09-05 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * asn1_print.c: handle end of content, this is part BER support,
+ however, OCTET STRING need some tweeking too.
+
+ * der.h: add UT_EndOfContent
+
+ * test.asn1: test asn1 spec file
+
+ * check-gen.c: check larget tags
+
+ * Makefile.am: add test asn1 spec file that we can use for testing
+ constructs that doesn't exists in already existing spec (like
+ large tags)
+
+ * der_put.c (der_put_tag): make sure there are space for the head
+ tag when we are dealing with large tags (>30)
+
+ * check-gen.c: add test for tag length
+
+ * check-common.c: export the map_ functions for OVERRUN/UNDERRUN
+ detection restore the SIGSEGV handler when test is done
+
+ * check-common.h: export the map_ functions for OVERRUN/UNDERRUN
+ detection
+
+ * gen_decode.c: check that the tag-length is not longer the length
+ use forwstr on some more places
+
+ * parse.y: revert part of 1.14.2.21, multiple IMPORT isn't allowed
+
+ * pkinit.asn1: correct usage of IMPORT
+
+ * CMS.asn1: correct usage of IMPORT
+
+ * pkcs8.asn1: pkcs8, encrypting private key
+
+ * pkcs12.asn1: pkcs12, key/crl/certificate file transport PDU
+
+ * Makefile.am: add pkcs8 and pkcs12
+
+ * der_free.c: reset length when freing primitives
+
+ * CMS.asn1: add EncryptedData
+
+2004-08-26 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_decode.c (decode_type): if the entry is already optional
+ when parsing a tag and we allocate the structure, not pass down
+ optional since that will case the subtype's decode_type also to
+ allocate an entry. and we'll leak an entry. Bug from Luke Howard
+ <lukeh@padl.com>. While here, use calloc.
+
+2004-04-29 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * k5.asn1: shift the last added etypes one step so rc2 doesn't
+ stomp on cram-md5
+
+2004-04-26 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * k5.asn1: add ETYPE_AESNNN_CBC_NONE
+
+ * CMS.asn1: add CMS symmetrical parameters moved to k5.asn1
+
+ * k5.asn1: add CMS symmetrical parameters here, more nametypes
+ enctype rc2-cbc
+
+2004-04-25 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_decode.c: free data on decode failure
+
+2004-04-24 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add CBCParameter and RC2CBCParameter
+
+ * CMS.asn1: add CBCParameter and RC2CBCParameter
+
+2004-04-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * check-der.c: add simple test for oid's, used to trigger malloc
+ bugs in you have picky malloc (like valgrind/purify/third)
+
+ * der_get.c (der_get_oid): handle all oid components being smaller
+ then 127 and allocate one extra element since first byte is split
+ to to elements.
+
+2004-04-16 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * canthandle.asn1: one thing handled
+
+ * gen_decode.c: handle OPTIONAL CONS-tag-less elements
+
+ * der_length.c (length_len): since length is no longer the same as
+ an unsigned, do the length counting here. ("unsigned" is zero
+ padded when most significate bit is set, length is not)
+
+2004-04-12 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * canthandle.asn1: document by example what the encoder can't
+ handle right now
+
+ * Makefile.am: add more stuff needed whem implementing x509
+ preserve TBSCertificate
+
+ * rfc2459.asn1: add more stuff needed whem implementing x509
+
+ * CMS.asn1: move some type to rfc2459.asn1 where they belong (and
+ import them)
+
+ * gen.c: preserve the raw data when asked too
+
+ * gen_decode.c: preserve the raw data when asked too
+
+ * gen_copy.c: preserve the raw data when asked too
+
+ * gen_free.c: preserve the raw data when asked too
+
+ * gen_locl.h: add preserve_type
+
+ * heim_asn1.h: add heim_any_cmp
+
+ * main.c: add flag --preserve-binary=Symbol1,Symbol2,... that make
+ the compiler generate stubs to save the raw data, its not used
+ right now when generating the stat
+
+ * k5.asn1: Windows uses PADATA 15 for the request too
+
+ * extra.c: add heim_any_cmp
+
+ * der_put.c: implement UTCtime correctly
+
+ * der_locl.h: remove #ifdef HAVE_TIMEGM\ntimegm\n#endif here from
+ der.h so one day der.h can get installed
+
+ * der_length.c: implement UTCtime correctly
+
+ * der_get.c: implement UTCtime correctly, prefix dce_fix with
+ _heim_fix
+
+ * der_copy.c: make copy_bit_string work again
+
+ * der_cmp.c: add octet_string, integer, bit_string cmp functions
+
+ * der.h: hide away more symbols, add more _cmp functions
+
+2004-03-06 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add more pkix types make k5 use rfc150 bitstrings,
+ everything else use der bitstrings
+
+ * main.c: as a compile time option, handle no rfc1510 bitstrings
+
+ * gen_locl.h: rfc1510 bitstrings flag
+
+ * gen_length.c: as a compile time option, handle no rfc1510
+ bitstrings
+
+ * gen_encode.c: as a compile time option, handle no rfc1510
+ bitstrings
+
+ * gen_decode.c: handle no rfc1510 bitstrings
+
+ * check-gen.c: test for bitstrings
+
+ * rfc2459.asn1: add Certificates and KeyUsage
+
+2004-02-22 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * pkinit.asn1: use Name from PKIX
+
+ * rfc2459.asn1: add more silly string types to DirectoryString
+
+ * gen_encode.c: add checks for data overflow when encoding
+ TBitString with members encode SET OF correctly by bytewise
+ sorting the members
+
+ * gen_decode.c: add checks for data overrun when encoding
+ TBitString with members
+
+ * der_put.c: add _heim_der_set_sort
+
+ * der_cmp.c: rename oid_cmp to heim_oid_cmp
+
+ * der.h: rename oid_cmp to heim_oid_cmp, add _heim_der_set_sort
+
+ * check-gen.c: add check for Name and (commented out) heim_integer
+
+ * check-der.c: test for "der_length.c: Fix len_unsigned for
+ certain negative integers, it got the length wrong" , from
+ Panasas, Inc.
+
+ * der_length.c: Fix len_unsigned for certain negative integers, it
+ got the length wrong, fix from Panasas, Inc.
+
+ rename len_int and len_unsigned to _heim_\&
+
+ * gen_length.c: 1.14: (length_type): TSequenceOf: add up the size
+ of all the elements, don't use just the size of the last element.
+
+2004-02-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * rfc2459.asn1: include defintion of Name
+
+ * pkinit.asn1: no need for ContentType, its cms internal
+
+ * CMS.asn1: move ContentInfo to CMS
+
+ * pkinit.asn1: update to pk-init-18, move ContentInfo to CMS
+
+ * Makefile.am: align with pk-init-18, move contentinfo to cms
+
+2004-02-17 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * der_get.c: rewrite previous commit
+
+ * der_get.c (der_get_heim_integer): handle positive integer
+ starting with 0
+
+ * der_length.c (der_put_heim_integer): try handle negative
+ integers better (?)
+
+ * der_put.c (der_put_heim_integer): try handle negative integers
+ better
+
+ * der_get.c (der_get_heim_integer): dont abort on negative integer just
+ return ASN1_OVERRUN for now
+
+ * parse.y: add ia5string, and printablestring
+
+ * gen_length.c: add ia5string, and printablestring
+
+ * gen_free.c: add ia5string, and printablestring
+
+ * gen_decode.c: add ia5string, and printablestring
+
+ * gen_copy.c: add ia5string, and printablestring
+
+ * gen.c: add ia5string, printablestring, and utf8string change
+ implemetation of heim_integer and store the data as bigendian byte
+ array with a external flag for signedness
+
+ * der_put.c: add ia5string, printablestring, and utf8string change
+ implemetation of heim_integer and store the data as bigendian byte
+ array with a external flag for signedness
+
+ * der_length.c: add ia5string, printablestring, and utf8string
+ change implemetation of heim_integer and store the data as
+ bigendian byte array with a external flag for signedness
+
+ * der_get.c: add ia5string, printablestring, and utf8string change
+ implemetation of heim_integer and store the data as bigendian byte
+ array with a external flag for signedness
+
+ * der_free.c: add ia5string, printablestring, and utf8string
+
+ * der_copy.c: add ia5string, printablestring, and utf8string
+
+ * der.h: add ia5string, printablestring, and utf8string
+
+ * asn1-common.h: add signedness flag to heim_integer, add
+ ia5string and printablestring
+
+2004-02-13 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * rfc2459.asn1: use BIGINTEGER where appropriate
+
+ * setchgpw2.asn1: spelling and add op-req again
+
+2004-02-12 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: clean up better
+
+2004-02-11 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_decode.c (decode_type): TTag, don't overshare the reallen
+ variable
+
+ * Makefile.am: adapt to log file name change
+
+ * gen.c: genereate log file name based on base name
+
+2003-11-26 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: += asn1_AlgorithmIdentifierNonOpt.x
+
+ * rfc2459.asn1: add AlgorithmIdentifierNonOpt and use it where
+ it's needed, make DomainParameters.validationParms heim_any as a
+ hack. Both are workarounds for the problem with heimdal's asn1
+ compiler have with decoing context tagless OPTIONALs.
+
+ * pkinit.asn1: don't import AlgorithmIdentifier
+
+2003-11-25 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * der_put.c (der_put_bit_string): make it work somewhat better
+ (should really prune off all trailing zeros)
+
+ * gen_encode.c (encode_type): bit string is not a constructed type
+
+ * der_length.c (length_bit_string): calculate right length for
+ bitstrings
+
+2003-11-24 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * der_cmp.c (oid_cmp): compare the whole array, not just
+ length/sizeof(component)
+
+ * check-common.c: mmap the scratch areas, mprotect before and
+ after, align data to the edge of the mprotect()ed area to provoke
+ bugs
+
+ * Makefile.am: add DomainParameters, ValidationParms
+
+ * rfc2459.asn1: add DomainParameters, ValidationParms
+
+ * check-der.c: add free function
+
+ * check-common.h: add free function
+
+ * check-common.c: add free function
+
+ * check-gen.c: check KRB-ERROR
+
+ * asn1_print.c: check end of tag_names loop into APPL class tags
+
+2003-11-23 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * der_put.c (der_put_generalized_time): check size, not *size
+
+2003-11-11 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_decode.c (decode_type/TBitString): skip over
+ skipped-bits-in-last-octet octet
+
+ * gen_glue.c (generate_units): generate units in reverse order to
+ keep unparse_units happy
+
+2003-11-08 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: generate all silly pkinit files
+
+ * pkinit.asn1: make it work again, add strange ms structures
+
+ * k5.asn1: PROV-SRV-LOCATION, PacketCable provisioning server
+ location, PKT-SP-SEC-I09-030728
+
+ * asn1-common.h: add bit string
+
+ * der_put.c: add bit string and utctime
+
+ * gen.c: add bit string and utctime
+
+ * gen_copy.c: add bit string and utctime
+
+ * der_copy.c: add bit string
+
+ * gen_decode.c: add utctime and bitstring
+
+ * gen_encode.c: add utctime and bitstring
+
+ * gen_free.c: add utctime and bitstring
+
+ * gen_glue.c: don't generate glue for member-less bit strings
+
+ * der_cmp.c: compare function for oids
+
+ * gen_length.c: add utc time, make bit string work for bits
+ strings w/o any members
+
+ * der_cmp.c: compare function for oids
+
+ * der.h: update boolean prototypes add utctime and bit_string
+
+ * der_free.c: add free_bit_string
+
+ * der_get.c: add bit string and utctime
+
+ * der_length.c: add bit string and utctime, fix memory leak in
+ length_generalized_time
+
+ * CMS.asn1: make EncryptedContentInfo.encryptedContent a OCTET
+ STRING to make the generator do the right thing with IMPLICIT
+ mumble OPTIONAL, make CertificateSet a heim_any_set
+
+ * extra.c, heim_asn1.h: add any_set, instead of just consuming one
+ der object, its consumes the rest of the data avaible
+
+ * extra.c, heim_asn1.h: extern implementation of ANY, decoder
+ needs to have hack removed when generator handles tagless optional
+ data
+
+ * pkinit.asn1: add KdcDHKeyInfo-Win2k
+
+2003-11-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * der_copy.c (copy_oid): copy all components
+
+ * parse.y: parse UTCTime, allow multiple IMPORT
+
+ * symbol.h: add TUTCTime
+
+ * rfc2459.asn1: update
+
+ * x509.asn1: update
+
+ * pkinit.asn1: update
+
+ * CMS.asn1: new file
+
+ * asn1_print.c: print some more lengths, check length before
+ steping out in the void, parse SET, only go down CONTEXT of type
+ CONS (not PRIM)
+
+2003-09-17 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_encode.c (TChoice, TSequence): code element in reverse
+ order...
+
+2003-09-16 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen.c: store NULL's as int's for now
+
+ * parse.y: remove dup of type def of UsefulType
+
+2003-09-11 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_decode.c (decode_type): if malloc failes, return ENOMEM
+
+2003-09-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * parse.y: kw_UTF8String is a token put tag around the OID
+
+ * asn1_print.c (UT_Integer): when the integer is larger then int
+ can handle, just print BIG INT and its size
+
+2003-09-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * gen_decode.c (decode_type): TTag, try to generate prettier code
+ in the non optional case, also remember to update length
+
+2003-01-22 Johan Danielsson <joda@pdc.kth.se>
+
+ * gen_decode.c: add flag to decode broken DCE BER encoding
+
+ * gen_locl.h: add flag to decode broken DCE BER encoding
+
+ * main.c: add flag to decode broken DCE BER encoding
+
diff --git a/third_party/heimdal/lib/asn1/MANUAL.md b/third_party/heimdal/lib/asn1/MANUAL.md
new file mode 100644
index 0000000..89c452a
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/MANUAL.md
@@ -0,0 +1,1287 @@
+# Introduction
+
+Heimdal is an implementation of PKIX and Kerberos. As such it must handle the
+use of [Abstract Syntax Notation One (ASN.1)](https://www.itu.int/rec/T-REC-X.680-X.693-202102-I/en)
+by those protocols. ASN.1 is a language for describing the schemata of network
+protocol messages. Associated with ASN.1 are the ASN.1 Encoding Rules (ERs)
+that specify how to encode such messages.
+
+In short:
+
+ - ASN.1 is just a _schema description language_
+
+ - ASN.1 Encoding Rules are specifications for encoding formats for values of
+ types described by ASN.1 schemas ("modules")
+
+Similar languages include:
+
+ - [DCE RPC's Interface Description Language (IDL)](https://pubs.opengroup.org/onlinepubs/9629399/chap4.htm#tagcjh_08)
+ - [Microsoft Interface Description Language (IDL)](https://docs.microsoft.com/en-us/windows/win32/midl/midl-start-page)
+ (MIDL is derived from the DCE RPC IDL)
+ - ONC RPC's eXternal Data Representation (XDR) [RFC4506](https://datatracker.ietf.org/doc/html/rfc4506)
+ - [XML Schema](https://en.wikipedia.org/wiki/XML_schema)
+ - Various JSON schema languages
+ - [Protocol Buffers](https://developers.google.com/protocol-buffers)
+ - and [many, many others](https://en.wikipedia.org/wiki/Comparison_of_data-serialization_formats)!
+ Many are not even listed there.
+
+Similar encoding rules include:
+
+ - DCE RPC's [NDR](https://pubs.opengroup.org/onlinepubs/9629399/chap14.htm)
+ - ONC RPC's [XDR](https://datatracker.ietf.org/doc/html/rfc4506)
+ - XML
+ - FastInfoSet
+ - JSON
+ - CBOR
+ - [Protocol Buffers](https://developers.google.com/protocol-buffers)
+ - [Flat Buffers](https://google.github.io/flatbuffers/)
+ - and [many, many others](https://en.wikipedia.org/wiki/Comparison_of_data-serialization_formats)!
+ Many are not even listed there.
+
+Many such languages are quite old. ASN.1 itself dates to the early 1980s, with
+the first specification published in 1984. XDR was first published in 1987.
+IDL's lineage dates back to sometime during the 1980s, via the Apollo Domain
+operating system.
+
+ASN.1 is standardized by the International Telecommunications Union (ITU-T),
+and has continued evolving over the years, with frequent updates.
+
+The two most useful and transcending features of ASN.1 are:
+
+ - the ability to formally express what some know as "open types", "typed
+ holes", or "references";
+
+ - the ability to add encoding rules over type, which for ASN.1 includes:
+
+ - binary, tag-length-value (TLV) encoding rules
+ - binary, non-TLV encoding rules
+ - textual encoding rules using XML and JSON
+ - an ad-hoc generic text-based ER called GSER
+
+ In principle ASN.1 can add encoding rules that would allow it to
+ interoperate with many others, such as: CBOR, protocol buffers, flat
+ buffers, NDR, and others.
+
+ Readers may recognize that some alternatives to ASN.1 have followed a
+ similar arc. For example, Protocol Buffers was originally a syntax and
+ encoding, and has become a syntax and set of various encodings (e.g., Flat
+ Buffers was added later). And XML has FastInfoSet as a binary encoding
+ alternative to XML's textual encoding.
+
+As well, ASN.1 has [high-quality, freely-available specifications](https://www.itu.int/rec/T-REC-X.680-X.693-202102-I/en).
+
+## ASN.1 Example
+
+For example, this is a `Certificate` as used in TLS and other protocols, taken
+from [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280):
+
+ ```ASN.1
+ Certificate ::= SEQUENCE {
+ tbsCertificate TBSCertificate,
+ signatureAlgorithm AlgorithmIdentifier,
+ signatureValue BIT STRING
+ }
+
+ TBSCertificate ::= SEQUENCE {
+ version [0] EXPLICIT Version DEFAULT v1,
+ serialNumber CertificateSerialNumber,
+ signature AlgorithmIdentifier,
+ issuer Name,
+ validity Validity,
+ subject Name,
+ subjectPublicKeyInfo SubjectPublicKeyInfo,
+ issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+ extensions [3] EXPLICIT Extensions OPTIONAL
+ }
+ ```
+
+and the same `Certificate` taken from a more modern version -from
+[RFC5912](https://datatracker.ietf.org/doc/html/rfc5912)- using newer features
+of ASN.1:
+
+ ```ASN.1
+ Certificate ::= SIGNED{TBSCertificate}
+
+ TBSCertificate ::= SEQUENCE {
+ version [0] Version DEFAULT v1,
+ serialNumber CertificateSerialNumber,
+ signature AlgorithmIdentifier{SIGNATURE-ALGORITHM,
+ {SignatureAlgorithms}},
+ issuer Name,
+ validity Validity,
+ subject Name,
+ subjectPublicKeyInfo SubjectPublicKeyInfo,
+ ... ,
+ [[2:
+ issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL
+ ]],
+ [[3:
+ extensions [3] Extensions{{CertExtensions}} OPTIONAL
+ ]], ...
+ }
+ ```
+
+As you can see, a `Certificate` is a structure containing a to-be-signed
+sub-structure, and a signature of that sub-structure, and the sub-structure
+has: a version number, a serial number, a signature algorithm, an issuer name,
+a validity period, a subject name, a public key for the subject name, "unique
+identifiers" for the issuer and subject entities, and "extensions".
+
+To understand more we'd have to look at the types of those fields of
+`TBSCertificate`, but for now we won't do that. The point here is to show that
+ASN.1 allows us to describe "types" of data in a way that resembles
+"structures", "records", or "classes" in various programming languages.
+
+To be sure, there are some "noisy" artifacts in the definition of
+`TBSCertificate` which mostly have to do with the original encoding rules for
+ASN.1. The original encoding rules for ASN.1 were tag-length-value (TLV)
+binary encodings, meaning that for every type, the encoding of a value of that
+type consisted of a _tag_, a _length_ of the value's encoding, and the _actual
+value's encoding_. Over time other encoding rules were added that do not
+require tags, such as the octet encoding rules (OER), but also JSON encoding
+rules (JER), XML encoding rules (XER), and others. There is almost no need for
+tagging directives like `[1] IMPLICIT` when using OER. But in existing
+protocols like PKIX and Kerberos that date back to the days when DER was king,
+tagging directives are unfortunately commonplace.
+
+## ASN.1 Crash Course
+
+This is not a specification. Readers should refer to the ITU-T's X.680 base
+specification for ASN.1's syntax.
+
+A schema is called a "module".
+
+A module looks like:
+
+```ASN.1
+-- This is a comment
+
+-- Here's the name of the module, here given as an "object identifier" or
+-- OID:
+PKIXAlgs-2009 { iso(1) identified-organization(3) dod(6)
+ internet(1) security(5) mechanisms(5) pkix(7) id-mod(0)
+ id-mod-pkix1-algorithms2008-02(56) }
+
+
+-- `DEFINITIONS` is a required keyword
+-- `EXPLICIT TAGS` will be explained later
+DEFINITIONS EXPLICIT TAGS ::=
+BEGIN
+-- list exported types, or `ALL`:
+EXPORTS ALL;
+-- import some types:
+IMPORTS PUBLIC-KEY, SIGNATURE-ALGORITHM, ... FROM AlgorithmInformation-2009
+ mda-sha224, mda-sha256, ... FROM PKIX1-PSS-OAEP-Algorithms-2009;
+
+-- type definitions follow:
+...
+
+END
+```
+
+Type names start with capital upper-case letters. Value names start with
+lower-case letters.
+
+Type definitions are of the form `TypeName ::= TypeDefinition`.
+
+Value (constant) definitions are of the form `valueName ::= TypeName <literal>`.
+
+There are some "universal" primitive types (e.g., string types, numeric types),
+and several "constructed" types (arrays, structures.
+
+Some useful primitive types include `BOOLEAN`, `INTEGER` and `UTF8String`.
+
+Structures are either `SEQUENCE { ... }` or `SET { ... }`. The "fields" of
+these are known as "members".
+
+Arrays are either `SEQUENCE OF SomeType` or `SET OF SomeType`.
+
+A `SEQUENCE`'s elements or members are ordered, while a `SET`'s are not. In
+practice this means that for _canonical_ encoding rules a `SET OF` type's
+values must be sorted, while a `SET { ... }` type's members need not be sorted
+at run-time, but are sorted by _tag_ at compile-time.
+
+Anonymous types are supported, such as `SET OF SET { a A, b B }` (which is a
+set of structures with an `a` field (member) of type `A` and a `b` member of
+type `B`).
+
+The members of structures can be `OPTIONAL` or have a `DEFAULT` value.
+
+There are also discriminated union types known as `CHOICE`s: `U ::= CHOICE { a
+A, b B, c C }` (in this case `U` is either an `A`, a `B`, or a `C`.
+
+Extensibility is supported. "Extensibility" means: the ability to add new
+members to structures, new alternatives to discriminated unions, etc. For
+example, `A ::= SEQUENCE { a0 A0, a1 A1, ... }` means that type `A` is a
+structure that has two fields and which may have more fields added in future
+revisions, therefore decoders _must_ be able to receive and decode encodings of
+extended versions of `A`, even encoders produced prior to the extensions being
+specified! (Normally a decoder "skips" extensions it doesn't know about, and
+the encoding rules need only make it possible to do so.)
+
+## TLV Encoding Rules
+
+The TLV encoding rules for ASN.1 are:
+
+ - Basic Encoding Rules (BER)
+ - Distinguished Encoding Rules (DER), a canonical subset of BER
+ - Canonical Encoding Rules (CER), another canonical subset of BER
+
+"Canonical" encoding rules yield just one way to encode any value of any type,
+while non-canonical rules possibly yield many ways to encode values of certain
+types. For example, JSON is not a canonical data encoding. A canonical form
+of JSON would have to specify what interstitial whitespace is allowed, a
+canonical representation of strings (which Unicode codepoints must be escaped
+and in what way, and which must not), and a canonical representation of decimal
+numbers.
+
+It is important to understand that originally ASN.1 came with TLV encoding
+rules, and some considerations around TLV encoding rules leaked into the
+language. For example, `A ::= SET { a0 [0] A0, a1 [1] A1 }` is a structure
+that has two members `a0` and `a1`, and when encoded those members will be
+tagged with a "context-specific" tags `0` and `1`, respectively.
+
+Tags only have to be specified when needed to disambiguate encodings.
+Ambiguities arise only in `CHOICE` types and sometimes in `SEQUENCE`/`SET`
+types that have `OPTIONAL`/`DEFAULT`ed members.
+
+In modern ASN.1 it is possible to specify that a module uses `AUTOMATIC`
+tagging so that one need never specify tags explicitly in order to fix
+ambiguities.
+
+Also, there are two types of tags: `IMPLICIT` and `EXPLICIT`. Implicit tags
+replace the tags that the tagged type would have otherwise. Explicit tags
+treat the encoding of a type's value (including its tag and length) as the
+value of the tagged type, thus yielding a tag-length-tag-length-value encoding
+-- a TLTLV encoding!
+
+Thus explicit tagging is more redundant and wasteful than implicit tagging.
+But implicit tagging loses metadata that is useful for tools that can decode
+TLV encodings without reference to the schema (module) corresponding to the
+types of values encoded.
+
+TLV encodings were probably never justified except by lack of tooling and
+belief that codecs for TLV ERs can be hand-coded. But TLV RTs exist, and
+because they are widely used, cannot be removed.
+
+## Other Encoding Rules
+
+The Packed Encoding Rules (PER) and Octet Encoding Rules (OER) are rules that
+resemble XDR, but with a 1-byte word size instead of 4-byte word size, and also
+with a 1-byte alignment instead of 4-byte alignment, yielding space-efficient
+encodings.
+
+Hand-coding XDR codecs is quite common and fairly easy. Hand-coding PER and
+OER is widely considered difficult because PER and OER try to be quite
+space-efficient.
+
+Hand-coding TLV codecs used to be considered easy, but really, never was.
+
+But no one should hand-code codecs for any encoding rules.
+
+Instead, one should use a compiler. This is true for ASN.1, and for all schema
+languages.
+
+## Encoding Rule Specific Syntactic Forms
+
+Some encoding rules require specific syntactic forms for some aspects of them.
+
+For example, the JER (JSON Encoding Rules) provide for syntax to select the use
+of JSON arrays vs. JSON objects for encoding structure types.
+
+For example, the TLV encoding rules provide for syntax for specifying
+alternative tags for disambiguation.
+
+## ASN.1 Syntax Specifications
+
+ - The base specification is ITU-T
+ [X.680](https://www.itu.int/rec/T-REC-X.680-202102-I/en).
+
+ - Additional syntax extensions include:
+
+ - [X.681 ASN.1 Information object specification](https://www.itu.int/rec/T-REC-X.681/en)
+ - [X.682 ASN.1 Constraint specification](https://www.itu.int/rec/T-REC-X.682/en)
+ - [X.682 ASN.1 Parameterization of ASN.1 specifications](https://www.itu.int/rec/T-REC-X.683/en)
+
+ Together these three specifications make the formal specification of open
+ types possible.
+
+## ASN.1 Encoding Rules Specifications
+
+ - The TLV Basic, Distinguished, and Canonical Encoding Rules (BER, DER, CER)
+ are described in ITU-T [X.690](https://www.itu.int/rec/T-REC-X.690/en).
+
+ - The more flat-buffers/XDR-like Packed Encoding Rules (PER) are described in
+ ITU-T [X.691](https://www.itu.int/rec/T-REC-X.691/en), and its successor,
+ the Octet Encoding Rules (OER) are described in
+ [X.696](https://www.itu.int/rec/T-REC-X.692/en).
+
+ - The XML Encoding Rules (XER) are described in ITU-T
+ [X.693](https://www.itu.int/rec/T-REC-X.693/en).
+
+ Related is the [X.694 Mapping W3C XML schema definitions into ASN.1](https://www.itu.int/rec/T-REC-X.694/en)
+
+ - The JSON Encoding Rules (JER) are described in ITU-T
+ [X.697](https://www.itu.int/rec/T-REC-X.697/en).
+
+ - The Generic String Encoding Rules are specified by IETF RFCs
+ [RFC3641](https://datatracker.ietf.org/doc/html/rfc3641),
+ [RFC3642](https://datatracker.ietf.org/doc/html/rfc3642),
+ [RFC4792](https://datatracker.ietf.org/doc/html/rfc4792).
+
+Additional ERs can be added.
+
+For example, XDR can clearly encode a very large subset of ASN.1, and with a
+few additional conventions, all of ASN.1.
+
+NDR too can clearly encode a very large subset of ASN.1, and with a few
+additional conventions, all of ASN. However, ASN.1 is not sufficiently rich a
+_syntax_ to express all of what NDR can express (think of NDR conformant and/or
+varying arrays), though with some extensions it could.
+
+## Commentary
+
+The text in this section is the personal opinion of the author(s).
+
+ - ASN.1 gets a bad rap because BER/DER/CER are terrible encoding rules, as are
+ all TLV encoding rules.
+
+ The BER family of encoding rules is a disaster, yes, but ASN.1 itself is
+ not. On the contrary, ASN.1 is quite rich in features and semantics -as
+ rich as any competitor- while also being very easy to write and understand
+ _as a syntax_.
+
+ - ASN.1 also gets a bad rap because its full syntax is not context-free, and
+ so parsing it can be tricky.
+
+ And yet the Heimdal ASN.1 compiler manages, using LALR(1) `yacc`/`bison`/`byacc`
+ parser-generators. For the subset of ASN.1 that this compiler handles,
+ there are no ambiguities. However, we understand that eventually we will
+ need run into ambiguities.
+
+ For example, `ValueSet` and `ObjectSet` are ambiguous. X.680 says:
+
+ ```
+ ValueSet ::= "{" ElementSetSpecs "}"
+ ```
+
+ while X.681 says:
+
+ ```
+ ObjectSet ::= "{" ObjectSetSpec "}"
+ ```
+
+ and the set members can be just the symbolic names of members, in which case
+ there's no grammatical difference between those two productions. These then
+ cause a conflict in the `FieldSetting` production, which is used in the
+ `ObjectDefn` production, which is used in defining an object (which is to be
+ referenced from some `ObjectSet` or `FieldSetting`).
+
+ This particular conflict can be resolved by one of:
+
+ - limiting the power of object sets by disallowing recursion (object sets
+ containing objects that have field settings that are object sets ...),
+
+ - or by introducing additional required and disambiguating syntactic
+ elements that preclude full compliance with ASN.1,
+
+ - or by simply using the same production and type internally to handle
+ both, the `ValueSet` and `ObjectSet` productions and then internally
+ resolving the actual type as late as possible by either inspecting the
+ types of the set members or by inspecting the expected kind of field that
+ the `ValueSet`-or-`ObjectSet` is setting.
+
+ Clearly, only the last of these is satisfying, but it is more work for the
+ compiler developer.
+
+ - TLV encodings are bad because they yield unnecessary redundance in
+ encodings. This is space-inefficient, but also a source of bugs in
+ hand-coded codecs for TLV encodings.
+
+ EXPLICIT tagging makes this worse by making the encoding a TLTLV encoding
+ (tag length tag length value). (The inner TLV is the V for the outer TL.)
+
+ - TLV encodings are often described as "self-describing" because one can
+ usually write a `dumpasn1` style of tool that attempts to decode a TLV
+ encoding of a value without reference to the value's type definition.
+
+ The use of `IMPLICIT` tagging with BER/DER/CER makes schema-less `dumpasn1`
+ style tools harder to use, as some type information is lost. E.g., a
+ primitive type implicitly tagged with a context tag results in a TLV
+ encoding where -without reference to the schema- the tag denotes no
+ information about the type of the value encoded. The user is left to figure
+ out what kind of data that is and to then decode it by hand. For
+ constructed types (arrays and structures), implicit tagging does not really
+ lose any metadata about the type that wasn't already lost by BER/DER/CER, so
+ there is no great loss there.
+
+ However, Heimdal's ASN.1 compiler includes an `asn1_print(1)` utility that
+ can print DER-encoded values in much more detail than a schema-less
+ `dumpasn1` style of tool can. This is because `asn1_print(1)` includes
+ a number of compiled ASN.1 modules, and it can be extended to include more.
+
+ - There is some merit to BER, however. Specifically, an appropriate use of
+ indeterminate length encoding with BER can yield on-line encoding. Think of
+ encoding streams of indeterminate size -- this cannot be done with DER or
+ Flat Buffers, or most encodings, though it can be done with some encodings,
+ such as BER and NDR (NDR has "pipes" for this).
+
+ Some clues are needed in order to produce an codec that can handle such
+ on-line behavior. In IDL/NDR that clue comes from the "pipe" type. In
+ ASN.1 there is no such clue and it would have to be provided separately to
+ the ASN.1 compiler (e.g., as a command-line option).
+
+ - Protocol Buffers is a TLV encoding. There was no need to make it a TLV
+ encoding.
+
+ Public opinion seems to prefer Flat Buffers now, which is not a TLV encoding
+ and which is more comparable to XDR/NDR/PER/OER.
+
+# Heimdal ASN.1 Compiler
+
+The Heimdal ASN.1 compiler and library implement a very large subset of the
+ASN.1 syntax, meanign large parts of X.680, X.681, X.682, and X.683.
+
+The compiler currently emits:
+
+ - a JSON representation of ASN.1 modules
+ - C types corresponding to ASN.1 modules' types
+ - C functions for DER (and some BER) codecs for ASN.1 modules' types
+
+We vaguely hope to eventually move to using the JSON representation of ASN.1
+modules to do code generation in a programming language like `jq` rather than
+in C. The idea there is to make it much easier to target other programming
+languages than C, especially Rust, so that we can start moving Heimdal to Rust
+(first after this would be `lib/hx509`, then `lib/krb5`, then `lib/hdb`, then
+`lib/gssapi`, then `kdc/`).
+
+The compiler has two "backends":
+
+ - C code generation
+ - "template" (byte-code) generation and interpretation
+
+## Features and Limitations
+
+Supported encoding rules:
+
+ - DER
+ - BER decoding (but not encoding)
+
+As well, the Heimdal ASN.1 compiler can render values as JSON using an ad-hoc
+metaschema that is not quite JER-compliant. A sample rendering of a complex
+PKIX `Certificate` with all typed holes automatically decoded is shown in
+[README.md#features](README.md#features).
+
+The Heimdal ASN.1 compiler supports open types via X.681/X.682/X.683 syntax.
+Specifically: (when using the template backend) the generated codecs can
+automatically and recursively decode and encode through "typed holes".
+
+An "open type", also known as "typed holes" or "references", is a part of a
+structure that can contain the encoding of a value of some arbitrary data type,
+with a hint of that value's type expressed in some way such as: via an "object
+identifier", or an integer, or even a string (e.g., like a URN).
+
+Open types are widely used as a form of extensibility.
+
+Historically, open types were never documented formally, but with natural
+language (e.g., English) meant only for humans to understand. Documenting open
+types with formal syntax allows compilers to support them specially.
+
+See the the [`asn1_compile(1)` manual page](#Manual-Page-for-asn1_compile)
+below and [README.md#features](README.md#features), for more details on
+limitations. Excerpt from the manual page:
+
+```
+The Information Object System support includes automatic codec support
+for encoding and decoding through “open types” which are also known as
+“typed holes”. See RFC5912 for examples of how to use the ASN.1 Infor-
+mation Object System via X.681/X.682/X.683 annotations. See the com-
+piler's README files for more information on ASN.1 Information Object
+System support.
+
+Extensions specific to Heimdal are generally not syntactic in nature but
+rather command-line options to this program. For example, one can use
+command-line options to:
+ • enable decoding of BER-encoded values;
+ • enable RFC1510-style handling of ‘BIT STRING’ types;
+ • enable saving of as-received encodings of specific types
+ for the purpose of signature validation;
+ • generate add/remove utility functions for array types;
+ • decorate generated ‘struct’ types with fields that are nei-
+ ther encoded nor decoded;
+etc.
+
+ASN.1 x.680 features supported:
+ • most primitive types (except BMPString and REAL);
+ • all constructed types, including SET and SET OF;
+ • explicit and implicit tagging.
+
+Size and range constraints on the ‘INTEGER’ type cause the compiler to
+generate appropriate C types such as ‘int’, ‘unsigned int’, ‘int64_t’,
+‘uint64_t’. Unconstrained ‘INTEGER’ is treated as ‘heim_integer’, which
+represents an integer of arbitrary size.
+
+Caveats and ASN.1 x.680 features not supported:
+ • JSON encoding support is not quite X.697 (JER) compatible.
+ Its JSON schema is subject to change without notice.
+ • Control over C types generated is very limited, mainly only
+ for integer types.
+ • When using the template backend, `SET { .. }` types are
+ currently not sorted by tag as they should be, but if the
+ module author sorts them by hand then correct DER will be
+ produced.
+ • ‘AUTOMATIC TAGS’ is not supported.
+ • The REAL type is not supported.
+ • The EmbeddedPDV type is not supported.
+ • The BMPString type is not supported.
+ • The IA5String is not properly supported, as it's essen‐
+ tially treated as a UTF8String with a different tag.
+ • All supported non-octet strings are treated as like the
+ UTF8String type.
+ • Only types can be imported into ASN.1 modules at this time.
+ • Only simple value syntax is supported. Constructed value
+ syntax (i.e., values of SET, SEQUENCE, SET OF, and SEQUENCE
+ OF types), is not supported. Values of `CHOICE` types are
+ also not supported.
+```
+
+## Easy-to-Use C Types
+
+The Heimdal ASN.1 compiler generates easy-to-use C types for ASN.1 types.
+
+Unconstrained `INTEGER` becomes `heim_integer` -- a large integer type.
+
+Constrained `INTEGER` types become `int`, `unsigned int`, `int64_t`, or
+`uint64_t`.
+
+String types generally become `char *` (C strings, i.e., NUL-terminated) or
+`heim_octet_string` (a counted byte string type).
+
+`SET` and `SEQUENCE` types become `struct` types.
+
+`SET OF SomeType` and `SEQUENCE OF SomeType` types become `struct` types with a
+`size_t len` field counting the number of elements of the array, and a pointer
+to `len` consecutive elements of the `SomeType` type.
+
+`CHOICE` types become a `struct` type with an `enum` discriminant and a
+`union`.
+
+Type names have hyphens turned to underscores.
+
+Every ASN.1 gets a `typedef`.
+
+`OPTIONAL` members of `SET`s and `SEQUENCE`s become pointer types (`NULL`
+values mean "absent", while non-`NULL` values mean "present").
+
+Tags are of no consequence to the C types generated.
+
+Types definitions to be topographically sorted because of the need to have
+forward declarations.
+
+Forward `typedef` declarations are emmitted.
+
+Circular type dependencies are allowed provided that `OPTIONAL` members are
+used for enough circular references so as to avoid creating types whose values
+have infinite size! (Circular type dependencies can be used to build linked
+lists, though that is a bit of a silly trick when one can use arrays instead,
+though in principle this could be used to do on-line encoding and decoding of
+arbitrarily large streams of objects. See the [commentary](#Commentary)
+section.)
+
+Thus `Certificate` becomes:
+
+```C
+typedef struct TBSCertificate {
+ heim_octet_string _save; /* see below! */
+ Version *version;
+ CertificateSerialNumber serialNumber;
+ AlgorithmIdentifier signature;
+ Name issuer;
+ Validity validity;
+ Name subject;
+ SubjectPublicKeyInfo subjectPublicKeyInfo;
+ heim_bit_string *issuerUniqueID;
+ heim_bit_string *subjectUniqueID;
+ Extensions *extensions;
+} TBSCertificate;
+
+typedef struct Certificate {
+ TBSCertificate tbsCertificate;
+ AlgorithmIdentifier signatureAlgorithm;
+ heim_bit_string signatureValue;
+} Certificate;
+```
+
+The `_save` field in `TBSCertificate` is generated when the compiler is invoked
+with `--preserve-binary=TBSCertificate`, and the decoder will place the
+original encoding of the value of a `TBSCertificate` in the decoded
+`TBSCertificate`'s `_save` field. This is very useful for signature
+validation: the application need not attempt to re-encode a `TBSCertificate` in
+order to validate its signature from the containing `Certificate`!
+
+Let's compare to the `Certificate` as defined in ASN.1:
+
+```ASN.1
+ Certificate ::= SEQUENCE {
+ tbsCertificate TBSCertificate,
+ signatureAlgorithm AlgorithmIdentifier,
+ signatureValue BIT STRING
+ }
+
+ TBSCertificate ::= SEQUENCE {
+ version [0] EXPLICIT Version DEFAULT v1,
+ serialNumber CertificateSerialNumber,
+ signature AlgorithmIdentifier,
+ issuer Name,
+ validity Validity,
+ subject Name,
+ subjectPublicKeyInfo SubjectPublicKeyInfo,
+ issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+ extensions [3] EXPLICIT Extensions OPTIONAL
+ }
+```
+
+The conversion from ASN.1 to C is quite mechanical and natural. That's what
+code-generators do, of course, so it's not surprising. But you can see that
+`Certificate` in ASN.1 and C differs only in:
+
+ - in C `SEQUENCE { }` becomes `struct { }`
+ - in C the type name comes first
+ - in C we drop the tagging directives (e.g., `[0] EXPLICIT`)
+ - `DEFAULT` and `OPTIONAL` become pointers
+ - in C we use `typedef`s to make the type names usable without having to add
+ `struct`
+
+## Circular Type Dependencies
+
+As noted above, circular type dependencies are supported.
+
+Here's a toy example from [XDR](https://datatracker.ietf.org/doc/html/rfc4506)
+-- a linked list:
+
+```XDR
+struct stringentry {
+ string item<>;
+ stringentry *next;
+};
+
+typedef stringentry *stringlist;
+```
+
+Here is the same example in ASN.1:
+
+```ASN.1
+Stringentry ::= SEQUENCE {
+ item UTF8String,
+ next Stringentry OPTIONAL
+}
+```
+
+which compiles to:
+
+```C
+typedef struct Stringentry Stringentry;
+struct Stringentry {
+ char *item;
+ Stringentry *next;
+};
+```
+
+This illustrates that `OPTIONAL` members in ASN.1 are like pointers in XDR.
+
+Making the `next` member not `OPTIONAL` would cause `Stringentry` to be
+infinitely large, and there is no way to declare the equivalent in C anyways
+(`struct foo { int a; struct foo b; };` will not compile in C).
+
+Mutual circular references are allowed too. In the following example `A`
+refers to `B` and `B` refers to `A`, but as long as one (or both) of those
+references is `OPTIONAL`, then it will be allowed:
+
+```ASN1
+A ::= SEQUENCE { name UTF8String, b B }
+B ::= SEQUENCE { name UTF8String, a A OPTIONAL }
+```
+
+```ASN1
+A ::= SEQUENCE { name UTF8String, b B OPTIONAL }
+B ::= SEQUENCE { name UTF8String, a A }
+```
+
+```ASN1
+A ::= SEQUENCE { name UTF8String, b B OPTIONAL }
+B ::= SEQUENCE { name UTF8String, a A OPTIONAL }
+```
+
+In the above example values of types `A` and `B` together form a linked list.
+
+Whereas this is broken and will not compile:
+
+```ASN1
+A ::= SEQUENCE { name UTF8String, b B }
+B ::= SEQUENCE { name UTF8String, a A } -- infinite size!
+```
+
+## Generated APIs For Any Given Type T
+
+The C functions generated for ASN.1 types are all of the same form, for any
+type `T`:
+
+```C
+int decode_T(const unsigned char *, size_t, TBSCertificate *, size_t *);
+int encode_T(unsigned char *, size_t, const TBSCertificate *, size_t *);
+size_t length_T(const TBSCertificate *);
+int copy_T(const TBSCertificate *, TBSCertificate *);
+void free_T(TBSCertificate *);
+char * print_T(const TBSCertificate *, int);
+```
+
+The `decode_T()` functions take a pointer to the encoded data, its length in
+bytes, a pointer to a C object of type `T` to decode into, and a pointer into
+which the number of bytes consumed will be written.
+
+The `length_T()` functions take a pointer to a C object of type `T` and return
+the number of bytes its encoding would need.
+
+The `encode_T()` functions take a pointer to enough bytes to encode the value,
+the number of bytes found there, a pointer to a C object of type `T` whose
+value to encode, and a pointer into which the number of bytes output will be
+written.
+
+> NOTE WELL: The first argument to `encode_T()` functions must point to the
+> last byte in the buffer into which the encoder will encode the value. This
+> is because the encoder encodes from the end towards the beginning.
+
+The `print_T()` functions encode the value of a C object of type `T` in JSON
+(though not in JER-compliant JSON). A sample printing of a complex PKIX
+`Certificate` can be seen in [README.md#features](README.md#features).
+
+The `copy_T()` functions take a pointer to a source C object of type `T` whose
+value they then copy to the destination C object of the same type. The copy
+constructor is equivalent to encoding the source value and decoding it onto the
+destination.
+
+The `free_T()` functions take a pointer to a C object of type `T` whose value's
+memory resources will be released. Note that the C object _itself_ is not
+freed, only its _content_.
+
+See [sample usage](#Using-the-Generated-APIs).
+
+These functions are all recursive.
+
+> NOTE WELL: These functions use the standard C memory allocator.
+> When using the Windows statically-linked C run-time, you must link with
+> `LIBASN1.LIB` to avoid possibly freeing memory allocated by a different
+> allocator.
+
+## Error Handling
+
+All codec functions that return errors return them as `int`.
+
+Error values are:
+
+ - system error codes (use `strerror()` to display them)
+
+or
+
+ - `ASN1_BAD_TIMEFORMAT`
+ - `ASN1_MISSING_FIELD`
+ - `ASN1_MISPLACED_FIELD`
+ - `ASN1_TYPE_MISMATCH`
+ - `ASN1_OVERFLOW`
+ - `ASN1_OVERRUN`
+ - `ASN1_BAD_ID`
+ - `ASN1_BAD_LENGTH`
+ - `ASN1_BAD_FORMAT`
+ - `ASN1_PARSE_ERROR`
+ - `ASN1_EXTRA_DATA`
+ - `ASN1_BAD_CHARACTER`
+ - `ASN1_MIN_CONSTRAINT`
+ - `ASN1_MAX_CONSTRAINT`
+ - `ASN1_EXACT_CONSTRAINT`
+ - `ASN1_INDEF_OVERRUN`
+ - `ASN1_INDEF_UNDERRUN`
+ - `ASN1_GOT_BER`
+ - `ASN1_INDEF_EXTRA_DATA`
+
+You can use the `com_err` library to display these errors as strings:
+
+```C
+ struct et_list *etl = NULL;
+ initialize_asn1_error_table_r(&etl);
+ int ret;
+
+ ...
+
+ ret = decode_T(...);
+ if (ret) {
+ const char *error_message;
+
+ if ((error_message = com_right(etl, ret)) == NULL)
+ error_message = strerror(ret);
+
+ fprintf(stderr, "Failed to decode T: %s\n",
+ error_message ? error_message : "<unknown error>");
+ }
+```
+
+## Using the Generated APIs
+
+Value construction is as usual in C. Use the standard C allocator for
+allocating values of `OPTIONAL` fields.
+
+Value destruction is done with the `free_T()` destructors.
+
+Decoding is just:
+
+```C
+ Certificate c;
+ size_t sz;
+ int ret;
+
+ ret = decode_Certificate(pointer_to_encoded_bytes,
+ number_of_encoded_bytes,
+ &c, &sz);
+ if (ret == 0) {
+ if (sz != number_of_encoded_bytes)
+ warnx("Extra bytes after Certificate!");
+ } else {
+ warnx("Failed to decode certificate!");
+ return ret;
+ }
+
+ /* Now do stuff with the Certificate */
+ ...
+
+ /* Now release the memory */
+ free_Certificate(&c);
+```
+
+Encoding involves calling the `length_T()` function to compute the number of
+bytes needed for the encoding, then allocating that many bytes, then calling
+`encode_T()` to encode into that memory. A convenience macro,
+`ASN1_MALLOC_ENCODE()`, does all three operations:
+
+```C
+ Certificate c;
+ size_t num_bytes, sz;
+ char *bytes = NULL;
+ int ret;
+
+ /* Build a `Certificate` in `c` */
+ ...
+
+ /* Encode `c` */
+ ASN1_MALLOC_ENCODE(Certificate, bytes, num_bytes, &c, sz, ret);
+ if (ret)
+ errx(1, "Out of memory encoding a Certificate");
+
+ /* This check isn't really needed -- it never fails */
+ if (num_bytes != sz)
+ errx(1, "ASN.1 encoder internal error");
+
+ /* Send the `num_bytes` in `bytes` */
+ ...
+
+ /* Free the memory allocated by `ASN1_MALLOC_ENCODE()` */
+ free(bytes);
+```
+
+or, the same code w/o the `ASN1_MALLOC_ENCODE()` macro:
+
+```C
+ Certificate c;
+ size_t num_bytes, sz;
+ char *bytes = NULL;
+ int ret;
+
+ /* Build a `Certificate` in `c` */
+ ...
+
+ /* Encode `c` */
+ num_bytes = length_Certificate(&c);
+ bytes = malloc(num_bytes);
+ if (bytes == NULL)
+ errx(1, "Out of memory");
+
+ /*
+ * Note that the memory to encode into, passed to encode_Certificate()
+ * must be a pointer to the _last_ byte of that memory, not the first!
+ */
+ ret = encode_Certificate(bytes + num_bytes - 1, num_bytes,
+ &c, &sz);
+ if (ret)
+ errx(1, "Out of memory encoding a Certificate");
+
+ /* This check isn't really needed -- it never fails */
+ if (num_bytes != sz)
+ errx(1, "ASN.1 encoder internal error");
+
+ /* Send the `num_bytes` in `bytes` */
+ ...
+
+ /* Free the memory allocated by `ASN1_MALLOC_ENCODE()` */
+ free(bytes);
+```
+
+## Open Types
+
+The handling of X.681/X.682/X.683 syntax for open types is described at length
+in [README-X681.md](README-X681.md).
+
+## Command-line Usage
+
+The compiler takes an ASN.1 module file name and outputs a C header and C
+source files, as well as various other metadata files:
+
+ - `<module>_asn1.h`
+
+ This file defines all the exported types from the given ASN.1 module as C
+ types.
+
+ - `<module>_asn1-priv.h`
+
+ This file defines all the non-exported types from the given ASN.1 module as
+ C types.
+
+ - `<module>_asn1_files`
+
+ This file is needed because the default is to place the code for each type
+ in a separate C source file, which can help improve the performance of
+ builds by making it easier to parallelize the building of the ASN.1 module.
+
+ - `asn1_<Type>.c` or `asn1_<module>_asn1.c`
+
+ If `--one-code-file` is used, then the implementation of the module will be
+ in a file named `asn1_<module>_asn1.c`, otherwise the implementation of each
+ type in the module will be in `asn1_<Type>.c`.
+
+ - `<module>_asn1.json`
+
+ This file contains a JSON description of the module (the schema for this
+ file is ad-hoc and subject to change w/o notice).
+
+ - `<module>_asn1_oids.c`
+
+ This file is meant to be `#include`d, and contains just calls to a
+ `DEFINE_OID_WITH_NAME(sym)` macro that the user must define, where `sym` is
+ the suffix of the name of a variable of type `heim_oid`. The full name of
+ the variable is `asn1_oid_ ## sym`.
+
+ - `<module>_asn1_syms.c`
+
+ This file is meant to be `#include`d, and contains just calls to these
+ macros that the user must define:
+
+ - `ASN1_SYM_INTVAL(name, genname, sym, num)`
+ - `ASN1_SYM_OID(name, genname, sym)`
+ - `ASN1_SYM_TYPE(name, genname, sym)`
+
+ where `name` is the C string literal name of the value or type as it appears
+ in the ASN.1 module, `genname` is the C string literal name of the value or
+ type as generated (e.g., with hyphens replaced by underscores), `sym` is the
+ symbol or symbol suffix (see above0, and `num` is the numeric value of the
+ integer value.
+
+Control over the C types used for ASN.1 `INTEGER` types is done by ASN.1 usage
+convention:
+
+ - unconstrained `INTEGER` types, or `INTEGER` types where only the minimum, or
+ only the maximum value is specified generate `heim_integer`
+
+ - constrained `INTEGER` types whose minimum and maximum fit in `unsigned`'s
+ range generate `unsigned`
+
+ - constrained `INTEGER` types whose minimum and maximum fit in `int`'s
+ range generate `int`
+
+ - constrained `INTEGER` types whose minimum and maximum fit in `uin64_t`'s
+ range generate `uin64_t`
+
+ - constrained `INTEGER` types whose minimum and maximum fit in `in64_t`'s
+ range generate `in64_t`
+
+ - `INTEGER` types with named members generate a C `struct` with `unsigned int`
+ bit-field members
+
+ - all other `INTEGER` types generate `heim_integer`
+
+Various code generation options are provided as command-line options or as
+ASN.1 usage conventions:
+
+ - `--type-file=C-HEADER-FILE` -- generate an `#include` directive to include
+ that header for some useful base types (within Heimdal we use `krb5-types.h`
+ as that header)
+
+ - `--template` -- use the "template" (byte-coded) backend
+
+ - `--one-code-file` -- causes all the code generated to be placed in one C
+ source file (mutually exclusive with `--template`)
+
+ - `--support-ber` -- accept non-DER BER when decoding
+
+ - `--preserve-binary=TYPE` -- add a `_save` field to the C struct type for the
+ ASN.1 `TYPE` where the decoder will save the original encoding of the value
+ of `TYPE` it decodes (useful for cryptographic signature verification!)
+
+ - `--sequence=TYPE` -- generate `add_TYPE()` and `remove_TYPE()` utility
+ functions (`TYPE` must be a `SET OF` or `SEQUENCE OF` type)
+
+ - `--decorate=DECORATION` -- add fields to generated C struct types as
+ described in the `DECORATION` (see the
+ [manual page](#Manual-Page-for-asn1_compile) below)
+
+ Decoration fields are never encoded or decoded. They are meant to be used
+ for, e.g., application state keeping.
+
+ - `--no-parse-units` -- normally the compiler generates code to use the
+ Heimdal `libroken` "units" utility for displaying bit fields; this option
+ disables this
+
+See the [manual page for `asn1_compile(1)`](#Manual-Page-for-asn1_compile) for
+a full listing of command-line options.
+
+### Manual Page for `asn1_compile(1)`
+
+```
+ASN1_COMPILE(1) BSD General Commands Manual ASN1_COMPILE(1)
+
+NAME
+ asn1_compile — compile ASN.1 modules
+
+SYNOPSIS
+ asn1_compile [--template] [--prefix-enum] [--enum-prefix=PREFIX]
+ [--encode-rfc1510-bit-string] [--decode-dce-ber]
+ [--support-ber] [--preserve-binary=TYPE] [--sequence=TYPE]
+ [--decorate=DECORATION] [--one-code-file] [--gen-name=NAME]
+ [--option-file=FILE] [--original-order] [--no-parse-units]
+ [--type-file=C-HEADER-FILE] [--version] [--help]
+ [FILE.asn1 [NAME]]
+
+DESCRIPTION
+ asn1_compile compiles an ASN.1 module into C source code and header
+ files.
+
+ A fairly large subset of ASN.1 as specified in X.680, and the ASN.1 In‐
+ formation Object System as specified in X.681, X.682, and X.683 is sup‐
+ ported, with support for the Distinguished Encoding Rules (DER), partial
+ Basic Encoding Rules (BER) support, and experimental JSON support (encod‐
+ ing only at this time).
+
+ See the compiler's README files for details about the C code and inter‐
+ faces it generates.
+
+ The Information Object System support includes automatic codec support
+ for encoding and decoding through “open types” which are also known as
+ “typed holes”. See RFC 5912 for examples of how to use the ASN.1 Infor‐
+ mation Object System via X.681/X.682/X.683 annotations. See the com‐
+ piler's README files for more information on ASN.1 Information Object
+ System support.
+
+ Extensions specific to Heimdal are generally not syntactic in nature but
+ rather command-line options to this program. For example, one can use
+ command-line options to:
+ • enable decoding of BER-encoded values;
+ • enable RFC1510-style handling of ‘BIT STRING’ types;
+ • enable saving of as-received encodings of specific types
+ for the purpose of signature validation;
+ • generate add/remove utility functions for array types;
+ • decorate generated ‘struct’ types with fields that are nei‐
+ ther encoded nor decoded;
+ etc.
+
+ ASN.1 x.680 features supported:
+ • most primitive types (except BMPString and REAL);
+ • all constructed types, including SET and SET OF;
+ • explicit and implicit tagging.
+
+ Size and range constraints on the ‘INTEGER’ type cause the compiler to
+ generate appropriate C types such as ‘int’, ‘unsigned int’, ‘int64_t’,
+ ‘uint64_t’. Unconstrained ‘INTEGER’ is treated as ‘heim_integer’, which
+ represents an integer of arbitrary size.
+
+ Caveats and ASN.1 x.680 features not supported:
+ • JSON encoding support is not quite X.697 (JER) compatible.
+ Its JSON schema is subject to change without notice.
+ • Control over C types generated is very limited, mainly only
+ for integer types.
+ • When using the template backend, `SET { .. }` types are
+ currently not sorted by tag as they should be, but if the
+ module author sorts them by hand then correct DER will be
+ produced.
+ • ‘AUTOMATIC TAGS’ is not supported.
+ • The REAL type is not supported.
+ • The EmbeddedPDV type is not supported.
+ • The BMPString type is not supported.
+ • The IA5String is not properly supported, as it's essen‐
+ tially treated as a UTF8String with a different tag.
+ • All supported non-octet strings are treated as like the
+ UTF8String type.
+ • Only types can be imported into ASN.1 modules at this time.
+ • Only simple value syntax is supported. Constructed value
+ syntax (i.e., values of SET, SEQUENCE, SET OF, and SEQUENCE
+ OF types), is not supported. Values of `CHOICE` types are
+ also not supported.
+
+ Options supported:
+
+ --template
+ Use the “template” backend instead of the “codegen” backend
+ (which is the default backend).
+
+ The template backend generates “templates” which are akin to
+ bytecode, and which are interpreted at run-time.
+
+ The codegen backend generates C code for all functions directly,
+ with no template interpretation.
+
+ The template backend scales better than the codegen backend be‐
+ cause as we add support for more encoding rules and more opera‐
+ tions (we may add value comparators) the templates stay mostly
+ the same, thus scaling linearly with size of module. Whereas the
+ codegen backend scales linear with the product of module size and
+ number of encoding rules supported.
+
+ --prefix-enum
+ This option should be removed because ENUMERATED types should al‐
+ ways have their labels prefixed.
+
+ --enum-prefix=PREFIX
+ This option should be removed because ENUMERATED types should al‐
+ ways have their labels prefixed.
+
+ --encode-rfc1510-bit-string
+ Use RFC1510, non-standard handling of “BIT STRING” types.
+
+ --decode-dce-ber
+
+ --support-ber
+
+ --preserve-binary=TYPE
+ Generate a field named ‘_save’ in the C struct generated for the
+ named TYPE. This field is used to preserve the original encoding
+ of the value of the TYPE.
+
+ This is useful for cryptographic applications so that they can
+ check signatures of encoded values as-received without having to
+ re-encode those values.
+
+ For example, the TBSCertificate type should have values preserved
+ so that Certificate validation can check the signatureValue over
+ the tbsCertificate's value as-received.
+
+ The alternative of encoding a value to check a signature of it is
+ brittle. For types where non-canonical encodings (such as BER)
+ are allowed, this alternative is bound to fail. Thus the point
+ of this option.
+
+ --sequence=TYPE
+ Generate add/remove functions for the named ASN.1 TYPE which must
+ be a ‘SET OF’ or ‘SEQUENCE OF’ type.
+
+ --decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?]
+ Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
+ or CHOICE type named ASN1-TYPE a “hidden” field named fname of
+ the given ASN.1 type FIELD-ASN1-TYPE, but do not encode or decode
+ it. If the fname ends in a question mark, then treat the field
+ as OPTIONAL.
+
+ This is useful for adding fields to existing types that can be
+ used for internal bookkeeping but which do not affect interoper‐
+ ability because they are neither encoded nor decoded. For exam‐
+ ple, one might decorate a request type with state needed during
+ processing of the request.
+
+ --decorate=ASN1-TYPE:void*:fname
+ Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
+ or CHOICE type named ASN1-TYPE a “hidden” field named fname of
+ type ‘void *’ (but do not encode or decode it.
+
+ The destructor and copy constructor functions generated by this
+ compiler for ASN1-TYPE will set this field to the ‘NULL’ pointer.
+
+ --decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header
+ Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
+ or CHOICE type named ASN1-TYPE a “hidden” field named fname of
+ the given external C type FIELD-C-TYPE, declared in the given
+ header but do not encode or decode this field. If the fname ends
+ in a question mark, then treat the field as OPTIONAL.
+
+ The header must include double quotes or angle brackets. The
+ copyfn must be the name of a copy constructor function that takes
+ a pointer to a source value of the type, and a pointer to a des‐
+ tination value of the type, in that order, and which returns zero
+ on success or else a system error code on failure. The freefn
+ must be the name of a destructor function that takes a pointer to
+ a value of the type and which releases resources referenced by
+ that value, but does not free the value itself (the run-time al‐
+ locates this value as needed from the C heap). The freefn should
+ also reset the value to a pristine state (such as all zeros).
+
+ If the copyfn and freefn are empty strings, then the decoration
+ field will neither be copied nor freed by the functions generated
+ for the TYPE.
+
+ --one-code-file
+ Generate a single source code file. Otherwise a separate code
+ file will be generated for every type.
+
+ --gen-name=NAME
+ Use NAME to form the names of the files generated.
+
+ --option-file=FILE
+ Take additional command-line options from FILE.
+
+ --original-order
+ Attempt to preserve the original order of type definition in the
+ ASN.1 module. By default the compiler generates types in a topo‐
+ logical sort order.
+
+ --no-parse-units
+ Do not generate to-int / from-int functions for enumeration
+ types.
+
+ --type-file=C-HEADER-FILE
+ Generate an include of the named header file that might be needed
+ for common type defintions.
+
+ --version
+
+ --help
+
+NOTES
+ Currently only the template backend supports automatic encoding and de‐
+ coding of open types via the ASN.1 Information Object System and
+ X.681/X.682/X.683 annotations.
+
+HEIMDAL February 22, 2021 HEIMDAL
+```
+
+# Future Directions
+
+The Heimdal ASN.1 compiler is focused on PKIX and Kerberos, and is almost
+feature-complete for dealing with those. It could use additional support for
+X.681/X.682/X.683 elements that would allow the compiler to understand
+`Certificate ::= SIGNED{TBSCertificate}`, particularly the ability to
+automatically validate cryptographic algorithm parameters. However, this is
+not that important.
+
+Another feature that might be nice is the ability of callers to specify smaller
+information object sets when decoding values of types like `Certificate`,
+mainly to avoid spending CPU cycles and memory allocations on decoding types in
+typed holes that are not of interest to the application.
+
+For testing purposes, a JSON reader to go with the JSON printer might be nice,
+and anyways, would make for a generally useful tool.
+
+Another feature that would be nice would to automatically generate SQL and LDAP
+code for HDB based on `lib/hdb/hdb.asn1` (with certain usage conventions and/or
+compiler command-line options to make it possible to map schemas usefully).
+
+For the `hxtool` command, it would be nice if the user could input arbitrary
+certificate extensions and `subjectAlternativeName` (SAN) values in JSON + an
+ASN.1 module and type reference that `hxtool` could then parse and encode using
+the ASN.1 compiler and library. Currently the `hx509` library and its `hxtool`
+command must be taught about every SAN type.
diff --git a/third_party/heimdal/lib/asn1/Makefile.am b/third_party/heimdal/lib/asn1/Makefile.am
new file mode 100644
index 0000000..e5af4ba
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/Makefile.am
@@ -0,0 +1,567 @@
+# $Id$
+
+include $(top_srcdir)/Makefile.am.common
+
+WFLAGS += $(WFLAGS_ENUM_CONV)
+
+AM_YFLAGS = -d -o asn1parse.c -t
+
+AM_CPPFLAGS += $(ROKEN_RENAME) -I$(top_builddir)/include -I$(top_srcdir)/lib/base
+
+man_MANS = asn1_print.1 asn1_compile.1
+
+lib_LTLIBRARIES = libasn1.la libasn1template.la
+libasn1_la_LDFLAGS = -version-info 8:0:0
+libasn1template_la_LDFLAGS = -version-info 8:0:0
+
+noinst_LTLIBRARIES = libasn1base.la
+
+if versionscript
+libasn1_la_LDFLAGS += $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map
+libasn1template_la_LDFLAGS += $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map
+endif
+
+
+libasn1_la_LIBADD = \
+ libasn1base.la \
+ @LIB_com_err@ \
+ $(LIBADD_roken)
+
+libasn1template_la_LIBADD = \
+ libasn1base.la \
+ @LIB_com_err@ \
+ $(LIBADD_roken)
+
+BUILT_SOURCES = \
+ $(gen_files_rfc2459) \
+ $(gen_files_rfc4108) \
+ $(gen_files_cms) \
+ $(gen_files_krb5) \
+ $(gen_files_ocsp) \
+ $(gen_files_pkinit) \
+ $(gen_files_pkcs8) \
+ $(gen_files_pkcs9) \
+ $(gen_files_pkcs10) \
+ $(gen_files_pkcs12) \
+ $(gen_files_digest) \
+ $(gen_files_kx509)
+
+BUILT_TEMPLATE_SOURCES = \
+ $(gen_files_rfc2459_template) \
+ $(gen_files_rfc4108_template) \
+ $(gen_files_cms_template) \
+ $(gen_files_krb5_template) \
+ $(gen_files_ocsp_template) \
+ $(gen_files_pkinit_template) \
+ $(gen_files_pkcs8_template) \
+ $(gen_files_pkcs9_template) \
+ $(gen_files_pkcs10_template) \
+ $(gen_files_pkcs12_template) \
+ $(gen_files_digest_template) \
+ $(gen_files_kx509_template)
+
+gen_files_krb5 = asn1_krb5_asn1.c
+gen_files_krb5_template = asn1_krb5_template_asn1.c
+gen_files_cms = asn1_cms_asn1.c
+gen_files_cms_template = asn1_cms_template_asn1.c
+gen_files_crmf = asn1_crmf_asn1.c
+gen_files_crmf_template = asn1_crmf_template_asn1.c
+gen_files_rfc2459 = asn1_rfc2459_asn1.c
+gen_files_rfc2459_template = asn1_rfc2459_template_asn1.c
+gen_files_rfc4108 = asn1_rfc4108_asn1.c
+gen_files_rfc4108_template = asn1_rfc4108_template_asn1.c
+gen_files_ocsp = asn1_ocsp_asn1.c
+gen_files_ocsp_template = asn1_ocsp_template_asn1.c
+gen_files_pkinit = asn1_pkinit_asn1.c
+gen_files_pkinit_template = asn1_pkinit_template_asn1.c
+gen_files_pkcs10 = asn1_pkcs10_asn1.c
+gen_files_pkcs10_template = asn1_pkcs10_template_asn1.c
+gen_files_pkcs12 = asn1_pkcs12_asn1.c
+gen_files_pkcs12_template = asn1_pkcs12_template_asn1.c
+gen_files_pkcs8 = asn1_pkcs8_asn1.c
+gen_files_pkcs8_template = asn1_pkcs8_template_asn1.c
+gen_files_pkcs9 = asn1_pkcs9_asn1.c
+gen_files_pkcs9_template = asn1_pkcs9_template_asn1.c
+gen_files_test = asn1_test_asn1.c
+gen_files_test_template = asn1_test_template_asn1.c
+gen_files_digest = asn1_digest_asn1.c
+gen_files_digest_template = asn1_digest_template_asn1.c
+gen_files_kx509 = asn1_kx509_asn1.c
+gen_files_kx509_template = asn1_kx509_template_asn1.c
+gen_files_x690sample = asn1_x690sample_asn1.c
+gen_files_x690sample_template = asn1_x690sample_template_asn1.c
+
+oid_resolution.lo: $(BUILT_SOURCES)
+
+noinst_PROGRAMS = asn1_gen
+
+bin_PROGRAMS = asn1_compile asn1_print
+
+TESTS = check-der check-gen check-gen-template check-timegm check-ber check-template
+check_PROGRAMS = $(TESTS)
+
+asn1_gen_SOURCES = asn1_gen.c
+asn1_print_SOURCES = asn1_print.c
+asn1_print_SOURCES += $(gen_files_x690sample_template)
+asn1_print_CPPFLAGS = -DASN1_PRINT_SUPPORTED
+check_der_SOURCES = check-der.c check-common.c check-common.h
+
+check_template_SOURCES = check-template.c check-common.c check-common.h
+nodist_check_template_SOURCES = $(gen_files_test_template)
+
+check_gen_template_CPPFLAGS = -DASN1_IOS_SUPPORTED
+dist_check_gen_template_SOURCES = check-gen.c check-common.c check-common.h
+nodist_check_gen_template_SOURCES = $(gen_files_test_template) \
+ $(gen_files_x690sample_template)
+
+dist_check_gen_SOURCES = check-gen.c check-common.c check-common.h
+nodist_check_gen_SOURCES = $(gen_files_test) $(gen_files_x690sample)
+
+build_HEADERZ = asn1-template.h
+
+asn1_compile_SOURCES = \
+ asn1parse.y \
+ der.h \
+ gen.c \
+ gen_copy.c \
+ gen_decode.c \
+ gen_encode.c \
+ gen_print.c \
+ gen_free.c \
+ gen_glue.c \
+ gen_length.c \
+ gen_locl.h \
+ gen_seq.c \
+ gen_template.c \
+ hash.c \
+ hash.h \
+ lex.l \
+ lex.h \
+ main.c \
+ asn1-template.h \
+ symbol.c \
+ symbol.h
+
+dist_libasn1base_la_SOURCES = \
+ der_locl.h \
+ der.c \
+ der.h \
+ der_get.c \
+ der_put.c \
+ der_free.c \
+ der_print.c \
+ der_length.c \
+ der_copy.c \
+ der_cmp.c \
+ der_format.c \
+ fuzzer.c \
+ heim_asn1.h \
+ extra.c \
+ roken_rename.h \
+ template.c \
+ timegm.c
+
+dist_libasn1_la_SOURCES = oid_resolution.c
+dist_libasn1template_la_SOURCES = oid_resolution.c
+
+nodist_libasn1base_la_SOURCES = \
+ asn1_err.h \
+ asn1_err.c
+
+nodist_libasn1_la_SOURCES = $(BUILT_SOURCES)
+
+if !ASN1_TEMPLATING
+nodist_libasn1template_la_SOURCES = $(BUILT_TEMPLATE_SOURCES)
+else
+nodist_libasn1template_la_SOURCES = $(BUILT_SOURCES)
+endif
+
+asn1_compile_LDADD = \
+ $(LIB_roken) $(LEXLIB)
+
+check_der_LDADD = \
+ libasn1.la \
+ $(LIB_roken)
+
+check_template_LDADD = $(check_der_LDADD)
+asn1_print_LDADD = libasn1template.la $(LIB_roken) $(LIB_com_err)
+asn1_gen_LDADD = $(check_der_LDADD)
+check_timegm_LDADD = $(check_der_LDADD)
+
+check_gen_template_LDADD = \
+ libasn1template.la \
+ $(LIB_roken)
+
+check_gen_LDADD = \
+ libasn1template.la \
+ $(LIB_roken)
+
+check_ber_LDADD = $(check_gen_LDADD)
+
+CLEANFILES = \
+ $(BUILT_SOURCES) \
+ $(gen_files_rfc2459) \
+ $(gen_files_rfc2459_template) \
+ $(gen_files_rfc4108) \
+ $(gen_files_rfc4108_template) \
+ $(gen_files_cms) \
+ $(gen_files_cms_template) \
+ $(gen_files_krb5) \
+ $(gen_files_krb5_template) \
+ $(gen_files_ocsp) \
+ $(gen_files_ocsp_template) \
+ $(gen_files_pkinit) \
+ $(gen_files_pkinit_template) \
+ $(gen_files_pkcs8) \
+ $(gen_files_pkcs8_template) \
+ $(gen_files_pkcs9) \
+ $(gen_files_pkcs9_template) \
+ $(gen_files_pkcs10) \
+ $(gen_files_pkcs10_template) \
+ $(gen_files_pkcs12) \
+ $(gen_files_pkcs12_template) \
+ $(gen_files_digest) \
+ $(gen_files_digest_template) \
+ $(gen_files_kx509) \
+ $(gen_files_kx509_template) \
+ $(gen_files_x690sample) \
+ $(gen_files_x690sample_template) \
+ $(gen_files_test) \
+ $(gen_files_test_template) \
+ $(nodist_check_gen_SOURCES) \
+ asn1parse.c asn1parse.h lex.c \
+ asn1_err.c asn1_err.h \
+ rfc2459_asn1_files rfc2459_asn1*.h \
+ rfc2459_template_asn1_files rfc2459_template_asn1*.h \
+ rfc4108_asn1_files rfc4108_asn1*.h \
+ rfc4108_template_asn1_files rfc4108_template_asn1*.h \
+ cms_asn1_files cms_asn1*.h \
+ cms_template_asn1_files cms_template_asn1* \
+ crmf_asn1_files crmf_asn1* \
+ crmf_template_asn1_files crmf_template_asn1* \
+ krb5_asn1_files krb5_asn1* \
+ krb5_template_asn1_files krb5_template_asn1* \
+ ocsp_asn1_files ocsp_asn1* \
+ ocsp_template_asn1_files ocsp_template_asn1* \
+ pkinit_asn1_files pkinit_asn1* \
+ pkinit_template_asn1_files pkinit_template_asn1* \
+ pkcs8_asn1_files pkcs8_asn1* \
+ pkcs8_template_asn1_files pkcs8_template_asn1* \
+ pkcs9_asn1_files pkcs9_asn1* \
+ pkcs9_template_asn1_files pkcs9_template_asn1* \
+ pkcs10_asn1_files pkcs10_asn1* \
+ pkcs10_template_asn1_files pkcs10_template_asn1* \
+ pkcs12_asn1_files pkcs12_asn1* \
+ pkcs12_template_asn1_files pkcs12_template_asn1* \
+ digest_asn1_files digest_asn1* \
+ digest_template_asn1_files digest_template_asn1* \
+ kx509_asn1_files kx509_asn1* \
+ kx509_template_asn1_files kx509_template_asn1* \
+ x690sample_asn1_files x690sample_asn1* \
+ x690sample_template_asn1_files x690sample_template_asn1* \
+ test_asn1_files test_asn1* \
+ test_template_asn1_files test_template_asn1* \
+ asn1_*_asn1.c *_asn1.json *_asn1_syms.c *_asn1_oids.c
+
+dist_include_HEADERS = der.h heim_asn1.h
+dist_include_HEADERS += $(srcdir)/der-protos.h $(srcdir)/der-private.h
+dist_include_HEADERS += asn1-common.h
+
+nodist_include_HEADERS = asn1_err.h
+nodist_include_HEADERS += krb5_asn1.h
+nodist_include_HEADERS += krb5_template_asn1.h
+nodist_include_HEADERS += pkinit_asn1.h
+nodist_include_HEADERS += pkinit_template_asn1.h
+nodist_include_HEADERS += cms_asn1.h
+nodist_include_HEADERS += cms_template_asn1.h
+nodist_include_HEADERS += crmf_asn1.h
+nodist_include_HEADERS += crmf_template_asn1.h
+nodist_include_HEADERS += rfc2459_asn1.h
+nodist_include_HEADERS += rfc2459_template_asn1.h
+nodist_include_HEADERS += rfc4108_asn1.h
+nodist_include_HEADERS += rfc4108_template_asn1.h
+nodist_include_HEADERS += ocsp_asn1.h
+nodist_include_HEADERS += ocsp_template_asn1.h
+nodist_include_HEADERS += pkcs8_asn1.h
+nodist_include_HEADERS += pkcs8_template_asn1.h
+nodist_include_HEADERS += pkcs9_asn1.h
+nodist_include_HEADERS += pkcs9_template_asn1.h
+nodist_include_HEADERS += pkcs10_asn1.h
+nodist_include_HEADERS += pkcs10_template_asn1.h
+nodist_include_HEADERS += pkcs12_asn1.h
+nodist_include_HEADERS += pkcs12_template_asn1.h
+nodist_include_HEADERS += digest_asn1.h
+nodist_include_HEADERS += digest_template_asn1.h
+nodist_include_HEADERS += kx509_asn1.h
+nodist_include_HEADERS += kx509_template_asn1.h
+nodist_include_HEADERS += x690sample_asn1.h
+nodist_include_HEADERS += x690sample_template_asn1.h
+
+priv_headers = krb5_asn1-priv.h
+priv_headers += krb5_template_asn1-priv.h
+priv_headers += pkinit_asn1-priv.h
+priv_headers += pkinit_template_asn1-priv.h
+priv_headers += cms_asn1-priv.h
+priv_headers += cms_template_asn1-priv.h
+priv_headers += crmf_asn1-priv.h
+priv_headers += crmf_template_asn1-priv.h
+priv_headers += rfc2459_asn1-priv.h
+priv_headers += rfc2459_template_asn1-priv.h
+priv_headers += rfc4108_asn1-priv.h
+priv_headers += rfc4108_template_asn1-priv.h
+priv_headers += ocsp_asn1-priv.h
+priv_headers += ocsp_template_asn1-priv.h
+priv_headers += pkcs8_asn1-priv.h
+priv_headers += pkcs8_template_asn1-priv.h
+priv_headers += pkcs9_asn1-priv.h
+priv_headers += pkcs9_template_asn1-priv.h
+priv_headers += pkcs10_asn1-priv.h
+priv_headers += pkcs10_template_asn1-priv.h
+priv_headers += pkcs12_asn1-priv.h
+priv_headers += pkcs12_template_asn1-priv.h
+priv_headers += digest_asn1-priv.h
+priv_headers += digest_template_asn1-priv.h
+priv_headers += kx509_asn1-priv.h
+priv_headers += kx509_template_asn1-priv.h
+priv_headers += x690sample_asn1-priv.h
+priv_headers += x690sample_template_asn1-priv.h
+priv_headers += test_asn1.h test_asn1-priv.h
+priv_headers += test_template_asn1.h test_template_asn1-priv.h
+
+
+
+$(asn1_compile_OBJECTS): asn1parse.h asn1parse.c $(srcdir)/der-protos.h $(srcdir)/der-private.h
+$(libasn1_la_OBJECTS): $(nodist_include_HEADERS) $(priv_headers) asn1_err.h $(srcdir)/der-protos.h $(srcdir)/der-private.h
+$(libasn1template_la_OBJECTS): $(nodist_include_HEADERS) $(priv_headers) asn1_err.h $(srcdir)/der-protos.h $(srcdir)/der-private.h
+$(libasn1base_la_OBJECTS): asn1_err.h $(srcdir)/der-protos.h $(srcdir)/der-private.h
+$(check_gen_OBJECTS): test_asn1.h
+$(check_template_OBJECTS): test_asn1_files
+$(asn1_print_OBJECTS): $(nodist_include_HEADERS) $(priv_headers)
+
+asn1parse.h: asn1parse.c
+
+$(gen_files_krb5) krb5_asn1.h krb5_asn1-priv.h: krb5_asn1_files
+$(gen_files_krb5_template) krb5_template_asn1.h krb5_template_asn1-priv.h: krb5_template_asn1_files
+$(gen_files_ocsp) ocsp_asn1.h ocsp_asn1-priv.h: ocsp_asn1_files
+$(gen_files_ocsp_template) ocsp_template_asn1.h ocsp_template_asn1-priv.h: ocsp_template_asn1_files
+$(gen_files_pkinit) pkinit_asn1.h pkinit_asn1-priv.h: pkinit_asn1_files
+$(gen_files_pkinit_template) pkinit_template_asn1.h pkinit_template_asn1-priv.h: pkinit_template_asn1_files
+$(gen_files_pkcs8) pkcs8_asn1.h pkcs8_asn1-priv.h: pkcs8_asn1_files
+$(gen_files_pkcs8_template) pkcs8_template_asn1.h pkcs8_template_asn1-priv.h: pkcs8_template_asn1_files
+$(gen_files_pkcs9) pkcs9_asn1.h pkcs9_asn1-priv.h: pkcs9_asn1_files
+$(gen_files_pkcs9_template) pkcs9_template_asn1.h pkcs9_template_asn1-priv.h: pkcs9_template_asn1_files
+$(gen_files_pkcs10) pkcs10_asn1.h pkcs10_asn1-priv.h: pkcs10_asn1_files
+$(gen_files_pkcs10_template) pkcs10_template_asn1.h pkcs10_template_asn1-priv.h: pkcs10_template_asn1_files
+$(gen_files_pkcs12) pkcs12_asn1.h pkcs12_asn1-priv.h: pkcs12_asn1_files
+$(gen_files_pkcs12_template) pkcs12_template_asn1.h pkcs12_template_asn1-priv.h: pkcs12_template_asn1_files
+$(gen_files_digest) digest_asn1.h digest_asn1-priv.h: digest_asn1_files
+$(gen_files_digest_template) digest_template_asn1.h digest_template_asn1-priv.h: digest_template_asn1_files
+$(gen_files_kx509) kx509_asn1.h kx509_asn1-priv.h: kx509_asn1_files
+$(gen_files_kx509_template) kx509_template_asn1.h kx509_template_asn1-priv.h: kx509_template_asn1_files
+$(gen_files_rfc2459) rfc2459_asn1.h rfc2459_asn1-priv.h: rfc2459_asn1_files
+$(gen_files_rfc2459_template) rfc2459_template_asn1.h rfc2459_template_asn1-priv.h: rfc2459_template_asn1_files
+$(gen_files_rfc4108) rfc4108_asn1.h rfc4108_asn1-priv.h: rfc4108_asn1_files
+$(gen_files_rfc4108_template) rfc4108_template_asn1.h rfc4108_template_asn1-priv.h: rfc4108_template_asn1_files
+$(gen_files_cms) cms_asn1.h cms_asn1-priv.h: cms_asn1_files
+$(gen_files_cms_template) cms_template_asn1.h cms_template_asn1-priv.h: cms_template_asn1_files
+$(gen_files_crmf) crmf_asn1.h crmf_asn1-priv.h: crmf_asn1_files
+$(gen_files_crmf_template) crmf_template_asn1.h crmf_template_asn1-priv.h: crmf_template_asn1_files
+$(gen_files_x690sample) x690sample_asn1.h x690sample_asn1-priv.h: x690sample_asn1_files
+$(gen_files_x690sample_template) x690sample_template_asn1.h x690sample_template_asn1-priv.h: x690sample_template_asn1_files
+$(gen_files_test) test_asn1.h test_asn1-priv.h: test_asn1_files
+$(gen_files_test_template) test_template_asn1.h test_template_asn1-priv.h: test_template_asn1_files
+
+if ASN1_TEMPLATING
+TEMPLATE_OPTION=--template
+else
+TEMPLATE_OPTION=
+endif
+
+# If the default is not templating, then we build a variant of libasn1 that is
+# templated anyways.
+rfc2459_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc2459.asn1
+ $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/rfc2459.opt $(srcdir)/rfc2459.asn1 rfc2459_template_asn1 || (rm -f rfc2459_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_rfc2459_template_asn1.c
+
+rfc4108_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc4108.asn1
+ $(ASN1_COMPILE) --one-code-file --template $(srcdir)/rfc4108.asn1 rfc4108_template_asn1 || (rm -f rfc4108_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_rfc4108_template_asn1.c
+
+cms_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/cms.asn1 $(srcdir)/cms.opt
+ $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/cms.opt $(srcdir)/cms.asn1 cms_template_asn1 || (rm -f cms_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_cms_template_asn1.c
+
+crmf_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/crmf.asn1 $(srcdir)/crmf.opt
+ $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/crmf.opt $(srcdir)/crmf.asn1 crmf_template_asn1 || (rm -f crmf_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_crmf_template_asn1.c
+
+krb5_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/krb5.asn1 $(srcdir)/krb5.opt
+ $(ASN1_COMPILE) --one-code-file --template \
+ --option-file=$(srcdir)/krb5.opt \
+ $(srcdir)/krb5.asn1 krb5_template_asn1 || (rm -f krb5_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_krb5_template_asn1.c
+
+ocsp_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/ocsp.asn1
+ $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/ocsp.opt $(srcdir)/ocsp.asn1 ocsp_template_asn1 || (rm -f ocsp_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_ocsp_template_asn1.c
+
+pkinit_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkinit.asn1
+ $(ASN1_COMPILE) --one-code-file --template $(srcdir)/pkinit.asn1 pkinit_template_asn1 || (rm -f pkinit_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkinit_template_asn1.c
+
+pkcs8_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs8.asn1
+ $(ASN1_COMPILE) --one-code-file --template $(srcdir)/pkcs8.asn1 pkcs8_template_asn1 || (rm -f pkcs8_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs8_template_asn1.c
+
+pkcs9_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs9.asn1
+ $(ASN1_COMPILE) --one-code-file --template $(srcdir)/pkcs9.asn1 pkcs9_template_asn1 || (rm -f pkcs9_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs9_template_asn1.c
+
+pkcs10_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs10.asn1
+ $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/pkcs10.opt $(srcdir)/pkcs10.asn1 pkcs10_template_asn1 || (rm -f pkcs10_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs10_template_asn1.c
+
+pkcs12_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs12.asn1
+ $(ASN1_COMPILE) --one-code-file --template $(srcdir)/pkcs12.asn1 pkcs12_template_asn1 || (rm -f pkcs12_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs12_template_asn1.c
+
+digest_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/digest.asn1
+ $(ASN1_COMPILE) --one-code-file --template $(srcdir)/digest.asn1 digest_template_asn1 || (rm -f digest_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_digest_template_asn1.c
+
+kx509_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/kx509.asn1
+ $(ASN1_COMPILE) --one-code-file --template $(srcdir)/kx509.asn1 kx509_template_asn1 || (rm -f kx509_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_kx509_template_asn1.c
+
+rfc2459_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc2459.asn1
+ $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/rfc2459.opt $(srcdir)/rfc2459.asn1 rfc2459_asn1 || (rm -f rfc2459_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_rfc2459_asn1.c
+
+rfc4108_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc4108.asn1
+ $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/rfc4108.asn1 rfc4108_asn1 || (rm -f rfc4108_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_rfc4108_asn1.c
+
+cms_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/cms.asn1 $(srcdir)/cms.opt
+ $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/cms.opt $(srcdir)/cms.asn1 cms_asn1 || (rm -f cms_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_cms_asn1.c
+
+crmf_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/crmf.asn1 $(srcdir)/crmf.opt
+ $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/crmf.opt $(srcdir)/crmf.asn1 crmf_asn1 || (rm -f crmf_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_crmf_asn1.c
+
+krb5_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/krb5.asn1 $(srcdir)/krb5.opt
+ $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) \
+ --option-file=$(srcdir)/krb5.opt \
+ $(srcdir)/krb5.asn1 krb5_asn1 || (rm -f krb5_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_krb5_asn1.c
+
+ocsp_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/ocsp.asn1
+ $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/ocsp.opt $(srcdir)/ocsp.asn1 ocsp_asn1 || (rm -f ocsp_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_ocsp_asn1.c
+
+pkinit_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkinit.asn1
+ $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/pkinit.asn1 pkinit_asn1 || (rm -f pkinit_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkinit_asn1.c
+
+pkcs8_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs8.asn1
+ $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/pkcs8.asn1 pkcs8_asn1 || (rm -f pkcs8_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs8_asn1.c
+
+pkcs9_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs9.asn1
+ $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/pkcs9.asn1 pkcs9_asn1 || (rm -f pkcs9_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs9_asn1.c
+
+pkcs10_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs10.asn1
+ $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/pkcs10.opt $(srcdir)/pkcs10.asn1 pkcs10_asn1 || (rm -f pkcs10_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs10_asn1.c
+
+pkcs12_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs12.asn1
+ $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/pkcs12.asn1 pkcs12_asn1 || (rm -f pkcs12_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs12_asn1.c
+
+digest_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/digest.asn1
+ $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/digest.asn1 digest_asn1 || (rm -f digest_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_digest_asn1.c
+
+kx509_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/kx509.asn1
+ $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/kx509.asn1 kx509_asn1 || (rm -f kx509_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_kx509_asn1.c
+
+x690sample_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/x690sample.asn1
+ $(ASN1_COMPILE) --one-code-file --template $(srcdir)/x690sample.asn1 x690sample_template_asn1 || (rm -f x690sample_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_x690sample_template_asn1.c
+
+x690sample_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/x690sample.asn1
+ $(ASN1_COMPILE) --one-code-file $(srcdir)/x690sample.asn1 x690sample_asn1 || (rm -f x690sample_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_x690sample_asn1.c
+
+test_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1
+ $(ASN1_COMPILE) --one-code-file \
+ --template \
+ --option-file=$(srcdir)/test.opt \
+ $(srcdir)/test.asn1 test_template_asn1 || (rm -f test_template_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_test_template_asn1.c
+
+test_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1
+ $(ASN1_COMPILE) --one-code-file \
+ --option-file=$(srcdir)/test.opt \
+ $(srcdir)/test.asn1 test_asn1 || (rm -f test_asn1_files ; exit 1)
+ @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_test_asn1.c
+
+
+EXTRA_DIST = \
+ NTMakefile \
+ README-template.md \
+ asn1_compile-version.rc \
+ libasn1-exports.def \
+ canthandle.asn1 \
+ cms.asn1 \
+ cms.opt \
+ crmf.asn1 \
+ crmf.opt \
+ digest.asn1 \
+ krb5.asn1 \
+ krb5.opt \
+ kx509.asn1 \
+ ocsp.asn1 \
+ ocsp.opt \
+ pkcs10.asn1 \
+ pkcs10.opt \
+ pkcs12.asn1 \
+ pkcs8.asn1 \
+ pkcs9.asn1 \
+ pkinit.asn1 \
+ pku2u.asn1 \
+ rfc2459.asn1 \
+ rfc2459.opt \
+ rfc4108.asn1 \
+ setchgpw2.asn1 \
+ tcg.asn1 \
+ test.asn1 \
+ test.opt \
+ x690sample.asn1 \
+ test.gen \
+ asn1_err.et \
+ asn1_err.c \
+ asn1_err.h \
+ asn1_print.1 \
+ asn1_compile.1 \
+ version-script.map
+
+DER_PROTOS = $(srcdir)/der-protos.h $(srcdir)/der-private.h
+
+ALL_OBJECTS = $(libasn1_la_OBJECTS)
+ALL_OBJECTS += $(libasn1template_la_OBJECTS)
+ALL_OBJECTS += $(libasn1base_la_OBJECTS)
+ALL_OBJECTS += $(asn1_print_OBJECTS)
+ALL_OBJECTS += $(asn1_compile_OBJECTS)
+ALL_OBJECTS += $(asn1_gen_OBJECTS)
+ALL_OBJECTS += $(check_template_OBJECTS)
+
+$(ALL_OBJECTS): $(DER_PROTOS) asn1_err.h
+
+$(srcdir)/der-protos.h: $(dist_libasn1base_la_SOURCES) $(dist_libasn1_la_SOURCES)
+ cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -o der-protos.h $(dist_libasn1base_la_SOURCES) $(dist_libasn1_la_SOURCES) || rm -f der-protos.h
+
+$(srcdir)/der-private.h: $(dist_libasn1base_la_SOURCES) $(dist_libasn1_la_SOURCES)
+ cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p der-private.h $(dist_libasn1base_la_SOURCES) $(dist_libasn1_la_SOURCES) || rm -f der-private.h
diff --git a/third_party/heimdal/lib/asn1/NTMakefile b/third_party/heimdal/lib/asn1/NTMakefile
new file mode 100644
index 0000000..19255c6
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/NTMakefile
@@ -0,0 +1,548 @@
+########################################################################
+#
+# Copyright (c) 2009-2022, Secure Endpoints Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# - Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+RELDIR=lib\asn1
+
+intcflags=-I$(SRCDIR) -I$(OBJ) -DROKEN_RENAME -DASN1_IOS_SUPPORTED -DASN1_LIB
+
+!include ../../windows/NTMakefile.w32
+
+ASN1_BINARIES = \
+ $(LIBEXECDIR)\asn1_compile.exe
+
+$(BINDIR)\asn1_compile.exe: \
+ $(OBJ)\asn1parse.obj \
+ $(OBJ)\gen.obj \
+ $(OBJ)\gen_copy.obj \
+ $(OBJ)\gen_decode.obj \
+ $(OBJ)\gen_encode.obj \
+ $(OBJ)\gen_print.obj \
+ $(OBJ)\gen_free.obj \
+ $(OBJ)\gen_glue.obj \
+ $(OBJ)\gen_length.obj \
+ $(OBJ)\gen_seq.obj \
+ $(OBJ)\gen_template.obj \
+ $(OBJ)\hash.obj \
+ $(OBJ)\lex.obj \
+ $(OBJ)\main.obj \
+ $(OBJ)\symbol.obj \
+ $(OBJ)\asn1_compile-version.res
+ $(EXECONLINK) $(LIBROKEN) $(LIBVERS)
+ $(EXEPREP_NOHEIM)
+
+$(OBJ)\lex.c: lex.l $(OBJ)\asn1parse.h
+ $(LEX) -o$@ lex.l
+
+$(OBJ)\lex.obj: $(OBJ)\lex.c
+ $(C2OBJ) -DYY_NO_UNISTD_H
+
+$(OBJ)\asn1parse.c $(OBJ)\asn1parse.h: asn1parse.y
+ $(YACC) -o $(OBJ)\asn1parse.c --defines=$(OBJ)\asn1parse.h $**
+
+$(OBJ)\asn1_err.c $(OBJ)\asn1_err.h: asn1_err.et
+ cd $(OBJ)
+ $(BINDIR)\compile_et.exe $(SRCDIR)\asn1_err.et
+ cd $(SRCDIR)
+
+$(BINDIR)\asn1_print.exe: $(OBJ)\asn1_print.obj $(LIBHEIMDAL)
+ $(EXECONLINK) $(LIBVERS) $(LIBROKEN) $(LIBCOMERR)
+ $(EXEPREP)
+
+$(BINDIR)\asn1_gen.exe: $(OBJ)\asn1_gen.obj $(LIBHEIMDAL)
+ $(EXECONLINK) $(LIBVERS) $(LIBROKEN)
+ $(EXEPREP)
+
+LIBASN1_X= \
+ $(OBJ)\asn1_rfc2459_asn1.c \
+ $(OBJ)\asn1_rfc4108_asn1.c \
+ $(OBJ)\asn1_cms_asn1.c \
+ $(OBJ)\asn1_krb5_asn1.c \
+ $(OBJ)\asn1_ocsp_asn1.c \
+ $(OBJ)\asn1_pkinit_asn1.c \
+ $(OBJ)\asn1_pkcs8_asn1.c \
+ $(OBJ)\asn1_pkcs9_asn1.c \
+ $(OBJ)\asn1_pkcs10_asn1.c \
+ $(OBJ)\asn1_pkcs12_asn1.c \
+ $(OBJ)\asn1_digest_asn1.c \
+ $(OBJ)\asn1_kx509_asn1.c \
+ $(OBJ)\asn1_x690sample_asn1.c
+
+LIBASN1_OBJS= \
+ $(OBJ)\der.obj \
+ $(OBJ)\der_get.obj \
+ $(OBJ)\der_put.obj \
+ $(OBJ)\der_free.obj \
+ $(OBJ)\der_print.obj \
+ $(OBJ)\der_length.obj \
+ $(OBJ)\der_copy.obj \
+ $(OBJ)\der_cmp.obj \
+ $(OBJ)\der_format.obj \
+ $(OBJ)\template.obj \
+ $(OBJ)\extra.obj \
+ $(OBJ)\oid_resolution.obj \
+ $(OBJ)\timegm.obj \
+ $(OBJ)\asn1_rfc2459_asn1.obj \
+ $(OBJ)\asn1_rfc4108_asn1.obj \
+ $(OBJ)\asn1_cms_asn1.obj \
+ $(OBJ)\asn1_krb5_asn1.obj \
+ $(OBJ)\asn1_ocsp_asn1.obj \
+ $(OBJ)\asn1_pkinit_asn1.obj \
+ $(OBJ)\asn1_pkcs8_asn1.obj \
+ $(OBJ)\asn1_pkcs9_asn1.obj \
+ $(OBJ)\asn1_pkcs10_asn1.obj \
+ $(OBJ)\asn1_pkcs12_asn1.obj \
+ $(OBJ)\asn1_digest_asn1.obj \
+ $(OBJ)\asn1_kx509_asn1.obj \
+ $(OBJ)\asn1_x690sample_asn1.obj \
+ $(OBJ)\asn1_err.obj
+
+$(OBJ)\oid_resolution.obj: $(LIBASN1_X)
+
+$(LIBASN1): $(LIBASN1_OBJS)
+ $(LIBCON_C) -out:$@ @<<
+$(**: =
+)
+<<
+
+clean::
+ -$(RM) $(LIBASN1)
+
+#
+# The static runtime version LIBASN1_S is for use by thirdparty
+# components. It is not used in the construction of the Heimdal
+# DLLs.
+
+LIBASN1_S_OBJS= \
+ $(OBJ)\der.s.obj \
+ $(OBJ)\der_get.s.obj \
+ $(OBJ)\der_put.s.obj \
+ $(OBJ)\der_free.s.obj \
+ $(OBJ)\der_print.s.obj \
+ $(OBJ)\der_length.s.obj \
+ $(OBJ)\der_copy.s.obj \
+ $(OBJ)\der_cmp.s.obj \
+ $(OBJ)\der_format.s.obj \
+ $(OBJ)\template.s.obj \
+ $(OBJ)\extra.s.obj \
+ $(OBJ)\oid_resolution.s.obj \
+ $(OBJ)\timegm.s.obj \
+ $(OBJ)\asn1_rfc2459_asn1.s.obj \
+ $(OBJ)\asn1_rfc4108_asn1.s.obj \
+ $(OBJ)\asn1_cms_asn1.s.obj \
+ $(OBJ)\asn1_krb5_asn1.s.obj \
+ $(OBJ)\asn1_ocsp_asn1.s.obj \
+ $(OBJ)\asn1_pkinit_asn1.s.obj \
+ $(OBJ)\asn1_pkcs8_asn1.s.obj \
+ $(OBJ)\asn1_pkcs9_asn1.s.obj \
+ $(OBJ)\asn1_pkcs10_asn1.s.obj \
+ $(OBJ)\asn1_pkcs12_asn1.s.obj \
+ $(OBJ)\asn1_digest_asn1.s.obj \
+ $(OBJ)\asn1_kx509_asn1.s.obj \
+ $(OBJ)\asn1_x690sample_asn1.s.obj \
+ $(OBJ)\asn1_err.s.obj
+
+$(OBJ)\oid_resolution.s.obj: oid_resolution.c $(LIBASN1_X)
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ oid_resolution.c
+
+$(OBJ)\der.s.obj: der.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\der_get.s.obj: der_get.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\der_put.s.obj: der_put.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\der_free.s.obj: der_free.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\der_print.s.obj: der_print.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\der_length.s.obj: der_length.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\der_copy.s.obj: der_copy.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\der_cmp.s.obj: der_cmp.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\der_format.s.obj: der_format.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\template.s.obj: template.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\extra.s.obj: extra.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\timegm.s.obj: timegm.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_rfc2459_asn1.s.obj: $(OBJ)\asn1_rfc2459_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_rfc4108_asn1.s.obj: $(OBJ)\asn1_rfc4108_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_cms_asn1.s.obj: $(OBJ)\asn1_cms_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_krb5_asn1.s.obj: $(OBJ)\asn1_krb5_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_ocsp_asn1.s.obj: $(OBJ)\asn1_ocsp_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_pkinit_asn1.s.obj: $(OBJ)\asn1_pkinit_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_pkcs8_asn1.s.obj: $(OBJ)\asn1_pkcs8_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_pkcs9_asn1.s.obj: $(OBJ)\asn1_pkcs9_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_pkcs10_asn1.s.obj: $(OBJ)\asn1_pkcs10_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_pkcs12_asn1.s.obj: $(OBJ)\asn1_pkcs12_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_digest_asn1.s.obj: $(OBJ)\asn1_digest_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_kx509_asn1.s.obj: $(OBJ)\asn1_kx509_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_x690sample_asn1.s.obj: $(OBJ)\asn1_x690sample_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_test_asn1.s.obj: $(OBJ)\asn1_test_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_test_template_asn1.s.obj: $(OBJ)\asn1_test_template_asn1.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_err.s.obj: $(OBJ)\asn1_err.c
+ $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(LIBASN1_S): $(LIBASN1_S_OBJS)
+ $(LIBCON_C) -out:$@ @<<
+$(**: =
+)
+<<
+
+clean::
+ -$(RM) $(LIBASN1_S)
+
+
+#
+# Generate list of exports
+#
+# This target is only used during development to generate a list of
+# symbols that are exported from all the object files in LIBASN1_OBJS.
+#
+exports-list.txt: $(LIBASN1_OBJS)
+ $(PERL) ..\..\cf\w32-list-externs-from-objs.pl -q -u @<< > $@
+$(**: =
+)
+<<
+
+$(OBJ)\asn1_krb5_asn1.c $(OBJ)\krb5_asn1.h: $(BINDIR)\asn1_compile.exe krb5.asn1 krb5.opt
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe \
+ --template \
+ --one-code-file \
+ --option-file=$(SRCDIR)\krb5.opt \
+ $(SRCDIR)\krb5.asn1 krb5_asn1 \
+ || ($(RM) $(OBJ)\krb5_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(OBJ)\asn1_ocsp_asn1.c $(OBJ)\ocsp_asn1.h: $(BINDIR)\asn1_compile.exe ocsp.asn1
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe \
+ --template \
+ --one-code-file \
+ --option-file=$(SRCDIR)\ocsp.opt \
+ $(SRCDIR)\ocsp.asn1 \
+ ocsp_asn1 \
+ || ($(RM) $(OBJ)\ocsp_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(OBJ)\asn1_pkinit_asn1.c $(OBJ)\pkinit_asn1.h: $(BINDIR)\asn1_compile.exe pkinit.asn1
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\pkinit.asn1 pkinit_asn1 \
+ || ($(RM) $(OBJ)\pkinit_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(OBJ)\asn1_pkcs8_asn1.c $(OBJ)\pkcs8_asn1.h: $(BINDIR)\asn1_compile.exe pkcs8.asn1
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\pkcs8.asn1 pkcs8_asn1 \
+ || ($(RM) $(OBJ)\pkcs8_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(OBJ)\asn1_pkcs9_asn1.c $(OBJ)\pkcs9_asn1.h: $(BINDIR)\asn1_compile.exe pkcs9.asn1
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\pkcs9.asn1 pkcs9_asn1 \
+ || ($(RM) $(OBJ)\pkcs9_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(OBJ)\asn1_pkcs10_asn1.c $(OBJ)\pkcs10_asn1.h: $(BINDIR)\asn1_compile.exe pkcs10.asn1
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe \
+ --template \
+ --one-code-file \
+ --option-file=$(SRCDIR)\pkcs10.opt \
+ $(SRCDIR)\pkcs10.asn1 \
+ pkcs10_asn1 \
+ || ($(RM) $(OBJ)\pkcs10_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(OBJ)\asn1_pkcs12_asn1.c $(OBJ)\pkcs12_asn1.h: $(BINDIR)\asn1_compile.exe pkcs12.asn1
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\pkcs12.asn1 pkcs12_asn1 \
+ || ($(RM) $(OBJ)\pkcs12_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(OBJ)\asn1_digest_asn1.c $(OBJ)\digest_asn1.h: $(BINDIR)\asn1_compile.exe digest.asn1
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\digest.asn1 digest_asn1 \
+ || ($(RM) $(OBJ)\digest_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(OBJ)\asn1_kx509_asn1.c $(OBJ)\kx509_asn1.h: $(BINDIR)\asn1_compile.exe kx509.asn1
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\kx509.asn1 kx509_asn1 \
+ || ($(RM) $(OBJ)\kx509_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(OBJ)\asn1_rfc2459_asn1.c $(OBJ)\rfc2459_asn1.h: $(BINDIR)\asn1_compile.exe rfc2459.asn1
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe \
+ --template \
+ --one-code-file \
+ --option-file=$(SRCDIR)\rfc2459.opt \
+ $(SRCDIR)\rfc2459.asn1 rfc2459_asn1 \
+ || ($(RM) $(OBJ)\rfc2459_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(OBJ)\asn1_rfc4108_asn1.c $(OBJ)\rfc4108_asn1.h: $(BINDIR)\asn1_compile.exe rfc4108.asn1
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe \
+ --template \
+ --one-code-file \
+ $(SRCDIR)\rfc4108.asn1 rfc4108_asn1 \
+ || ($(RM) $(OBJ)\rfc4108_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(OBJ)\asn1_cms_asn1.c $(OBJ)\cms_asn1.h: $(BINDIR)\asn1_compile.exe cms.asn1 cms.opt
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe \
+ --template \
+ --one-code-file --option-file=$(SRCDIR)\cms.opt \
+ $(SRCDIR)\cms.asn1 cms_asn1 \
+ || ($(RM) $(OBJ)\cms_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(gen_files_crmf) $(OBJ)\crmf_asn1.h: $(BINDIR)\asn1_compile.exe crmf.asn1 crmf.opt
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe \
+ --template \
+ --one-code-file --option-file=$(SRCDIR)\crmf.opt \
+ $(SRCDIR)\crmf.asn1 crmf_asn1 \
+ || ($(RM) $(OBJ)\crmf_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(OBJ)\asn1_x690sample_asn1.c $(OBJ)\x690sample_asn1.h: $(BINDIR)\asn1_compile.exe x690sample.asn1
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe \
+ --template \
+ --one-code-file \
+ $(SRCDIR)\x690sample.asn1 x690sample_asn1 \
+ || ($(RM) $(OBJ)\x690sample_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(OBJ)\asn1_test_asn1.c $(OBJ)\test_asn1.h: $(BINDIR)\asn1_compile.exe test.asn1
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe \
+ --template \
+ --option-file=$(SRCDIR)/test.opt \
+ --one-code-file \
+ $(SRCDIR)\test.asn1 test_asn1 \
+ || ($(RM) $(OBJ)\test_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+$(OBJ)\asn1_test_template_asn1.c $(OBJ)\test_template_asn1.h: $(BINDIR)\asn1_compile.exe test.asn1
+ cd $(OBJ)
+ $(BINDIR)\asn1_compile.exe \
+ --template \
+ --option-file=$(SRCDIR)/test.opt \
+ --one-code-file \
+ $(SRCDIR)\test.asn1 test_template_asn1 \
+ || ($(RM) $(OBJ)\test_template_asn1.h ; exit /b 1)
+ cd $(SRCDIR)
+
+INCFILES= \
+ $(INCDIR)\der.h \
+ $(INCDIR)\heim_asn1.h \
+ $(INCDIR)\der-protos.h \
+ $(INCDIR)\der-private.h \
+ $(INCDIR)\asn1-common.h \
+ $(INCDIR)\asn1-template.h \
+ $(OBJ)\asn1_err.h
+
+$(INCDIR)\der-protos.h: $(OBJ)\der-protos.h
+
+GENINCFILES= \
+ $(INCDIR)\asn1_err.h \
+ $(INCDIR)\cms_asn1.h \
+ $(INCDIR)\crmf_asn1.h \
+ $(INCDIR)\digest_asn1.h \
+ $(INCDIR)\krb5_asn1.h \
+ $(INCDIR)\kx509_asn1.h \
+ $(INCDIR)\ocsp_asn1.h \
+ $(INCDIR)\pkcs12_asn1.h \
+ $(INCDIR)\pkcs8_asn1.h \
+ $(INCDIR)\pkcs9_asn1.h \
+ $(INCDIR)\pkcs10_asn1.h \
+ $(INCDIR)\pkinit_asn1.h \
+ $(INCDIR)\rfc2459_asn1.h \
+ $(INCDIR)\rfc4108_asn1.h \
+ $(INCDIR)\x690sample_asn1.h \
+ $(OBJ)\krb5_asn1-priv.h \
+ $(OBJ)\ocsp_asn1-priv.h \
+ $(OBJ)\pkinit_asn1-priv.h \
+ $(OBJ)\cms_asn1-priv.h \
+ $(OBJ)\crmf_asn1-priv.h \
+ $(OBJ)\rfc2459_asn1-priv.h \
+ $(OBJ)\rfc4108_asn1-priv.h \
+ $(OBJ)\x690sample_asn1-priv.h \
+ $(OBJ)\pkcs8_asn1-priv.h \
+ $(OBJ)\pkcs9_asn1-priv.h \
+ $(OBJ)\pkcs10_asn1-priv.h \
+ $(OBJ)\pkcs12_asn1-priv.h \
+ $(OBJ)\digest_asn1-priv.h \
+ $(OBJ)\kx509_asn1-priv.h \
+ $(OBJ)\test_template_asn1.h \
+ $(OBJ)\test_template_asn1-priv.h \
+ $(OBJ)\test_asn1.h \
+ $(OBJ)\test_asn1-priv.h
+
+libasn1_base_SOURCES= \
+ der_locl.h \
+ der.c \
+ der.h \
+ der_get.c \
+ der_put.c \
+ der_free.c \
+ der_print.c \
+ der_length.c \
+ der_copy.c \
+ der_cmp.c \
+ der_format.c \
+ template.c \
+ heim_asn1.h \
+ extra.c \
+ timegm.c
+
+libasn1_SOURCES= \
+ oid_resolution.c
+
+$(OBJ)\der-protos.h: $(libasn1_SOURCES)
+ $(PERL) ..\..\cf\make-proto.pl -q -P remove -o $(OBJ)\der-protos.h $(libasn1_base_SOURCES) $(libasn1_SOURCES) || $(RM) $(OBJ)\der-protos.h
+
+$(OBJ)\der-private.h: $(libasn1_SOURCES)
+ $(PERL) ..\..\cf\make-proto.pl -q -P remove -p $(OBJ)\der-private.h $(libasn1_base_SOURCES) $(libasn1_SOURCES) || $(RM) $(OBJ)\der-private.h
+
+clean::
+ -$(RM) $(INCDIR)\der-protos.h
+
+all:: $(INCFILES) $(GENINCFILES) $(ASN1_BINARIES) $(LIBASN1) $(LIBASN1_S)
+
+all-tools:: $(LIBEXECDIR)\asn1_print.exe $(BINDIR)\asn1_gen.exe
+
+clean::
+ -$(RM) $(INCFILES)
+ -$(RM) $(GENINCFILES)
+ -$(RM) $(ASN1_BINARIES:.exe=.*)
+ -$(RM) $(LIBASN1)
+ -$(RM) $(LIBEXECDIR)\asn1_print.*
+ -$(RM) $(LIBEXECDIR)\asn1_gen.*
+
+TEST_BINARIES=\
+ $(OBJ)\check-der.exe \
+ $(OBJ)\check-gen-template.exe \
+ $(OBJ)\check-timegm.exe \
+ $(OBJ)\check-ber.exe \
+ $(OBJ)\check-template.exe
+
+test-binaries: $(TEST_BINARIES)
+
+test-run:
+ cd $(OBJ)
+ -check-der.exe
+ -check-gen-template.exe
+ -check-timegm.exe
+ -check-ber.exe
+ -check-template.exe
+ cd $(SRC)
+
+test:: test-binaries test-run
+
+clean::
+ -$(RM) $(TEST_BINARIES:.exe=*)
+
+$(OBJ)\check-ber.exe: $(OBJ)\check-ber.obj \
+ $(LIBHEIMDAL) $(LIBROKEN)
+ $(EXECONLINK)
+ $(EXEPREP_NODIST)
+
+$(OBJ)\check-der.exe: $(OBJ)\check-der.obj $(OBJ)\check-common.obj \
+ $(LIBHEIMDAL) $(LIBROKEN)
+ $(EXECONLINK)
+ $(EXEPREP_NODIST)
+
+$(OBJ)\check-gen-template.exe: $(OBJ)\check-gen.obj $(OBJ)\check-common.obj \
+ $(LIBHEIMDAL) $(LIBROKEN) $(OBJ)\asn1_test_template_asn1.obj
+ $(EXECONLINK)
+ $(EXEPREP_NODIST)
+
+$(OBJ)\check-timegm.exe: $(OBJ)\check-timegm.obj \
+ $(LIBHEIMDAL) $(LIBROKEN)
+ $(EXECONLINK)
+ $(EXEPREP_NODIST)
+
+$(OBJ)\check-template.exe: $(OBJ)\check-template.obj $(OBJ)\check-common.obj \
+ $(LIBHEIMDAL) $(LIBROKEN) $(OBJ)\asn1_test_asn1.obj
+ $(EXECONLINK)
+ $(EXEPREP_NODIST)
diff --git a/third_party/heimdal/lib/asn1/README-X681.md b/third_party/heimdal/lib/asn1/README-X681.md
new file mode 100644
index 0000000..e0d270b
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/README-X681.md
@@ -0,0 +1,1124 @@
+# Automatic Open Type Handling via X.68x Support in Heimdal's ASN.1 Compiler
+
+## Table of Contents
+
+ 1. [Introduction](#Introduction)
+ 2. [Typed Holes / Open Types](#typed-holes--open-types)
+ 3. [ASN.1 IOS, Constraint, and Parameterization](#asn1-ios-constraint-and-parameterization)
+ - [IOS Crash Course](#ios-crash-course)
+ 4. [Usage](#Usage)
+ 5. [Limitations](#Limitations)
+ 6. [Implementation Design](#implementation-design)
+ 7. [Moving From C](#moving-from-c)
+
+## Introduction
+
+ASN.1 is a set of specifications for "syntax" for defining data schemas, and
+"encoding rules" for encoding values of data of types defined in those schemas.
+There are many encoding rules, but one syntax.
+
+The base of ASN.1 _syntax_ is specified by X.680, an ITU-T standard. The
+encoding rules are specified by the X.69x series (X.690 through X.697).
+
+This README is concerned primarily with the X.68x series.
+
+While X.680 is essential for implementing many Internet (and other) protocols,
+and sufficient for implementing all of those, there are extensions in the
+remainder of the X.68x series that can make life a lot easier for developers
+who have to use ASN.1 for interoperability reasons.
+
+Various syntax extensions are specified in X.68x series documents:
+
+ - X.681: Information Object specification
+ - X.682: Constraint specification
+ - X.683: Parameterization of ASN.1 specifications
+
+The intent of X.681, X.682, and X.683 is to add ways to formally express
+constraints that would otherwise require natural language to express. Give a
+compiler more formally-expressed constraints and it can do more labor-saving
+than it could otherwise.
+
+A subset of these three extensions, X.681, X.682, and X.683, can enable some
+rather magical features. These magical features are generally not the focus of
+those ITU-T specifications nor of many RFCs that make use of them, but
+nonetheless they are of interest to us.
+
+This README covers some ideas for what this magic is, and implementation of it.
+
+RFC 6025 does an excellent job of elucidating X.681, which otherwise most
+readers unfamiliar with it will no doubt find inscrutable. Hopefully this
+README improves that further.
+
+The magic that we're after is simply the *automatic and recursive handling of
+open types by an ASN.1 compiler*.
+
+Combined with eventual support for the ASN.1 JSON Encoding Rules (JER) [X.697],
+this feature could give us unprecendented visibility into really complex data
+structures, such as Endorsement Key Certificates (EKcerts) for Trusted Platform
+Module (TPM) applications.
+
+Support for JER and automatic handling of open types should allow us to
+trivially implement a command-line tool that can parse any DER or JER (JSON)
+encoding of any value whose type is known and compiled, and which could
+transcode to the other encoding rules. I.e., dump DER to JSON, and parse JSON
+to output DER.
+
+Indeed, Heimdal's `asn1_print` program currently supports transcoding of DER to
+JSON, though it's not quite X.697-compliant JSON! Heimdal does not currently
+support parsing JSON-encoded values of ASN.1 types.
+
+Combined with transcoders for JSON/CBOR and other binary-JSON formats, we could
+support those encodings too.
+
+We could really see how much space OER/JER/CBOR save over DER for Kerberos
+tickets, PKIX certificates, and much else.
+
+We especially want this for PKIX, and more than anything for certificates, as
+the TBSCertificate type is full of deeply nested open types: DNs and
+subjectDirectory attributes, otherName SAN types, and certificate extensions.
+
+Besides a magical ASN.1 DER/JER dumper/transcoder utility, we want to replace
+DN attribute and subject alternative name (SAN) `otherName` tables and much
+hand-coded handling of certificate extensions in `lib/hx509/`.
+
+The reader should already be familiar with ASN.1, which anyways is a set of two
+things:
+
+ - an abstract syntax for specifying schemas for data interchange
+
+ - a set of encoding rules
+
+A very common thing to see in projects that use ASN.1, as well as projects that
+use alternatives to ASN.1, is a pattern known as the "typed hole" or "open
+type".
+
+The ASN.1 Information Object System (IOS) [X.681] is all about automating the
+otherwise very annoying task of dealing with "typed holes" / "open types".
+
+The ASN.1 IOS is not sufficient to implement the magic we're after. Also
+needed is constraint specification and parameterization of types.
+
+ITU-T references:
+
+https://www.itu.int/rec/T-REC-X.680-201508-I/en
+https://www.itu.int/rec/T-REC-X.681-201508-I/en
+https://www.itu.int/rec/T-REC-X.682-201508-I/en
+https://www.itu.int/rec/T-REC-X.683-201508-I/en
+
+
+## Typed Holes / Open Types
+
+A typed hole or open type is a pattern of data structure that generally looks
+like:
+
+```
+ { type_id, bytes_encoding_a_value_of_a_type_identified_by_type_id }
+```
+
+I.e., an opaque datum and an identifier of what kind of datum that is. This
+happens because the structure with the typed hole is used in contexts where it
+can't know all possible things that can go in it. In many cases we do know
+what all possible things are that can go in a typed hole, but many years ago
+didn't, say, or anyways, had a reason to use a typed hole.
+
+These are used not only in protocols that use ASN.1, but in many protocols that
+use syntaxes and encodings unrelated to ASN.1. I.e., these concepts are *not*
+ASN.1-specific.
+
+Many Internet protocols use typed holes, and many use typed holes in ASN.1
+types. For example, PKIX, Kerberos, LDAP, and others, use ASN.1 and typed
+holes.
+
+For examples of an Internet protocol that does not use ASN.1 but which still
+has typed holes, see IP, MIME, SSHv2, IKEv2, and others. Most quintessentilly,
+IP itself, since IP packet payloads are for some upper layer protocol
+identified in the IP packet header.
+
+In ASN.1 these generally look like:
+
+```ASN.1
+ TypedHole ::= SEQUENCE {
+ typeId INTEGER,
+ opaque OCTET STRING
+ }
+```
+
+or
+
+```ASN.1
+ -- Old ASN.1 style
+ TypedHole ::= SEQUENCE {
+ typeId OBJECT IDENTIFIER,
+ opaque ANY DEFINED BY typeID
+ }
+```
+
+or
+
+```ASN.1
+ -- Old ASN.1 style
+ TypedHole ::= SEQUENCE {
+ typeId OBJECT IDENTIFIER,
+ opaque ANY -- DEFINED BY typeID
+ }
+```
+
+or any number of variations.
+
+ Note: the `ANY` variations are no longer conformant to X.680 (the base
+ ASN.1 specification).
+
+The pattern is `{ id, hole }` where the `hole` is ultimately an opaque sequence
+of bytes whose content's schema is identified by the `id` in the same data
+structure. The pattern does not require just two fields, and it does not
+require any particular type for the hole, nor for the type ID. Sometimes the
+"hole" is an `OCTET STRING`, sometimes it's a `BIT STRING`, sometimes it's an
+`ANY` or `ANY DEFINED BY`. Sometimes the hole is even an array of (`SET OF` or
+`SEQUENCE OF`, in ASN.1) values of the type identified by the id field.
+
+An example from PKIX:
+
+```ASN.1
+Extension ::= SEQUENCE {
+ extnID OBJECT IDENTIFIER, -- <- type ID
+ critical BOOLEAN OPTIONAL,
+ extnValue OCTET STRING, -- <- hole
+}
+```
+
+which shows that typed holes don't always have just three fields, and the type
+identifier isn't always an integer.
+
+Now, Heimdal's ASN.1 compiler generates the obvious C data structure for PKIX's
+`Extension` type:
+
+```C
+ typedef struct Extension {
+ heim_oid extnID;
+ int *critical;
+ heim_octet_string extnValue;
+ } Extension;
+```
+
+and applications using this compiler have to inspect the `extnID` field,
+comparing it to any number of OIDs, to determine the type of `extnValue`, then
+must call `decode_ThatType()` to decode whatever that octet string has.
+
+This is very inconvenient.
+
+Compare this to the handling of discriminated unions (what ASN.1 calls a
+`CHOICE`):
+
+```C
+ /*
+ * ASN.1 definition:
+ *
+ * DistributionPointName ::= CHOICE {
+ * fullName [0] IMPLICIT SEQUENCE OF GeneralName,
+ * nameRelativeToCRLIssuer [1] RelativeDistinguishedName,
+ * }
+ */
+
+ /* C equivalent */
+ typedef struct DistributionPointName {
+ enum DistributionPointName_enum {
+ choice_DistributionPointName_fullName = 1,
+ choice_DistributionPointName_nameRelativeToCRLIssuer
+ } element;
+ union {
+ struct DistributionPointName_fullName {
+ unsigned int len;
+ GeneralName *val;
+ } fullName;
+ RelativeDistinguishedName nameRelativeToCRLIssuer;
+ } u;
+ } DistributionPointName;
+```
+
+The ASN.1 encoding on the wire of a `CHOICE` value, almost no matter the
+encoding rules, looks... remarkably like the encoding of a typed hole. Though
+generally the alternatives of a discriminated union have to all be encoded with
+the same encoding rules, whereas with typed holes the encoded data could be
+encoded in radically different encoding rules than the structure containing it
+in a typed hole.
+
+In fact, extensible `CHOICE`s are handled by our compiler as a discriminated
+union one of whose alternatives is a typed hole when the `CHOICE` is
+extensible:
+
+```C
+ typedef struct DigestRepInner {
+ enum DigestRepInner_enum {
+ choice_DigestRepInner_asn1_ellipsis = 0, /* <--- unknown CHOICE arm */
+ choice_DigestRepInner_error,
+ choice_DigestRepInner_initReply,
+ choice_DigestRepInner_response,
+ choice_DigestRepInner_ntlmInitReply,
+ choice_DigestRepInner_ntlmResponse,
+ choice_DigestRepInner_supportedMechs
+ /* ... */
+ } element;
+ union {
+ DigestError error;
+ DigestInitReply initReply;
+ DigestResponse response;
+ NTLMInitReply ntlmInitReply;
+ NTLMResponse ntlmResponse;
+ DigestTypes supportedMechs;
+ heim_octet_string asn1_ellipsis; /* <--- unknown CHOICE arm */
+ } u;
+ } DigestRepInner;
+```
+
+The critical thing to understand is that our compiler automatically decodes
+(and encodes) `CHOICE`s' alternatives, but it used to NOT do that for typed
+holes because it knows nothing about them. Now, however, our compiler can
+do this for typed holes provided the module specifies what the alternatives
+are.
+
+It would be nice if we could treat *all* typed holes like `CHOICE`s whenever
+the compiler knows the alternatives!
+
+And that's exactly what the ASN.1 IOS system makes possible. With ASN.1 IOS
+support, our compiler can automatically decode all the `Certificate`
+extensions, and all the distinguished name extensions it knows about.
+
+There is a fair bit of code in `lib/hx509/` that deals with encoding and
+decoding things in typed holes where the compiler could just handle that
+automatically for us, allowing us to delete a lot of code.
+
+Even more importantly, if we ever add support for visual encoding rules of
+ASN.1, such as JSON Encoding Rules (JER) [X.697] or Generic String Encoding
+Rules (GSER) [RFC2641], we could have a utility program to automatically
+display or compile DER (and other encodings) of certifcates and many other
+interesting data structures.
+
+Indeed, we do now have such a utility (`asn1_print`), able to transcode DER to
+JSON.
+
+## ASN.1 IOS, Constraint, and Parameterization
+
+The ASN.1 IOS is additional syntax that allows ASN.1 module authors to express
+all the details about typed holes that ASN.1 compilers need to make developers'
+lives much easier.
+
+RFC5912 has lots of examples, such as this `CLASS` corresponding to the
+`Extension` type from PKIX:
+
+```ASN.1
+ -- A class that provides some of the details of the PKIX Extension typed
+ -- hole:
+ EXTENSION ::= CLASS {
+ -- The following are fields of a class (as opposed to "members" of
+ -- SEQUENCE or SET types):
+ &id OBJECT IDENTIFIER UNIQUE, -- This is a fixed-type value field.
+ -- UNIQUE -> There can be only one
+ -- object with this OID
+ -- in any object set of
+ -- this class.
+ -- I.e., this is like a
+ -- PRIMARY KEY in a SQL
+ -- TABLE spec.
+ &ExtnType, -- This is a type field (the hole).
+ &Critical BOOLEAN DEFAULT {TRUE | FALSE } -- fixed-type value set field.
+ } WITH SYNTAX {
+ -- This is a specification of easy to use (but hard-to-parse) syntax for
+ -- specifying instances of this CLASS:
+ SYNTAX &ExtnType IDENTIFIED BY &id
+ [CRITICALITY &Critical]
+ }
+
+ -- Here's a parameterized Extension type. The formal parameter is an as-yet
+ -- unspecified set of valid things this hole can carry for some particular
+ -- instance of this type. The actual parameter will be specified later (see
+ -- below).
+ Extension{EXTENSION:ExtensionSet} ::= SEQUENCE {
+ -- The type ID has to be the &id field of the EXTENSION CLASS of the
+ -- ExtensionSet object set parameter.
+ extnID EXTENSION.&id({ExtensionSet}),
+ -- This is the critical field, whose DEFAULT value should be that of
+ -- the &Critical field of the EXTENSION CLASS of the ExtensionSet object
+ -- set parameter.
+ critical BOOLEAN
+ -- (EXTENSION.&Critical({ExtensionSet}{@extnID}))
+ DEFAULT FALSE,
+ -- Finally, the hole is an OCTET STRING constrained to hold the encoding
+ -- of the type named by the &ExtnType field of the EXTENSION CLASS of the
+ -- ExtensionSet object set parameter.
+ --
+ -- Note that for all members of this SEQUENCE, the fields of the object
+ -- referenced must be of the same object in the ExtensionSet object set
+ -- parameter. That's how we get to say that some OID implies some type
+ -- for the hole.
+ extnValue OCTET STRING (CONTAINING
+ EXTENSION.&ExtnType({ExtensionSet}{@extnID}))
+ -- contains the DER encoding of the ASN.1 value
+ -- corresponding to the extension type identified
+ -- by extnID
+ }
+
+ -- This is just a SEQUENCE of Extensions, the parameterized version.
+ Extensions{EXTENSION:ExtensionSet} ::=
+ SEQUENCE SIZE (1..MAX) OF Extension{{ExtensionSet}}
+```
+
+and these uses of it in RFC5280 (PKIX base) where the actual parameter is
+given:
+
+```ASN.1
+ -- Here we have an individual "object" specifying that the OID
+ -- id-ce-authorityKeyIdentifier implies AuthorityKeyIdentifier as the hole
+ -- type:
+ ext-AuthorityKeyIdentifier EXTENSION ::= { SYNTAX
+ AuthorityKeyIdentifier IDENTIFIED BY
+ id-ce-authorityKeyIdentifier }
+
+ -- And here's the OID, for completeness:
+ id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 }
+ ...
+
+ -- And Here's an object set for the EXTENSION CLASS collecting a bunch of
+ -- related extensions (here they are the extensions that certificates can
+ -- carry in their extensions member):
+ CertExtensions EXTENSION ::= {
+ ext-AuthorityKeyIdentifier | ext-SubjectKeyIdentifier |
+ ext-KeyUsage | ext-PrivateKeyUsagePeriod |
+ ext-CertificatePolicies | ext-PolicyMappings |
+ ext-SubjectAltName | ext-IssuerAltName |
+ ext-SubjectDirectoryAttributes |
+ ext-BasicConstraints | ext-NameConstraints |
+ ext-PolicyConstraints | ext-ExtKeyUsage |
+ ext-CRLDistributionPoints | ext-InhibitAnyPolicy |
+ ext-FreshestCRL | ext-AuthorityInfoAccess |
+ ext-SubjectInfoAccessSyntax, ... }
+ ...
+
+ -- Lastly, we have a Certificate, and the place where the Extensions type's
+ -- actual parameter is specified.
+ --
+ -- This is where the rubber meets the road:
+
+ Certificate ::= SIGNED{TBSCertificate}
+
+ TBSCertificate ::= SEQUENCE {
+ version [0] Version DEFAULT v1,
+ serialNumber CertificateSerialNumber,
+ signature AlgorithmIdentifier{SIGNATURE-ALGORITHM,
+ {SignatureAlgorithms}},
+ issuer Name,
+ validity Validity,
+ subject Name,
+ subjectPublicKeyInfo SubjectPublicKeyInfo,
+ ... ,
+ [[2: -- If present, version MUST be v2
+ issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL
+ ]],
+ [[3: -- If present, version MUST be v3 --
+ extensions [3] Extensions{{CertExtensions}} OPTIONAL
+ -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ -- The rubber meets the road *here*.
+ --
+ -- This says that the set of *known* certificate
+ -- extensions are those for which there are "objects"
+ -- in the "object set" named CertExtensions.
+ ]], ... }
+```
+
+Notice that the `extensions` field of `TBSCertificate` is of type `Extensions`
+parametrized by the `CertExtensions` "information object set".
+
+This allows the compiler to know that if any of the OIDs listed in the
+`CertExtensions` object set appear as the actual value of the `extnID` member
+of an `Extension` value, then the `extnValue` member of the same `Extension`
+value must be an instance of the type associated with that OID. For example,
+an `Extension` with `extnID` value of `id-ce-authorityKeyIdentifier` must have
+an `extnValue` of type `AuthorityKeyIdentifier`.
+
+
+### IOS Crash Course
+
+The ASN.1 IOS may be... a bit difficult to understand -- the syntax isn't
+pretty. And X.681 has a lot of strange terminology, like "variable type value
+set field".
+
+An IOS "class" has fields, and those fields are of kind
+`[Fixed]Type[Value[Set]]` or `Object[Set]`. Then there's "objects" and "object
+sets". Hopefully this section will make all of that comprehensible.
+
+_Classes_ have fields of various kinds. More on this below.
+
+_Classes_ can also have zero, one, or more _object sets_ associated with them,
+and each object set has zero, one, or more _objects_ that are also themselves
+associated with classes. Each object has a setting for each required field of
+a class, and possibly also for optional/defaulted fields as well.
+
+As X.681 explains, IOS object sets really are akin to relational database
+tables, while objects are akin to rows of the same, with columns specified by
+classes.
+
+Or one can think of _classes_ as relational tables with one predefined column
+naming object sets, and rows being objects grouped into object sets by that
+column. IOS supports complex path expressions across these objects (but we
+won't need to support that yet).
+
+These relational entities are immutable in that they are defined in ASN.1
+modules that are compiled and there is no way to change them at run-time, only
+query them (although perhaps object sets marked as extensible are intended to
+be extensible at run-time?). To mutate them one must edit the ASN.1 module
+that defines them and recompile it. IOS entities also have no on-the-wire
+representation.
+
+So far, the IOS seems just so useless to us: we have some, but non-urgent need
+to specify immutable relational data. For example, cryptosystem parameters,
+which PKIX does define using IOS, but again: not urgent.
+
+The magic for us lies in being able to document and constrain actual datatypes
+using the IOS [X.681], constraint specification [X.682], and type
+parameterization [X.683]. We can express the following things:
+
+ - that some _member_ of a `SET` or `SEQUENCE` is of open type
+
+ - that some _member_ of a `SET` or `SEQUENCE` identifies a type encoded into
+ an open type member of the same (or related) `SET` or `SEQUENCE`
+
+ - what pairs of `{type ID value, type}` are allowed for some `SET`'s or
+ `SEQUENCE`'s open type members
+
+With this our ASN.1 compiler has the metadata it needs in order to
+auto-generate decoding and encoding of values of open types.
+
+A termnology point: `CHOICE`, `SET`, and `SEQUENCE` types have "members", but
+_classes_ and _objects_ have "fields", and _object sets_ have "elements".
+
+Objects must have "_settings_" for all the required fields of the object's
+class and none, some, or all of the `OPTIONAL` or `DEFAULT` fields of the
+class. This is very similar to `SET`/`SEQUENCE` members, which can be
+`OPTIONAL` or `DEFAULT`ed.
+
+The _members_ (we call them fields in C, instance variables in C++, Java, ...)
+of a `SET` or `SEQUENCE` type are typed, just as in C, C++, Java, etc. for
+struct or object types.
+
+There are several kinds of fields of classes. These can be confusing, so it is
+useful that we explain them by reference to how they relate to the members of
+`SEQUENCE` types constrained by object sets:
+
+ - A `type field` of a class is one that specifies a `SET` or `SEQUENCE` member
+ of unknown (i.e., open) type.
+
+ The type of that `SET` or `SEQUENCE` member will not be not truly unknown,
+ but determined by some other member of the SET or SEQUENCE, and that will be
+ specified in a "value field" (or "value set" field) an "object" in an
+ "object set" of that class.
+
+ This is essentially a "type variable", akin to those seen in high-level
+ languages like Haskell.
+
+ - A `fixed type value field` of a class is one that specifies a SET or
+ SEQUENCE member of fixed type. Being of fixed-type, this is not a type
+ variable, naturally.
+
+ - A `fixed type value set field` of a class is like a `fixed type value
+ field`, but where object sets should provide a set of values with which to
+ constrain `SET`/`SEQUENCE` members corresponding to the field.
+
+ - A `variable type value [set] field` is one where the type of the `SET` or
+ `SEQUENCE` member corresponding to the field will vary according to some
+ specified `type field` of the same class.
+
+ - An `object field` will be a field that names another class (possibly the
+ same class), which can be used to provide rich hierarchical type semantics
+ that... we mostly don't need for now.
+
+ These define relations between classes, much like `FOREIGN KEY`s in SQL.
+
+ These are also known as `link fields`.
+
+ - Similarly for `object set field`s.
+
+As usual for ASN.1, the case of the first letter of a field name is meaningful:
+
+ - value and object field names start with a lower case letter;
+ - type, value set, and object set fields start with an upper-case letter.
+
+The form of a `fixed type value` field and a `fixed type value set` field is
+the same, differing only the case of the first letter of the field name.
+Similarly for `variable type value` and `variable type value set` fields.
+Similarly, again, for `object` and `object set` fields.
+
+Here's a simple example from PKIX:
+
+```ASN.1
+ -- An IOS class used to impose constraints on the PKIX Extension type:
+ EXTENSION ::= CLASS {
+ &id OBJECT IDENTIFIER UNIQUE,
+ &ExtnType,
+ &Critical BOOLEAN DEFAULT {TRUE | FALSE }
+ } WITH SYNTAX {
+ SYNTAX &ExtnType IDENTIFIED BY &id
+ [CRITICALITY &Critical]
+ }
+```
+
+ - The `&id` field of `EXTENSION` is a fixed-type value field. It's not a
+ fixed-type value _set_ field because its identifier (`id`) starts with a
+ lower-case letter.
+
+ The `&id` field is intended to make the `extnId` member of the `Extension`
+ `SEQUENCE` type name identify the actual type of the `extnValue` member of
+ the same `SEQUENCE` type.
+
+ Note that `UNIQUE` keyword tells us there can be only one object with any
+ given value of this field in any object set of this class. (There is no way
+ to specify the equivalent of a multi-column `PRIMARY KEY` from SQL, only
+ single-column primary/unique keys. Note that the `&id` field is not marked
+ `OPTIONAL` or `DEFAULT`, which is like saying it's `NOT NULL` in SQL.)
+
+ - The `&ExtnType` field is a type field. We can tell because no type is named
+ in its declaration!
+
+ - The `&Critical` field is a fixed-type value set field. We can tell because
+ it specifies a type (`BOOLEAN`) and starts with an upper-case letter.
+
+ In-tree we could avoid having to implement fixed-type value set fields by
+ renaming this one to `&critical` and eliding its `DEFAULT <ValueSet>` given
+ that we know there are only two possible values for a `BOOLEAN` field.
+
+ - Ignore the `WITH SYNTAX` clause for now. All it does is specify a
+ user-friendly but implementor-hostile syntax for specifying objects.
+
+Note that none of the `Extension` extensions in PKIX actually specify
+`CRITICALITY`/`&Critical`, so... we just don't need fixed-type value set
+fields. We could elide the `&Critical` field of the `EXTENSION` class
+altogether.
+
+Here's another, much more complex example from PKIX:
+
+```ASN.1
+ ATTRIBUTE ::= CLASS {
+ &id OBJECT IDENTIFIER UNIQUE,
+ &Type OPTIONAL,
+ &equality-match MATCHING-RULE OPTIONAL,
+ &minCount INTEGER DEFAULT 1,
+ &maxCount INTEGER OPTIONAL
+ }
+ MATCHING-RULE ::= CLASS {
+ &ParentMatchingRules MATCHING-RULE OPTIONAL,
+ &AssertionType OPTIONAL,
+ &uniqueMatchIndicator ATTRIBUTE OPTIONAL,
+ &id OBJECT IDENTIFIER UNIQUE
+ }
+```
+
+ - For `ATTRIBUTE` the fields are:
+ - The `&id` field is a fixed-type value field (intended to name the type of
+ members linked to the `&Type` field).
+ - The `&Type` field is a type field (open type).
+ - The `&equality-match` is an object field linking to object sets of the
+ `MATCHING-RULE` class.
+ - The `minCount` and `maxCount` fields are fixed-type value fields.
+ - For `MATCHING-RULE` the fields are:
+ - The `&ParentMatchingRules` is an object set field linking to more
+ `MATCHING-RULE`s.
+ - The `&AssertionType` field is a type field (open type).
+ - The `&uniqueMatchIndicator` field is an object field linking back to some
+ object of the `ATTRIBUTE` class that indicates whether the match is
+ unique (presumably).
+ - The `&id` field is a fixed-type value field (intended to name the type of
+ members linked to the `&AssertionType` field).
+
+No `Attribute`s in PKIX (at least RFC 5912) specify matching rules, so we
+really don't need support for object nor object set fields.
+
+Because
+ - no objects in object sets of `EXTENSION` in PKIX specify "criticality",
+ - and no objects in object sets of `ATTRIBUTE` in PKIX specify matching rules,
+ - and no matching rules are specified in PKIX (or maybe just one),
+we can drop `MATCHING-RULE` and simplify `ATTRIBUTE` and `EXTENSION` as:
+
+```ASN.1
+ EXTENSION ::= CLASS {
+ &id OBJECT IDENTIFIER UNIQUE,
+ &ExtnType
+ }
+ ATTRIBUTE ::= CLASS {
+ &id OBJECT IDENTIFIER UNIQUE,
+ &Type OPTIONAL,
+ &minCount INTEGER DEFAULT 1,
+ &maxCount INTEGER OPTIONAL
+ }
+```
+
+X.681 has an example in appendix D.2 that has at least one field of every kind.
+
+Again, the rubber that are IOS classes and object sets meet the road when
+defining types:
+
+```ASN.1
+ -- Define the Extension type but link it to the EXTENSION class so that
+ -- an object set for that class can constrain it:
+ Extension{EXTENSION:ExtensionSet} ::= SEQUENCE {
+ extnID EXTENSION.&id({ExtensionSet}),
+ critical BOOLEAN
+ (EXTENSION.&Critical({ExtensionSet}{@extnID}))
+ DEFAULT FALSE,
+ extnValue OCTET STRING (CONTAINING
+ EXTENSION.&ExtnType({ExtensionSet}{@extnID}))
+ }
+ -- Most members of TBSCertificate elided for brevity:
+ TBSCertificate ::= SEQUENCE {
+ ...,
+ extensions [3] Extensions{{CertExtensions}} OPTIONAL
+ -- ^^^^^^^^^^^^^^^^
+ -- the rubber meets the road here!!
+ ...
+ }
+
+ OTHER-NAME ::= TYPE-IDENTIFIER
+ -- Most members of GeneralName elided for brevity:
+ GeneralName ::= CHOICE {
+ otherName [0] INSTANCE OF OTHER-NAME({KnownOtherNames}),
+ -- ^^^^^^^^^^^^^^^^^
+ -- rubber & road meet!
+ ...
+ }
+```
+
+(The `CertExtensions` and `KnownOtherNames` object sets are not shown here for
+brevity. PKIX doesn't even define an `KnownOtherNames` object set, though it
+well could.)
+
+The above demonstrates two ways to create `SEQUENCE` types that are constrained
+by IOS classes. One is by defining the types of the members of a `SEQUENCE`
+type by reference to class fields. The other is by using `INSTANCE OF` to say
+that the class defines the type directly. The first lets us do things like
+have a mix members of a `SEQUENCE` type where some are defined by relation to a
+class and others are not, or where multiple classes are used.
+
+In the case of `INSTANCE OF`, what shall the names of the members of the
+derived type be? Well, such types can _only_ be instances of `TYPE-IDENTIFIER`
+or classes copied from and isomorphic to it (as `OTHER-NAME` is in the above
+exammle), and so the names of their two members are just baked in by X.681
+annex C.1 as:
+
+```ASN.1
+ SEQUENCE {
+ type-id <DefinedObjectClass>.&id,
+ value[0] <DefinedObjectClass>.&Type
+ }
+ -- where <DefinedObjectClass> is the name of the class, which has to be
+ -- `TYPE-IDENTIFIER` or exactly like it.
+```
+
+(This means we can't use `INSTANCE OF` with `EXTENSION`, though we can for
+`OTHER-NAME`.)
+
+PKIX has much more complex classes for relating and constraining cryptographic
+algorithms and their parameters:
+
+ - `DIGEST-ALGORITHM`,
+ - `SIGNATURE-ALGORITHM`,
+ - `PUBLIC-KEY`,
+ - `KEY-TRANSPORT`,
+ - `KEY-AGREE`,
+ - `KEY-WRAP`,
+ - `KEY-DERIVATION`,
+ - `MAC-ALGORITHM`,
+ - `CONTENT-ENCRYPTION`,
+ - `ALGORITHM`,
+ - `SMIME-CAPS`,
+ - and `CURVE`.
+
+These show the value of just the relational data aspect of IOS. They can not
+only be used by the codecs at run-time to perform validation of, e.g.,
+cryptographic algorithm parameters, but also to provide those rules to other
+code in the application so that the programmer doesn't have to manually write
+the same in C, C++, Java, etc, and can refer to them when applying those
+cryptographic algorithms. And, of course, the object sets for the above
+classes can be and are specified in standards documents, making it very easy to
+import them into projects that have an IOS-capable ASN.1 compiler.
+
+Still, for Heimdal we won't bother with the full power of X.681/X.682/X.683 for
+now.
+
+## Usage
+
+To use this feature you must use the `--template` and `--one-code-file`
+arguments to `asn1_compile`. C types are generated from ASN.1 types as
+described above.
+
+Note that failure to decode open type values does not cause decoding to fail
+altogether. It is important that applications check for undecoded open types.
+Open type decoding failures manifest as `NULL` values for the `u` field of the
+decoded open type structures (see above).
+
+For examples of X.681/X.682/X.683 usage, look at `lib/asn1/rfc2459.asn1`.
+
+## Limitations
+
+ - `AtNotation` supported is very limited.
+
+ - Object set extensibility is not supported.
+
+ - Only one formal (and actual) type parameter is supported at this time.
+
+ - `TYPE-IDENTIFIER` is not built-in at this time. (But users can define it as
+ specified.)
+
+ - `CLASS` "copying" is not supported at this time.
+
+ - Link fields are not supported.
+
+ - `Information from objects` constructs are not supported.
+
+ - `IMPORTS` of IOS entities are not supported at this time.
+
+ - ...
+
+## Implementation Design
+
+NOTE: This has already be implemented in the `master` branch of Heimdal.
+
+ - The required specifications, X.681, X.682, and X.683, are fairly large and
+ non-trivial. We can implement just the subset of those three that we need
+ to implement PKIX, just as we already implement just the subset of X.680
+ that we need to implement PKIX and Kerberos.
+
+ For dealing with PKIX, the bare minimum of IOS classes we want are:
+
+ - `ATTRIBUTE` (used for `DN` attributes in RFC5280, specifically for the
+ `SingleAttribute` and `AttributeSet` types, RDNs, and the
+ `subjectDirectoryAttributes` extension)
+ - `EXTENSION` (used for `Extension`, i.e., certificate extensions in
+ RFC5280)
+ - `TYPE-IDENTIFIER` (used for `OtherName` and for CMS' `Content-Type`)
+
+ The minimal subset of X.681, X.682, and X.683 needed to implement those
+ three is all we need.
+
+ _Eventually_ we may want to increase that subset so as to implement other
+ IOS classes from PKIX, such as `DIGEST-ALGORITHM`, and to provide object
+ sets and query functionality for them to applications so that we can use
+ standard modules to encode information about cryptosystems. But not right
+ now.
+
+ Note that there's no object set specified for OTHER-NAME instances, but we
+ can and have creates our own. We want magic open type decoding to recurse
+ all the way down and handle DN attributes, extensions, SANs, policy
+ qualifiers, the works.
+
+ - We'll really want to do this mainly for the template compiler and begin
+ abandoning the original compiler. The codegen backend generates the same C
+ types, but no code for automatic, recursive handling of open types.
+
+ Maintaining two compiler backends is difficult enough; adding complex
+ features beyond X.680 to both is too much work. The template compiler is
+ simply superior just on account of its output size scaling as `O(N)` instead
+ of `O(M * N)` where `M` is the number of encoding rules supported and `N` is
+ the size of an ASN.1 module (or all modules).
+
+ - Also, to make the transition to using IOS in-tree, we'll want to keep
+ existing fields of C structures as generated by the compiler today, only
+ adding new ones, that way code that hasn't been updated to use the automatic
+ encoding/decoding can still work and we can then update Heimdal in-tree
+ slowly to take advantage of the new magic.
+
+ Below are the C types for the ASN.1 PKIX types we care about, as generated
+ by the current prototype.
+
+ `Extension` compiles to:
+
+```C
+typedef struct Extension {
+ heim_oid extnID;
+ int critical;
+ heim_octet_string extnValue;
+ /* NEW: */
+ struct {
+ enum {
+ choice_Extension_iosnumunknown = 0,
+ choice_Extension_iosnum_id_x509_ce_authorityKeyIdentifier,
+ choice_Extension_iosnum_id_x509_ce_subjectKeyIdentifier,
+ choice_Extension_iosnum_id_x509_ce_keyUsage,
+ choice_Extension_iosnum_id_x509_ce_privateKeyUsagePeriod,
+ choice_Extension_iosnum_id_x509_ce_certificatePolicies,
+ choice_Extension_iosnum_id_x509_ce_policyMappings,
+ choice_Extension_iosnum_id_x509_ce_subjectAltName,
+ choice_Extension_iosnum_id_x509_ce_issuerAltName,
+ choice_Extension_iosnum_id_x509_ce_basicConstraints,
+ choice_Extension_iosnum_id_x509_ce_nameConstraints,
+ choice_Extension_iosnum_id_x509_ce_policyConstraints,
+ choice_Extension_iosnum_id_x509_ce_extKeyUsage,
+ choice_Extension_iosnum_id_x509_ce_cRLDistributionPoints,
+ choice_Extension_iosnum_id_x509_ce_inhibitAnyPolicy,
+ choice_Extension_iosnum_id_x509_ce_freshestCRL,
+ choice_Extension_iosnum_id_pkix_pe_authorityInfoAccess,
+ choice_Extension_iosnum_id_pkix_pe_subjectInfoAccess,
+ } element;
+ union {
+ void *_any;
+ AuthorityKeyIdentifier* ext_AuthorityKeyIdentifier;
+ SubjectKeyIdentifier* ext_SubjectKeyIdentifier;
+ KeyUsage* ext_KeyUsage;
+ PrivateKeyUsagePeriod* ext_PrivateKeyUsagePeriod;
+ CertificatePolicies* ext_CertificatePolicies;
+ PolicyMappings* ext_PolicyMappings;
+ GeneralNames* ext_SubjectAltName;
+ GeneralNames* ext_IssuerAltName;
+ BasicConstraints* ext_BasicConstraints;
+ NameConstraints* ext_NameConstraints;
+ PolicyConstraints* ext_PolicyConstraints;
+ ExtKeyUsage* ext_ExtKeyUsage;
+ CRLDistributionPoints* ext_CRLDistributionPoints;
+ SkipCerts* ext_InhibitAnyPolicy;
+ CRLDistributionPoints* ext_FreshestCRL;
+ AuthorityInfoAccessSyntax* ext_AuthorityInfoAccess;
+ SubjectInfoAccessSyntax* ext_SubjectInfoAccessSyntax;
+ } u;
+ } _ioschoice_extnValue;
+} Extension;
+```
+
+ The `SingleAttribute` and `AttributeSet` types compile to:
+
+```C
+typedef struct SingleAttribute {
+ heim_oid type;
+ HEIM_ANY value;
+ struct {
+ enum {
+ choice_SingleAttribute_iosnumunknown = 0,
+ choice_SingleAttribute_iosnum_id_at_name,
+ choice_SingleAttribute_iosnum_id_at_surname,
+ choice_SingleAttribute_iosnum_id_at_givenName,
+ choice_SingleAttribute_iosnum_id_at_initials,
+ choice_SingleAttribute_iosnum_id_at_generationQualifier,
+ choice_SingleAttribute_iosnum_id_at_commonName,
+ choice_SingleAttribute_iosnum_id_at_localityName,
+ choice_SingleAttribute_iosnum_id_at_stateOrProvinceName,
+ choice_SingleAttribute_iosnum_id_at_organizationName,
+ choice_SingleAttribute_iosnum_id_at_organizationalUnitName,
+ choice_SingleAttribute_iosnum_id_at_title,
+ choice_SingleAttribute_iosnum_id_at_dnQualifier,
+ choice_SingleAttribute_iosnum_id_at_countryName,
+ choice_SingleAttribute_iosnum_id_at_serialNumber,
+ choice_SingleAttribute_iosnum_id_at_pseudonym,
+ choice_SingleAttribute_iosnum_id_domainComponent,
+ choice_SingleAttribute_iosnum_id_at_emailAddress,
+ } element;
+ union {
+ void *_any;
+ X520name* at_name;
+ X520name* at_surname;
+ X520name* at_givenName;
+ X520name* at_initials;
+ X520name* at_generationQualifier;
+ X520CommonName* at_x520CommonName;
+ X520LocalityName* at_x520LocalityName;
+ DirectoryString* at_x520StateOrProvinceName;
+ DirectoryString* at_x520OrganizationName;
+ DirectoryString* at_x520OrganizationalUnitName;
+ DirectoryString* at_x520Title;
+ heim_printable_string* at_x520dnQualifier;
+ heim_printable_string* at_x520countryName;
+ heim_printable_string* at_x520SerialNumber;
+ DirectoryString* at_x520Pseudonym;
+ heim_ia5_string* at_domainComponent;
+ heim_ia5_string* at_emailAddress;
+ } u;
+ } _ioschoice_value;
+} SingleAttribute;
+```
+
+ and
+
+```C
+typedef struct AttributeSet {
+ heim_oid type;
+ struct AttributeSet_values
+ {
+ unsigned int len;
+ HEIM_ANY* val;
+ } values;
+ struct {
+ enum {
+ choice_AttributeSet_iosnumunknown = 0,
+ choice_AttributeSet_iosnum_id_at_name,
+ choice_AttributeSet_iosnum_id_at_surname,
+ choice_AttributeSet_iosnum_id_at_givenName,
+ choice_AttributeSet_iosnum_id_at_initials,
+ choice_AttributeSet_iosnum_id_at_generationQualifier,
+ choice_AttributeSet_iosnum_id_at_commonName,
+ choice_AttributeSet_iosnum_id_at_localityName,
+ choice_AttributeSet_iosnum_id_at_stateOrProvinceName,
+ choice_AttributeSet_iosnum_id_at_organizationName,
+ choice_AttributeSet_iosnum_id_at_organizationalUnitName,
+ choice_AttributeSet_iosnum_id_at_title,
+ choice_AttributeSet_iosnum_id_at_dnQualifier,
+ choice_AttributeSet_iosnum_id_at_countryName,
+ choice_AttributeSet_iosnum_id_at_serialNumber,
+ choice_AttributeSet_iosnum_id_at_pseudonym,
+ choice_AttributeSet_iosnum_id_domainComponent,
+ choice_AttributeSet_iosnum_id_at_emailAddress,
+ } element;
+ unsigned int len;
+ union {
+ void *_any;
+ X520name* at_name;
+ X520name* at_surname;
+ X520name* at_givenName;
+ X520name* at_initials;
+ X520name* at_generationQualifier;
+ X520CommonName* at_x520CommonName;
+ X520LocalityName* at_x520LocalityName;
+ DirectoryString* at_x520StateOrProvinceName;
+ DirectoryString* at_x520OrganizationName;
+ DirectoryString* at_x520OrganizationalUnitName;
+ DirectoryString* at_x520Title;
+ heim_printable_string* at_x520dnQualifier;
+ heim_printable_string* at_x520countryName;
+ heim_printable_string* at_x520SerialNumber;
+ DirectoryString* at_x520Pseudonym;
+ heim_ia5_string* at_domainComponent;
+ heim_ia5_string* at_emailAddress;
+ } *val;
+ } _ioschoice_values;
+} AttributeSet;
+```
+
+ The `OtherName` type compiles to:
+
+```C
+typedef struct OtherName {
+ heim_oid type_id;
+ HEIM_ANY value;
+ struct {
+ enum {
+ choice_OtherName_iosnumunknown = 0,
+ choice_OtherName_iosnum_id_pkix_on_xmppAddr,
+ choice_OtherName_iosnum_id_pkix_on_dnsSRV,
+ choice_OtherName_iosnum_id_pkix_on_hardwareModuleName,
+ choice_OtherName_iosnum_id_pkix_on_permanentIdentifier,
+ choice_OtherName_iosnum_id_pkix_on_pkinit_san,
+ choice_OtherName_iosnum_id_pkix_on_pkinit_ms_san,
+ } element;
+ union {
+ void *_any;
+ heim_utf8_string* on_xmppAddr;
+ heim_ia5_string* on_dnsSRV;
+ HardwareModuleName* on_hardwareModuleName;
+ PermanentIdentifier* on_permanentIdentifier;
+ KRB5PrincipalName* on_krb5PrincipalName;
+ heim_utf8_string* on_pkinit_ms_san;
+ } u;
+ } _ioschoice_value;
+} OtherName;
+```
+
+ If a caller to `encode_Certificate()` passes a certificate object with
+ extensions with `_ioselement == choice_Extension_iosnumunknown` (or
+ whatever, for each open type), then the encoder will use the `extnID` and
+ `extnValue` fields, otherwise it will use the new `_ioschoice_extnValue`
+ field and leave `extnID` and `extnValue` cleared. If both are set, the
+ `extnID` and `extnValue` fields, and also the new `_ioschoice_extnValue`
+ field, then the encoder will ignore the latter.
+
+ In both cases, the `critical` field gets used as-is. The rule is be that we
+ support *two* special C struct fields for open types: a hole type ID enum
+ field, and a decoded hole value union. All other fields will map to either
+ normal (possibly constrained) members of the SET/SEQUENCE.
+
+ - Type ID values get mapped to discrete enum values. Object sets get sorted
+ by object type IDs so that for decoding they can be and are binary-searched.
+ For encoding and other cases (destructors and copy constructors) we directly
+ index the object set by the mapped type ID enum.
+
+ - The C header generator remains shared between the two backends.
+
+ - SET and SEQUENCE types containing an open type are represented as follows in
+ their templates.
+
+```C
+ extern const struct asn1_template asn1_CertExtensions[];
+ /*...*/
+ const struct asn1_template asn1_Extension_tag__22[] = {
+ /* 0 */ { 0, sizeof(struct Extension), ((void*)5) },
+ /* 1 */ { A1_TAG_T(ASN1_C_UNIV, PRIM, UT_OID),
+ offsetof(struct Extension, extnID),
+ asn1_AttributeType_tag__1 },
+ /* 2 */ { A1_OP_DEFVAL | A1_DV_BOOLEAN, ~0, (void*)0 },
+ /* 3 */ { A1_TAG_T(ASN1_C_UNIV, PRIM, UT_Boolean) | A1_FLAG_DEFAULT,
+ offsetof(struct Extension, critical),
+ asn1_Extension_tag_critical_24 },
+ /* 4 */ { A1_TAG_T(ASN1_C_UNIV, PRIM, UT_OctetString),
+ offsetof(struct Extension, extnValue),
+ asn1_Extension_tag_extnValue_25 },
+ /* NEW: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */
+ /* 5 */ { A1_OP_OPENTYPE_OBJSET | 0 | (2 << 10) | 0,
+ offsetof(Extension, _ioschoice_extnValue),
+ asn1_CertExtensions }
+ };
+ const struct asn1_template asn1_Extension[] = {
+ /* 0 */ { 0, sizeof(Extension), ((void*)1) },
+ /* 1 */ { A1_TAG_T(ASN1_C_UNIV, CONS, UT_Sequence),
+ 0, asn1_Extension_tag__22 }
+ };
+
+ /* NEW: */
+ const struct asn1_template asn1_CertExtensions[] = {
+ /*
+ * Header template entry bearing the count of objects in
+ * this object set:
+ */
+ /* 0 */ { 0, 0, ((void*)18) },
+
+ /*
+ * Value of object #0 in this set: two entries, one naming
+ * a type ID field value, and the other naming the type
+ * that corresponds to that value.
+ *
+ * In this case, the first object is for the
+ * AuthorityKeyIdentifier type as a certificate extension.
+ */
+ /* 1 */ { A1_OP_OPENTYPE_ID, 0,
+ (const void*)&asn1_oid_id_x509_ce_authorityKeyIdentifier },
+ /* 2 */ { A1_OP_OPENTYPE, sizeof(AuthorityKeyIdentifier),
+ (const void*)&asn1_AuthorityKeyIdentifier },
+
+ /* Value of object #1 (SubjectKeyIdentifier): */
+
+ /* 3 */ { A1_OP_OPENTYPE_ID, 0,
+ (const void*)&asn1_oid_id_x509_ce_subjectKeyIdentifier },
+ /* 4 */ { A1_OP_OPENTYPE, sizeof(SubjectKeyIdentifier),
+ (const void*)&asn1_SubjectKeyIdentifier },
+ /* 5 */
+
+ /* And so on...*/
+
+ /* Value of object #17 */
+ /* 35 */ { A1_OP_OPENTYPE_ID, 0,
+ (const void*)&asn1_oid_id_pkix_pe_subjectInfoAccess },
+ /* 36 */ { A1_OP_OPENTYPE, sizeof(SubjectInfoAccessSyntax),
+ (const void*)&asn1_SubjectInfoAccessSyntax }
+ };
+```
+
+ After the template entries for all the normal fields of a struct there will
+ be an object set reference entry identifying the type ID and open type
+ fields's entries' indices in the same template. The object set has a header
+ entry followed by pairs of entries each representing a single object and all
+ of them representing the object set.
+
+ This allows the encoder and decoder to both find the object set quickly,
+ especially since the objects are sorted by type ID value.
+
+## Moving From C
+
+ - Generate and output a JSON representation of the compiled ASN.1 module.
+
+ - Code codegen/templategen backends in jq or Haskell or whatever.
+
+ - Code template interpreters in &lt;host&gt; language.
+
+ - Eventually rewrite the compiler itself in Rust or whatever.
diff --git a/third_party/heimdal/lib/asn1/README-template.md b/third_party/heimdal/lib/asn1/README-template.md
new file mode 100644
index 0000000..9f1b60f
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/README-template.md
@@ -0,0 +1,278 @@
+
+#Notes on Heimdal's ASN.1 compiler's "template" backend
+
+```bash
+size .libs/libasn1.dylib
+size .libs/libasn1base.a | awk '{sum += $1} END {print sum}' | sed 's/^/TEXT baselib: /'
+size .libs/asn1_*.o | awk '{sum += $1} END {print sum}' | sed 's/^/generated code stubs: /'
+size *_asn1-template.o | awk '{sum += $1} END {print sum}' | sed 's/^/TEXT stubs: /'
+```
+
+Notes about the template parser:
+
+ - assumption: code is large, tables smaller
+
+ - size scales better as features as added:
+
+ - adding encoding rules, textual value parsers, comparators, and so on, are
+ just new template interpreter, and generally that means no change to
+ templates.
+
+ - so template sizing scales like `O(M + N)` where `M` is the size of the
+ modules and `N` is the size of the interpreters
+
+ - but codegen sizing scales like `O(M * N)`
+
+ - as we add interpreters the size advantage of templates increases
+
+ - smaller tables and code, more memory sharing, smaller cache footprint,
+ should lead to better performance
+
+ - templates are shared for encode/decode/free/copy/print interpreters,
+ whereas none of those operations as generated by the codegen backend
+ share any code
+
+ - very compressible -- we waste a lot of space in `struct asn1_template` on
+ 64-bit systems, and still it's smaller than the code generated by the
+ codegen backend
+
+ Note that the template backend does currently dedup templates, though that
+ is a quadratic operation that we may eventually have to make optional (right
+ now it's not a problem).
+
+ If we made the `ptr` field a `uint32_t` instead of a pointer, and wrote a
+ linker for templates, and squeezed out some bits of `tt` and `offset` (we'll
+ never need even 8 bits for tags, let alone 20!, and we'll never need 32 bits
+ for struct sizes and field offsets either, maybe not even 16-bits), we could
+ cut the size of `struct asn1_template` in half.
+
+ Also, once we add OER/JER we could have an option to not support TLV ERs and
+ then drop a lot of the tag-related parts of the minified AST that templates
+ are, further shrinking the templates.
+
+ The smaller the templates, the faster interpreting will be.
+
+ - use explicit stack instead of recursion in template interpreter to reduce
+ stack use and increase speed
+
+ The code generated by the codegen backend is also recursive, though the
+ compiler could inline some calls. Using an explicit stack in an iterative
+ interpreter would likely be a big win.
+
+ - how to generate template based stubs
+
+ (Note: it's now the default for Heimdal itself.)
+
+ Use the `--template` option to `asn1_compile` to use the template backend,
+ or leave it off to use the codegen backend.
+
+ - the template backend now has more functionality than the codegen backend
+
+ - much easier to extend! adding new encoding rules is just adding a few
+ functions to template.c, one set of length/encode/decode functions per ER,
+ so we could add OER/PER/XDR/GSER/JER with very little work outside that one
+ file and `gen_template.c` (to generate stub functions and possibly slight
+ alterations to templates) and gen.c (to generate declarations of those stub
+ functions).
+
+ - template decoding has been fuzzed extensively with American Fuzzy Lop (AFL)
+
+TODO:
+
+ - Generate templates for enumerations, with their names and values, so that
+ values of enumerated types can be printed.
+
+ - Remove old fuzzer. Rely on AFL only.
+
+ - Fuzzing tests, always more fuzzing:
+
+ - Instructions:
+
+```
+ $ git clone https://github.com/heimdal/heimdal
+ $ cd heimdal
+ $ srcdir=$PWD
+ $ autoreconf -fi
+ $
+ $ mkdir build
+ $ cd build
+ $
+ $ ../configure --srcdir=$srcdir ...
+ $ make -j4
+ $
+ $ cd lib/asn1
+ $ make clean
+ $ AFL_HARDEN=1 make -j4 asn1_print check CC=afl-gcc # or CC=afl-clang
+ $
+ $ # $srcdir/lib/asn1/fuzz-inputs/ has at least one minimized DER value
+ $ # produced by taking an EK certificate and truncating the signatureValue
+ $ # and tbsCertificate.subjectPublicKeyInfo fields then re-encoding, thus
+ $ # cutting down the size of the certificate by 45%. AFL finds interesting
+ $ # code paths much faster if the input corpus is minimized.
+ $
+ $ mkdir f
+ $ ../../libtool --mode=execute afl-fuzz -i $srcdir/lib/asn1/fuzz-inputs -o $PWD/f ./asn1_print '@@' Certificate
+ $
+ $ # Or
+ $ ../../libtool --mode=execute afl-fuzz -i $srcdir/lib/asn1/fuzz-inputs -o $PWD/f ./asn1_print -A '@@'
+ $
+ $ # Examine crash reports, if any. Each crash report consists of an input
+ $ # that caused a crash, so run valgrind on each such input:
+ $
+ $ for i in f/crashes/id*; do
+ > echo $i
+ > ../../libtool --mode=execute valgrind --num-callers=64 ./asn1_print $i \
+ > Certificate IOSCertificationRequest >/dev/null 2> f/crashes/vg-${i##*/}
+ > done
+ $
+ $ # then review the valgrind output:
+ $ $PAGER f/crashes/vg-*
+```
+
+ - Here's a screenshot of AFL running on the previous commit:
+
+```
+ american fuzzy lop 2.52b (asn1_print)
+
+┌─ process timing ─────────────────────────────────────┬─ overall results ─────┐
+│ run time : 1 days, 22 hrs, 39 min, 51 sec │ cycles done : 18 │
+│ last new path : 0 days, 0 hrs, 38 min, 5 sec │ total paths : 2310 │
+│ last uniq crash : none seen yet │ uniq crashes : 0 │
+│ last uniq hang : none seen yet │ uniq hangs : 0 │
+├─ cycle progress ────────────────────┬─ map coverage ─┴───────────────────────┤
+│ now processing : 997* (43.16%) │ map density : 2.19% / 8.74% │
+│ paths timed out : 0 (0.00%) │ count coverage : 3.25 bits/tuple │
+├─ stage progress ────────────────────┼─ findings in depth ────────────────────┤
+│ now trying : interest 16/8 │ favored paths : 319 (13.81%) │
+│ stage execs : 13.1k/13.4k (98.18%) │ new edges on : 506 (21.90%) │
+│ total execs : 91.9M │ total crashes : 0 (0 unique) │
+│ exec speed : 576.2/sec │ total tmouts : 2158 (180 unique) │
+├─ fuzzing strategy yields ───────────┴───────────────┬─ path geometry ────────┤
+│ bit flips : 565/5.60M, 124/5.60M, 74/5.59M │ levels : 19 │
+│ byte flips : 4/699k, 17/375k, 15/385k │ pending : 552 │
+│ arithmetics : 323/20.7M, 8/10.6M, 1/517k │ pend fav : 0 │
+│ known ints : 85/1.76M, 148/9.98M, 175/16.8M │ own finds : 2308 │
+│ dictionary : 0/0, 0/0, 12/6.62M │ imported : n/a │
+│ havoc : 757/6.35M, 0/0 │ stability : 100.00% │
+│ trim : 14.30%/336k, 46.60% ├────────────────────────┘
+└─────────────────────────────────────────────────────┘ [cpu000:196%]
+```
+
+ - TODO: Make building with AFL a ./cofigure option.
+
+ - TODO: Make fuzzing with AFL a make target.
+
+ - Fuzz decode round-tripping (don't just decode, but also encoded the
+ decoded).
+
+ - Performance testing
+
+ - `ASN1_MALLOC_ENCODE()` as a function, replaces `encode_` and `length_`
+
+ - Fix SIZE constraits
+
+ - Proper implementation of `SET { ... }`
+
+ - Compact types that only contain on entry to not having a header.
+
+
+SIZE - Futher down is later generations of the template parser
+
+```
+ code:
+ ==================
+ __TEXT __DATA __OBJC others dec hex
+ 462848 12288 0 323584 798720 c3000 (O2)
+
+ trivial types:
+ ==================
+ __TEXT __DATA __OBJC others dec hex
+ 446464 12288 0 323584 782336 bf000 (O2)
+
+ OPTIONAL
+ ==================
+ __TEXT __DATA __OBJC others dec hex
+ 425984 16384 0 323584 765952 bb000 (O2)
+
+ SEQ OF
+ ==================
+ __TEXT __DATA __OBJC others dec hex
+ 368640 32768 0 327680 729088 b2000 (O2)
+ 348160 32768 0 327680 708608 ad000 (Os)
+
+ BOOLEAN
+ ==================
+ 339968 32768 0 327680 700416 ab000 (Os)
+
+ TYPE_EXTERNAL:
+ ==================
+ 331776 32768 0 327680 692224 a9000 (Os)
+
+ SET OF
+ ==================
+ 327680 32768 0 327680 688128 a8000 (Os)
+
+ TYPE_EXTERNAL everywhere
+ ==================
+ __TEXT __DATA __OBJC others dec hex
+ 167936 69632 0 327680 565248 8a000 (Os)
+
+ TAG uses ->ptr (header and trailer)
+ ==================
+ 229376 102400 0 421888 753664 b8000 (O0)
+
+ TAG uses ->ptr (header only)
+ ==================
+ 221184 77824 0 421888 720896 b0000 (O0)
+
+ BER support for octet string (not working)
+ ==================
+ 180224 73728 0 417792 671744 a4000 (O2)
+
+ CHOICE and BIT STRING missign
+ ==================
+ __TEXT __DATA __OBJC others dec hex
+ 172032 73728 0 417792 663552 a2000 (Os)
+
+ No accessor functions to global variable
+ ==================
+ __TEXT __DATA __OBJC others dec hex
+ 159744 73728 0 393216 626688 99000 (Os)
+
+ All types tables (except choice) (id still objects)
+ ==================
+ __TEXT __DATA __OBJC others dec hex
+ 167936 77824 0 421888 667648 a3000
+ base lib: 22820
+
+ __TEXT __DATA __OBJC others dec hex
+ ==================
+ 167936 77824 0 421888 667648 a3000 (Os)
+ baselib: 22820
+ generated code stubs: 41472
+ TEXT stubs: 112560
+
+ All types, id still objects
+ ==================
+ __TEXT __DATA __OBJC others dec hex
+ 155648 81920 0 430080 667648 a3000 (Os)
+ TEXT baselib: 23166
+ generated code stubs: 20796
+ TEXT stubs: 119891
+
+ All types, id still objects, dup compression
+ ==================
+ __TEXT __DATA __OBJC others dec hex
+ 143360 65536 0 376832 585728 8f000 (Os)
+ TEXT baselib: 23166
+ generated code stubs: 20796
+ TEXT stubs: 107147
+
+ All types, dup compression, id vars
+ ==================
+ __TEXT __DATA __OBJC others dec hex
+ 131072 65536 0 352256 548864 86000
+ TEXT baselib: 23166
+ generated code stubs: 7536
+ TEXT stubs: 107147
+```
diff --git a/third_party/heimdal/lib/asn1/README.md b/third_party/heimdal/lib/asn1/README.md
new file mode 100644
index 0000000..9c4e697
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/README.md
@@ -0,0 +1,1327 @@
+# Heimdal's ASN.1 Compiler
+
+This is a new README, and it's not very rich in contents yet. Be sure to check
+out the [README on the template backend](/lib/asn1/README-template.md) and the [README
+on automatic open type decoding via X.681/X.682/X.683
+annotations](/lib/asn1/README-X681.md).
+
+## Table of Contents
+
+ 1. [Introduction](#Introduction)
+ 2. [ASN.1 Support in Heimdal](#asn1-support-in-heimdal)
+ 3. [News](#News)
+ 4. [Features](#Features)
+ 5. [Limitations](#Limitations)
+ 6. [Compiler Usage](#Compiler-usage)
+ 7. [APIs Generated by the Compiler](#APIs-generated-by-the-compiler)
+ 8. [`asn1_print` Usage](#asn1_print-usage)
+ 9. [Implementation](#implementation)
+ 10. [Moving From C](#moving-from-c)
+
+## Introduction
+
+ASN.1 is a... some would say baroque, perhaps obsolete, archaic even, "syntax"
+for expressing data type schemas, and also a set of "encoding rules" (ERs) that
+specify many ways to encode values of those types for interchange.
+
+Some ERs are binary, others are textual. Some binary ERs are tag-length-value
+(TLV), others have no need for tagging. Some of the ERs are roundly and
+rightly disliked, but then there are XER (XML Encoding Rules) and JER (JSON
+Encoding Rules) that really illustrate how the syntax and the encoding rules
+really are separate and distinct things.
+
+ASN.1 is a wheel that everyone loves to reinvent, and often badly. It's worth
+knowing a bit about it before reinventing this wheel badly yet again.
+
+It's also worth pondering that there appears to be ways to map most data
+exchange metaschemas and schemas onto others, and therefore too, transliterate
+most encodings onto others.
+
+First, an example of the syntax:
+
+```ASN.1
+-- This is what a certificate looks like (as in TLS server certificates, or
+-- "SSL certs):
+Certificate ::= SEQUENCE {
+ tbsCertificate TBSCertificate,
+ signatureAlgorithm AlgorithmIdentifier,
+ signatureValue BIT STRING
+}
+
+-- The main body of a certificate is here though:
+TBSCertificate ::= SEQUENCE {
+ version [0] Version DEFAULT 1,
+ serialNumber CertificateSerialNumber,
+ signature AlgorithmIdentifier,
+ issuer Name,
+ validity Validity,
+ subject Name,
+ subjectPublicKeyInfo SubjectPublicKeyInfo,
+ issuerUniqueID [1] IMPLICIT BIT STRING OPTIONAL,
+ subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL,
+ extensions [3] EXPLICIT Extensions OPTIONAL
+}
+```
+
+Here we see something akin to a "structure" or "record" with various named
+fields of various types. Some of these are optional, which means they can have
+no value given in encodings. One is defaulted, which means that if no values
+is given in encodings then the default value is intended.
+
+Those `[0]` things are called tags and are decidedly obsolete, along with all
+"tag-length-value" (TLV) or "self-describing" encoding rules. Tags appear as
+lexical tokens in ASN.1 only because a) in the early 80s TLV encodings were
+thought fantastic, and b) automatic tagging wasn't invented and implemented
+until it was too late. New ASN.1 modules should never need to have those tags
+appear in the syntax.
+
+ASN.1 has a lot of competition, and may even be obsolete. Obsolete
+technologies take decades to die out because of the need to interoperate with
+the installed base. So even if ASN.1 is obsolete, we find ourselves needing to
+implement a large subset of it in order to implement certain important network
+protocols.
+
+Encoding rules? There are many:
+
+ - JSON Encoding Rules (JER) ([X.697](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.697))
+
+ Use JSON instead of some binary scheme like DER (see below).
+
+ - XML Encoding Rules (XER) ([X.693](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.693))
+
+ - Generic String Encoding Rules (GSER) ([RFC3641](https://tools.ietf.org/html/rfc3641))
+
+ - Basic, Distinguished, and Canonical Encoding Rules (BER, DER, CER) ([X.690](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.690)
+
+ These are the dreaded tag-length-value encoding rules. They are redundant,
+ wasteful, and inefficient in spite of being non-textual (i.e., binary)!
+
+ The descriptor "tag-length-value" is due to all values being encoded as some
+ bytes for a "tag", then some bytes for the length of the encoded value, then
+ the encoded value itself. The body of a structured type (e.g.,
+ `Certificate`) is itself a concatenation of the TLV encodings of the fields
+ of that structured type, in order.
+
+ DER and CER are alternative canonical forms of BER.
+
+ - Packed Encoding Rules (PER) ([X.691](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.691)) and Octet Encoding Rules (OER) ([X.696](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.696))
+
+ These are a lot like eXternal Data Representation
+ ([XDR](https://tools.ietf.org/html/rfc4506.html)), but with 1-octet
+ alignment instead of 4-octet alignment.
+
+There is also a meta encoding rule system, the Encoding Control Notation (ECN)
+([X.692](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.692))
+intended to be able to express all sorts of kinds of encodings.
+
+Heimdal currently only supports DER for encoding, and DER and BER for decoding,
+but soon may support JER as well, and can print values as JSON, though not
+compliant with JER.
+
+The syntax itself is specified by
+[X.680](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.680),
+with extensions via
+[X.681](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.681),
+[X.682](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.682),
+and
+[X.683](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.683),.
+
+## ASN.1 Support in Heimdal
+
+Heimdal contains an implementation of:
+
+ - ASN.1
+ - PKIX
+ - Kerberos
+ - misc. Heimdal-specific protocols related to PKIX and Kerberos, such as:
+
+ - Online certification authority protocols
+ - Kerberos KDC replication protocols
+ - Kerberos administration protocols
+
+PKIX and Kerberos both require ASN.1 and DER support.
+
+For historical reasons many ASN.1-using projects have used hand-rolled codecs
+that have proven difficult to implement, maintain, and extend, and, of course,
+buggy. Heimdal has its own ASN.1 module compiler and library in order to avoid
+the pitfalls of hand-rolled codecs, and to satisfy Heimdal's internal needs.
+
+There are other ASN.1 compilers and libraries out there, of course, but it
+would prove difficult to switch compilers as generally ASN.1 compilers lack
+sufficient control over generated types and APIs for programming languages.
+
+Heimdal's ASN.1 compiler supports a large subset of X.680, X.681, X.682, and
+X.683, as well as a large subset of X.690, with an architecture that should
+make it easy to add support for encoding rules other than X.690.
+
+## News
+
+In recent times the following features have been added:
+
+ - Feature parity for the "template" backend, even superiority, as the codegen
+ backend does not yet support automatic open type decoding/encoding.
+
+ - IMPLICIT tagging support is finally complete.
+
+ - Automatic open type traversal, using a subset of X.681/X.682/X.683 for
+ expressing the requisite metadata.
+
+ - Decoration of ASN.1 types with "hidden" fields (ones that don't get encoded
+ or decoded) of ASN.1 or C types.
+
+## Futures
+
+ - JER support?
+
+ - XDR/NDR/OER support?
+
+ - Generate comparators? (lib/hx509 has a half-baked Certificate comparator)
+
+## Features
+
+ - Most of X.680 is supported.
+
+ - Most of X.690 is supported for decoding, with only DER supported for
+ encoding.
+
+ - For cryptographic applications there is a `--preserve-binary=TYPE` compiler
+ option that causes the `TYPE`'s C `struct` to gain a `_save` field where the
+ original encoding of the `TYPE` is preserved by the decoder. This allows
+ cryptographic applications to validate signatures, MACs, authenticated
+ decryption tags, checksums, etc., without having to re-encode the `TYPE`
+ (which wouldn't even work if the encoding received were BER and BER were
+ permitted for that `TYPE`).
+
+ - Unconstrained integer types have a large integer representation in C that is
+ not terribly useful in common cases. Range and member constraints on
+ integer types cause the compiler to use `int`, `int64_t`, `unsigned int`,
+ and/or `uint64_t` as appropriate.
+
+ - The Heimdal ASN.1 compiler currently handles a large subset of X.680, and
+ (in a branch) a small subset of X.681, X.682, and X.683, which manifests as
+ automatic handling of all open types contained in `SET`/`SEQUENCE` types
+ that are parameterized with information object sets. This allows all open
+ types in PKIX certificates, for example, to get decoded automatically no
+ matter how deeply nested. We use a TCG EK certificate that has eight
+ certificate extensions, including subject alternative names and subject
+ directory attributes where the attribute values are not string types, and
+ all of these things get decoded automatically.
+
+ - The template backend dedups templates to save space. This is an O(N^2) kind
+ of feature that we need to make optional, but it works. (When we implement
+ JER this will have the side-effect of printing the wrong type names in some
+ cases because two or more types have the same templates and get deduped.)
+
+ - There is an _experimental_ ASN.1 module -> JSON feature in the compiler. It
+ currently dumps type and value definitions, but not class, or object set
+ definitions. Even for types, it is not complete, and the JSON schema used
+ is subject to change *WITHOUT NOTICE*.
+
+ Perhaps eventually we can re-write the compiler as a C-coded ASN.1 -> JSON
+ stage followed by a jq-coded code and template generator state, which would
+ make it much easier to extend the compiler.
+
+ - We have an `asn1_print` program that can decode DER from any exported types
+ from any ASN.1 modules committed in Heimdal:
+
+ ```bash
+ $ ./asn1_print ek.crt Certificate |
+ jq '.tbsCertificate.extensions[3]._extnValue[]._values'
+ ```
+
+ ```JSON
+ [
+ {
+ "_type": "TPMSpecification",
+ "family": "2.0",
+ "level": 0,
+ "revision": 138
+ }
+ ]
+ [
+ {
+ "_type": "TPMSecurityAssertions",
+ "version": 0,
+ "fieldUpgradable": true,
+ "ekGenerationType": "ekgt-injected",
+ "ekGenerationLocation": "tpmManufacturer",
+ "ekCertificateGenerationLocation": "tpmManufacturer",
+ "ccInfo": {
+ "_type": "CommonCriteriaMeasures",
+ "version": "3.1",
+ "assurancelevel": "ealevel4",
+ "evaluationStatus": "evaluationCompleted",
+ "plus": true,
+ "strengthOfFunction": null,
+ "profileOid": null,
+ "profileUri": null,
+ "targetOid": null,
+ "targetUri": null
+ },
+ "fipsLevel": {
+ "_type": "FIPSLevel",
+ "version": "140-2",
+ "level": "sllevel2",
+ "plus": false
+ },
+ "iso9000Certified": false,
+ "iso9000Uri": null
+ }
+ ]
+ ```
+
+ A complete dump of such a certificate:
+
+ ```bash
+ $ ./asn1_print ek.crt Certificate | jq .
+ ```
+
+ ```JSON
+ {
+ "_type": "Certificate",
+ "tbsCertificate": {
+ "_type": "TBSCertificate",
+ "_save": "30820376A00302010202146A0597BA71D7E6D3AC0EDC9EDC95A15B998DE40A300D06092A864886F70D01010B05003055310B3009060355040613024348311E301C060355040A131553544D6963726F656C656374726F6E696373204E56312630240603550403131D53544D2054504D20454B20496E7465726D656469617465204341203035301E170D3138313231343030303030305A170D3238313231343030303030305A300030820122300D06092A864886F70D01010105000382010F003082010A0282010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E905B097012B5BDE50380C355B1A2A721BBC3D08DD21796CDB239FA95310651B1B56FD2CFE53C87352EBD996E33256160404CE9302A08066801E786A2F86E181F949966F492A85B58EAA4A6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E8F266BF1EA5EB271FDCF374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A294973FEDCCF0C340AFFD14B64F041165581ACA34147C1C75617047058F7ED7D603E032508094FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040FC1D2927C7657414490D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A18AFE59F9D6F149744E5F0D559B10203010001A38201A9308201A5301F0603551D230418301680141ADB994AB58BE57A0CC9B900E7851E1A43C0866030420603551D20043B303930370604551D2000302F302D06082B060105050702011621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F30590603551D110101FF044F304DA44B304931163014060567810502010C0B69643A353335343444323031173015060567810502020C0C53543333485450484148433031163014060567810502030C0B69643A303034393030303830670603551D090460305E301706056781050210310E300C0C03322E300201000202008A304306056781050212313A30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100300E0603551D0F0101FF040403020520300C0603551D130101FF0402300030100603551D250409300706056781050801304A06082B06010505070101043E303C303A06082B06010505073002862E687474703A2F2F7365637572652E676C6F62616C7369676E2E636F6D2F73746D74706D656B696E7430352E637274",
+ "version": "rfc3280_version_3",
+ "serialNumber": "6A0597BA71D7E6D3AC0EDC9EDC95A15B998DE40A",
+ "signature": {
+ "_type": "AlgorithmIdentifier",
+ "algorithm": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "1.2.840.113549.1.1.11",
+ "components": [
+ 1,
+ 2,
+ 840,
+ 113549,
+ 1,
+ 1,
+ 11
+ ],
+ "name": "id-pkcs1-sha256WithRSAEncryption"
+ },
+ "parameters": "0500"
+ },
+ "issuer": {
+ "_choice": "rdnSequence",
+ "value": [
+ [
+ {
+ "_type": "AttributeTypeAndValue",
+ "type": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.5.4.6",
+ "components": [
+ 2,
+ 5,
+ 4,
+ 6
+ ],
+ "name": "id-at-countryName"
+ },
+ "value": {
+ "_choice": "printableString",
+ "value": "CH"
+ }
+ }
+ ],
+ [
+ {
+ "_type": "AttributeTypeAndValue",
+ "type": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.5.4.10",
+ "components": [
+ 2,
+ 5,
+ 4,
+ 10
+ ],
+ "name": "id-at-organizationName"
+ },
+ "value": {
+ "_choice": "printableString",
+ "value": "STMicroelectronics NV"
+ }
+ }
+ ],
+ [
+ {
+ "_type": "AttributeTypeAndValue",
+ "type": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.5.4.3",
+ "components": [
+ 2,
+ 5,
+ 4,
+ 3
+ ],
+ "name": "id-at-commonName"
+ },
+ "value": {
+ "_choice": "printableString",
+ "value": "STM TPM EK Intermediate CA 05"
+ }
+ }
+ ]
+ ]
+ },
+ "validity": {
+ "_type": "Validity",
+ "notBefore": {
+ "_choice": "utcTime",
+ "value": "2018-12-14T00:00:00Z"
+ },
+ "notAfter": {
+ "_choice": "utcTime",
+ "value": "2028-12-14T00:00:00Z"
+ }
+ },
+ "subject": {
+ "_choice": "rdnSequence",
+ "value": []
+ },
+ "subjectPublicKeyInfo": {
+ "_type": "SubjectPublicKeyInfo",
+ "algorithm": {
+ "_type": "AlgorithmIdentifier",
+ "algorithm": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "1.2.840.113549.1.1.1",
+ "components": [
+ 1,
+ 2,
+ 840,
+ 113549,
+ 1,
+ 1,
+ 1
+ ],
+ "name": "id-pkcs1-rsaEncryption"
+ },
+ "parameters": "0500"
+ },
+ "subjectPublicKey": "2160:3082010A0282010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E905B097012B5BDE50380C355B1A2A721BBC3D08DD21796CDB239FA95310651B1B56FD2CFE53C87352EBD996E33256160404CE9302A08066801E786A2F86E181F949966F492A85B58EAA4A6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E8F266BF1EA5EB271FDCF374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A294973FEDCCF0C340AFFD14B64F041165581ACA34147C1C75617047058F7ED7D603E032508094FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040FC1D2927C7657414490D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A18AFE59F9D6F149744E5F0D559B10203010001"
+ },
+ "issuerUniqueID": null,
+ "subjectUniqueID": null,
+ "extensions": [
+ {
+ "_type": "Extension",
+ "extnID": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.5.29.35",
+ "components": [
+ 2,
+ 5,
+ 29,
+ 35
+ ],
+ "name": "id-x509-ce-authorityKeyIdentifier"
+ },
+ "critical": false,
+ "extnValue": "301680141ADB994AB58BE57A0CC9B900E7851E1A43C08660",
+ "_extnValue_choice": "ext-AuthorityKeyIdentifier",
+ "_extnValue": {
+ "_type": "AuthorityKeyIdentifier",
+ "keyIdentifier": "1ADB994AB58BE57A0CC9B900E7851E1A43C08660",
+ "authorityCertIssuer": null,
+ "authorityCertSerialNumber": null
+ }
+ },
+ {
+ "_type": "Extension",
+ "extnID": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.5.29.32",
+ "components": [
+ 2,
+ 5,
+ 29,
+ 32
+ ],
+ "name": "id-x509-ce-certificatePolicies"
+ },
+ "critical": false,
+ "extnValue": "303930370604551D2000302F302D06082B060105050702011621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F",
+ "_extnValue_choice": "ext-CertificatePolicies",
+ "_extnValue": [
+ {
+ "_type": "PolicyInformation",
+ "policyIdentifier": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.5.29.32.0",
+ "components": [
+ 2,
+ 5,
+ 29,
+ 32,
+ 0
+ ],
+ "name": "id-x509-ce-certificatePolicies-anyPolicy"
+ },
+ "policyQualifiers": [
+ {
+ "_type": "PolicyQualifierInfo",
+ "policyQualifierId": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "1.3.6.1.5.5.7.2.1",
+ "components": [
+ 1,
+ 3,
+ 6,
+ 1,
+ 5,
+ 5,
+ 7,
+ 2,
+ 1
+ ],
+ "name": "id-pkix-qt-cps"
+ },
+ "qualifier": "1621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_type": "Extension",
+ "extnID": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.5.29.17",
+ "components": [
+ 2,
+ 5,
+ 29,
+ 17
+ ],
+ "name": "id-x509-ce-subjectAltName"
+ },
+ "critical": true,
+ "extnValue": "304DA44B304931163014060567810502010C0B69643A353335343444323031173015060567810502020C0C53543333485450484148433031163014060567810502030C0B69643A3030343930303038",
+ "_extnValue_choice": "ext-SubjectAltName",
+ "_extnValue": [
+ {
+ "_choice": "directoryName",
+ "value": {
+ "_choice": "rdnSequence",
+ "value": [
+ [
+ {
+ "_type": "AttributeTypeAndValue",
+ "type": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.23.133.2.1",
+ "components": [
+ 2,
+ 23,
+ 133,
+ 2,
+ 1
+ ],
+ "name": "tcg-at-tpmManufacturer"
+ },
+ "value": {
+ "_choice": "utf8String",
+ "value": "id:53544D20"
+ }
+ }
+ ],
+ [
+ {
+ "_type": "AttributeTypeAndValue",
+ "type": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.23.133.2.2",
+ "components": [
+ 2,
+ 23,
+ 133,
+ 2,
+ 2
+ ],
+ "name": "tcg-at-tpmModel"
+ },
+ "value": {
+ "_choice": "utf8String",
+ "value": "ST33HTPHAHC0"
+ }
+ }
+ ],
+ [
+ {
+ "_type": "AttributeTypeAndValue",
+ "type": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.23.133.2.3",
+ "components": [
+ 2,
+ 23,
+ 133,
+ 2,
+ 3
+ ],
+ "name": "tcg-at-tpmVersion"
+ },
+ "value": {
+ "_choice": "utf8String",
+ "value": "id:00490008"
+ }
+ }
+ ]
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "_type": "Extension",
+ "extnID": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.5.29.9",
+ "components": [
+ 2,
+ 5,
+ 29,
+ 9
+ ],
+ "name": "id-x509-ce-subjectDirectoryAttributes"
+ },
+ "critical": false,
+ "extnValue": "305E301706056781050210310E300C0C03322E300201000202008A304306056781050212313A30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100",
+ "_extnValue_choice": "ext-SubjectDirectoryAttributes",
+ "_extnValue": [
+ {
+ "_type": "AttributeSet",
+ "type": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.23.133.2.16",
+ "components": [
+ 2,
+ 23,
+ 133,
+ 2,
+ 16
+ ],
+ "name": "tcg-at-tpmSpecification"
+ },
+ "values": [
+ "300C0C03322E300201000202008A"
+ ],
+ "_values_choice": "at-TPMSpecification",
+ "_values": [
+ {
+ "_type": "TPMSpecification",
+ "family": "2.0",
+ "level": 0,
+ "revision": 138
+ }
+ ]
+ },
+ {
+ "_type": "AttributeSet",
+ "type": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.23.133.2.18",
+ "components": [
+ 2,
+ 23,
+ 133,
+ 2,
+ 18
+ ],
+ "name": "tcg-at-tpmSecurityAssertions"
+ },
+ "values": [
+ "30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100"
+ ],
+ "_values_choice": "at-TPMSecurityAssertions",
+ "_values": [
+ {
+ "_type": "TPMSecurityAssertions",
+ "version": 0,
+ "fieldUpgradable": true,
+ "ekGenerationType": "ekgt-injected",
+ "ekGenerationLocation": "tpmManufacturer",
+ "ekCertificateGenerationLocation": "tpmManufacturer",
+ "ccInfo": {
+ "_type": "CommonCriteriaMeasures",
+ "version": "3.1",
+ "assurancelevel": "ealevel4",
+ "evaluationStatus": "evaluationCompleted",
+ "plus": true,
+ "strengthOfFunction": null,
+ "profileOid": null,
+ "profileUri": null,
+ "targetOid": null,
+ "targetUri": null
+ },
+ "fipsLevel": {
+ "_type": "FIPSLevel",
+ "version": "140-2",
+ "level": "sllevel2",
+ "plus": false
+ },
+ "iso9000Certified": false,
+ "iso9000Uri": null
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_type": "Extension",
+ "extnID": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.5.29.15",
+ "components": [
+ 2,
+ 5,
+ 29,
+ 15
+ ],
+ "name": "id-x509-ce-keyUsage"
+ },
+ "critical": true,
+ "extnValue": "03020520",
+ "_extnValue_choice": "ext-KeyUsage",
+ "_extnValue": [
+ "keyEncipherment"
+ ]
+ },
+ {
+ "_type": "Extension",
+ "extnID": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.5.29.19",
+ "components": [
+ 2,
+ 5,
+ 29,
+ 19
+ ],
+ "name": "id-x509-ce-basicConstraints"
+ },
+ "critical": true,
+ "extnValue": "3000",
+ "_extnValue_choice": "ext-BasicConstraints",
+ "_extnValue": {
+ "_type": "BasicConstraints",
+ "cA": false,
+ "pathLenConstraint": null
+ }
+ },
+ {
+ "_type": "Extension",
+ "extnID": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.5.29.37",
+ "components": [
+ 2,
+ 5,
+ 29,
+ 37
+ ],
+ "name": "id-x509-ce-extKeyUsage"
+ },
+ "critical": false,
+ "extnValue": "300706056781050801",
+ "_extnValue_choice": "ext-ExtKeyUsage",
+ "_extnValue": [
+ {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "2.23.133.8.1",
+ "components": [
+ 2,
+ 23,
+ 133,
+ 8,
+ 1
+ ],
+ "name": "tcg-kp-EKCertificate"
+ }
+ ]
+ },
+ {
+ "_type": "Extension",
+ "extnID": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "1.3.6.1.5.5.7.1.1",
+ "components": [
+ 1,
+ 3,
+ 6,
+ 1,
+ 5,
+ 5,
+ 7,
+ 1,
+ 1
+ ],
+ "name": "id-pkix-pe-authorityInfoAccess"
+ },
+ "critical": false,
+ "extnValue": "303C303A06082B06010505073002862E687474703A2F2F7365637572652E676C6F62616C7369676E2E636F6D2F73746D74706D656B696E7430352E637274",
+ "_extnValue_choice": "ext-AuthorityInfoAccess",
+ "_extnValue": [
+ {
+ "_type": "AccessDescription",
+ "accessMethod": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "1.3.6.1.5.5.7.48.2",
+ "components": [
+ 1,
+ 3,
+ 6,
+ 1,
+ 5,
+ 5,
+ 7,
+ 48,
+ 2
+ ],
+ "name": "id-pkix-ad-caIssuers"
+ },
+ "accessLocation": {
+ "_choice": "uniformResourceIdentifier",
+ "value": "http://secure.globalsign.com/stmtpmekint05.crt"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "signatureAlgorithm": {
+ "_type": "AlgorithmIdentifier",
+ "algorithm": {
+ "_type": "OBJECT IDENTIFIER",
+ "oid": "1.2.840.113549.1.1.11",
+ "components": [
+ 1,
+ 2,
+ 840,
+ 113549,
+ 1,
+ 1,
+ 11
+ ],
+ "name": "id-pkcs1-sha256WithRSAEncryption"
+ },
+ "parameters": "0500"
+ },
+ "signatureValue": "2048:3D4C381E5B4F1BCBE09C63D52F1F04570CAEA142FD9CD942043B11F8E3BDCF50007AE16CF8869013041E92CDD3280BA4B51FBBD40582ED750219E261A695095674855AACEB520ADAFF9E7E908480A39CDCF900462D9171960FFE55D3AC49E8C981341BBD2EFBCC252A4C18A4F3B7C84CCE42CE70A208C84D2630A7ABFBE72D6271E75B9FF1C971D20EB3DBD763F1E04D834EAA692D2E4001BBF4730A3E3FDA9711AE386524D91C63BE0E516D00D5C6141FCCF6C539F3518E180049865BE16B69CAE1F8CB7FDC474B38F7EE56CBE7D8A89D9BA99B65D5265AEF32AA62426B10E6D75BB8677EC44F755BBC2806FD2B4E04BDF5D44259DBEAA42B6F563DF7AA7506"
+ }
+ ```
+
+ (Notice that OID names look a bit weird. For reasons that may have been
+ lost to time and may no longer be relevant, these OIDs are defined with
+ slightly different names in the ASN.1 modules in Heimdal's source tree.
+ We'll fix this eventually.)
+
+...
+
+## Limitations
+
+ - `libasn1`'s and, therefore, `asn1_print`'s JSON support is not X.697 (JER)
+ compatible.
+
+ - Control over C types generated is very limited, mainly only for integer
+ types.
+
+ - When using the template backend, `SET { .. }` types are currently not sorted
+ by tag as they should be, but if the module author sorts them by hand then
+ DER will be produced.
+
+ - `REAL` is not supported.
+
+ - `EmbeddedPDV` is not supported.
+
+ - `BMPString` is not supported.
+
+ - IA5String is not properly supported -- it's essentially treated as a
+ `UTF8String` with a different tag. This is true of all the string types.
+
+ - Only types can be imported at this time. Without some rototilling we likely
+ will not be able to import anything other than types, values, and object
+ sets.
+
+ - Only simple value syntax is supported. Constructed value syntax (i.e.,
+ values of `SET`, `SEQUENCE`, `SET OF`, and `SEQUENCE OF`), is not supported.
+ Values of `CHOICE` types are also not supported.
+
+ - There is no way to substitute object sets at run-time. This means that
+ automatic decoding through open types will spend more CPU cycles than the
+ application might want, by decoding more types than the application might
+ care about. The ability to substitute object sets at run-time would require
+ a change to the APIs generated.
+
+ - ...
+
+## Compiler Usage
+
+The various options for the Heimdal ASN.1 compiler are described in its manual
+page, which is included below.
+
+The `--option-file=FILE` option is particularly useful, as it allows additional
+compiler options to be read from a file.
+
+The `--preserve-binary=TYPE-NAME` option is critical for signature validation
+as it causes the decoder to save the encoding of the given type so that
+signature validation code can easily find the original encoding and thus avoid
+having to re-encode or resort to other hacks. E.g., we use this for preserving
+the original encoding of the `tbsCertificate` field of `Certificate`.
+
+The `--sequence=TYPE-NAME` causes the compiler to generate additional utility
+functions for adding or removing items from the named type when it is a
+`SEQUENCE OF` or `SET OF` type.
+
+See the manual page `asn1_compile.1`:
+
+```text
+ASN1_COMPILE(1) BSD General Commands Manual ASN1_COMPILE(1)
+
+NAME
+ asn1_compile — compile ASN.1 modules
+
+SYNOPSIS
+ asn1_compile [--template] [--prefix-enum] [--enum-prefix=PREFIX]
+ [--encode-rfc1510-bit-string] [--decode-dce-ber]
+ [--support-ber] [--preserve-binary=TYPE] [--sequence=TYPE]
+ [--decorate=DECORATION] [--one-code-file] [--gen-name=NAME]
+ [--option-file=FILE] [--original-order] [--no-parse-units]
+ [--type-file=C-HEADER-FILE] [--version] [--help]
+ [FILE.asn1 [NAME]]
+
+DESCRIPTION
+ asn1_compile compiles an ASN.1 module into C source code and header
+ files.
+
+ A fairly large subset of ASN.1 as specified in X.680, and the ASN.1 In‐
+ formation Object System as specified in X.681, X.682, and X.683 is sup‐
+ ported, with support for the Distinguished Encoding Rules (DER), partial
+ Basic Encoding Rules (BER) support, and experimental JSON support (encod‐
+ ing only at this time).
+
+ See the compiler's README files for details about the C code and inter‐
+ faces it generates.
+
+ The Information Object System support includes automatic codec support
+ for encoding and decoding through “open types” which are also known as
+ “typed holes”. See RFC 5912 for examples of how to use the ASN.1 Infor‐
+ mation Object System via X.681/X.682/X.683 annotations. See the com‐
+ piler's README files for more information on ASN.1 Information Object
+ System support.
+
+ Extensions specific to Heimdal are generally not syntactic in nature but
+ rather command-line options to this program. For example, one can use
+ command-line options to:
+ • enable decoding of BER-encoded values;
+ • enable RFC1510-style handling of ‘BIT STRING’ types;
+ • enable saving of as-received encodings of specific types
+ for the purpose of signature validation;
+ • generate add/remove utility functions for array types;
+ • decorate generated ‘struct’ types with fields that are nei‐
+ ther encoded nor decoded;
+ etc.
+
+ ASN.1 x.680 features supported:
+ • most primitive types (except BMPString and REAL);
+ • all constructed types, including SET and SET OF;
+ • explicit and implicit tagging.
+
+ Size and range constraints on the ‘INTEGER’ type cause the compiler to
+ generate appropriate C types such as ‘int’, ‘unsigned int’, ‘int64_t’,
+ ‘uint64_t’. Unconstrained ‘INTEGER’ is treated as ‘heim_integer’, which
+ represents an integer of arbitrary size.
+
+ Caveats and ASN.1 x.680 features not supported:
+ • JSON encoding support is not quite X.697 (JER) compatible.
+ Its JSON schema is subject to change without notice.
+ • Control over C types generated is very limited, mainly only
+ for integer types.
+ • When using the template backend, `SET { .. }` types are
+ currently not sorted by tag as they should be, but if the
+ module author sorts them by hand then correct DER will be
+ produced.
+ • ‘AUTOMATIC TAGS’ is not supported.
+ • The REAL type is not supported.
+ • The EmbeddedPDV type is not supported.
+ • The BMPString type is not supported.
+ • The IA5String is not properly supported, as it's essen‐
+ tially treated as a UTF8String with a different tag.
+ • All supported non-octet strings are treated as like the
+ UTF8String type.
+ • Only types can be imported into ASN.1 modules at this time.
+ • Only simple value syntax is supported. Constructed value
+ syntax (i.e., values of SET, SEQUENCE, SET OF, and SEQUENCE
+ OF types), is not supported. Values of `CHOICE` types are
+ also not supported.
+
+ Options supported:
+
+ --template
+ Use the “template” backend instead of the “codegen” backend
+ (which is the default backend).
+
+ The template backend generates “templates” which are akin to
+ bytecode, and which are interpreted at run-time.
+
+ The codegen backend generates C code for all functions directly,
+ with no template interpretation.
+
+ The template backend scales better than the codegen backend be‐
+ cause as we add support for more encoding rules and more opera‐
+ tions (we may add value comparators) the templates stay mostly
+ the same, thus scaling linearly with size of module. Whereas the
+ codegen backend scales linear with the product of module size and
+ number of encoding rules supported.
+
+ --prefix-enum
+ This option should be removed because ENUMERATED types should al‐
+ ways have their labels prefixed.
+
+ --enum-prefix=PREFIX
+ This option should be removed because ENUMERATED types should al‐
+ ways have their labels prefixed.
+
+ --encode-rfc1510-bit-string
+ Use RFC1510, non-standard handling of “BIT STRING” types.
+
+ --decode-dce-ber
+
+ --support-ber
+
+ --preserve-binary=TYPE
+ Generate a field named ‘_save’ in the C struct generated for the
+ named TYPE. This field is used to preserve the original encoding
+ of the value of the TYPE.
+
+ This is useful for cryptographic applications so that they can
+ check signatures of encoded values as-received without having to
+ re-encode those values.
+
+ For example, the TBSCertificate type should have values preserved
+ so that Certificate validation can check the signatureValue over
+ the tbsCertificate's value as-received.
+
+ The alternative of encoding a value to check a signature of it is
+ brittle. For types where non-canonical encodings (such as BER)
+ are allowed, this alternative is bound to fail. Thus the point
+ of this option.
+
+ --sequence=TYPE
+ Generate add/remove functions for the named ASN.1 TYPE which must
+ be a ‘SET OF’ or ‘SEQUENCE OF’ type.
+
+ --decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?]
+ Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
+ or CHOICE type named ASN1-TYPE a “hidden” field named fname of
+ the given ASN.1 type FIELD-ASN1-TYPE, but do not encode or decode
+ it. If the fname ends in a question mark, then treat the field
+ as OPTIONAL.
+
+ This is useful for adding fields to existing types that can be
+ used for internal bookkeeping but which do not affect interoper‐
+ ability because they are neither encoded nor decoded. For exam‐
+ ple, one might decorate a request type with state needed during
+ processing of the request.
+
+ --decorate=ASN1-TYPE:void*:fname
+ Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
+ or CHOICE type named ASN1-TYPE a “hidden” field named fname of
+ type ‘void *’ (but do not encode or decode it.
+
+ The destructor and copy constructor functions generated by this
+ compiler for ASN1-TYPE will set this field to the ‘NULL’ pointer.
+
+ --decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header
+ Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
+ or CHOICE type named ASN1-TYPE a “hidden” field named fname of
+ the given external C type FIELD-C-TYPE, declared in the given
+ header but do not encode or decode this field. If the fname ends
+ in a question mark, then treat the field as OPTIONAL.
+
+ The header must include double quotes or angle brackets. The
+ copyfn must be the name of a copy constructor function that takes
+ a pointer to a source value of the type, and a pointer to a des‐
+ tination value of the type, in that order, and which returns zero
+ on success or else a system error code on failure. The freefn
+ must be the name of a destructor function that takes a pointer to
+ a value of the type and which releases resources referenced by
+ that value, but does not free the value itself (the run-time al‐
+ locates this value as needed from the C heap). The freefn should
+ also reset the value to a pristine state (such as all zeros).
+
+ If the copyfn and freefn are empty strings, then the decoration
+ field will neither be copied nor freed by the functions generated
+ for the TYPE.
+
+ --one-code-file
+ Generate a single source code file. Otherwise a separate code
+ file will be generated for every type.
+
+ --gen-name=NAME
+ Use NAME to form the names of the files generated.
+
+ --option-file=FILE
+ Take additional command-line options from FILE.
+
+ --original-order
+ Attempt to preserve the original order of type definition in the
+ ASN.1 module. By default the compiler generates types in a topo‐
+ logical sort order.
+
+ --no-parse-units
+ Do not generate to-int / from-int functions for enumeration
+ types.
+
+ --type-file=C-HEADER-FILE
+ Generate an include of the named header file that might be needed
+ for common type defintions.
+
+ --version
+
+ --help
+
+NOTES
+ Currently only the template backend supports automatic encoding and de‐
+ coding of open types via the ASN.1 Information Object System and
+ X.681/X.682/X.683 annotations.
+
+HEIMDAL February 22, 2021 HEIMDAL
+```
+
+## APIs Generated by the Compiler
+
+Every named type in an ASN.1 module gets a corresponding type in C.
+Em-dashes in symbols become underscores.
+
+Every named type in an ASN.1 module also gets several functions generated
+associated with it:
+
+ - `int decode_TypeName(const unsigned char *, size_t, TypeName *, size_t *);`
+
+ Decodes a value of `TypeName` in the given byte array of the given size,
+ into the given `TypeName` object, and outputs the number of bytes parsed.
+
+ Returns 0 on success, or an error that can be formatted as a string using
+ the `com_err` library.
+
+ - `int encode_TypeName(unsigned char *, size_t, const TypeName *, size_t *);`
+
+ Encodes the given object of `TypeName` type into the given byte array of the
+ given size, outputting the number of bytes used.
+
+ NOTE WELL: the `unsigned char *` pointer must point to the _last_ byte of
+ the buffer!
+
+ Returns 0 on success, or an error that can be formatted as a string using
+ the `com_err` library, including system errors such as `ENOMEM`.
+
+ - `int length_TypeName(const TypeName *);`
+
+ Returns the number of bytes needed to encode the given object.
+
+ - `void free_TypeName(TypeName *);`
+
+ Releases the memory associated with the content of the given object, but
+ note that the object itself is _not_ released.
+
+ - `int copy_TypeName(const TypeName *, TypeName *);`
+
+ Copies the content of the given `const` object to the destination,
+ non-`const` object.
+
+ Returns 0 on success, or an error that can be formatted as a string using
+ the `com_err` library, including system errors such as `ENOMEM`.
+
+ - `char *print_TypeName(const TypeName *, int);`
+
+ Returns a string (JSON) representation of the given object. The `int`
+ argument is a bitset of flags:
+
+ - `ASN1_PRINT_INDENT`
+
+ Indent the JSON. If not given the the JSON will have no interstitial
+ whitespace, including newlines.
+
+You will want to review the data structures generated. They look like:
+
+```C
+ typedef struct TBSCertificate TBSCertificate;
+ typedef struct AlgorithmIdentifier AlgorithmIdentifier;
+ typedef struct ... ...;
+
+ /*
+ Certificate ::= SEQUENCE {
+ tbsCertificate TBSCertificate,
+ signatureAlgorithm AlgorithmIdentifier,
+ signatureValue BIT STRING {
+ },
+ }
+ */
+
+ typedef struct Certificate {
+ TBSCertificate tbsCertificate;
+ AlgorithmIdentifier signatureAlgorithm;
+ heim_bit_string signatureValue;
+ } Certificate;
+
+ /*
+ TBSCertificate ::= SEQUENCE {
+ version [0] Version OPTIONAL,
+ serialNumber CertificateSerialNumber,
+ signature AlgorithmIdentifier,
+ issuer Name,
+ validity Validity,
+ subject Name,
+ subjectPublicKeyInfo SubjectPublicKeyInfo,
+ issuerUniqueID [1] IMPLICIT BIT STRING {
+ } OPTIONAL,
+ subjectUniqueID [2] IMPLICIT BIT STRING {
+ } OPTIONAL,
+ extensions [3] Extensions OPTIONAL,
+ }
+ */
+
+ typedef struct TBSCertificate {
+ heim_octet_string _save;
+ Version *version;
+ CertificateSerialNumber serialNumber;
+ AlgorithmIdentifier signature;
+ Name issuer;
+ Validity validity;
+ Name subject;
+ SubjectPublicKeyInfo subjectPublicKeyInfo;
+ heim_bit_string *issuerUniqueID;
+ heim_bit_string *subjectUniqueID;
+ Extensions *extensions;
+ } TBSCertificate;
+```
+
+Note how trivial the mapping onto C is.
+
+`OPTIONAL` fields become pointer fields, with `NULL` indicating
+absence and non-NULL indicating presence.
+
+And so on.
+
+## `asn1_print` Usage
+
+```text
+ASN1_PRINT(1) BSD General Commands Manual ASN1_PRINT(1)
+
+NAME
+ asn1_print — dump ASN.1 DER encoded values
+
+SYNOPSIS
+ asn1_print [-i | --no-indent] [-I | --inner] [-l | --list-types]
+ [-A | --try-all-types] [-S | --raw-sequence] [-n | --no-print]
+ [-q | --quiet] [--test-encode] [--test-copy]
+ [-l -v | --version] [-l -h | --help] [FILE [TypeName...]]
+
+DESCRIPTION
+ asn1_print Dumps ASN.1 DER-encoded values. If one or more TypeName argu-
+ ments are given, then asn1_print will print the value in a JSON-like for-
+ mat using its knowledge of the ASN.1 modules defining those types, stop-
+ ping at the first type for which it can successfully decode the value.
+ If TypeNames are given, they must be the names of ASN.1 types exported by
+ an ASN.1 modules that are compiled into asn1_print. Use the
+ --try-all-types option to attempt decoding as all ASN.1 types known to
+ asn1_print. If neither any TypeName nor --try-all-types are given, then
+ the value will be parsed and displayed using just the self-describing
+ nature of DER.
+
+ Options supported:
+
+ -i, --no-indent
+ Do not indent dump.
+
+ -I, --inner
+ Try to parse inner structures of OCTET STRING and constructed
+ values.
+
+ -l, --list-types
+ List all types known to asn1_print.
+
+ -A, --try-all-types
+ Attempt to decode the value as any of all types known to
+ asn1_print.
+
+ -S, --raw-sequence
+ If a value parses as a given TypeName but any bytes are left
+ over, try to parse those separately as well until all bytes are
+ consumed or an error occurs.
+
+ -n, --no-print
+ For the case where -A or --try-all-types or where a TypeName is
+ given, do not output a JSON representation of the value, just
+ attempt to decode it. This is useful for fuzzing.
+
+ -q, --quiet
+ Similar to -n, --no-print but JSON output will be formatted, just
+ not output. As with -n, --no-print, this option requires -A -/
+ --try-all-types or that a TypeName be given. This is useful for
+ fuzzing.
+
+ --test-encode
+ Check that encoding produces the same value as decoding. Useful
+ for fuzzing.
+
+ --test-copy
+ Test copy functions. Useful for fuzzing.
+
+ -v, --version
+
+ -h, --help
+
+HEIMDAL February 22, 2021 HEIMDAL
+```
+
+## Implementation
+
+See:
+
+ - `lib/asn1/main.c` for the `main()` function of the compiler
+ - `lib/asn1/asn1parse.y` for the grammar and most of the parsing into an AST
+ - `lib/asn1/symbol.h` for the types making up the AST
+ - `lib/asn1/{hash,symbol}.c` for compiler AST supporting functionality
+ - `lib/asn1/gen.c` for the C header file generator
+ - `lib/asn1/gen_template.c` for the template generator
+ - `lib/asn1/gen_{decode,encode,length,copy,free}.c` for the C code generator
+ - `lib/asn1/gen_{glue,seq}.c` for misc code generator
+ - `lib/asn1/template.c` for the template interpreter
+ - `lib/asn1/der*.c` for primitive type primitives
+ - `lib/asn1/extra.c` for primitives related to `ANY`
+
+...
+
+## Futures
+
+ - Add JER support so we can convert between JER and DER?
+
+ - Add XDR support? There are no ASN.1 Encoding Rules based on XDR, but it is
+ trivial to construct such for at least that subset of ASN.1 for which the
+ XDR syntax has equivalent semantics.
+
+ - Add OER support?
+
+ - Add NDR support? There are no ASN.1 Encoding Rules based on NDR, but it is
+ trivial to construct such for at least that subset of ASN.1 for which the
+ IDL syntax has equivalent semantics.
+
+ - Perhaps third parties will contribute more control over generated types?
+ This may require separate publication of the Heimdal ASN.1 compiler from the
+ rest of Heimdal.
+
+## Moving From C
+
+ - Generate and output a JSON representation of the compiled ASN.1 module.
+
+ - Code codegen/templategen backends in jq or Haskell or whatever.
+
+ - Code template interpreters in some host language.
+
+ - Eventually rewrite the compiler itself in Rust or whatever.
diff --git a/third_party/heimdal/lib/asn1/asn1-common.h b/third_party/heimdal/lib/asn1/asn1-common.h
new file mode 100644
index 0000000..7797eed
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/asn1-common.h
@@ -0,0 +1,90 @@
+/* $Id$ */
+
+#include <stddef.h>
+#include <time.h>
+#include <krb5-types.h>
+
+#ifndef __asn1_common_definitions__
+#define __asn1_common_definitions__
+
+#ifndef __HEIM_BASE_DATA__
+#define __HEIM_BASE_DATA__ 1
+struct heim_base_data {
+ size_t length;
+ void *data;
+};
+#endif
+
+typedef struct heim_integer {
+ size_t length;
+ void *data;
+ int negative;
+} heim_integer;
+
+typedef struct heim_base_data heim_octet_string;
+
+typedef char *heim_general_string;
+typedef char *heim_utf8_string;
+typedef struct heim_base_data heim_printable_string;
+typedef struct heim_base_data heim_ia5_string;
+
+typedef struct heim_bmp_string {
+ size_t length;
+ uint16_t *data;
+} heim_bmp_string;
+
+typedef struct heim_universal_string {
+ size_t length;
+ uint32_t *data;
+} heim_universal_string;
+
+typedef char *heim_visible_string;
+
+typedef struct heim_oid {
+ size_t length;
+ unsigned *components;
+} heim_oid;
+
+typedef struct heim_bit_string {
+ size_t length;
+ void *data;
+} heim_bit_string;
+
+typedef struct heim_base_data heim_any;
+typedef struct heim_base_data heim_any_set;
+typedef struct heim_base_data HEIM_ANY;
+typedef struct heim_base_data HEIM_ANY_SET;
+
+enum asn1_print_flags {
+ ASN1_PRINT_INDENT = 1,
+};
+
+#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \
+ do { \
+ (BL) = length_##T((S)); \
+ (B) = malloc((BL)); \
+ if((B) == NULL) { \
+ (R) = ENOMEM; \
+ } else { \
+ (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \
+ (S), (L)); \
+ if((R) != 0) { \
+ free((B)); \
+ (B) = NULL; \
+ } \
+ } \
+ } while (0)
+
+#ifdef _WIN32
+#ifndef ASN1_LIB
+#define ASN1EXP __declspec(dllimport)
+#else
+#define ASN1EXP
+#endif
+#define ASN1CALL __stdcall
+#else
+#define ASN1EXP
+#define ASN1CALL
+#endif
+
+#endif
diff --git a/third_party/heimdal/lib/asn1/asn1-template.h b/third_party/heimdal/lib/asn1/asn1-template.h
new file mode 100644
index 0000000..07c4461
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/asn1-template.h
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* asn1 templates */
+
+#ifndef __TEMPLATE_H__
+#define __TEMPLATE_H__
+
+/*
+ * TBD:
+ *
+ * - For OER also encode number of optional/default/extension elements into
+ * header entry's ptr field, not just the number of entries that follow it.
+ *
+ * - For JER we'll need to encode encoding options (encode as array, encode as
+ * object, etc.)
+ *
+ * - For open types we'll need to be able to indicate what encoding rules the
+ * type uses.
+ *
+ * - We have too many bits for tags (20) and probably not enough for ops (4
+ * bits, and we've used all but one).
+ */
+
+/* header:
+ * HF flags if not a BIT STRING type
+ * HBF flags if a BIT STRING type
+ *
+ * ptr is count of elements
+ * offset is size of struct
+ */
+
+/* tag:
+ * 0..20 tag
+ * 21 type
+ * 22..23 class
+ * 24..27 flags
+ * 28..31 op
+ *
+ * ptr points to template for tagged type
+ * offset is offset of struct field
+ */
+
+/* parse:
+ * 0..11 type
+ * 12..23 unused
+ * 24..27 flags
+ * 28..31 op
+ *
+ * ptr is NULL
+ * offset is ...
+ */
+
+/* defval: (next template entry is defaulted)
+ *
+ * DV flags (ptr is or points to defval)
+ *
+ * ptr is default value or pointer to default value
+ * offset is all ones
+ */
+
+/* name: first one is the name of the SET/SEQUENCE/CHOICE type
+ * subsequent ones are the name of the nth field
+ *
+ * 0..23 unused
+ * 24..27 flags A1_NM_*
+ * 28..31 op
+ *
+ * ptr is const char * pointer to the name as C string
+ * offset is all zeros
+ */
+
+/* objset:
+ * 0..9 open type ID entry index
+ * 10..19 open type entry index
+ * 20..23 unused
+ * 24..27 flags A1_OS_*
+ * 28..31 op
+ *
+ * ptr points to object set template
+ * offset is the offset of the choice struct
+ */
+
+/* opentypeid: offset is zero
+ * ptr points to value if it is not an integer
+ * ptr is the value if it is an integer
+ * 0..23 unused
+ * 24..27 flags A1_OTI_*
+ * 28..31 op
+ */
+
+/* opentype: offset is sizeof C type for this open type choice
+ * ptr points to template for type choice
+ * 0..23 unused
+ * 24..27 flags
+ * 28..31 op
+ */
+
+#define A1_OP_MASK (0xf0000000)
+#define A1_OP_TYPE (0x10000000) /* templated type */
+#define A1_OP_TYPE_EXTERN (0x20000000) /* templated type (imported) */
+#define A1_OP_TAG (0x30000000) /* a tag */
+#define A1_OP_PARSE (0x40000000) /* primitive type */
+#define A1_OP_SEQOF (0x50000000) /* sequence of */
+#define A1_OP_SETOF (0x60000000) /* set of */
+#define A1_OP_BMEMBER (0x70000000) /* BIT STRING member */
+#define A1_OP_CHOICE (0x80000000) /* CHOICE */
+#define A1_OP_DEFVAL (0x90000000) /* def. value */
+#define A1_OP_OPENTYPE_OBJSET (0xa0000000) /* object set for open type */
+#define A1_OP_OPENTYPE_ID (0xb0000000) /* open type id field */
+#define A1_OP_OPENTYPE (0xc0000000) /* open type field */
+#define A1_OP_NAME (0xd0000000) /* symbol */
+#define A1_OP_TYPE_DECORATE (0xe0000000) /* decoration w/ templated type */
+#define A1_OP_TYPE_DECORATE_EXTERN (0xf0000000) /* decoration w/ some C type */
+ /* 0x00.. is still free */
+
+#define A1_FLAG_MASK (0x0f000000)
+#define A1_FLAG_OPTIONAL (0x01000000)
+#define A1_FLAG_IMPLICIT (0x02000000)
+#define A1_FLAG_DEFAULT (0x04000000)
+
+#define A1_TAG_T(CLASS,TYPE,TAG) ((A1_OP_TAG) | (((CLASS) << 22) | ((TYPE) << 21) | (TAG)))
+#define A1_TAG_CLASS(x) (((x) >> 22) & 0x3)
+#define A1_TAG_TYPE(x) (((x) >> 21) & 0x1)
+#define A1_TAG_TAG(x) ((x) & 0x1fffff)
+
+#define A1_TAG_LEN(t) ((uintptr_t)(t)->ptr)
+#define A1_HEADER_LEN(t) ((uintptr_t)(t)->ptr)
+
+#define A1_PARSE_T(type) ((A1_OP_PARSE) | (type))
+#define A1_PARSE_TYPE_MASK 0xfff
+#define A1_PARSE_TYPE(x) (A1_PARSE_TYPE_MASK & (x))
+
+#define A1_PF_INDEFINTE 0x1
+#define A1_PF_ALLOW_BER 0x2
+
+#define A1_HF_PRESERVE 0x1
+#define A1_HF_ELLIPSIS 0x2
+
+#define A1_HBF_RFC1510 0x1
+
+#define A1_DV_BOOLEAN 0x01
+#define A1_DV_INTEGER 0x02
+#define A1_DV_INTEGER32 0x04
+#define A1_DV_INTEGER64 0x08
+#define A1_DV_UTF8STRING 0x10
+
+#define A1_OS_IS_SORTED (0x01000000)
+#define A1_OS_OT_IS_ARRAY (0x02000000)
+#define A1_OTI_IS_INTEGER (0x04000000)
+
+
+struct asn1_template {
+ uint32_t tt;
+ uint32_t offset;
+ const void *ptr;
+};
+
+typedef int (ASN1CALL *asn1_type_decode)(const unsigned char *, size_t, void *, size_t *);
+typedef int (ASN1CALL *asn1_type_encode)(unsigned char *, size_t, const void *, size_t *);
+typedef size_t (ASN1CALL *asn1_type_length)(const void *);
+typedef void (ASN1CALL *asn1_type_release)(void *);
+typedef int (ASN1CALL *asn1_type_copy)(const void *, void *);
+typedef char * (ASN1CALL *asn1_type_print)(const void *, int);
+
+struct asn1_type_func {
+ asn1_type_encode encode;
+ asn1_type_decode decode;
+ asn1_type_length length;
+ asn1_type_copy copy;
+ asn1_type_release release;
+ asn1_type_print print;
+ size_t size;
+};
+
+struct template_of {
+ unsigned int len;
+ void *val;
+};
+
+enum template_types {
+ A1T_IMEMBER = 0,
+ A1T_HEIM_INTEGER,
+ A1T_INTEGER,
+ A1T_INTEGER64,
+ A1T_UNSIGNED,
+ A1T_UNSIGNED64,
+ A1T_GENERAL_STRING,
+ A1T_OCTET_STRING,
+ A1T_OCTET_STRING_BER,
+ A1T_IA5_STRING,
+ A1T_BMP_STRING,
+ A1T_UNIVERSAL_STRING,
+ A1T_PRINTABLE_STRING,
+ A1T_VISIBLE_STRING,
+ A1T_UTF8_STRING,
+ A1T_GENERALIZED_TIME,
+ A1T_UTC_TIME,
+ A1T_HEIM_BIT_STRING,
+ A1T_BOOLEAN,
+ A1T_OID,
+ A1T_TELETEX_STRING,
+ A1T_NUM_ENTRY
+};
+
+extern struct asn1_type_func asn1_template_prim[A1T_NUM_ENTRY];
+
+#define ABORT_ON_ERROR() abort()
+
+#define DPOC(data,offset) ((const void *)(((const unsigned char *)data) + offset))
+#define DPO(data,offset) ((void *)(((unsigned char *)data) + offset))
+
+/*
+ * These functions are needed by the generated template stubs and are
+ * really internal functions. Since they are part of der-private.h
+ * that contains extra prototypes that really a private we included a
+ * copy here.
+ */
+
+int
+_asn1_copy_top (
+ const struct asn1_template * /*t*/,
+ const void * /*from*/,
+ void * /*to*/);
+
+void
+_asn1_free_top(const struct asn1_template *, void *);
+
+char *
+_asn1_print_top(const struct asn1_template *, int, const void *);
+
+int
+_asn1_decode_top (
+ const struct asn1_template * /*t*/,
+ unsigned /*flags*/,
+ const unsigned char * /*p*/,
+ size_t /*len*/,
+ void * /*data*/,
+ size_t * /*size*/);
+
+int
+_asn1_encode (
+ const struct asn1_template * /*t*/,
+ unsigned char * /*p*/,
+ size_t /*len*/,
+ const void * /*data*/,
+ size_t * /*size*/);
+
+int
+_asn1_encode_fuzzer (
+ const struct asn1_template * /*t*/,
+ unsigned char * /*p*/,
+ size_t /*len*/,
+ const void * /*data*/,
+ size_t * /*size*/);
+
+void
+_asn1_free (
+ const struct asn1_template * /*t*/,
+ void * /*data*/);
+
+size_t
+_asn1_length (
+ const struct asn1_template * /*t*/,
+ const void * /*data*/);
+
+size_t
+_asn1_length_fuzzer (
+ const struct asn1_template * /*t*/,
+ const void * /*data*/);
+
+
+#endif
diff --git a/third_party/heimdal/lib/asn1/asn1_compile-version.rc b/third_party/heimdal/lib/asn1/asn1_compile-version.rc
new file mode 100644
index 0000000..120fb85
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/asn1_compile-version.rc
@@ -0,0 +1,36 @@
+/***********************************************************************
+ * Copyright (c) 2010, Secure Endpoints Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **********************************************************************/
+
+#define RC_FILE_TYPE VFT_APP
+#define RC_FILE_DESC_0409 "ASN.1 Compiler"
+#define RC_FILE_ORIG_0409 "asn1_compile.exe"
+
+#include "../../windows/version.rc"
diff --git a/third_party/heimdal/lib/asn1/asn1_compile.1 b/third_party/heimdal/lib/asn1/asn1_compile.1
new file mode 100644
index 0000000..9af2767
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/asn1_compile.1
@@ -0,0 +1,355 @@
+.\" Copyright (c) 2019 Kungliga Tekniska Högskolan
+.\" (Royal Institute of Technology, Stockholm, Sweden).
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" 3. Neither the name of the Institute nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id$
+.\"
+.Dd February 22, 2021
+.Dt ASN1_COMPILE 1
+.Os HEIMDAL
+.Sh NAME
+.Nm asn1_compile
+.Nd compile ASN.1 modules
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Op Fl Fl template
+.Op Fl Fl prefix-enum
+.Op Fl Fl enum-prefix=PREFIX
+.Op Fl Fl encode-rfc1510-bit-string
+.Op Fl Fl decode-dce-ber
+.Op Fl Fl support-ber
+.Op Fl Fl preserve-binary=TYPE
+.Op Fl Fl sequence=TYPE
+.Op Fl Fl decorate=DECORATION
+.Op Fl Fl one-code-file
+.Op Fl Fl gen-name=NAME
+.Op Fl Fl option-file=FILE
+.Op Fl Fl original-order
+.Op Fl Fl no-parse-units
+.Op Fl Fl type-file=C-HEADER-FILE
+.Op Fl Fl version
+.Op Fl Fl help
+.Op Ar FILE.asn1 Op Ar NAME
+.Ek
+.Sh DESCRIPTION
+.Nm
+compiles an ASN.1 module into C source code and header files.
+.Pp
+A fairly large subset of ASN.1 as specified in X.680, and the
+ASN.1 Information Object System as specified in X.681, X.682, and
+X.683 is supported, with support for the Distinguished Encoding
+Rules (DER), partial Basic Encoding Rules (BER) support, and
+experimental JSON support (encoding only at this time).
+.Pp
+See the compiler's README files for details about the C code and
+interfaces it generates.
+.Pp
+The Information Object System support includes automatic codec
+support for encoding and decoding through
+.Dq open types
+which are also known as
+.Dq typed holes .
+See RFC 5912 for examples of how to use the ASN.1
+Information Object System via X.681/X.682/X.683 annotations. See
+the compiler's README files for more information on ASN.1
+Information Object System support.
+.Pp
+Extensions specific to Heimdal are generally not syntactic in
+nature but rather command-line options to this program.
+For example, one can use command-line options to:
+.Bl -bullet -compact -width Ds -offset indent
+.It
+enable decoding of BER-encoded values;
+.It
+enable RFC1510-style handling of
+.Sq BIT STRING
+types;
+.It
+enable saving of as-received encodings of specific types for the
+purpose of signature validation;
+.It
+generate add/remove utility functions for array types;
+.It
+decorate generated
+.Sq struct
+types with fields that are neither encoded nor decoded;
+.El
+etc.
+.Pp
+ASN.1 x.680 features supported:
+.Bl -bullet -compact -width Ds -offset indent
+.It
+most primitive types (except BMPString and REAL);
+.It
+all constructed types, including SET and SET OF;
+.It
+explicit and implicit tagging.
+.El
+.Pp
+Size and range constraints on the
+.Sq INTEGER
+type cause the compiler to generate appropriate C types such as
+.Sq int ,
+.Sq unsigned int ,
+.Sq int64_t ,
+.Sq uint64_t .
+Unconstrained
+.Sq INTEGER
+is treated as
+.Sq heim_integer ,
+which represents an integer of arbitrary size.
+.Pp
+Caveats and ASN.1 x.680 features not supported:
+.Bl -bullet -compact -width Ds -offset indent
+.It
+JSON encoding support is not quite X.697 (JER) compatible.
+Its JSON schema is subject to change without notice.
+.It
+Control over C types generated is very limited, mainly only for
+integer types.
+.It
+When using the template backend, `SET { .. }` types are currently
+not sorted by tag as they should be, but if the module author
+sorts them by hand then correct DER will be produced.
+.It
+.Sq AUTOMATIC TAGS
+is not supported.
+.It
+The
+.Va REAL
+type is not supported.
+.It
+The
+.Va EmbeddedPDV
+type is not supported.
+.It
+The
+.Va BMPString
+type is not supported.
+.It
+The
+.Va IA5String
+is not properly supported, as it's essentially treated as a
+.Va UTF8String
+with a different tag.
+.It
+All supported non-octet strings are treated as like the
+.Va UTF8String
+type.
+.It
+Only types can be imported into ASN.1 modules at this time.
+.It
+Only simple value syntax is supported.
+Constructed value syntax (i.e., values of SET, SEQUENCE, SET OF,
+and SEQUENCE OF types), is not supported.
+Values of `CHOICE` types are also not supported.
+.El
+.Pp
+Options supported:
+.Bl -tag -width Ds
+.It Fl Fl template
+Use the
+.Dq template
+backend instead of the
+.Dq codegen
+backend (which is the default backend).
+.Pp
+The template backend generates
+.Dq templates
+which are akin to bytecode, and which are interpreted at
+run-time.
+.Pp
+The codegen backend generates C code for all functions directly,
+with no template interpretation.
+.Pp
+The template backend scales better than the codegen backend
+because as we add support for more encoding rules and more
+operations (we may add value comparators) the templates stay
+mostly the same, thus scaling linearly with size of module.
+Whereas the codegen backend scales linear with the product of
+module size and number of encoding rules supported.
+.It Fl Fl prefix-enum
+This option should be removed because ENUMERATED types should
+always have their labels prefixed.
+.It Fl Fl enum-prefix=PREFIX
+This option should be removed because ENUMERATED types should
+always have their labels prefixed.
+.It Fl Fl encode-rfc1510-bit-string
+Use RFC1510, non-standard handling of
+.Dq BIT STRING
+types.
+.It Fl Fl decode-dce-ber
+.It Fl Fl support-ber
+.It Fl Fl preserve-binary=TYPE
+Generate a field named
+.Sq _save
+in the C struct generated for the named
+.Ar TYPE .
+This field is used to preserve the original encoding of the value
+of the
+.Ar TYPE .
+.Pp
+This is useful for cryptographic applications so that they can
+check signatures of encoded values as-received without having to
+re-encode those values.
+.Pp
+For example, the TBSCertificate type should have values preserved
+so that Certificate validation can check the signatureValue over
+the tbsCertificate's value as-received.
+.Pp
+The alternative of encoding a value to check a signature of it is
+brittle.
+For types where non-canonical encodings (such as BER) are
+allowed, this alternative is bound to fail.
+Thus the point of this option.
+.It Fl Fl sequence=TYPE
+Generate add/remove functions for the named ASN.1
+.Ar TYPE
+which must be a
+.Sq SET OF
+or
+.Sq SEQUENCE OF
+type.
+.It Fl Fl decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?]
+Add to the C struct generated for the given ASN.1 SET, SEQUENCE, or
+CHOICE type named
+.Ar ASN1-TYPE
+a
+.Dq hidden
+field named
+.Ar fname
+of the given ASN.1 type
+.Ar FIELD-ASN1-TYPE ,
+but do not encode or decode it.
+If the
+.Ar fname
+ends in a question mark, then treat the field as OPTIONAL.
+.Pp
+This is useful for adding fields to existing types that can be
+used for internal bookkeeping but which do not affect
+interoperability because they are neither encoded nor decoded.
+For example, one might decorate a request type with state needed
+during processing of the request.
+.It Fl Fl decorate=ASN1-TYPE:void*:fname
+Add to the C struct generated for the given ASN.1 SET, SEQUENCE, or
+CHOICE type named
+.Ar ASN1-TYPE
+a
+.Dq hidden
+field named
+.Ar fname
+of type
+.Sq void *
+(but do not encode or decode it.
+.Pp
+The destructor and copy constructor functions generated by this
+compiler for
+.Ar ASN1-TYPE
+will set this field to the
+.Sq NULL
+pointer.
+.It Fl Fl decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header
+Add to the C struct generated for the given ASN.1 SET, SEQUENCE, or
+CHOICE type named
+.Ar ASN1-TYPE
+a
+.Dq hidden
+field named
+.Ar fname
+of the given external C type
+.Ar FIELD-C-TYPE ,
+declared in the given
+.Ar header
+but do not encode or decode this field.
+If the
+.Ar fname
+ends in a question mark, then treat the field as OPTIONAL.
+.Pp
+The
+.Ar header
+must include double quotes or angle brackets.
+The
+.Ar copyfn
+must be the name of a copy constructor function that takes a
+pointer to a source value of the type, and a pointer to a
+destination value of the type, in that order, and which returns
+zero on success or else a system error code on failure.
+The
+.Ar freefn
+must be the name of a destructor function that takes a pointer to
+a value of the type and which releases resources referenced by
+that value, but does not free the value itself (the run-time
+allocates this value as needed from the C heap).
+The
+.Ar freefn
+should also reset the value to a pristine state (such as all
+zeros).
+.Pp
+If the
+.Ar copyfn
+and
+.Ar freefn
+are empty strings, then the decoration field will neither be
+copied nor freed by the functions generated for the
+.Ar TYPE .
+.It Fl Fl one-code-file
+Generate a single source code file.
+Otherwise a separate code file will be generated for every type.
+.It Fl Fl gen-name=NAME
+Use
+.Ar NAME
+to form the names of the files generated.
+.It Fl Fl option-file=FILE
+Take additional command-line options from
+.Ar FILE .
+The options file must have one command-line option per-line, but
+leading whitespace is ignored, and lines that start with a hash
+symbol
+.Sq ( # )
+are comments and are ignored.
+.It Fl Fl original-order
+Attempt to preserve the original order of type definition in the
+ASN.1 module.
+By default the compiler generates types in a topological sort
+order.
+.It Fl Fl no-parse-units
+Do not generate to-int / from-int functions for enumeration
+types.
+.It Fl Fl type-file=C-HEADER-FILE
+Generate an include of the named header file that might be needed
+for common type defintions.
+.It Fl Fl version
+.It Fl Fl help
+.El
+.Sh NOTES
+Currently only the template backend supports automatic encoding
+and decoding of open types via the ASN.1 Information Object
+System and X.681/X.682/X.683 annotations.
diff --git a/third_party/heimdal/lib/asn1/asn1_err.et b/third_party/heimdal/lib/asn1/asn1_err.et
new file mode 100644
index 0000000..ac7a9eb
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/asn1_err.et
@@ -0,0 +1,29 @@
+#
+# Error messages for the asn.1 library
+#
+# This might look like a com_err file, but is not
+#
+id "$Id$"
+
+error_table asn1
+prefix ASN1
+error_code BAD_TIMEFORMAT, "ASN.1 failed call to system time library"
+error_code MISSING_FIELD, "ASN.1 structure is missing a required field"
+error_code MISPLACED_FIELD, "ASN.1 unexpected field number"
+error_code TYPE_MISMATCH, "ASN.1 type numbers are inconsistent"
+error_code OVERFLOW, "ASN.1 value too large"
+error_code OVERRUN, "ASN.1 encoding ended unexpectedly"
+error_code BAD_ID, "ASN.1 identifier doesn't match expected value"
+error_code BAD_LENGTH, "ASN.1 length doesn't match expected value"
+error_code BAD_FORMAT, "ASN.1 badly-formatted encoding"
+error_code PARSE_ERROR, "ASN.1 parse error"
+error_code EXTRA_DATA, "ASN.1 extra data past end of end structure"
+error_code BAD_CHARACTER, "ASN.1 invalid character in string"
+error_code MIN_CONSTRAINT, "ASN.1 too few elements"
+error_code MAX_CONSTRAINT, "ASN.1 too many elements"
+error_code EXACT_CONSTRAINT, "ASN.1 wrong number of elements"
+error_code INDEF_OVERRUN, "ASN.1 BER indefinte encoding overrun"
+error_code INDEF_UNDERRUN, "ASN.1 BER indefinte encoding underun"
+error_code GOT_BER, "ASN.1 got BER encoded when expected DER"
+error_code INDEF_EXTRA_DATA, "ASN.1 EoC tag contained data"
+end
diff --git a/third_party/heimdal/lib/asn1/asn1_gen.c b/third_party/heimdal/lib/asn1/asn1_gen.c
new file mode 100644
index 0000000..6a0244f
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/asn1_gen.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+#include <com_err.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <getarg.h>
+#include <hex.h>
+#include <err.h>
+
+RCSID("$Id$");
+
+static int
+doit(const char *fn)
+{
+ char buf[2048];
+ char *fnout = NULL;
+ const char *bname;
+ unsigned long line = 0;
+ FILE *f, *fout;
+ size_t offset = 0;
+
+ f = fopen(fn, "r");
+ if (f == NULL)
+ err(1, "fopen");
+
+ bname = strrchr(fn, '/');
+ if (bname)
+ bname++;
+ else
+ bname = fn;
+
+ if (asprintf(&fnout, "%s.out", bname) < 0 || fnout == NULL)
+ errx(1, "malloc");
+
+ fout = fopen(fnout, "w");
+ if (fout == NULL)
+ err(1, "fopen: output file");
+
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+ char *ptr, *class, *type, *tag, *length, *data, *foo;
+ int ret, l, c, ty, ta;
+ unsigned char p[6], *pdata;
+ size_t sz;
+
+ line++;
+
+ buf[strcspn(buf, "\r\n")] = '\0';
+ if (buf[0] == '#' || buf[0] == '\0')
+ continue;
+
+ ptr = buf;
+ while (isspace((unsigned char)*ptr))
+ ptr++;
+
+ class = strtok_r(ptr, " \t\n", &foo);
+ if (class == NULL) errx(1, "class missing on line %lu", line);
+ type = strtok_r(NULL, " \t\n", &foo);
+ if (type == NULL) errx(1, "type missing on line %lu", line);
+ tag = strtok_r(NULL, " \t\n", &foo);
+ if (tag == NULL) errx(1, "tag missing on line %lu", line);
+ length = strtok_r(NULL, " \t\n", &foo);
+ if (length == NULL) errx(1, "length missing on line %lu", line);
+ data = strtok_r(NULL, " \t\n", &foo);
+
+ c = der_get_class_num(class);
+ if (c == -1) errx(1, "no valid class on line %lu", line);
+ ty = der_get_type_num(type);
+ if (ty == -1) errx(1, "no valid type on line %lu", line);
+ ta = der_get_tag_num(tag);
+ if (ta == -1)
+ ta = atoi(tag);
+
+ l = atoi(length);
+
+ printf("line: %3lu offset: %3lu class: %d type: %d "
+ "tag: %3d length: %3d %s\n",
+ line, (unsigned long)offset, c, ty, ta, l,
+ data ? "<have data>" : "<no data>");
+
+ ret = der_put_length_and_tag(p + sizeof(p) - 1, sizeof(p),
+ l,
+ c,
+ ty,
+ ta,
+ &sz);
+ if (ret)
+ errx(1, "der_put_length_and_tag: %d", ret);
+
+ if (fwrite(p + sizeof(p) - sz , sz, 1, fout) != 1)
+ err(1, "fwrite length/tag failed");
+ offset += sz;
+
+ if (data) {
+ size_t datalen;
+
+ datalen = strlen(data) / 2;
+ pdata = emalloc(sz);
+
+ if (hex_decode(data, pdata, datalen) != datalen)
+ errx(1, "failed to decode data");
+
+ if (fwrite(pdata, datalen, 1, fout) != 1)
+ err(1, "fwrite data failed");
+ offset += datalen;
+
+ free(pdata);
+ }
+ }
+ printf("line: eof offset: %lu\n", (unsigned long)offset);
+
+ if (fclose(fout) == EOF)
+ err(1, "writes to file %s failed", fnout);
+ fclose(f);
+ return 0;
+}
+
+
+static int version_flag;
+static int help_flag;
+struct getargs args[] = {
+ { "version", 0, arg_flag, &version_flag, NULL, NULL },
+ { "help", 0, arg_flag, &help_flag, NULL, NULL }
+};
+int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int code)
+{
+ arg_printusage(args, num_args, NULL, "parse-file");
+ exit(code);
+}
+
+int
+main(int argc, char **argv)
+{
+ int optidx = 0;
+
+ setprogname (argv[0]);
+
+ if(getarg(args, num_args, argc, argv, &optidx))
+ usage(1);
+ if(help_flag)
+ usage(0);
+ if(version_flag) {
+ print_version(NULL);
+ exit(0);
+ }
+ argv += optidx;
+ argc -= optidx;
+ if (argc != 1)
+ usage (1);
+
+ return doit (argv[0]);
+}
diff --git a/third_party/heimdal/lib/asn1/asn1_print.1 b/third_party/heimdal/lib/asn1/asn1_print.1
new file mode 100644
index 0000000..8066b0b
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/asn1_print.1
@@ -0,0 +1,135 @@
+.\" Copyright (c) 2021 Kungliga Tekniska Högskolan
+.\" (Royal Institute of Technology, Stockholm, Sweden).
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" 3. Neither the name of the Institute nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id$
+.\"
+.Dd February 22, 2021
+.Dt ASN1_PRINT 1
+.Os HEIMDAL
+.Sh NAME
+.Nm asn1_print
+.Nd dump ASN.1 DER encoded values
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Oo Fl i \*(Ba Xo Fl Fl no-indent Xc Oc
+.Oo Fl I \*(Ba Xo Fl Fl inner Xc Oc
+.Oo Fl l \*(Ba Xo Fl Fl list-types Xc Oc
+.Oo Fl A \*(Ba Xo Fl Fl try-all-types Xc Oc
+.Oo Fl S \*(Ba Xo Fl Fl raw-sequence Xc Oc
+.Oo Fl n \*(Ba Xo Fl Fl no-print Xc Oc
+.Oo Fl q \*(Ba Xo Fl Fl quiet Xc Oc
+.Oo Xo Fl Fl test-encode Xc Oc
+.Oo Xo Fl Fl test-copy Xc Oc
+.Oo Fl l v \*(Ba Xo
+.Fl Fl version
+.Xc
+.Oc
+.Oo Fl l h \*(Ba Xo
+.Fl Fl help
+.Xc
+.Oc
+.Op Ar FILE Op Ar TypeName...
+.Ek
+.Sh DESCRIPTION
+.Nm
+Dumps ASN.1 DER-encoded values.
+If one or more
+.Ar TypeName
+arguments are given, then
+.Nm
+will print the value in a JSON-like format using its knowledge of
+the ASN.1 modules defining those types, stopping at the first type
+for which it can successfully decode the value.
+If
+.Ar TypeNames
+are given, they must be the names of ASN.1 types exported by an
+ASN.1 modules that are compiled into
+.Nm .
+Use the
+.Fl Fl try-all-types
+option to attempt decoding as all ASN.1 types known to
+.Nm .
+If neither any
+.Ar TypeName
+nor
+.Fl Fl try-all-types
+are given, then the value will be parsed and displayed using just
+the self-describing nature of DER.
+.Pp
+Options supported:
+.Bl -tag -width Ds
+.It Fl i, Fl Fl no-indent
+Do not indent dump.
+.It Fl I, Fl Fl inner
+Try to parse inner structures of OCTET STRING and constructed values.
+.It Fl l, Fl Fl list-types
+List all types known to
+.Nm .
+.It Fl A, Fl Fl try-all-types
+Attempt to decode the value as any of all types known to
+.Nm .
+.It Fl S, Fl Fl raw-sequence
+If a value parses as a given
+.Ar TypeName
+but any bytes are left over, try to parse those separately as
+well until all bytes are consumed or an error occurs.
+.It Fl n, Fl Fl no-print
+For the case where
+.Fl A
+or
+.Fl Fl try-all-types
+or where a
+.Ar TypeName
+is given, do not output a JSON representation of the value, just
+attempt to decode it.
+This is useful for fuzzing.
+.It Fl q, Fl Fl quiet
+Similar to
+.Fl n, Fl Fl no-print
+but JSON output will be formatted, just not output.
+As with
+.Fl n, Fl Fl no-print,
+this option requires
+.Fl A / Fl Fl try-all-types
+or that a
+.Ar TypeName
+be given.
+This is useful for fuzzing.
+.It Fl Fl test-encode
+Check that encoding produces the same value as decoding.
+Useful for fuzzing.
+.It Fl Fl test-copy
+Test copy functions.
+Useful for fuzzing.
+.It Fl v, Fl Fl version
+.It Fl h, Fl Fl help
+.El
diff --git a/third_party/heimdal/lib/asn1/asn1_print.c b/third_party/heimdal/lib/asn1/asn1_print.c
new file mode 100644
index 0000000..9ef6ffd
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/asn1_print.c
@@ -0,0 +1,692 @@
+/*
+ * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+#include <com_err.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+#include <getarg.h>
+#include <err.h>
+#include <der.h>
+#include "cms_asn1.h"
+#include "digest_asn1.h"
+#include "krb5_asn1.h"
+#include "kx509_asn1.h"
+#include "ocsp_asn1.h"
+#include "pkcs10_asn1.h"
+#include "pkcs12_asn1.h"
+#include "pkcs8_asn1.h"
+#include "pkcs9_asn1.h"
+#include "pkinit_asn1.h"
+#include "rfc2459_asn1.h"
+#include "rfc4108_asn1.h"
+#ifdef ASN1_PRINT_SUPPORTED
+#include "x690sample_template_asn1.h"
+#else
+#include "x690sample_asn1.h"
+#endif
+
+static int quiet_flag = 0;
+static int print_flag = 1;
+static int test_copy_flag;
+static int test_encode_flag;
+static int sequence_flag;
+static int try_all_flag;
+static int indent_flag = 1;
+static int inner_flag;
+
+static unsigned long indefinite_form_loop;
+static unsigned long indefinite_form_loop_max = 10000;
+
+typedef size_t (*lengther)(void *);
+typedef int (*copyer)(const void *, void *);
+typedef int (*encoder)(unsigned char *, size_t, void *, size_t *);
+typedef int (*decoder)(const unsigned char *, size_t, void *, size_t *);
+typedef char *(*printer)(const void *, int);
+typedef void (*releaser)(void *);
+const struct types {
+ const char *name;
+ size_t sz;
+ copyer cpy;
+ lengther len;
+ decoder decode;
+ encoder encode;
+ printer print;
+ releaser release;
+} types[] = {
+#define ASN1_SYM_INTVAL(n, gn, gns, i)
+#define ASN1_SYM_OID(n, gn, gns)
+#ifdef ASN1_PRINT_SUPPORTED
+#define ASN1_SYM_TYPE(n, gn, gns) \
+ { \
+ n, \
+ sizeof(gns), \
+ (copyer)copy_ ## gns, \
+ (lengther)length_ ## gns, \
+ (decoder)decode_ ## gns, \
+ (encoder)encode_ ## gns, \
+ (printer)print_ ## gns, \
+ (releaser)free_ ## gns, \
+ },
+#else
+#define ASN1_SYM_TYPE(n, gn, gns) \
+ { \
+ n, \
+ sizeof(gns), \
+ (copyer)copy_ ## gns, \
+ (lengther)length_ ## gns, \
+ (decoder)decode_ ## gns, \
+ (encoder)encode_ ## gns, \
+ 0, \
+ (releaser)free_ ## gns, \
+ },
+#endif
+#include "cms_asn1_syms.c"
+#include "digest_asn1_syms.c"
+#include "krb5_asn1_syms.c"
+#include "kx509_asn1_syms.c"
+#include "ocsp_asn1_syms.c"
+#include "pkcs10_asn1_syms.c"
+#include "pkcs12_asn1_syms.c"
+#include "pkcs8_asn1_syms.c"
+#include "pkcs9_asn1_syms.c"
+#include "pkinit_asn1_syms.c"
+#include "rfc2459_asn1_syms.c"
+#include "rfc4108_asn1_syms.c"
+#ifdef ASN1_PRINT_SUPPORTED
+#include "x690sample_template_asn1_syms.c"
+#else
+#include "x690sample_asn1_syms.c"
+#endif
+};
+
+struct types sorted_types[sizeof(types)/sizeof(types[0])];
+
+static size_t
+loop (unsigned char *buf, size_t len, int indent)
+{
+ unsigned char *start_buf = buf;
+
+ while (len > 0) {
+ int ret;
+ Der_class class;
+ Der_type type;
+ unsigned int tag;
+ size_t sz;
+ size_t length;
+ size_t loop_length = 0;
+ int end_tag = 0;
+ const char *tagname;
+
+ ret = der_get_tag (buf, len, &class, &type, &tag, &sz);
+ if (ret)
+ errx (1, "der_get_tag: %s", error_message (ret));
+ if (sz > len)
+ errx (1, "unreasonable length (%u) > %u",
+ (unsigned)sz, (unsigned)len);
+ buf += sz;
+ len -= sz;
+ if (indent_flag) {
+ int i;
+ for (i = 0; i < indent; ++i)
+ printf (" ");
+ }
+ printf ("%s %s ", der_get_class_name(class), der_get_type_name(type));
+ tagname = der_get_tag_name(tag);
+ if (class == ASN1_C_UNIV && tagname != NULL)
+ printf ("%s = ", tagname);
+ else
+ printf ("tag %d = ", tag);
+ ret = der_get_length (buf, len, &length, &sz);
+ if (ret)
+ errx (1, "der_get_tag: %s", error_message (ret));
+ if (sz > len)
+ errx (1, "unreasonable tag length (%u) > %u",
+ (unsigned)sz, (unsigned)len);
+ buf += sz;
+ len -= sz;
+ if (length == ASN1_INDEFINITE) {
+ if ((class == ASN1_C_UNIV && type == PRIM && tag == UT_OctetString) ||
+ (class == ASN1_C_CONTEXT && type == CONS) ||
+ (class == ASN1_C_UNIV && type == CONS && tag == UT_Sequence) ||
+ (class == ASN1_C_UNIV && type == CONS && tag == UT_Set)) {
+ printf("*INDEFINITE FORM*");
+ } else {
+ fflush(stdout);
+ errx(1, "indef form used on unsupported object");
+ }
+ end_tag = 1;
+ if (indefinite_form_loop > indefinite_form_loop_max)
+ errx(1, "indefinite form used recursively more then %lu "
+ "times, aborting", indefinite_form_loop_max);
+ indefinite_form_loop++;
+ length = len;
+ } else if (length > len) {
+ printf("\n");
+ fflush(stdout);
+ errx (1, "unreasonable inner length (%u) > %u",
+ (unsigned)length, (unsigned)len);
+ }
+ if (class == ASN1_C_CONTEXT || class == ASN1_C_APPL) {
+ printf ("%lu bytes [%u]", (unsigned long)length, tag);
+ if (type == CONS) {
+ printf("\n");
+ loop_length = loop (buf, length, indent + 2);
+ } else {
+ printf(" IMPLICIT content\n");
+ }
+ } else if (class == ASN1_C_UNIV) {
+ switch (tag) {
+ case UT_EndOfContent:
+ printf (" INDEFINITE length was %lu\n",
+ (unsigned long)(buf - start_buf));
+ break;
+ case UT_Set :
+ case UT_Sequence :
+ printf ("%lu bytes {\n", (unsigned long)length);
+ loop_length = loop (buf, length, indent + 2);
+ if (indent_flag) {
+ int i;
+ for (i = 0; i < indent; ++i)
+ printf (" ");
+ printf ("}\n");
+ } else
+ printf ("} indent = %d\n", indent / 2);
+ break;
+ case UT_Integer : {
+ int val;
+
+ if (length <= sizeof(val)) {
+ ret = der_get_integer (buf, length, &val, NULL);
+ if (ret)
+ errx (1, "der_get_integer: %s", error_message (ret));
+ printf ("integer %d\n", val);
+ } else {
+ heim_integer vali;
+ char *p;
+
+ ret = der_get_heim_integer(buf, length, &vali, NULL);
+ if (ret)
+ errx (1, "der_get_heim_integer: %s",
+ error_message (ret));
+ ret = der_print_hex_heim_integer(&vali, &p);
+ if (ret)
+ errx (1, "der_print_hex_heim_integer: %s",
+ error_message (ret));
+ printf ("BIG NUM integer: length %lu %s\n",
+ (unsigned long)length, p);
+ free(p);
+ }
+ break;
+ }
+ case UT_OctetString : {
+ heim_octet_string str;
+ size_t i;
+
+ ret = der_get_octet_string (buf, length, &str, NULL);
+ if (ret)
+ errx (1, "der_get_octet_string: %s", error_message (ret));
+ printf ("(length %lu), ", (unsigned long)length);
+
+ if (inner_flag) {
+ Der_class class2;
+ Der_type type2;
+ unsigned int tag2;
+
+ ret = der_get_tag(str.data, str.length,
+ &class2, &type2, &tag2, &sz);
+ if (ret || sz > str.length ||
+ type2 != CONS || tag2 != UT_Sequence)
+ goto just_an_octet_string;
+
+ printf("{\n");
+ loop (str.data, str.length, indent + 2);
+ for (i = 0; i < indent; ++i)
+ printf (" ");
+ printf ("}\n");
+
+ } else {
+ unsigned char *uc;
+
+ just_an_octet_string:
+ uc = (unsigned char *)str.data;
+ for (i = 0; i < min(16,length); ++i)
+ printf ("%02x", uc[i]);
+ printf ("\n");
+ }
+ free (str.data);
+ break;
+ }
+ case UT_IA5String :
+ case UT_PrintableString : {
+ heim_printable_string str;
+ unsigned char *s;
+ size_t n;
+
+ memset(&str, 0, sizeof(str));
+
+ ret = der_get_printable_string (buf, length, &str, NULL);
+ if (ret)
+ errx (1, "der_get_general_string: %s",
+ error_message (ret));
+ s = str.data;
+ printf("\"");
+ for (n = 0; n < str.length; n++) {
+ if (isprint(s[n]))
+ printf ("%c", s[n]);
+ else
+ printf ("#%02x", s[n]);
+ }
+ printf("\"\n");
+ der_free_printable_string(&str);
+ break;
+ }
+ case UT_GeneralizedTime :
+ case UT_GeneralString :
+ case UT_VisibleString :
+ case UT_UTF8String : {
+ heim_general_string str;
+
+ ret = der_get_general_string (buf, length, &str, NULL);
+ if (ret)
+ errx (1, "der_get_general_string: %s",
+ error_message (ret));
+ printf ("\"%s\"\n", str);
+ free (str);
+ break;
+ }
+ case UT_OID: {
+ heim_oid o;
+ char *p;
+
+ ret = der_get_oid(buf, length, &o, NULL);
+ if (ret)
+ errx (1, "der_get_oid: %s", error_message (ret));
+ ret = der_print_heim_oid_sym(&o, '.', &p);
+ der_free_oid(&o);
+ if (ret)
+ errx (1, "der_print_heim_oid_sym: %s", error_message (ret));
+ printf("%s\n", p);
+ free(p);
+
+ break;
+ }
+ case UT_Enumerated: {
+ int num;
+
+ ret = der_get_integer (buf, length, &num, NULL);
+ if (ret)
+ errx (1, "der_get_enum: %s", error_message (ret));
+
+ printf("%u\n", num);
+ break;
+ }
+ default :
+ printf ("%lu bytes\n", (unsigned long)length);
+ break;
+ }
+ }
+ if (end_tag) {
+ if (loop_length == 0)
+ errx(1, "zero length INDEFINITE data ? indent = %d\n",
+ indent / 2);
+ if (loop_length < length)
+ length = loop_length;
+ if (indefinite_form_loop == 0)
+ errx(1, "internal error in indefinite form loop detection");
+ indefinite_form_loop--;
+ } else if (loop_length)
+ errx(1, "internal error for INDEFINITE form");
+ buf += length;
+ len -= length;
+ }
+ return 0;
+}
+
+static int
+type_cmp(const void *va, const void *vb)
+{
+ const struct types *ta = (const struct types *)va;
+ const struct types *tb = (const struct types *)vb;
+
+ return strcmp(ta->name, tb->name);
+}
+
+static int
+dotype(unsigned char *buf, size_t len, char **argv, size_t *size)
+{
+ const char *typename = "";
+ size_t matches = 0;
+ size_t sz;
+ size_t tried = 0;
+ size_t i = 0;
+ void *v;
+ int ret = 0;
+
+ *size = len;
+
+ memcpy(sorted_types, types, sizeof(types));
+ qsort(sorted_types,
+ sizeof(types)/sizeof(types[0]),
+ sizeof(types[0]),
+ type_cmp);
+
+ while ((try_all_flag && i < sizeof(types)/sizeof(types[0])) ||
+ (typename = (argv++)[0])) {
+
+ if (try_all_flag) {
+ typename = sorted_types[i].name;
+ } else {
+ size_t right = sizeof(types)/sizeof(types[0]) - 1;
+ size_t left = 0;
+ size_t mid = (left + right) >> 1;
+ int c = -1;
+
+ while (left <= right) {
+ mid = (left + right) >> 1;
+ c = strcmp(sorted_types[mid].name, typename);
+ if (c < 0)
+ left = mid + 1;
+ else if (c > 0)
+ right = mid - 1;
+ else
+ break;
+ }
+ if (c != 0)
+ errx(1, "Type %s not found", typename);
+ i = mid;
+ }
+ v = ecalloc(1, sorted_types[i].sz);
+ ret = sorted_types[i].decode(buf, len, v, &sz);
+ if (ret == 0) {
+ matches++;
+ if (!quiet_flag && sz == len) {
+ fprintf(stderr, "Match: %s\n", typename);
+ } else if (sequence_flag) {
+ *size = sz;
+ } else if (!quiet_flag) {
+ fprintf(stderr, "Prefix match: %s\n", typename);
+ }
+ if (print_flag) {
+ static int warned = 0;
+
+ if (!sorted_types[i].print) {
+ if (!warned)
+ warnx("Missing print support; try enabling / not "
+ "disabling ASN.1 templating in build "
+ "configuration");
+ warned = 1;
+ } else {
+ char *s;
+
+ s = sorted_types[i].print(v, indent_flag ? ASN1_PRINT_INDENT : 0);
+ if (!s)
+ err(1, "Could not print %s\n", typename);
+ if (!quiet_flag)
+ printf("%s\n", s);
+ free(s);
+ }
+ }
+ if (test_encode_flag) {
+ unsigned char *der = emalloc(sz);
+ size_t wants = sorted_types[i].len(v);
+
+ if (wants != sz)
+ errx(1, "Encoding will not round trip");
+ ret = sorted_types[i].encode(der + (sz - 1), sz, v, &sz);
+ if (ret != 0)
+ errx(1, "Encoding failed");
+ if (memcmp(buf, der, sz) != 0)
+ errx(1, "Encoding did not round trip");
+ free(der);
+ }
+ if (test_copy_flag) {
+ void *vcpy = ecalloc(1, sorted_types[i].sz);
+
+ ret = sorted_types[i].cpy(v, vcpy);
+ if (ret != 0)
+ errx(1, "Copy function failed");
+ if (test_encode_flag) {
+ unsigned char *der = emalloc(sz);
+ size_t wants = sorted_types[i].len(vcpy);
+
+ if (wants != sz)
+ errx(1, "Encoding of copy will not round trip");
+ ret = sorted_types[i].encode(der + (sz - 1), sz, vcpy, &sz);
+ if (ret != 0)
+ errx(1, "Encoding of copy failed");
+ if (memcmp(buf, der, sz) != 0)
+ errx(1, "Encoding of copy did not round trip");
+ free(der);
+ }
+ sorted_types[i].release(vcpy);
+ free(vcpy);
+ }
+ }
+ sorted_types[i].release(v);
+ free(v);
+ tried++;
+ i++;
+
+ if (ret == 0 && !try_all_flag && !argv[0])
+ return 0;
+
+ if (!try_all_flag && argv[0])
+ continue;
+
+ if (try_all_flag) {
+ if (i < sizeof(types)/sizeof(types[0]))
+ continue;
+ if (matches)
+ break;
+ }
+ if (tried > 1)
+ errx(1, "No type matched the input value");
+
+ /* XXX Use com_err */
+ switch (ret) {
+ case ASN1_BAD_TIMEFORMAT:
+ errx(1, "Could not decode and print data as type %s: "
+ "Bad time format", typename);
+ case ASN1_MISSING_FIELD:
+ errx(1, "Could not decode and print data as type %s: "
+ "Missing required field", typename);
+ case ASN1_MISPLACED_FIELD:
+ errx(1, "Could not decode and print data as type %s: "
+ "Fields out of order", typename);
+ case ASN1_TYPE_MISMATCH:
+ errx(1, "Could not decode and print data as type %s: "
+ "Type mismatch", typename);
+ case ASN1_OVERFLOW:
+ errx(1, "Could not decode and print data as type %s: "
+ "DER value too large", typename);
+ case ASN1_OVERRUN:
+ errx(1, "Could not decode and print data as type %s: "
+ "DER value too short", typename);
+ case ASN1_BAD_ID:
+ errx(1, "Could not decode and print data as type %s: "
+ "DER tag is unexpected", typename);
+ case ASN1_BAD_LENGTH:
+ errx(1, "Could not decode and print data as type %s: "
+ "DER length does not match value", typename);
+ case ASN1_BAD_FORMAT:
+ case ASN1_PARSE_ERROR:
+ errx(1, "Could not decode and print data as type %s: "
+ "DER badly formatted", typename);
+ case ASN1_EXTRA_DATA:
+ errx(1, "Could not decode and print data as type %s: "
+ "Extra data past end of end structure", typename);
+ case ASN1_BAD_CHARACTER:
+ errx(1, "Could not decode and print data as type %s: "
+ "Invalid character encoding in string", typename);
+ case ASN1_MIN_CONSTRAINT:
+ errx(1, "Could not decode and print data as type %s: "
+ "Too few elements", typename);
+ case ASN1_MAX_CONSTRAINT:
+ errx(1, "Could not decode and print data as type %s: "
+ "Too many elements", typename);
+ case ASN1_EXACT_CONSTRAINT:
+ errx(1, "Could not decode and print data as type %s: "
+ "Wrong count of elements", typename);
+ case ASN1_INDEF_OVERRUN:
+ errx(1, "Could not decode and print data as type %s: "
+ "BER indefinte encoding overun", typename);
+ case ASN1_INDEF_UNDERRUN:
+ errx(1, "Could not decode and print data as type %s: "
+ "BER indefinte encoding underun", typename);
+ case ASN1_GOT_BER:
+ errx(1, "Could not decode and print data as type %s: "
+ "BER encoding when DER expected", typename);
+ case ASN1_INDEF_EXTRA_DATA:
+ errx(1, "Could not decode and print data as type %s: "
+ "End-of-contents tag contains data", typename);
+ default:
+ errx(1, "Could not decode and print data as type %s", typename);
+ }
+ }
+ return 0;
+}
+
+static int
+doit(char **argv)
+{
+ int fd = open(argv[0], O_RDONLY);
+ struct stat sb;
+ unsigned char *buf;
+ size_t len;
+ int ret;
+
+ if(fd < 0)
+ err(1, "opening %s for read", argv[0]);
+ if (fstat (fd, &sb) < 0)
+ err(1, "stat %s", argv[0]);
+ len = sb.st_size;
+ buf = emalloc(len);
+ if (read(fd, buf, len) != len)
+ errx(1, "read failed");
+ close(fd);
+
+ argv++;
+ if (argv[0] || try_all_flag) {
+ size_t off = 0;
+ size_t sz = 0;
+
+ do {
+ ret = dotype(buf + off, len - off, argv, &sz);
+ off += sz;
+ } while (ret == 0 && sequence_flag && off < len);
+ } else {
+ ret = loop(buf, len, 0);
+ }
+ free(buf);
+ return ret;
+}
+
+
+static int list_types_flag;
+static int version_flag;
+static int help_flag;
+struct getargs args[] = {
+ { "indent", 'i', arg_negative_flag, &indent_flag,
+ "\tdo not indent dump", NULL },
+ { "inner", 'I', arg_flag, &inner_flag,
+ "\ttry to parse inner structures of OCTET STRING", NULL },
+ { "list-types", 'l', arg_flag, &list_types_flag,
+ "\tlist ASN.1 types known to this program", NULL },
+ { "try-all-types", 'A', arg_flag, &try_all_flag,
+ "\ttry all known types", NULL },
+ { "raw-sequence", 'S', arg_flag, &sequence_flag,
+ "\ttry parsing leftover data", NULL },
+ { "test-encode", 0, arg_flag, &test_encode_flag,
+ "\ttest encode round trip (for memory debugging and fuzzing)", NULL },
+ { "test-copy", 0, arg_flag, &test_copy_flag,
+ "\ttest copy operation (for memory debugging and fuzzing)", NULL },
+ { "print", 'n', arg_negative_flag, &print_flag,
+ "\ttest copy operation (for memory debugging and fuzzing)", NULL },
+ { "quiet", 'q', arg_flag, &quiet_flag,
+ "\tOutput nothing (exit status 0 means type matched)", NULL },
+ { "version", 'v', arg_flag, &version_flag, NULL, NULL },
+ { "help", 'h', arg_flag, &help_flag, NULL, NULL }
+};
+int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int code)
+{
+ arg_printusage(args, num_args, NULL, "dump-file [TypeName [TypeName ...]]");
+ exit(code);
+}
+
+int
+main(int argc, char **argv)
+{
+ int optidx = 0;
+
+ setprogname(argv[0]);
+ initialize_asn1_error_table();
+ if (getarg(args, num_args, argc, argv, &optidx))
+ usage(1);
+ if (help_flag)
+ usage(0);
+ if (version_flag) {
+ print_version(NULL);
+ exit(0);
+ }
+ argv += optidx;
+ argc -= optidx;
+
+ if (sequence_flag && try_all_flag)
+ errx(1, "--raw-sequence and --try-all-types are mutually exclusive");
+ if (quiet_flag && !try_all_flag && argc < 2)
+ errx(1, "--quiet requires --try-all-types or that a TypeName be given");
+ if (!print_flag && !try_all_flag && argc < 2)
+ errx(1, "--no-print requires --try-all-types or that a TypeName be given");
+
+ if (list_types_flag) {
+ size_t i;
+
+ if (argc)
+ errx(1, "--list-types is exclusive of other options or arguments");
+
+ for (i = 0; i < sizeof(types)/sizeof(types[0]); i++)
+ printf("%s\n", types[i].name);
+ exit(0);
+ }
+
+ if (argc < 1)
+ usage(1);
+ return doit(argv);
+}
diff --git a/third_party/heimdal/lib/asn1/asn1parse.y b/third_party/heimdal/lib/asn1/asn1parse.y
new file mode 100644
index 0000000..d9e3fba
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/asn1parse.y
@@ -0,0 +1,2036 @@
+/*
+ * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id$ */
+
+%{
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include "symbol.h"
+#include "lex.h"
+#include "gen_locl.h"
+#include "der.h"
+
+static Type *new_type (Typetype t);
+/*static IOSClass *new_class(struct fieldhead *);*/
+/*static IOSObject *new_object(struct objfieldhead *);*/
+/*IOSObjectSet *new_object_set(struct objectshead *);*/
+static struct objectshead *add_object_set_spec(struct objectshead *, IOSObject *);
+static ObjectField *new_field_setting(char *, Type *, struct value *);
+static struct objfieldhead *add_field_setting(struct objfieldhead *, ObjectField *);
+static struct fieldhead *add_field_spec(struct fieldhead *, Field *);
+static Field *new_type_field(char *, int, Type *);
+static Field *new_fixed_type_value_field(char *, Type *, int, int, struct value *);
+static Type *parametrize_type(Type *, IOSClass *);
+static Type *type_from_class_field(IOSClass *, const char *);
+static void validate_object_set(IOSObjectSet *);
+/*static Type *type_from_object(const char *, const char *);*/
+static struct constraint_spec *new_constraint_spec(enum ctype);
+static Type *new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype);
+void yyerror (const char *);
+#define yyerror yyerror
+static struct objid *new_objid(const char *label, int value);
+static void add_oid_to_tail(struct objid *, struct objid *);
+static void fix_labels(Symbol *s);
+
+struct string_list {
+ char *string;
+ struct string_list *next;
+};
+
+static int default_tag_env = TE_EXPLICIT;
+static unsigned long idcounter;
+
+/* Declarations for Bison */
+#define YYMALLOC malloc
+#define YYFREE free
+
+%}
+
+%union {
+ int64_t constant;
+ struct value *value;
+ struct range *range;
+ char *name;
+ Type *type;
+ IOSClass *class;
+ IOSObjectSet *objectset;
+ IOSObject *object;
+ Field *field;
+ ObjectField *objfield;
+ Member *member;
+ IOSClass *formalparam;
+ struct objid *objid;
+ char *defval;
+ struct string_list *sl;
+ struct tagtype tag;
+ struct memhead *members;
+ struct fieldhead *fields;
+ struct objectshead *objects;
+ struct objfieldhead *objfields;
+ struct constraint_spec *constraint_spec;
+}
+
+%token kw_ABSENT
+%token kw_ABSTRACT_SYNTAX
+%token kw_ALL
+%token kw_APPLICATION
+%token kw_AUTOMATIC
+%token kw_BEGIN
+%token kw_BIT
+%token kw_BMPString
+%token kw_BOOLEAN
+%token kw_BY
+%token kw_CHARACTER
+%token kw_CHOICE
+%token kw_CLASS
+%token kw_COMPONENT
+%token kw_COMPONENTS
+%token kw_CONSTRAINED
+%token kw_CONTAINING
+%token kw_DEFAULT
+%token kw_DEFINITIONS
+%token kw_EMBEDDED
+%token kw_ENCODED
+%token kw_END
+%token kw_ENUMERATED
+%token kw_EXCEPT
+%token kw_EXPLICIT
+%token kw_EXPORTS
+%token kw_EXTENSIBILITY
+%token kw_EXTERNAL
+%token kw_FALSE
+%token kw_FROM
+%token kw_GeneralString
+%token kw_GeneralizedTime
+%token kw_GraphicString
+%token kw_IA5String
+%token kw_IDENTIFIER
+%token kw_IMPLICIT
+%token kw_IMPLIED
+%token kw_IMPORTS
+%token kw_INCLUDES
+%token kw_INSTANCE
+%token kw_INTEGER
+%token kw_INTERSECTION
+%token kw_ISO646String
+%token kw_MAX
+%token kw_MIN
+%token kw_MINUS_INFINITY
+%token kw_NULL
+%token kw_NumericString
+%token kw_OBJECT
+%token kw_OCTET
+%token kw_OF
+%token kw_OPTIONAL
+%token kw_ObjectDescriptor
+%token kw_PATTERN
+%token kw_PDV
+%token kw_PLUS_INFINITY
+%token kw_PRESENT
+%token kw_PRIVATE
+%token kw_PrintableString
+%token kw_REAL
+%token kw_RELATIVE_OID
+%token kw_SEQUENCE
+%token kw_SET
+%token kw_SIZE
+%token kw_STRING
+%token kw_SYNTAX
+%token kw_T61String
+%token kw_TAGS
+%token kw_TRUE
+%token kw_TYPE_IDENTIFIER
+%token kw_TeletexString
+%token kw_UNION
+%token kw_UNIQUE
+%token kw_UNIVERSAL
+%token kw_UTCTime
+%token kw_UTF8String
+%token kw_UniversalString
+%token kw_VideotexString
+%token kw_VisibleString
+%token kw_WITH
+
+%token RANGE
+%token EEQUAL
+%token ELLIPSIS
+
+%token <name> TYPE_IDENTIFIER referencename
+%token <name> CLASS_IDENTIFIER
+%token <name> VALUE_IDENTIFIER
+%token <name> STRING
+
+%token <constant> NUMBER
+%type <constant> SignedNumber
+%type <constant> Class tagenv
+%type <constant> DummyReference
+
+%type <name> Identifier
+
+/*
+ * The NULL keyword being both a value and a type causes a reduce/reduce
+ * conflict in the FieldSetting production since its alternatives are
+ *
+ * '&' Identifier Type
+ *
+ * and
+ *
+ * '&' Identifier Value
+ *
+ * and NULL is both a type and a value.
+ *
+ * For now we work around this by having a ValueExNull production that excludes
+ * the NULL value. To really get past this will require unifying the type and
+ * value types (e.g., via type punning).
+ */
+%type <value> Value ValueExNull
+%type <value> BuiltinValue BuiltinValueExNull
+%type <value> IntegerValue
+%type <value> BooleanValue
+%type <value> ObjectIdentifierValue
+%type <value> CharacterStringValue
+%type <value> NullValue
+%type <value> DefinedValue
+%type <value> ReferencedValue
+%type <value> Valuereference
+
+%type <class> DefinedObjectClass ParamGovernor
+%type <class> ObjectClassDefn
+%type <class> Parameter
+
+%type <type> Type
+%type <type> BuiltinType
+%type <type> BitStringType
+%type <type> BooleanType
+%type <type> ChoiceType
+%type <type> ConstrainedType
+%type <type> UnconstrainedType
+%type <type> EnumeratedType
+%type <type> IntegerType
+%type <type> NullType
+%type <type> OctetStringType
+%type <type> SequenceType
+%type <type> SequenceOfType
+%type <type> SetType
+%type <type> SetOfType
+%type <type> TaggedType
+%type <type> ReferencedType
+%type <type> DefinedType
+%type <type> UsefulType
+%type <type> ObjectIdentifierType
+%type <type> CharacterStringType
+%type <type> RestrictedCharactedStringType
+%type <type> ObjectClassFieldType
+%type <type> ParameterizedType
+/*%type <type> TypeFromObject*/
+
+%type <objectset> ObjectSet DefinedObjectSet
+%type <objectset> ActualParameter
+%type <object> Object DefinedObject ObjectDefn
+%type <objfield> FieldSetting
+
+%type <tag> Tag
+
+%type <field> FieldSpec TypeFieldSpec FixedTypeValueFieldSpec
+%type <fields> FieldSpecList
+%type <member> ComponentType
+%type <member> NamedBit
+%type <member> NamedNumber
+%type <member> NamedType
+%type <members> ComponentTypeList
+%type <members> Enumerations
+%type <members> NamedBitList
+%type <members> NamedNumberList
+%type <objects> ObjectSetSpec
+%type <objfields> FieldSettings
+
+%type <objid> objid objid_list objid_element objid_opt
+%type <range> range size
+
+%type <sl> referencenames
+
+%type <constraint_spec> Constraint
+%type <constraint_spec> ConstraintSpec
+%type <constraint_spec> SubtypeConstraint
+%type <constraint_spec> GeneralConstraint
+%type <constraint_spec> ContentsConstraint
+%type <constraint_spec> UserDefinedConstraint
+%type <constraint_spec> SimpleTableConstraint TableConstraint
+%type <constraint_spec> ComponentRelationConstraint
+
+
+%start ModuleDefinition
+
+%%
+
+/*
+ * We have sinned by allowing types to have names that start with lower-case,
+ * and values that have names that start with upper-case.
+ *
+ * UPDATE: We sin no more. However, parts of this block comment are still
+ * relevant.
+ *
+ * That worked when we only supported basic X.680 because the rules for
+ * TypeAssignment and ValueAssignment are clearly unambiguous in spite of the
+ * case issue.
+ *
+ * We now pay the price because X.681 adds productions where the only thing we
+ * have to help us distinguish certain rules is the form of an identifier: the
+ * case of its first letter.
+ *
+ * We have cleansed our sin by not allowing wrong-case identifiers any more.
+ *
+ * Some historical instances of this sin in-tree:
+ *
+ * - DOMAIN-X500-COMPRESS (value (enum) but name starts with upper-case)
+ * - krb5int32 (type but name starts with lower-case)
+ * - krb5uint32 (type but name starts with lower-case)
+ * - hdb_keyset (type but name starts with lower-case)
+ * - hdb_entry (type but name starts with lower-case)
+ * - hdb_entry_alias (type but name starts with lower-case)
+ * - HDB_DB_FORMAT INTEGER (value (int) but name starts with upper-case)
+ *
+ * We have fixed all of these and others, in some cases leaving behind aliases
+ * in header files as needed.
+ *
+ * We have one shift/reduce conflict (shift ObjectClassAssignment, reduce
+ * TypeAssignment) and one reduce/reduce conflict (ObjectAssignment vs
+ * ValueAssignment) that we avoid by requiring CLASS names to start with an
+ * underscore.
+ *
+ * In the FieldSetting rule, also, we get a reduce/reduce conflict if we use
+ * `Identifier' instead of `TYPE_IDENTIFIER' for type field settings and
+ * `VALUE_IDENTIFIER' for value field settings, and then we can't make
+ * progress.
+ *
+ * Looking forward, we may not (will not) be able to distinguish ValueSet and
+ * ObjectSet field settings from each other either, and we may not (will not)
+ * be able distinguish Object and Value field settings from each other as well.
+ * To deal with those we will have to run-time type-tag and type-pun the C
+ * structures for valueset/objectset and value/object, and have one rule for
+ * each of those that inspects the type of the item to decide what kind of
+ * setting it is.
+ *
+ * Sadly, the extended syntax for ASN.1 (x.680 + x.681/2/3) appears to have
+ * ambiguities that cannot be resolved with bison/yacc.
+ */
+Identifier : TYPE_IDENTIFIER { $$ = $1; }
+ | VALUE_IDENTIFIER { $$ = $1; };
+
+ModuleDefinition: Identifier objid_opt kw_DEFINITIONS TagDefault ExtensionDefault
+ EEQUAL kw_BEGIN ModuleBody kw_END
+ {
+ struct objid **o = objid2list($2);
+ size_t i;
+
+ fprintf(jsonfile,
+ "{\"module\":\"%s\",\"tagging\":\"%s\",\"objid\":[", $1,
+ default_tag_env == TE_EXPLICIT ? "explicit" : "implicit");
+
+ for (i = 0; o && o[i]; i++) {
+ fprintf(jsonfile, "%s{\"value\":%d", i ? "," : "", o[i]->value);
+ if (o[i]->label)
+ fprintf(jsonfile, ",\"label\":\"%s\"", o[i]->label);
+ fprintf(jsonfile, "}");
+ }
+ fprintf(jsonfile, "]}\n");
+ free(o);
+ }
+ ;
+
+TagDefault : kw_EXPLICIT kw_TAGS
+ { default_tag_env = TE_EXPLICIT; }
+ | kw_IMPLICIT kw_TAGS
+ { default_tag_env = TE_IMPLICIT; }
+ | kw_AUTOMATIC kw_TAGS
+ { lex_error_message("automatic tagging is not supported"); }
+ | /* empty */
+ ;
+
+ExtensionDefault: kw_EXTENSIBILITY kw_IMPLIED
+ { lex_error_message("no extensibility options supported"); }
+ | /* empty */
+ ;
+
+ModuleBody : Exports Imports AssignmentList
+ | /* empty */
+ ;
+
+Imports : kw_IMPORTS SymbolsImported ';'
+ | /* empty */
+ ;
+
+SymbolsImported : SymbolsFromModuleList
+ | /* empty */
+ ;
+
+SymbolsFromModuleList: SymbolsFromModule
+ | SymbolsFromModuleList SymbolsFromModule
+ ;
+
+SymbolsFromModule: referencenames kw_FROM Identifier objid_opt
+ {
+ /*
+ * FIXME We really could use knowing what kind of thing the
+ * identifier identifies -- a type, a value, what?
+ *
+ * Our sin of allowing type names to start with lower-case
+ * and values with upper-case means we can't tell. So we
+ * assume it's types only, but that means we can't import
+ * OID values, but we really want to!
+ *
+ * One thing we could do is not force `s->stype = Stype'
+ * here, instead set it to a new `Sunknown' value so that
+ * the first place that refers to this symbol with enough
+ * context to imply a symbol type can set it.
+ */
+ struct string_list *sl;
+ for(sl = $1; sl != NULL; sl = sl->next) {
+ Symbol *s = addsym(sl->string);
+ s->stype = Stype;
+ gen_template_import(s);
+ }
+ add_import($3);
+ }
+ ;
+
+Exports : kw_EXPORTS referencenames ';'
+ {
+ struct string_list *sl;
+ for(sl = $2; sl != NULL; sl = sl->next)
+ add_export(sl->string);
+ }
+ | kw_EXPORTS kw_ALL
+ | /* empty */
+ ;
+
+AssignmentList : Assignment
+ | Assignment AssignmentList
+ ;
+
+Assignment : TypeAssignment
+ | ValueAssignment
+ | ParameterizedTypeAssignment
+ | ObjectClassAssignment
+ | ObjectAssignment
+ | ObjectSetAssignment
+ /* | ParameterizedAssignment // from X.683 */
+ ;
+
+referencenames : Identifier ',' referencenames
+ {
+ $$ = emalloc(sizeof(*$$));
+ $$->string = $1;
+ $$->next = $3;
+ }
+ | Identifier
+ {
+ $$ = emalloc(sizeof(*$$));
+ $$->string = $1;
+ $$->next = NULL;
+ }
+ ;
+
+DefinedObjectClass
+ : CLASS_IDENTIFIER
+ {
+ Symbol *s = addsym($1);
+ if(s->stype != Sclass)
+ lex_error_message ("%s is not a class\n", $1);
+ $$ = s->iosclass;
+ };
+
+ObjectClassAssignment
+ : CLASS_IDENTIFIER EEQUAL ObjectClassDefn
+ {
+ Symbol *s = addsym($1);
+ s->stype = Sclass;
+ s->iosclass = $3;
+ s->iosclass->symbol = s;
+ fix_labels(s);
+ }
+ | CLASS_IDENTIFIER EEQUAL DefinedObjectClass
+ {
+ Symbol *s = addsym($1);
+ s->stype = Sclass;
+ s->iosclass = $3;
+ }
+ /* | ParameterizedObjectClass */
+ ;
+
+ObjectClassDefn : kw_CLASS '{' FieldSpecList '}'
+ {
+ $$ = ecalloc(1, sizeof(*$$));
+ $$->fields = $3;
+ $$->id = idcounter++;
+ };
+
+ObjectAssignment: VALUE_IDENTIFIER DefinedObjectClass EEQUAL Object
+ {
+ Symbol *s = addsym($1);
+ s->stype = Sobj;
+ s->object = $4;
+ s->object->iosclass = $2;
+ if (!s->object->symbol)
+ s->object->symbol = s;
+ fix_labels(s);
+ }
+ ;
+
+ObjectSetAssignment
+ : TYPE_IDENTIFIER DefinedObjectClass EEQUAL ObjectSet
+ {
+ Symbol *s = addsym($1);
+ s->stype = Sobjset;
+ s->iosclass = $2;
+ s->objectset = $4;
+ s->objectset->symbol = s->objectset->symbol ? s->objectset->symbol : s;
+ s->objectset->iosclass = $2;
+ validate_object_set($4);
+ generate_template_objectset_forwards(s);
+ }
+ ;
+
+ObjectSet : '{' ObjectSetSpec '}'
+ {
+ $$ = ecalloc(1, sizeof(*$$));
+ $$->objects = $2;
+ $$->id = idcounter++;
+ }
+ ;
+
+ObjectSetSpec : DefinedObject
+ { $$ = add_object_set_spec(NULL, $1); }
+ | ObjectSetSpec '|' DefinedObject
+ { $$ = add_object_set_spec($1, $3); }
+ ;
+
+Object : DefinedObject
+ | ObjectDefn
+ /* | ObjectFromObject */
+ /* | ParameterizedObject */
+ ;
+
+DefinedObject : VALUE_IDENTIFIER
+ {
+ Symbol *s = addsym($1);
+ if(s->stype != Sobj)
+ lex_error_message ("%s is not an object\n", $1);
+ $$ = s->object;
+ }
+ ;
+
+DefinedObjectSet: TYPE_IDENTIFIER
+ {
+ Symbol *s = addsym($1);
+ if(s->stype != Sobjset && s->stype != SUndefined)
+ lex_error_message ("%s is not an object set\n", $1);
+ $$ = s->objectset;
+ }
+ ;
+
+
+ObjectDefn : '{' FieldSettings '}' /* DefaultSyntax */
+ {
+ $$ = ecalloc(1, sizeof(*$$));
+ $$->objfields = $2;
+ $$->id = idcounter++;
+ }
+ /* | DefinedSyntax */
+ ;
+
+FieldSettings : FieldSetting
+ {
+ $$ = add_field_setting(NULL, $1);
+ }
+ | FieldSettings ',' FieldSetting
+ {
+ $$ = add_field_setting($1, $3);
+ }
+ ;
+
+/* See note on `Identifier' */
+FieldSetting : '&' Identifier Type
+ { $$ = new_field_setting($2, $3, NULL); }
+ | '&' Identifier ValueExNull
+ { $$ = new_field_setting($2, NULL, $3); }
+ /* | '&' TYPE_IDENTIFIER ValueSet */
+ /* | '&' VALUE_IDENTIFIER Object */
+ /* | '&' TYPE_IDENTIFIER ObjectSet */
+ ;
+
+/* Fields of a class */
+FieldSpecList : FieldSpec
+ { $$ = add_field_spec(NULL, $1); }
+ | FieldSpecList ',' FieldSpec
+ { $$ = add_field_spec($1, $3); };
+
+/*
+ * Fields of a CLASS
+ *
+ * There are seven kinds of class/object fields:
+ *
+ * - type fields,
+ * - fixed-type value fields,
+ * - fixed-type value set fields,
+ * - variable-type value fields
+ * - variable-type value set fields
+ * - object fields
+ * - object set fields
+ *
+ * We care only to support the bare minimum to treat open types as a CHOICE of
+ * sorts and automatically encode/decode values in open types. That's: type
+ * fields and fixed-type value fields.
+ */
+FieldSpec : TypeFieldSpec
+ | FixedTypeValueFieldSpec
+ /* | VariableTypeValueFieldSpec */
+ /* | VariableTypeValueSetFieldSpec */
+ /* | FixedTypeValueSetFieldSpec */
+ /* | ObjectFieldSpec */
+ /* | ObjectSetFieldSpec */
+ ;
+TypeFieldSpec : '&' Identifier
+ { $$ = new_type_field($2, 0, NULL); }
+ | '&' Identifier kw_OPTIONAL
+ { $$ = new_type_field($2, 1, NULL); }
+ | '&' Identifier kw_DEFAULT Type
+ { $$ = new_type_field($2, 1, $4); }
+ ;
+
+FixedTypeValueFieldSpec
+ : '&' Identifier Type
+ { $$ = new_fixed_type_value_field($2, $3, 0, 0, NULL); }
+ | '&' Identifier Type kw_UNIQUE
+ { $$ = new_fixed_type_value_field($2, $3, 1, 0, NULL); }
+ | '&' Identifier Type kw_UNIQUE kw_OPTIONAL
+ { $$ = new_fixed_type_value_field($2, $3, 1, 1, NULL); }
+ | '&' Identifier Type kw_UNIQUE kw_DEFAULT Value
+ { $$ = new_fixed_type_value_field($2, $3, 1, 0, $6); }
+ | '&' Identifier Type kw_OPTIONAL
+ { $$ = new_fixed_type_value_field($2, $3, 0, 1, NULL); }
+ | '&' Identifier Type kw_DEFAULT Value
+ { $$ = new_fixed_type_value_field($2, $3, 0, 0, $5); };
+
+/*
+ * Now we need a bit of X.683, just enough to parse PKIX.
+ *
+ * E.g., we need to parse this sort of type definition, which isn't quite the
+ * final type definition because the ExtensionSet will be provided later.
+ *
+ *-- <- ObjectClassDefn ->
+ * EXTENSION ::= CLASS {
+ * &id OBJECT IDENTIFIER UNIQUE,
+ * -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * -- FixedTypeValueFieldSpec
+ *
+ * &ExtnType,
+ * -- ^^^^^^^^^
+ * -- TypeFieldSpec
+ *
+ * &Critical BOOLEAN DEFAULT {TRUE | FALSE }
+ * -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * -- FixedTypeValueFieldSpec
+ * } WITH SYNTAX {
+ * SYNTAX &ExtnType IDENTIFIED BY &id
+ * [CRITICALITY &Critical]
+ * }
+ *
+ *-- <--------- ParameterizedTypeAssignment -------->
+ * -- NOTE: The name of this type has to be Extension, really.
+ * -- But the name of the Extension type with the actual
+ * -- parameter provided also has to be Extension.
+ * -- We could disallow that and require that the various
+ * -- Extension types all have different names, then we'd
+ * -- let the one with the actual parameter in PKIX be the
+ * -- one named Extension. Or we could find a way to let
+ * -- them all share one symbol name, or at least two:
+ * -- the one with the formal parameter, and just one with
+ * -- an actual parameter.
+ * --
+ * -- Also, IMPORTing types that have formal parameters is
+ * -- almost certainly going to require parsing the IMPORTed
+ * -- module. Until we do that, users will be able to work
+ * -- around that by just copying CLASSes and pameterized
+ * -- type definitions around. But when we do start parsing
+ * -- IMPORTed modules we might need to do something about
+ * -- many types possibly having the same names, though we
+ * -- might do nothing and simply say "don't do that!".
+ * Extension{EXTENSION:ExtensionSet} ::= SEQUENCE {
+ * -- ^^^^^^^^^^^^
+ * -- is a DummyReference, which is a Reference, basically
+ * -- it is an object set variable which will have an object
+ * -- set value supplied where constrained types are defined
+ * -- from this one, possibly anonymous types where
+ * -- SEQUENCE/SET members of this type are defined.
+ * -- ^^^^^^^^^
+ * -- is a ParamGovernor, really, just Governor, either a Type or
+ * -- DefinedObjectClass (we only need DefinedObjectClass)
+ * -- ^^^^^^^^^^^^^^^^^^^^^^
+ * -- is a Parameter
+ * -- ^^^^^^^^^^^^^^^^^^^^^^^^
+ * -- is a ParameterList (we need only support one param though)
+ * extnID EXTENSION.&id({ExtensionSet}),
+ * -- ^^^^^^^^^^^^^^^^
+ * -- simple table constraint limiting id to OIDs
+ * -- from ExtensionSet
+ * -- ^^^^^^^^^^^^^
+ * -- a reference to the id field of the EXTENSION CLASS
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING (CONTAINING
+ * -- ObjectClassFieldType
+ * -- vvvvvvvvvvvvvvvvvvv
+ * EXTENSION.&ExtnType({ExtensionSet}{@extnID}))
+ * -- ^^^^^^^^^
+ * -- AtNotation
+ * -- ^^^^^^^^^^^^^^
+ * -- DefinedObjectSet
+ * -- ^^^^^^^^^^^^^^^^^^^^^^^^
+ * -- ComponentRelationConstraint
+ * -- says that extnValue will contain
+ * -- a value of a type identified by
+ * -- the OID in extnID in the object
+ * -- set ExtensionSet (which is a set
+ * -- of {OID, type} objects)
+ * -- ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * -- ConstraintSpec
+ * -- ^^^^^^^^^^^^^^^^^^^
+ * -- another type ref
+ * }
+ *
+ * Then later we'll see (ParameterizedType, a part of DefinedType):
+ *
+ * TBSCertificate ::= SEQUENCE {
+ * ...
+ * -- Here is where the object set is linked into the
+ * -- whole thing, making *magic* possible. This is
+ * -- where the real Extensions type is defined. Sadly
+ * -- this might mean we can't have a C type named
+ * -- Extensions. Hmmm. We might need an ASN.1
+ * -- extension that lets use do this:
+ * --
+ * -- Extension ::= Extension{{CertExtensions}}
+ * --
+ * -- or
+ * --
+ * -- Extension ::= ParameterizedExtension{{CertExtensions}}
+ * --
+ * -- and then rename the Extension type above to this.
+ * -- Then we can define Extensions as a SEQUENCE OF
+ * -- that.
+ * --
+ * -- <- ParameterizedType ->
+ * extensions [3] Extensions{{CertExtensions}} OPTIONAL
+ * -- ^^^^^^^^^^^^^^
+ * -- ObjectSetSpec
+ * -- ^^^^^^^^^^^^^^^^
+ * -- ObjectSet
+ * -- ^^^^^^^^^^^^^^^^^^
+ * -- ActualParameterList
+ * -- ^^^^^^^^^^
+ * -- Type
+ * }
+ *
+ * Then:
+ *
+ * -- Object set, limits what Extensions can be in TBSCertificate.
+ *-- <- ObjectSetAssignment ->
+ * CertExtensions EXTENSION ::= {
+ * -- ^^^^^^^^^
+ * -- DefinedObjectClass
+ *-- ^^^^^^^^^^^^^^
+ *-- objectsetreference, for us, IDENTIFIER
+ * ext-AuthorityKeyIdentifier | ext-SubjectKeyIdentifier | ...
+ * }
+ *
+ * and:
+ *
+ * -- ObjectAssignment (with defined syntax, which we're not going to support):
+ * --
+ * -- Defines one particular object in the CertExtensions object set.
+ * -- We don't need th SYNTAX bits though -- ETOOMUCHWORK.
+ * -- This says that the OID id-ce-authorityKeyIdentifier means the extnValue
+ * -- is a DER-encoded AuthorityKeyIdentifier.
+ * ext-AuthorityKeyIdentifier EXTENSION ::= { SYNTAX
+ * AuthorityKeyIdentifier IDENTIFIED BY
+ * id-ce-authorityKeyIdentifier }
+ * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 }
+ *
+ * -- ObjectAssignment (with default syntax):
+ * ext-AuthorityKeyIdentifier EXTENSION ::= {
+ * -- fields don't have to be in order since we have the field names
+ * &extnId id-ce-authorityKeyIdentifier,
+ * &extnValue AuthorityKeyIdentifier
+ * }
+ *
+ * -- Plain old type def using only X.680
+ * AuthorityKeyIdentifier ::= SEQUENCE {
+ * keyIdentifier [0] KeyIdentifier OPTIONAL,
+ * authorityCertIssuer [1] GeneralNames OPTIONAL,
+ * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
+ *
+ * In terms of compilation, we'll want to support only the template backend,
+ * though we'll generate the same C types for both, the template backend and
+ * the codegen backend.
+ *
+ * The generators should see a type for Extension that includes a) the
+ * parametrization (relating members in the SEQUENCE to fields in the CLASS),
+ * and b) the object set CertExtensions for the _same_ class.
+ *
+ * - The C types for ASN.1 parametrized types with object set parameters
+ * should be laid out just as before, but with additional fields:
+ *
+ * typedef struct Extension {
+ * heim_oid extnID;
+ * int *critical;
+ * heim_octet_string extnValue;
+ * // NEW FIELDS BELOW
+ * enum {
+ * opentypechoice_unknown_Extension = 0
+ * opentypechoice_Extension_id_ce_authorityKeyIdentifier,
+ * ...
+ * } _element;
+ * union {
+ * // er, what should this be named?! we have no name information
+ * // and naming it after its object value name is probably not a good
+ * // idea or not easy. We do have the OID value and possible name
+ * // though, so we should use that:
+ * AuthorityKeyIdentifier id_ce_authorityKeyIdentifier;
+ * ...
+ * } _u;
+ * } Extension;
+ *
+ * - The template for this should consist of new struct asn1_template entries
+ * following the ones for the normal fields of Extension. The first of these
+ * should have an OP that indicates that the following N entries correspond
+ * to the object set that specifies this open type, then the following N
+ * entries should each point to an object in the object set. Or maybe the
+ * object set should be a separate template -- either way. We'll also want a
+ * flag to indicate whether the object set is sorted (none of the type IDs
+ * are IMPORTed) or not (some of the type IDs are IMPORTed) so we can binary
+ * search the object set at encode/decode time.
+ *
+ * Hmm, we can assume the object sets are already sorted when there's
+ * IMPORTed IDs -- the author can do it. Yes, they're sets, but lexically
+ * they must be in some order.
+ *
+ * I like that, actually, requiring that the module author manually sort the
+ * object sets, at least when they refer to type IDs that are IMPORTed. Or
+ * maybe forbid object sets that use IMPORTed type IDs -- the module author
+ * can always copy their definitions anyways.
+ */
+
+TypeAssignment : Identifier EEQUAL Type
+ {
+ Symbol *s = addsym($1);
+ s->stype = Stype;
+ s->type = $3;
+ fix_labels(s);
+
+ /*
+ * Hack: make sure that non-anonymous enumeration types get
+ * a symbol tacked on so we can generate a template for
+ * their members for value printing.
+ */
+ if (s->type->type == TTag && $3->symbol == NULL &&
+ $3->subtype != NULL && $3->subtype->type == TInteger &&
+ $3->subtype->symbol == NULL) {
+ $3->subtype->symbol = s;
+ }
+ if (original_order)
+ generate_type(s);
+ else
+ generate_type_header_forwards(s);
+ }
+ ;
+
+ParameterizedTypeAssignment
+ /* For now we'll only support one parameter -- enough for PKIX */
+ : Identifier '{' Parameter '}' EEQUAL Type
+ {
+ char *pname = NULL;
+ Symbol *s;
+
+ if (asprintf(&pname, "%s{%s:x}", $1, $3->symbol->name) == -1 ||
+ pname == NULL)
+ err(1, "Out of memory");
+ s = addsym(pname);
+ free($1);
+ s->stype = Sparamtype;
+ s->type = parametrize_type($6, $3);
+ s->type->symbol = s;
+ fix_labels(s);
+ }
+ ;
+
+/*
+ * We're not going to support governor variables for now. We don't need to.
+ *
+ * Also, we're not going to support more than one formal parameter.
+ * Correspondingly we'll only support a single actual parameter (the count of
+ * formal and actual parameters has to match, naturally).
+ */
+
+Parameter : ParamGovernor ':' DummyReference
+ { $$ = $1; };
+ /* | DummyReference */
+ ;
+
+DummyReference : TYPE_IDENTIFIER { $$ = idcounter++; };
+
+ParamGovernor : DefinedObjectClass
+ { $$ = $1; }
+ /* | DummyGovernor */
+ /* | Type */
+ ;
+
+UnconstrainedType : BitStringType
+ | BooleanType
+ | CharacterStringType
+ | ChoiceType
+ | EnumeratedType
+ | IntegerType
+ | NullType
+ | ObjectIdentifierType
+ | OctetStringType
+ | SequenceType
+ | SetType
+ | ObjectClassFieldType; /* X.681 */
+
+Type : BuiltinType | ReferencedType | ConstrainedType ;
+
+BuiltinType : BitStringType
+ | BooleanType
+ | CharacterStringType
+ | ChoiceType
+ | EnumeratedType
+ | IntegerType
+ | NullType
+ | ObjectIdentifierType
+ | OctetStringType
+ | SequenceType
+ | SequenceOfType
+ | SetType
+ | SetOfType
+ | TaggedType
+ | ObjectClassFieldType /* X.681 */
+ /* | InstanceOfType // X.681 */
+ ;
+
+ObjectClassFieldType
+ : DefinedObjectClass '.' '&' Identifier
+ { $$ = type_from_class_field($1, $4); };
+
+BooleanType : kw_BOOLEAN
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_Boolean,
+ TE_EXPLICIT, new_type(TBoolean));
+ }
+ ;
+
+ /*
+ * The spec says the values in a ValueRange are Values, but a) all
+ * the various value ranges do not involve OBJECT IDENTIFIER, b)
+ * we only support integer value ranges at this time (as opposed
+ * to, e.g., time ranges, and we don't even support time values at
+ * this time), c) allowing OBJECT IDENTIFIER here causes a
+ * shift-reduce conflict, so we limit ourselves to integer values
+ * in ranges. We could always define IntegerValueRange,
+ * TimeValueRange, etc. when we add support for more value types.
+ */
+range : IntegerValue RANGE IntegerValue
+ {
+ if($1->type != integervalue)
+ lex_error_message("Non-integer used in first part of range");
+ if($1->type != integervalue)
+ lex_error_message("Non-integer in second part of range");
+ $$ = ecalloc(1, sizeof(*$$));
+ $$->min = $1->u.integervalue;
+ $$->max = $3->u.integervalue;
+ }
+ | IntegerValue RANGE kw_MAX
+ {
+ if($1->type != integervalue)
+ lex_error_message("Non-integer in first part of range");
+ $$ = ecalloc(1, sizeof(*$$));
+ $$->min = $1->u.integervalue;
+ $$->max = INT_MAX;
+ }
+ | kw_MIN RANGE IntegerValue
+ {
+ if($3->type != integervalue)
+ lex_error_message("Non-integer in second part of range");
+ $$ = ecalloc(1, sizeof(*$$));
+ $$->min = INT_MIN;
+ $$->max = $3->u.integervalue;
+ }
+ | IntegerValue
+ {
+ if($1->type != integervalue)
+ lex_error_message("Non-integer used in limit");
+ $$ = ecalloc(1, sizeof(*$$));
+ $$->min = $1->u.integervalue;
+ $$->max = $1->u.integervalue;
+ }
+ ;
+
+
+IntegerType : kw_INTEGER
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_Integer,
+ TE_EXPLICIT, new_type(TInteger));
+ }
+ | kw_INTEGER '{' NamedNumberList '}'
+ {
+ $$ = new_type(TInteger);
+ $$->members = $3;
+ $$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, $$);
+ }
+ ;
+
+NamedNumberList : NamedNumber
+ {
+ $$ = emalloc(sizeof(*$$));
+ HEIM_TAILQ_INIT($$);
+ HEIM_TAILQ_INSERT_HEAD($$, $1, members);
+ }
+ | NamedNumberList ',' NamedNumber
+ {
+ HEIM_TAILQ_INSERT_TAIL($1, $3, members);
+ $$ = $1;
+ }
+ | NamedNumberList ',' ELLIPSIS
+ { $$ = $1; } /* XXX used for Enumerations */
+ ;
+
+NamedNumber : Identifier '(' SignedNumber ')'
+ {
+ $$ = emalloc(sizeof(*$$));
+ $$->name = $1;
+ $$->gen_name = estrdup($1);
+ output_name ($$->gen_name);
+ $$->val = $3;
+ $$->optional = 0;
+ $$->ellipsis = 0;
+ $$->type = NULL;
+ }
+ | Identifier '(' DefinedValue ')'
+ {
+ if ($3->type != integervalue)
+ lex_error_message("Named number %s not a numeric value",
+ $3->s->name);
+ $$ = emalloc(sizeof(*$$));
+ $$->name = $1;
+ $$->gen_name = estrdup($1);
+ output_name ($$->gen_name);
+ $$->val = $3->u.integervalue;
+ $$->optional = 0;
+ $$->ellipsis = 0;
+ $$->type = NULL;
+ }
+ ;
+
+EnumeratedType : kw_ENUMERATED '{' Enumerations '}'
+ {
+ $$ = new_type(TInteger);
+ $$->members = $3;
+ $$ = new_tag(ASN1_C_UNIV, UT_Enumerated, TE_EXPLICIT, $$);
+ }
+ ;
+
+Enumerations : NamedNumberList /* XXX */
+ ;
+
+BitStringType : kw_BIT kw_STRING
+ {
+ $$ = new_type(TBitString);
+ $$->members = emalloc(sizeof(*$$->members));
+ HEIM_TAILQ_INIT($$->members);
+ $$ = new_tag(ASN1_C_UNIV, UT_BitString, TE_EXPLICIT, $$);
+ }
+ | kw_BIT kw_STRING '{' NamedBitList '}'
+ {
+ $$ = new_type(TBitString);
+ $$->members = $4;
+ $$ = new_tag(ASN1_C_UNIV, UT_BitString, TE_EXPLICIT, $$);
+ }
+ ;
+
+ObjectIdentifierType: kw_OBJECT kw_IDENTIFIER
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_OID,
+ TE_EXPLICIT, new_type(TOID));
+ }
+ ;
+OctetStringType : kw_OCTET kw_STRING size
+ {
+ Type *t = new_type(TOctetString);
+ t->range = $3;
+ if (t->range) {
+ if (t->range->min < 0)
+ lex_error_message("can't use a negative SIZE range "
+ "length for OCTET STRING");
+ }
+ $$ = new_tag(ASN1_C_UNIV, UT_OctetString,
+ TE_EXPLICIT, t);
+ }
+ ;
+
+NullType : kw_NULL
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_Null,
+ TE_EXPLICIT, new_type(TNull));
+ }
+ ;
+
+size :
+ { $$ = NULL; }
+ | kw_SIZE '(' range ')'
+ { $$ = $3; }
+ ;
+
+
+SequenceType : kw_SEQUENCE '{' /* ComponentTypeLists */ ComponentTypeList '}'
+ {
+ $$ = new_type(TSequence);
+ $$->members = $3;
+ $$ = new_tag(ASN1_C_UNIV, UT_Sequence, default_tag_env, $$);
+ }
+ | kw_SEQUENCE '{' '}'
+ {
+ $$ = new_type(TSequence);
+ $$->members = NULL;
+ $$ = new_tag(ASN1_C_UNIV, UT_Sequence, default_tag_env, $$);
+ }
+ ;
+
+SequenceOfType : kw_SEQUENCE size kw_OF Type
+ {
+ $$ = new_type(TSequenceOf);
+ $$->range = $2;
+ if ($$->range) {
+ if ($$->range->min < 0)
+ lex_error_message("can't use a negative SIZE range "
+ "length for SEQUENCE OF");
+ }
+
+ $$->subtype = $4;
+ $$ = new_tag(ASN1_C_UNIV, UT_Sequence, default_tag_env, $$);
+ }
+ ;
+
+SetType : kw_SET '{' /* ComponentTypeLists */ ComponentTypeList '}'
+ {
+ $$ = new_type(TSet);
+ $$->members = $3;
+ $$ = new_tag(ASN1_C_UNIV, UT_Set, default_tag_env, $$);
+ }
+ | kw_SET '{' '}'
+ {
+ $$ = new_type(TSet);
+ $$->members = NULL;
+ $$ = new_tag(ASN1_C_UNIV, UT_Set, default_tag_env, $$);
+ }
+ ;
+
+SetOfType : kw_SET kw_OF Type
+ {
+ $$ = new_type(TSetOf);
+ $$->subtype = $3;
+ $$ = new_tag(ASN1_C_UNIV, UT_Set, default_tag_env, $$);
+ }
+ ;
+
+ChoiceType : kw_CHOICE '{' /* AlternativeTypeLists */ ComponentTypeList '}'
+ {
+ $$ = new_type(TChoice);
+ $$->members = $3;
+ }
+ ;
+
+ReferencedType : DefinedType
+ | UsefulType
+ /* | TypeFromObject // X.681 */
+ /* | ValueSetFromObjects // X.681 */
+ ;
+
+/*
+TypeFromObject : VALUE_IDENTIFIER '.' '&' TYPE_IDENTIFIER
+ { $$ = type_from_object($1, $4); };
+ */
+
+DefinedType : TYPE_IDENTIFIER
+ {
+ Symbol *s = addsym($1);
+ $$ = new_type(TType);
+ if(s->stype != Stype && s->stype != SUndefined)
+ lex_error_message ("%s is not a type\n", $1);
+ else
+ $$->symbol = s;
+ }
+ | ParameterizedType
+ { $$ = $1; }
+ ;
+
+ /*
+ * Should be ActualParameterList, but we'll do just one for now
+ * as that's enough for PKIX.
+ */
+ParameterizedType
+ : Identifier '{' ActualParameter '}' /* XXX ActualParameterList */
+ {
+ Symbol *s, *ps;
+ char *pname = NULL;
+
+ if ($3 == NULL) {
+ lex_error_message("Unknown ActualParameter object set parametrizing %s\n", $1);
+ exit(1);
+ }
+
+ /* Lookup the type from a ParameterizedTypeAssignment */
+ if (asprintf(&pname, "%s{%s:x}", $1,
+ $3->iosclass->symbol->name) == -1 ||
+ pname == NULL)
+ err(1, "Out of memory");
+ ps = addsym(pname);
+ if (ps->stype != Sparamtype)
+ lex_error_message ("%s is not a parameterized type\n", $1);
+
+ s = addsym($1);
+ $$ = ps->type; /* XXX copy, probably */
+ if (!ps->type)
+ errx(1, "Wrong class (%s) parameter for parameterized "
+ "type %s", $3->iosclass->symbol->name, $1);
+ s->stype = Stype;
+ if(s->stype != Stype && s->stype != SUndefined)
+ lex_error_message ("%s is not a type\n", $1);
+ else
+ $$->symbol = s;
+ $$->actual_parameter = $3;
+ if ($$->type == TTag)
+ $$->subtype->actual_parameter = $3;
+ }
+
+/*
+ * Per X.683 $1 for ActualParameter should be any of: a Type, a Value, a
+ * ValueSet, a DefinedObjectClass, an Object, or an ObjectSet. For PKIX we
+ * need nothing more than an ObjectSet here.
+ *
+ * Also, we can't lexically or syntactically tell the difference between all
+ * these things, though fortunately we can for ObjectSet.
+ */
+ActualParameter : DefinedObjectSet
+ { $$ = $1; };
+
+UsefulType : kw_GeneralizedTime
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_GeneralizedTime,
+ TE_EXPLICIT, new_type(TGeneralizedTime));
+ }
+ | kw_UTCTime
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_UTCTime,
+ TE_EXPLICIT, new_type(TUTCTime));
+ }
+ ;
+
+ConstrainedType : UnconstrainedType Constraint
+ {
+ $$ = $1;
+ if ($2->ctype == CT_RANGE) {
+ if ($1->type != TTag || $1->subtype->type != TInteger)
+ lex_error_message("RANGE constraints apply only to INTEGER types");
+ $$->subtype->range = $2->u.range;
+ free($2);
+ } else {
+ $$->constraint = $2;
+ }
+ /* if (Constraint.type == contentConstraint) {
+ assert(Constraint.u.constraint.type == octetstring|bitstring-w/o-NamedBitList); // remember to check type reference too
+ if (Constraint.u.constraint.type) {
+ assert((Constraint.u.constraint.type.length % 8) == 0);
+ }
+ }
+ if (Constraint.u.constraint.encoding) {
+ type == der-oid|ber-oid
+ }
+ */
+ }
+ ;
+
+
+Constraint : '(' ConstraintSpec ')'
+ {
+ $$ = $2;
+ }
+ ;
+
+ConstraintSpec : SubtypeConstraint | GeneralConstraint
+ ;
+
+SubtypeConstraint: range
+ {
+ $$ = new_constraint_spec(CT_RANGE);
+ $$->u.range = $1;
+ }
+
+GeneralConstraint: ContentsConstraint
+ | UserDefinedConstraint
+ | TableConstraint
+ ;
+
+ContentsConstraint: kw_CONTAINING Type
+ {
+ $$ = new_constraint_spec(CT_CONTENTS);
+ $$->u.content.type = $2;
+ $$->u.content.encoding = NULL;
+ }
+ | kw_ENCODED kw_BY Value
+ {
+ if ($3->type != objectidentifiervalue)
+ lex_error_message("Non-OID used in ENCODED BY constraint");
+ $$ = new_constraint_spec(CT_CONTENTS);
+ $$->u.content.type = NULL;
+ $$->u.content.encoding = $3;
+ }
+ | kw_CONTAINING Type kw_ENCODED kw_BY Value
+ {
+ if ($5->type != objectidentifiervalue)
+ lex_error_message("Non-OID used in ENCODED BY constraint");
+ $$ = new_constraint_spec(CT_CONTENTS);
+ $$->u.content.type = $2;
+ $$->u.content.encoding = $5;
+ }
+ ;
+
+UserDefinedConstraint: kw_CONSTRAINED kw_BY '{' '}'
+ {
+ $$ = new_constraint_spec(CT_USER);
+ }
+ ;
+
+TableConstraint : SimpleTableConstraint
+ { $$ = $1; }
+ | ComponentRelationConstraint
+ { $$ = $1; };
+
+SimpleTableConstraint
+ : '{' TYPE_IDENTIFIER '}'
+ {
+ $$ = ecalloc(1, sizeof(*$$));
+ $$->ctype = CT_TABLE_CONSTRAINT;
+ $$->u.content.crel.objectname = $2;
+ $$->u.content.crel.membername = 0;
+ };
+
+/*
+ * In X.682, ComponentRelationConstraint is a fantastically more complicated
+ * production. The stuff in the second set of braces is a list of AtNotation,
+ * and AtNotation is '@' followed by some number of '.'s, followed by a
+ * ComponentIdList, which is a non-empty set of identifiers separated by '.'s.
+ * The number of '.'s is a "level" used to identify a SET, SEQUENCE, or CHOICE
+ * where the path of member identifiers is rooted that ultimately identifies
+ * the field providing the constraint.
+ *
+ * So in
+ *
+ * extnValue OCTET STRING
+ * (CONTAINING
+ * EXTENSION.&ExtnType({ExtensionSet}{@extnID}))
+ * ^^^^^^^^^^^^^^^^^^^
+ * ObjectClassFieldType
+ * meaning the open type field
+ * &ExtnType of EXTENSION
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
+ * GeneralConstraint
+ * ^^^^^^^^^^^^^^^^^^^^^^^
+ * ComponentRelationConstraint
+ * ^^^^^^^^^^^^^^
+ * DefinedObjectSet
+ * ^^^^^^^^
+ * '{' AtNotation ',' + '}'
+ *
+ * we have EXTENSION.&ExtnType is the ObjectClassFieldType, and
+ * ({ExtensionSet}{@extnID}) is the ComponentRelationConstraint on the
+ * extnValue member, where {ExtensionSet} is the DummyReference from the formal
+ * parameter of the enclosing parameterized type, and {@extnID} is the
+ * AtNotation list identifying the field of the class/objects-in-the-object-set
+ * that will be identifying the type of the extnValue field.
+ *
+ * We need just the one AtNotation component.
+ */
+ComponentRelationConstraint
+ : '{' TYPE_IDENTIFIER '}' '{' '@' Identifier '}'
+ {
+ $$ = ecalloc(1, sizeof(*$$));
+ $$->ctype = CT_TABLE_CONSTRAINT;
+ $$->u.content.crel.objectname = $2;
+ $$->u.content.crel.membername = $6;
+ };
+
+TaggedType : Tag tagenv Type
+ {
+ $$ = new_type(TTag);
+ $$->tag = $1;
+ $$->tag.tagenv = $2;
+ if (template_flag) {
+ $$->subtype = $3;
+ } else if ($2 == TE_IMPLICIT) {
+ Type *t = $3;
+
+ /*
+ * FIXME We shouldn't do this... The logic for
+ * dealing with IMPLICIT tags belongs elsewhere.
+ */
+ while (t->type == TType) {
+ if (t->subtype)
+ t = t->subtype;
+ else if (t->symbol && t->symbol->type)
+ t = t->symbol->type;
+ else
+ break;
+ }
+ /*
+ * IMPLICIT tags of CHOICE types are EXPLICIT
+ * instead.
+ */
+ if (t->type == TChoice) {
+ $$->implicit_choice = 1;
+ $$->tag.tagenv = TE_EXPLICIT;
+ }
+ if($3->type == TTag && $2 == TE_IMPLICIT) {
+ $$->subtype = $3->subtype;
+ free($3);
+ } else {
+ $$->subtype = $3;
+ }
+ } else {
+ $$->subtype = $3;
+ }
+ }
+ ;
+
+Tag : '[' Class NUMBER ']'
+ {
+ $$.tagclass = $2;
+ $$.tagvalue = $3;
+ $$.tagenv = default_tag_env;
+ }
+ ;
+
+Class : /* */
+ {
+ $$ = ASN1_C_CONTEXT;
+ }
+ | kw_UNIVERSAL
+ {
+ $$ = ASN1_C_UNIV;
+ }
+ | kw_APPLICATION
+ {
+ $$ = ASN1_C_APPL;
+ }
+ | kw_PRIVATE
+ {
+ $$ = ASN1_C_PRIVATE;
+ }
+ ;
+
+tagenv : /* */
+ {
+ $$ = default_tag_env;
+ }
+ | kw_EXPLICIT
+ {
+ $$ = default_tag_env;
+ }
+ | kw_IMPLICIT
+ {
+ $$ = TE_IMPLICIT;
+ }
+ ;
+
+
+ValueAssignment : VALUE_IDENTIFIER Type EEQUAL Value
+ {
+ Symbol *s;
+ s = addsym ($1);
+
+ s->stype = SValue;
+ s->value = $4;
+ generate_constant (s);
+ /*
+ * Save this value's name so we can know some name for
+ * this value wherever _a_ name may be needed for it.
+ *
+ * This is useful for OIDs used as type IDs in objects
+ * sets of classes with open types. We'll generate
+ * enum labels from those OIDs' names.
+ */
+ s->value->s = s;
+ }
+ ;
+
+CharacterStringType: RestrictedCharactedStringType
+ ;
+
+RestrictedCharactedStringType: kw_GeneralString
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_GeneralString,
+ TE_EXPLICIT, new_type(TGeneralString));
+ }
+ | kw_TeletexString
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_TeletexString,
+ TE_EXPLICIT, new_type(TTeletexString));
+ }
+ | kw_UTF8String
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_UTF8String,
+ TE_EXPLICIT, new_type(TUTF8String));
+ }
+ | kw_PrintableString
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_PrintableString,
+ TE_EXPLICIT, new_type(TPrintableString));
+ }
+ | kw_VisibleString
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_VisibleString,
+ TE_EXPLICIT, new_type(TVisibleString));
+ }
+ | kw_IA5String
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_IA5String,
+ TE_EXPLICIT, new_type(TIA5String));
+ }
+ | kw_BMPString
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_BMPString,
+ TE_EXPLICIT, new_type(TBMPString));
+ }
+ | kw_UniversalString
+ {
+ $$ = new_tag(ASN1_C_UNIV, UT_UniversalString,
+ TE_EXPLICIT, new_type(TUniversalString));
+ }
+
+ ;
+
+ComponentTypeList: ComponentType
+ {
+ $$ = emalloc(sizeof(*$$));
+ HEIM_TAILQ_INIT($$);
+ HEIM_TAILQ_INSERT_HEAD($$, $1, members);
+ }
+ | ComponentTypeList ',' ComponentType
+ {
+ HEIM_TAILQ_INSERT_TAIL($1, $3, members);
+ $$ = $1;
+ }
+ | ComponentTypeList ',' ELLIPSIS
+ {
+ struct member *m = ecalloc(1, sizeof(*m));
+ m->name = estrdup("...");
+ m->gen_name = estrdup("asn1_ellipsis");
+ m->ellipsis = 1;
+ HEIM_TAILQ_INSERT_TAIL($1, m, members);
+ $$ = $1;
+ }
+ ;
+
+NamedType : Identifier Type
+ {
+ $$ = emalloc(sizeof(*$$));
+ $$->name = $1;
+ $$->gen_name = estrdup($1);
+ output_name ($$->gen_name);
+ $$->type = $2;
+ $$->ellipsis = 0;
+ }
+ ;
+
+ComponentType : NamedType
+ {
+ $$ = $1;
+ $$->optional = 0;
+ $$->defval = NULL;
+ }
+ | NamedType kw_OPTIONAL
+ {
+ $$ = $1;
+ $$->optional = 1;
+ $$->defval = NULL;
+ }
+ | NamedType kw_DEFAULT Value
+ {
+ $$ = $1;
+ $$->optional = 0;
+ $$->defval = $3;
+ }
+ ;
+
+NamedBitList : NamedBit
+ {
+ $$ = emalloc(sizeof(*$$));
+ HEIM_TAILQ_INIT($$);
+ HEIM_TAILQ_INSERT_HEAD($$, $1, members);
+ }
+ | NamedBitList ',' NamedBit
+ {
+ HEIM_TAILQ_INSERT_TAIL($1, $3, members);
+ $$ = $1;
+ }
+ ;
+
+NamedBit : Identifier '(' NUMBER ')'
+ {
+ $$ = emalloc(sizeof(*$$));
+ $$->name = $1;
+ $$->gen_name = estrdup($1);
+ output_name ($$->gen_name);
+ $$->val = $3;
+ $$->optional = 0;
+ $$->ellipsis = 0;
+ $$->type = NULL;
+ }
+ ;
+
+objid_opt : objid
+ | /* empty */ { $$ = NULL; }
+ ;
+
+objid : '{' objid_list '}'
+ {
+ $$ = $2;
+ }
+ ;
+
+objid_list : /* empty */
+ {
+ $$ = NULL;
+ }
+ | objid_element objid_list
+ {
+ if ($2) {
+ $$ = $2;
+ add_oid_to_tail($2, $1);
+ } else {
+ $$ = $1;
+ }
+ }
+ ;
+
+objid_element : Identifier '(' NUMBER ')'
+ {
+ $$ = new_objid($1, $3);
+ }
+ | Identifier
+ {
+ Symbol *s = addsym($1);
+ if(s->stype != SValue ||
+ s->value->type != objectidentifiervalue) {
+ lex_error_message("%s is not an object identifier\n",
+ s->name);
+ exit(1);
+ }
+ $$ = s->value->u.objectidentifiervalue;
+ }
+ | NUMBER
+ {
+ $$ = new_objid(NULL, $1);
+ }
+ ;
+
+Value : BuiltinValue
+ | ReferencedValue
+ ;
+
+ValueExNull : BuiltinValueExNull
+ | ReferencedValue
+ ;
+
+BuiltinValue : BooleanValue
+ | CharacterStringValue
+ | IntegerValue
+ | ObjectIdentifierValue
+ | NullValue
+ ;
+
+BuiltinValueExNull
+ : BooleanValue
+ | CharacterStringValue
+ | IntegerValue
+ | ObjectIdentifierValue
+ ;
+
+ReferencedValue : DefinedValue
+ ;
+
+DefinedValue : Valuereference
+ ;
+
+Valuereference : VALUE_IDENTIFIER
+ {
+ Symbol *s = addsym($1);
+ if(s->stype != SValue)
+ lex_error_message ("%s is not a value\n",
+ s->name);
+ else
+ $$ = s->value;
+ }
+ ;
+
+CharacterStringValue: STRING
+ {
+ $$ = emalloc(sizeof(*$$));
+ $$->type = stringvalue;
+ $$->u.stringvalue = $1;
+ }
+ ;
+
+BooleanValue : kw_TRUE
+ {
+ $$ = emalloc(sizeof(*$$));
+ $$->type = booleanvalue;
+ $$->u.booleanvalue = 1;
+ }
+ | kw_FALSE
+ {
+ $$ = emalloc(sizeof(*$$));
+ $$->type = booleanvalue;
+ $$->u.booleanvalue = 0;
+ }
+ ;
+
+IntegerValue : SignedNumber
+ {
+ $$ = emalloc(sizeof(*$$));
+ $$->type = integervalue;
+ $$->u.integervalue = $1;
+ }
+ ;
+
+SignedNumber : NUMBER
+ ;
+
+NullValue : kw_NULL
+ {
+ }
+ ;
+
+ObjectIdentifierValue: objid
+ {
+ $$ = emalloc(sizeof(*$$));
+ $$->type = objectidentifiervalue;
+ $$->u.objectidentifiervalue = $1;
+ }
+ ;
+
+%%
+
+void
+yyerror (const char *s)
+{
+ lex_error_message ("%s\n", s);
+}
+
+static Type *
+new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype)
+{
+ Type *t;
+ if(oldtype->type == TTag && oldtype->tag.tagenv == TE_IMPLICIT) {
+ t = oldtype;
+ oldtype = oldtype->subtype; /* XXX */
+ } else
+ t = new_type (TTag);
+
+ t->tag.tagclass = tagclass;
+ t->tag.tagvalue = tagvalue;
+ t->tag.tagenv = tagenv;
+ t->subtype = oldtype;
+ return t;
+}
+
+static struct objid *
+new_objid(const char *label, int value)
+{
+ struct objid *s;
+ s = emalloc(sizeof(*s));
+ s->label = label;
+ s->value = value;
+ s->next = NULL;
+ return s;
+}
+
+static void
+add_oid_to_tail(struct objid *head, struct objid *tail)
+{
+ struct objid *o;
+ o = head;
+ while (o->next)
+ o = o->next;
+ o->next = tail;
+}
+
+static Type *
+new_type (Typetype tt)
+{
+ Type *t = ecalloc(1, sizeof(*t));
+ t->type = tt;
+ t->id = idcounter++;
+ return t;
+}
+
+static struct constraint_spec *
+new_constraint_spec(enum ctype ct)
+{
+ struct constraint_spec *c = ecalloc(1, sizeof(*c));
+ c->ctype = ct;
+ return c;
+}
+
+static void fix_labels2(Type *t, const char *prefix);
+static void fix_labels1(struct memhead *members, const char *prefix)
+{
+ Member *m;
+
+ if(members == NULL)
+ return;
+ HEIM_TAILQ_FOREACH(m, members, members) {
+ if (asprintf(&m->label, "%s_%s", prefix, m->gen_name) < 0)
+ errx(1, "malloc");
+ if (m->label == NULL)
+ errx(1, "malloc");
+ if(m->type != NULL)
+ fix_labels2(m->type, m->label);
+ }
+}
+
+static void fix_labels2(Type *t, const char *prefix)
+{
+ for(; t; t = t->subtype)
+ fix_labels1(t->members, prefix);
+}
+
+static void
+fix_labels(Symbol *s)
+{
+ char *p = NULL;
+ if (asprintf(&p, "choice_%s", s->gen_name) < 0 || p == NULL)
+ errx(1, "malloc");
+ if (s->type)
+ fix_labels2(s->type, p);
+ free(p);
+}
+
+static struct objectshead *
+add_object_set_spec(struct objectshead *lst, IOSObject *o)
+{
+ if (lst == NULL) {
+ lst = emalloc(sizeof(*lst));
+ HEIM_TAILQ_INIT(lst);
+ HEIM_TAILQ_INSERT_HEAD(lst, o, objects);
+ } else {
+ HEIM_TAILQ_INSERT_TAIL(lst, o, objects);
+ }
+ return lst;
+}
+
+static struct objfieldhead *
+add_field_setting(struct objfieldhead *lst, ObjectField *f)
+{
+ if (lst == NULL) {
+ lst = emalloc(sizeof(*lst));
+ HEIM_TAILQ_INIT(lst);
+ HEIM_TAILQ_INSERT_HEAD(lst, f, objfields);
+ } else {
+ HEIM_TAILQ_INSERT_TAIL(lst, f, objfields);
+ }
+ return lst;
+}
+
+static struct fieldhead *
+add_field_spec(struct fieldhead *lst, Field *f)
+{
+ if (lst == NULL) {
+ lst = emalloc(sizeof(*lst));
+ HEIM_TAILQ_INIT(lst);
+ HEIM_TAILQ_INSERT_HEAD(lst, f, fields);
+ } else {
+ HEIM_TAILQ_INSERT_TAIL(lst, f, fields);
+ }
+ return lst;
+}
+
+static ObjectField *
+new_field_setting(char *n, Type *t, struct value *v)
+{
+ ObjectField *of;
+
+ of = ecalloc(1, sizeof(*of));
+ of->value = v;
+ of->type = t;
+ of->name = n;
+ return of;
+}
+
+static Field *
+new_type_field(char *n, int optional, Type *t)
+{
+ Field *f;
+
+ f = ecalloc(1, sizeof(*f));
+ f->optional = optional;
+ f->unique = 0;
+ f->defval = 0;
+ f->type = t;
+ f->name = n;
+ return f;
+}
+
+static Field *
+new_fixed_type_value_field(char *n, Type *t, int unique, int optional, struct value *defval)
+{
+ Field *f;
+
+ f = ecalloc(1, sizeof(*f));
+ f->optional = optional;
+ f->unique = unique;
+ f->defval = defval;
+ f->type = t;
+ f->name = n;
+ return f;
+}
+
+static Type *
+parametrize_type(Type *t, IOSClass *c)
+{
+ Type *type;
+
+ type = new_type(TType);
+ *type = *t; /* XXX Copy, or use subtype; this only works as long as we don't cleanup! */
+ type->formal_parameter = c;
+ return type;
+}
+
+static Type *
+type_from_class_field(IOSClass *c, const char *n)
+{
+ Field *f;
+ Type *t;
+
+ HEIM_TAILQ_FOREACH(f, c->fields, fields) {
+ if (strcmp(f->name, n) == 0) {
+ t = new_type(TType);
+ if (f->type) {
+ *t = *f->type;
+ } else {
+ Symbol *s = addsym("HEIM_ANY");
+ if(s->stype != Stype && s->stype != SUndefined)
+ errx(1, "Do not define HEIM_ANY, only import it\n");
+ s->stype = Stype;
+ t->symbol = s;
+ }
+ t->typeref.iosclass = c;
+ t->typeref.field = f;
+ return t;
+ }
+ }
+ return NULL;
+}
+
+static void
+validate_object_set(IOSObjectSet *os)
+{
+ IOSObject **objects;
+ ObjectField *of;
+ IOSObject *o;
+ Field *cf;
+ size_t nobjs, i;
+
+ /* Check unique fields */
+ HEIM_TAILQ_FOREACH(cf, os->iosclass->fields, fields) {
+ if (!cf->unique)
+ continue;
+ if (!cf->type)
+ errx(1, "Type fields of classes can't be UNIQUE (%s)",
+ os->iosclass->symbol->name);
+ sort_object_set(os, cf, &objects, &nobjs);
+ for (i = 0; i < nobjs; i++) {
+ HEIM_TAILQ_FOREACH(of, objects[i]->objfields, objfields) {
+ if (strcmp(cf->name, of->name) != 0)
+ continue;
+ if (!of->value)
+ errx(1, "Value not specified for required UNIQUE field %s of object %s",
+ cf->name, objects[i]->symbol->name);
+ break;
+ }
+ if (i == 0)
+ continue;
+ if (object_cmp(&objects[i - 1], &objects[i]) == 0)
+ errx(1, "Duplicate values of UNIQUE field %s of objects %s and %s",
+ cf->name, objects[i - 1]->symbol->name,
+ objects[i]->symbol->name);
+ }
+ free(objects);
+ }
+
+ /* Check required fields */
+ HEIM_TAILQ_FOREACH(cf, os->iosclass->fields, fields) {
+ if (cf->optional || cf->defval || !cf->type)
+ continue;
+ HEIM_TAILQ_FOREACH(o, os->objects, objects) {
+ int specified = 0;
+
+ HEIM_TAILQ_FOREACH(of, o->objfields, objfields) {
+ if (strcmp(of->name, cf->name) != 0)
+ continue;
+ if (of->value)
+ specified = 1;
+ break;
+ }
+ if (!specified)
+ errx(1, "Value not specified for required non-UNIQUE field %s of object %s",
+ cf->name, o->symbol->name);
+ }
+ }
+}
diff --git a/third_party/heimdal/lib/asn1/canthandle.asn1 b/third_party/heimdal/lib/asn1/canthandle.asn1
new file mode 100644
index 0000000..4378428
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/canthandle.asn1
@@ -0,0 +1,15 @@
+-- $Id$ --
+
+CANTHANDLE DEFINITIONS ::= BEGIN
+
+-- Currently the compiler handles SET { ... } types, but does NOT sort
+-- their members as should be done in the case of conforming DER encoders.
+-- The workaround is to sort the members of such types manually in their
+-- definitions. See X.690, section 10.3, and X.680, section 8.6 for details.
+
+-- Can't handle primitives in SET OF, causing the compiler to crash
+-- Workaround is to define a type that is only an integer and use that
+
+Baz ::= SET OF INTEGER
+
+END
diff --git a/third_party/heimdal/lib/asn1/check-ber.c b/third_party/heimdal/lib/asn1/check-ber.c
new file mode 100644
index 0000000..57450f4
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/check-ber.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2008 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <der_locl.h>
+#include <rfc2459_asn1.h>
+#include <cms_asn1.h>
+
+
+RCSID("$Id$");
+
+static const unsigned char *contentdata = (unsigned char *)
+ "\x30\x80\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x07\x02\xa0\x80\x30"
+ "\x80\x02\x01\x03\x31\x0b\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05"
+ "\x00\x30\x80\x06\x07\x2b\x06\x01\x05\x02\x03\x01\xa0\x80\x24\x80"
+ "\x04\x40\x30\x3e\xa0\x3c\x30\x3a\xa0\x05\x02\x03\x0e\x03\x86\xa1"
+ "\x11\x18\x0f\x32\x30\x30\x38\x31\x32\x31\x33\x31\x39\x34\x35\x34"
+ "\x32\x5a\xa2\x06\x02\x04\xba\xbd\x97\x8a\xa3\x16\x04\x14\x41\x28"
+ "\x79\xa8\xd0\xe4\xb1\x0f\xb1\xfc\xa6\x0b\x4d\x2b\x85\x3d\xd9\x17"
+ "\x3f\xdc\x00\x00\x00\x00\x00\x00\xa0\x82\x0b\x6c\x30\x82\x05\x57"
+ "\x30\x82\x04\x3f\xa0\x03\x02\x01\x02\x02\x03\x47\x3d\x05\x30\x0d"
+ "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x81\x86"
+ "\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1d\x30"
+ "\x1b\x06\x03\x55\x04\x0a\x13\x14\x41\x70\x70\x6c\x65\x20\x43\x6f"
+ "\x6d\x70\x75\x74\x65\x72\x2c\x20\x49\x6e\x63\x2e\x31\x2d\x30\x2b"
+ "\x06\x03\x55\x04\x0b\x13\x24\x41\x70\x70\x6c\x65\x20\x43\x6f\x6d"
+ "\x70\x75\x74\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74"
+ "\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x29\x30\x27\x06"
+ "\x03\x55\x04\x03\x13\x20\x41\x70\x70\x6c\x65\x20\x2e\x4d\x61\x63"
+ "\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74"
+ "\x68\x6f\x72\x69\x74\x79\x30\x1e\x17\x0d\x30\x38\x31\x30\x30\x31"
+ "\x30\x38\x30\x36\x33\x33\x5a\x17\x0d\x30\x39\x31\x30\x30\x32\x30"
+ "\x38\x30\x36\x33\x33\x5a\x30\x71\x31\x0b\x30\x09\x06\x03\x55\x04"
+ "\x06\x13\x02\x55\x53\x31\x13\x30\x11\x06\x03\x55\x04\x0a\x13\x0a"
+ "\x41\x70\x70\x6c\x65\x20\x49\x6e\x63\x2e\x31\x0f\x30\x0d\x06\x03"
+ "\x55\x04\x0b\x13\x06\x6d\x65\x2e\x63\x6f\x6d\x31\x15\x30\x13\x06"
+ "\x03\x55\x04\x03\x13\x0c\x62\x69\x74\x63\x6f\x6c\x6c\x65\x63\x74"
+ "\x6f\x72\x31\x25\x30\x23\x06\x03\x55\x04\x0d\x13\x1c\x4d\x6f\x62"
+ "\x69\x6c\x65\x4d\x65\x20\x53\x68\x61\x72\x69\x6e\x67\x20\x43\x65"
+ "\x72\x74\x69\x66\x69\x63\x61\x74\x65\x30\x81\xa3\x30\x0d\x06\x09"
+ "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x91\x00\x30"
+ "\x81\x8d\x02\x81\x81\x00\xe1\x15\xd8\xfa\xe9\xc2\xb7\x2e\xf0\xd9"
+ "\xbe\xdb\x0c\xd8\xcb\xf3\x88\x13\xd7\x22\xf8\x4d\xf4\xb6\x31\x17"
+ "\xe5\x92\x42\xef\x15\xe4\x5f\x12\x58\x3d\x8d\x0b\xa4\x03\x76\xe0"
+ "\xd0\xf2\x46\xb4\x4b\x14\x78\x23\x1c\x38\xb0\x99\xff\x36\x6f\x0e"
+ "\x26\xdf\x76\xd0\x01\x03\x7a\xd9\xcd\x1c\x92\xa6\x10\x5e\xed\x8a"
+ "\xb0\xfe\x9b\x8c\x96\xb0\x91\x9f\x97\xd0\xf4\x9c\x81\x8e\xbf\xb5"
+ "\x41\x24\x81\xb0\x1b\xb3\x8c\xd3\x92\x5c\xfd\x2b\x04\x61\xc3\x21"
+ "\x6c\xa9\xe4\xa0\xfe\xa5\x1c\x76\xfd\xda\x3b\x81\x7c\xa0\x5c\x2c"
+ "\xf6\x8f\x6e\x74\x52\x35\x02\x07\x01\x00\x01\x00\x01\x00\x01\xa3"
+ "\x82\x02\x60\x30\x82\x02\x5c\x30\x0c\x06\x03\x55\x1d\x13\x01\x01"
+ "\xff\x04\x02\x30\x00\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04"
+ "\x04\x03\x02\x03\x88\x30\x28\x06\x03\x55\x1d\x25\x04\x21\x30\x1f"
+ "\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02\x06\x0a\x2a\x86\x48\x86"
+ "\xf7\x63\x64\x03\x02\x01\x06\x07\x2b\x06\x01\x05\x02\x03\x04\x30"
+ "\x1d\x06\x03\x55\x1d\x0e\x04\x16\x04\x14\x11\xb3\x15\xb5\xab\x31"
+ "\xbb\xa5\x48\xee\xd6\x33\xd2\x86\xc3\x0b\x2a\x4c\x5e\x94\x30\x1f"
+ "\x06\x03\x55\x1d\x23\x04\x18\x30\x16\x80\x14\x7a\x7d\x90\xb1\x30"
+ "\x59\x08\x92\x91\xf9\x53\xb9\x71\x1d\x35\x33\x67\x34\x8b\xd5\x30"
+ "\x81\xa5\x06\x08\x2b\x06\x01\x05\x05\x07\x01\x01\x04\x81\x98\x30"
+ "\x81\x95\x30\x27\x06\x08\x2b\x06\x01\x05\x05\x07\x30\x01\x86\x1b"
+ "\x68\x74\x74\x70\x3a\x2f\x2f\x63\x65\x72\x74\x69\x6e\x66\x6f\x2e"
+ "\x6d\x65\x2e\x63\x6f\x6d\x2f\x6f\x63\x73\x70\x30\x44\x06\x08\x2b"
+ "\x06\x01\x05\x05\x07\x30\x02\x86\x38\x68\x74\x74\x70\x3a\x2f\x2f"
+ "\x77\x77\x77\x2e\x61\x70\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x63\x65"
+ "\x72\x74\x69\x66\x69\x63\x61\x74\x65\x61\x75\x74\x68\x6f\x72\x69"
+ "\x74\x79\x2f\x63\x61\x73\x69\x67\x6e\x65\x72\x73\x2e\x68\x74\x6d"
+ "\x6c\x30\x24\x06\x03\x55\x1d\x12\x86\x1d\x68\x74\x74\x70\x3a\x2f"
+ "\x2f\x63\x65\x72\x74\x69\x6e\x66\x6f\x2e\x6d\x65\x2e\x63\x6f\x6d"
+ "\x2f\x43\x41\x2e\x63\x65\x72\x30\x82\x01\x28\x06\x03\x55\x1d\x20"
+ "\x04\x82\x01\x1f\x30\x82\x01\x1b\x30\x82\x01\x17\x06\x09\x2a\x86"
+ "\x48\x86\xf7\x63\x64\x05\x02\x30\x82\x01\x08\x30\x40\x06\x08\x2b"
+ "\x06\x01\x05\x05\x07\x02\x01\x16\x34\x68\x74\x74\x70\x3a\x2f\x2f"
+ "\x77\x77\x77\x2e\x61\x70\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x63\x65"
+ "\x72\x74\x69\x66\x69\x63\x61\x74\x65\x61\x75\x74\x68\x6f\x72\x69"
+ "\x74\x79\x2f\x74\x65\x72\x6d\x73\x2e\x68\x74\x6d\x6c\x30\x81\xc3"
+ "\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x81\xb6\x1a\x81\xb3"
+ "\x52\x65\x6c\x69\x61\x6e\x63\x65\x20\x6f\x6e\x20\x74\x68\x69\x73"
+ "\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x62\x79\x20"
+ "\x61\x6e\x79\x20\x70\x61\x72\x74\x79\x20\x61\x73\x73\x75\x6d\x65"
+ "\x73\x20\x61\x63\x63\x65\x70\x74\x61\x6e\x63\x65\x20\x6f\x66\x20"
+ "\x74\x68\x65\x20\x74\x68\x65\x6e\x20\x61\x70\x70\x6c\x69\x63\x61"
+ "\x62\x6c\x65\x20\x73\x74\x61\x6e\x64\x61\x72\x64\x20\x74\x65\x72"
+ "\x6d\x73\x20\x61\x6e\x64\x20\x63\x6f\x6e\x64\x69\x74\x69\x6f\x6e"
+ "\x73\x20\x6f\x66\x20\x75\x73\x65\x2c\x20\x63\x65\x72\x74\x69\x66"
+ "\x69\x63\x61\x74\x65\x20\x70\x6f\x6c\x69\x63\x79\x20\x61\x6e\x64"
+ "\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x70"
+ "\x72\x61\x63\x74\x69\x63\x65\x20\x73\x74\x61\x74\x65\x6d\x65\x6e"
+ "\x74\x73\x2e\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05"
+ "\x05\x00\x03\x82\x01\x01\x00\x39\xb1\x81\xbe\x55\xf1\xb1\xe4\x16"
+ "\x5d\x7c\x5b\x6a\xe8\xcf\xee\xaa\x87\x91\x81\xf2\x57\x0d\x32\x6c"
+ "\xc6\x47\xdc\x71\x70\xfa\x7c\x47\x84\x7f\xa5\x69\x1b\x4c\x52\x98"
+ "\x7f\xc8\x1f\x62\x06\x83\xae\x0a\xef\x55\x29\x35\xb3\xa0\x04\x88"
+ "\xa6\x45\x0a\xd0\xd7\x4e\x5c\x63\x3e\xe7\xb2\x28\x85\xd3\x01\x56"
+ "\x2b\x89\xb5\x60\x9a\xa5\x9d\x85\x0d\x76\x9e\xe1\x4a\x54\x8b\x6f"
+ "\xad\xc4\xc2\x43\x2f\x18\xaa\x18\x1a\x64\x2f\x2e\xe3\xc9\xb8\xa8"
+ "\xdd\xba\x53\xc4\x18\xcf\x4e\x30\xbf\x06\xa7\xdb\x12\x34\x24\x5c"
+ "\x71\x60\x2a\xd2\x93\xef\x54\x83\x4e\x5d\xc5\x5f\x00\x8d\x02\x85"
+ "\xe5\x17\x68\x46\xfa\xd4\x45\x96\x71\xf7\x93\x58\x4d\x83\x6b\x01"
+ "\xcb\xdb\x7d\x61\x67\x69\xbe\xf1\x4c\x4b\xe2\x3e\xf6\x4e\x62\x77"
+ "\x26\x86\xc4\x3b\x96\x38\x27\x0b\x02\x0d\x07\xc9\x95\x53\x6d\x03"
+ "\xff\x61\xfb\x67\x7f\x8a\x2e\x2f\xc5\xff\x5a\xf9\x53\xd8\xb3\xae"
+ "\xf1\x05\x27\x92\x79\x22\xd5\x55\x6e\xd6\xbf\xdb\x9d\xad\xbf\xbf"
+ "\x7d\x15\xd8\x1c\x3d\x63\x86\xf1\xf1\x78\xfe\xfb\x62\x06\x8c\xf4"
+ "\x0f\xa8\x91\xa8\x7c\xef\x51\x96\x09\x52\x68\xec\x09\xdd\xb9\x9a"
+ "\x62\x49\xac\xbe\x20\x20\x9b\x30\x82\x06\x0d\x30\x82\x04\xf5\xa0"
+ "\x03\x02\x01\x02\x02\x01\x0f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7"
+ "\x0d\x01\x01\x05\x05\x00\x30\x81\x86\x31\x0b\x30\x09\x06\x03\x55"
+ "\x04\x06\x13\x02\x55\x53\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13"
+ "\x14\x41\x70\x70\x6c\x65\x20\x43\x6f\x6d\x70\x75\x74\x65\x72\x2c"
+ "\x20\x49\x6e\x63\x2e\x31\x2d\x30\x2b\x06\x03\x55\x04\x0b\x13\x24"
+ "\x41\x70\x70\x6c\x65\x20\x43\x6f\x6d\x70\x75\x74\x65\x72\x20\x43"
+ "\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f"
+ "\x72\x69\x74\x79\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x41"
+ "\x70\x70\x6c\x65\x20\x52\x6f\x6f\x74\x20\x43\x65\x72\x74\x69\x66"
+ "\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x30"
+ "\x1e\x17\x0d\x30\x35\x30\x32\x31\x30\x32\x30\x33\x38\x32\x37\x5a"
+ "\x17\x0d\x31\x31\x31\x31\x31\x30\x32\x30\x33\x38\x32\x37\x5a\x30"
+ "\x81\x86\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31"
+ "\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13\x14\x41\x70\x70\x6c\x65\x20"
+ "\x43\x6f\x6d\x70\x75\x74\x65\x72\x2c\x20\x49\x6e\x63\x2e\x31\x2d"
+ "\x30\x2b\x06\x03\x55\x04\x0b\x13\x24\x41\x70\x70\x6c\x65\x20\x43"
+ "\x6f\x6d\x70\x75\x74\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63"
+ "\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x31\x29\x30"
+ "\x27\x06\x03\x55\x04\x03\x13\x20\x41\x70\x70\x6c\x65\x20\x2e\x4d"
+ "\x61\x63\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41"
+ "\x75\x74\x68\x6f\x72\x69\x74\x79\x30\x82\x01\x22\x30\x0d\x06\x09"
+ "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00"
+ "\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xbb\x73\x84\xb0\x48\x36\x64"
+ "\xf8\x1f\xa2\x57\x89\xb6\xe2\x71\x3c\x36\x5e\x56\xeb\xdb\x96\x16"
+ "\x23\x1c\x81\xd0\x14\x2d\xd6\xf0\x4b\x22\x9b\x3f\xb7\x7a\x2c\xa2"
+ "\xf0\x69\x48\x33\xb7\x9e\xef\x68\xe7\xbc\x30\x07\x73\xbc\x61\xb0"
+ "\x01\x51\xef\x44\xdf\xdb\x45\x04\x96\x80\x2c\x7b\xe8\x93\x1f\x89"
+ "\x92\x60\x21\xcd\x34\x55\x00\x66\x31\x03\x01\x01\x44\x25\x94\x0b"
+ "\x42\x78\xca\x5a\x05\x1e\x77\x73\x24\x75\x6a\xc8\x45\x9c\xef\x2b"
+ "\x2a\x51\x29\x8f\xeb\x7e\x62\xd7\xfa\xcd\x32\xfd\x31\xe8\xcd\xde"
+ "\xab\x0d\xb5\xb4\x56\xc2\x68\x51\x09\x0c\x29\xe5\x38\x7b\x50\x68"
+ "\xbe\x00\x87\x8c\x56\xef\xd3\x1b\xa3\xc9\x6e\xa6\x74\x43\xeb\x83"
+ "\xd4\x63\x5f\x13\x79\x1e\xf8\x85\xbf\xbf\x73\x69\x36\xc5\x56\x12"
+ "\x6c\xe4\xee\xaf\x86\xab\x65\xb6\x04\xf0\x5a\x63\x2d\xa3\x31\x6c"
+ "\xe8\x48\x10\x65\xc0\x74\x45\x0d\x97\x58\x90\x3d\x91\x83\x14\xf2"
+ "\x6f\xba\xad\x2f\x6c\x41\x6e\x3c\xb7\x8f\x72\x4a\x1d\xf0\xb7\x1a"
+ "\xc0\xf0\x72\x0b\x3d\x9d\x7a\x8b\x4d\xb0\x33\xb7\x5f\x83\xef\x08"
+ "\x5b\x5f\x35\x35\x3b\x52\xdf\x30\xb1\x00\x6c\xa6\x3a\x86\xc4\xf4"
+ "\x7c\xe1\x79\x74\x5f\x0b\x35\xb8\xe1\x02\x03\x01\x00\x01\xa3\x82"
+ "\x02\x82\x30\x82\x02\x7e\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff"
+ "\x04\x04\x03\x02\x01\x86\x30\x0f\x06\x03\x55\x1d\x13\x01\x01\xff"
+ "\x04\x05\x30\x03\x01\x01\xff\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16"
+ "\x04\x14\x7a\x7d\x90\xb1\x30\x59\x08\x92\x91\xf9\x53\xb9\x71\x1d"
+ "\x35\x33\x67\x34\x8b\xd5\x30\x1f\x06\x03\x55\x1d\x23\x04\x18\x30"
+ "\x16\x80\x14\x2b\xd0\x69\x47\x94\x76\x09\xfe\xf4\x6b\x8d\x2e\x40"
+ "\xa6\xf7\x47\x4d\x7f\x08\x5e\x30\x82\x01\x28\x06\x03\x55\x1d\x20"
+ "\x04\x82\x01\x1f\x30\x82\x01\x1b\x30\x82\x01\x17\x06\x09\x2a\x86"
+ "\x48\x86\xf7\x63\x64\x05\x02\x30\x82\x01\x08\x30\x40\x06\x08\x2b"
+ "\x06\x01\x05\x05\x07\x02\x01\x16\x34\x68\x74\x74\x70\x3a\x2f\x2f"
+ "\x77\x77\x77\x2e\x61\x70\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x63\x65"
+ "\x72\x74\x69\x66\x69\x63\x61\x74\x65\x61\x75\x74\x68\x6f\x72\x69"
+ "\x74\x79\x2f\x74\x65\x72\x6d\x73\x2e\x68\x74\x6d\x6c\x30\x81\xc3"
+ "\x06\x08\x2b\x06\x01\x05\x05\x07\x02\x02\x30\x81\xb6\x1a\x81\xb3"
+ "\x52\x65\x6c\x69\x61\x6e\x63\x65\x20\x6f\x6e\x20\x74\x68\x69\x73"
+ "\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x62\x79\x20"
+ "\x61\x6e\x79\x20\x70\x61\x72\x74\x79\x20\x61\x73\x73\x75\x6d\x65"
+ "\x73\x20\x61\x63\x63\x65\x70\x74\x61\x6e\x63\x65\x20\x6f\x66\x20"
+ "\x74\x68\x65\x20\x74\x68\x65\x6e\x20\x61\x70\x70\x6c\x69\x63\x61"
+ "\x62\x6c\x65\x20\x73\x74\x61\x6e\x64\x61\x72\x64\x20\x74\x65\x72"
+ "\x6d\x73\x20\x61\x6e\x64\x20\x63\x6f\x6e\x64\x69\x74\x69\x6f\x6e"
+ "\x73\x20\x6f\x66\x20\x75\x73\x65\x2c\x20\x63\x65\x72\x74\x69\x66"
+ "\x69\x63\x61\x74\x65\x20\x70\x6f\x6c\x69\x63\x79\x20\x61\x6e\x64"
+ "\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x20\x70"
+ "\x72\x61\x63\x74\x69\x63\x65\x20\x73\x74\x61\x74\x65\x6d\x65\x6e"
+ "\x74\x73\x2e\x30\x43\x06\x03\x55\x1d\x1f\x04\x3c\x30\x3a\x30\x38"
+ "\xa0\x36\xa0\x34\x86\x32\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77"
+ "\x2e\x61\x70\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x63\x65\x72\x74\x69"
+ "\x66\x69\x63\x61\x74\x65\x61\x75\x74\x68\x6f\x72\x69\x74\x79\x2f"
+ "\x72\x6f\x6f\x74\x2e\x63\x72\x6c\x30\x81\xa9\x06\x08\x2b\x06\x01"
+ "\x05\x05\x07\x01\x01\x04\x81\x9c\x30\x81\x99\x30\x44\x06\x08\x2b"
+ "\x06\x01\x05\x05\x07\x30\x02\x86\x38\x68\x74\x74\x70\x3a\x2f\x2f"
+ "\x77\x77\x77\x2e\x61\x70\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x63\x65"
+ "\x72\x74\x69\x66\x69\x63\x61\x74\x65\x61\x75\x74\x68\x6f\x72\x69"
+ "\x74\x79\x2f\x63\x61\x73\x69\x67\x6e\x65\x72\x73\x2e\x68\x74\x6d"
+ "\x6c\x30\x51\x06\x03\x55\x1d\x12\x86\x4a\x68\x74\x74\x70\x3a\x2f"
+ "\x2f\x77\x77\x77\x2e\x61\x70\x70\x6c\x65\x2e\x63\x6f\x6d\x2f\x63"
+ "\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x61\x75\x74\x68\x6f\x72"
+ "\x69\x74\x79\x2f\x41\x70\x70\x6c\x65\x43\x6f\x6d\x70\x75\x74\x65"
+ "\x72\x52\x6f\x6f\x74\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65"
+ "\x2e\x63\x65\x72\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01"
+ "\x05\x05\x00\x03\x82\x01\x01\x00\x16\x06\xe5\x56\x65\x44\x7d\xd0"
+ "\xaa\x99\x29\xe5\xc6\x97\x0b\x02\x43\x25\x88\x8c\x42\xba\xfb\xd6"
+ "\x5b\xb7\x20\x10\x69\x04\x4e\x91\x81\x08\xec\xf5\x23\x1f\xd2\x6d"
+ "\x3f\x35\xae\xdb\xff\xb8\xc9\x2b\x4b\x28\x73\xc4\x26\x03\xe1\x92"
+ "\x5e\xb2\x84\x0d\xa7\x13\xc6\x34\x54\xf1\x49\x1f\xa9\x47\x88\xb1"
+ "\x40\x9b\xd3\x61\x93\x5b\xcf\xc7\x53\xe7\x9f\x54\x7b\x30\xc6\xb8"
+ "\x3a\x89\x6f\x06\x09\x45\xa1\x94\x98\xbe\x8b\xea\x25\x7d\x91\x89"
+ "\xf9\x27\x62\xb9\x5f\x2d\xea\xa9\xe7\x96\x5c\xbe\xe5\x84\x6d\xe8"
+ "\x50\x27\xb4\xb1\xea\x9f\xf7\x92\x0d\x54\x86\xf0\x37\x31\x47\x0d"
+ "\x54\xde\x91\xe8\x78\xe8\x61\x27\x7c\xc3\xea\xd0\xfc\x21\xa1\x08"
+ "\xc8\xe5\x01\x0e\x15\xf5\x61\x60\xce\xff\xbd\x44\xd6\x8a\x1b\x67"
+ "\xf8\x1f\x82\xe2\xa6\xb3\xfc\x3a\xc7\x30\xae\x93\x89\x29\x2e\x81"
+ "\x43\x0c\x9b\xd5\x18\xa6\x74\x66\x7d\x1c\x79\xe6\x22\xef\xba\xf8"
+ "\x23\xb3\xd3\x50\x76\x20\xde\x7a\x93\x91\x40\xcd\x16\xad\x82\x6a"
+ "\xe6\xe7\x25\xf5\xb3\xbb\x36\x61\x38\x8f\xaf\x36\x5f\x4b\xae\xc1"
+ "\xc6\x89\x99\xb1\xb1\xd9\xf1\xa3\x51\x50\xa1\x00\x3d\xdd\x16\x89"
+ "\xcf\x35\x05\x62\xa0\x8b\x48\x0a\x31\x82\x01\x35\x30\x82\x01\x31"
+ "\x02\x01\x01\x30\x81\x8e\x30\x81\x86\x31\x0b\x30\x09\x06\x03\x55"
+ "\x04\x06\x13\x02\x55\x53\x31\x1d\x30\x1b\x06\x03\x55\x04\x0a\x13"
+ "\x14\x41\x70\x70\x6c\x65\x20\x43\x6f\x6d\x70\x75\x74\x65\x72\x2c"
+ "\x20\x49\x6e\x63\x2e\x31\x2d\x30\x2b\x06\x03\x55\x04\x0b\x13\x24"
+ "\x41\x70\x70\x6c\x65\x20\x43\x6f\x6d\x70\x75\x74\x65\x72\x20\x43"
+ "\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f"
+ "\x72\x69\x74\x79\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x41"
+ "\x70\x70\x6c\x65\x20\x2e\x4d\x61\x63\x20\x43\x65\x72\x74\x69\x66"
+ "\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6f\x72\x69\x74\x79\x02"
+ "\x03\x47\x3d\x05\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x30"
+ "\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x04\x81"
+ "\x80\x6d\xba\xa5\x44\x89\x98\x2d\x5e\xc4\xf6\xc0\x1e\x36\x70\x63"
+ "\x43\xf6\x61\x3c\x0b\x43\x32\x50\x54\x95\x1e\x51\x41\x17\xd2\x7f"
+ "\x47\x00\x21\x92\x61\xbf\x42\x63\xa4\xc8\x3a\x7f\x8d\x36\xea\xf1"
+ "\x2d\x9f\x0c\x30\xbc\xe1\x5e\x16\xea\xcc\x01\xdf\xbd\x6b\xc8\xc3"
+ "\xad\x12\x0e\x6a\x4d\xd5\xad\x15\x41\xcd\xde\xb9\xf9\xf5\xf2\xdc"
+ "\x65\xaf\x61\x28\x68\x40\x52\x59\xf8\xb8\xa6\xec\xce\xed\x5e\x16"
+ "\x7b\xbd\x72\x5e\x6a\x6e\x8b\x29\xb2\x97\x22\xe9\x99\xa3\xd6\xa9"
+ "\x0e\xb3\x5e\xd3\x18\x24\x06\x20\x78\xc8\xa7\xa8\xe7\x76\x3a\x8a"
+ "\x19\x00\x00\x00\x00\x00\x00";
+
+static size_t contentlen = 3367;
+
+
+static int
+test_ber(void)
+{
+ ContentInfo ci;
+ size_t size;
+ int ret;
+
+ ret = decode_ContentInfo(contentdata, contentlen, &ci, &size);
+ if (ret)
+ return 1;
+
+ free_ContentInfo(&ci);
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret = 0;
+
+ ret += test_ber();
+
+ return ret;
+}
diff --git a/third_party/heimdal/lib/asn1/check-common.c b/third_party/heimdal/lib/asn1/check-common.c
new file mode 100644
index 0000000..8a6b5da
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/check-common.c
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 1999 - 2006 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <roken.h>
+
+#include "asn1-common.h"
+#include "check-common.h"
+
+struct map_page {
+ void *start;
+ size_t size;
+ void *data_start;
+ size_t data_size;
+ enum map_type type;
+};
+
+/* #undef HAVE_MMAP */
+
+void *
+map_alloc(enum map_type type, const void *buf,
+ size_t size, struct map_page **map)
+{
+#ifndef HAVE_MMAP
+ unsigned char *p;
+ size_t len = size + sizeof(long) * 2;
+ int i;
+
+ *map = ecalloc(1, sizeof(**map));
+
+ p = emalloc(len);
+ (*map)->type = type;
+ (*map)->start = p;
+ (*map)->size = len;
+ (*map)->data_start = p + sizeof(long);
+ for (i = sizeof(long); i > 0; i--)
+ p[sizeof(long) - i] = 0xff - i;
+ for (i = sizeof(long); i > 0; i--)
+ p[len - i] = 0xff - i;
+#else
+ unsigned char *p;
+ int flags, ret, fd;
+ size_t pagesize = getpagesize();
+
+ *map = ecalloc(1, sizeof(**map));
+
+ (*map)->type = type;
+
+#ifdef MAP_ANON
+ flags = MAP_ANON;
+ fd = -1;
+#else
+ flags = 0;
+ fd = open ("/dev/zero", O_RDONLY);
+ if(fd < 0)
+ err (1, "open /dev/zero");
+#endif
+ flags |= MAP_PRIVATE;
+
+ (*map)->size = size + pagesize - (size % pagesize) + pagesize * 2;
+
+ p = (unsigned char *)mmap(0, (*map)->size, PROT_READ | PROT_WRITE,
+ flags, fd, 0);
+ if (p == (unsigned char *)MAP_FAILED)
+ err (1, "mmap");
+
+ (*map)->start = p;
+
+ ret = mprotect (p, pagesize, 0);
+ if (ret < 0)
+ err (1, "mprotect");
+
+ ret = mprotect (p + (*map)->size - pagesize, pagesize, 0);
+ if (ret < 0)
+ err (1, "mprotect");
+
+ switch (type) {
+ case OVERRUN:
+ (*map)->data_start = p + (*map)->size - pagesize - size;
+ break;
+ case UNDERRUN:
+ (*map)->data_start = p + pagesize;
+ break;
+ default:
+ abort();
+ }
+#endif
+ (*map)->data_size = size;
+ if (buf)
+ memcpy((*map)->data_start, buf, size);
+ return (*map)->data_start;
+}
+
+void
+map_free(struct map_page *map, const char *test_name, const char *map_name)
+{
+#ifndef HAVE_MMAP
+ unsigned char *p = map->start;
+ int i;
+
+ for (i = sizeof(long); i > 0; i--)
+ if (p[sizeof(long) - i] != 0xff - i)
+ errx(1, "%s: %s underrun %d\n", test_name, map_name, i);
+ for (i = sizeof(long); i > 0; i--)
+ if (p[map->size - i] != 0xff - i)
+ errx(1, "%s: %s overrun %lu\n", test_name, map_name,
+ (unsigned long)map->size - i);
+ free(map->start);
+#else
+ int ret;
+
+ ret = munmap (map->start, map->size);
+ if (ret < 0)
+ err (1, "munmap");
+#endif
+ free(map);
+}
+
+static void
+print_bytes (unsigned const char *buf, size_t len)
+{
+ int i;
+
+ for (i = 0; i < len; ++i)
+ printf ("%02x ", buf[i]);
+}
+
+#ifndef MAP_FAILED
+#define MAP_FAILED (-1)
+#endif
+
+static char *current_test = "<uninit>";
+static char *current_state = "<uninit>";
+
+static RETSIGTYPE
+segv_handler(int sig)
+{
+ int fd;
+ char msg[] = "SIGSEGV i current test: ";
+ /* For compilers that insist we check write(2)'s result here */
+ int e = 1;
+
+ fd = open("/dev/stdout", O_WRONLY, 0600);
+ if (fd >= 0) {
+
+ if (write(fd, msg, sizeof(msg)) == -1 ||
+ write(fd, current_test, strlen(current_test)) == -1 ||
+ write(fd, " ", 1) == -1 ||
+ write(fd, current_state, strlen(current_state)) == -1 ||
+ write(fd, "\n", 1) == -1)
+ e = 2;
+ (void) close(fd);
+ }
+ _exit(e);
+}
+
+int
+generic_test (const struct test_case *tests,
+ unsigned ntests,
+ size_t data_size,
+ int (ASN1CALL *encode)(unsigned char *, size_t, void *, size_t *),
+ size_t (ASN1CALL *length)(void *),
+ int (ASN1CALL *decode)(unsigned char *, size_t, void *, size_t *),
+ void (ASN1CALL *free_data)(void *),
+ int (*cmp)(void *a, void *b),
+ int (ASN1CALL *copy)(const void *from, void *to))
+{
+ unsigned char *buf, *buf2;
+ int i;
+ int failures = 0;
+ void *data;
+ struct map_page *data_map, *buf_map, *buf2_map;
+
+#ifdef HAVE_SIGACTION
+ struct sigaction sa, osa;
+#endif
+
+ for (i = 0; i < ntests; ++i) {
+ int ret;
+ size_t sz, consumed_sz, length_sz, buf_sz;
+ void *to = NULL;
+
+ current_test = tests[i].name;
+
+ current_state = "init";
+
+#ifdef HAVE_SIGACTION
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+#ifdef SA_RESETHAND
+ sa.sa_flags |= SA_RESETHAND;
+#endif
+ sa.sa_handler = segv_handler;
+ sigaction (SIGSEGV, &sa, &osa);
+#endif
+
+ data = map_alloc(OVERRUN, NULL, data_size, &data_map);
+
+ buf_sz = tests[i].byte_len;
+ buf = map_alloc(UNDERRUN, NULL, buf_sz, &buf_map);
+
+ current_state = "encode";
+ ret = (*encode) (buf + buf_sz - 1, buf_sz,
+ tests[i].val, &sz);
+ if (ret != 0) {
+ printf ("encoding of %s failed %d\n", tests[i].name, ret);
+ ++failures;
+ continue;
+ }
+ if (sz != tests[i].byte_len) {
+ printf ("encoding of %s has wrong len (%lu != %lu)\n",
+ tests[i].name,
+ (unsigned long)sz, (unsigned long)tests[i].byte_len);
+ ++failures;
+ continue;
+ }
+
+ current_state = "length";
+ length_sz = (*length) (tests[i].val);
+ if (sz != length_sz) {
+ printf ("length for %s is bad (%lu != %lu)\n",
+ tests[i].name, (unsigned long)length_sz, (unsigned long)sz);
+ ++failures;
+ continue;
+ }
+
+ current_state = "memcmp";
+ if (memcmp (buf, tests[i].bytes, tests[i].byte_len) != 0) {
+ printf ("encoding of %s has bad bytes:\n"
+ "correct: ", tests[i].name);
+ print_bytes ((unsigned char *)tests[i].bytes, tests[i].byte_len);
+ printf ("\nactual: ");
+ print_bytes (buf, sz);
+ printf ("\n");
+#if 0
+ rk_dumpdata("correct", tests[i].bytes, tests[i].byte_len);
+ rk_dumpdata("actual", buf, sz);
+ exit (1);
+#endif
+ ++failures;
+ continue;
+ }
+
+ buf2 = map_alloc(OVERRUN, buf, sz, &buf2_map);
+
+ current_state = "decode";
+ ret = (*decode) (buf2, sz, data, &consumed_sz);
+ if (ret != 0) {
+ printf ("decoding of %s failed %d\n", tests[i].name, ret);
+ ++failures;
+ continue;
+ }
+ if (sz != consumed_sz) {
+ printf ("different length decoding %s (%ld != %ld)\n",
+ tests[i].name,
+ (unsigned long)sz, (unsigned long)consumed_sz);
+ ++failures;
+ continue;
+ }
+ current_state = "cmp";
+ if ((*cmp)(data, tests[i].val) != 0) {
+ printf ("%s: comparison failed\n", tests[i].name);
+ ++failures;
+ continue;
+ }
+
+ current_state = "copy";
+ if (copy) {
+ to = emalloc(data_size);
+ ret = (*copy)(data, to);
+ if (ret != 0) {
+ printf ("copy of %s failed %d\n", tests[i].name, ret);
+ ++failures;
+ continue;
+ }
+
+ current_state = "cmp-copy";
+ if ((*cmp)(data, to) != 0) {
+ printf ("%s: copy comparison failed\n", tests[i].name);
+ ++failures;
+ continue;
+ }
+ }
+
+ current_state = "free";
+ if (free_data) {
+ (*free_data)(data);
+ if (to) {
+ (*free_data)(to);
+ free(to);
+ }
+ }
+
+ current_state = "free";
+ map_free(buf_map, tests[i].name, "encode");
+ map_free(buf2_map, tests[i].name, "decode");
+ map_free(data_map, tests[i].name, "data");
+
+#ifdef HAVE_SIGACTION
+ sigaction (SIGSEGV, &osa, NULL);
+#endif
+ }
+ current_state = "done";
+ return failures;
+}
+
+/*
+ * check for failures
+ *
+ * a test size (byte_len) of -1 means that the test tries to trigger a
+ * integer overflow (and later a malloc of to little memory), just
+ * allocate some memory and hope that is enough for that test.
+ */
+
+int
+generic_decode_fail (const struct test_case *tests,
+ unsigned ntests,
+ size_t data_size,
+ int (ASN1CALL *decode)(unsigned char *, size_t, void *, size_t *))
+{
+ unsigned char *buf;
+ int i;
+ int failures = 0;
+ void *data;
+ struct map_page *data_map, *buf_map;
+
+#ifdef HAVE_SIGACTION
+ struct sigaction sa, osa;
+#endif
+
+ for (i = 0; i < ntests; ++i) {
+ int ret;
+ size_t sz;
+ const void *bytes;
+
+ current_test = tests[i].name;
+
+ current_state = "init";
+
+#ifdef HAVE_SIGACTION
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+#ifdef SA_RESETHAND
+ sa.sa_flags |= SA_RESETHAND;
+#endif
+ sa.sa_handler = segv_handler;
+ sigaction (SIGSEGV, &sa, &osa);
+#endif
+
+ data = map_alloc(OVERRUN, NULL, data_size, &data_map);
+
+ if (tests[i].byte_len < 0xffffff && tests[i].byte_len >= 0) {
+ sz = tests[i].byte_len;
+ bytes = tests[i].bytes;
+ } else {
+ sz = 4096;
+ bytes = NULL;
+ }
+
+ buf = map_alloc(OVERRUN, bytes, sz, &buf_map);
+
+ if (tests[i].byte_len == -1)
+ memset(buf, 0, sz);
+
+ current_state = "decode";
+ ret = (*decode) (buf, tests[i].byte_len, data, &sz);
+ if (ret == 0) {
+ printf ("sucessfully decoded %s\n", tests[i].name);
+ ++failures;
+ continue;
+ }
+
+ current_state = "free";
+ if (buf)
+ map_free(buf_map, tests[i].name, "encode");
+ map_free(data_map, tests[i].name, "data");
+
+#ifdef HAVE_SIGACTION
+ sigaction (SIGSEGV, &osa, NULL);
+#endif
+ }
+ current_state = "done";
+ return failures;
+}
diff --git a/third_party/heimdal/lib/asn1/check-common.h b/third_party/heimdal/lib/asn1/check-common.h
new file mode 100644
index 0000000..6ea1f81
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/check-common.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1999 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define IF_OPT_COMPARE(ac,bc,e) \
+ if (((ac)->e == NULL && (bc)->e != NULL) || (((ac)->e != NULL && (bc)->e == NULL))) return 1; \
+ if ((ac)->e)
+#define COMPARE_OPT_STRING(ac,bc,e) \
+ do { if (strcmp(*(ac)->e, *(bc)->e) != 0) return 1; } while(0)
+#define COMPARE_OPT_OCTET_STRING(ac,bc,e) \
+ do { if ((ac)->e->length != (bc)->e->length || memcmp((ac)->e->data, (bc)->e->data, (ac)->e->length) != 0) return 1; } while(0)
+#define COMPARE_STRING(ac,bc,e) \
+ do { if (strcmp((ac)->e, (bc)->e) != 0) return 1; } while(0)
+#define COMPARE_INTEGER(ac,bc,e) \
+ do { if ((ac)->e != (bc)->e) return 1; } while(0)
+#define COMPARE_OPT_INTEGER(ac,bc,e) \
+ do { if (*(ac)->e != *(bc)->e) return 1; } while(0)
+#define COMPARE_MEM(ac,bc,e,len) \
+ do { if (memcmp((ac)->e, (bc)->e,len) != 0) return 1; } while(0)
+#define COMPARE_OCTET_STRING(ac,bc,e) \
+ do { if ((ac)->e.length != (bc)->e.length || memcmp((ac)->e.data, (bc)->e.data, (ac)->e.length) != 0) return 1; } while(0)
+
+struct test_case {
+ void *val;
+ ssize_t byte_len;
+ const char *bytes;
+ char *name;
+};
+
+typedef int (ASN1CALL *generic_encode)(unsigned char *, size_t, void *, size_t *);
+typedef size_t (ASN1CALL *generic_length)(void *);
+typedef int (ASN1CALL *generic_decode)(unsigned char *, size_t, void *, size_t *);
+typedef void (ASN1CALL *generic_free)(void *);
+typedef int (ASN1CALL *generic_copy)(const void *, void *);
+
+int
+generic_test (const struct test_case *tests,
+ unsigned ntests,
+ size_t data_size,
+ int (ASN1CALL *encode)(unsigned char *, size_t, void *, size_t *),
+ size_t (ASN1CALL *length)(void *),
+ int (ASN1CALL *decode)(unsigned char *, size_t, void *, size_t *),
+ void (ASN1CALL *free_data)(void *),
+ int (*cmp)(void *a, void *b),
+ int (ASN1CALL *copy)(const void *a, void *b));
+
+int
+generic_decode_fail(const struct test_case *tests,
+ unsigned ntests,
+ size_t data_size,
+ int (ASN1CALL *decode)(unsigned char *, size_t, void *, size_t *));
+
+
+struct map_page;
+
+enum map_type { OVERRUN, UNDERRUN };
+
+struct map_page;
+
+void * map_alloc(enum map_type, const void *, size_t, struct map_page **);
+void map_free(struct map_page *, const char *, const char *);
diff --git a/third_party/heimdal/lib/asn1/check-der.c b/third_party/heimdal/lib/asn1/check-der.c
new file mode 100644
index 0000000..58c1446
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/check-der.c
@@ -0,0 +1,1215 @@
+/*
+ * Copyright (c) 1999 - 2007 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+#include <err.h>
+#include <roken.h>
+
+#include <asn1-common.h>
+#include <asn1_err.h>
+#include <der.h>
+
+#include "check-common.h"
+
+RCSID("$Id$");
+
+static int
+cmp_integer (void *a, void *b)
+{
+ int *ia = (int *)a;
+ int *ib = (int *)b;
+
+ return *ib - *ia;
+}
+
+static int
+test_integer (void)
+{
+ struct test_case tests[] = {
+ {NULL, 1, "\x00", NULL },
+ {NULL, 1, "\x7f", NULL },
+ {NULL, 2, "\x00\x80", NULL },
+ {NULL, 2, "\x01\x00", NULL },
+ {NULL, 1, "\x80", NULL },
+ {NULL, 2, "\xff\x7f", NULL },
+ {NULL, 1, "\xff", NULL },
+ {NULL, 2, "\xff\x01", NULL },
+ {NULL, 2, "\x00\xff", NULL },
+ {NULL, 2, "\xfe\x01", NULL },
+ {NULL, 4, "\x7f\xff\xff\xff", NULL }
+ };
+
+ int values[] = {0, 127, 128, 256, -128, -129, -1, -255, 255,
+ -511, 0x7fffffff};
+ int i, ret;
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ for (i = 0; i < ntests; ++i) {
+ tests[i].val = &values[i];
+ if (asprintf (&tests[i].name, "integer %d", values[i]) < 0)
+ errx(1, "malloc");
+ if (tests[i].name == NULL)
+ errx(1, "malloc");
+ }
+
+ ret = generic_test (tests, ntests, sizeof(int),
+ (generic_encode)der_put_integer,
+ (generic_length) der_length_integer,
+ (generic_decode)der_get_integer,
+ (generic_free)NULL,
+ cmp_integer,
+ NULL);
+
+ for (i = 0; i < ntests; ++i)
+ free (tests[i].name);
+ return ret;
+}
+
+static int
+test_one_int(int val)
+{
+ int ret, dval;
+ unsigned char *buf;
+ size_t len_len, len;
+
+ len = _heim_len_int(val);
+
+ buf = emalloc(len + 2);
+
+ buf[0] = '\xff';
+ buf[len + 1] = '\xff';
+ memset(buf + 1, 0, len);
+
+ ret = der_put_integer(buf + 1 + len - 1, len, &val, &len_len);
+ if (ret) {
+ printf("integer %d encode failed %d\n", val, ret);
+ return 1;
+ }
+ if (len != len_len) {
+ printf("integer %d encode fail with %d len %lu, result len %lu\n",
+ val, ret, (unsigned long)len, (unsigned long)len_len);
+ return 1;
+ }
+
+ ret = der_get_integer(buf + 1, len, &dval, &len_len);
+ if (ret) {
+ printf("integer %d decode failed %d\n", val, ret);
+ return 1;
+ }
+ if (len != len_len) {
+ printf("integer %d decoded diffrent len %lu != %lu",
+ val, (unsigned long)len, (unsigned long)len_len);
+ return 1;
+ }
+ if (val != dval) {
+ printf("decode decoded to diffrent value %d != %d",
+ val, dval);
+ return 1;
+ }
+
+ if (buf[0] != (unsigned char)'\xff') {
+ printf("precanary dead %d\n", val);
+ return 1;
+ }
+ if (buf[len + 1] != (unsigned char)'\xff') {
+ printf("postecanary dead %d\n", val);
+ return 1;
+ }
+ free(buf);
+ return 0;
+}
+
+static int
+test_integer_more (void)
+{
+ int64_t i, n1, n2, n3, n4, n5, n6;
+
+ n2 = 0;
+ for (i = 0; i < (sizeof(int) * 8); i++) {
+ n1 = 0x01 << i;
+ n2 = n2 | n1;
+ n3 = ~n1;
+ n4 = ~n2;
+ n5 = (-1) & ~(0x3f << i);
+ n6 = (-1) & ~(0x7f << i);
+
+ test_one_int(n1);
+ test_one_int(n2);
+ test_one_int(n3);
+ test_one_int(n4);
+ test_one_int(n5);
+ test_one_int(n6);
+ }
+ return 0;
+}
+
+static int
+cmp_unsigned (void *a, void *b)
+{
+ return *(unsigned int*)b - *(unsigned int*)a;
+}
+
+static int
+test_unsigned (void)
+{
+ struct test_case tests[] = {
+ {NULL, 1, "\x00", NULL },
+ {NULL, 1, "\x7f", NULL },
+ {NULL, 2, "\x00\x80", NULL },
+ {NULL, 2, "\x01\x00", NULL },
+ {NULL, 2, "\x02\x00", NULL },
+ {NULL, 3, "\x00\x80\x00", NULL },
+ {NULL, 5, "\x00\x80\x00\x00\x00", NULL },
+ {NULL, 4, "\x7f\xff\xff\xff", NULL }
+ };
+
+ unsigned int values[] = {0, 127, 128, 256, 512, 32768,
+ 0x80000000, 0x7fffffff};
+ int i, ret;
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ for (i = 0; i < ntests; ++i) {
+ tests[i].val = &values[i];
+ if (asprintf (&tests[i].name, "unsigned %u", values[i]) < 0)
+ errx(1, "malloc");
+ if (tests[i].name == NULL)
+ errx(1, "malloc");
+ }
+
+ ret = generic_test (tests, ntests, sizeof(int),
+ (generic_encode)der_put_unsigned,
+ (generic_length)der_length_unsigned,
+ (generic_decode)der_get_unsigned,
+ (generic_free)NULL,
+ cmp_unsigned,
+ NULL);
+ for (i = 0; i < ntests; ++i)
+ free (tests[i].name);
+ return ret;
+}
+
+static int
+cmp_octet_string (void *a, void *b)
+{
+ return der_heim_octet_string_cmp(a, b);
+}
+
+static int
+test_octet_string (void)
+{
+ heim_octet_string s1 = {8, "\x01\x23\x45\x67\x89\xab\xcd\xef"};
+
+ struct test_case tests[] = {
+ {NULL, 8, "\x01\x23\x45\x67\x89\xab\xcd\xef", NULL }
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+ int ret;
+
+ tests[0].val = &s1;
+ if (asprintf (&tests[0].name, "a octet string") < 0)
+ errx(1, "malloc");
+ if (tests[0].name == NULL)
+ errx(1, "malloc");
+
+ ret = generic_test (tests, ntests, sizeof(heim_octet_string),
+ (generic_encode)der_put_octet_string,
+ (generic_length)der_length_octet_string,
+ (generic_decode)der_get_octet_string,
+ (generic_free)der_free_octet_string,
+ cmp_octet_string,
+ NULL);
+ free(tests[0].name);
+ return ret;
+}
+
+static int
+cmp_bmp_string (void *a, void *b)
+{
+ heim_bmp_string *oa = (heim_bmp_string *)a;
+ heim_bmp_string *ob = (heim_bmp_string *)b;
+
+ return der_heim_bmp_string_cmp(oa, ob);
+}
+
+static uint16_t bmp_d1[] = { 32 };
+static uint16_t bmp_d2[] = { 32, 32 };
+
+static int
+test_bmp_string (void)
+{
+ heim_bmp_string s1 = { 1, bmp_d1 };
+ heim_bmp_string s2 = { 2, bmp_d2 };
+
+ struct test_case tests[] = {
+ {NULL, 2, "\x00\x20", NULL },
+ {NULL, 4, "\x00\x20\x00\x20", NULL }
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+ int ret;
+
+ tests[0].val = &s1;
+ if (asprintf (&tests[0].name, "a bmp string") < 0)
+ errx(1, "malloc");
+ if (tests[0].name == NULL)
+ errx(1, "malloc");
+ tests[1].val = &s2;
+ if (asprintf (&tests[1].name, "second bmp string") < 0)
+ errx(1, "malloc");
+ if (tests[1].name == NULL)
+ errx(1, "malloc");
+
+ ret = generic_test (tests, ntests, sizeof(heim_bmp_string),
+ (generic_encode)der_put_bmp_string,
+ (generic_length)der_length_bmp_string,
+ (generic_decode)der_get_bmp_string,
+ (generic_free)der_free_bmp_string,
+ cmp_bmp_string,
+ NULL);
+ free(tests[0].name);
+ free(tests[1].name);
+ return ret;
+}
+
+static int
+cmp_universal_string (void *a, void *b)
+{
+ heim_universal_string *oa = (heim_universal_string *)a;
+ heim_universal_string *ob = (heim_universal_string *)b;
+
+ return der_heim_universal_string_cmp(oa, ob);
+}
+
+static uint32_t universal_d1[] = { 32 };
+static uint32_t universal_d2[] = { 32, 32 };
+
+static int
+test_universal_string (void)
+{
+ heim_universal_string s1 = { 1, universal_d1 };
+ heim_universal_string s2 = { 2, universal_d2 };
+
+ struct test_case tests[] = {
+ {NULL, 4, "\x00\x00\x00\x20", NULL },
+ {NULL, 8, "\x00\x00\x00\x20\x00\x00\x00\x20", NULL }
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+ int ret;
+
+ tests[0].val = &s1;
+ if (asprintf (&tests[0].name, "a universal string") < 0)
+ errx(1, "malloc");
+ if (tests[0].name == NULL)
+ errx(1, "malloc");
+ tests[1].val = &s2;
+ if (asprintf (&tests[1].name, "second universal string") < 0)
+ errx(1, "malloc");
+ if (tests[1].name == NULL)
+ errx(1, "malloc");
+
+ ret = generic_test (tests, ntests, sizeof(heim_universal_string),
+ (generic_encode)der_put_universal_string,
+ (generic_length)der_length_universal_string,
+ (generic_decode)der_get_universal_string,
+ (generic_free)der_free_universal_string,
+ cmp_universal_string,
+ NULL);
+ free(tests[0].name);
+ free(tests[1].name);
+ return ret;
+}
+
+static int
+cmp_general_string (void *a, void *b)
+{
+ char **sa = (char **)a;
+ char **sb = (char **)b;
+
+ return strcmp (*sa, *sb);
+}
+
+static int
+test_general_string (void)
+{
+ char *s1 = "Test User 1";
+
+ struct test_case tests[] = {
+ {NULL, 11, "\x54\x65\x73\x74\x20\x55\x73\x65\x72\x20\x31", NULL }
+ };
+ int ret, ntests = sizeof(tests) / sizeof(*tests);
+
+ tests[0].val = &s1;
+ if (asprintf (&tests[0].name, "the string \"%s\"", s1) < 0)
+ errx(1, "malloc");
+ if (tests[0].name == NULL)
+ errx(1, "malloc");
+
+ ret = generic_test (tests, ntests, sizeof(unsigned char *),
+ (generic_encode)der_put_general_string,
+ (generic_length)der_length_general_string,
+ (generic_decode)der_get_general_string,
+ (generic_free)der_free_general_string,
+ cmp_general_string,
+ NULL);
+ free(tests[0].name);
+ return ret;
+}
+
+static int
+cmp_generalized_time (void *a, void *b)
+{
+ time_t *ta = (time_t *)a;
+ time_t *tb = (time_t *)b;
+
+ return (int)(*tb - *ta);
+}
+
+static int
+test_generalized_time (void)
+{
+ struct test_case tests[] = {
+ {NULL, 15, "19700101000000Z", NULL },
+ {NULL, 15, "19851106210627Z", NULL }
+ };
+ time_t values[] = {0, 500159187};
+ int i, ret;
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ for (i = 0; i < ntests; ++i) {
+ tests[i].val = &values[i];
+ if (asprintf (&tests[i].name, "time %d", (int)values[i]) < 0)
+ errx(1, "malloc");
+ if (tests[i].name == NULL)
+ errx(1, "malloc");
+ }
+
+ ret = generic_test (tests, ntests, sizeof(time_t),
+ (generic_encode)der_put_generalized_time,
+ (generic_length)der_length_generalized_time,
+ (generic_decode)der_get_generalized_time,
+ (generic_free)NULL,
+ cmp_generalized_time,
+ NULL);
+ for (i = 0; i < ntests; ++i)
+ free(tests[i].name);
+ return ret;
+}
+
+static int
+test_cmp_oid (void *a, void *b)
+{
+ return der_heim_oid_cmp((heim_oid *)a, (heim_oid *)b);
+}
+
+static unsigned oid_comp1[] = { 1, 1, 1 };
+static unsigned oid_comp2[] = { 1, 1 };
+static unsigned oid_comp3[] = { 6, 15, 1 };
+static unsigned oid_comp4[] = { 6, 15 };
+
+static int
+test_oid (void)
+{
+ struct test_case tests[] = {
+ {NULL, 2, "\x29\x01", NULL },
+ {NULL, 1, "\x29", NULL },
+ {NULL, 2, "\xff\x01", NULL },
+ {NULL, 1, "\xff", NULL }
+ };
+ heim_oid values[] = {
+ { 3, oid_comp1 },
+ { 2, oid_comp2 },
+ { 3, oid_comp3 },
+ { 2, oid_comp4 }
+ };
+ int i, ret;
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ for (i = 0; i < ntests; ++i) {
+ tests[i].val = &values[i];
+ if (asprintf (&tests[i].name, "oid %d", i) < 0)
+ errx(1, "malloc");
+ if (tests[i].name == NULL)
+ errx(1, "malloc");
+ }
+
+ ret = generic_test (tests, ntests, sizeof(heim_oid),
+ (generic_encode)der_put_oid,
+ (generic_length)der_length_oid,
+ (generic_decode)der_get_oid,
+ (generic_free)der_free_oid,
+ test_cmp_oid,
+ NULL);
+ for (i = 0; i < ntests; ++i)
+ free(tests[i].name);
+ return ret;
+}
+
+static int
+test_cmp_bit_string (void *a, void *b)
+{
+ return der_heim_bit_string_cmp((heim_bit_string *)a, (heim_bit_string *)b);
+}
+
+static int
+test_bit_string (void)
+{
+ struct test_case tests[] = {
+ {NULL, 1, "\x00", NULL }
+ };
+ heim_bit_string values[] = {
+ { 0, "" }
+ };
+ int i, ret;
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ for (i = 0; i < ntests; ++i) {
+ tests[i].val = &values[i];
+ if (asprintf (&tests[i].name, "bit_string %d", i) < 0)
+ errx(1, "malloc");
+ if (tests[i].name == NULL)
+ errx(1, "malloc");
+ }
+
+ ret = generic_test (tests, ntests, sizeof(heim_bit_string),
+ (generic_encode)der_put_bit_string,
+ (generic_length)der_length_bit_string,
+ (generic_decode)der_get_bit_string,
+ (generic_free)der_free_bit_string,
+ test_cmp_bit_string,
+ NULL);
+ for (i = 0; i < ntests; ++i)
+ free(tests[i].name);
+ return ret;
+}
+
+static int
+test_cmp_heim_integer (void *a, void *b)
+{
+ return der_heim_integer_cmp((heim_integer *)a, (heim_integer *)b);
+}
+
+static int
+test_heim_integer (void)
+{
+ struct test_case tests[] = {
+ {NULL, 1, "\xff", NULL },
+ {NULL, 2, "\xff\x01", NULL },
+ {NULL, 2, "\xfe\x01", NULL },
+ {NULL, 2, "\xef\x01", NULL },
+ {NULL, 3, "\xff\x00\xff", NULL },
+ {NULL, 3, "\xff\x01\x00", NULL },
+ {NULL, 1, "\x00", NULL },
+ {NULL, 1, "\x01", NULL },
+ {NULL, 2, "\x00\x80", NULL },
+ };
+
+ heim_integer values[] = {
+ { 1, "\x01", 1 },
+ { 1, "\xff", 1 },
+ { 2, "\x01\xff", 1 },
+ { 2, "\x10\xff", 1 },
+ { 2, "\xff\x01", 1 },
+ { 2, "\xff\x00", 1 },
+ { 0, "", 0 },
+ { 1, "\x01", 0 },
+ { 1, "\x80", 0 },
+ };
+ int i, ret;
+ int ntests = sizeof(tests) / sizeof(tests[0]);
+ size_t size;
+ heim_integer i2;
+
+ for (i = 0; i < ntests; ++i) {
+ tests[i].val = &values[i];
+ if (asprintf (&tests[i].name, "heim_integer %d", i) < 0)
+ errx(1, "malloc");
+ if (tests[i].name == NULL)
+ errx(1, "malloc");
+ }
+
+ ret = generic_test (tests, ntests, sizeof(heim_integer),
+ (generic_encode)der_put_heim_integer,
+ (generic_length)der_length_heim_integer,
+ (generic_decode)der_get_heim_integer,
+ (generic_free)der_free_heim_integer,
+ test_cmp_heim_integer,
+ NULL);
+ for (i = 0; i < ntests; ++i)
+ free (tests[i].name);
+ if (ret)
+ return ret;
+
+ /* test zero length integer (BER format) */
+ ret = der_get_heim_integer(NULL, 0, &i2, &size);
+ if (ret)
+ errx(1, "der_get_heim_integer");
+ if (i2.length != 0)
+ errx(1, "der_get_heim_integer wrong length");
+ der_free_heim_integer(&i2);
+
+ return 0;
+}
+
+static int
+test_cmp_boolean (void *a, void *b)
+{
+ return !!*(int *)a != !!*(int *)b;
+}
+
+static int
+test_boolean (void)
+{
+ struct test_case tests[] = {
+ {NULL, 1, "\xff", NULL },
+ {NULL, 1, "\x00", NULL }
+ };
+
+ int values[] = { 1, 0 };
+ int i, ret;
+ int ntests = sizeof(tests) / sizeof(tests[0]);
+ size_t size;
+ heim_integer i2;
+
+ for (i = 0; i < ntests; ++i) {
+ tests[i].val = &values[i];
+ if (asprintf (&tests[i].name, "heim_boolean %d", i) < 0)
+ errx(1, "malloc");
+ if (tests[i].name == NULL)
+ errx(1, "malloc");
+ }
+
+ ret = generic_test (tests, ntests, sizeof(int),
+ (generic_encode)der_put_boolean,
+ (generic_length)der_length_boolean,
+ (generic_decode)der_get_boolean,
+ (generic_free)NULL,
+ test_cmp_boolean,
+ NULL);
+ for (i = 0; i < ntests; ++i)
+ free (tests[i].name);
+ if (ret)
+ return ret;
+
+ /* test zero length integer (BER format) */
+ ret = der_get_heim_integer(NULL, 0, &i2, &size);
+ if (ret)
+ errx(1, "der_get_heim_integer");
+ if (i2.length != 0)
+ errx(1, "der_get_heim_integer wrong length");
+ der_free_heim_integer(&i2);
+
+ return 0;
+}
+
+static int
+check_fail_unsigned(void)
+{
+ struct test_case tests[] = {
+ {NULL, sizeof(unsigned) + 1,
+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01", "data overrun" }
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ return generic_decode_fail(tests, ntests, sizeof(unsigned),
+ (generic_decode)der_get_unsigned);
+}
+
+static int
+check_fail_integer(void)
+{
+ struct test_case tests[] = {
+ {NULL, sizeof(int) + 1,
+ "\x01\x01\x01\x01\x01\x01\x01\x01\x01", "data overrun" }
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ return generic_decode_fail(tests, ntests, sizeof(int),
+ (generic_decode)der_get_integer);
+}
+
+static int
+check_fail_length(void)
+{
+ struct test_case tests[] = {
+ {NULL, 0, "", "empty input data"},
+ {NULL, 1, "\x82", "internal length overrun" }
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ return generic_decode_fail(tests, ntests, sizeof(size_t),
+ (generic_decode)der_get_length);
+}
+
+static int
+check_fail_boolean(void)
+{
+ struct test_case tests[] = {
+ {NULL, 0, "", "empty input data"}
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ return generic_decode_fail(tests, ntests, sizeof(int),
+ (generic_decode)der_get_boolean);
+}
+
+static int
+check_fail_general_string(void)
+{
+ struct test_case tests[] = {
+ { NULL, 3, "A\x00i", "NUL char in string"}
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ return generic_decode_fail(tests, ntests, sizeof(heim_general_string),
+ (generic_decode)der_get_general_string);
+}
+
+static int
+check_fail_bmp_string(void)
+{
+ struct test_case tests[] = {
+ {NULL, 1, "\x00", "odd (1) length bmpstring"},
+ {NULL, 3, "\x00\x00\x00", "odd (3) length bmpstring"}
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ return generic_decode_fail(tests, ntests, sizeof(heim_bmp_string),
+ (generic_decode)der_get_bmp_string);
+}
+
+static int
+check_fail_universal_string(void)
+{
+ struct test_case tests[] = {
+ {NULL, 1, "\x00", "x & 3 == 1 universal string"},
+ {NULL, 2, "\x00\x00", "x & 3 == 2 universal string"},
+ {NULL, 3, "\x00\x00\x00", "x & 3 == 3 universal string"},
+ {NULL, 5, "\x00\x00\x00\x00\x00", "x & 3 == 1 universal string"},
+ {NULL, 6, "\x00\x00\x00\x00\x00\x00", "x & 3 == 2 universal string"},
+ {NULL, 7, "\x00\x00\x00\x00\x00\x00\x00", "x & 3 == 3 universal string"}
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ return generic_decode_fail(tests, ntests, sizeof(heim_universal_string),
+ (generic_decode)der_get_universal_string);
+}
+
+static int
+check_fail_heim_integer(void)
+{
+#if 0
+ struct test_case tests[] = {
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ return generic_decode_fail(tests, ntests, sizeof(heim_integer),
+ (generic_decode)der_get_heim_integer);
+#else
+ return 0;
+#endif
+}
+
+static int
+check_fail_generalized_time(void)
+{
+ struct test_case tests[] = {
+ {NULL, 1, "\x00", "no time"}
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ return generic_decode_fail(tests, ntests, sizeof(time_t),
+ (generic_decode)der_get_generalized_time);
+}
+
+static int
+check_fail_oid(void)
+{
+ struct test_case tests[] = {
+ {NULL, 0, "", "empty input data"},
+ {NULL, 2, "\x00\x80", "last byte continuation" },
+ {NULL, 11, "\x00\x81\x80\x80\x80\x80\x80\x80\x80\x80\x00",
+ "oid element overflow" }
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ return generic_decode_fail(tests, ntests, sizeof(heim_oid),
+ (generic_decode)der_get_oid);
+}
+
+static int
+check_fail_bitstring(void)
+{
+ struct test_case tests[] = {
+ {NULL, 0, "", "empty input data"},
+ {NULL, 1, "\x08", "larger then 8 bits trailer"},
+ {NULL, 1, "\x01", "to few bytes for bits"},
+ {NULL, -2, "\x00", "length overrun"},
+ {NULL, -1, "", "length to short"}
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ return generic_decode_fail(tests, ntests, sizeof(heim_bit_string),
+ (generic_decode)der_get_bit_string);
+}
+
+static int
+check_heim_integer_same(const char *p, const char *norm_p, heim_integer *i)
+{
+ heim_integer i2;
+ char *str;
+ int ret;
+
+ ret = der_print_hex_heim_integer(i, &str);
+ if (ret)
+ errx(1, "der_print_hex_heim_integer: %d", ret);
+
+ if (strcmp(str, norm_p) != 0)
+ errx(1, "der_print_hex_heim_integer: %s != %s", str, p);
+
+ ret = der_parse_hex_heim_integer(str, &i2);
+ if (ret)
+ errx(1, "der_parse_hex_heim_integer: %d", ret);
+
+ if (der_heim_integer_cmp(i, &i2) != 0)
+ errx(1, "der_heim_integer_cmp: p %s", p);
+
+ der_free_heim_integer(&i2);
+ free(str);
+
+ ret = der_parse_hex_heim_integer(p, &i2);
+ if (ret)
+ errx(1, "der_parse_hex_heim_integer: %d", ret);
+
+ if (der_heim_integer_cmp(i, &i2) != 0)
+ errx(1, "der_heim_integer_cmp: norm");
+
+ der_free_heim_integer(&i2);
+
+ return 0;
+}
+
+static int
+test_heim_int_format(void)
+{
+ heim_integer i = { 1, "\x10", 0 };
+ heim_integer i2 = { 1, "\x10", 1 };
+ heim_integer i3 = { 1, "\01", 0 };
+ char *p =
+ "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
+ "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
+ "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
+ "FFFFFFFF" "FFFFFFFF";
+ heim_integer bni = {
+ 128,
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC9\x0F\xDA\xA2"
+ "\x21\x68\xC2\x34\xC4\xC6\x62\x8B\x80\xDC\x1C\xD1"
+ "\x29\x02\x4E\x08\x8A\x67\xCC\x74\x02\x0B\xBE\xA6"
+ "\x3B\x13\x9B\x22\x51\x4A\x08\x79\x8E\x34\x04\xDD"
+ "\xEF\x95\x19\xB3\xCD\x3A\x43\x1B\x30\x2B\x0A\x6D"
+ "\xF2\x5F\x14\x37\x4F\xE1\x35\x6D\x6D\x51\xC2\x45"
+ "\xE4\x85\xB5\x76\x62\x5E\x7E\xC6\xF4\x4C\x42\xE9"
+ "\xA6\x37\xED\x6B\x0B\xFF\x5C\xB6\xF4\x06\xB7\xED"
+ "\xEE\x38\x6B\xFB\x5A\x89\x9F\xA5\xAE\x9F\x24\x11"
+ "\x7C\x4B\x1F\xE6\x49\x28\x66\x51\xEC\xE6\x53\x81"
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
+ 0
+ };
+ heim_integer f;
+ int ret = 0;
+
+ ret += check_heim_integer_same(p, p, &bni);
+ ret += check_heim_integer_same("10", "10", &i);
+ ret += check_heim_integer_same("00000010", "10", &i);
+ ret += check_heim_integer_same("-10", "-10", &i2);
+ ret += check_heim_integer_same("-00000010", "-10", &i2);
+ ret += check_heim_integer_same("01", "01", &i3);
+ ret += check_heim_integer_same("1", "01", &i3);
+
+ {
+ int r;
+ r = der_parse_hex_heim_integer("-", &f);
+ if (r == 0) {
+ der_free_heim_integer(&f);
+ ret++;
+ }
+ /* used to cause UMR */
+ r = der_parse_hex_heim_integer("00", &f);
+ if (r == 0)
+ der_free_heim_integer(&f);
+ else
+ ret++;
+ }
+
+ return ret;
+}
+
+static int
+test_heim_oid_format_same(const char *str, const heim_oid *oid)
+{
+ int ret;
+ char *p;
+ heim_oid o2;
+
+ ret = der_print_heim_oid(oid, ' ', &p);
+ if (ret) {
+ printf("fail to print oid: %s\n", str);
+ return 1;
+ }
+
+ if (strcmp(p, str) != 0) {
+ printf("oid %s != formated oid %s\n", str, p);
+ free(p);
+ return 1;
+ }
+
+ ret = der_parse_heim_oid(p, " ", &o2);
+ if (ret) {
+ printf("failed to parse %s\n", p);
+ free(p);
+ return 1;
+ }
+ free(p);
+ ret = der_heim_oid_cmp(&o2, oid);
+ der_free_oid(&o2);
+
+ if (ret != 0)
+ return 1;
+ return 0;
+}
+
+static unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 };
+
+static int
+test_heim_oid_format(void)
+{
+ heim_oid sha1 = { 6, sha1_oid_tree };
+ int ret = 0;
+
+ ret += test_heim_oid_format_same("1 3 14 3 2 26", &sha1);
+
+ return ret;
+}
+
+static int
+check_trailing_nul(void)
+{
+ int i, ret;
+ struct {
+ int fail;
+ const unsigned char *p;
+ size_t len;
+ const char *s;
+ size_t size;
+ } foo[] = {
+ { 1, (const unsigned char *)"foo\x00o", 5, NULL, 0 },
+ { 1, (const unsigned char *)"\x00o", 2, NULL, 0 },
+ { 0, (const unsigned char *)"\x00\x00\x00\x00\x00", 5, "", 5 },
+ { 0, (const unsigned char *)"\x00", 1, "", 1 },
+ { 0, (const unsigned char *)"", 0, "", 0 },
+ { 0, (const unsigned char *)"foo\x00\x00", 5, "foo", 5 },
+ { 0, (const unsigned char *)"foo\0", 4, "foo", 4 },
+ { 0, (const unsigned char *)"foo", 3, "foo", 3 }
+ };
+
+ for (i = 0; i < sizeof(foo)/sizeof(foo[0]); i++) {
+ char *s;
+ size_t size;
+ ret = der_get_general_string(foo[i].p, foo[i].len, &s, &size);
+ if (foo[i].fail) {
+ if (ret == 0)
+ errx(1, "check %d NULL didn't fail", i);
+ continue;
+ }
+ if (ret)
+ errx(1, "NULL check %d der_get_general_string failed", i);
+ if (foo[i].size != size)
+ errx(1, "NUL check i = %d size failed", i);
+ if (strcmp(foo[i].s, s) != 0)
+ errx(1, "NUL check i = %d content failed", i);
+ free(s);
+ }
+ return 0;
+}
+
+static int
+test_misc_cmp(void)
+{
+ int ret;
+
+ /* diffrent lengths are diffrent */
+ {
+ const heim_octet_string os1 = { 1, "a" } , os2 = { 0, NULL };
+ ret = der_heim_octet_string_cmp(&os1, &os2);
+ if (ret == 0)
+ return 1;
+ }
+ /* diffrent data are diffrent */
+ {
+ const heim_octet_string os1 = { 1, "a" } , os2 = { 1, "b" };
+ ret = der_heim_octet_string_cmp(&os1, &os2);
+ if (ret == 0)
+ return 1;
+ }
+ /* diffrent lengths are diffrent */
+ {
+ const heim_bit_string bs1 = { 8, "a" } , bs2 = { 7, "a" };
+ ret = der_heim_bit_string_cmp(&bs1, &bs2);
+ if (ret == 0)
+ return 1;
+ }
+ /* diffrent data are diffrent */
+ {
+ const heim_bit_string bs1 = { 7, "\x0f" } , bs2 = { 7, "\x02" };
+ ret = der_heim_bit_string_cmp(&bs1, &bs2);
+ if (ret == 0)
+ return 1;
+ }
+ /* diffrent lengths are diffrent */
+ {
+ uint16_t data = 1;
+ heim_bmp_string bs1 = { 1, NULL } , bs2 = { 0, NULL };
+ bs1.data = &data;
+ ret = der_heim_bmp_string_cmp(&bs1, &bs2);
+ if (ret == 0)
+ return 1;
+ }
+ /* diffrent lengths are diffrent */
+ {
+ uint32_t data;
+ heim_universal_string us1 = { 1, NULL } , us2 = { 0, NULL };
+ us1.data = &data;
+ ret = der_heim_universal_string_cmp(&us1, &us2);
+ if (ret == 0)
+ return 1;
+ }
+ /* same */
+ {
+ uint32_t data = (uint32_t)'a';
+ heim_universal_string us1 = { 1, NULL } , us2 = { 1, NULL };
+ us1.data = &data;
+ us2.data = &data;
+ ret = der_heim_universal_string_cmp(&us1, &us2);
+ if (ret != 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+corner_generalized_time(void)
+{
+ const char *str = "760520140000Z";
+ size_t size;
+ time_t t;
+ int ret;
+
+ ret = der_get_generalized_time((const unsigned char*)str, strlen(str),
+ &t, &size);
+ if (ret)
+ return 1;
+ return 0;
+}
+
+static int
+corner_tag(void)
+{
+ struct {
+ int ok;
+ const char *ptr;
+ size_t len;
+ } tests[] = {
+ { 1, "\x00", 1 },
+ { 0, "\xff", 1 },
+ { 0, "\xff\xff\xff\xff\xff\xff\xff\xff", 8 }
+ };
+ int i, ret;
+ Der_class cl;
+ Der_type ty;
+ unsigned int tag;
+ size_t size;
+
+ for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
+ ret = der_get_tag((const unsigned char*)tests[i].ptr,
+ tests[i].len, &cl, &ty, &tag, &size);
+ if (ret) {
+ if (tests[i].ok)
+ errx(1, "failed while shouldn't");
+ } else {
+ if (!tests[i].ok)
+ errx(1, "passed while shouldn't");
+ }
+ }
+ return 0;
+}
+
+struct randomcheck {
+ asn1_type_decode decoder;
+ asn1_type_release release;
+ size_t typesize;
+ size_t inputsize;
+} randomcheck[] = {
+#define el(name, type, maxlen) { \
+ (asn1_type_decode)der_get_##name, \
+ (asn1_type_release)der_free_##name, \
+ sizeof(type), \
+ maxlen \
+ }
+ el(integer, int, 6),
+ el(heim_integer, heim_integer, 12),
+ el(integer, int, 6),
+ el(unsigned, unsigned, 6),
+ el(general_string, heim_general_string, 12),
+ el(octet_string, heim_octet_string, 12),
+ { (asn1_type_decode)der_get_octet_string_ber,
+ (asn1_type_release)der_free_octet_string,
+ sizeof(heim_octet_string), 20 },
+ el(generalized_time, time_t, 20),
+ el(utctime, time_t, 20),
+ el(bit_string, heim_bit_string, 10),
+ el(oid, heim_oid, 10),
+ { NULL, NULL, 0, 0 }
+#undef el
+};
+
+static void
+asn1rand(uint8_t *randbytes, size_t len)
+{
+ while (len) {
+ *randbytes++ = rk_random();
+ len--;
+ }
+}
+
+static int
+check_random(void)
+{
+ struct randomcheck *r = randomcheck;
+ uint8_t *input;
+ void *type;
+ size_t size, insize;
+ int ret;
+
+ while (r->decoder) {
+ type = emalloc(r->typesize);
+ memset(type, 0, r->typesize);
+
+ input = emalloc(r->inputsize);
+
+ /* try all zero first */
+ memset(input, 0, r->inputsize);
+
+ ret = r->decoder(input, r->inputsize, type, &size);
+ if (!ret)
+ r->release(type);
+
+ /* try all one first */
+ memset(input, 0xff, r->inputsize);
+ ret = r->decoder(input, r->inputsize, type, &size);
+ if (!ret)
+ r->release(type);
+
+ /* try 0x41 too */
+ memset(input, 0x41, r->inputsize);
+ ret = r->decoder(input, r->inputsize, type, &size);
+ if (!ret)
+ r->release(type);
+
+ /* random */
+ asn1rand(input, r->inputsize);
+ ret = r->decoder(input, r->inputsize, type, &size);
+ if (!ret)
+ r->release(type);
+
+ /* let make buffer smaller */
+ insize = r->inputsize;
+ do {
+ insize--;
+ asn1rand(input, insize);
+
+ ret = r->decoder(input, insize, type, &size);
+ if (!ret)
+ r->release(type);
+ } while(insize > 0);
+
+ free(type);
+
+ r++;
+ }
+ return 0;
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ int ret = 0;
+
+ ret += test_integer ();
+ ret += test_integer_more();
+ ret += test_unsigned ();
+ ret += test_octet_string ();
+ ret += test_bmp_string ();
+ ret += test_universal_string ();
+ ret += test_general_string ();
+ ret += test_generalized_time ();
+ ret += test_oid ();
+ ret += test_bit_string();
+ ret += test_heim_integer();
+ ret += test_boolean();
+
+ ret += check_fail_unsigned();
+ ret += check_fail_integer();
+ ret += check_fail_length();
+ ret += check_fail_boolean();
+ ret += check_fail_general_string();
+ ret += check_fail_bmp_string();
+ ret += check_fail_universal_string();
+ ret += check_fail_heim_integer();
+ ret += check_fail_generalized_time();
+ ret += check_fail_oid();
+ ret += check_fail_bitstring();
+ ret += test_heim_int_format();
+ ret += test_heim_oid_format();
+ ret += check_trailing_nul();
+ ret += test_misc_cmp();
+ ret += corner_generalized_time();
+ ret += corner_tag();
+ ret += check_random();
+
+ return ret;
+}
diff --git a/third_party/heimdal/lib/asn1/check-gen.c b/third_party/heimdal/lib/asn1/check-gen.c
new file mode 100644
index 0000000..4941c74
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/check-gen.c
@@ -0,0 +1,2758 @@
+/*
+ * Copyright (c) 1999 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <roken.h>
+
+#include <asn1-common.h>
+#include <asn1_err.h>
+#include <der.h>
+#include <krb5_asn1.h>
+#include <heim_asn1.h>
+#include <rfc2459_asn1.h>
+#include <x690sample_asn1.h>
+#include <test_asn1.h>
+#include <cms_asn1.h>
+
+#include "check-common.h"
+
+static int my_copy_vers_called;
+static int my_free_vers_called;
+
+#include <limits.h>
+#if UINT_MAX == 0xffffffff
+// 32 bit
+#define DISABLE_TEST_64
+#endif
+
+int
+my_copy_vers(const my_vers *from, my_vers *to)
+{
+ my_copy_vers_called++;
+ *to = *from;
+ return 0;
+}
+
+void
+my_free_vers(my_vers *v)
+{
+ my_free_vers_called++;
+ v->v = -1;
+}
+
+static char *lha_principal[] = { "lha" };
+static char *lharoot_princ[] = { "lha", "root" };
+static char *datan_princ[] = { "host", "nutcracker.e.kth.se" };
+static char *nada_tgt_principal[] = { "krbtgt", "NADA.KTH.SE" };
+
+static int
+cmp_principal (void *a, void *b)
+{
+ Principal *pa = a;
+ Principal *pb = b;
+ int i;
+
+ COMPARE_STRING(pa,pb,realm);
+ COMPARE_INTEGER(pa,pb,name.name_type);
+ COMPARE_INTEGER(pa,pb,name.name_string.len);
+
+ for (i = 0; i < pa->name.name_string.len; i++)
+ COMPARE_STRING(pa,pb,name.name_string.val[i]);
+
+ return 0;
+}
+
+static int
+test_principal (void)
+{
+
+ struct test_case tests[] = {
+ { NULL, 29,
+ "\x30\x1b\xa0\x10\x30\x0e\xa0\x03\x02\x01\x01\xa1\x07\x30\x05\x1b"
+ "\x03\x6c\x68\x61\xa1\x07\x1b\x05\x53\x55\x2e\x53\x45",
+ NULL
+ },
+ { NULL, 35,
+ "\x30\x21\xa0\x16\x30\x14\xa0\x03\x02\x01\x01\xa1\x0d\x30\x0b\x1b"
+ "\x03\x6c\x68\x61\x1b\x04\x72\x6f\x6f\x74\xa1\x07\x1b\x05\x53\x55"
+ "\x2e\x53\x45",
+ NULL
+ },
+ { NULL, 54,
+ "\x30\x34\xa0\x26\x30\x24\xa0\x03\x02\x01\x03\xa1\x1d\x30\x1b\x1b"
+ "\x04\x68\x6f\x73\x74\x1b\x13\x6e\x75\x74\x63\x72\x61\x63\x6b\x65"
+ "\x72\x2e\x65\x2e\x6b\x74\x68\x2e\x73\x65\xa1\x0a\x1b\x08\x45\x2e"
+ "\x4b\x54\x48\x2e\x53\x45",
+ NULL
+ }
+ };
+
+
+ Principal values[] = {
+ { { KRB5_NT_PRINCIPAL, { 1, lha_principal } }, "SU.SE", NULL },
+ { { KRB5_NT_PRINCIPAL, { 2, lharoot_princ } }, "SU.SE", NULL },
+ { { KRB5_NT_SRV_HST, { 2, datan_princ } }, "E.KTH.SE", NULL }
+ };
+ int i, ret;
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ for (i = 0; i < ntests; ++i) {
+ tests[i].val = &values[i];
+ if (asprintf (&tests[i].name, "Principal %d", i) < 0)
+ errx(1, "malloc");
+ if (tests[i].name == NULL)
+ errx(1, "malloc");
+ }
+
+ ret = generic_test (tests, ntests, sizeof(Principal),
+ (generic_encode)encode_Principal,
+ (generic_length)length_Principal,
+ (generic_decode)decode_Principal,
+ (generic_free)free_Principal,
+ cmp_principal,
+ NULL);
+ for (i = 0; i < ntests; ++i)
+ free (tests[i].name);
+
+ return ret;
+}
+
+static int
+cmp_authenticator (void *a, void *b)
+{
+ Authenticator *aa = a;
+ Authenticator *ab = b;
+ int i;
+
+ COMPARE_INTEGER(aa,ab,authenticator_vno);
+ COMPARE_STRING(aa,ab,crealm);
+
+ COMPARE_INTEGER(aa,ab,cname.name_type);
+ COMPARE_INTEGER(aa,ab,cname.name_string.len);
+
+ for (i = 0; i < aa->cname.name_string.len; i++)
+ COMPARE_STRING(aa,ab,cname.name_string.val[i]);
+
+ return 0;
+}
+
+static int
+test_authenticator (void)
+{
+ struct test_case tests[] = {
+ { NULL, 63,
+ "\x62\x3d\x30\x3b\xa0\x03\x02\x01\x05\xa1\x0a\x1b\x08"
+ "\x45\x2e\x4b\x54\x48\x2e\x53\x45\xa2\x10\x30\x0e\xa0"
+ "\x03\x02\x01\x01\xa1\x07\x30\x05\x1b\x03\x6c\x68\x61"
+ "\xa4\x03\x02\x01\x0a\xa5\x11\x18\x0f\x31\x39\x37\x30"
+ "\x30\x31\x30\x31\x30\x30\x30\x31\x33\x39\x5a",
+ NULL
+ },
+ { NULL, 67,
+ "\x62\x41\x30\x3f\xa0\x03\x02\x01\x05\xa1\x07\x1b\x05"
+ "\x53\x55\x2e\x53\x45\xa2\x16\x30\x14\xa0\x03\x02\x01"
+ "\x01\xa1\x0d\x30\x0b\x1b\x03\x6c\x68\x61\x1b\x04\x72"
+ "\x6f\x6f\x74\xa4\x04\x02\x02\x01\x24\xa5\x11\x18\x0f"
+ "\x31\x39\x37\x30\x30\x31\x30\x31\x30\x30\x31\x36\x33"
+ "\x39\x5a",
+ NULL
+ }
+ };
+
+ Authenticator values[] = {
+ { 5, "E.KTH.SE", { KRB5_NT_PRINCIPAL, { 1, lha_principal } },
+ NULL, 10, 99, NULL, NULL, NULL },
+ { 5, "SU.SE", { KRB5_NT_PRINCIPAL, { 2, lharoot_princ } },
+ NULL, 292, 999, NULL, NULL, NULL }
+ };
+ int i, ret;
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ for (i = 0; i < ntests; ++i) {
+ tests[i].val = &values[i];
+ if (asprintf (&tests[i].name, "Authenticator %d", i) < 0)
+ errx(1, "malloc");
+ if (tests[i].name == NULL)
+ errx(1, "malloc");
+ }
+
+ ret = generic_test (tests, ntests, sizeof(Authenticator),
+ (generic_encode)encode_Authenticator,
+ (generic_length)length_Authenticator,
+ (generic_decode)decode_Authenticator,
+ (generic_free)free_Authenticator,
+ cmp_authenticator,
+ (generic_copy)copy_Authenticator);
+ for (i = 0; i < ntests; ++i)
+ free(tests[i].name);
+
+ return ret;
+}
+
+static int
+cmp_KRB_ERROR (void *a, void *b)
+{
+ KRB_ERROR *aa = a;
+ KRB_ERROR *ab = b;
+ int i;
+
+ COMPARE_INTEGER(aa,ab,pvno);
+ COMPARE_INTEGER(aa,ab,msg_type);
+
+ IF_OPT_COMPARE(aa,ab,ctime) {
+ COMPARE_INTEGER(aa,ab,ctime);
+ }
+ IF_OPT_COMPARE(aa,ab,cusec) {
+ COMPARE_INTEGER(aa,ab,cusec);
+ }
+ COMPARE_INTEGER(aa,ab,stime);
+ COMPARE_INTEGER(aa,ab,susec);
+ COMPARE_INTEGER(aa,ab,error_code);
+
+ IF_OPT_COMPARE(aa,ab,crealm) {
+ COMPARE_OPT_STRING(aa,ab,crealm);
+ }
+#if 0
+ IF_OPT_COMPARE(aa,ab,cname) {
+ COMPARE_OPT_STRING(aa,ab,cname);
+ }
+#endif
+ COMPARE_STRING(aa,ab,realm);
+
+ COMPARE_INTEGER(aa,ab,sname.name_string.len);
+ for (i = 0; i < aa->sname.name_string.len; i++)
+ COMPARE_STRING(aa,ab,sname.name_string.val[i]);
+
+ IF_OPT_COMPARE(aa,ab,e_text) {
+ COMPARE_OPT_STRING(aa,ab,e_text);
+ }
+ IF_OPT_COMPARE(aa,ab,e_data) {
+ /* COMPARE_OPT_OCTET_STRING(aa,ab,e_data); */
+ }
+
+ return 0;
+}
+
+static int
+test_krb_error (void)
+{
+ struct test_case tests[] = {
+ { NULL, 127,
+ "\x7e\x7d\x30\x7b\xa0\x03\x02\x01\x05\xa1\x03\x02\x01\x1e\xa4\x11"
+ "\x18\x0f\x32\x30\x30\x33\x31\x31\x32\x34\x30\x30\x31\x31\x31\x39"
+ "\x5a\xa5\x05\x02\x03\x04\xed\xa5\xa6\x03\x02\x01\x1f\xa7\x0d\x1b"
+ "\x0b\x4e\x41\x44\x41\x2e\x4b\x54\x48\x2e\x53\x45\xa8\x10\x30\x0e"
+ "\xa0\x03\x02\x01\x01\xa1\x07\x30\x05\x1b\x03\x6c\x68\x61\xa9\x0d"
+ "\x1b\x0b\x4e\x41\x44\x41\x2e\x4b\x54\x48\x2e\x53\x45\xaa\x20\x30"
+ "\x1e\xa0\x03\x02\x01\x01\xa1\x17\x30\x15\x1b\x06\x6b\x72\x62\x74"
+ "\x67\x74\x1b\x0b\x4e\x41\x44\x41\x2e\x4b\x54\x48\x2e\x53\x45",
+ "KRB-ERROR Test 1"
+ }
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+ KRB_ERROR e1;
+ PrincipalName lhaprincipalname = { 1, { 1, lha_principal } };
+ PrincipalName tgtprincipalname = { 1, { 2, nada_tgt_principal } };
+ char *realm = "NADA.KTH.SE";
+
+ e1.pvno = 5;
+ e1.msg_type = 30;
+ e1.ctime = NULL;
+ e1.cusec = NULL;
+ e1.stime = 1069632679;
+ e1.susec = 322981;
+ e1.error_code = 31;
+ e1.crealm = &realm;
+ e1.cname = &lhaprincipalname;
+ e1.realm = "NADA.KTH.SE";
+ e1.sname = tgtprincipalname;
+ e1.e_text = NULL;
+ e1.e_data = NULL;
+
+ tests[0].val = &e1;
+
+ return generic_test (tests, ntests, sizeof(KRB_ERROR),
+ (generic_encode)encode_KRB_ERROR,
+ (generic_length)length_KRB_ERROR,
+ (generic_decode)decode_KRB_ERROR,
+ (generic_free)free_KRB_ERROR,
+ cmp_KRB_ERROR,
+ (generic_copy)copy_KRB_ERROR);
+}
+
+static int
+cmp_Name (void *a, void *b)
+{
+ Name *aa = a;
+ Name *ab = b;
+
+ COMPARE_INTEGER(aa,ab,element);
+
+ return 0;
+}
+
+static int
+test_Name (void)
+{
+ struct test_case tests[] = {
+ { NULL, 35,
+ "\x30\x21\x31\x1f\x30\x0b\x06\x03\x55\x04\x03\x13\x04\x4c\x6f\x76"
+ "\x65\x30\x10\x06\x03\x55\x04\x07\x13\x09\x53\x54\x4f\x43\x4b\x48"
+ "\x4f\x4c\x4d",
+ "Name CN=Love+L=STOCKHOLM"
+ },
+ { NULL, 35,
+ "\x30\x21\x31\x1f\x30\x0b\x06\x03\x55\x04\x03\x13\x04\x4c\x6f\x76"
+ "\x65\x30\x10\x06\x03\x55\x04\x07\x13\x09\x53\x54\x4f\x43\x4b\x48"
+ "\x4f\x4c\x4d",
+ "Name L=STOCKHOLM+CN=Love"
+ }
+ };
+
+ int ntests = sizeof(tests) / sizeof(*tests);
+ Name n1, n2;
+ RelativeDistinguishedName rdn1[1];
+ RelativeDistinguishedName rdn2[1];
+ AttributeTypeAndValue atv1[2];
+ AttributeTypeAndValue atv2[2];
+ unsigned cmp_CN[] = { 2, 5, 4, 3 };
+ unsigned cmp_L[] = { 2, 5, 4, 7 };
+
+ /* n1 */
+ n1.element = choice_Name_rdnSequence;
+ n1.u.rdnSequence.val = rdn1;
+ n1.u.rdnSequence.len = sizeof(rdn1)/sizeof(rdn1[0]);
+ rdn1[0].val = atv1;
+ rdn1[0].len = sizeof(atv1)/sizeof(atv1[0]);
+
+ atv1[0].type.length = sizeof(cmp_CN)/sizeof(cmp_CN[0]);
+ atv1[0].type.components = cmp_CN;
+ atv1[0].value.element = choice_DirectoryString_printableString;
+ atv1[0].value.u.printableString.data = "Love";
+ atv1[0].value.u.printableString.length = 4;
+
+ atv1[1].type.length = sizeof(cmp_L)/sizeof(cmp_L[0]);
+ atv1[1].type.components = cmp_L;
+ atv1[1].value.element = choice_DirectoryString_printableString;
+ atv1[1].value.u.printableString.data = "STOCKHOLM";
+ atv1[1].value.u.printableString.length = 9;
+
+ /* n2 */
+ n2.element = choice_Name_rdnSequence;
+ n2.u.rdnSequence.val = rdn2;
+ n2.u.rdnSequence.len = sizeof(rdn2)/sizeof(rdn2[0]);
+ rdn2[0].val = atv2;
+ rdn2[0].len = sizeof(atv2)/sizeof(atv2[0]);
+
+ atv2[0].type.length = sizeof(cmp_L)/sizeof(cmp_L[0]);
+ atv2[0].type.components = cmp_L;
+ atv2[0].value.element = choice_DirectoryString_printableString;
+ atv2[0].value.u.printableString.data = "STOCKHOLM";
+ atv2[0].value.u.printableString.length = 9;
+
+ atv2[1].type.length = sizeof(cmp_CN)/sizeof(cmp_CN[0]);
+ atv2[1].type.components = cmp_CN;
+ atv2[1].value.element = choice_DirectoryString_printableString;
+ atv2[1].value.u.printableString.data = "Love";
+ atv2[1].value.u.printableString.length = 4;
+
+ /* */
+ tests[0].val = &n1;
+ tests[1].val = &n2;
+
+ return generic_test (tests, ntests, sizeof(Name),
+ (generic_encode)encode_Name,
+ (generic_length)length_Name,
+ (generic_decode)decode_Name,
+ (generic_free)free_Name,
+ cmp_Name,
+ (generic_copy)copy_Name);
+}
+
+static int
+cmp_KeyUsage (void *a, void *b)
+{
+ KeyUsage *aa = a;
+ KeyUsage *ab = b;
+
+ return KeyUsage2int(*aa) != KeyUsage2int(*ab);
+}
+
+static int
+test_bit_string (void)
+{
+ struct test_case tests[] = {
+ { NULL, 4,
+ "\x03\x02\x07\x80",
+ "bitstring 1"
+ },
+ { NULL, 4,
+ "\x03\x02\x05\xa0",
+ "bitstring 2"
+ },
+ { NULL, 5,
+ "\x03\x03\x07\x00\x80",
+ "bitstring 3"
+ },
+ { NULL, 3,
+ "\x03\x01\x00",
+ "bitstring 4"
+ }
+ };
+
+ int ntests = sizeof(tests) / sizeof(*tests);
+ KeyUsage ku1, ku2, ku3, ku4;
+
+ memset(&ku1, 0, sizeof(ku1));
+ ku1.digitalSignature = 1;
+ tests[0].val = &ku1;
+
+ memset(&ku2, 0, sizeof(ku2));
+ ku2.digitalSignature = 1;
+ ku2.keyEncipherment = 1;
+ tests[1].val = &ku2;
+
+ memset(&ku3, 0, sizeof(ku3));
+ ku3.decipherOnly = 1;
+ tests[2].val = &ku3;
+
+ memset(&ku4, 0, sizeof(ku4));
+ tests[3].val = &ku4;
+
+
+ return generic_test (tests, ntests, sizeof(KeyUsage),
+ (generic_encode)encode_KeyUsage,
+ (generic_length)length_KeyUsage,
+ (generic_decode)decode_KeyUsage,
+ (generic_free)free_KeyUsage,
+ cmp_KeyUsage,
+ (generic_copy)copy_KeyUsage);
+}
+
+static int
+cmp_TicketFlags (void *a, void *b)
+{
+ TicketFlags *aa = a;
+ TicketFlags *ab = b;
+
+ return TicketFlags2int(*aa) != TicketFlags2int(*ab);
+}
+
+static int
+test_bit_string_rfc1510 (void)
+{
+ struct test_case tests[] = {
+ { NULL, 7,
+ "\x03\x05\x00\x80\x00\x00\x00",
+ "TF bitstring 1"
+ },
+ { NULL, 7,
+ "\x03\x05\x00\x40\x20\x00\x00",
+ "TF bitstring 2"
+ },
+ { NULL, 7,
+ "\x03\x05\x00\x00\x20\x00\x00",
+ "TF bitstring 3"
+ },
+ { NULL, 7,
+ "\x03\x05\x00\x00\x00\x00\x00",
+ "TF bitstring 4"
+ }
+ };
+
+ int ntests = sizeof(tests) / sizeof(*tests);
+ TicketFlags tf1, tf2, tf3, tf4;
+
+ memset(&tf1, 0, sizeof(tf1));
+ tf1.reserved = 1;
+ tests[0].val = &tf1;
+
+ memset(&tf2, 0, sizeof(tf2));
+ tf2.forwardable = 1;
+ tf2.pre_authent = 1;
+ tests[1].val = &tf2;
+
+ memset(&tf3, 0, sizeof(tf3));
+ tf3.pre_authent = 1;
+ tests[2].val = &tf3;
+
+ memset(&tf4, 0, sizeof(tf4));
+ tests[3].val = &tf4;
+
+
+ return generic_test (tests, ntests, sizeof(TicketFlags),
+ (generic_encode)encode_TicketFlags,
+ (generic_length)length_TicketFlags,
+ (generic_decode)decode_TicketFlags,
+ (generic_free)free_TicketFlags,
+ cmp_TicketFlags,
+ (generic_copy)copy_TicketFlags);
+}
+
+static int
+cmp_KerberosTime (void *a, void *b)
+{
+ KerberosTime *aa = a;
+ KerberosTime *ab = b;
+
+ return *aa != *ab;
+}
+
+static int
+test_time (void)
+{
+ struct test_case tests[] = {
+ { NULL, 17,
+ "\x18\x0f\x31\x39\x37\x30\x30\x31\x30\x31\x30\x31\x31\x38\x33\x31"
+ "\x5a",
+ "time 1" },
+ { NULL, 17,
+ "\x18\x0f\x32\x30\x30\x39\x30\x35\x32\x34\x30\x32\x30\x32\x34\x30"
+ "\x5a",
+ "time 2" }
+ };
+
+ int ntests = sizeof(tests) / sizeof(*tests);
+ KerberosTime times[] = {
+ 4711,
+ 1243130560
+ };
+
+ tests[0].val = &times[0];
+ tests[1].val = &times[1];
+
+ return generic_test (tests, ntests, sizeof(KerberosTime),
+ (generic_encode)encode_KerberosTime,
+ (generic_length)length_KerberosTime,
+ (generic_decode)decode_KerberosTime,
+ (generic_free)free_KerberosTime,
+ cmp_KerberosTime,
+ (generic_copy)copy_KerberosTime);
+}
+
+struct {
+ const char *cert;
+ size_t len;
+} certs[] = {
+ {
+ "\x30\x82\x02\x6c\x30\x82\x01\xd5\xa0\x03\x02\x01\x02\x02\x09\x00"
+ "\x99\x32\xde\x61\x0e\x40\x19\x8a\x30\x0d\x06\x09\x2a\x86\x48\x86"
+ "\xf7\x0d\x01\x01\x05\x05\x00\x30\x2a\x31\x1b\x30\x19\x06\x03\x55"
+ "\x04\x03\x0c\x12\x68\x78\x35\x30\x39\x20\x54\x65\x73\x74\x20\x52"
+ "\x6f\x6f\x74\x20\x43\x41\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13"
+ "\x02\x53\x45\x30\x1e\x17\x0d\x30\x39\x30\x34\x32\x36\x32\x30\x32"
+ "\x39\x34\x30\x5a\x17\x0d\x31\x39\x30\x34\x32\x34\x32\x30\x32\x39"
+ "\x34\x30\x5a\x30\x2a\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x0c\x12"
+ "\x68\x78\x35\x30\x39\x20\x54\x65\x73\x74\x20\x52\x6f\x6f\x74\x20"
+ "\x43\x41\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x30"
+ "\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05"
+ "\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xb9\xd3\x1b\x67"
+ "\x1c\xf7\x5e\x26\x81\x3b\x82\xff\x03\xa4\x43\xb5\xb2\x63\x0b\x89"
+ "\x58\x43\xfe\x3d\xe0\x38\x7d\x93\x74\xbb\xad\x21\xa4\x29\xd9\x34"
+ "\x79\xf3\x1c\x8c\x5a\xd6\xb0\xd7\x19\xea\xcc\xaf\xe0\xa8\x40\x02"
+ "\x1d\x91\xf1\xac\x36\xb0\xfb\x08\xbd\xcc\x9a\xe1\xb7\x6e\xee\x0a"
+ "\x69\xbf\x6d\x2b\xee\x20\x82\x61\x06\xf2\x18\xcc\x89\x11\x64\x7e"
+ "\xb2\xff\x47\xd1\x3b\x52\x73\xeb\x5a\xc0\x03\xa6\x4b\xc7\x40\x7e"
+ "\xbc\xe1\x0e\x65\x44\x3f\x40\x8b\x02\x82\x54\x04\xd9\xcc\x2c\x67"
+ "\x01\xb6\x16\x82\xd8\x33\x53\x17\xd7\xde\x8d\x5d\x02\x03\x01\x00"
+ "\x01\xa3\x81\x99\x30\x81\x96\x30\x1d\x06\x03\x55\x1d\x0e\x04\x16"
+ "\x04\x14\x6e\x48\x13\xdc\xbf\x8b\x95\x4c\x13\xf3\x1f\x97\x30\xdd"
+ "\x27\x96\x59\x9b\x0e\x68\x30\x5a\x06\x03\x55\x1d\x23\x04\x53\x30"
+ "\x51\x80\x14\x6e\x48\x13\xdc\xbf\x8b\x95\x4c\x13\xf3\x1f\x97\x30"
+ "\xdd\x27\x96\x59\x9b\x0e\x68\xa1\x2e\xa4\x2c\x30\x2a\x31\x1b\x30"
+ "\x19\x06\x03\x55\x04\x03\x0c\x12\x68\x78\x35\x30\x39\x20\x54\x65"
+ "\x73\x74\x20\x52\x6f\x6f\x74\x20\x43\x41\x31\x0b\x30\x09\x06\x03"
+ "\x55\x04\x06\x13\x02\x53\x45\x82\x09\x00\x99\x32\xde\x61\x0e\x40"
+ "\x19\x8a\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff"
+ "\x30\x0b\x06\x03\x55\x1d\x0f\x04\x04\x03\x02\x01\xe6\x30\x0d\x06"
+ "\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x81\x81\x00"
+ "\x52\x9b\xe4\x0e\xee\xc2\x5d\xb7\xf1\xba\x47\xe3\xfe\xaf\x3d\x51"
+ "\x10\xfd\xe8\x0d\x14\x58\x05\x36\xa7\xeb\xd8\x05\xe5\x27\x6f\x51"
+ "\xb8\xec\x90\xd9\x03\xe1\xbc\x9c\x93\x38\x21\x5c\xaf\x4e\x6c\x7b"
+ "\x6c\x65\xa9\x92\xcd\x94\xef\xa8\xae\x90\x12\x14\x78\x2d\xa3\x15"
+ "\xaa\x42\xf1\xd9\x44\x64\x2c\x3c\xc0\xbd\x3a\x48\xd8\x80\x45\x8b"
+ "\xd1\x79\x82\xe0\x0f\xdf\x08\x3c\x60\x21\x6f\x31\x47\x98\xae\x2f"
+ "\xcb\xb1\xa1\xb9\xc1\xa3\x71\x5e\x4a\xc2\x67\xdf\x66\x0a\x51\xb5"
+ "\xad\x60\x05\xdb\x02\xd4\x1a\xd2\xb9\x4e\x01\x08\x2b\xc3\x57\xaf",
+ 624 },
+ {
+ "\x30\x82\x02\x54\x30\x82\x01\xbd\xa0\x03\x02\x01\x02\x02\x01\x08"
+ "\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30"
+ "\x2a\x31\x1b\x30\x19\x06\x03\x55\x04\x03\x0c\x12\x68\x78\x35\x30"
+ "\x39\x20\x54\x65\x73\x74\x20\x52\x6f\x6f\x74\x20\x43\x41\x31\x0b"
+ "\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x30\x1e\x17\x0d\x30"
+ "\x39\x30\x34\x32\x36\x32\x30\x32\x39\x34\x30\x5a\x17\x0d\x31\x39"
+ "\x30\x34\x32\x34\x32\x30\x32\x39\x34\x30\x5a\x30\x1b\x31\x0b\x30"
+ "\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x0c\x30\x0a\x06\x03"
+ "\x55\x04\x03\x0c\x03\x6b\x64\x63\x30\x81\x9f\x30\x0d\x06\x09\x2a"
+ "\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81"
+ "\x89\x02\x81\x81\x00\xd2\x41\x7a\xf8\x4b\x55\xb2\xaf\x11\xf9\x43"
+ "\x9b\x43\x81\x09\x3b\x9a\x94\xcf\x00\xf4\x85\x75\x92\xd7\x2a\xa5"
+ "\x11\xf1\xa8\x50\x6e\xc6\x84\x74\x24\x17\xda\x84\xc8\x03\x37\xb2"
+ "\x20\xf3\xba\xb5\x59\x36\x21\x4d\xab\x70\xe2\xc3\x09\x93\x68\x14"
+ "\x12\x79\xc5\xbb\x9e\x1b\x4a\xf0\xc6\x24\x59\x25\xc3\x1c\xa8\x70"
+ "\x66\x5b\x3e\x41\x8e\xe3\x25\x71\x9a\x94\xa0\x5b\x46\x91\x6f\xdd"
+ "\x58\x14\xec\x89\xe5\x8c\x96\xc5\x38\x60\xe4\xab\xf2\x75\xee\x6e"
+ "\x62\xfc\xe1\xbd\x03\x47\xff\xc4\xbe\x0f\xca\x70\x73\xe3\x74\x58"
+ "\x3a\x2f\x04\x2d\x39\x02\x03\x01\x00\x01\xa3\x81\x98\x30\x81\x95"
+ "\x30\x09\x06\x03\x55\x1d\x13\x04\x02\x30\x00\x30\x0b\x06\x03\x55"
+ "\x1d\x0f\x04\x04\x03\x02\x05\xe0\x30\x12\x06\x03\x55\x1d\x25\x04"
+ "\x0b\x30\x09\x06\x07\x2b\x06\x01\x05\x02\x03\x05\x30\x1d\x06\x03"
+ "\x55\x1d\x0e\x04\x16\x04\x14\x3a\xd3\x73\xff\xab\xdb\x7d\x8d\xc6"
+ "\x3a\xa2\x26\x3e\xae\x78\x95\x80\xc9\xe6\x31\x30\x48\x06\x03\x55"
+ "\x1d\x11\x04\x41\x30\x3f\xa0\x3d\x06\x06\x2b\x06\x01\x05\x02\x02"
+ "\xa0\x33\x30\x31\xa0\x0d\x1b\x0b\x54\x45\x53\x54\x2e\x48\x35\x4c"
+ "\x2e\x53\x45\xa1\x20\x30\x1e\xa0\x03\x02\x01\x01\xa1\x17\x30\x15"
+ "\x1b\x06\x6b\x72\x62\x74\x67\x74\x1b\x0b\x54\x45\x53\x54\x2e\x48"
+ "\x35\x4c\x2e\x53\x45\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01"
+ "\x01\x05\x05\x00\x03\x81\x81\x00\x83\xf4\x14\xa7\x6e\x59\xff\x80"
+ "\x64\xe7\xfa\xcf\x13\x80\x86\xe1\xed\x02\x38\xad\x96\x72\x25\xe5"
+ "\x06\x7a\x9a\xbc\x24\x74\xa9\x75\x55\xb2\x49\x80\x69\x45\x95\x4a"
+ "\x4c\x76\xa9\xe3\x4e\x49\xd3\xc2\x69\x5a\x95\x03\xeb\xba\x72\x23"
+ "\x9c\xfd\x3d\x8b\xc6\x07\x82\x3b\xf4\xf3\xef\x6c\x2e\x9e\x0b\xac"
+ "\x9e\x6c\xbb\x37\x4a\xa1\x9e\x73\xd1\xdc\x97\x61\xba\xfc\xd3\x49"
+ "\xa6\xc2\x4c\x55\x2e\x06\x37\x76\xb5\xef\x57\xe7\x57\x58\x8a\x71"
+ "\x63\xf3\xeb\xe7\x55\x68\x0d\xf6\x46\x4c\xfb\xf9\x43\xbb\x0c\x92"
+ "\x4f\x4e\x22\x7b\x63\xe8\x4f\x9c",
+ 600
+ }
+};
+
+static int
+test_cert(void)
+{
+ Certificate c, c2;
+ size_t size;
+ size_t i;
+ int ret;
+
+ memset(&c, 0, sizeof(c));
+ ret = copy_Certificate(&c, &c2);
+ if (ret)
+ return ret;
+ free_Certificate(&c2);
+
+ for (i = 0; i < sizeof(certs)/sizeof(certs[0]); i++) {
+
+ ret = decode_Certificate((unsigned char *)certs[i].cert,
+ certs[i].len, &c, &size);
+ if (ret)
+ return ret;
+
+ ret = copy_Certificate(&c, &c2);
+ free_Certificate(&c);
+ if (ret)
+ return ret;
+
+ free_Certificate(&c2);
+ }
+
+ return 0;
+}
+
+struct {
+ const char *sd;
+ size_t len;
+} signeddata[] = {
+ {
+ "\x30\x80\x02\x01\x03\x31\x0b\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a"
+ "\x05\x00\x30\x80\x06\x07\x2b\x06\x01\x05\x02\x03\x03\xa0\x80\x24"
+ "\x80\x04\x50\x30\x4e\xa0\x2b\x30\x29\xa0\x03\x02\x01\x12\xa1\x22"
+ "\x04\x20\x78\xf4\x86\x31\xc6\xc2\xc9\xcb\xef\x0c\xd7\x3a\x2a\xcd"
+ "\x8c\x13\x34\x83\xb1\x5c\xa8\xbe\xbf\x2f\xea\xd2\xbb\xd8\x8c\x18"
+ "\x47\x01\xa1\x1f\x30\x1d\xa0\x03\x02\x01\x0c\xa1\x16\x04\x14\xa6"
+ "\x2c\x52\xb2\x80\x98\x30\x40\xbc\x5f\xb0\x77\x2d\x8a\xd7\xa1\xda"
+ "\x3c\xc5\x62\x00\x00\x00\x00\x00\x00\xa0\x82\x02\x09\x30\x82\x02"
+ "\x05\x30\x82\x01\x6e\xa0\x03\x02\x01\x02\x02\x04\x49\x75\x57\xbf"
+ "\x30\x0b\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x30\x3b\x31"
+ "\x1f\x30\x1d\x06\x03\x55\x04\x03\x0c\x16\x63\x6f\x6d\x2e\x61\x70"
+ "\x70\x6c\x65\x2e\x6b\x65\x72\x62\x65\x72\x6f\x73\x2e\x6b\x64\x63"
+ "\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x0c\x0f\x53\x79\x73\x74\x65"
+ "\x6d\x20\x49\x64\x65\x6e\x74\x69\x74\x79\x30\x1e\x17\x0d\x30\x39"
+ "\x31\x32\x30\x34\x30\x30\x32\x30\x32\x34\x5a\x17\x0d\x32\x39\x31"
+ "\x31\x32\x39\x30\x30\x32\x30\x32\x34\x5a\x30\x3b\x31\x1f\x30\x1d"
+ "\x06\x03\x55\x04\x03\x0c\x16\x63\x6f\x6d\x2e\x61\x70\x70\x6c\x65"
+ "\x2e\x6b\x65\x72\x62\x65\x72\x6f\x73\x2e\x6b\x64\x63\x31\x18\x30"
+ "\x16\x06\x03\x55\x04\x0a\x0c\x0f\x53\x79\x73\x74\x65\x6d\x20\x49"
+ "\x64\x65\x6e\x74\x69\x74\x79\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86"
+ "\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89"
+ "\x02\x81\x81\x00\xb2\xc5\x4b\x34\xe3\x93\x99\xbb\xaa\xd1\x70\x62"
+ "\x6c\x9c\xcc\xa6\xbc\x47\xc3\x23\xff\x15\xb9\x11\x27\x0a\xf8\x55"
+ "\x4c\xb2\x43\x34\x75\xad\x55\xbb\xb9\x8a\xd0\x25\x64\xa4\x8c\x82"
+ "\x74\x5d\x89\x52\xe2\x76\x75\x08\x67\xb5\x9c\x9c\x69\x86\x0c\x6d"
+ "\x79\xf7\xa0\xbe\x42\x8f\x90\x46\x0c\x18\xf4\x7a\x56\x17\xa4\x65"
+ "\x00\x3a\x5e\x3e\xbf\xbc\xf5\xe2\x2c\x26\x03\x52\xdd\xd4\x85\x3f"
+ "\x03\xd7\x0c\x45\x7f\xff\xdd\x1e\x70\x6c\x9f\xb0\x8c\xd0\x33\xad"
+ "\x92\x54\x17\x9d\x88\x89\x1a\xee\xef\xf7\x96\x3e\x68\xc3\xd1\x60"
+ "\x47\x86\x80\x5d\x02\x03\x01\x00\x01\xa3\x18\x30\x16\x30\x14\x06"
+ "\x03\x55\x1d\x25\x04\x0d\x30\x0b\x06\x09\x2a\x86\x48\x86\xf7\x63"
+ "\x64\x04\x04\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05"
+ "\x05\x00\x03\x81\x81\x00\x9b\xbb\xaa\x63\x66\xd8\x70\x84\x3e\xf6"
+ "\xa1\x3b\xf3\xe6\xd7\x3d\xfc\x4f\xc9\x45\xaa\x31\x43\x8d\xb5\x72"
+ "\xe4\x34\x95\x7b\x6e\x5f\xe5\xc8\x5e\xaf\x12\x08\x6d\xd7\x25\x76"
+ "\x40\xd5\xdc\x83\x7f\x2f\x74\xd1\x63\xc0\x7c\x26\x4d\x53\x10\xe7"
+ "\xfa\xcc\xf2\x60\x41\x63\xdf\x56\xd6\xd9\xc0\xb4\xd0\x73\x99\x54"
+ "\x40\xad\x90\x79\x2d\xd2\x5e\xcb\x13\x22\x2b\xd0\x76\xef\x8a\x48"
+ "\xfd\xb2\x6e\xca\x04\x4e\x91\x3f\xb4\x63\xad\x22\x3a\xf7\x20\x9c"
+ "\x4c\x0e\x47\x78\xe5\x2a\x85\x0e\x90\x7a\xce\x46\xe6\x15\x02\xb0"
+ "\x83\xe7\xac\xfa\x92\xf8\x31\x81\xe8\x30\x81\xe5\x02\x01\x01\x30"
+ "\x43\x30\x3b\x31\x1f\x30\x1d\x06\x03\x55\x04\x03\x0c\x16\x63\x6f"
+ "\x6d\x2e\x61\x70\x70\x6c\x65\x2e\x6b\x65\x72\x62\x65\x72\x6f\x73"
+ "\x2e\x6b\x64\x63\x31\x18\x30\x16\x06\x03\x55\x04\x0a\x0c\x0f\x53"
+ "\x79\x73\x74\x65\x6d\x20\x49\x64\x65\x6e\x74\x69\x74\x79\x02\x04"
+ "\x49\x75\x57\xbf\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x30"
+ "\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x04\x81"
+ "\x80\x50\x2c\x69\xe1\xd2\xc4\xd1\xcc\xdc\xe0\xe9\x8a\x6b\x6a\x97"
+ "\x1b\xb4\xe0\xa8\x20\xbe\x09\x6d\xe1\x55\x5f\x07\x70\x94\x2e\x14"
+ "\xed\x4e\xb1\x69\x75\x40\xbb\x99\x87\xed\x23\x50\x27\x5f\xaa\xc4"
+ "\x84\x60\x06\xfe\x45\xfd\x7e\x1b\x18\xe0\x0b\x77\x35\x2a\xb2\xf2"
+ "\xe0\x88\x31\xad\x82\x31\x4a\xbc\x6d\x71\x62\xe6\x4d\x33\xb4\x09"
+ "\x6e\x3f\x14\x12\xf2\x89\x29\x31\x84\x60\x2b\xa8\x2d\xe6\xca\x2f"
+ "\x03\x3d\xd4\x69\x89\xb3\x98\xfd\xac\x63\x14\xaf\x6a\x52\x2a\xac"
+ "\xe3\x8e\xfa\x21\x41\x8f\xcc\x04\x2d\x52\xee\x49\x54\x0d\x58\x51"
+ "\x77\x00\x00",
+ 883
+ }
+};
+
+static int
+test_SignedData(void)
+{
+ SignedData sd;
+ size_t size, i;
+ int ret;
+
+ for (i = 0; i < sizeof(signeddata) / sizeof(signeddata[0]); i++) {
+
+ ret = decode_SignedData((unsigned char *)signeddata[i].sd,
+ signeddata[i].len, &sd, &size);
+ if (ret)
+ return ret;
+
+ free_SignedData(&sd);
+ }
+
+ return 0;
+}
+
+
+static int
+cmp_TESTLargeTag (void *a, void *b)
+{
+ TESTLargeTag *aa = a;
+ TESTLargeTag *ab = b;
+
+ COMPARE_INTEGER(aa,ab,foo);
+ COMPARE_INTEGER(aa,ab,bar);
+ return 0;
+}
+
+static int
+test_large_tag (void)
+{
+ struct test_case tests[] = {
+ { NULL, 15, "\x30\x0d\xbf\x7f\x03\x02\x01\x01\xbf\x81\x00\x03\x02\x01\x02", "large tag 1" }
+ };
+
+ int ntests = sizeof(tests) / sizeof(*tests);
+ TESTLargeTag lt1;
+
+ memset(&lt1, 0, sizeof(lt1));
+ lt1.foo = 1;
+ lt1.bar = 2;
+
+ tests[0].val = &lt1;
+
+ return generic_test (tests, ntests, sizeof(TESTLargeTag),
+ (generic_encode)encode_TESTLargeTag,
+ (generic_length)length_TESTLargeTag,
+ (generic_decode)decode_TESTLargeTag,
+ (generic_free)free_TESTLargeTag,
+ cmp_TESTLargeTag,
+ (generic_copy)copy_TESTLargeTag);
+}
+
+struct test_data {
+ int ok;
+ size_t len;
+ size_t expected_len;
+ void *data;
+};
+
+static int
+check_tag_length(void)
+{
+ struct test_data td[] = {
+ { 1, 3, 3, "\x02\x01\x00"},
+ { 1, 3, 3, "\x02\x01\x7f"},
+ { 1, 4, 4, "\x02\x02\x00\x80"},
+ { 1, 4, 4, "\x02\x02\x01\x00"},
+ { 1, 4, 4, "\x02\x02\x02\x00"},
+ { 0, 3, 0, "\x02\x02\x00"},
+ { 0, 3, 0, "\x02\x7f\x7f"},
+ { 0, 4, 0, "\x02\x03\x00\x80"},
+ { 0, 4, 0, "\x02\x7f\x01\x00"},
+ { 0, 5, 0, "\x02\xff\x7f\x02\x00"}
+ };
+ size_t sz;
+ TESTuint32 values[] = {0, 127, 128, 256, 512,
+ 0, 127, 128, 256, 512 };
+ TESTuint32 u;
+ int i, ret, failed = 0;
+ void *buf;
+
+ for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) {
+ struct map_page *page;
+
+ buf = map_alloc(OVERRUN, td[i].data, td[i].len, &page);
+
+ ret = decode_TESTuint32(buf, td[i].len, &u, &sz);
+ if (ret) {
+ if (td[i].ok) {
+ printf("failed with tag len test %d\n", i);
+ failed = 1;
+ }
+ } else {
+ if (td[i].ok == 0) {
+ printf("failed with success for tag len test %d\n", i);
+ failed = 1;
+ }
+ if (td[i].expected_len != sz) {
+ printf("wrong expected size for tag test %d\n", i);
+ failed = 1;
+ }
+ if (values[i] != u) {
+ printf("wrong value for tag test %d\n", i);
+ failed = 1;
+ }
+ }
+ map_free(page, "test", "decode");
+ }
+ return failed;
+}
+
+static int
+check_tag_length64(void)
+{
+ struct test_data td[] = {
+ { 1, 3, 3, "\x02\x01\x00"},
+ { 1, 7, 7, "\x02\x05\x01\xff\xff\xff\xff"},
+ { 1, 7, 7, "\x02\x05\x02\x00\x00\x00\x00"},
+ { 1, 9, 9, "\x02\x07\x7f\xff\xff\xff\xff\xff\xff"},
+ { 1, 10, 10, "\x02\x08\x00\x80\x00\x00\x00\x00\x00\x00"},
+ { 1, 10, 10, "\x02\x08\x7f\xff\xff\xff\xff\xff\xff\xff"},
+ { 1, 11, 11, "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff"},
+ { 0, 3, 0, "\x02\x02\x00"},
+ { 0, 3, 0, "\x02\x7f\x7f"},
+ { 0, 4, 0, "\x02\x03\x00\x80"},
+ { 0, 4, 0, "\x02\x7f\x01\x00"},
+ { 0, 5, 0, "\x02\xff\x7f\x02\x00"}
+ };
+ size_t sz;
+ TESTuint64 values[] = {0, 8589934591LL, 8589934592LL,
+ 36028797018963967LL, 36028797018963968LL,
+ 9223372036854775807LL, 18446744073709551615ULL,
+ 0, 127, 128, 256, 512 };
+ TESTuint64 u;
+ int i, ret, failed = 0;
+ void *buf;
+
+ if (sizeof(TESTuint64) != sizeof(uint64_t)) {
+ ret += 1;
+ printf("sizeof(TESTuint64) %d != sizeof(uint64_t) %d\n",
+ (int)sizeof(TESTuint64), (int)sizeof(uint64_t));
+ }
+
+ for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) {
+ struct map_page *page;
+
+ buf = map_alloc(OVERRUN, td[i].data, td[i].len, &page);
+
+ ret = decode_TESTuint64(buf, td[i].len, &u, &sz);
+ if (ret) {
+ if (td[i].ok) {
+ printf("failed with tag len test %d\n", i);
+ printf("ret = %d\n", ret);
+ failed = 1;
+ }
+ } else {
+ if (td[i].ok == 0) {
+ printf("failed with success for tag len test %d\n", i);
+ failed = 1;
+ }
+ if (td[i].expected_len != sz) {
+ printf("wrong expected size for tag test %d\n", i);
+ printf("sz = %lu\n", (unsigned long)sz);
+ failed = 1;
+ }
+ if (values[i] != u) {
+ printf("wrong value for tag test %d\n", i);
+ printf("Expected value: %llu\nActual value: %llu\n",
+ (unsigned long long)values[i], (unsigned long long)u);
+ failed = 1;
+ }
+ }
+ map_free(page, "test", "decode");
+ }
+ return failed;
+}
+
+static int
+check_tag_length64s(void)
+{
+ struct test_data td[] = {
+ { 1, 3, 3, "\x02\x01\x00"},
+ { 1, 7, 7, "\x02\x05\xfe\x00\x00\x00\x01"},
+ { 1, 7, 7, "\x02\x05\xfe\x00\x00\x00\x00"},
+ { 1, 9, 9, "\x02\x07\x80\x00\x00\x00\x00\x00\x01"},
+ { 1, 9, 9, "\x02\x07\x80\x00\x00\x00\x00\x00\x00"},
+ { 1, 10, 10, "\x02\x08\x80\x00\x00\x00\x00\x00\x00\x01"},
+ { 1, 9, 9, "\x02\x07\x80\x00\x00\x00\x00\x00\x01"},
+ { 0, 3, 0, "\x02\x02\x00"},
+ { 0, 3, 0, "\x02\x7f\x7f"},
+ { 0, 4, 0, "\x02\x03\x00\x80"},
+ { 0, 4, 0, "\x02\x7f\x01\x00"},
+ { 0, 5, 0, "\x02\xff\x7f\x02\x00"}
+ };
+ size_t sz;
+ TESTint64 values[] = {0, -8589934591LL, -8589934592LL,
+ -36028797018963967LL, -36028797018963968LL,
+ -9223372036854775807LL, -36028797018963967LL,
+ 0, 127, 128, 256, 512 };
+ TESTint64 u;
+ int i, ret, failed = 0;
+ void *buf;
+
+ for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) {
+ struct map_page *page;
+
+ buf = map_alloc(OVERRUN, td[i].data, td[i].len, &page);
+
+ ret = decode_TESTint64(buf, td[i].len, &u, &sz);
+ if (ret) {
+ if (td[i].ok) {
+ printf("failed with tag len test %d\n", i);
+ printf("ret = %d\n", ret);
+ failed = 1;
+ }
+ } else {
+ if (td[i].ok == 0) {
+ printf("failed with success for tag len test %d\n", i);
+ failed = 1;
+ }
+ if (td[i].expected_len != sz) {
+ printf("wrong expected size for tag test %d\n", i);
+ printf("sz = %lu\n", (unsigned long)sz);
+ failed = 1;
+ }
+ if (values[i] != u) {
+ printf("wrong value for tag test %d\n", i);
+ printf("Expected value: %lld\nActual value: %lld\n",
+ (long long)values[i], (long long)u);
+ failed = 1;
+ }
+ }
+ map_free(page, "test", "decode");
+ }
+ return failed;
+}
+
+static int
+cmp_TESTChoice (void *a, void *b)
+{
+ return 0;
+}
+
+static int
+test_choice (void)
+{
+ struct test_case tests[] = {
+ { NULL, 5, "\xa1\x03\x02\x01\x01", "large choice 1" },
+ { NULL, 5, "\xa2\x03\x02\x01\x02", "large choice 2" }
+ };
+
+ int ret = 0, ntests = sizeof(tests) / sizeof(*tests);
+ TESTChoice1 c1;
+ TESTChoice1 c2_1;
+ TESTChoice2 c2_2;
+
+ memset(&c1, 0, sizeof(c1));
+ c1.element = choice_TESTChoice1_i1;
+ c1.u.i1 = 1;
+ tests[0].val = &c1;
+
+ memset(&c2_1, 0, sizeof(c2_1));
+ c2_1.element = choice_TESTChoice1_i2;
+ c2_1.u.i2 = 2;
+ tests[1].val = &c2_1;
+
+ ret += generic_test (tests, ntests, sizeof(TESTChoice1),
+ (generic_encode)encode_TESTChoice1,
+ (generic_length)length_TESTChoice1,
+ (generic_decode)decode_TESTChoice1,
+ (generic_free)free_TESTChoice1,
+ cmp_TESTChoice,
+ (generic_copy)copy_TESTChoice1);
+
+ memset(&c2_2, 0, sizeof(c2_2));
+ c2_2.element = choice_TESTChoice2_asn1_ellipsis;
+ c2_2.u.asn1_ellipsis.data = "\xa2\x03\x02\x01\x02";
+ c2_2.u.asn1_ellipsis.length = 5;
+ tests[1].val = &c2_2;
+
+ ret += generic_test (tests, ntests, sizeof(TESTChoice2),
+ (generic_encode)encode_TESTChoice2,
+ (generic_length)length_TESTChoice2,
+ (generic_decode)decode_TESTChoice2,
+ (generic_free)free_TESTChoice2,
+ cmp_TESTChoice,
+ (generic_copy)copy_TESTChoice2);
+
+ return ret;
+}
+
+/* Test --decorate=TYPE:FIELD-TYPE:field-name[?] */
+static int
+test_decorated(void)
+{
+ TESTNotDecorated tnd;
+ TESTDecorated td, td_copy;
+ size_t len, size;
+ void *ptr;
+ int ret;
+
+ memset(&td, 0, sizeof(td));
+ memset(&tnd, 0, sizeof(tnd));
+
+ my_copy_vers_called = 0;
+ my_free_vers_called = 0;
+
+ td.version = 3;
+ td.version3.v = 5;
+ td.privthing = &td;
+ if ((td.version2 = malloc(sizeof(*td.version2))) == NULL)
+ errx(1, "out of memory");
+ *td.version2 = 5;
+ ASN1_MALLOC_ENCODE(TESTDecorated, ptr, len, &td, &size, ret);
+ if (ret) {
+ warnx("could not encode a TESTDecorated struct");
+ return 1;
+ }
+ ret = decode_TESTNotDecorated(ptr, len, &tnd, &size);
+ if (ret) {
+ warnx("could not decode a TESTDecorated struct as TESTNotDecorated");
+ return 1;
+ }
+ free(ptr);
+ if (size != len) {
+ warnx("TESTDecorated encoded size mismatch");
+ return 1;
+ }
+ if (td.version != tnd.version) {
+ warnx("TESTDecorated did not decode as a TESTNotDecorated correctly");
+ return 1;
+ }
+ if (copy_TESTDecorated(&td, &td_copy)) {
+ warnx("copy_TESTDecorated() failed");
+ return 1;
+ }
+ if (td.version != td_copy.version) {
+ warnx("copy_TESTDecorated() did not work correctly (1)");
+ return 1;
+ }
+ if (td_copy.version2 == NULL || *td.version2 != *td_copy.version2) {
+ warnx("copy_TESTDecorated() did not work correctly (2)");
+ return 1;
+ }
+ if (td.version3.v != td_copy.version3.v ||
+ my_copy_vers_called != 1) {
+ warnx("copy_TESTDecorated() did not work correctly (3)");
+ return 1;
+ }
+ if (td_copy.privthing != 0) {
+ warnx("copy_TESTDecorated() did not work correctly (4)");
+ return 1;
+ }
+
+ free_TESTDecorated(&td_copy);
+ free_TESTDecorated(&td);
+ if (td.version2) {
+ warnx("free_TESTDecorated() did not work correctly (1)");
+ return 1;
+ }
+ if (td.version3.v != 0 || my_free_vers_called != 2) {
+ warnx("free_TESTDecorated() did not work correctly (2)");
+ return 1;
+ }
+ if (td.privthing != 0) {
+ warnx("free_TESTDecorated() did not work correctly (3)");
+ return 1;
+ }
+ return 0;
+}
+
+static int
+test_extensible_choice(void)
+{
+ PA_FX_FAST_REQUEST r, r2;
+ size_t len, size;
+ void *ptr;
+ int ret;
+
+ memset(&r, 0, sizeof(r));
+
+ ret = copy_PA_FX_FAST_REQUEST(&r, &r2);
+ if (ret)
+ return ret;
+ free_PA_FX_FAST_REQUEST(&r2);
+
+ r.element = 0;
+ r.u.asn1_ellipsis.data = "hello";
+ r.u.asn1_ellipsis.length = sizeof("hello") - 1;
+ ret = copy_PA_FX_FAST_REQUEST(&r, &r2);
+ if (ret)
+ errx(1, "Out of memory");
+ if (r2.element != 0)
+ errx(1, "Extensible CHOICE copy failure to set discriminant to 0");
+ if (r2.u.asn1_ellipsis.length != r.u.asn1_ellipsis.length)
+ errx(1, "Extensible CHOICE copy failure to copy extension");
+ if (memcmp(r.u.asn1_ellipsis.data, r2.u.asn1_ellipsis.data,
+ r.u.asn1_ellipsis.length) != 0)
+ errx(1, "Extensible CHOICE copy failure to copy extension (2)");
+ free_PA_FX_FAST_REQUEST(&r2);
+
+ ASN1_MALLOC_ENCODE(PA_FX_FAST_REQUEST, ptr, len, &r, &size, ret);
+ if (ret || len != size)
+ errx(1, "Extensible CHOICE encoding failure");
+
+ ret = decode_PA_FX_FAST_REQUEST(ptr, len, &r2, &size);
+ if (ret || len != size)
+ errx(1, "Extensible CHOICE decoding failure");
+
+ if (r2.element != 0)
+ errx(1, "Extensible CHOICE decode failure to set discriminant to 0");
+ if (r2.u.asn1_ellipsis.length != r.u.asn1_ellipsis.length)
+ errx(1, "Extensible CHOICE decode failure to copy extension");
+ if (memcmp(r.u.asn1_ellipsis.data, r2.u.asn1_ellipsis.data,
+ r.u.asn1_ellipsis.length) != 0)
+ errx(1, "Extensible CHOICE decode failure to copy extension (2)");
+
+ free_PA_FX_FAST_REQUEST(&r2);
+ free(ptr);
+ return 0;
+}
+
+static int
+test_decorated_choice(void)
+{
+ TESTNotDecoratedChoice tndc;
+ TESTDecoratedChoice tdc, tdc_copy;
+ size_t len, size;
+ void *ptr;
+ int ret;
+
+ memset(&tdc, 0, sizeof(tdc));
+ memset(&tndc, 0, sizeof(tndc));
+
+ my_copy_vers_called = 0;
+ my_free_vers_called = 0;
+
+ tdc.element = choice_TESTDecoratedChoice_version;
+ tdc.u.version = 3;
+ tdc.version3.v = 5;
+ tdc.privthing = &tdc;
+ if ((tdc.version2 = malloc(sizeof(*tdc.version2))) == NULL)
+ errx(1, "out of memory");
+ *tdc.version2 = 5;
+ ASN1_MALLOC_ENCODE(TESTDecoratedChoice, ptr, len, &tdc, &size, ret);
+ if (ret) {
+ warnx("could not encode a TESTDecoratedChoice struct");
+ return 1;
+ }
+ ret = decode_TESTNotDecoratedChoice(ptr, len, &tndc, &size);
+ if (ret) {
+ warnx("could not decode a TESTDecoratedChoice struct as TESTNotDecoratedChoice");
+ return 1;
+ }
+ free(ptr);
+ if (size != len) {
+ warnx("TESTDecoratedChoice encoded size mismatch");
+ return 1;
+ }
+ if ((int)tdc.element != (int)tndc.element ||
+ tdc.u.version != tndc.u.version) {
+ warnx("TESTDecoratedChoice did not decode as a TESTNotDecoratedChoice correctly");
+ return 1;
+ }
+ if (copy_TESTDecoratedChoice(&tdc, &tdc_copy)) {
+ warnx("copy_TESTDecoratedChoice() failed");
+ return 1;
+ }
+ if ((int)tdc.element != (int)tdc_copy.element ||
+ tdc.u.version != tdc_copy.u.version) {
+ warnx("copy_TESTDecoratedChoice() did not work correctly (1)");
+ return 1;
+ }
+ if (tdc_copy.version2 == NULL || *tdc.version2 != *tdc_copy.version2) {
+ warnx("copy_TESTDecoratedChoice() did not work correctly (2)");
+ return 1;
+ }
+ if (tdc.version3.v != tdc_copy.version3.v ||
+ my_copy_vers_called != 1) {
+ warnx("copy_TESTDecoratedChoice() did not work correctly (3)");
+ return 1;
+ }
+ if (tdc_copy.privthing != 0) {
+ warnx("copy_TESTDecoratedChoice() did not work correctly (4)");
+ return 1;
+ }
+
+ free_TESTDecoratedChoice(&tdc_copy);
+ free_TESTDecoratedChoice(&tdc);
+ if (tdc.version2) {
+ warnx("free_TESTDecoratedChoice() did not work correctly (1)");
+ return 1;
+ }
+ if (tdc.version3.v != 0 || my_free_vers_called != 2) {
+ warnx("free_TESTDecoratedChoice() did not work correctly (2)");
+ return 1;
+ }
+ if (tdc.privthing != 0) {
+ warnx("free_TESTDecoratedChoice() did not work correctly (3)");
+ return 1;
+ }
+ return 0;
+}
+
+
+static int
+cmp_TESTImplicit (void *a, void *b)
+{
+ TESTImplicit *aa = a;
+ TESTImplicit *ab = b;
+
+ COMPARE_INTEGER(aa,ab,ti1);
+ COMPARE_INTEGER(aa,ab,ti2.foo);
+ COMPARE_INTEGER(aa,ab,ti3);
+ return 0;
+}
+
+static int
+cmp_TESTImplicit2 (void *a, void *b)
+{
+ TESTImplicit2 *aa = a;
+ TESTImplicit2 *ab = b;
+
+ COMPARE_INTEGER(aa,ab,ti1);
+ COMPARE_INTEGER(aa,ab,ti3);
+ IF_OPT_COMPARE(aa,ab,ti4) {
+ COMPARE_INTEGER(aa,ab,ti4[0]);
+ }
+ return 0;
+}
+
+static int
+cmp_TESTImplicit3 (void *a, void *b)
+{
+ TESTImplicit3 *aa = a;
+ TESTImplicit3 *ab = b;
+
+ COMPARE_INTEGER(aa,ab,element);
+ if (aa->element == choice_TESTImplicit3_ti1) {
+ COMPARE_INTEGER(aa,ab,u.ti1);
+ } else {
+ COMPARE_INTEGER(aa,ab,u.ti2.element);
+ COMPARE_INTEGER(aa,ab,u.ti2.u.i1);
+ }
+ return 0;
+}
+
+static int
+cmp_TESTImplicit4 (void *a, void *b)
+{
+ TESTImplicit4 *aa = a;
+ TESTImplicit4 *ab = b;
+
+ COMPARE_INTEGER(aa,ab,element);
+ if (aa->element == choice_TESTImplicit4_ti1) {
+ COMPARE_INTEGER(aa,ab,u.ti1);
+ } else {
+ COMPARE_INTEGER(aa,ab,u.ti2.element);
+ COMPARE_INTEGER(aa,ab,u.ti2.u.i1);
+ }
+ return 0;
+}
+
+static int
+test_implicit (void)
+{
+ int ret = 0;
+ /*
+ * UNIV CONS Sequence = 14 bytes {
+ * CONTEXT PRIM tag 0 = 1 bytes [0] IMPLICIT content
+ * CONTEXT CONS tag 1 = 6 bytes [1]
+ * CONTEXT CONS tag 127 = 3 bytes [127]
+ * UNIV PRIM Integer = integer 2
+ * CONTEXT PRIM tag 2 = 1 bytes [2] IMPLICIT content
+ * }
+ */
+ struct test_case tests[] = {
+ { NULL, 16,
+ "\x30\x0e\x80\x01\x00\xa1\x06\xbf\x7f\x03\x02\x01\x02\x82\x01\x03",
+ "implicit 1" }
+ };
+ /*
+ * UNIV CONS Sequence = 10 bytes {
+ * CONTEXT PRIM tag 0 = 1 bytes [0] IMPLICIT content
+ * CONTEXT PRIM tag 2 = 1 bytes [2] IMPLICIT content
+ * CONTEXT PRIM tag 51 = 1 bytes [51] IMPLICIT content
+ * }
+ */
+ struct test_case tests2[] = {
+ { NULL, 12,
+ "\x30\x0a\x80\x01\x01\x82\x01\x03\x9f\x33\x01\x04",
+ "implicit 2" }
+ };
+ /*
+ * CONTEXT CONS tag 5 = 5 bytes [5]
+ * CONTEXT CONS tag 1 = 3 bytes [1]
+ * UNIV PRIM Integer = integer 5
+ */
+ struct test_case tests3[] = {
+ { NULL, 7,
+ "\xa5\x05\xa1\x03\x02\x01\x05",
+ "implicit 3" }
+ };
+ /*
+ * Notice: same as tests3[].bytes.
+ *
+ * CONTEXT CONS tag 5 = 5 bytes [5]
+ * CONTEXT CONS tag 1 = 3 bytes [1]
+ * UNIV PRIM Integer = integer 5
+ */
+ struct test_case tests4[] = {
+ { NULL, 7,
+ "\xa5\x05\xa1\x03\x02\x01\x05",
+ "implicit 4" }
+ };
+
+ TESTImplicit c0;
+ TESTImplicit2 c1;
+ TESTImplicit3 c2;
+ TESTImplicit4 c3;
+ int ti4 = 4;
+
+ memset(&c0, 0, sizeof(c0));
+ c0.ti1 = 0;
+ c0.ti2.foo = 2;
+ c0.ti3 = 3;
+ tests[0].val = &c0;
+
+ memset(&c1, 0, sizeof(c1));
+ c1.ti1 = 1;
+ c1.ti3 = 3;
+ c1.ti4 = &ti4;
+ tests2[0].val = &c1;
+
+ memset(&c2, 0, sizeof(c2));
+ c2.element = choice_TESTImplicit3_ti2;
+ c2.u.ti2.element = choice_TESTImplicit3_ti2_i1;
+ c2.u.ti2.u.i1 = 5;
+ tests3[0].val = &c2;
+
+ memset(&c3, 0, sizeof(c3));
+ c3.element = choice_TESTImplicit4_ti2;
+ c3.u.ti2.element = choice_TESTChoice2_i1;
+ c3.u.ti2.u.i1 = 5;
+ tests4[0].val = &c3;
+
+ ret += generic_test(tests,
+ sizeof(tests) / sizeof(*tests),
+ sizeof(TESTImplicit),
+ (generic_encode)encode_TESTImplicit,
+ (generic_length)length_TESTImplicit,
+ (generic_decode)decode_TESTImplicit,
+ (generic_free)free_TESTImplicit,
+ cmp_TESTImplicit,
+ (generic_copy)copy_TESTImplicit);
+
+ ret += generic_test(tests2,
+ sizeof(tests2) / sizeof(*tests2),
+ sizeof(TESTImplicit2),
+ (generic_encode)encode_TESTImplicit2,
+ (generic_length)length_TESTImplicit2,
+ (generic_decode)decode_TESTImplicit2,
+ (generic_free)free_TESTImplicit2,
+ cmp_TESTImplicit2,
+ NULL);
+
+ ret += generic_test(tests3,
+ sizeof(tests3) / sizeof(*tests3),
+ sizeof(TESTImplicit3),
+ (generic_encode)encode_TESTImplicit3,
+ (generic_length)length_TESTImplicit3,
+ (generic_decode)decode_TESTImplicit3,
+ (generic_free)free_TESTImplicit3,
+ cmp_TESTImplicit3,
+ NULL);
+
+ ret += generic_test(tests4,
+ sizeof(tests4) / sizeof(*tests4),
+ sizeof(TESTImplicit4),
+ (generic_encode)encode_TESTImplicit4,
+ (generic_length)length_TESTImplicit4,
+ (generic_decode)decode_TESTImplicit4,
+ (generic_free)free_TESTImplicit4,
+ cmp_TESTImplicit4,
+ NULL);
+
+ return ret;
+}
+
+static int
+cmp_TESTAlloc (void *a, void *b)
+{
+ TESTAlloc *aa = a;
+ TESTAlloc *ab = b;
+
+ IF_OPT_COMPARE(aa,ab,tagless) {
+ COMPARE_INTEGER(aa,ab,tagless->ai);
+ }
+
+ COMPARE_INTEGER(aa,ab,three);
+
+ IF_OPT_COMPARE(aa,ab,tagless2) {
+ COMPARE_OPT_OCTET_STRING(aa, ab, tagless2);
+ }
+
+ return 0;
+}
+
+/*
+UNIV CONS Sequence 12
+ UNIV CONS Sequence 5
+ CONTEXT CONS 0 3
+ UNIV PRIM Integer 1 01
+ CONTEXT CONS 1 3
+ UNIV PRIM Integer 1 03
+
+UNIV CONS Sequence 5
+ CONTEXT CONS 1 3
+ UNIV PRIM Integer 1 03
+
+UNIV CONS Sequence 8
+ CONTEXT CONS 1 3
+ UNIV PRIM Integer 1 04
+ UNIV PRIM Integer 1 05
+
+*/
+
+static int
+test_taglessalloc (void)
+{
+ struct test_case tests[] = {
+ { NULL, 14,
+ "\x30\x0c\x30\x05\xa0\x03\x02\x01\x01\xa1\x03\x02\x01\x03",
+ "alloc 1" },
+ { NULL, 7,
+ "\x30\x05\xa1\x03\x02\x01\x03",
+ "alloc 2" },
+ { NULL, 10,
+ "\x30\x08\xa1\x03\x02\x01\x04\x02\x01\x05",
+ "alloc 3" }
+ };
+
+ int ret = 0, ntests = sizeof(tests) / sizeof(*tests);
+ TESTAlloc c1, c2, c3;
+ heim_any any3;
+
+ memset(&c1, 0, sizeof(c1));
+ c1.tagless = ecalloc(1, sizeof(*c1.tagless));
+ c1.tagless->ai = 1;
+ c1.three = 3;
+ tests[0].val = &c1;
+
+ memset(&c2, 0, sizeof(c2));
+ c2.tagless = NULL;
+ c2.three = 3;
+ tests[1].val = &c2;
+
+ memset(&c3, 0, sizeof(c3));
+ c3.tagless = NULL;
+ c3.three = 4;
+ c3.tagless2 = &any3;
+ any3.data = "\x02\x01\x05";
+ any3.length = 3;
+ tests[2].val = &c3;
+
+ ret += generic_test (tests, ntests, sizeof(TESTAlloc),
+ (generic_encode)encode_TESTAlloc,
+ (generic_length)length_TESTAlloc,
+ (generic_decode)decode_TESTAlloc,
+ (generic_free)free_TESTAlloc,
+ cmp_TESTAlloc,
+ (generic_copy)copy_TESTAlloc);
+
+ free(c1.tagless);
+
+ return ret;
+}
+
+static int
+cmp_TESTOptional (void *a, void *b)
+{
+ TESTOptional *aa = a;
+ TESTOptional *ab = b;
+
+ IF_OPT_COMPARE(aa,ab,zero) {
+ COMPARE_OPT_INTEGER(aa,ab,zero);
+ }
+ IF_OPT_COMPARE(aa,ab,one) {
+ COMPARE_OPT_INTEGER(aa,ab,one);
+ }
+ return 0;
+}
+
+/*
+UNIV CONS Sequence 5
+ CONTEXT CONS 0 3
+ UNIV PRIM Integer 1 00
+
+UNIV CONS Sequence 5
+ CONTEXT CONS 1 3
+ UNIV PRIM Integer 1 03
+
+UNIV CONS Sequence 10
+ CONTEXT CONS 0 3
+ UNIV PRIM Integer 1 00
+ CONTEXT CONS 1 3
+ UNIV PRIM Integer 1 01
+
+*/
+
+static int
+test_optional (void)
+{
+ struct test_case tests[] = {
+ { NULL, 2,
+ "\x30\x00",
+ "optional 0" },
+ { NULL, 7,
+ "\x30\x05\xa0\x03\x02\x01\x00",
+ "optional 1" },
+ { NULL, 7,
+ "\x30\x05\xa1\x03\x02\x01\x01",
+ "optional 2" },
+ { NULL, 12,
+ "\x30\x0a\xa0\x03\x02\x01\x00\xa1\x03\x02\x01\x01",
+ "optional 3" }
+ };
+
+ int ret = 0, ntests = sizeof(tests) / sizeof(*tests);
+ TESTOptional c0, c1, c2, c3;
+ int zero = 0;
+ int one = 1;
+
+ c0.zero = NULL;
+ c0.one = NULL;
+ tests[0].val = &c0;
+
+ c1.zero = &zero;
+ c1.one = NULL;
+ tests[1].val = &c1;
+
+ c2.zero = NULL;
+ c2.one = &one;
+ tests[2].val = &c2;
+
+ c3.zero = &zero;
+ c3.one = &one;
+ tests[3].val = &c3;
+
+ ret += generic_test (tests, ntests, sizeof(TESTOptional),
+ (generic_encode)encode_TESTOptional,
+ (generic_length)length_TESTOptional,
+ (generic_decode)decode_TESTOptional,
+ (generic_free)free_TESTOptional,
+ cmp_TESTOptional,
+ (generic_copy)copy_TESTOptional);
+
+ return ret;
+}
+
+static int
+check_fail_largetag(void)
+{
+ struct test_case tests[] = {
+ {NULL, 14, "\x30\x0c\xbf\x87\xff\xff\xff\xff\xff\x7f\x03\x02\x01\x01",
+ "tag overflow"},
+ {NULL, 0, "", "empty buffer"},
+ {NULL, 7, "\x30\x05\xa1\x03\x02\x02\x01",
+ "one too short" },
+ {NULL, 7, "\x30\x04\xa1\x03\x02\x02\x01",
+ "two too short" },
+ {NULL, 7, "\x30\x03\xa1\x03\x02\x02\x01",
+ "three too short" },
+ {NULL, 7, "\x30\x02\xa1\x03\x02\x02\x01",
+ "four too short" },
+ {NULL, 7, "\x30\x01\xa1\x03\x02\x02\x01",
+ "five too short" },
+ {NULL, 7, "\x30\x00\xa1\x03\x02\x02\x01",
+ "six too short" },
+ {NULL, 7, "\x30\x05\xa1\x04\x02\x02\x01",
+ "inner one too long" },
+ {NULL, 7, "\x30\x00\xa1\x02\x02\x02\x01",
+ "inner one too short" },
+ {NULL, 8, "\x30\x05\xbf\x7f\x03\x02\x02\x01",
+ "inner one too short"},
+ {NULL, 8, "\x30\x06\xbf\x64\x03\x02\x01\x01",
+ "wrong tag"},
+ {NULL, 10, "\x30\x08\xbf\x9a\x9b\x38\x03\x02\x01\x01",
+ "still wrong tag"}
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ return generic_decode_fail(tests, ntests, sizeof(TESTLargeTag),
+ (generic_decode)decode_TESTLargeTag);
+}
+
+
+static int
+check_fail_sequence(void)
+{
+ struct test_case tests[] = {
+ {NULL, 0, "", "empty buffer"},
+ {NULL, 24,
+ "\x30\x16\xa0\x03\x02\x01\x01\xa1\x08\x30\x06\xbf\x7f\x03\x02\x01\x01"
+ "\x02\x01\x01\xa2\x03\x02\x01\x01",
+ "missing one byte from the end, internal length ok"},
+ {NULL, 25,
+ "\x30\x18\xa0\x03\x02\x01\x01\xa1\x08\x30\x06\xbf\x7f\x03\x02\x01\x01"
+ "\x02\x01\x01\xa2\x03\x02\x01\x01",
+ "inner length one byte too long"},
+ {NULL, 24,
+ "\x30\x17\xa0\x03\x02\x01\x01\xa1\x08\x30\x06\xbf\x7f\x03\x02\x01"
+ "\x01\x02\x01\x01\xa2\x03\x02\x01\x01",
+ "correct buffer but missing one too short"}
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ return generic_decode_fail(tests, ntests, sizeof(TESTSeq),
+ (generic_decode)decode_TESTSeq);
+}
+
+static int
+check_fail_choice(void)
+{
+ struct test_case tests[] = {
+ {NULL, 6,
+ "\xa1\x02\x02\x01\x01",
+ "choice one too short"},
+ {NULL, 6,
+ "\xa1\x03\x02\x02\x01",
+ "choice one too short inner"}
+ };
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ return generic_decode_fail(tests, ntests, sizeof(TESTChoice1),
+ (generic_decode)decode_TESTChoice1);
+}
+
+static int
+check_fail_Ticket(void)
+{
+ char buf[100];
+ size_t i;
+ int ret;
+ struct test_case test;
+ Ticket ticket;
+
+ for (i = 0; i < sizeof(buf); i++) {
+ memset(buf, 0, sizeof(buf));
+ memset(&ticket, 0, sizeof(ticket));
+ test.val = &ticket;
+ test.byte_len = i;
+ test.bytes = buf;
+ test.name = "zero life";
+ ret = generic_decode_fail(&test, 1, sizeof(Ticket),
+ (generic_decode)decode_Ticket);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int
+check_seq(void)
+{
+ TESTSeqOf seq;
+ TESTInteger i = 0;
+ int ret;
+
+ seq.val = NULL;
+ seq.len = 0;
+
+ ret = add_TESTSeqOf(&seq, &i);
+ if (ret) { printf("failed adding\n"); goto out; }
+ ret = add_TESTSeqOf(&seq, &i);
+ if (ret) { printf("failed adding\n"); goto out; }
+ ret = add_TESTSeqOf(&seq, &i);
+ if (ret) { printf("failed adding\n"); goto out; }
+ ret = add_TESTSeqOf(&seq, &i);
+ if (ret) { printf("failed adding\n"); goto out; }
+
+ ret = remove_TESTSeqOf(&seq, seq.len - 1);
+ if (ret) { printf("failed removing\n"); goto out; }
+ ret = remove_TESTSeqOf(&seq, 2);
+ if (ret) { printf("failed removing\n"); goto out; }
+ ret = remove_TESTSeqOf(&seq, 0);
+ if (ret) { printf("failed removing\n"); goto out; }
+ ret = remove_TESTSeqOf(&seq, 0);
+ if (ret) { printf("failed removing\n"); goto out; }
+ ret = remove_TESTSeqOf(&seq, 0);
+ if (ret == 0) {
+ printf("can remove from empty list");
+ return 1;
+ }
+
+ if (seq.len != 0) {
+ printf("seq not empty!");
+ return 1;
+ }
+ free_TESTSeqOf(&seq);
+ ret = 0;
+
+out:
+
+ return ret;
+}
+
+#define test_seq_of(type, ok, ptr) \
+{ \
+ heim_octet_string os; \
+ size_t size; \
+ type decode; \
+ ASN1_MALLOC_ENCODE(type, os.data, os.length, ptr, &size, ret); \
+ if (ret) \
+ return ret; \
+ if (os.length != size) \
+ abort(); \
+ ret = decode_##type(os.data, os.length, &decode, &size); \
+ free(os.data); \
+ if (ret) { \
+ if (ok) \
+ return 1; \
+ } else { \
+ free_##type(&decode); \
+ if (!ok) \
+ return 1; \
+ if (size != 0) \
+ return 1; \
+ } \
+ return 0; \
+}
+
+static int
+check_seq_of_size(void)
+{
+#if 0 /* template */
+ TESTInteger integers[4] = { 1, 2, 3, 4 };
+ int ret;
+
+ {
+ TESTSeqSizeOf1 ssof1f1 = { 1, integers };
+ TESTSeqSizeOf1 ssof1ok1 = { 2, integers };
+ TESTSeqSizeOf1 ssof1f2 = { 3, integers };
+
+ test_seq_of(TESTSeqSizeOf1, 0, &ssof1f1);
+ test_seq_of(TESTSeqSizeOf1, 1, &ssof1ok1);
+ test_seq_of(TESTSeqSizeOf1, 0, &ssof1f2);
+ }
+ {
+ TESTSeqSizeOf2 ssof2f1 = { 0, NULL };
+ TESTSeqSizeOf2 ssof2ok1 = { 1, integers };
+ TESTSeqSizeOf2 ssof2ok2 = { 2, integers };
+ TESTSeqSizeOf2 ssof2f2 = { 3, integers };
+
+ test_seq_of(TESTSeqSizeOf2, 0, &ssof2f1);
+ test_seq_of(TESTSeqSizeOf2, 1, &ssof2ok1);
+ test_seq_of(TESTSeqSizeOf2, 1, &ssof2ok2);
+ test_seq_of(TESTSeqSizeOf2, 0, &ssof2f2);
+ }
+ {
+ TESTSeqSizeOf3 ssof3f1 = { 0, NULL };
+ TESTSeqSizeOf3 ssof3ok1 = { 1, integers };
+ TESTSeqSizeOf3 ssof3ok2 = { 2, integers };
+
+ test_seq_of(TESTSeqSizeOf3, 0, &ssof3f1);
+ test_seq_of(TESTSeqSizeOf3, 1, &ssof3ok1);
+ test_seq_of(TESTSeqSizeOf3, 1, &ssof3ok2);
+ }
+ {
+ TESTSeqSizeOf4 ssof4ok1 = { 0, NULL };
+ TESTSeqSizeOf4 ssof4ok2 = { 1, integers };
+ TESTSeqSizeOf4 ssof4ok3 = { 2, integers };
+ TESTSeqSizeOf4 ssof4f1 = { 3, integers };
+
+ test_seq_of(TESTSeqSizeOf4, 1, &ssof4ok1);
+ test_seq_of(TESTSeqSizeOf4, 1, &ssof4ok2);
+ test_seq_of(TESTSeqSizeOf4, 1, &ssof4ok3);
+ test_seq_of(TESTSeqSizeOf4, 0, &ssof4f1);
+ }
+#endif
+ return 0;
+}
+
+static int
+check_TESTMechTypeList(void)
+{
+ TESTMechTypeList tl;
+ unsigned oid1[] = { 1, 2, 840, 48018, 1, 2, 2};
+ unsigned oid2[] = { 1, 2, 840, 113554, 1, 2, 2};
+ unsigned oid3[] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 30};
+ unsigned oid4[] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10};
+ TESTMechType array[] = {{ 7, oid1 },
+ { 7, oid2 },
+ { 10, oid3 },
+ { 10, oid4 }};
+ size_t size, len;
+ void *ptr;
+ int ret;
+
+ tl.len = 4;
+ tl.val = array;
+
+ ASN1_MALLOC_ENCODE(TESTMechTypeList, ptr, len, &tl, &size, ret);
+ if (ret)
+ errx(1, "TESTMechTypeList: %d", ret);
+ if (len != size)
+ abort();
+ free(ptr);
+ return 0;
+}
+
+static int
+cmp_TESTSeqOf4(void *a, void *b)
+{
+ TESTSeqOf4 *aa = a;
+ TESTSeqOf4 *ab = b;
+ int i;
+
+ IF_OPT_COMPARE(aa, ab, b1) {
+ COMPARE_INTEGER(aa->b1, ab->b1, len);
+ for (i = 0; i < aa->b1->len; ++i) {
+ COMPARE_INTEGER(aa->b1->val+i, ab->b1->val+i, u1);
+ COMPARE_INTEGER(aa->b1->val+i, ab->b1->val+i, u2);
+ COMPARE_OCTET_STRING(aa->b1->val+i, ab->b1->val+i, s1);
+ COMPARE_OCTET_STRING(aa->b1->val+i, ab->b1->val+i, s2);
+ }
+ }
+ IF_OPT_COMPARE(aa, ab, b2) {
+ COMPARE_INTEGER(aa->b2, ab->b2, len);
+ for (i = 0; i < aa->b2->len; ++i) {
+ COMPARE_INTEGER(aa->b2->val+i, ab->b2->val+i, u1);
+ COMPARE_INTEGER(aa->b2->val+i, ab->b2->val+i, u2);
+ COMPARE_INTEGER(aa->b2->val+i, ab->b2->val+i, u3);
+ COMPARE_OCTET_STRING(aa->b2->val+i, ab->b2->val+i, s1);
+ COMPARE_OCTET_STRING(aa->b2->val+i, ab->b2->val+i, s2);
+ COMPARE_OCTET_STRING(aa->b2->val+i, ab->b2->val+i, s3);
+ }
+ }
+ IF_OPT_COMPARE(aa, ab, b3) {
+ COMPARE_INTEGER(aa->b3, ab->b3, len);
+ for (i = 0; i < aa->b3->len; ++i) {
+ COMPARE_INTEGER(aa->b3->val+i, ab->b3->val+i, u1);
+ COMPARE_INTEGER(aa->b3->val+i, ab->b3->val+i, u2);
+ COMPARE_INTEGER(aa->b3->val+i, ab->b3->val+i, u3);
+ COMPARE_INTEGER(aa->b3->val+i, ab->b3->val+i, u4);
+ COMPARE_OCTET_STRING(aa->b3->val+i, ab->b3->val+i, s1);
+ COMPARE_OCTET_STRING(aa->b3->val+i, ab->b3->val+i, s2);
+ COMPARE_OCTET_STRING(aa->b3->val+i, ab->b3->val+i, s3);
+ COMPARE_OCTET_STRING(aa->b3->val+i, ab->b3->val+i, s4);
+ }
+ }
+ return 0;
+}
+
+static int
+test_seq4 (void)
+{
+ int ret = 0;
+ struct test_case tests[] = {
+ { NULL, 2,
+ "\x30\x00",
+ "seq4 0" },
+ { NULL, 4,
+ "\x30\x02" "\xa1\x00",
+ "seq4 1" },
+ { NULL, 8,
+ "\x30\x06" "\xa0\x02\x30\x00" "\xa1\x00",
+ "seq4 2" },
+ { NULL, 2 + (2 + 0x18) + (2 + 0x27) + (2 + 0x31),
+ "\x30\x76" /* 2 SEQ */
+ "\xa0\x18\x30\x16" /* 4 [0] SEQ */
+ "\x30\x14" /* 2 SEQ */
+ "\x04\x00" /* 2 OCTET-STRING */
+ "\x04\x02\x01\x02" /* 4 OCTET-STRING */
+ "\x02\x01\x01" /* 3 INT */
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff"
+ /* 11 INT */
+ "\xa1\x27" /* 2 [1] IMPL SEQ */
+ "\x30\x25" /* 2 SEQ */
+ "\x02\x01\x01" /* 3 INT */
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff"
+ /* 11 INT */
+ "\x02\x09\x00\x80\x00\x00\x00\x00\x00\x00\x00"
+ /* 11 INT */
+ "\x04\x00" /* 2 OCTET-STRING */
+ "\x04\x02\x01\x02" /* 4 OCTET-STRING */
+ "\x04\x04\x00\x01\x02\x03" /* 6 OCTET-STRING */
+ "\xa2\x31" /* 2 [2] IMPL SEQ */
+ "\x30\x2f" /* 2 SEQ */
+ "\x04\x00" /* 2 OCTET-STRING */
+ "\x02\x01\x01" /* 3 INT */
+ "\x04\x02\x01\x02" /* 4 OCTET-STRING */
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff"
+ /* 11 INT */
+ "\x04\x04\x00\x01\x02\x03" /* 6 OCTET-STRING */
+ "\x02\x09\x00\x80\x00\x00\x00\x00\x00\x00\x00"
+ /* 11 INT */
+ "\x04\x01\x00" /* 3 OCTET-STRING */
+ "\x02\x05\x01\x00\x00\x00\x00", /* 7 INT */
+ "seq4 3" },
+ };
+
+ int ntests = sizeof(tests) / sizeof(*tests);
+ TESTSeqOf4 c[4];
+ struct TESTSeqOf4_b1 b1[4];
+ struct TESTSeqOf4_b2 b2[4];
+ struct TESTSeqOf4_b3 b3[4];
+ struct TESTSeqOf4_b1_val b1val[4];
+ struct TESTSeqOf4_b2_val b2val[4];
+ struct TESTSeqOf4_b3_val b3val[4];
+
+ c[0].b1 = NULL;
+ c[0].b2 = NULL;
+ c[0].b3 = NULL;
+ tests[0].val = &c[0];
+
+ b2[1].len = 0;
+ b2[1].val = NULL;
+ c[1].b1 = NULL;
+ c[1].b2 = &b2[1];
+ c[1].b3 = NULL;
+ tests[1].val = &c[1];
+
+ b1[2].len = 0;
+ b1[2].val = NULL;
+ b2[2].len = 0;
+ b2[2].val = NULL;
+ c[2].b1 = &b1[2];
+ c[2].b2 = &b2[2];
+ c[2].b3 = NULL;
+ tests[2].val = &c[2];
+
+ b1val[3].s1.data = "";
+ b1val[3].s1.length = 0;
+ b1val[3].u1 = 1LL;
+ b1val[3].s2.data = "\x01\x02";
+ b1val[3].s2.length = 2;
+ b1val[3].u2 = -1LL;
+
+ b2val[3].s1.data = "";
+ b2val[3].s1.length = 0;
+ b2val[3].u1 = 1LL;
+ b2val[3].s2.data = "\x01\x02";
+ b2val[3].s2.length = 2;
+ b2val[3].u2 = -1LL;
+ b2val[3].s3.data = "\x00\x01\x02\x03";
+ b2val[3].s3.length = 4;
+ b2val[3].u3 = 1LL<<63;
+
+ b3val[3].s1.data = "";
+ b3val[3].s1.length = 0;
+ b3val[3].u1 = 1LL;
+ b3val[3].s2.data = "\x01\x02";
+ b3val[3].s2.length = 2;
+ b3val[3].u2 = -1LL;
+ b3val[3].s3.data = "\x00\x01\x02\x03";
+ b3val[3].s3.length = 4;
+ b3val[3].u3 = 1LL<<63;
+ b3val[3].s4.data = "\x00";
+ b3val[3].s4.length = 1;
+ b3val[3].u4 = 1LL<<32;
+
+ b1[3].len = 1;
+ b1[3].val = &b1val[3];
+ b2[3].len = 1;
+ b2[3].val = &b2val[3];
+ b3[3].len = 1;
+ b3[3].val = &b3val[3];
+ c[3].b1 = &b1[3];
+ c[3].b2 = &b2[3];
+ c[3].b3 = &b3[3];
+ tests[3].val = &c[3];
+
+ ret += generic_test (tests, ntests, sizeof(TESTSeqOf4),
+ (generic_encode)encode_TESTSeqOf4,
+ (generic_length)length_TESTSeqOf4,
+ (generic_decode)decode_TESTSeqOf4,
+ (generic_free)free_TESTSeqOf4,
+ cmp_TESTSeqOf4,
+ (generic_copy)copy_TESTSeqOf4);
+ return ret;
+}
+
+static int
+cmp_test_seqof5 (void *a, void *b)
+{
+ TESTSeqOf5 *aval = a;
+ TESTSeqOf5 *bval = b;
+
+ IF_OPT_COMPARE(aval, bval, outer) {
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u0);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s0);
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u1);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s1);
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u2);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s2);
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u3);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s3);
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u4);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s4);
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u5);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s5);
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u6);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s6);
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u7);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s7);
+ }
+ return 0;
+}
+
+static int
+test_seqof5(void)
+{
+ struct test_case tests[] = {
+ { NULL, 2, "\x30\x00", "seq5 0" },
+ { NULL, 126,
+ "\x30\x7c" /* SEQ */
+ "\x30\x7a" /* SEQ */
+ "\x30\x78" /* SEQ */
+ "\x02\x01\x01" /* INT 1 */
+ "\x04\x06\x01\x01\x01\x01\x01\x01" /* "\0x1"x6 */
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xfe" /* INT ~1 */
+ "\x04\x06\x02\x02\x02\x02\x02\x02" /* "\x02"x6 */
+ "\x02\x01\x02" /* INT 2 */
+ "\x04\x06\x03\x03\x03\x03\x03\x03" /* "\x03"x6 */
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xfd" /* INT ~2 */
+ "\x04\x06\x04\x04\x04\x04\x04\x04" /* ... */
+ "\x02\x01\x03"
+ "\x04\x06\x05\x05\x05\x05\x05\x05"
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xfc"
+ "\x04\x06\x06\x06\x06\x06\x06\x06"
+ "\x02\x01\x04"
+ "\x04\x06\x07\x07\x07\x07\x07\x07"
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xfb"
+ "\x04\x06\x08\x08\x08\x08\x08\x08",
+ "seq5 1" },
+ };
+
+ int ret = 0, ntests = sizeof(tests) / sizeof(*tests);
+ TESTSeqOf5 c[2];
+ struct TESTSeqOf5_outer outer;
+ struct TESTSeqOf5_outer_inner inner;
+ TESTuint64 u[8];
+ heim_octet_string s[8];
+ int i;
+
+ c[0].outer = NULL;
+ tests[0].val = &c[0];
+
+ for (i = 0; i < 8; ++i) {
+ u[i] = (i&1) == 0 ? i/2+1 : ~(i/2+1);
+ s[i].data = memset(malloc(s[i].length = 6), i+1, 6);
+ }
+
+ inner.u0 = u[0]; inner.u1 = u[1]; inner.u2 = u[2]; inner.u3 = u[3];
+ inner.u4 = u[4]; inner.u5 = u[5]; inner.u6 = u[6]; inner.u7 = u[7];
+ inner.s0 = s[0]; inner.s1 = s[1]; inner.s2 = s[2]; inner.s3 = s[3];
+ inner.s4 = s[4]; inner.s5 = s[5]; inner.s6 = s[6]; inner.s7 = s[7];
+
+ outer.inner = inner;
+ c[1].outer = &outer;
+ tests[1].val = &c[1];
+
+ ret += generic_test (tests, ntests, sizeof(TESTSeqOf5),
+ (generic_encode)encode_TESTSeqOf5,
+ (generic_length)length_TESTSeqOf5,
+ (generic_decode)decode_TESTSeqOf5,
+ (generic_free)free_TESTSeqOf5,
+ cmp_test_seqof5,
+ NULL);
+
+ for (i = 0; i < 8; ++i)
+ free(s[i].data);
+
+ return ret;
+}
+
+static int
+cmp_default(void *a, void *b)
+{
+ TESTDefault *aa = a;
+ TESTDefault *ab = b;
+
+ COMPARE_STRING(aa,ab,name);
+ COMPARE_INTEGER(aa,ab,version);
+ COMPARE_INTEGER(aa,ab,maxint);
+ COMPARE_INTEGER(aa,ab,works);
+ return 0;
+}
+
+static int
+test_default(void)
+{
+ struct test_case tests[] = {
+#ifndef DISABLE_TEST_64
+ { NULL, 2, "\x30\x00", NULL },
+#endif
+ { NULL, 25,
+ "\x30\x17\x0c\x07\x68\x65\x69\x6d\x64\x61"
+ "\x6c\xa0\x03\x02\x01\x07\x02\x04\x7f\xff"
+ "\xff\xff\x01\x01\x00",
+ NULL
+ },
+#ifndef DISABLE_TEST_64
+ { NULL, 10,
+ "\x30\x08\xa0\x03\x02\x01\x07\x01\x01\x00",
+ NULL
+ },
+#endif
+ { NULL, 17,
+ "\x30\x0f\x0c\x07\x68\x65\x69\x6d\x64\x61\x6c\x02\x04"
+ "\x7f\xff\xff\xff",
+ NULL
+ }
+ };
+
+ TESTDefault values[] = {
+#ifndef DISABLE_TEST_64
+ { "Heimdal", 8, 9223372036854775807LL, 1 },
+#endif
+ { "heimdal", 7, 2147483647, 0 },
+#ifndef DISABLE_TEST_64
+ { "Heimdal", 7, 9223372036854775807LL, 0 },
+#endif
+ { "heimdal", 8, 2147483647, 1 },
+ };
+ int i, ret;
+ int ntests = sizeof(tests) / sizeof(*tests);
+
+ for (i = 0; i < ntests; ++i) {
+ tests[i].val = &values[i];
+ if (asprintf (&tests[i].name, "TESTDefault %d", i) < 0)
+ errx(1, "malloc");
+ if (tests[i].name == NULL)
+ errx(1, "malloc");
+ }
+
+ ret = generic_test (tests, ntests, sizeof(TESTDefault),
+ (generic_encode)encode_TESTDefault,
+ (generic_length)length_TESTDefault,
+ (generic_decode)decode_TESTDefault,
+ (generic_free)free_TESTDefault,
+ cmp_default,
+ (generic_copy)copy_TESTDefault);
+ for (i = 0; i < ntests; ++i)
+ free(tests[i].name);
+
+ return ret;
+}
+
+static int
+test_x690sample(void)
+{
+ /*
+ * Taken from X.690, Appendix A, though sadly it's not specified whether
+ * it's in BER, DER, or CER, but it is clearly BER and neither DER nor CER
+ * because the tags of the members of the X690SamplePersonnelRecord type
+ * are not canonically sorted in the given sample.
+ *
+ * Our compiler does NOT canonically sort the members of SET { ... } types
+ * so it produces the same encoding after decoding this test vector. That
+ * is clearly a bug given that we aim to output DER.
+ *
+ * The template compiler doesn't even decode SET { ... } values properly
+ * when their members are not in the same order as defined (but the regular
+ * compiler does).
+ */
+ X690SamplePersonnelRecord r;
+ heim_octet_string os;
+ unsigned char encoded_sample[] = {
+ 0x60, 0x81, 0x85, 0x61, 0x10, 0x1a, 0x04, 0x4a, 0x6f, 0x68, 0x6e, 0x1a,
+ 0x01, 0x50, 0x1a, 0x05, 0x53, 0x6d, 0x69, 0x74, 0x68, 0xa0, 0x0a, 0x1a,
+ 0x08, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x42, 0x01, 0x33,
+ 0xa1, 0x0a, 0x43, 0x08, 0x31, 0x39, 0x37, 0x31, 0x30, 0x39, 0x31, 0x37,
+ 0xa2, 0x12, 0x61, 0x10, 0x1a, 0x04, 0x4d, 0x61, 0x72, 0x79, 0x1a, 0x01,
+ 0x54, 0x1a, 0x05, 0x53, 0x6d, 0x69, 0x74, 0x68, 0xa3, 0x42, 0x31, 0x1f,
+ 0x61, 0x11, 0x1a, 0x05, 0x52, 0x61, 0x6c, 0x70, 0x68, 0x1a, 0x01, 0x54,
+ 0x1a, 0x05, 0x53, 0x6d, 0x69, 0x74, 0x68, 0xa0, 0x0a, 0x43, 0x08, 0x31,
+ 0x39, 0x35, 0x37, 0x31, 0x31, 0x31, 0x31, 0x31, 0x1f, 0x61, 0x11, 0x1a,
+ 0x05, 0x53, 0x75, 0x73, 0x61, 0x6e, 0x1a, 0x01, 0x42, 0x1a, 0x05, 0x53,
+ 0x6d, 0x69, 0x74, 0x68, 0xa0, 0x0a, 0x43, 0x08, 0x31, 0x39, 0x35, 0x39,
+ 0x30, 0x37, 0x31, 0x37
+ };
+ size_t sz = 0;
+ int ret;
+
+ memset(&r, 0, sizeof(r));
+ if (decode_X690SamplePersonnelRecord(encoded_sample, sizeof(encoded_sample), &r, &sz))
+ return 1;
+ if (sz != sizeof(encoded_sample))
+ return 1;
+ free_X690SamplePersonnelRecord(&r);
+ memset(&r, 0, sizeof(r));
+
+ /* We re-construct the record manually to double-check the spec */
+ r.name.givenName = strdup("John");
+ r.name.initial = strdup("P");
+ r.name.familyName = strdup("Smith");
+ r.title = strdup("Director");
+ r.dateOfHire = strdup("19710917");
+ r.number = 51;
+ r.nameOfSpouse.givenName = strdup("Mary");
+ r.nameOfSpouse.initial = strdup("T");
+ r.nameOfSpouse.familyName = strdup("Smith");
+ r.children.val = calloc(2, sizeof(r.children.val[0]));
+ r.children.len = 2;
+ r.children.val[0].name.givenName = strdup("Ralph");
+ r.children.val[0].name.initial = strdup("T");
+ r.children.val[0].name.familyName = strdup("Smith");
+ r.children.val[0].dateOfBirth = strdup("19571111");
+ r.children.val[1].name.givenName = strdup("Susan");
+ r.children.val[1].name.initial = strdup("B");
+ r.children.val[1].name.familyName = strdup("Smith");
+ r.children.val[1].dateOfBirth = strdup("19590717");
+ os.length = 0;
+ os.data = 0;
+ ASN1_MALLOC_ENCODE(X690SamplePersonnelRecord, os.data, os.length, &r, &sz,
+ ret);
+ if (ret || sz != sizeof(encoded_sample) || sz != os.length ||
+ memcmp(encoded_sample, os.data, sz) != 0)
+ return 1;
+ free_X690SamplePersonnelRecord(&r);
+ free(os.data);
+ return 0;
+}
+
+#if ASN1_IOS_SUPPORTED
+static int
+test_ios(void)
+{
+ unsigned char encoded_sample[] = {
+ 0x30, 0x82, 0x04, 0x8e, 0x30, 0x82, 0x03, 0x76,
+ 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x6a,
+ 0x05, 0x97, 0xba, 0x71, 0xd7, 0xe6, 0xd3, 0xac,
+ 0x0e, 0xdc, 0x9e, 0xdc, 0x95, 0xa1, 0x5b, 0x99,
+ 0x8d, 0xe4, 0x0a, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+ 0x05, 0x00, 0x30, 0x55, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43,
+ 0x48, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x15, 0x53, 0x54, 0x4d, 0x69,
+ 0x63, 0x72, 0x6f, 0x65, 0x6c, 0x65, 0x63, 0x74,
+ 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x73, 0x20, 0x4e,
+ 0x56, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x1d, 0x53, 0x54, 0x4d, 0x20,
+ 0x54, 0x50, 0x4d, 0x20, 0x45, 0x4b, 0x20, 0x49,
+ 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69,
+ 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x20, 0x30,
+ 0x35, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x31,
+ 0x32, 0x31, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x31, 0x32,
+ 0x31, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x5a, 0x30, 0x00, 0x30, 0x82, 0x01, 0x22, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02,
+ 0x82, 0x01, 0x01, 0x00, 0xcc, 0x14, 0xeb, 0x27,
+ 0xa7, 0x8c, 0xeb, 0x0e, 0xa4, 0x86, 0xfa, 0x2d,
+ 0xf7, 0x83, 0x5f, 0x5f, 0xa8, 0xe9, 0x05, 0xb0,
+ 0x97, 0x01, 0x2b, 0x5b, 0xde, 0x50, 0x38, 0x0c,
+ 0x35, 0x5b, 0x1a, 0x2a, 0x72, 0x1b, 0xbc, 0x3d,
+ 0x08, 0xdd, 0x21, 0x79, 0x6c, 0xdb, 0x23, 0x9f,
+ 0xa9, 0x53, 0x10, 0x65, 0x1b, 0x1b, 0x56, 0xfd,
+ 0x2c, 0xfe, 0x53, 0xc8, 0x73, 0x52, 0xeb, 0xd9,
+ 0x96, 0xe3, 0x32, 0x56, 0x16, 0x04, 0x04, 0xce,
+ 0x93, 0x02, 0xa0, 0x80, 0x66, 0x80, 0x1e, 0x78,
+ 0x6a, 0x2f, 0x86, 0xe1, 0x81, 0xf9, 0x49, 0x96,
+ 0x6f, 0x49, 0x2a, 0x85, 0xb5, 0x8e, 0xaa, 0x4a,
+ 0x6a, 0x8c, 0xb3, 0x69, 0x75, 0x51, 0xbb, 0x23,
+ 0x6e, 0x87, 0xcc, 0x7b, 0xf8, 0xec, 0x13, 0x47,
+ 0x87, 0x1c, 0x91, 0xe1, 0x54, 0x37, 0xe8, 0xf2,
+ 0x66, 0xbf, 0x1e, 0xa5, 0xeb, 0x27, 0x1f, 0xdc,
+ 0xf3, 0x74, 0xd8, 0xb4, 0x7d, 0xf8, 0xbc, 0xe8,
+ 0x9e, 0x1f, 0xad, 0x61, 0xc2, 0xa0, 0x88, 0xcb,
+ 0x40, 0x36, 0xb3, 0x59, 0xcb, 0x72, 0xa2, 0x94,
+ 0x97, 0x3f, 0xed, 0xcc, 0xf0, 0xc3, 0x40, 0xaf,
+ 0xfd, 0x14, 0xb6, 0x4f, 0x04, 0x11, 0x65, 0x58,
+ 0x1a, 0xca, 0x34, 0x14, 0x7c, 0x1c, 0x75, 0x61,
+ 0x70, 0x47, 0x05, 0x8f, 0x7e, 0xd7, 0xd6, 0x03,
+ 0xe0, 0x32, 0x50, 0x80, 0x94, 0xfa, 0x73, 0xe8,
+ 0xb9, 0x15, 0x3d, 0xa3, 0xbf, 0x25, 0x5d, 0x2c,
+ 0xbb, 0xc5, 0xdf, 0x30, 0x1b, 0xa8, 0xf7, 0x4d,
+ 0x19, 0x8b, 0xeb, 0xce, 0x86, 0x04, 0x0f, 0xc1,
+ 0xd2, 0x92, 0x7c, 0x76, 0x57, 0x41, 0x44, 0x90,
+ 0xd8, 0x02, 0xf4, 0x82, 0xf3, 0xeb, 0xf2, 0xde,
+ 0x35, 0xee, 0x14, 0x9a, 0x1a, 0x6d, 0xe8, 0xd1,
+ 0x68, 0x91, 0xfb, 0xfb, 0xa0, 0x2a, 0x18, 0xaf,
+ 0xe5, 0x9f, 0x9d, 0x6f, 0x14, 0x97, 0x44, 0xe5,
+ 0xf0, 0xd5, 0x59, 0xb1, 0x02, 0x03, 0x01, 0x00,
+ 0x01, 0xa3, 0x82, 0x01, 0xa9, 0x30, 0x82, 0x01,
+ 0xa5, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23,
+ 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x1a, 0xdb,
+ 0x99, 0x4a, 0xb5, 0x8b, 0xe5, 0x7a, 0x0c, 0xc9,
+ 0xb9, 0x00, 0xe7, 0x85, 0x1e, 0x1a, 0x43, 0xc0,
+ 0x86, 0x60, 0x30, 0x42, 0x06, 0x03, 0x55, 0x1d,
+ 0x20, 0x04, 0x3b, 0x30, 0x39, 0x30, 0x37, 0x06,
+ 0x04, 0x55, 0x1d, 0x20, 0x00, 0x30, 0x2f, 0x30,
+ 0x2d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x02, 0x01, 0x16, 0x21, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e,
+ 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54,
+ 0x50, 0x4d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73,
+ 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x30, 0x59,
+ 0x06, 0x03, 0x55, 0x1d, 0x11, 0x01, 0x01, 0xff,
+ 0x04, 0x4f, 0x30, 0x4d, 0xa4, 0x4b, 0x30, 0x49,
+ 0x31, 0x16, 0x30, 0x14, 0x06, 0x05, 0x67, 0x81,
+ 0x05, 0x02, 0x01, 0x0c, 0x0b, 0x69, 0x64, 0x3a,
+ 0x35, 0x33, 0x35, 0x34, 0x34, 0x44, 0x32, 0x30,
+ 0x31, 0x17, 0x30, 0x15, 0x06, 0x05, 0x67, 0x81,
+ 0x05, 0x02, 0x02, 0x0c, 0x0c, 0x53, 0x54, 0x33,
+ 0x33, 0x48, 0x54, 0x50, 0x48, 0x41, 0x48, 0x43,
+ 0x30, 0x31, 0x16, 0x30, 0x14, 0x06, 0x05, 0x67,
+ 0x81, 0x05, 0x02, 0x03, 0x0c, 0x0b, 0x69, 0x64,
+ 0x3a, 0x30, 0x30, 0x34, 0x39, 0x30, 0x30, 0x30,
+ 0x38, 0x30, 0x67, 0x06, 0x03, 0x55, 0x1d, 0x09,
+ 0x04, 0x60, 0x30, 0x5e, 0x30, 0x17, 0x06, 0x05,
+ 0x67, 0x81, 0x05, 0x02, 0x10, 0x31, 0x0e, 0x30,
+ 0x0c, 0x0c, 0x03, 0x32, 0x2e, 0x30, 0x02, 0x01,
+ 0x00, 0x02, 0x02, 0x00, 0x8a, 0x30, 0x43, 0x06,
+ 0x05, 0x67, 0x81, 0x05, 0x02, 0x12, 0x31, 0x3a,
+ 0x30, 0x38, 0x02, 0x01, 0x00, 0x01, 0x01, 0xff,
+ 0xa0, 0x03, 0x0a, 0x01, 0x01, 0xa1, 0x03, 0x0a,
+ 0x01, 0x00, 0xa2, 0x03, 0x0a, 0x01, 0x00, 0xa3,
+ 0x10, 0x30, 0x0e, 0x16, 0x03, 0x33, 0x2e, 0x31,
+ 0x0a, 0x01, 0x04, 0x0a, 0x01, 0x02, 0x01, 0x01,
+ 0xff, 0xa4, 0x0f, 0x30, 0x0d, 0x16, 0x05, 0x31,
+ 0x34, 0x30, 0x2d, 0x32, 0x0a, 0x01, 0x02, 0x01,
+ 0x01, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d,
+ 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02,
+ 0x05, 0x20, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d,
+ 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00,
+ 0x30, 0x10, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04,
+ 0x09, 0x30, 0x07, 0x06, 0x05, 0x67, 0x81, 0x05,
+ 0x08, 0x01, 0x30, 0x4a, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x3e,
+ 0x30, 0x3c, 0x30, 0x3a, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2e,
+ 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x73,
+ 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x67, 0x6c,
+ 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x69, 0x67, 0x6e,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x74, 0x6d,
+ 0x74, 0x70, 0x6d, 0x65, 0x6b, 0x69, 0x6e, 0x74,
+ 0x30, 0x35, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01,
+ 0x01, 0x00, 0x3d, 0x4c, 0x38, 0x1e, 0x5b, 0x4f,
+ 0x1b, 0xcb, 0xe0, 0x9c, 0x63, 0xd5, 0x2f, 0x1f,
+ 0x04, 0x57, 0x0c, 0xae, 0xa1, 0x42, 0xfd, 0x9c,
+ 0xd9, 0x42, 0x04, 0x3b, 0x11, 0xf8, 0xe3, 0xbd,
+ 0xcf, 0x50, 0x00, 0x7a, 0xe1, 0x6c, 0xf8, 0x86,
+ 0x90, 0x13, 0x04, 0x1e, 0x92, 0xcd, 0xd3, 0x28,
+ 0x0b, 0xa4, 0xb5, 0x1f, 0xbb, 0xd4, 0x05, 0x82,
+ 0xed, 0x75, 0x02, 0x19, 0xe2, 0x61, 0xa6, 0x95,
+ 0x09, 0x56, 0x74, 0x85, 0x5a, 0xac, 0xeb, 0x52,
+ 0x0a, 0xda, 0xff, 0x9e, 0x7e, 0x90, 0x84, 0x80,
+ 0xa3, 0x9c, 0xdc, 0xf9, 0x00, 0x46, 0x2d, 0x91,
+ 0x71, 0x96, 0x0f, 0xfe, 0x55, 0xd3, 0xac, 0x49,
+ 0xe8, 0xc9, 0x81, 0x34, 0x1b, 0xbd, 0x2e, 0xfb,
+ 0xcc, 0x25, 0x2a, 0x4c, 0x18, 0xa4, 0xf3, 0xb7,
+ 0xc8, 0x4c, 0xce, 0x42, 0xce, 0x70, 0xa2, 0x08,
+ 0xc8, 0x4d, 0x26, 0x30, 0xa7, 0xab, 0xfb, 0xe7,
+ 0x2d, 0x62, 0x71, 0xe7, 0x5b, 0x9f, 0xf1, 0xc9,
+ 0x71, 0xd2, 0x0e, 0xb3, 0xdb, 0xd7, 0x63, 0xf1,
+ 0xe0, 0x4d, 0x83, 0x4e, 0xaa, 0x69, 0x2d, 0x2e,
+ 0x40, 0x01, 0xbb, 0xf4, 0x73, 0x0a, 0x3e, 0x3f,
+ 0xda, 0x97, 0x11, 0xae, 0x38, 0x65, 0x24, 0xd9,
+ 0x1c, 0x63, 0xbe, 0x0e, 0x51, 0x6d, 0x00, 0xd5,
+ 0xc6, 0x14, 0x1f, 0xcc, 0xf6, 0xc5, 0x39, 0xf3,
+ 0x51, 0x8e, 0x18, 0x00, 0x49, 0x86, 0x5b, 0xe1,
+ 0x6b, 0x69, 0xca, 0xe1, 0xf8, 0xcb, 0x7f, 0xdc,
+ 0x47, 0x4b, 0x38, 0xf7, 0xee, 0x56, 0xcb, 0xe7,
+ 0xd8, 0xa8, 0x9d, 0x9b, 0xa9, 0x9b, 0x65, 0xd5,
+ 0x26, 0x5a, 0xef, 0x32, 0xaa, 0x62, 0x42, 0x6b,
+ 0x10, 0xe6, 0xd7, 0x5b, 0xb8, 0x67, 0x7e, 0xc4,
+ 0x4f, 0x75, 0x5b, 0xbc, 0x28, 0x06, 0xfd, 0x2b,
+ 0x4e, 0x04, 0xbd, 0xf5, 0xd4, 0x42, 0x59, 0xdb,
+ 0xea, 0xa4, 0x2b, 0x6f, 0x56, 0x3d, 0xf7, 0xaa,
+ 0x75, 0x06,
+ };
+ char cert_json[] = {
+ "{\"_type\":\"Certificate\",\"tbsCertificate\":{\"_type\":\"TBSCertificate"
+ "\",\"_save\":\"30820376A00302010202146A0597BA71D7E6D3AC0EDC9EDC95A15"
+ "B998DE40A300D06092A864886F70D01010B05003055310B30090603550406130"
+ "24348311E301C060355040A131553544D6963726F656C656374726F6E6963732"
+ "04E56312630240603550403131D53544D2054504D20454B20496E7465726D656"
+ "469617465204341203035301E170D3138313231343030303030305A170D32383"
+ "13231343030303030305A300030820122300D06092A864886F70D01010105000"
+ "382010F003082010A0282010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E90"
+ "5B097012B5BDE50380C355B1A2A721BBC3D08DD21796CDB239FA95310651B1B5"
+ "6FD2CFE53C87352EBD996E33256160404CE9302A08066801E786A2F86E181F94"
+ "9966F492A85B58EAA4A6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E"
+ "8F266BF1EA5EB271FDCF374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A"
+ "294973FEDCCF0C340AFFD14B64F041165581ACA34147C1C75617047058F7ED7D"
+ "603E032508094FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040"
+ "FC1D2927C7657414490D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A1"
+ "8AFE59F9D6F149744E5F0D559B10203010001A38201A9308201A5301F0603551"
+ "D230418301680141ADB994AB58BE57A0CC9B900E7851E1A43C08660304206035"
+ "51D20043B303930370604551D2000302F302D06082B060105050702011621687"
+ "474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F3"
+ "0590603551D110101FF044F304DA44B304931163014060567810502010C0B696"
+ "43A353335343444323031173015060567810502020C0C5354333348545048414"
+ "8433031163014060567810502030C0B69643A303034393030303830670603551"
+ "D090460305E301706056781050210310E300C0C03322E300201000202008A304"
+ "306056781050212313A30380201000101FFA0030A0101A1030A0100A2030A010"
+ "0A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A010"
+ "2010100300E0603551D0F0101FF040403020520300C0603551D130101FF04023"
+ "00030100603551D250409300706056781050801304A06082B060105050701010"
+ "43E303C303A06082B06010505073002862E687474703A2F2F7365637572652E6"
+ "76C6F62616C7369676E2E636F6D2F73746D74706D656B696E7430352E637274\""
+ ",\"version\":\"rfc3280_version_3\",\"serialNumber\":\"6A0597BA71D7E6D3A"
+ "C0EDC9EDC95A15B998DE40A\",\"signature\":{\"_type\":\"AlgorithmIdentifi"
+ "er\",\"algorithm\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"1.2.840.1135"
+ "49.1.1.11\",\"components\":[1,2,840,113549,1,1,11],\"name\":\"id-pkcs1"
+ "-sha256WithRSAEncryption\"},\"parameters\":\"0500\"},\"issuer\":{\"_choi"
+ "ce\":\"rdnSequence\",\"value\":[[{\"_type\":\"AttributeTypeAndValue\",\"ty"
+ "pe\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.5.4.6\",\"components\":[2"
+ ",5,4,6],\"name\":\"id-at-countryName\"},\"value\":{\"_choice\":\"printabl"
+ "eString\",\"value\":\"CH\"}}],[{\"_type\":\"AttributeTypeAndValue\",\"type"
+ "\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.5.4.10\",\"components\":[2,"
+ "5,4,10],\"name\":\"id-at-organizationName\"},\"value\":{\"_choice\":\"pri"
+ "ntableString\",\"value\":\"STMicroelectronics NV\"}}],[{\"_type\":\"Attr"
+ "ibuteTypeAndValue\",\"type\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2."
+ "5.4.3\",\"components\":[2,5,4,3],\"name\":\"id-at-commonName\"},\"value\""
+ ":{\"_choice\":\"printableString\",\"value\":\"STM TPM EK Intermediate C"
+ "A 05\"}}]]},\"validity\":{\"_type\":\"Validity\",\"notBefore\":{\"_choice\""
+ ":\"utcTime\",\"value\":\"2018-12-14T00:00:00Z\"},\"notAfter\":{\"_choice\""
+ ":\"utcTime\",\"value\":\"2028-12-14T00:00:00Z\"}},\"subject\":{\"_choice\""
+ ":\"rdnSequence\",\"value\":[]},\"subjectPublicKeyInfo\":{\"_type\":\"Subj"
+ "ectPublicKeyInfo\",\"algorithm\":{\"_type\":\"AlgorithmIdentifier\",\"al"
+ "gorithm\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"1.2.840.113549.1.1."
+ "1\",\"components\":[1,2,840,113549,1,1,1],\"name\":\"id-pkcs1-rsaEncry"
+ "ption\"},\"parameters\":\"0500\"},\"subjectPublicKey\":\"2160:3082010A02"
+ "82010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E905B097012B5BDE50380C"
+ "355B1A2A721BBC3D08DD21796CDB239FA95310651B1B56FD2CFE53C87352EBD9"
+ "96E33256160404CE9302A08066801E786A2F86E181F949966F492A85B58EAA4A"
+ "6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E8F266BF1EA5EB271FDC"
+ "F374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A294973FEDCCF0C340AF"
+ "FD14B64F041165581ACA34147C1C75617047058F7ED7D603E032508094FA73E8"
+ "B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040FC1D2927C7657414490"
+ "D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A18AFE59F9D6F149744E5"
+ "F0D559B10203010001\"},\"issuerUniqueID\":null,\"subjectUniqueID\":nul"
+ "l,\"extensions\":[{\"_type\":\"Extension\",\"extnID\":{\"_type\":\"OBJECT I"
+ "DENTIFIER\",\"oid\":\"2.5.29.35\",\"components\":[2,5,29,35],\"name\":\"id"
+ "-x509-ce-authorityKeyIdentifier\"},\"critical\":false,\"extnValue\":\""
+ "301680141ADB994AB58BE57A0CC9B900E7851E1A43C08660\",\"_extnValue_ch"
+ "oice\":\"ext-AuthorityKeyIdentifier\",\"_extnValue\":{\"_type\":\"Author"
+ "ityKeyIdentifier\",\"keyIdentifier\":\"1ADB994AB58BE57A0CC9B900E7851"
+ "E1A43C08660\",\"authorityCertIssuer\":null,\"authorityCertSerialNumb"
+ "er\":null}},{\"_type\":\"Extension\",\"extnID\":{\"_type\":\"OBJECT IDENTI"
+ "FIER\",\"oid\":\"2.5.29.32\",\"components\":[2,5,29,32],\"name\":\"id-x509"
+ "-ce-certificatePolicies\"},\"critical\":false,\"extnValue\":\"30393037"
+ "0604551D2000302F302D06082B060105050702011621687474703A2F2F777777"
+ "2E73742E636F6D2F54504D2F7265706F7369746F72792F\",\"_extnValue_choi"
+ "ce\":\"ext-CertificatePolicies\",\"_extnValue\":[{\"_type\":\"PolicyInfo"
+ "rmation\",\"policyIdentifier\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\""
+ "2.5.29.32.0\",\"components\":[2,5,29,32,0],\"name\":\"id-x509-ce-certi"
+ "ficatePolicies-anyPolicy\"},\"policyQualifiers\":[{\"_type\":\"PolicyQ"
+ "ualifierInfo\",\"policyQualifierId\":{\"_type\":\"OBJECT IDENTIFIER\",\""
+ "oid\":\"1.3.6.1.5.5.7.2.1\",\"components\":[1,3,6,1,5,5,7,2,1],\"name\""
+ ":\"id-pkix-qt-cps\"},\"qualifier\":\"1621687474703A2F2F7777772E73742E"
+ "636F6D2F54504D2F7265706F7369746F72792F\",\"_qualifier_choice\":\"pq-"
+ "CPS\"}]}]},{\"_type\":\"Extension\",\"extnID\":{\"_type\":\"OBJECT IDENTIF"
+ "IER\",\"oid\":\"2.5.29.17\",\"components\":[2,5,29,17],\"name\":\"id-x509-"
+ "ce-subjectAltName\"},\"critical\":true,\"extnValue\":\"304DA44B3049311"
+ "63014060567810502010C0B69643A35333534344432303117301506056781050"
+ "2020C0C53543333485450484148433031163014060567810502030C0B69643A3"
+ "030343930303038\",\"_extnValue_choice\":\"ext-SubjectAltName\",\"_extn"
+ "Value\":[{\"_choice\":\"directoryName\",\"value\":{\"_choice\":\"rdnSequen"
+ "ce\",\"value\":[[{\"_type\":\"AttributeTypeAndValue\",\"type\":{\"_type\":\""
+ "OBJECT IDENTIFIER\",\"oid\":\"2.23.133.2.1\",\"components\":[2,23,133,2"
+ ",1],\"name\":\"tcg-at-tpmManufacturer\"},\"value\":{\"_choice\":\"utf8Str"
+ "ing\",\"value\":\"id:53544D20\"}}],[{\"_type\":\"AttributeTypeAndValue\","
+ "\"type\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.23.133.2.2\",\"compon"
+ "ents\":[2,23,133,2,2],\"name\":\"tcg-at-tpmModel\"},\"value\":{\"_choice"
+ "\":\"utf8String\",\"value\":\"ST33HTPHAHC0\"}}],[{\"_type\":\"AttributeTyp"
+ "eAndValue\",\"type\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.23.133.2"
+ ".3\",\"components\":[2,23,133,2,3],\"name\":\"tcg-at-tpmVersion\"},\"val"
+ "ue\":{\"_choice\":\"utf8String\",\"value\":\"id:00490008\"}}]]}}]},{\"_typ"
+ "e\":\"Extension\",\"extnID\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.5."
+ "29.9\",\"components\":[2,5,29,9],\"name\":\"id-x509-ce-subjectDirector"
+ "yAttributes\"},\"critical\":false,\"extnValue\":\"305E3017060567810502"
+ "10310E300C0C03322E300201000202008A304306056781050212313A30380201"
+ "000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A"
+ "01020101FFA40F300D16053134302D320A0102010100\",\"_extnValue_choice"
+ "\":\"ext-SubjectDirectoryAttributes\",\"_extnValue\":[{\"_type\":\"Attri"
+ "buteSet\",\"type\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.23.133.2.1"
+ "6\",\"components\":[2,23,133,2,16],\"name\":\"tcg-at-tpmSpecification\""
+ "},\"values\":[\"300C0C03322E300201000202008A\"],\"_values_choice\":\"at"
+ "-TPMSpecification\",\"_values\":[{\"_type\":\"TPMSpecification\",\"famil"
+ "y\":\"2.0\",\"level\":0,\"revision\":138}]},{\"_type\":\"AttributeSet\",\"ty"
+ "pe\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.23.133.2.18\",\"componen"
+ "ts\":[2,23,133,2,18],\"name\":\"tcg-at-tpmSecurityAssertions\"},\"valu"
+ "es\":[\"30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603"
+ "332E310A01040A01020101FFA40F300D16053134302D320A0102010100\"],\"_v"
+ "alues_choice\":\"at-TPMSecurityAssertions\",\"_values\":[{\"_type\":\"TP"
+ "MSecurityAssertions\",\"version\":0,\"fieldUpgradable\":true,\"ekGener"
+ "ationType\":\"ekgt-injected\",\"ekGenerationLocation\":\"tpmManufactur"
+ "er\",\"ekCertificateGenerationLocation\":\"tpmManufacturer\",\"ccInfo\""
+ ":{\"_type\":\"CommonCriteriaMeasures\",\"version\":\"3.1\",\"assurancelev"
+ "el\":\"ealevel4\",\"evaluationStatus\":\"evaluationCompleted\",\"plus\":t"
+ "rue,\"strengthOfFunction\":null,\"profileOid\":null,\"profileUri\":nul"
+ "l,\"targetOid\":null,\"targetUri\":null},\"fipsLevel\":{\"_type\":\"FIPSL"
+ "evel\",\"version\":\"140-2\",\"level\":\"sllevel2\",\"plus\":false},\"iso900"
+ "0Certified\":false,\"iso9000Uri\":null}]}]},{\"_type\":\"Extension\",\"e"
+ "xtnID\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.5.29.15\",\"component"
+ "s\":[2,5,29,15],\"name\":\"id-x509-ce-keyUsage\"},\"critical\":true,\"ex"
+ "tnValue\":\"03020520\",\"_extnValue_choice\":\"ext-KeyUsage\",\"_extnVal"
+ "ue\":[\"keyEncipherment\"]},{\"_type\":\"Extension\",\"extnID\":{\"_type\":"
+ "\"OBJECT IDENTIFIER\",\"oid\":\"2.5.29.19\",\"components\":[2,5,29,19],\""
+ "name\":\"id-x509-ce-basicConstraints\"},\"critical\":true,\"extnValue\""
+ ":\"3000\",\"_extnValue_choice\":\"ext-BasicConstraints\",\"_extnValue\":"
+ "{\"_type\":\"BasicConstraints\",\"cA\":false,\"pathLenConstraint\":null}"
+ "},{\"_type\":\"Extension\",\"extnID\":{\"_type\":\"OBJECT IDENTIFIER\",\"oi"
+ "d\":\"2.5.29.37\",\"components\":[2,5,29,37],\"name\":\"id-x509-ce-extKe"
+ "yUsage\"},\"critical\":false,\"extnValue\":\"300706056781050801\",\"_ext"
+ "nValue_choice\":\"ext-ExtKeyUsage\",\"_extnValue\":[{\"_type\":\"OBJECT "
+ "IDENTIFIER\",\"oid\":\"2.23.133.8.1\",\"components\":[2,23,133,8,1],\"na"
+ "me\":\"tcg-kp-EKCertificate\"}]},{\"_type\":\"Extension\",\"extnID\":{\"_t"
+ "ype\":\"OBJECT IDENTIFIER\",\"oid\":\"1.3.6.1.5.5.7.1.1\",\"components\":"
+ "[1,3,6,1,5,5,7,1,1],\"name\":\"id-pkix-pe-authorityInfoAccess\"},\"cr"
+ "itical\":false,\"extnValue\":\"303C303A06082B06010505073002862E68747"
+ "4703A2F2F7365637572652E676C6F62616C7369676E2E636F6D2F73746D74706"
+ "D656B696E7430352E637274\",\"_extnValue_choice\":\"ext-AuthorityInfoA"
+ "ccess\",\"_extnValue\":[{\"_type\":\"AccessDescription\",\"accessMethod\""
+ ":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"1.3.6.1.5.5.7.48.2\",\"compon"
+ "ents\":[1,3,6,1,5,5,7,48,2],\"name\":\"id-pkix-ad-caIssuers\"},\"acces"
+ "sLocation\":{\"_choice\":\"uniformResourceIdentifier\",\"value\":\"http:"
+ "//secure.globalsign.com/stmtpmekint05.crt\"}}]}]},\"signatureAlgor"
+ "ithm\":{\"_type\":\"AlgorithmIdentifier\",\"algorithm\":{\"_type\":\"OBJEC"
+ "T IDENTIFIER\",\"oid\":\"1.2.840.113549.1.1.11\",\"components\":[1,2,84"
+ "0,113549,1,1,11],\"name\":\"id-pkcs1-sha256WithRSAEncryption\"},\"par"
+ "ameters\":\"0500\"},\"signatureValue\":\"2048:3D4C381E5B4F1BCBE09C63D5"
+ "2F1F04570CAEA142FD9CD942043B11F8E3BDCF50007AE16CF8869013041E92CD"
+ "D3280BA4B51FBBD40582ED750219E261A695095674855AACEB520ADAFF9E7E90"
+ "8480A39CDCF900462D9171960FFE55D3AC49E8C981341BBD2EFBCC252A4C18A4"
+ "F3B7C84CCE42CE70A208C84D2630A7ABFBE72D6271E75B9FF1C971D20EB3DBD7"
+ "63F1E04D834EAA692D2E4001BBF4730A3E3FDA9711AE386524D91C63BE0E516D"
+ "00D5C6141FCCF6C539F3518E180049865BE16B69CAE1F8CB7FDC474B38F7EE56"
+ "CBE7D8A89D9BA99B65D5265AEF32AA62426B10E6D75BB8677EC44F755BBC2806"
+ "FD2B4E04BDF5D44259DBEAA42B6F563DF7AA7506\""
+ "}"
+ };
+ heim_octet_string os;
+ Certificate c0, c1;
+ size_t i, nknown, size;
+ char *s;
+ int ret;
+
+ /*
+ * Test automatic decoding of open types.
+ *
+ * Decode a value that has plenty of open types with values of known
+ * alternatives in them, then check that we got what we wanted.
+ */
+ ret = decode_Certificate(encoded_sample, sizeof(encoded_sample),
+ &c0, &size);
+ if (ret)
+ return 1;
+ if (size != sizeof(encoded_sample))
+ return 1;
+
+ s = print_Certificate(&c0, 0);
+ if (!s)
+ return 1;
+ if (strcmp(s, cert_json) != 0)
+ return 1;
+ free(s);
+
+ ret = copy_Certificate(&c0, &c1);
+ if (ret)
+ return 1;
+
+ if (!c0.tbsCertificate.extensions || !c1.tbsCertificate.extensions)
+ return 1;
+ if (!c0.tbsCertificate.extensions->len ||
+ c0.tbsCertificate.extensions->len != c1.tbsCertificate.extensions->len)
+ return 1;
+ for (i = nknown = 0; i < c0.tbsCertificate.extensions->len; i++) {
+ if (c0.tbsCertificate.extensions->val[i]._ioschoice_extnValue.element !=
+ c1.tbsCertificate.extensions->val[i]._ioschoice_extnValue.element)
+ return 1;
+ if (c0.tbsCertificate.extensions->val[i]._ioschoice_extnValue.element) {
+#if 0
+ fprintf(stderr, "extension %llu known %u\n",
+ (unsigned long long)i,
+ c0.tbsCertificate.extensions->val[i]._ioschoice_extnValue._element);
+#endif
+ nknown++;
+ }
+ }
+ if (!nknown)
+ return 1;
+
+
+ /*
+ * Check that this round trips. But note that this attempt to encode will
+ * ignore the automatically decoded open type values from above because
+ * their encodings are still present.
+ */
+ ASN1_MALLOC_ENCODE(Certificate, os.data, os.length, &c1, &size, ret);
+ if (ret)
+ return 1;
+ if (os.length != size || size != sizeof(encoded_sample))
+ return 1;
+ if (memcmp(os.data, encoded_sample, os.length) != 0)
+ return 1;
+ der_free_octet_string(&os);
+
+ /*
+ * Test automatic encoding of open types by clearing the encoding of one
+ * such open type value, forcing the encoder to encode the value from
+ * before.
+ */
+ der_free_octet_string(&c0.tbsCertificate.extensions->val[0].extnValue);
+ der_free_oid(&c0.tbsCertificate.extensions->val[0].extnID);
+
+ ASN1_MALLOC_ENCODE(Certificate, os.data, os.length, &c0, &size, ret);
+ if (ret)
+ return 1;
+ if (os.length != size || size != sizeof(encoded_sample))
+ return 1;
+ if (memcmp(os.data, encoded_sample, os.length) != 0)
+ return 1;
+ der_free_octet_string(&os);
+
+ /*
+ * Repeat, but with the copy, as this will test that copying data
+ * structures with decoded open types in them also copies those.
+ */
+ der_free_octet_string(&c1.tbsCertificate.extensions->val[0].extnValue);
+ der_free_oid(&c1.tbsCertificate.extensions->val[0].extnID);
+
+ ASN1_MALLOC_ENCODE(Certificate, os.data, os.length, &c1, &size, ret);
+ if (ret)
+ return 1;
+ if (os.length != size || size != sizeof(encoded_sample))
+ return 1;
+ if (memcmp(os.data, encoded_sample, os.length) != 0)
+ return 1;
+ der_free_octet_string(&os);
+
+ free_Certificate(&c0);
+ free_Certificate(&c1);
+ return 0;
+}
+#endif
+
+int
+main(int argc, char **argv)
+{
+ int ret = 0;
+
+#define DO_ONE(t) if (t()) { fprintf(stderr, "%s() failed!\n", #t); ret++; }
+ DO_ONE(test_principal);
+ DO_ONE(test_authenticator);
+ DO_ONE(test_krb_error);
+ DO_ONE(test_Name);
+ DO_ONE(test_bit_string);
+ DO_ONE(test_bit_string_rfc1510);
+ DO_ONE(test_time);
+ DO_ONE(test_cert);
+
+ DO_ONE(check_tag_length);
+ DO_ONE(check_tag_length64);
+ DO_ONE(check_tag_length64s);
+ DO_ONE(test_large_tag);
+ DO_ONE(test_choice);
+
+ DO_ONE(test_implicit);
+
+ DO_ONE(test_taglessalloc);
+ DO_ONE(test_optional);
+
+ DO_ONE(check_fail_largetag);
+ DO_ONE(check_fail_sequence);
+ DO_ONE(check_fail_choice);
+ DO_ONE(check_fail_Ticket);
+
+ DO_ONE(check_seq);
+ DO_ONE(check_seq_of_size);
+ DO_ONE(test_SignedData);
+
+ DO_ONE(check_TESTMechTypeList);
+ DO_ONE(test_seq4);
+ DO_ONE(test_seqof5);
+
+ DO_ONE(test_x690sample);
+
+ DO_ONE(test_default);
+
+ DO_ONE(test_extensible_choice);
+
+ DO_ONE(test_decorated_choice);
+ DO_ONE(test_decorated);
+
+#if ASN1_IOS_SUPPORTED
+ DO_ONE(test_ios);
+#endif
+
+ return ret;
+}
diff --git a/third_party/heimdal/lib/asn1/check-gen.h b/third_party/heimdal/lib/asn1/check-gen.h
new file mode 100644
index 0000000..df8c474
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/check-gen.h
@@ -0,0 +1,9 @@
+#ifndef _CHECK_GEN_H
+#define _CHECK_GEN_H
+typedef struct my_vers_s {
+ int v;
+} my_vers;
+
+int my_copy_vers(const my_vers *, my_vers *);
+void my_free_vers(my_vers *);
+#endif /* _CHECK_GEN_H */
diff --git a/third_party/heimdal/lib/asn1/check-template.c b/third_party/heimdal/lib/asn1/check-template.c
new file mode 100644
index 0000000..ef5bd69
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/check-template.c
@@ -0,0 +1,532 @@
+/*
+ * Copyright (c) 1999 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <roken.h>
+
+#include <asn1-common.h>
+#include <asn1_err.h>
+#include <der.h>
+#include <test_asn1.h>
+
+#include "check-common.h"
+#include "der_locl.h"
+
+int
+my_copy_vers(const my_vers *from, my_vers *to)
+{
+ *to = *from;
+ return 0;
+}
+
+void
+my_free_vers(my_vers *v)
+{
+ v->v = -1;
+}
+
+static int
+cmp_dummy (void *a, void *b)
+{
+ return 0;
+}
+
+static int
+test_uint64(void)
+{
+ struct test_case tests[] = {
+ { NULL, 3, "\x02\x01\x00", "uint64 0" },
+ { NULL, 7, "\x02\x05\x01\xff\xff\xff\xff", "uint64 1" },
+ { NULL, 7, "\x02\x05\x02\x00\x00\x00\x00", "uint64 2" },
+ { NULL, 9, "\x02\x07\x7f\xff\xff\xff\xff\xff\xff", "uint64 3" },
+ { NULL, 10, "\x02\x08\x00\x80\x00\x00\x00\x00\x00\x00", "uint64 4" },
+ { NULL, 10, "\x02\x08\x7f\xff\xff\xff\xff\xff\xff\xff", "uint64 5" },
+ { NULL, 11, "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", "uint64 6" }
+ };
+
+ size_t i;
+ int ret = 0, ntests = sizeof(tests) / sizeof(*tests);
+ TESTuint64 values[] = { 0, 8589934591LL, 8589934592LL,
+ 36028797018963967LL, 36028797018963968LL,
+ 9223372036854775807LL, 18446744073709551615ULL };
+
+ for (i = 0; i < ntests; i++)
+ tests[i].val = &values[i];
+
+ if (sizeof(TESTuint64) != sizeof(uint64_t)) {
+ ret += 1;
+ printf("sizeof(TESTuint64) %d != sizeof(uint64_t) %d\n",
+ (int)sizeof(TESTuint64), (int)sizeof(uint64_t));
+ }
+
+ ret += generic_test (tests, ntests, sizeof(TESTuint64),
+ (generic_encode)encode_TESTuint64,
+ (generic_length)length_TESTuint64,
+ (generic_decode)decode_TESTuint64,
+ (generic_free)free_TESTuint64,
+ cmp_dummy,
+ NULL);
+ return ret;
+}
+
+static int
+test_seqofseq(void)
+{
+ struct test_case tests[] = {
+ { NULL, 2,
+ "\x30\x00",
+ "seqofseq 0" },
+ { NULL, 9,
+ "\x30\x07\x30\x05\xa0\x03\x02\x01\x00",
+ "seqofseq 1" },
+ { NULL, 16,
+ "\x30\x0e\x30\x05\xa0\x03\x02\x01\x00\x30\x05\xa0\x03\x02\x01\x01",
+ "seqofseq 2" }
+ };
+
+ int ret = 0, ntests = sizeof(tests) / sizeof(*tests);
+ TESTSeqOfSeq c0, c1, c2;
+ struct TESTSeqOfSeq_val i[2];
+
+ i[0].zero = 0;
+ i[1].zero = 1;
+
+ c0.len = 0;
+ c0.val = NULL;
+ tests[0].val = &c0;
+
+ c1.len = 1;
+ c1.val = i;
+ tests[1].val = &c1;
+
+ c2.len = 2;
+ c2.val = i;
+ tests[2].val = &c2;
+
+ ret += generic_test (tests, ntests, sizeof(TESTSeqOfSeq),
+ (generic_encode)encode_TESTSeqOfSeq,
+ (generic_length)length_TESTSeqOfSeq,
+ (generic_decode)decode_TESTSeqOfSeq,
+ (generic_free)free_TESTSeqOfSeq,
+ cmp_dummy,
+ NULL);
+ return ret;
+}
+
+static int
+test_seqofseq2(void)
+{
+ struct test_case tests[] = {
+ { NULL, 2,
+ "\x30\x00",
+ "seqofseq2 0" },
+ { NULL, 11,
+ "\x30\x09\x30\x07\xa0\x05\x1b\x03\x65\x74\x74",
+ "seqofseq2 1" },
+ { NULL, 21,
+ "\x30\x13\x30\x07\xa0\x05\x1b\x03\x65\x74\x74\x30\x08\xa0"
+ "\x06\x1b\x04\x74\x76\x61\x61",
+ "seqofseq2 2" }
+ };
+
+ int ret = 0, ntests = sizeof(tests) / sizeof(*tests);
+ TESTSeqOfSeq2 c0, c1, c2;
+ struct TESTSeqOfSeq2_val i[2];
+
+ i[0].string = "ett";
+ i[1].string = "tvaa";
+
+ c0.len = 0;
+ c0.val = NULL;
+ tests[0].val = &c0;
+
+ c1.len = 1;
+ c1.val = i;
+ tests[1].val = &c1;
+
+ c2.len = 2;
+ c2.val = i;
+ tests[2].val = &c2;
+
+ ret += generic_test (tests, ntests, sizeof(TESTSeqOfSeq2),
+ (generic_encode)encode_TESTSeqOfSeq2,
+ (generic_length)length_TESTSeqOfSeq2,
+ (generic_decode)decode_TESTSeqOfSeq2,
+ (generic_free)free_TESTSeqOfSeq2,
+ cmp_dummy,
+ NULL);
+ return ret;
+}
+
+static int
+test_seqof2(void)
+{
+ struct test_case tests[] = {
+ { NULL, 4,
+ "\x30\x02\x30\x00",
+ "seqof2 1" },
+ { NULL, 9,
+ "\x30\x07\x30\x05\x1b\x03\x66\x6f\x6f",
+ "seqof2 2" },
+ { NULL, 14,
+ "\x30\x0c\x30\x0a\x1b\x03\x66\x6f\x6f\x1b\x03\x62\x61\x72",
+ "seqof2 3" }
+ };
+
+ int ret = 0, ntests = sizeof(tests) / sizeof(*tests);
+ TESTSeqOf2 c0, c1, c2;
+ heim_general_string i[2];
+
+ i[0] = "foo";
+ i[1] = "bar";
+
+ c0.strings.val = NULL;
+ c0.strings.len = 0;
+ tests[0].val = &c0;
+
+ c1.strings.len = 1;
+ c1.strings.val = i;
+ tests[1].val = &c1;
+
+ c2.strings.len = 2;
+ c2.strings.val = i;
+ tests[2].val = &c2;
+
+ ret += generic_test (tests, ntests, sizeof(TESTSeqOf2),
+ (generic_encode)encode_TESTSeqOf2,
+ (generic_length)length_TESTSeqOf2,
+ (generic_decode)decode_TESTSeqOf2,
+ (generic_free)free_TESTSeqOf2,
+ cmp_dummy,
+ NULL);
+ return ret;
+}
+
+static int
+test_seqof3(void)
+{
+ struct test_case tests[] = {
+ { NULL, 2,
+ "\x30\x00",
+ "seqof3 0" },
+ { NULL, 4,
+ "\x30\x02\x30\x00",
+ "seqof3 1" },
+ { NULL, 9,
+ "\x30\x07\x30\x05\x1b\x03\x66\x6f\x6f",
+ "seqof3 2" },
+ { NULL, 14,
+ "\x30\x0c\x30\x0a\x1b\x03\x66\x6f\x6f\x1b\x03\x62\x61\x72",
+ "seqof3 3" }
+ };
+
+ int ret = 0, ntests = sizeof(tests) / sizeof(*tests);
+ TESTSeqOf3 c0, c1, c2, c3;
+ struct TESTSeqOf3_strings s1, s2, s3;
+ heim_general_string i[2];
+
+ i[0] = "foo";
+ i[1] = "bar";
+
+ c0.strings = NULL;
+ tests[0].val = &c0;
+
+ s1.val = NULL;
+ s1.len = 0;
+ c1.strings = &s1;
+ tests[1].val = &c1;
+
+ s2.len = 1;
+ s2.val = i;
+ c2.strings = &s2;
+ tests[2].val = &c2;
+
+ s3.len = 2;
+ s3.val = i;
+ c3.strings = &s3;
+ tests[3].val = &c3;
+
+ ret += generic_test (tests, ntests, sizeof(TESTSeqOf3),
+ (generic_encode)encode_TESTSeqOf3,
+ (generic_length)length_TESTSeqOf3,
+ (generic_decode)decode_TESTSeqOf3,
+ (generic_free)free_TESTSeqOf3,
+ cmp_dummy,
+ NULL);
+ return ret;
+}
+
+
+static int
+test_seqof4(void)
+{
+ struct test_case tests[] = {
+ { NULL, 2,
+ "\x30\x00",
+ "seq4 0" },
+ { NULL, 4,
+ "\x30\x02" "\xa1\x00",
+ "seq4 1" },
+ { NULL, 8,
+ "\x30\x06" "\xa0\x02\x30\x00" "\xa1\x00",
+ "seq4 2" },
+ { NULL, 2 + (2 + 0x18) + (2 + 0x27) + (2 + 0x31),
+ "\x30\x76" /* 2 SEQ */
+ "\xa0\x18\x30\x16" /* 4 [0] SEQ */
+ "\x30\x14" /* 2 SEQ */
+ "\x04\x00" /* 2 OCTET-STRING */
+ "\x04\x02\x01\x02" /* 4 OCTET-STRING */
+ "\x02\x01\x01" /* 3 INT */
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff"
+ /* 11 INT */
+ "\xa1\x27" /* 2 [1] IMPL SEQ */
+ "\x30\x25" /* 2 SEQ */
+ "\x02\x01\x01" /* 3 INT */
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff"
+ /* 11 INT */
+ "\x02\x09\x00\x80\x00\x00\x00\x00\x00\x00\x00"
+ /* 11 INT */
+ "\x04\x00" /* 2 OCTET-STRING */
+ "\x04\x02\x01\x02" /* 4 OCTET-STRING */
+ "\x04\x04\x00\x01\x02\x03" /* 6 OCTET-STRING */
+ "\xa2\x31" /* 2 [2] IMPL SEQ */
+ "\x30\x2f" /* 2 SEQ */
+ "\x04\x00" /* 2 OCTET-STRING */
+ "\x02\x01\x01" /* 3 INT */
+ "\x04\x02\x01\x02" /* 4 OCTET-STRING */
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff"
+ /* 11 INT */
+ "\x04\x04\x00\x01\x02\x03" /* 6 OCTET-STRING */
+ "\x02\x09\x00\x80\x00\x00\x00\x00\x00\x00\x00"
+ /* 11 INT */
+ "\x04\x01\x00" /* 3 OCTET-STRING */
+ "\x02\x05\x01\x00\x00\x00\x00", /* 7 INT */
+ "seq4 3" },
+ };
+
+ int ret = 0, ntests = sizeof(tests) / sizeof(*tests);
+ TESTSeqOf4 c[4];
+ struct TESTSeqOf4_b1 b1[4];
+ struct TESTSeqOf4_b2 b2[4];
+ struct TESTSeqOf4_b3 b3[4];
+ struct TESTSeqOf4_b1_val b1val[4];
+ struct TESTSeqOf4_b2_val b2val[4];
+ struct TESTSeqOf4_b3_val b3val[4];
+
+ c[0].b1 = NULL;
+ c[0].b2 = NULL;
+ c[0].b3 = NULL;
+ tests[0].val = &c[0];
+
+ b2[1].len = 0;
+ b2[1].val = NULL;
+ c[1].b1 = NULL;
+ c[1].b2 = &b2[1];
+ c[1].b3 = NULL;
+ tests[1].val = &c[1];
+
+ b1[2].len = 0;
+ b1[2].val = NULL;
+ b2[2].len = 0;
+ b2[2].val = NULL;
+ c[2].b1 = &b1[2];
+ c[2].b2 = &b2[2];
+ c[2].b3 = NULL;
+ tests[2].val = &c[2];
+
+ b1val[3].s1.data = "";
+ b1val[3].s1.length = 0;
+ b1val[3].u1 = 1LL;
+ b1val[3].s2.data = "\x01\x02";
+ b1val[3].s2.length = 2;
+ b1val[3].u2 = (TESTuint64)-1LL;
+
+ b2val[3].s1.data = "";
+ b2val[3].s1.length = 0;
+ b2val[3].u1 = 1LL;
+ b2val[3].s2.data = "\x01\x02";
+ b2val[3].s2.length = 2;
+ b2val[3].u2 = (TESTuint64)-1LL;
+ b2val[3].s3.data = "\x00\x01\x02\x03";
+ b2val[3].s3.length = 4;
+ b2val[3].u3 = 1ULL<<63;
+
+ b3val[3].s1.data = "";
+ b3val[3].s1.length = 0;
+ b3val[3].u1 = 1LL;
+ b3val[3].s2.data = "\x01\x02";
+ b3val[3].s2.length = 2;
+ b3val[3].u2 = (TESTuint64)-1LL;
+ b3val[3].s3.data = "\x00\x01\x02\x03";
+ b3val[3].s3.length = 4;
+ b3val[3].u3 = 1ULL<<63;
+ b3val[3].s4.data = "\x00";
+ b3val[3].s4.length = 1;
+ b3val[3].u4 = 1LL<<32;
+
+ b1[3].len = 1;
+ b1[3].val = &b1val[3];
+ b2[3].len = 1;
+ b2[3].val = &b2val[3];
+ b3[3].len = 1;
+ b3[3].val = &b3val[3];
+ c[3].b1 = &b1[3];
+ c[3].b2 = &b2[3];
+ c[3].b3 = &b3[3];
+ tests[3].val = &c[3];
+
+ ret += generic_test (tests, ntests, sizeof(TESTSeqOf4),
+ (generic_encode)encode_TESTSeqOf4,
+ (generic_length)length_TESTSeqOf4,
+ (generic_decode)decode_TESTSeqOf4,
+ (generic_free)free_TESTSeqOf4,
+ cmp_dummy,
+ NULL);
+ return ret;
+}
+
+static int
+cmp_test_seqof5 (void *a, void *b)
+{
+ TESTSeqOf5 *aval = a;
+ TESTSeqOf5 *bval = b;
+
+ IF_OPT_COMPARE(aval, bval, outer) {
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u0);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s0);
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u1);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s1);
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u2);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s2);
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u3);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s3);
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u4);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s4);
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u5);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s5);
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u6);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s6);
+ COMPARE_INTEGER(&aval->outer->inner, &bval->outer->inner, u7);
+ COMPARE_OCTET_STRING(&aval->outer->inner, &bval->outer->inner, s7);
+ }
+ return 0;
+}
+
+static int
+test_seqof5(void)
+{
+ struct test_case tests[] = {
+ { NULL, 2, "\x30\x00", "seq5 0" },
+ { NULL, 126,
+ "\x30\x7c" /* SEQ */
+ "\x30\x7a" /* SEQ */
+ "\x30\x78" /* SEQ */
+ "\x02\x01\x01" /* INT 1 */
+ "\x04\x06\x01\x01\x01\x01\x01\x01" /* "\0x1"x6 */
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xfe" /* INT ~1 */
+ "\x04\x06\x02\x02\x02\x02\x02\x02" /* "\x02"x6 */
+ "\x02\x01\x02" /* INT 2 */
+ "\x04\x06\x03\x03\x03\x03\x03\x03" /* "\x03"x6 */
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xfd" /* INT ~2 */
+ "\x04\x06\x04\x04\x04\x04\x04\x04" /* ... */
+ "\x02\x01\x03"
+ "\x04\x06\x05\x05\x05\x05\x05\x05"
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xfc"
+ "\x04\x06\x06\x06\x06\x06\x06\x06"
+ "\x02\x01\x04"
+ "\x04\x06\x07\x07\x07\x07\x07\x07"
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xfb"
+ "\x04\x06\x08\x08\x08\x08\x08\x08",
+ "seq5 1" },
+ };
+
+ int ret = 0, ntests = sizeof(tests) / sizeof(*tests);
+ TESTSeqOf5 c[2];
+ struct TESTSeqOf5_outer outer;
+ struct TESTSeqOf5_outer_inner inner;
+ TESTuint64 u[8];
+ heim_octet_string s[8];
+ int i;
+
+ c[0].outer = NULL;
+ tests[0].val = &c[0];
+
+ for (i = 0; i < 8; ++i) {
+ u[i] = (i&1) == 0 ? i/2+1 : ~(i/2+1);
+ s[i].data = memset(malloc(s[i].length = 6), i+1, 6);
+ }
+
+ inner.u0 = u[0]; inner.u1 = u[1]; inner.u2 = u[2]; inner.u3 = u[3];
+ inner.u4 = u[4]; inner.u5 = u[5]; inner.u6 = u[6]; inner.u7 = u[7];
+ inner.s0 = s[0]; inner.s1 = s[1]; inner.s2 = s[2]; inner.s3 = s[3];
+ inner.s4 = s[4]; inner.s5 = s[5]; inner.s6 = s[6]; inner.s7 = s[7];
+
+ outer.inner = inner;
+ c[1].outer = &outer;
+ tests[1].val = &c[1];
+
+ ret += generic_test (tests, ntests, sizeof(TESTSeqOf5),
+ (generic_encode)encode_TESTSeqOf5,
+ (generic_length)length_TESTSeqOf5,
+ (generic_decode)decode_TESTSeqOf5,
+ (generic_free)free_TESTSeqOf5,
+ cmp_test_seqof5,
+ NULL);
+
+ for (i = 0; i < 8; ++i)
+ free(s[i].data);
+
+ return ret;
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret = 0;
+
+ ret += test_uint64();
+ ret += test_seqofseq();
+ ret += test_seqofseq2();
+ ret += test_seqof2();
+ ret += test_seqof3();
+ ret += test_seqof4();
+ ret += test_seqof5();
+
+ return ret;
+}
diff --git a/third_party/heimdal/lib/asn1/check-timegm.c b/third_party/heimdal/lib/asn1/check-timegm.c
new file mode 100644
index 0000000..13d3abc
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/check-timegm.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <der_locl.h>
+
+RCSID("$Id$");
+
+static int
+test_timegm(void)
+{
+ int ret = 0;
+ struct tm tm;
+ time_t t;
+
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_year = 106;
+ tm.tm_mon = 9;
+ tm.tm_mday = 1;
+ tm.tm_hour = 10;
+ tm.tm_min = 3;
+
+ t = _der_timegm(&tm);
+ if (t != 1159696980)
+ ret += 1;
+
+ tm.tm_mday = 0;
+ t = _der_timegm(&tm);
+ if (t != -1)
+ ret += 1;
+
+ _der_gmtime(1159696980, &tm);
+ if (tm.tm_year != 106 ||
+ tm.tm_mon != 9 ||
+ tm.tm_mday != 1 ||
+ tm.tm_hour != 10 ||
+ tm.tm_min != 3 ||
+ tm.tm_sec != 0)
+ errx(1, "tmtime failes");
+
+ return ret;
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret = 0;
+
+ ret += test_timegm();
+
+ return ret;
+}
diff --git a/third_party/heimdal/lib/asn1/cms.asn1 b/third_party/heimdal/lib/asn1/cms.asn1
new file mode 100644
index 0000000..ae547e5
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/cms.asn1
@@ -0,0 +1,149 @@
+-- From RFC 3369 --
+-- $Id$ --
+
+CMS DEFINITIONS ::= BEGIN
+
+IMPORTS CertificateSerialNumber, AlgorithmIdentifier, Name,
+ Attribute, Certificate, SubjectKeyIdentifier FROM rfc2459
+ HEIM_ANY FROM heim;
+
+id-pkcs7 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ us(840) rsadsi(113549) pkcs(1) pkcs7(7) }
+
+id-pkcs7-data OBJECT IDENTIFIER ::= { id-pkcs7 1 }
+id-pkcs7-signedData OBJECT IDENTIFIER ::= { id-pkcs7 2 }
+id-pkcs7-envelopedData OBJECT IDENTIFIER ::= { id-pkcs7 3 }
+id-pkcs7-signedAndEnvelopedData OBJECT IDENTIFIER ::= { id-pkcs7 4 }
+id-pkcs7-digestedData OBJECT IDENTIFIER ::= { id-pkcs7 5 }
+id-pkcs7-encryptedData OBJECT IDENTIFIER ::= { id-pkcs7 6 }
+
+CMSVersion ::= INTEGER {
+ cMSVersion-v0(0),
+ cMSVersion-v1(1),
+ cMSVersion-v2(2),
+ cMSVersion-v3(3),
+ cMSVersion-v4(4)
+}
+
+DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
+SignatureAlgorithmIdentifier ::= AlgorithmIdentifier
+
+ContentType ::= OBJECT IDENTIFIER
+MessageDigest ::= OCTET STRING
+
+ContentInfo ::= SEQUENCE {
+ contentType ContentType,
+ content [0] EXPLICIT HEIM_ANY OPTIONAL -- DEFINED BY contentType
+}
+
+EncapsulatedContentInfo ::= SEQUENCE {
+ eContentType ContentType,
+ eContent [0] EXPLICIT OCTET STRING OPTIONAL
+}
+
+CertificateSet ::= SET OF HEIM_ANY
+
+CertificateList ::= Certificate
+
+CertificateRevocationLists ::= SET OF CertificateList
+
+IssuerAndSerialNumber ::= SEQUENCE {
+ issuer Name,
+ serialNumber CertificateSerialNumber
+}
+
+-- RecipientIdentifier is same as SignerIdentifier,
+-- lets glue them togheter and save some bytes and share code for them
+
+CMSIdentifier ::= CHOICE {
+ issuerAndSerialNumber IssuerAndSerialNumber,
+ subjectKeyIdentifier [0] SubjectKeyIdentifier
+}
+
+SignerIdentifier ::= CMSIdentifier
+RecipientIdentifier ::= CMSIdentifier
+
+--- CMSAttributes are the combined UnsignedAttributes and SignedAttributes
+--- to store space and share code
+
+CMSAttributes ::= SET OF Attribute -- SIZE (1..MAX)
+
+SignatureValue ::= OCTET STRING
+
+SignerInfo ::= SEQUENCE {
+ version CMSVersion,
+ sid SignerIdentifier,
+ digestAlgorithm DigestAlgorithmIdentifier,
+ signedAttrs [0] IMPLICIT CMSAttributes OPTIONAL,
+ signatureAlgorithm SignatureAlgorithmIdentifier,
+ signature SignatureValue,
+ unsignedAttrs [1] IMPLICIT CMSAttributes OPTIONAL
+}
+
+SignerInfos ::= SET OF SignerInfo
+
+SignedData ::= SEQUENCE {
+ version CMSVersion,
+ digestAlgorithms DigestAlgorithmIdentifiers,
+ encapContentInfo EncapsulatedContentInfo,
+ certificates [0] IMPLICIT CertificateSet OPTIONAL,
+ crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ signerInfos SignerInfos
+}
+
+OriginatorInfo ::= SEQUENCE {
+ certs [0] IMPLICIT CertificateSet OPTIONAL,
+ crls [1] IMPLICIT CertificateRevocationLists OPTIONAL
+}
+
+KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+
+EncryptedKey ::= OCTET STRING
+
+KeyTransRecipientInfo ::= SEQUENCE {
+ version CMSVersion, -- always set to 0 or 2
+ rid RecipientIdentifier,
+ keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ encryptedKey EncryptedKey
+}
+
+RecipientInfo ::= KeyTransRecipientInfo
+
+RecipientInfos ::= SET OF RecipientInfo
+
+EncryptedContent ::= OCTET STRING
+
+EncryptedContentInfo ::= SEQUENCE {
+ contentType ContentType,
+ contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+ encryptedContent [0] IMPLICIT OCTET STRING OPTIONAL
+}
+
+UnprotectedAttributes ::= SET OF Attribute -- SIZE (1..MAX)
+
+CMSEncryptedData ::= SEQUENCE {
+ version CMSVersion,
+ encryptedContentInfo EncryptedContentInfo,
+ unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+}
+
+EnvelopedData ::= SEQUENCE {
+ version CMSVersion,
+ originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ recipientInfos RecipientInfos,
+ encryptedContentInfo EncryptedContentInfo,
+ unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+}
+
+-- Data ::= OCTET STRING
+
+CMSRC2CBCParameter ::= SEQUENCE {
+ rc2ParameterVersion INTEGER (0..4294967295),
+ iv OCTET STRING -- exactly 8 octets
+}
+
+CMSCBCParameter ::= OCTET STRING
+
+END
diff --git a/third_party/heimdal/lib/asn1/cms.opt b/third_party/heimdal/lib/asn1/cms.opt
new file mode 100644
index 0000000..49333e5
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/cms.opt
@@ -0,0 +1,2 @@
+--decode-dce-ber
+--sequence=DigestAlgorithmIdentifiers
diff --git a/third_party/heimdal/lib/asn1/crmf.asn1 b/third_party/heimdal/lib/asn1/crmf.asn1
new file mode 100644
index 0000000..696a89b
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/crmf.asn1
@@ -0,0 +1,110 @@
+-- $Id$
+PKCS10 DEFINITIONS ::=
+
+BEGIN
+
+IMPORTS
+ Time,
+ GeneralName,
+ SubjectPublicKeyInfo,
+ RelativeDistinguishedName,
+ AttributeTypeAndValue,
+ Extension,
+ AlgorithmIdentifier
+ FROM rfc2459
+ HEIM_ANY
+ FROM heim;
+
+CRMFRDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+
+Controls ::= SEQUENCE -- SIZE(1..MAX) -- OF AttributeTypeAndValue
+
+PKMACValue ::= SEQUENCE {
+ algId AlgorithmIdentifier,
+ value BIT STRING
+}
+
+-- XXX IMPLICIT brokenness
+POPOSigningKeyInput ::= SEQUENCE {
+ authInfo CHOICE {
+ sender [0] IMPLICIT GeneralName,
+ publicKeyMAC PKMACValue
+ },
+ publicKey SubjectPublicKeyInfo
+} -- from CertTemplate
+
+-- XXX IMPLICIT brokenness
+POPOSigningKey ::= SEQUENCE {
+ poposkInput [0] IMPLICIT POPOSigningKeyInput OPTIONAL,
+ algorithmIdentifier AlgorithmIdentifier,
+ signature BIT STRING }
+
+PBMParameter ::= SEQUENCE {
+ salt OCTET STRING,
+ owf AlgorithmIdentifier,
+ iterationCount INTEGER,
+ mac AlgorithmIdentifier
+}
+
+SubsequentMessage ::= INTEGER {
+ encrCert (0),
+ challengeResp (1)
+}
+
+POPOPrivKey ::= CHOICE {
+ thisMessage [0] BIT STRING, -- Deprecated
+ subsequentMessage [1] IMPLICIT SubsequentMessage,
+ dhMAC [2] BIT STRING, -- Deprecated
+ agreeMAC [3] IMPLICIT PKMACValue,
+ encryptedKey [4] HEIM_ANY
+}
+
+ProofOfPossession ::= CHOICE {
+ raVerified [0] NULL,
+ signature [1] POPOSigningKey,
+ keyEncipherment [2] POPOPrivKey,
+ keyAgreement [3] POPOPrivKey
+}
+
+CertTemplate ::= SEQUENCE {
+ version [0] INTEGER OPTIONAL,
+ serialNumber [1] INTEGER OPTIONAL,
+ signingAlg [2] SEQUENCE {
+ algorithm OBJECT IDENTIFIER,
+ parameters HEIM_ANY OPTIONAL
+ } -- AlgorithmIdentifier -- OPTIONAL,
+ issuer [3] IMPLICIT CHOICE {
+ rdnSequence CRMFRDNSequence
+ } -- Name -- OPTIONAL,
+ validity [4] SEQUENCE {
+ notBefore [0] Time OPTIONAL,
+ notAfter [1] Time OPTIONAL
+ } -- OptionalValidity -- OPTIONAL,
+ subject [5] IMPLICIT CHOICE {
+ rdnSequence CRMFRDNSequence
+ } -- Name -- OPTIONAL,
+ publicKey [6] IMPLICIT SEQUENCE {
+ algorithm AlgorithmIdentifier,
+ subjectPublicKey BIT STRING OPTIONAL
+ } -- SubjectPublicKeyInfo -- OPTIONAL,
+ issuerUID [7] IMPLICIT BIT STRING OPTIONAL,
+ subjectUID [8] IMPLICIT BIT STRING OPTIONAL,
+ extensions [9] IMPLICIT SEQUENCE OF Extension OPTIONAL
+}
+
+CertRequest ::= SEQUENCE {
+ certReqId INTEGER,
+ certTemplate CertTemplate,
+ controls Controls OPTIONAL
+}
+
+CertReqMsg ::= SEQUENCE {
+ certReq CertRequest,
+ popo ProofOfPossession OPTIONAL,
+ regInfo SEQUENCE OF AttributeTypeAndValue OPTIONAL }
+
+CertReqMessages ::= SEQUENCE OF CertReqMsg
+
+
+END
+
diff --git a/third_party/heimdal/lib/asn1/crmf.opt b/third_party/heimdal/lib/asn1/crmf.opt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/crmf.opt
diff --git a/third_party/heimdal/lib/asn1/der.c b/third_party/heimdal/lib/asn1/der.c
new file mode 100644
index 0000000..bea4ae5
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/der.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+#include <com_err.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <getarg.h>
+#include <err.h>
+
+RCSID("$Id$");
+
+
+static const char *class_names[] = {
+ "UNIV", /* 0 */
+ "APPL", /* 1 */
+ "CONTEXT", /* 2 */
+ "PRIVATE" /* 3 */
+};
+
+static const char *type_names[] = {
+ "PRIM", /* 0 */
+ "CONS" /* 1 */
+};
+
+static const char *tag_names[] = {
+ "EndOfContent", /* 0 */
+ "Boolean", /* 1 */
+ "Integer", /* 2 */
+ "BitString", /* 3 */
+ "OctetString", /* 4 */
+ "Null", /* 5 */
+ "ObjectID", /* 6 */
+ NULL, /* 7 */
+ NULL, /* 8 */
+ NULL, /* 9 */
+ "Enumerated", /* 10 */
+ NULL, /* 11 */
+ "UTF8String", /* 12 */
+ NULL, /* 13 */
+ NULL, /* 14 */
+ NULL, /* 15 */
+ "Sequence", /* 16 */
+ "Set", /* 17 */
+ NULL, /* 18 */
+ "PrintableString", /* 19 */
+ NULL, /* 20 */
+ NULL, /* 21 */
+ "IA5String", /* 22 */
+ "UTCTime", /* 23 */
+ "GeneralizedTime", /* 24 */
+ NULL, /* 25 */
+ "VisibleString", /* 26 */
+ "GeneralString", /* 27 */
+ NULL, /* 28 */
+ NULL, /* 29 */
+ "BMPString" /* 30 */
+};
+
+static int
+get_type(const char *name, const char *list[], unsigned len)
+{
+ unsigned i;
+ for (i = 0; i < len; i++)
+ if (list[i] && strcasecmp(list[i], name) == 0)
+ return i;
+ return -1;
+}
+
+#define SIZEOF_ARRAY(a) (sizeof((a))/sizeof((a)[0]))
+
+const char * ASN1CALL
+der_get_class_name(unsigned num)
+{
+ if (num >= SIZEOF_ARRAY(class_names))
+ return NULL;
+ return class_names[num];
+}
+
+int ASN1CALL
+der_get_class_num(const char *name)
+{
+ return get_type(name, class_names, SIZEOF_ARRAY(class_names));
+}
+
+const char * ASN1CALL
+der_get_type_name(unsigned num)
+{
+ if (num >= SIZEOF_ARRAY(type_names))
+ return NULL;
+ return type_names[num];
+}
+
+int ASN1CALL
+der_get_type_num(const char *name)
+{
+ return get_type(name, type_names, SIZEOF_ARRAY(type_names));
+}
+
+const char * ASN1CALL
+der_get_tag_name(unsigned num)
+{
+ if (num >= SIZEOF_ARRAY(tag_names))
+ return NULL;
+ return tag_names[num];
+}
+
+int ASN1CALL
+der_get_tag_num(const char *name)
+{
+ return get_type(name, tag_names, SIZEOF_ARRAY(tag_names));
+}
diff --git a/third_party/heimdal/lib/asn1/der.h b/third_party/heimdal/lib/asn1/der.h
new file mode 100644
index 0000000..ec5603e
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/der.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id$ */
+
+#ifndef __DER_H__
+#define __DER_H__
+
+#include <stdint.h>
+
+typedef enum {
+ ASN1_C_UNIV = 0,
+ ASN1_C_APPL = 1,
+ ASN1_C_CONTEXT = 2,
+ ASN1_C_PRIVATE = 3
+} Der_class;
+
+typedef enum {PRIM = 0, CONS = 1} Der_type;
+
+#define MAKE_TAG(CLASS, TYPE, TAG) (((CLASS) << 6) | ((TYPE) << 5) | (TAG))
+
+/* Universal tags */
+
+enum {
+ UT_EndOfContent = 0,
+ UT_Boolean = 1,
+ UT_Integer = 2,
+ UT_BitString = 3,
+ UT_OctetString = 4,
+ UT_Null = 5,
+ UT_OID = 6,
+ UT_Enumerated = 10,
+ UT_UTF8String = 12,
+ UT_Sequence = 16,
+ UT_Set = 17,
+ UT_PrintableString = 19,
+ UT_IA5String = 22,
+ UT_UTCTime = 23,
+ UT_GeneralizedTime = 24,
+ UT_VisibleString = 26,
+ UT_GeneralString = 27,
+ UT_UniversalString = 28,
+ UT_BMPString = 30,
+ /* unsupported types */
+ UT_ObjectDescriptor = 7,
+ UT_External = 8,
+ UT_Real = 9,
+ UT_EmbeddedPDV = 11,
+ UT_RelativeOID = 13,
+ UT_NumericString = 18,
+ UT_TeletexString = 20,
+ UT_VideotexString = 21,
+ UT_GraphicString = 25
+};
+
+#define ASN1_INDEFINITE 0xdce0deed
+
+typedef struct heim_der_time_t {
+ time_t dt_sec;
+ unsigned long dt_nsec;
+} heim_der_time_t;
+
+typedef struct heim_ber_time_t {
+ time_t bt_sec;
+ unsigned bt_nsec;
+ int bt_zone;
+} heim_ber_time_t;
+
+struct asn1_template;
+
+#include <der-protos.h>
+
+int _heim_fix_dce(size_t reallen, size_t *len);
+int _heim_der_set_sort(const void *, const void *);
+int _heim_time2generalizedtime (time_t, heim_octet_string *, int);
+
+#endif /* __DER_H__ */
diff --git a/third_party/heimdal/lib/asn1/der_cmp.c b/third_party/heimdal/lib/asn1/der_cmp.c
new file mode 100644
index 0000000..f745270
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/der_cmp.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2003-2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+
+int ASN1CALL
+der_heim_oid_cmp(const heim_oid *p, const heim_oid *q)
+{
+ int c;
+
+ if (p->length == q->length) {
+ if (p->length == 0)
+ return 0;
+ return memcmp(p->components,
+ q->components,
+ p->length * sizeof(*p->components));
+ }
+ if (p->length < q->length) {
+ if (p->length == 0 ||
+ (c = memcmp(p->components,
+ q->components,
+ p->length * sizeof(*p->components))) == 0)
+ return -1;
+ return c;
+ }
+ if (q->length == 0 ||
+ (c = memcmp(p->components,
+ q->components,
+ q->length * sizeof(*p->components))) == 0)
+ return 1;
+ return c;
+}
+
+int ASN1CALL
+der_heim_octet_string_cmp(const heim_octet_string *p,
+ const heim_octet_string *q)
+{
+ int c;
+
+ if (p->length == q->length) {
+ if (p->length == 0)
+ return 0;
+ return memcmp(p->data, q->data, p->length);
+ }
+ if (p->length < q->length) {
+ if (p->length == 0 ||
+ (c = memcmp(p->data, q->data, p->length)) == 0)
+ return -1;
+ return c;
+ }
+ if (q->length == 0 ||
+ (c = memcmp(p->data, q->data, q->length)) == 0)
+ return 1;
+ return c;
+}
+
+int ASN1CALL
+der_printable_string_cmp(const heim_printable_string *p,
+ const heim_printable_string *q)
+{
+ return der_heim_octet_string_cmp(p, q);
+}
+
+int ASN1CALL
+der_ia5_string_cmp(const heim_ia5_string *p,
+ const heim_ia5_string *q)
+{
+ return der_heim_octet_string_cmp(p, q);
+}
+
+int ASN1CALL
+der_heim_bit_string_cmp(const heim_bit_string *p,
+ const heim_bit_string *q)
+{
+ unsigned char pc, qc;
+ size_t bits;
+ int c = 0;
+
+ /* Compare prefix */
+ if (p->length == 0 && q->length == 0)
+ return 0;
+ if (p->length > 7 && q->length > 7) {
+ if (p->length < q->length)
+ c = memcmp(p->data, q->data, p->length / 8);
+ else
+ c = memcmp(p->data, q->data, q->length / 8);
+ }
+ if (c)
+ return c;
+
+ /* Prefixes are equal, c == 0 */
+
+ if (p->length == q->length && p->length % 8 == 0)
+ return 0;
+ if (p->length == 0 && q->length)
+ return -1; /* No trailing bits of p to compare to corresponding bits of q */
+ if (q->length == 0 && p->length)
+ return 1; /* No trailing bits of q to compare to corresponding bits of p */
+
+ /* c == 0, lengths are not equal, both are at least 1 bit */
+ pc = ((unsigned char *)p->data)[p->length / 8];
+ qc = ((unsigned char *)q->data)[q->length / 8];
+ if (p->length < q->length)
+ bits = p->length % 8;
+ else
+ bits = q->length % 8;
+
+ if (bits > 0) {
+ if ((pc & 0x80) == 0 && (qc & 0x80) != 0)
+ return -1;
+ if ((pc & 0x80) != 0 && (qc & 0x80) == 0)
+ return 1;
+ }
+ if (bits > 1) {
+ if ((pc & 0x40) == 0 && (qc & 0x40) != 0)
+ return -1;
+ if ((pc & 0x40) != 0 && (qc & 0x40) == 0)
+ return 1;
+ }
+ if (bits > 2) {
+ if ((pc & 0x20) == 0 && (qc & 0x20) != 0)
+ return -1;
+ if ((pc & 0x20) != 0 && (qc & 0x20) == 0)
+ return 1;
+ }
+ if (bits > 3) {
+ if ((pc & 0x10) == 0 && (qc & 0x10) != 0)
+ return -1;
+ if ((pc & 0x10) != 0 && (qc & 0x10) == 0)
+ return 1;
+ }
+ if (bits > 4) {
+ if ((pc & 0x08) == 0 && (qc & 0x08) != 0)
+ return -1;
+ if ((pc & 0x08) != 0 && (qc & 0x08) == 0)
+ return 1;
+ }
+ if (bits > 5) {
+ if ((pc & 0x04) == 0 && (qc & 0x04) != 0)
+ return -1;
+ if ((pc & 0x04) != 0 && (qc & 0x04) == 0)
+ return 1;
+ }
+ if (bits > 6) {
+ if ((pc & 0x02) == 0 && (qc & 0x02) != 0)
+ return -1;
+ if ((pc & 0x02) != 0 && (qc & 0x02) == 0)
+ return 1;
+ }
+ /*
+ * `bits' can't be 8.
+ *
+ * All leading `bits' bits of the tail of the shorter of `p' or `q' are
+ * equal.
+ */
+ if (p->length < q->length)
+ return -1;
+ if (q->length < p->length)
+ return 1;
+ return 0;
+}
+
+int ASN1CALL
+der_heim_integer_cmp(const heim_integer *p,
+ const heim_integer *q)
+{
+ if (p->negative != q->negative)
+ return q->negative - p->negative;
+ if (p->length != q->length)
+ return (int)(p->length - q->length);
+ return memcmp(p->data, q->data, p->length);
+}
+
+int ASN1CALL
+der_heim_bmp_string_cmp(const heim_bmp_string *p, const heim_bmp_string *q)
+{
+ int c;
+
+ if (p->length == q->length) {
+ if (p->length == 0)
+ return 0;
+ return memcmp(p->data, q->data, p->length * sizeof(q->data[0]));
+ }
+ if (p->length < q->length) {
+ if (p->length == 0 ||
+ (c = memcmp(p->data, q->data, p->length * sizeof(q->data[0]))) == 0)
+ return -1;
+ return c;
+ }
+ if (q->length == 0 ||
+ (c = memcmp(p->data, q->data, q->length * sizeof(q->data[0]))) == 0)
+ return 1;
+ return c;
+}
+
+int ASN1CALL
+der_heim_universal_string_cmp(const heim_universal_string *p,
+ const heim_universal_string *q)
+{
+ int c;
+
+ if (p->length == q->length) {
+ if (p->length == 0)
+ return 0;
+ return memcmp(p->data, q->data, p->length * sizeof(q->data[0]));
+ }
+ if (p->length < q->length) {
+ if (p->length == 0 ||
+ (c = memcmp(p->data, q->data, p->length * sizeof(q->data[0]))) == 0)
+ return -1;
+ return c;
+ }
+ if (q->length == 0 ||
+ (c = memcmp(p->data, q->data, q->length * sizeof(q->data[0]))) == 0)
+ return 1;
+ return c;
+}
diff --git a/third_party/heimdal/lib/asn1/der_copy.c b/third_party/heimdal/lib/asn1/der_copy.c
new file mode 100644
index 0000000..f67fff6
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/der_copy.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+
+RCSID("$Id$");
+
+int ASN1CALL
+der_copy_general_string (const heim_general_string *from,
+ heim_general_string *to)
+{
+ *to = strdup(*from);
+ if(*to == NULL)
+ return ENOMEM;
+ return 0;
+}
+
+int ASN1CALL
+der_copy_integer (const int *from, int *to)
+{
+ *to = *from;
+ return 0;
+}
+
+int ASN1CALL
+der_copy_integer64 (const int64_t *from, int64_t *to)
+{
+ *to = *from;
+ return 0;
+}
+
+int ASN1CALL
+der_copy_unsigned (const unsigned *from, unsigned *to)
+{
+ *to = *from;
+ return 0;
+}
+
+int ASN1CALL
+der_copy_unsigned64 (const uint64_t *from, uint64_t *to)
+{
+ *to = *from;
+ return 0;
+}
+
+int ASN1CALL
+der_copy_generalized_time (const time_t *from, time_t *to)
+{
+ *to = *from;
+ return 0;
+}
+
+int ASN1CALL
+der_copy_utctime (const time_t *from, time_t *to)
+{
+ *to = *from;
+ return 0;
+}
+
+int ASN1CALL
+der_copy_utf8string (const heim_utf8_string *from, heim_utf8_string *to)
+{
+ return der_copy_general_string(from, to);
+}
+
+int ASN1CALL
+der_copy_printable_string (const heim_printable_string *from,
+ heim_printable_string *to)
+{
+ assert(from->length == 0 || (from->length > 0 && from->data != NULL));
+ to->data = malloc(from->length + 1);
+ if (to->data == NULL) {
+ to->length = 0;
+ return ENOMEM;
+ }
+ to->length = from->length;
+ if (to->length > 0)
+ memcpy(to->data, from->data, to->length);
+ ((char *)to->data)[to->length] = '\0';
+ return 0;
+}
+
+int ASN1CALL
+der_copy_ia5_string (const heim_ia5_string *from,
+ heim_ia5_string *to)
+{
+ return der_copy_printable_string(from, to);
+}
+
+int ASN1CALL
+der_copy_bmp_string (const heim_bmp_string *from, heim_bmp_string *to)
+{
+ assert(from->length == 0 || (from->length > 0 && from->data != NULL));
+ if (from->length == 0)
+ to->data = calloc(1, sizeof(from->data[0]));
+ else
+ to->data = malloc(from->length * sizeof(from->data[0]));
+ if (to->data == NULL) {
+ to->length = 0;
+ return ENOMEM;
+ }
+ to->length = from->length;
+ if (to->length > 0)
+ memcpy(to->data, from->data, to->length * sizeof(to->data[0]));
+ return 0;
+}
+
+int ASN1CALL
+der_copy_universal_string (const heim_universal_string *from,
+ heim_universal_string *to)
+{
+ assert(from->length == 0 || (from->length > 0 && from->data != NULL));
+ if (from->length == 0)
+ to->data = calloc(1, sizeof(from->data[0]));
+ else
+ to->data = malloc(from->length * sizeof(from->data[0]));
+ if (to->data == NULL) {
+ to->length = 0;
+ return ENOMEM;
+ }
+ to->length = from->length;
+ if (to->length > 0)
+ memcpy(to->data, from->data, to->length * sizeof(to->data[0]));
+ return 0;
+}
+
+int ASN1CALL
+der_copy_visible_string (const heim_visible_string *from,
+ heim_visible_string *to)
+{
+ return der_copy_general_string(from, to);
+}
+
+int ASN1CALL
+der_copy_octet_string (const heim_octet_string *from, heim_octet_string *to)
+{
+ assert(from->length == 0 || (from->length > 0 && from->data != NULL));
+ if (from->length == 0) {
+ if (from->data == NULL) {
+ *to = *from;
+ return 0;
+ }
+ to->data = calloc(1, 1);
+ } else
+ to->data = malloc(from->length);
+ if (to->data == NULL) {
+ to->length = 0;
+ return ENOMEM;
+ }
+ to->length = from->length;
+ if (to->length > 0)
+ memcpy(to->data, from->data, to->length);
+ return 0;
+}
+
+int ASN1CALL
+der_copy_heim_integer (const heim_integer *from, heim_integer *to)
+{
+ assert(from->length == 0 || (from->length > 0 && from->data != NULL));
+ if (from->length == 0)
+ to->data = calloc(1, 1);
+ else
+ to->data = malloc(from->length);
+ if (to->data == NULL) {
+ to->length = 0;
+ return ENOMEM;
+ }
+ to->length = from->length;
+ if (to->length > 0)
+ memcpy(to->data, from->data, to->length);
+ to->negative = from->negative;
+ return 0;
+}
+
+int ASN1CALL
+der_copy_oid (const heim_oid *from, heim_oid *to)
+{
+ if (from->length == 0) {
+ to->length = 0;
+ to->components = calloc(1, sizeof(*from->components));
+ if (to->components == NULL)
+ return ENOMEM;
+ return 0;
+ }
+ assert(from->components != NULL);
+ to->components = malloc(from->length * sizeof(*from->components));
+ if (to->components == NULL) {
+ to->length = 0;
+ return ENOMEM;
+ }
+ to->length = from->length;
+ memcpy(to->components, from->components,
+ to->length * sizeof(*to->components));
+ return 0;
+}
+
+int ASN1CALL
+der_copy_bit_string (const heim_bit_string *from, heim_bit_string *to)
+{
+ size_t len;
+
+ assert(from->length == 0 || (from->length > 0 && from->data != NULL));
+
+ len = (from->length + 7) / 8;
+ if (len == 0)
+ to->data = calloc(1, 1);
+ else
+ to->data = malloc(len);
+ if (to->data == NULL) {
+ to->length = 0;
+ return ENOMEM;
+ }
+ to->length = from->length;
+ if (len > 0)
+ memcpy(to->data, from->data, len);
+ return 0;
+}
diff --git a/third_party/heimdal/lib/asn1/der_format.c b/third_party/heimdal/lib/asn1/der_format.c
new file mode 100644
index 0000000..bb4a7ce
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/der_format.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+#include <hex.h>
+
+RCSID("$Id$");
+
+int ASN1CALL
+der_parse_hex_heim_integer (const char *p, heim_integer *data)
+{
+ ssize_t len;
+
+ data->length = 0;
+ data->negative = 0;
+ data->data = NULL;
+
+ if (*p == '-') {
+ p++;
+ data->negative = 1;
+ }
+
+ len = strlen(p);
+ if (len <= 0) {
+ data->data = NULL;
+ data->length = 0;
+ return EINVAL;
+ }
+
+ data->length = (len / 2) + 1;
+ data->data = malloc(data->length);
+ if (data->data == NULL) {
+ data->length = 0;
+ return ENOMEM;
+ }
+
+ len = hex_decode(p, data->data, data->length);
+ if (len < 0) {
+ free(data->data);
+ data->data = NULL;
+ data->length = 0;
+ return EINVAL;
+ }
+
+ {
+ unsigned char *q = data->data;
+ while(len > 0 && *q == 0) {
+ q++;
+ len--;
+ }
+ data->length = len;
+ memmove(data->data, q, len);
+ }
+ return 0;
+}
+
+int ASN1CALL
+der_print_hex_heim_integer (const heim_integer *data, char **p)
+{
+ ssize_t len;
+ char *q;
+
+ len = hex_encode(data->data, data->length, p);
+ if (len < 0)
+ return ENOMEM;
+
+ if (data->negative) {
+ len = asprintf(&q, "-%s", *p);
+ free(*p);
+ if (len < 0)
+ return ENOMEM;
+ *p = q;
+ }
+ return 0;
+}
+
+int ASN1CALL
+der_print_heim_oid (const heim_oid *oid, char delim, char **str)
+{
+ struct rk_strpool *p = NULL;
+ size_t i;
+
+ if (oid->length == 0)
+ return EINVAL;
+
+ for (i = 0; i < oid->length ; i++) {
+ p = rk_strpoolprintf(p, "%d", oid->components[i]);
+ if (p && i < oid->length - 1)
+ p = rk_strpoolprintf(p, "%c", delim);
+ if (p == NULL) {
+ *str = NULL;
+ return ENOMEM;
+ }
+ }
+
+ *str = rk_strpoolcollect(p);
+ if (*str == NULL)
+ return ENOMEM;
+ return 0;
+}
+
+int ASN1CALL
+der_parse_heim_oid (const char *str, const char *sep, heim_oid *data)
+{
+ char *s, *w, *brkt, *endptr;
+ unsigned int *c;
+ long l;
+
+ data->length = 0;
+ data->components = NULL;
+
+ if (sep == NULL)
+ sep = ".";
+
+ s = strdup(str);
+
+ for (w = strtok_r(s, sep, &brkt);
+ w != NULL;
+ w = strtok_r(NULL, sep, &brkt)) {
+
+ c = realloc(data->components,
+ (data->length + 1) * sizeof(data->components[0]));
+ if (c == NULL) {
+ der_free_oid(data);
+ free(s);
+ return ENOMEM;
+ }
+ data->components = c;
+
+ l = strtol(w, &endptr, 10);
+ if (*endptr != '\0' || l < 0 || l > INT_MAX) {
+ der_free_oid(data);
+ free(s);
+ return EINVAL;
+ }
+ data->components[data->length++] = (unsigned int)l;
+ }
+ free(s);
+ return 0;
+}
diff --git a/third_party/heimdal/lib/asn1/der_free.c b/third_party/heimdal/lib/asn1/der_free.c
new file mode 100644
index 0000000..d80406f
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/der_free.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+
+RCSID("$Id$");
+
+void ASN1CALL
+der_free_general_string (heim_general_string *str)
+{
+ free(*str);
+ *str = NULL;
+}
+
+void ASN1CALL
+der_free_integer (int *i)
+{
+ *i = 0;
+}
+
+void ASN1CALL
+der_free_integer64 (int64_t *i)
+{
+ *i = 0;
+}
+
+void ASN1CALL
+der_free_unsigned (unsigned *u)
+{
+ *u = 0;
+}
+
+void ASN1CALL
+der_free_unsigned64 (uint64_t *u)
+{
+ *u = 0;
+}
+
+void ASN1CALL
+der_free_generalized_time(time_t *t)
+{
+ *t = 0;
+}
+
+void ASN1CALL
+der_free_utctime(time_t *t)
+{
+ *t = 0;
+}
+
+
+void ASN1CALL
+der_free_utf8string (heim_utf8_string *str)
+{
+ free(*str);
+ *str = NULL;
+}
+
+void ASN1CALL
+der_free_printable_string (heim_printable_string *str)
+{
+ der_free_octet_string(str);
+}
+
+void ASN1CALL
+der_free_ia5_string (heim_ia5_string *str)
+{
+ der_free_octet_string(str);
+}
+
+void ASN1CALL
+der_free_bmp_string (heim_bmp_string *k)
+{
+ free(k->data);
+ k->data = NULL;
+ k->length = 0;
+}
+
+void ASN1CALL
+der_free_universal_string (heim_universal_string *k)
+{
+ free(k->data);
+ k->data = NULL;
+ k->length = 0;
+}
+
+void ASN1CALL
+der_free_visible_string (heim_visible_string *str)
+{
+ free(*str);
+ *str = NULL;
+}
+
+void ASN1CALL
+der_free_octet_string (heim_octet_string *k)
+{
+ free(k->data);
+ k->data = NULL;
+ k->length = 0;
+}
+
+void ASN1CALL
+der_free_heim_integer (heim_integer *k)
+{
+ free(k->data);
+ k->data = NULL;
+ k->length = 0;
+}
+
+void ASN1CALL
+der_free_oid (heim_oid *k)
+{
+ free(k->components);
+ k->components = NULL;
+ k->length = 0;
+}
+
+void ASN1CALL
+der_free_bit_string (heim_bit_string *k)
+{
+ free(k->data);
+ k->data = NULL;
+ k->length = 0;
+}
diff --git a/third_party/heimdal/lib/asn1/der_get.c b/third_party/heimdal/lib/asn1/der_get.c
new file mode 100644
index 0000000..06564b7
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/der_get.c
@@ -0,0 +1,842 @@
+/*
+ * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+
+/*
+ * All decoding functions take a pointer `p' to first position in
+ * which to read, from the left, `len' which means the maximum number
+ * of characters we are able to read, `ret' were the value will be
+ * returned and `size' where the number of used bytes is stored.
+ * Either 0 or an error code is returned.
+ */
+
+int ASN1CALL
+der_get_unsigned (const unsigned char *p, size_t len,
+ unsigned *ret, size_t *size)
+{
+ unsigned val = 0;
+ size_t oldlen = len;
+
+ if (len == sizeof(val) + 1 && p[0] == 0)
+ ;
+ else if (len > sizeof(val))
+ return ASN1_OVERRUN;
+
+ while (len--)
+ val = val * 256 + *p++;
+ *ret = val;
+ if(size) *size = oldlen;
+ return 0;
+}
+
+int ASN1CALL
+der_get_unsigned64 (const unsigned char *p, size_t len,
+ uint64_t *ret, size_t *size)
+{
+ uint64_t val = 0;
+ size_t oldlen = len;
+
+ if (len == sizeof(val) + 1 && p[0] == 0)
+ ;
+ else if (len > sizeof(val))
+ return ASN1_OVERRUN;
+
+ while (len--)
+ val = val * 256 + *p++;
+ *ret = val;
+ if(size) *size = oldlen;
+ return 0;
+}
+
+int ASN1CALL
+der_get_integer (const unsigned char *p, size_t len,
+ int *ret, size_t *size)
+{
+ int val = 0;
+ size_t oldlen = len;
+
+ if (len == sizeof(val) + 1 && (p[0] == 0 || p[0] == 0xff))
+ ;
+ else if (len > sizeof(val))
+ return ASN1_OVERRUN;
+
+ /* We assume we're on a twos-complement platform */
+ if (len > 0) {
+ val = (signed char)*p++;
+ while (--len)
+ val = val * 256 + *p++;
+ }
+ *ret = val;
+ if(size) *size = oldlen;
+ return 0;
+}
+
+int ASN1CALL
+der_get_integer64 (const unsigned char *p, size_t len,
+ int64_t *ret, size_t *size)
+{
+ int64_t val = 0;
+ size_t oldlen = len;
+
+ if (len > sizeof(val))
+ return ASN1_OVERRUN;
+
+ /* We assume we're on a twos-complement platform */
+ if (len > 0) {
+ val = (signed char)*p++;
+ while (--len)
+ val = val * 256 + *p++;
+ }
+ *ret = val;
+ if(size) *size = oldlen;
+ return 0;
+}
+
+
+int ASN1CALL
+der_get_length (const unsigned char *p, size_t len,
+ size_t *val, size_t *size)
+{
+ size_t v;
+
+ if (len <= 0)
+ return ASN1_OVERRUN;
+ --len;
+ v = *p++;
+ if (v < 128) {
+ *val = v;
+ if(size) *size = 1;
+ } else {
+ int e;
+ size_t l;
+ unsigned tmp;
+
+ if(v == 0x80){
+ *val = ASN1_INDEFINITE;
+ if(size) *size = 1;
+ return 0;
+ }
+ v &= 0x7F;
+ if (len < v)
+ return ASN1_OVERRUN;
+ e = der_get_unsigned (p, v, &tmp, &l);
+ if(e) return e;
+ *val = tmp;
+ if(size) *size = l + 1;
+ }
+ return 0;
+}
+
+int ASN1CALL
+der_get_boolean(const unsigned char *p, size_t len, int *data, size_t *size)
+{
+ if(len < 1)
+ return ASN1_OVERRUN;
+ if(*p != 0)
+ *data = 1;
+ else
+ *data = 0;
+ *size = 1;
+ return 0;
+}
+
+int ASN1CALL
+der_get_general_string (const unsigned char *p, size_t len,
+ heim_general_string *str, size_t *size)
+{
+ const unsigned char *p1;
+ char *s;
+
+ assert(p != NULL);
+
+ if (size)
+ *size = 0;
+
+ p1 = memchr(p, 0, len);
+ if (p1 != NULL) {
+ /*
+ * Allow trailing NULs. We allow this since MIT Kerberos sends
+ * an strings in the NEED_PREAUTH case that includes a
+ * trailing NUL.
+ */
+ while ((size_t)(p1 - p) < len && *p1 == '\0')
+ p1++;
+ if ((size_t)(p1 - p) != len) {
+ *str = NULL;
+ return ASN1_BAD_CHARACTER;
+ }
+ }
+ if (len == SIZE_MAX) {
+ *str = NULL;
+ return ASN1_BAD_LENGTH;
+ }
+
+ *str = s = malloc (len + 1);
+ if (s == NULL)
+ return ENOMEM;
+ memcpy (s, p, len);
+ s[len] = '\0';
+
+ if(size) *size = len;
+ return 0;
+}
+
+int ASN1CALL
+der_get_utf8string (const unsigned char *p, size_t len,
+ heim_utf8_string *str, size_t *size)
+{
+ return der_get_general_string(p, len, str, size);
+}
+
+#define gen_data_zero(_data) \
+ do { (_data)->length = 0; (_data)->data = NULL; } while(0)
+
+int ASN1CALL
+der_get_printable_string(const unsigned char *p, size_t len,
+ heim_printable_string *str, size_t *size)
+{
+ assert(p != NULL);
+
+ if (size)
+ *size = 0;
+
+ if (len == SIZE_MAX) {
+ gen_data_zero(str);
+ return ASN1_BAD_LENGTH;
+ }
+ str->length = len;
+ str->data = malloc(len + 1);
+ if (str->data == NULL) {
+ gen_data_zero(str);
+ return ENOMEM;
+ }
+
+ memcpy(str->data, p, len);
+ ((char *)str->data)[len] = '\0';
+ if(size) *size = len;
+ return 0;
+}
+
+int ASN1CALL
+der_get_ia5_string(const unsigned char *p, size_t len,
+ heim_ia5_string *str, size_t *size)
+{
+ return der_get_printable_string(p, len, str, size);
+}
+
+int ASN1CALL
+der_get_bmp_string (const unsigned char *p, size_t len,
+ heim_bmp_string *data, size_t *size)
+{
+ size_t i;
+
+ assert(p != NULL);
+
+ if (size)
+ *size = 0;
+
+ if (len & 1) {
+ gen_data_zero(data);
+ return ASN1_BAD_FORMAT;
+ }
+ data->length = len / 2;
+ if (data->length > UINT_MAX/sizeof(data->data[0])) {
+ gen_data_zero(data);
+ return ERANGE;
+ }
+ data->data = malloc(data->length * sizeof(data->data[0]));
+ if (data->data == NULL && data->length != 0) {
+ gen_data_zero(data);
+ return ENOMEM;
+ }
+
+ for (i = 0; i < data->length; i++) {
+ data->data[i] = (p[0] << 8) | p[1];
+ p += 2;
+ /* check for NUL in the middle of the string */
+ if (data->data[i] == 0 && i != (data->length - 1)) {
+ free(data->data);
+ gen_data_zero(data);
+ return ASN1_BAD_CHARACTER;
+ }
+ }
+ if (size) *size = len;
+
+ return 0;
+}
+
+int ASN1CALL
+der_get_universal_string (const unsigned char *p, size_t len,
+ heim_universal_string *data, size_t *size)
+{
+ size_t i;
+
+ assert(p != NULL);
+
+ if (size)
+ *size = 0;
+
+ if (len & 3) {
+ gen_data_zero(data);
+ return ASN1_BAD_FORMAT;
+ }
+ data->length = len / 4;
+ if (data->length > UINT_MAX/sizeof(data->data[0])) {
+ gen_data_zero(data);
+ return ERANGE;
+ }
+ data->data = malloc(data->length * sizeof(data->data[0]));
+ if (data->data == NULL && data->length != 0) {
+ gen_data_zero(data);
+ return ENOMEM;
+ }
+
+ for (i = 0; i < data->length; i++) {
+ data->data[i] = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ p += 4;
+ /* check for NUL in the middle of the string */
+ if (data->data[i] == 0 && i != (data->length - 1)) {
+ free(data->data);
+ gen_data_zero(data);
+ return ASN1_BAD_CHARACTER;
+ }
+ }
+ if (size) *size = len;
+ return 0;
+}
+
+int ASN1CALL
+der_get_visible_string (const unsigned char *p, size_t len,
+ heim_visible_string *str, size_t *size)
+{
+ return der_get_general_string(p, len, str, size);
+}
+
+int ASN1CALL
+der_get_octet_string (const unsigned char *p, size_t len,
+ heim_octet_string *data, size_t *size)
+{
+ assert(p != NULL);
+
+ if (size)
+ *size = 0;
+
+ if (len == 0)
+ data->data = malloc(1);
+ else
+ data->data = malloc(len);
+ if (data->data == NULL) {
+ data->length = 0;
+ return ENOMEM;
+ }
+ data->length = len;
+ memcpy (data->data, p, len);
+ if (size)
+ *size = len;
+ return 0;
+}
+
+int ASN1CALL
+der_get_octet_string_ber (const unsigned char *p, size_t len,
+ heim_octet_string *data, size_t *size)
+{
+ int e;
+ Der_type type;
+ Der_class cls;
+ unsigned int tag, depth = 0;
+ size_t l, datalen, oldlen = len;
+
+ assert(p != NULL);
+
+ if (size)
+ *size = 0;
+
+ data->length = 0;
+ data->data = NULL;
+
+ while (len) {
+ e = der_get_tag (p, len, &cls, &type, &tag, &l);
+ if (e) goto out;
+ if (cls != ASN1_C_UNIV) {
+ e = ASN1_BAD_ID;
+ goto out;
+ }
+ if (type == PRIM && tag == UT_EndOfContent) {
+ if (depth == 0)
+ break;
+ depth--;
+ }
+ if (tag != UT_OctetString) {
+ e = ASN1_BAD_ID;
+ goto out;
+ }
+
+ p += l;
+ len -= l;
+ e = der_get_length (p, len, &datalen, &l);
+ if (e) goto out;
+ p += l;
+ len -= l;
+
+ if (datalen > len)
+ return ASN1_OVERRUN;
+
+ if (type == PRIM && datalen) {
+ void *ptr;
+
+ ptr = realloc(data->data, data->length + datalen);
+ if (ptr == NULL) {
+ e = ENOMEM;
+ goto out;
+ }
+ data->data = ptr;
+ memcpy(((unsigned char *)data->data) + data->length, p, datalen);
+ data->length += datalen;
+ } else if (type != PRIM)
+ depth++;
+
+ p += datalen;
+ len -= datalen;
+ }
+ if (depth != 0)
+ return ASN1_INDEF_OVERRUN;
+ if(size) *size = oldlen - len;
+ return 0;
+ out:
+ free(data->data);
+ data->data = NULL;
+ data->length = 0;
+ return e;
+}
+
+
+int ASN1CALL
+der_get_heim_integer (const unsigned char *p, size_t len,
+ heim_integer *data, size_t *size)
+{
+ data->length = 0;
+ data->negative = 0;
+ data->data = NULL;
+
+ if (size)
+ *size = 0;
+
+ if (len == 0)
+ return 0;
+
+ assert(p != NULL);
+
+ if (p[0] & 0x80) {
+ unsigned char *q;
+ int carry = 1;
+
+
+ /*
+ * A negative number. It's going to be a twos complement byte array.
+ * We're going to leave the positive value in `data->data', but set the
+ * `data->negative' flag. That means we need to negate the
+ * twos-complement integer received.
+ */
+ data->negative = 1;
+ data->length = len;
+
+ if (p[0] == 0xff) {
+ if (data->length == 1) {
+ /* One byte of all ones == -1 */
+ q = data->data = malloc(1);
+ *q = 1;
+ data->length = 1;
+ if (size)
+ *size = 1;
+ return 0;
+ }
+
+ p++;
+ data->length--;
+
+ /*
+ * We could check if the next byte's high bit is set, which would
+ * be an error ("illegal padding" in OpenSSL). However, this would
+ * mean failing to accept certificates made by certain CAs that
+ * would read 8 bytes of RNG into a buffer, slap on length 8, then
+ * slap on the tag [UNIVERSAL INTEGER], and make that the
+ * serialNumber field's encoding, which then fails to parse in
+ * around 1 in 256 certificates.
+ *
+ * So let's not.
+ *
+ * if (p[0] & 0x80)
+ * return ASN1_PARSE_ERROR; // or a new error code
+ */
+ }
+ data->data = malloc(data->length);
+ if (data->data == NULL) {
+ data->length = 0;
+ if (size)
+ *size = 0;
+ return ENOMEM;
+ }
+
+ /*
+ * Note that if `data->length' were zero, this would be UB because we
+ * underflow if data->length is zero even though we wouldn't actually
+ * dereference the byte before data->data. Thus we check above for
+ * that.
+ */
+ q = &((unsigned char*)data->data)[data->length - 1];
+ p += data->length - 1;
+ while (q >= (unsigned char*)data->data) {
+ /* *p XOR 0xff -> ~*p; we're dealing with twos complement */
+ *q = *p ^ 0xff;
+ if (carry)
+ carry = !++*q;
+ p--;
+ q--;
+ }
+ } else {
+ data->negative = 0;
+ data->length = len;
+
+ if (p[0] == 0) {
+ p++;
+ data->length--;
+ }
+ data->data = malloc(data->length);
+ if (data->data == NULL && data->length != 0) {
+ data->length = 0;
+ if (size)
+ *size = 0;
+ return ENOMEM;
+ }
+ memcpy(data->data, p, data->length);
+ }
+ if (size)
+ *size = len;
+ return 0;
+}
+
+static int
+generalizedtime2time (const char *s, time_t *t)
+{
+ struct tm tm;
+
+ memset(&tm, 0, sizeof(tm));
+ if (sscanf (s, "%04d%02d%02d%02d%02d%02dZ",
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
+ &tm.tm_min, &tm.tm_sec) != 6) {
+ if (sscanf (s, "%02d%02d%02d%02d%02d%02dZ",
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
+ &tm.tm_min, &tm.tm_sec) != 6)
+ return ASN1_BAD_TIMEFORMAT;
+ if (tm.tm_year < 50)
+ tm.tm_year += 2000;
+ else
+ tm.tm_year += 1900;
+ }
+ tm.tm_year -= 1900;
+ tm.tm_mon -= 1;
+ *t = _der_timegm (&tm);
+ return 0;
+}
+
+static int ASN1CALL
+der_get_time (const unsigned char *p, size_t len,
+ time_t *data, size_t *size)
+{
+ char *times;
+ int e;
+
+ assert(p != NULL);
+
+ if (size)
+ *size = 0;
+
+ if (len == SIZE_MAX || len == 0)
+ return ASN1_BAD_LENGTH;
+
+ times = malloc(len + 1);
+ if (times == NULL)
+ return ENOMEM;
+ memcpy(times, p, len);
+ times[len] = '\0';
+ e = generalizedtime2time(times, data);
+ free (times);
+ if(size) *size = len;
+ return e;
+}
+
+int ASN1CALL
+der_get_generalized_time (const unsigned char *p, size_t len,
+ time_t *data, size_t *size)
+{
+ return der_get_time(p, len, data, size);
+}
+
+int ASN1CALL
+der_get_utctime (const unsigned char *p, size_t len,
+ time_t *data, size_t *size)
+{
+ return der_get_time(p, len, data, size);
+}
+
+int ASN1CALL
+der_get_oid (const unsigned char *p, size_t len,
+ heim_oid *data, size_t *size)
+{
+ size_t n;
+ size_t oldlen = len;
+
+ assert(p != NULL);
+
+ if (size)
+ *size = 0;
+
+ if (len < 1)
+ return ASN1_OVERRUN;
+
+ if (len == SIZE_MAX)
+ return ASN1_BAD_LENGTH;
+
+ if (len + 1 > UINT_MAX/sizeof(data->components[0]))
+ return ERANGE;
+
+ data->components = malloc((len + 1) * sizeof(data->components[0]));
+ if (data->components == NULL) {
+ data->length = 0;
+ return ENOMEM;
+ }
+ data->components[0] = (*p) / 40;
+ data->components[1] = (*p) % 40;
+ --len;
+ ++p;
+ for (n = 2; len > 0; ++n) {
+ unsigned u = 0, u1;
+
+ do {
+ --len;
+ u1 = u * 128 + (*p++ % 128);
+ /* check that we don't overflow the element */
+ if (u1 < u) {
+ der_free_oid(data);
+ return ASN1_OVERRUN;
+ }
+ u = u1;
+ } while (len > 0 && p[-1] & 0x80);
+ data->components[n] = u;
+ }
+ if (n > 2 && p[-1] & 0x80) {
+ der_free_oid (data);
+ return ASN1_OVERRUN;
+ }
+ data->length = n;
+ if (size)
+ *size = oldlen;
+ return 0;
+}
+
+int ASN1CALL
+der_get_tag (const unsigned char *p, size_t len,
+ Der_class *cls, Der_type *type,
+ unsigned int *tag, size_t *size)
+{
+ size_t ret = 0;
+
+ if (size)
+ *size = 0;
+
+ if (len < 1)
+ return ASN1_MISSING_FIELD;
+
+ assert(p != NULL);
+
+ *cls = (Der_class)(((*p) >> 6) & 0x03);
+ *type = (Der_type)(((*p) >> 5) & 0x01);
+ *tag = (*p) & 0x1f;
+ p++; len--; ret++;
+ if(*tag == 0x1f) {
+ unsigned int continuation;
+ unsigned int tag1;
+ *tag = 0;
+ do {
+ if(len < 1)
+ return ASN1_OVERRUN;
+ continuation = *p & 128;
+ tag1 = *tag * 128 + (*p % 128);
+ /* check that we don't overflow the tag */
+ if (tag1 < *tag)
+ return ASN1_OVERFLOW;
+ *tag = tag1;
+ p++; len--; ret++;
+ } while(continuation);
+ }
+ if(size) *size = ret;
+ return 0;
+}
+
+int ASN1CALL
+der_match_tag (const unsigned char *p, size_t len,
+ Der_class cls, Der_type type,
+ unsigned int tag, size_t *size)
+{
+ Der_type thistype;
+ int e;
+
+ e = der_match_tag2(p, len, cls, &thistype, tag, size);
+ if (e) return e;
+ if (thistype != type) return ASN1_BAD_ID;
+ return 0;
+}
+
+int ASN1CALL
+der_match_tag2 (const unsigned char *p, size_t len,
+ Der_class cls, Der_type *type,
+ unsigned int tag, size_t *size)
+{
+ size_t l;
+ Der_class thisclass;
+ unsigned int thistag;
+ int e;
+
+ if (size)
+ *size = 0;
+
+ e = der_get_tag(p, len, &thisclass, type, &thistag, &l);
+ if (e) return e;
+ /*
+ * We do depend on ASN1_BAD_ID being returned in places where we're
+ * essentially implementing an application-level CHOICE where we try to
+ * decode one way then the other. In Heimdal this happens only in lib/hdb/
+ * where we try to decode a blob as an hdb_entry, then as an
+ * hdb_entry_alias. Applications should really not depend on this.
+ */
+ if (cls != thisclass && (cls == ASN1_C_APPL || thisclass == ASN1_C_APPL))
+ return ASN1_BAD_ID;
+ if (cls != thisclass || tag != thistag)
+ return ASN1_MISSING_FIELD;
+ if (size) *size = l;
+ return 0;
+}
+
+/*
+ * Returns 0 if the encoded data at `p' of length `len' starts with the tag of
+ * class `cls`, type `type', and tag value `tag', and puts the length of the
+ * payload (i.e., the length of V in TLV, not the length of TLV) in
+ * `*length_ret', and the size of the whole thing (the TLV) in `*size' if
+ * `size' is not NULL.
+ *
+ * Else returns an error.
+ */
+int ASN1CALL
+der_match_tag_and_length (const unsigned char *p, size_t len,
+ Der_class cls, Der_type *type, unsigned int tag,
+ size_t *length_ret, size_t *size)
+{
+ size_t l, ret = 0;
+ int e;
+
+ e = der_match_tag2 (p, len, cls, type, tag, &l);
+ if (e) return e;
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length (p, len, length_ret, &l);
+ if (e) return e;
+ if(size) *size = ret + l;
+ return 0;
+}
+
+
+
+/*
+ * Old versions of DCE was based on a very early beta of the MIT code,
+ * which used MAVROS for ASN.1 encoding. MAVROS had the interesting
+ * feature that it encoded data in the forward direction, which has
+ * it's problems, since you have no idea how long the data will be
+ * until after you're done. MAVROS solved this by reserving one byte
+ * for length, and later, if the actual length was longer, it reverted
+ * to indefinite, BER style, lengths. The version of MAVROS used by
+ * the DCE people could apparently generate correct X.509 DER encodings, and
+ * did this by making space for the length after encoding, but
+ * unfortunately this feature wasn't used with Kerberos.
+ */
+
+int
+_heim_fix_dce(size_t reallen, size_t *len)
+{
+ if(reallen == ASN1_INDEFINITE)
+ return 1;
+ if(*len < reallen)
+ return -1;
+ *len = reallen;
+ return 0;
+}
+
+int ASN1CALL
+der_get_bit_string (const unsigned char *p, size_t len,
+ heim_bit_string *data, size_t *size)
+{
+ assert(p != NULL);
+
+ if (size)
+ *size = 0;
+
+ if (len < 1)
+ return ASN1_OVERRUN;
+ if (p[0] > 7)
+ return ASN1_BAD_FORMAT;
+ if (len - 1 == 0 && p[0] != 0)
+ return ASN1_BAD_FORMAT;
+ /* check if any of the three upper bits are set
+ * any of them will cause a interger overrun */
+ if ((len - 1) >> (sizeof(len) * 8 - 3))
+ return ASN1_OVERRUN;
+ /*
+ * If there is data to copy, do that now.
+ */
+ if (len - 1 > 0) {
+ data->length = (len - 1) * 8;
+ data->data = malloc(len - 1);
+ if (data->data == NULL) {
+ data->length = 0;
+ return ENOMEM;
+ }
+ memcpy (data->data, p + 1, len - 1);
+ data->length -= p[0];
+ } else {
+ data->data = NULL;
+ data->length = 0;
+ }
+ if(size) *size = len;
+ return 0;
+}
diff --git a/third_party/heimdal/lib/asn1/der_length.c b/third_party/heimdal/lib/asn1/der_length.c
new file mode 100644
index 0000000..cd50df8
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/der_length.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+
+RCSID("$Id$");
+
+size_t
+_heim_len_unsigned (unsigned val)
+{
+ size_t ret = 0;
+ int last_val_gt_128;
+
+ do {
+ ++ret;
+ last_val_gt_128 = (val >= 128);
+ val /= 256;
+ } while (val);
+
+ if(last_val_gt_128)
+ ret++;
+
+ return ret;
+}
+
+size_t
+_heim_len_unsigned64 (uint64_t val)
+{
+ size_t ret = 0;
+ int last_val_gt_128;
+
+ do {
+ ++ret;
+ last_val_gt_128 = (val >= 128);
+ val /= 256;
+ } while (val);
+
+ if(last_val_gt_128)
+ ret++;
+
+ return ret;
+}
+
+size_t
+_heim_len_int (int val)
+{
+ unsigned char q;
+ size_t ret = 0;
+
+ if (val >= 0) {
+ do {
+ q = val % 256;
+ ret++;
+ val /= 256;
+ } while(val);
+ if(q >= 128)
+ ret++;
+ } else {
+ val = ~val;
+ do {
+ q = ~(val % 256);
+ ret++;
+ val /= 256;
+ } while(val);
+ if(q < 128)
+ ret++;
+ }
+ return ret;
+}
+
+size_t
+_heim_len_int64 (int64_t val)
+{
+ unsigned char q;
+ size_t ret = 0;
+
+ if (val >= 0) {
+ do {
+ q = val % 256;
+ ret++;
+ val /= 256;
+ } while(val);
+ if(q >= 128)
+ ret++;
+ } else {
+ val = ~val;
+ do {
+ q = ~(val % 256);
+ ret++;
+ val /= 256;
+ } while(val);
+ if(q < 128)
+ ret++;
+ }
+ return ret;
+}
+
+static size_t
+len_oid (const heim_oid *oid)
+{
+ size_t ret = 1;
+ size_t n;
+
+ for (n = 2; n < oid->length; ++n) {
+ unsigned u = oid->components[n];
+
+ do {
+ ++ret;
+ u /= 128;
+ } while(u > 0);
+ }
+ return ret;
+}
+
+size_t ASN1CALL
+der_length_len (size_t len)
+{
+ if (len < 128)
+ return 1;
+ else {
+ int ret = 0;
+ do {
+ ++ret;
+ len /= 256;
+ } while (len);
+ return ret + 1;
+ }
+}
+
+size_t ASN1CALL
+der_length_tag(unsigned int tag)
+{
+ size_t len = 0;
+
+ if(tag <= 30)
+ return 1;
+ while(tag) {
+ tag /= 128;
+ len++;
+ }
+ return len + 1;
+}
+
+size_t ASN1CALL
+der_length_integer (const int *data)
+{
+ return _heim_len_int (*data);
+}
+
+size_t ASN1CALL
+der_length_integer64 (const int64_t *data)
+{
+ return _heim_len_int64 (*data);
+}
+
+size_t ASN1CALL
+der_length_unsigned (const unsigned *data)
+{
+ return _heim_len_unsigned(*data);
+}
+
+size_t ASN1CALL
+der_length_unsigned64 (const uint64_t *data)
+{
+ return _heim_len_unsigned64(*data);
+}
+
+size_t ASN1CALL
+der_length_enumerated (const unsigned *data)
+{
+ return _heim_len_int (*data);
+}
+
+size_t ASN1CALL
+der_length_general_string (const heim_general_string *data)
+{
+ return strlen(*data);
+}
+
+size_t ASN1CALL
+der_length_utf8string (const heim_utf8_string *data)
+{
+ return strlen(*data);
+}
+
+size_t ASN1CALL
+der_length_printable_string (const heim_printable_string *data)
+{
+ return data->length;
+}
+
+size_t ASN1CALL
+der_length_ia5_string (const heim_ia5_string *data)
+{
+ return data->length;
+}
+
+size_t ASN1CALL
+der_length_bmp_string (const heim_bmp_string *data)
+{
+ return data->length * 2;
+}
+
+size_t ASN1CALL
+der_length_universal_string (const heim_universal_string *data)
+{
+ return data->length * 4;
+}
+
+size_t ASN1CALL
+der_length_visible_string (const heim_visible_string *data)
+{
+ return strlen(*data);
+}
+
+size_t ASN1CALL
+der_length_octet_string (const heim_octet_string *k)
+{
+ return k->length;
+}
+
+size_t ASN1CALL
+der_length_heim_integer (const heim_integer *k)
+{
+ if (k->length == 0)
+ return 1;
+ if (k->negative && k->length == 1 && ((unsigned char *)k->data)[0] == 1)
+ return 1;
+ else if (k->negative)
+ return k->length + (((~(((unsigned char *)k->data)[0])) & 0x80) ? 0 : 1);
+ else
+ return k->length + ((((unsigned char *)k->data)[0] & 0x80) ? 1 : 0);
+}
+
+size_t ASN1CALL
+der_length_oid (const heim_oid *k)
+{
+ return len_oid (k);
+}
+
+size_t ASN1CALL
+der_length_generalized_time (const time_t *t)
+{
+ heim_octet_string k;
+ size_t ret;
+
+ _heim_time2generalizedtime (*t, &k, 1);
+ ret = k.length;
+ free(k.data);
+ return ret;
+}
+
+size_t ASN1CALL
+der_length_utctime (const time_t *t)
+{
+ heim_octet_string k;
+ size_t ret;
+
+ _heim_time2generalizedtime (*t, &k, 0);
+ ret = k.length;
+ free(k.data);
+ return ret;
+}
+
+size_t ASN1CALL
+der_length_boolean (const int *k)
+{
+ return 1;
+}
+
+size_t ASN1CALL
+der_length_bit_string (const heim_bit_string *k)
+{
+ return (k->length + 7) / 8 + 1;
+}
diff --git a/third_party/heimdal/lib/asn1/der_locl.h b/third_party/heimdal/lib/asn1/der_locl.h
new file mode 100644
index 0000000..a086e18
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/der_locl.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1997 - 2002, 2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id$ */
+
+#ifndef __DER_LOCL_H__
+#define __DER_LOCL_H__
+
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <time.h>
+#include <errno.h>
+#include <roken.h>
+
+#include <asn1-common.h>
+#include <asn1_err.h>
+#include <der.h>
+#include <der-private.h>
+#include "asn1-template.h"
+
+time_t _der_timegm (struct tm *);
+struct tm * _der_gmtime(time_t t, struct tm *);
+size_t _heim_len_unsigned (unsigned);
+size_t _heim_len_int (int);
+
+#endif /* __DER_LOCL_H__ */
diff --git a/third_party/heimdal/lib/asn1/der_print.c b/third_party/heimdal/lib/asn1/der_print.c
new file mode 100644
index 0000000..dada747
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/der_print.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2021 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+#include "hex.h"
+
+RCSID("$Id$");
+
+char * ASN1CALL
+der_print_general_string(const heim_general_string *str, int flags)
+{
+ return strdup(*str);
+}
+
+char * ASN1CALL
+der_print_boolean(const int *i, int flags)
+{
+ return *i ? strdup("true") : strdup("false");
+}
+
+char * ASN1CALL
+der_print_integer(const int *i, int flags)
+{
+ char *s = NULL;
+
+ if (asprintf(&s, "%d", *i) == -1 || s == NULL)
+ return NULL;
+ return s;
+}
+
+char * ASN1CALL
+der_print_integer64(const int64_t *i, int flags)
+{
+ char *s = NULL;
+
+ if (asprintf(&s, "%lld", (long long)*i) == -1 || s == NULL)
+ return NULL;
+ return s;
+}
+
+char * ASN1CALL
+der_print_unsigned(const unsigned *u, int flags)
+{
+ char *s = NULL;
+
+ if (asprintf(&s, "%u", *u) == -1 || s == NULL)
+ return NULL;
+ return s;
+}
+
+char * ASN1CALL
+der_print_unsigned64(const uint64_t *u, int flags)
+{
+ char *s = NULL;
+
+ if (asprintf(&s, "%llu", (long long)*u) == -1 || s == NULL)
+ return NULL;
+ return s;
+}
+
+char * ASN1CALL
+der_print_generalized_time(const time_t *t, int flags)
+{
+ struct tm tms;
+ char str[sizeof("1970-01-01T00:00:00Z")];
+
+#ifdef WIN32
+ if (gmtime_s(&tms, t) != 0 ||
+ strftime(str, sizeof(str), "%Y-%m-%dT%H:%M:%SZ", &tms) == 0)
+ return NULL;
+#else
+ if (strftime(str, sizeof(str), "%Y-%m-%dT%H:%M:%SZ", gmtime_r(t, &tms)) == 0)
+ return NULL;
+#endif
+ return strdup(str);
+}
+
+char * ASN1CALL
+der_print_utctime(const time_t *t, int flags)
+{
+ struct tm tms;
+ char str[sizeof("1970-01-01T00:00:00Z")];
+
+#ifdef WIN32
+ if (gmtime_s(&tms, t) != 0 ||
+ strftime(str, sizeof(str), "%Y-%m-%dT%H:%M:%SZ", &tms) == 0)
+ return NULL;
+#else
+ if (strftime(str, sizeof(str), "%Y-%m-%dT%H:%M:%SZ", gmtime_r(t, &tms)) == 0)
+ return NULL;
+#endif
+ return strdup(str);
+}
+
+
+char * ASN1CALL
+der_print_utf8string(const heim_utf8_string *str, int flags)
+{
+ return strdup(*str);
+}
+
+char * ASN1CALL
+der_print_printable_string(const heim_printable_string *str, int flags)
+{
+ return strndup(str->data, str->length);
+}
+
+char * ASN1CALL
+der_print_ia5_string(const heim_ia5_string *str, int flags)
+{
+ return strndup(str->data, str->length);
+}
+
+char * ASN1CALL
+der_print_bmp_string(const heim_bmp_string *k, int flags)
+{
+ return strdup("<BMPString-not-supported>");
+}
+
+char * ASN1CALL
+der_print_universal_string(const heim_universal_string *k, int flags)
+{
+ return strdup("<UniversalString-not-supported>");
+}
+
+char * ASN1CALL
+der_print_visible_string(const heim_visible_string *str, int flags)
+{
+ return strdup(*str);
+}
+
+char * ASN1CALL
+der_print_octet_string(const heim_octet_string *k, int flags)
+{
+ char *s = NULL;
+
+ (void) hex_encode(k->data, k->length, &s);
+ return s;
+}
+
+char * ASN1CALL
+der_print_heim_integer(const heim_integer *k, int flags)
+{
+ char *s = NULL;
+
+ (void) der_print_hex_heim_integer(k, &s);
+ return s;
+}
+
+char * ASN1CALL
+der_print_oid(const heim_oid *k, int flags)
+{
+ struct rk_strpool *r = NULL;
+ const char *sym = NULL;
+ char *s = NULL;
+ size_t i;
+
+ (void) der_print_heim_oid(k, '.', &s);
+
+ if (!s)
+ return NULL;
+ r = rk_strpoolprintf(r, "{\"_type\":\"OBJECT IDENTIFIER\","
+ "\"oid\":\"%s\","
+ "\"components\":[",
+ s);
+ free(s);
+ for (i = 0; i < k->length; i++)
+ r = rk_strpoolprintf(r, "%s%u", i ? "," : "", k->components[i]);
+ if (r)
+ r = rk_strpoolprintf(r, "]");
+ (void) der_find_heim_oid_by_oid(k, &sym);
+ if (sym && r) {
+ if ((s = strdup(sym))) {
+ for (i = 0; s[i]; i++)
+ if (s[i] == '_')
+ s[i] = '-';
+ }
+ r = rk_strpoolprintf(r, ",\"name\":\"%s\"", s ? s : sym);
+ free(s);
+ }
+ if (r)
+ r = rk_strpoolprintf(r, "}");
+ return rk_strpoolcollect(r);
+}
+
+char * ASN1CALL
+der_print_bit_string(const heim_bit_string *k, int flags)
+{
+ char *s2 = NULL;
+ char *s = NULL;
+
+ (void) hex_encode(k->data, k->length / 8, &s);
+ if (asprintf(&s2, "%llu:%s", (unsigned long long)k->length, s) == -1 || !s2)
+ s2 = NULL;
+ free(s);
+ return s2;
+}
diff --git a/third_party/heimdal/lib/asn1/der_put.c b/third_party/heimdal/lib/asn1/der_put.c
new file mode 100644
index 0000000..106d456
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/der_put.c
@@ -0,0 +1,717 @@
+/*
+ * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+
+RCSID("$Id$");
+
+/*
+ * All encoding functions take a pointer `p' to first position in
+ * which to write, from the right, `len' which means the maximum
+ * number of characters we are able to write. The function returns
+ * the number of characters written in `size' (if non-NULL).
+ * The return value is 0 or an error.
+ */
+
+int ASN1CALL
+der_put_unsigned (unsigned char *p, size_t len, const unsigned *v, size_t *size)
+{
+ unsigned char *base = p;
+ unsigned val = *v;
+
+ *size = 0;
+
+ if (val) {
+ while (len > 0 && val) {
+ *p-- = val % 256;
+ val /= 256;
+ --len;
+ }
+ if (val != 0)
+ return ASN1_OVERFLOW;
+ else {
+ if(p[1] >= 128) {
+ if(len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = 0;
+ }
+ *size = base - p;
+ return 0;
+ }
+ } else if (len < 1)
+ return ASN1_OVERFLOW;
+ else {
+ *p = 0;
+ *size = 1;
+ return 0;
+ }
+}
+
+int ASN1CALL
+der_put_unsigned64 (unsigned char *p, size_t len, const uint64_t *v, size_t *size)
+{
+ unsigned char *base = p;
+ uint64_t val = *v;
+
+ *size = 0;
+
+ if (val) {
+ while (len > 0 && val) {
+ *p-- = val % 256;
+ val /= 256;
+ --len;
+ }
+ if (val != 0)
+ return ASN1_OVERFLOW;
+ else {
+ if(p[1] >= 128) {
+ if(len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = 0;
+ }
+ *size = base - p;
+ return 0;
+ }
+ } else if (len < 1)
+ return ASN1_OVERFLOW;
+ else {
+ *p = 0;
+ *size = 1;
+ return 0;
+ }
+}
+
+int ASN1CALL
+der_put_integer (unsigned char *p, size_t len, const int *v, size_t *size)
+{
+ unsigned char *base = p;
+ int val = *v;
+
+ *size = 0;
+
+ if(val >= 0) {
+ do {
+ if(len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = val % 256;
+ len--;
+ val /= 256;
+ } while(val);
+ if(p[1] >= 128) {
+ if(len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = 0;
+ len--;
+ }
+ } else {
+ val = ~val;
+ do {
+ if(len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = ~(val % 256);
+ len--;
+ val /= 256;
+ } while(val);
+ if(p[1] < 128) {
+ if(len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = 0xff;
+ len--;
+ }
+ }
+ *size = base - p;
+ return 0;
+}
+
+int ASN1CALL
+der_put_integer64 (unsigned char *p, size_t len, const int64_t *v, size_t *size)
+{
+ unsigned char *base = p;
+ int64_t val = *v;
+
+ *size = 0;
+
+ if(val >= 0) {
+ do {
+ if(len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = val % 256;
+ len--;
+ val /= 256;
+ } while(val);
+ if(p[1] >= 128) {
+ if(len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = 0;
+ len--;
+ }
+ } else {
+ val = ~val;
+ do {
+ if(len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = ~(val % 256);
+ len--;
+ val /= 256;
+ } while(val);
+ if(p[1] < 128) {
+ if(len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = 0xff;
+ len--;
+ }
+ }
+ *size = base - p;
+ return 0;
+}
+
+
+int ASN1CALL
+der_put_length (unsigned char *p, size_t len, size_t val, size_t *size)
+{
+ if (size)
+ *size = 0;
+
+ if (len < 1)
+ return ASN1_OVERFLOW;
+
+ if (val < 128) {
+ *p = val;
+ if (size)
+ *size = 1;
+ } else {
+ size_t l = 0;
+
+ while(val > 0) {
+ if(len < 2)
+ return ASN1_OVERFLOW;
+ *p-- = val % 256;
+ val /= 256;
+ len--;
+ l++;
+ }
+ *p = 0x80 | l;
+ if(size)
+ *size = l + 1;
+ }
+ return 0;
+}
+
+int ASN1CALL
+der_put_boolean(unsigned char *p, size_t len, const int *data, size_t *size)
+{
+ *size = 0;
+
+ if(len < 1)
+ return ASN1_OVERFLOW;
+ if(*data != 0)
+ *p = 0xff;
+ else
+ *p = 0;
+ *size = 1;
+ return 0;
+}
+
+int ASN1CALL
+der_put_general_string (unsigned char *p, size_t len,
+ const heim_general_string *str, size_t *size)
+{
+ size_t slen;
+
+ assert(p != NULL && str != NULL && *str != NULL && size != NULL);
+ *size = 0;
+ slen = strlen(*str);
+ if (len < slen)
+ return ASN1_OVERFLOW;
+ p -= slen;
+ memcpy (p+1, *str, slen);
+ *size = slen;
+ return 0;
+}
+
+int ASN1CALL
+der_put_utf8string (unsigned char *p, size_t len,
+ const heim_utf8_string *str, size_t *size)
+{
+ return der_put_general_string(p, len, str, size);
+}
+
+int ASN1CALL
+der_put_printable_string (unsigned char *p, size_t len,
+ const heim_printable_string *str, size_t *size)
+{
+ return der_put_octet_string(p, len, str, size);
+}
+
+int ASN1CALL
+der_put_ia5_string (unsigned char *p, size_t len,
+ const heim_ia5_string *str, size_t *size)
+{
+ return der_put_octet_string(p, len, str, size);
+}
+
+int ASN1CALL
+der_put_bmp_string (unsigned char *p, size_t len,
+ const heim_bmp_string *data, size_t *size)
+{
+ size_t i;
+
+ assert(p != NULL && data != NULL);
+
+ if (size)
+ *size = 0;
+
+ if (len / 2 < data->length)
+ return ASN1_OVERFLOW;
+ p -= data->length * 2;
+ for (i = 0; i < data->length; i++) {
+ p[1] = (data->data[i] >> 8) & 0xff;
+ p[2] = data->data[i] & 0xff;
+ p += 2;
+ }
+ if (size) *size = data->length * 2;
+ return 0;
+}
+
+int ASN1CALL
+der_put_universal_string (unsigned char *p, size_t len,
+ const heim_universal_string *data, size_t *size)
+{
+ size_t i;
+
+ if (size)
+ *size = 0;
+
+ if (len / 4 < data->length)
+ return ASN1_OVERFLOW;
+ p -= data->length * 4;
+ for (i = 0; i < data->length; i++) {
+ p[1] = (data->data[i] >> 24) & 0xff;
+ p[2] = (data->data[i] >> 16) & 0xff;
+ p[3] = (data->data[i] >> 8) & 0xff;
+ p[4] = data->data[i] & 0xff;
+ p += 4;
+ }
+ if (size) *size = data->length * 4;
+ return 0;
+}
+
+int ASN1CALL
+der_put_visible_string (unsigned char *p, size_t len,
+ const heim_visible_string *str, size_t *size)
+{
+ return der_put_general_string(p, len, str, size);
+}
+
+int ASN1CALL
+der_put_octet_string (unsigned char *p, size_t len,
+ const heim_octet_string *data, size_t *size)
+{
+ assert(p != NULL && data != NULL && size != NULL);
+
+ *size = 0;
+ if (len < data->length)
+ return ASN1_OVERFLOW;
+ p -= data->length;
+ if (data->length)
+ memcpy(p+1, data->data, data->length);
+ *size = data->length;
+ return 0;
+}
+
+int ASN1CALL
+der_put_heim_integer (unsigned char *p, size_t len,
+ const heim_integer *data, size_t *size)
+{
+ unsigned char *buf;
+ int hibitset = 0;
+
+ assert(p != NULL);
+
+ if (size)
+ *size = 0;
+
+ if (data->length == 0) {
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = 0;
+ if (size)
+ *size = 1;
+ return 0;
+ }
+ if (len < data->length)
+ return ASN1_OVERFLOW;
+
+ assert(data->data != NULL);
+ buf = data->data;
+ len -= data->length;
+
+ if (data->negative) {
+ ssize_t i;
+ int carry;
+
+ /*
+ * We represent the parsed integer as a positive value with a
+ * negativity flag. But we need to put it on the wire as the shortest
+ * twos-complement byte sequence possible. So we're going to negate
+ * the number as go.
+ */
+ if (data->length == 1 && *(unsigned char *)data->data == 1) {
+ *(p--) = 0xff;
+ } else {
+ for (i = data->length - 1, carry = 1; i >= 0; i--) {
+ *p = buf[i] ^ 0xff;
+ if (carry)
+ carry = !++*p;
+ p--;
+ }
+ if (p[1] < 128) {
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = 0xff;
+ len--;
+ hibitset = 1;
+ }
+ }
+ } else {
+ p -= data->length;
+ memcpy(p + 1, buf, data->length);
+
+ if (p[1] >= 128) {
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ p[0] = 0;
+ len--;
+ hibitset = 1;
+ }
+ }
+ if (size)
+ *size = data->length + hibitset;
+ return 0;
+}
+
+int ASN1CALL
+der_put_generalized_time (unsigned char *p, size_t len,
+ const time_t *data, size_t *size)
+{
+ heim_octet_string k;
+ size_t l;
+ int e;
+
+ e = _heim_time2generalizedtime (*data, &k, 1);
+ if (e)
+ return e;
+ e = der_put_octet_string(p, len, &k, &l);
+ free(k.data);
+ if(e)
+ return e;
+ if(size)
+ *size = l;
+ return 0;
+}
+
+int ASN1CALL
+der_put_utctime (unsigned char *p, size_t len,
+ const time_t *data, size_t *size)
+{
+ heim_octet_string k;
+ size_t l;
+ int e;
+
+ e = _heim_time2generalizedtime (*data, &k, 0);
+ if (e)
+ return e;
+ e = der_put_octet_string(p, len, &k, &l);
+ free(k.data);
+ if(e)
+ return e;
+ if(size)
+ *size = l;
+ return 0;
+}
+
+int ASN1CALL
+der_put_oid (unsigned char *p, size_t len,
+ const heim_oid *data, size_t *size)
+{
+ unsigned char *base = p;
+ size_t n;
+
+ for (n = data->length - 1; n >= 2; --n) {
+ unsigned u = data->components[n];
+
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = u % 128;
+ u /= 128;
+ --len;
+ while (u > 0) {
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = 128 + u % 128;
+ u /= 128;
+ --len;
+ }
+ }
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = 40 * data->components[0] + data->components[1];
+ *size = base - p;
+ return 0;
+}
+
+/*
+ * Output a copy of the DER TLV at `p' with a different outermost tag.
+ *
+ * This is used in the implementation of IMPLICIT tags in generated decoder
+ * functions.
+ */
+int ASN1CALL
+der_replace_tag(const unsigned char *p, size_t len,
+ unsigned char **out, size_t *outlen,
+ Der_class class, Der_type type,
+ unsigned int tag)
+{
+ Der_class found_class;
+ Der_type found_type;
+ unsigned int found_tag;
+ size_t payload_len, l, tag_len, len_len;
+ int e;
+
+ assert(p != NULL && out != NULL && outlen != NULL);
+
+ e = der_get_tag(p, len, &found_class, &found_type, &found_tag, &l);
+ if (e)
+ return e;
+ if (found_type != type)
+ return ASN1_TYPE_MISMATCH;
+ /* We don't care what found_class and found_tag are though */
+ tag_len = der_length_tag(tag);
+ p += l;
+ len -= l;
+ e = der_get_length(p, len, &payload_len, &len_len);
+ if (e)
+ return e;
+ if (payload_len > len)
+ return ASN1_OVERFLOW;
+ /*
+ * `p' now points at the payload; `*out' + the length of the tag points at
+ * where we should copy the DER length and the payload.
+ */
+ if ((*out = malloc(*outlen = tag_len + len_len + payload_len)) == NULL)
+ return ENOMEM;
+ memcpy(*out + tag_len, p, len_len + payload_len);
+
+ /* Put the new tag */
+ e = der_put_tag(*out + tag_len - 1, tag_len, class, type, tag, &l);
+ if (e)
+ return e;
+ if (l != tag_len)
+ return ASN1_OVERFLOW;
+ return 0;
+}
+
+#if 0
+int ASN1CALL
+der_encode_implicit(unsigned char *p, size_t len,
+ asn1_generic_encoder_f encoder,
+ void *obj, size_t *size,
+ Der_type type,
+ unsigned int ttag, Der_class iclass, unsigned int itag)
+{
+ size_t ttaglen = der_length_tag(ttag);
+ size_t itaglen = der_length_tag(itag);
+ size_t l;
+ unsigned char *p2;
+ int e;
+
+ assert(p != NULL && size != NULL);
+
+ /* Attempt to encode in place */
+ e = encoder(p, len, obj, size);
+ if (e == 0) {
+ /* Fits! Rewrite tag, adjust reported size. */
+ e = der_put_tag(p + ttaglen - 1, itaglen, iclass, type, itag, &l);
+ if (e == 0) {
+ (*size) -= ttaglen;
+ (*size) += itaglen;
+ }
+ return e;
+ }
+ if (e != ASN1_OVERFLOW || itaglen <= ttaglen)
+ return e;
+
+ /*
+ * Did not fit because ttaglen > itaglen and this was the last / only thing
+ * being encoded in a buffer of just the right size.
+ */
+ if ((p2 = malloc(len + ttaglen - itaglen)) == NULL)
+ e = ENOMEM;
+ if (e == 0)
+ e = encoder(p2 + len + ttaglen - itaglen - 1, len + ttaglen - itaglen,
+ obj, size);
+ if (e == 0)
+ e = der_put_tag(p2 + ttaglen - 1, itaglen, iclass, type, itag, &l);
+ if (e == 0) {
+ (*size) -= ttaglen;
+ (*size) += itaglen;
+ memcpy(p - *size, p2 + ttaglen - itaglen, *size);
+ }
+ free(p2);
+ return e;
+}
+#endif
+
+int ASN1CALL
+der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type,
+ unsigned int tag, size_t *size)
+{
+ if (tag <= 30) {
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ *p = MAKE_TAG(class, type, tag);
+ *size = 1;
+ } else {
+ size_t ret = 0;
+ unsigned int continuation = 0;
+
+ do {
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = tag % 128 | continuation;
+ len--;
+ ret++;
+ tag /= 128;
+ continuation = 0x80;
+ } while(tag > 0);
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = MAKE_TAG(class, type, 0x1f);
+ ret++;
+ *size = ret;
+ }
+ return 0;
+}
+
+int ASN1CALL
+der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val,
+ Der_class class, Der_type type,
+ unsigned int tag, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+
+ e = der_put_length (p, len, len_val, &l);
+ if(e)
+ return e;
+ p -= l;
+ len -= l;
+ ret += l;
+ e = der_put_tag (p, len, class, type, tag, &l);
+ if(e)
+ return e;
+
+ ret += l;
+ *size = ret;
+ return 0;
+}
+
+int
+_heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep)
+{
+ struct tm tm;
+ const size_t len = gtimep ? 15 : 13;
+ int bytes;
+
+ s->data = NULL;
+ s->length = 0;
+ if (_der_gmtime(t, &tm) == NULL)
+ return ASN1_BAD_TIMEFORMAT;
+ s->data = malloc(len + 1);
+ if (s->data == NULL)
+ return ENOMEM;
+ s->length = len;
+ if (gtimep)
+ bytes = snprintf(s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ",
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+ else
+ bytes = snprintf(s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ",
+ tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+ if (bytes > len)
+ abort();
+
+ return 0;
+}
+
+int ASN1CALL
+der_put_bit_string (unsigned char *p, size_t len,
+ const heim_bit_string *data, size_t *size)
+{
+ size_t data_size;
+
+ assert(p != NULL && data != NULL && size != NULL);
+
+ *size = 0;
+ data_size = (data->length + 7) / 8;
+ if (len < data_size + 1)
+ return ASN1_OVERFLOW;
+ p -= data_size + 1;
+
+ memcpy (p+2, data->data, data_size);
+ if (data->length && (data->length % 8) != 0)
+ p[1] = 8 - (data->length % 8);
+ else
+ p[1] = 0;
+ *size = data_size + 1;
+ return 0;
+}
+
+int
+_heim_der_set_sort(const void *a1, const void *a2)
+{
+ const heim_octet_string *s1, *s2;
+ int ret;
+
+ assert(a1 != NULL && a2 != NULL);
+ s1 = a1;
+ s2 = a2;
+ ret = memcmp(s1->data, s2->data,
+ s1->length < s2->length ? s1->length : s2->length);
+ if (ret != 0)
+ return ret;
+ return (int)(s1->length - s2->length);
+}
diff --git a/third_party/heimdal/lib/asn1/digest.asn1 b/third_party/heimdal/lib/asn1/digest.asn1
new file mode 100644
index 0000000..7a73993
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/digest.asn1
@@ -0,0 +1,179 @@
+-- $Id$
+
+DIGEST DEFINITIONS ::=
+BEGIN
+
+IMPORTS EncryptedData, Principal FROM krb5;
+
+DigestTypes ::= BIT STRING {
+ ntlm-v1(0),
+ ntlm-v1-session(1),
+ ntlm-v2(2),
+ digest-md5(3),
+ chap-md5(4),
+ ms-chap-v2(5)
+}
+
+DigestInit ::= SEQUENCE {
+ type UTF8String, -- http, sasl, chap, cram-md5 --
+ channel [0] SEQUENCE {
+ cb-type UTF8String,
+ cb-binding UTF8String
+ } OPTIONAL,
+ hostname [1] UTF8String OPTIONAL -- for chap/cram-md5
+}
+
+DigestInitReply ::= SEQUENCE {
+ nonce UTF8String, -- service nonce/challenge
+ opaque UTF8String, -- server state
+ identifier [0] UTF8String OPTIONAL
+}
+
+
+DigestRequest ::= SEQUENCE {
+ type UTF8String, -- http, sasl-md5, chap, cram-md5 --
+ digest UTF8String, -- http:md5/md5-sess sasl:clear/int/conf --
+ username UTF8String, -- username user used
+ responseData UTF8String, -- client response
+ authid [0] UTF8String OPTIONAL,
+ authentication-user [1] Principal OPTIONAL, -- principal to get key from
+ realm [2] UTF8String OPTIONAL,
+ method [3] UTF8String OPTIONAL,
+ uri [4] UTF8String OPTIONAL,
+ serverNonce UTF8String, -- same as "DigestInitReply.nonce"
+ clientNonce [5] UTF8String OPTIONAL,
+ nonceCount [6] UTF8String OPTIONAL,
+ qop [7] UTF8String OPTIONAL,
+ identifier [8] UTF8String OPTIONAL,
+ hostname [9] UTF8String OPTIONAL,
+ opaque UTF8String -- same as "DigestInitReply.opaque"
+}
+-- opaque = hex(cksum(type|serverNonce|identifier|hostname,digest-key))
+-- serverNonce = hex(time[4bytes]random[12bytes])(-cbType:cbBinding)
+
+
+DigestError ::= SEQUENCE {
+ reason UTF8String,
+ code INTEGER (-2147483648..2147483647)
+}
+
+DigestResponse ::= SEQUENCE {
+ success BOOLEAN,
+ rsp [0] UTF8String OPTIONAL,
+ tickets [1] SEQUENCE OF OCTET STRING OPTIONAL,
+ channel [2] SEQUENCE {
+ cb-type UTF8String,
+ cb-binding UTF8String
+ } OPTIONAL,
+ session-key [3] OCTET STRING OPTIONAL
+}
+
+NTLMInit ::= SEQUENCE {
+ flags [0] INTEGER (0..4294967295),
+ hostname [1] UTF8String OPTIONAL,
+ domain [1] UTF8String OPTIONAL
+}
+
+NTLMInitReply ::= SEQUENCE {
+ flags [0] INTEGER (0..4294967295),
+ opaque [1] OCTET STRING,
+ targetname [2] UTF8String,
+ challenge [3] OCTET STRING,
+ targetinfo [4] OCTET STRING OPTIONAL
+}
+
+NTLMRequest ::= SEQUENCE {
+ flags [0] INTEGER (0..4294967295),
+ opaque [1] OCTET STRING,
+ username [2] UTF8String,
+ targetname [3] UTF8String,
+ targetinfo [4] OCTET STRING OPTIONAL,
+ lm [5] OCTET STRING,
+ ntlm [6] OCTET STRING,
+ sessionkey [7] OCTET STRING OPTIONAL
+}
+
+NTLMResponse ::= SEQUENCE {
+ success [0] BOOLEAN,
+ flags [1] INTEGER (0..4294967295),
+ sessionkey [2] OCTET STRING OPTIONAL,
+ tickets [3] SEQUENCE OF OCTET STRING OPTIONAL
+}
+
+NTLMRequest2 ::= SEQUENCE {
+ loginUserName [0] UTF8String,
+ loginDomainName [1] UTF8String,
+ flags [2] INTEGER (0..4294967295),
+ lmchallenge [3] OCTET STRING SIZE (8),
+ ntChallengeResponce [4] OCTET STRING,
+ lmChallengeResponce [5] OCTET STRING
+}
+
+NTLMReply ::= SEQUENCE {
+ success [0] BOOLEAN,
+ flags [1] INTEGER (0..4294967295),
+ sessionkey [2] OCTET STRING OPTIONAL
+}
+
+DigestReqInner ::= CHOICE {
+ init [0] DigestInit,
+ digestRequest [1] DigestRequest,
+ ntlmInit [2] NTLMInit,
+ ntlmRequest [3] NTLMRequest,
+ supportedMechs [4] NULL
+}
+
+DigestREQ ::= [APPLICATION 128] SEQUENCE {
+ apReq [0] OCTET STRING,
+ innerReq [1] EncryptedData
+}
+
+DigestRepInner ::= CHOICE {
+ error [0] DigestError,
+ initReply [1] DigestInitReply,
+ response [2] DigestResponse,
+ ntlmInitReply [3] NTLMInitReply,
+ ntlmResponse [4] NTLMResponse,
+ supportedMechs [5] DigestTypes,
+ ...
+}
+
+DigestREP ::= [APPLICATION 129] SEQUENCE {
+ apRep [0] OCTET STRING,
+ innerRep [1] EncryptedData
+}
+
+
+-- HTTP
+
+-- md5
+-- A1 = unq(username-value) ":" unq(realm-value) ":" passwd
+-- md5-sess
+-- A1 = HEX(H(unq(username-value) ":" unq(realm-value) ":" passwd ) ":" unq(nonce-value) ":" unq(cnonce-value))
+
+-- qop == auth
+-- A2 = Method ":" digest-uri-value
+-- qop == auth-int
+-- A2 = Method ":" digest-uri-value ":" H(entity-body)
+
+-- request-digest = HEX(KD(HEX(H(A1)),
+-- unq(nonce-value) ":" nc-value ":" unq(cnonce-value) ":" unq(qop-value) ":" HEX(H(A2))))
+-- no "qop"
+-- request-digest = HEX(KD(HEX(H(A1)), unq(nonce-value) ":" HEX(H(A2))))
+
+
+-- SASL:
+-- SS = H( { unq(username-value), ":", unq(realm-value), ":", password } )
+-- A1 = { SS, ":", unq(nonce-value), ":", unq(cnonce-value) }
+-- A1 = { SS, ":", unq(nonce-value), ":", unq(cnonce-value), ":", unq(authzid-value) }
+
+-- A2 = "AUTHENTICATE:", ":", digest-uri-value
+-- qop == auth-int,auth-conf
+-- A2 = "AUTHENTICATE:", ":", digest-uri-value, ":00000000000000000000000000000000"
+
+-- response-value = HEX( KD ( HEX(H(A1)),
+-- { unq(nonce-value), ":" nc-value, ":",
+-- unq(cnonce-value), ":", qop-value, ":",
+-- HEX(H(A2)) }))
+
+END
diff --git a/third_party/heimdal/lib/asn1/extra.c b/third_party/heimdal/lib/asn1/extra.c
new file mode 100644
index 0000000..253ac5a
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/extra.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2003 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+#include "heim_asn1.h"
+#include <vis.h>
+#include <vis-extras.h>
+
+RCSID("$Id$");
+
+int ASN1CALL
+encode_heim_any(unsigned char *p, size_t len,
+ const heim_any *data, size_t *size)
+{
+ return der_put_octet_string (p, len, data, size);
+}
+
+int ASN1CALL
+decode_heim_any(const unsigned char *p, size_t len,
+ heim_any *data, size_t *size)
+{
+ size_t len_len, length, l;
+ Der_class thisclass;
+ Der_type thistype;
+ unsigned int thistag;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+
+ e = der_get_tag (p, len, &thisclass, &thistype, &thistag, &l);
+ if (e) return e;
+ if (l > len)
+ return ASN1_OVERFLOW;
+ e = der_get_length(p + l, len - l, &length, &len_len);
+ if (e) return e;
+ if (length == ASN1_INDEFINITE) {
+ if (len < len_len + l)
+ return ASN1_OVERFLOW;
+ length = len - (len_len + l);
+ } else {
+ if (len < length + len_len + l)
+ return ASN1_OVERFLOW;
+ }
+
+ data->data = malloc(length + len_len + l);
+ if (data->data == NULL)
+ return ENOMEM;
+ data->length = length + len_len + l;
+ memcpy(data->data, p, length + len_len + l);
+
+ if (size)
+ *size = length + len_len + l;
+
+ return 0;
+}
+
+void ASN1CALL
+free_heim_any(heim_any *data)
+{
+ der_free_octet_string(data);
+}
+
+char * ASN1CALL
+print_heim_any(const heim_any *data, int flags)
+{
+ char *s2 = NULL;
+ char *s = der_print_octet_string(data, 0);
+ int r = -1;
+
+ (void)flags;
+ if (s)
+ r = rk_strasvis(&s2, s, VIS_CSTYLE|VIS_TAB|VIS_NL, "\"");
+ free(s);
+ s = NULL;
+ if (r > -1)
+ (void) asprintf(&s, "\"%s\"", s2);
+ free(s2);
+ return s;
+}
+
+size_t ASN1CALL
+length_heim_any(const heim_any *data)
+{
+ return data->length;
+}
+
+int ASN1CALL
+copy_heim_any(const heim_any *from, heim_any *to)
+{
+ return der_copy_octet_string(from, to);
+}
+
+int ASN1CALL
+encode_HEIM_ANY(unsigned char *p, size_t len,
+ const heim_any *data, size_t *size)
+{
+ return encode_heim_any(p, len, data, size);
+}
+
+int ASN1CALL
+decode_HEIM_ANY(const unsigned char *p, size_t len,
+ heim_any *data, size_t *size)
+{
+ return decode_heim_any(p, len, data, size);
+}
+
+void ASN1CALL
+free_HEIM_ANY(heim_any *data)
+{
+ der_free_octet_string(data);
+}
+
+char * ASN1CALL
+print_HEIM_ANY(const heim_any *data, int flags)
+{
+ char *s2 = NULL;
+ char *s = der_print_octet_string(data, 0);
+ int r = -1;
+
+ (void)flags;
+ if (s)
+ r = rk_strasvis(&s2, s, VIS_CSTYLE|VIS_TAB|VIS_NL, "\"");
+ free(s);
+ s = NULL;
+ if (r > -1)
+ (void) asprintf(&s, "\"%s\"", s2);
+ free(s2);
+ return s;
+}
+
+size_t ASN1CALL
+length_HEIM_ANY(const heim_any *data)
+{
+ return data->length;
+}
+
+int ASN1CALL
+copy_HEIM_ANY(const heim_any *from, heim_any *to)
+{
+ return der_copy_octet_string(from, to);
+}
+
+int ASN1CALL
+encode_heim_any_set(unsigned char *p, size_t len,
+ const heim_any_set *data, size_t *size)
+{
+ return der_put_octet_string (p, len, data, size);
+}
+
+int ASN1CALL
+decode_heim_any_set(const unsigned char *p, size_t len,
+ heim_any_set *data, size_t *size)
+{
+ return der_get_octet_string(p, len, data, size);
+}
+
+void ASN1CALL
+free_heim_any_set(heim_any_set *data)
+{
+ der_free_octet_string(data);
+}
+
+char * ASN1CALL
+print_heim_any_set(const heim_any_set *data, int flags)
+{
+ char *s2 = NULL;
+ char *s = der_print_octet_string(data, 0);
+ int r = -1;
+
+ (void)flags;
+ if (s)
+ r = rk_strasvis(&s2, s, VIS_CSTYLE|VIS_TAB|VIS_NL, "\"");
+ free(s);
+ s = NULL;
+ if (r > -1)
+ (void) asprintf(&s, "\"%s\"", s2);
+ free(s2);
+ return s;
+}
+
+size_t ASN1CALL
+length_heim_any_set(const heim_any *data)
+{
+ return data->length;
+}
+
+int ASN1CALL
+copy_heim_any_set(const heim_any_set *from, heim_any_set *to)
+{
+ return der_copy_octet_string(from, to);
+}
+
+int ASN1CALL
+heim_any_cmp(const heim_any_set *p, const heim_any_set *q)
+{
+ return der_heim_octet_string_cmp(p, q);
+}
+
+int ASN1CALL
+encode_HEIM_ANY_SET(unsigned char *p, size_t len,
+ const heim_any_set *data, size_t *size)
+{
+ return encode_heim_any_set(p, len, data, size);
+}
+
+int ASN1CALL
+decode_HEIM_ANY_SET(const unsigned char *p, size_t len,
+ heim_any_set *data, size_t *size)
+{
+ return decode_heim_any_set(p, len, data, size);
+}
+
+void ASN1CALL
+free_HEIM_ANY_SET(heim_any_set *data)
+{
+ der_free_octet_string(data);
+}
+
+char * ASN1CALL
+print_HEIM_ANY_SET(const heim_any_set *data, int flags)
+{
+ char *s2 = NULL;
+ char *s = der_print_octet_string(data, 0);
+ int r = -1;
+
+ (void)flags;
+ if (s)
+ r = rk_strasvis(&s2, s, VIS_CSTYLE|VIS_TAB|VIS_NL, "\"");
+ free(s);
+ s = NULL;
+ if (r > -1)
+ (void) asprintf(&s, "\"%s\"", s2);
+ free(s2);
+ return s;
+}
+
+size_t ASN1CALL
+length_HEIM_ANY_SET(const heim_any *data)
+{
+ return data->length;
+}
+
+int ASN1CALL
+copy_HEIM_ANY_SET(const heim_any_set *from, heim_any_set *to)
+{
+ return der_copy_octet_string(from, to);
+}
+
+int ASN1CALL
+HEIM_ANY_cmp(const heim_any_set *p, const heim_any_set *q)
+{
+ return der_heim_octet_string_cmp(p, q);
+}
diff --git a/third_party/heimdal/lib/asn1/fuzz-inputs/KrbFastArmoredReq b/third_party/heimdal/lib/asn1/fuzz-inputs/KrbFastArmoredReq
new file mode 100644
index 0000000..21ac360
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/fuzz-inputs/KrbFastArmoredReq
Binary files differ
diff --git a/third_party/heimdal/lib/asn1/fuzz-inputs/minimal-ek.crt b/third_party/heimdal/lib/asn1/fuzz-inputs/minimal-ek.crt
new file mode 100644
index 0000000..7e9bc70
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/fuzz-inputs/minimal-ek.crt
Binary files differ
diff --git a/third_party/heimdal/lib/asn1/fuzz-inputs/x690sample.der b/third_party/heimdal/lib/asn1/fuzz-inputs/x690sample.der
new file mode 100644
index 0000000..ec1c2c2
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/fuzz-inputs/x690sample.der
@@ -0,0 +1,5 @@
+`aJohnPSmith
+DirectorB3
+C19710917aMaryTSmithB1aRalphTSmith
+C195711111aSusanBSmith
+C19590717 \ No newline at end of file
diff --git a/third_party/heimdal/lib/asn1/fuzzer.c b/third_party/heimdal/lib/asn1/fuzzer.c
new file mode 100644
index 0000000..527f7e9
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/fuzzer.c
@@ -0,0 +1,742 @@
+/*
+ * Copyright (c) 2009 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 - 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+#include <com_err.h>
+
+enum trigger_method { FOFF, FRANDOM, FLINEAR, FLINEAR_SIZE };
+
+#ifdef ASN1_FUZZER
+static enum trigger_method method = FOFF;
+
+/* FLINEAR */
+static unsigned long fnum, fcur, fsize;
+#endif
+
+int
+asn1_fuzzer_method(const char *mode)
+{
+#ifdef ASN1_FUZZER
+ if (mode == NULL || strcasecmp(mode, "off") == 0) {
+ method = FOFF;
+ } else if (strcasecmp(mode, "random") == 0) {
+ method = FRANDOM;
+ } else if (strcasecmp(mode, "linear") == 0) {
+ method = FLINEAR;
+ } else if (strcasecmp(mode, "linear-size") == 0) {
+ method = FLINEAR_SIZE;
+ } else
+ return 1;
+ return 0;
+#else
+ return 1;
+#endif
+}
+
+void
+asn1_fuzzer_reset(void)
+{
+#ifdef ASN1_FUZZER
+ fcur = 0;
+ fsize = 0;
+ fnum = 0;
+#endif
+}
+
+void
+asn1_fuzzer_next(void)
+{
+#ifdef ASN1_FUZZER
+ fcur = 0;
+ fsize = 0;
+ fnum++;
+#endif
+}
+
+int
+asn1_fuzzer_done(void)
+{
+#ifndef ASN1_FUZZER
+ abort();
+#else
+ /* since code paths */
+ return (fnum > 10000);
+#endif
+}
+
+#ifdef ASN1_FUZZER
+
+static int
+fuzzer_trigger(unsigned int chance)
+{
+ switch(method) {
+ case FOFF:
+ return 0;
+ case FRANDOM:
+ if ((rk_random() % chance) != 1)
+ return 0;
+ return 1;
+ case FLINEAR:
+ if (fnum == fcur++)
+ return 1;
+ return 0;
+ case FLINEAR_SIZE:
+ return 0;
+ }
+ return 0;
+}
+
+static int
+fuzzer_size_trigger(unsigned long *cur)
+{
+ if (method != FLINEAR_SIZE)
+ return 0;
+ if (fnum == (*cur)++)
+ return 1;
+ return 0;
+}
+
+static size_t
+fuzzer_length_len (size_t len)
+{
+ if (fuzzer_size_trigger(&fsize)) {
+ len = 0;
+ } else if (fuzzer_size_trigger(&fsize)) {
+ len = 129;
+ } else if (fuzzer_size_trigger(&fsize)) {
+ len = 0xffff;
+ }
+
+ if (len < 128)
+ return 1;
+ else {
+ int ret = 0;
+ do {
+ ++ret;
+ len /= 256;
+ } while (len);
+ return ret + 1;
+ }
+}
+
+static int
+fuzzer_put_length (unsigned char *p, size_t len, size_t val, size_t *size)
+{
+ if (len < 1)
+ return ASN1_OVERFLOW;
+
+ if (fuzzer_size_trigger(&fcur)) {
+ val = 0;
+ } else if (fuzzer_size_trigger(&fcur)) {
+ val = 129;
+ } else if (fuzzer_size_trigger(&fcur)) {
+ val = 0xffff;
+ }
+
+ if (val < 128) {
+ *p = val;
+ *size = 1;
+ } else {
+ size_t l = 0;
+
+ while(val > 0) {
+ if(len < 2)
+ return ASN1_OVERFLOW;
+ *p-- = val % 256;
+ val /= 256;
+ len--;
+ l++;
+ }
+ *p = 0x80 | l;
+ if(size)
+ *size = l + 1;
+ }
+ return 0;
+}
+
+static int
+fuzzer_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type,
+ unsigned int tag, size_t *size)
+{
+ unsigned fcont = 0;
+
+ if (tag <= 30) {
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ if (fuzzer_trigger(100))
+ *p = MAKE_TAG(class, type, 0x1f);
+ else
+ *p = MAKE_TAG(class, type, tag);
+ *size = 1;
+ } else {
+ size_t ret = 0;
+ unsigned int continuation = 0;
+
+ do {
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = tag % 128 | continuation;
+ len--;
+ ret++;
+ tag /= 128;
+ continuation = 0x80;
+ } while(tag > 0);
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ if (fuzzer_trigger(100))
+ *p-- = MAKE_TAG(class, type, 0);
+ else
+ *p-- = MAKE_TAG(class, type, 0x1f);
+ ret++;
+ *size = ret;
+ }
+ return 0;
+}
+
+static int
+fuzzer_put_length_and_tag (unsigned char *p, size_t len, size_t len_val,
+ Der_class class, Der_type type,
+ unsigned int tag, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+
+ e = fuzzer_put_length (p, len, len_val, &l);
+ if(e)
+ return e;
+ p -= l;
+ len -= l;
+ ret += l;
+ e = fuzzer_put_tag (p, len, class, type, tag, &l);
+ if(e)
+ return e;
+
+ ret += l;
+ *size = ret;
+ return 0;
+}
+
+static int
+fuzzer_put_general_string (unsigned char *p, size_t len,
+ const heim_general_string *str, size_t *size)
+{
+ size_t slen = strlen(*str);
+
+ if (len < slen)
+ return ASN1_OVERFLOW;
+ p -= slen;
+ if (slen >= 2 && fuzzer_trigger(100)) {
+ memcpy(p+1, *str, slen);
+ memcpy(p+1, "%s", 2);
+ } else if (slen >= 2 && fuzzer_trigger(100)) {
+ memcpy(p+1, *str, slen);
+ memcpy(p+1, "%n", 2);
+ } else if (slen >= 4 && fuzzer_trigger(100)) {
+ memcpy(p+1, *str, slen);
+ memcpy(p+1, "%10n", 4);
+ } else if (slen >= 10 && fuzzer_trigger(100)) {
+ memcpy(p+1, *str, slen);
+ memcpy(p+1, "%n%n%n%n%n", 10);
+ } else if (slen >= 10 && fuzzer_trigger(100)) {
+ memcpy(p+1, *str, slen);
+ memcpy(p+1, "%n%p%s%d%x", 10);
+ } else if (slen >= 7 && fuzzer_trigger(100)) {
+ memcpy(p+1, *str, slen);
+ memcpy(p+1, "%.1024d", 7);
+ } else if (slen >= 7 && fuzzer_trigger(100)) {
+ memcpy(p+1, *str, slen);
+ memcpy(p+1, "%.2049d", 7);
+ } else if (fuzzer_trigger(100)) {
+ memset(p+1, 0, slen);
+ } else if (fuzzer_trigger(100)) {
+ memset(p+1, 0xff, slen);
+ } else if (fuzzer_trigger(100)) {
+ memset(p+1, 'A', slen);
+ } else {
+ memcpy(p+1, *str, slen);
+ }
+ *size = slen;
+ return 0;
+}
+
+
+struct asn1_type_func fuzzerprim[A1T_NUM_ENTRY] = {
+#define fuzel(name, type) { \
+ (asn1_type_encode)fuzzer_put_##name, \
+ (asn1_type_decode)der_get_##name, \
+ (asn1_type_length)der_length_##name, \
+ (asn1_type_copy)der_copy_##name, \
+ (asn1_type_release)der_free_##name, \
+ sizeof(type) \
+ }
+#define el(name, type) { \
+ (asn1_type_encode)der_put_##name, \
+ (asn1_type_decode)der_get_##name, \
+ (asn1_type_length)der_length_##name, \
+ (asn1_type_copy)der_copy_##name, \
+ (asn1_type_release)der_free_##name, \
+ sizeof(type) \
+ }
+#define elber(name, type) { \
+ (asn1_type_encode)der_put_##name, \
+ (asn1_type_decode)der_get_##name##_ber, \
+ (asn1_type_length)der_length_##name, \
+ (asn1_type_copy)der_copy_##name, \
+ (asn1_type_release)der_free_##name, \
+ sizeof(type) \
+ }
+ el(integer, int),
+ el(integer64, int64_t),
+ el(heim_integer, heim_integer),
+ el(integer, int),
+ el(unsigned, unsigned),
+ el(uninteger64, uint64_t),
+ fuzel(general_string, heim_general_string),
+ el(octet_string, heim_octet_string),
+ elber(octet_string, heim_octet_string),
+ el(ia5_string, heim_ia5_string),
+ el(bmp_string, heim_bmp_string),
+ el(universal_string, heim_universal_string),
+ el(printable_string, heim_printable_string),
+ el(visible_string, heim_visible_string),
+ el(utf8string, heim_utf8_string),
+ el(generalized_time, time_t),
+ el(utctime, time_t),
+ el(bit_string, heim_bit_string),
+ { (asn1_type_encode)der_put_boolean, (asn1_type_decode)der_get_boolean,
+ (asn1_type_length)der_length_boolean, (asn1_type_copy)der_copy_integer,
+ (asn1_type_release)der_free_integer, sizeof(int)
+ },
+ el(oid, heim_oid),
+ el(general_string, heim_general_string),
+#undef fuzel
+#undef el
+#undef elber
+};
+
+
+
+int
+_asn1_encode_fuzzer(const struct asn1_template *t,
+ unsigned char *p, size_t len,
+ const void *data, size_t *size)
+{
+ size_t elements = A1_HEADER_LEN(t);
+ int ret = 0;
+ size_t oldlen = len;
+
+ t += A1_HEADER_LEN(t);
+
+ while (elements) {
+ switch (t->tt & A1_OP_MASK) {
+ case A1_OP_TYPE:
+ case A1_OP_TYPE_EXTERN: {
+ size_t newsize;
+ const void *el = DPOC(data, t->offset);
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ void **pel = (void **)el;
+ if (*pel == NULL)
+ break;
+ el = *pel;
+ }
+
+ if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
+ ret = _asn1_encode_fuzzer(t->ptr, p, len, el, &newsize);
+ } else {
+ const struct asn1_type_func *f = t->ptr;
+ ret = (f->encode)(p, len, el, &newsize);
+ }
+
+ if (ret)
+ return ret;
+ p -= newsize; len -= newsize;
+
+ break;
+ }
+ case A1_OP_TAG: {
+ const void *olddata = data;
+ size_t l, datalen;
+
+ data = DPOC(data, t->offset);
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ void **el = (void **)data;
+ if (*el == NULL) {
+ data = olddata;
+ break;
+ }
+ data = *el;
+ }
+
+ ret = _asn1_encode_fuzzer(t->ptr, p, len, data, &datalen);
+ if (ret)
+ return ret;
+
+ len -= datalen; p -= datalen;
+
+ ret = fuzzer_put_length_and_tag(p, len, datalen,
+ A1_TAG_CLASS(t->tt),
+ A1_TAG_TYPE(t->tt),
+ A1_TAG_TAG(t->tt), &l);
+ if (ret)
+ return ret;
+
+ p -= l; len -= l;
+
+ data = olddata;
+
+ break;
+ }
+ case A1_OP_PARSE: {
+ unsigned int type = A1_PARSE_TYPE(t->tt);
+ size_t newsize;
+ const void *el = DPOC(data, t->offset);
+
+ if (type > sizeof(fuzzerprim)/sizeof(fuzzerprim[0])) {
+ ABORT_ON_ERROR();
+ return ASN1_PARSE_ERROR;
+ }
+
+ ret = (fuzzerprim[type].encode)(p, len, el, &newsize);
+ if (ret)
+ return ret;
+ p -= newsize; len -= newsize;
+
+ break;
+ }
+ case A1_OP_SETOF: {
+ const struct template_of *el = DPOC(data, t->offset);
+ size_t ellen = _asn1_sizeofType(t->ptr);
+ heim_octet_string *val;
+ unsigned char *elptr = el->val;
+ size_t i, totallen;
+
+ if (el->len == 0)
+ break;
+
+ if (el->len > UINT_MAX/sizeof(val[0]))
+ return ERANGE;
+
+ val = malloc(sizeof(val[0]) * el->len);
+ if (val == NULL)
+ return ENOMEM;
+
+ for(totallen = 0, i = 0; i < el->len; i++) {
+ unsigned char *next;
+ size_t l;
+
+ val[i].length = _asn1_length(t->ptr, elptr);
+ val[i].data = malloc(val[i].length);
+
+ ret = _asn1_encode_fuzzer(t->ptr, DPO(val[i].data, val[i].length - 1),
+ val[i].length, elptr, &l);
+ if (ret)
+ break;
+
+ next = elptr + ellen;
+ if (next < elptr) {
+ ret = ASN1_OVERFLOW;
+ break;
+ }
+ elptr = next;
+ totallen += val[i].length;
+ }
+ if (ret == 0 && totallen > len)
+ ret = ASN1_OVERFLOW;
+ if (ret) {
+ do {
+ free(val[i].data);
+ } while(i-- > 0);
+ free(val);
+ return ret;
+ }
+
+ len -= totallen;
+
+ qsort(val, el->len, sizeof(val[0]), _heim_der_set_sort);
+
+ i = el->len - 1;
+ do {
+ p -= val[i].length;
+ memcpy(p + 1, val[i].data, val[i].length);
+ free(val[i].data);
+ } while(i-- > 0);
+ free(val);
+
+ break;
+
+ }
+ case A1_OP_SEQOF: {
+ struct template_of *el = DPO(data, t->offset);
+ size_t ellen = _asn1_sizeofType(t->ptr);
+ size_t newsize;
+ unsigned int i;
+ unsigned char *elptr = el->val;
+
+ if (el->len == 0)
+ break;
+
+ elptr += ellen * (el->len - 1);
+
+ for (i = 0; i < el->len; i++) {
+ ret = _asn1_encode_fuzzer(t->ptr, p, len,
+ elptr,
+ &newsize);
+ if (ret)
+ return ret;
+ p -= newsize; len -= newsize;
+ elptr -= ellen;
+ }
+
+ break;
+ }
+ case A1_OP_BMEMBER: {
+ const struct asn1_template *bmember = t->ptr;
+ size_t size = bmember->offset;
+ size_t elements = A1_HEADER_LEN(bmember);
+ size_t pos;
+ unsigned char c = 0;
+ unsigned int bitset = 0;
+ int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
+
+ bmember += elements;
+
+ if (rfc1510)
+ pos = 31;
+ else
+ pos = bmember->offset;
+
+ while (elements && len) {
+ while (bmember->offset / 8 < pos / 8) {
+ if (rfc1510 || bitset || c) {
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = c; len--;
+ }
+ c = 0;
+ pos -= 8;
+ }
+ _asn1_bmember_put_bit(&c, data, bmember->offset, size, &bitset);
+ elements--; bmember--;
+ }
+ if (rfc1510 || bitset) {
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = c; len--;
+ }
+
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ if (rfc1510 || bitset == 0)
+ *p-- = 0;
+ else
+ *p-- = bitset - 1;
+
+ len--;
+
+ break;
+ }
+ case A1_OP_CHOICE: {
+ const struct asn1_template *choice = t->ptr;
+ const unsigned int *element = DPOC(data, choice->offset);
+ size_t datalen;
+ const void *el;
+
+ if (*element > A1_HEADER_LEN(choice)) {
+ printf("element: %d\n", *element);
+ return ASN1_PARSE_ERROR;
+ }
+
+ if (*element == 0) {
+ ret += der_put_octet_string(p, len,
+ DPOC(data, choice->tt), &datalen);
+ } else {
+ choice += *element;
+ el = DPOC(data, choice->offset);
+ ret = _asn1_encode_fuzzer(choice->ptr, p, len, el, &datalen);
+ if (ret)
+ return ret;
+ }
+ len -= datalen; p -= datalen;
+
+ break;
+ }
+ default:
+ ABORT_ON_ERROR();
+ }
+ t--;
+ elements--;
+ }
+
+ if (fuzzer_trigger(1000)) {
+ memset(p + 1, 0, oldlen - len);
+ } else if (fuzzer_trigger(1000)) {
+ memset(p + 1, 0x41, oldlen - len);
+ } else if (fuzzer_trigger(1000)) {
+ memset(p + 1, 0xff, oldlen - len);
+ }
+
+ if (size)
+ *size = oldlen - len;
+
+ return 0;
+}
+
+size_t
+_asn1_length_fuzzer(const struct asn1_template *t, const void *data)
+{
+ size_t elements = A1_HEADER_LEN(t);
+ size_t ret = 0;
+
+ t += A1_HEADER_LEN(t);
+
+ while (elements) {
+ switch (t->tt & A1_OP_MASK) {
+ case A1_OP_TYPE:
+ case A1_OP_TYPE_EXTERN: {
+ const void *el = DPOC(data, t->offset);
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ void **pel = (void **)el;
+ if (*pel == NULL)
+ break;
+ el = *pel;
+ }
+
+ if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
+ ret += _asn1_length(t->ptr, el);
+ } else {
+ const struct asn1_type_func *f = t->ptr;
+ ret += (f->length)(el);
+ }
+ break;
+ }
+ case A1_OP_TAG: {
+ size_t datalen;
+ const void *olddata = data;
+
+ data = DPO(data, t->offset);
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ void **el = (void **)data;
+ if (*el == NULL) {
+ data = olddata;
+ break;
+ }
+ data = *el;
+ }
+ datalen = _asn1_length(t->ptr, data);
+ ret += der_length_tag(A1_TAG_TAG(t->tt)) + fuzzer_length_len(datalen);
+ ret += datalen;
+ data = olddata;
+ break;
+ }
+ case A1_OP_PARSE: {
+ unsigned int type = A1_PARSE_TYPE(t->tt);
+ const void *el = DPOC(data, t->offset);
+
+ if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
+ ABORT_ON_ERROR();
+ break;
+ }
+ ret += (asn1_template_prim[type].length)(el);
+ break;
+ }
+ case A1_OP_SETOF:
+ case A1_OP_SEQOF: {
+ const struct template_of *el = DPOC(data, t->offset);
+ size_t ellen = _asn1_sizeofType(t->ptr);
+ const unsigned char *element = el->val;
+ unsigned int i;
+
+ for (i = 0; i < el->len; i++) {
+ ret += _asn1_length(t->ptr, element);
+ element += ellen;
+ }
+
+ break;
+ }
+ case A1_OP_BMEMBER: {
+ const struct asn1_template *bmember = t->ptr;
+ size_t size = bmember->offset;
+ size_t elements = A1_HEADER_LEN(bmember);
+ int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
+
+ if (rfc1510) {
+ ret += 5;
+ } else {
+
+ ret += 1;
+
+ bmember += elements;
+
+ while (elements) {
+ if (_asn1_bmember_isset_bit(data, bmember->offset, size)) {
+ ret += (bmember->offset / 8) + 1;
+ break;
+ }
+ elements--; bmember--;
+ }
+ }
+ break;
+ }
+ case A1_OP_CHOICE: {
+ const struct asn1_template *choice = t->ptr;
+ const unsigned int *element = DPOC(data, choice->offset);
+
+ if (*element > A1_HEADER_LEN(choice))
+ break;
+
+ if (*element == 0) {
+ ret += der_length_octet_string(DPOC(data, choice->tt));
+ } else {
+ choice += *element;
+ ret += _asn1_length(choice->ptr, DPOC(data, choice->offset));
+ }
+ break;
+ }
+ default:
+ ABORT_ON_ERROR();
+ break;
+ }
+ elements--;
+ t--;
+ }
+ return ret;
+}
+
+#endif /* ASN1_FUZZER */
diff --git a/third_party/heimdal/lib/asn1/gen.c b/third_party/heimdal/lib/asn1/gen.c
new file mode 100644
index 0000000..55ec5f6
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/gen.c
@@ -0,0 +1,2090 @@
+/*
+ * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gen_locl.h"
+
+extern const char *enum_prefix;
+extern int prefix_enum;
+
+RCSID("$Id$");
+
+FILE *jsonfile, *privheaderfile, *headerfile, *oidsfile, *codefile, *logfile, *templatefile;
+FILE *symsfile;
+
+#define STEM "asn1"
+
+static const char *orig_filename;
+static char *privheader, *header, *template;
+static const char *headerbase = STEM;
+
+/* XXX same as der_length_tag */
+static size_t
+length_tag(unsigned int tag)
+{
+ size_t len = 0;
+
+ if(tag <= 30)
+ return 1;
+ while(tag) {
+ tag /= 128;
+ len++;
+ }
+ return len + 1;
+}
+
+/*
+ * list of all IMPORTs
+ */
+
+struct import {
+ const char *module;
+ struct import *next;
+};
+
+static struct import *imports = NULL;
+
+void
+add_import (const char *module)
+{
+ struct import *tmp = emalloc (sizeof(*tmp));
+
+ tmp->module = module;
+ tmp->next = imports;
+ imports = tmp;
+
+ fprintf (headerfile, "#include <%s_asn1.h>\n", module);
+ fprintf(jsonfile, "{\"imports\":\"%s\"}\n", module);
+}
+
+/*
+ * List of all exported symbols
+ *
+ * XXX A hash table would be nice here.
+ */
+
+struct sexport {
+ const char *name;
+ int defined;
+ struct sexport *next;
+};
+
+static struct sexport *exports = NULL;
+
+void
+add_export (const char *name)
+{
+ struct sexport *tmp = emalloc (sizeof(*tmp));
+
+ tmp->name = name;
+ tmp->next = exports;
+ exports = tmp;
+}
+
+int
+is_export(const char *name)
+{
+ struct sexport *tmp;
+
+ if (exports == NULL) /* no export list, all exported */
+ return 1;
+
+ for (tmp = exports; tmp != NULL; tmp = tmp->next) {
+ if (strcmp(tmp->name, name) == 0) {
+ tmp->defined = 1;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+const char *
+get_filename (void)
+{
+ return orig_filename;
+}
+
+void
+init_generate (const char *filename, const char *base)
+{
+ char *fn = NULL;
+
+ orig_filename = filename;
+ if (base != NULL) {
+ headerbase = strdup(base);
+ if (headerbase == NULL)
+ errx(1, "strdup");
+ }
+
+ /* JSON file */
+ if (asprintf(&fn, "%s.json", headerbase) < 0 || fn == NULL)
+ errx(1, "malloc");
+ jsonfile = fopen(fn, "w");
+ if (jsonfile == NULL)
+ err(1, "open %s", fn);
+ free(fn);
+ fn = NULL;
+
+ /* public header file */
+ if (asprintf(&header, "%s.h", headerbase) < 0 || header == NULL)
+ errx(1, "malloc");
+ if (asprintf(&fn, "%s.h", headerbase) < 0 || fn == NULL)
+ errx(1, "malloc");
+ headerfile = fopen (fn, "w");
+ if (headerfile == NULL)
+ err (1, "open %s", fn);
+ free(fn);
+ fn = NULL;
+
+ /* private header file */
+ if (asprintf(&privheader, "%s-priv.h", headerbase) < 0 || privheader == NULL)
+ errx(1, "malloc");
+ if (asprintf(&fn, "%s-priv.h", headerbase) < 0 || fn == NULL)
+ errx(1, "malloc");
+ privheaderfile = fopen (fn, "w");
+ if (privheaderfile == NULL)
+ err (1, "open %s", fn);
+ free(fn);
+ fn = NULL;
+
+ /* template file */
+ if (asprintf(&template, "%s-template.c", headerbase) < 0 || template == NULL)
+ errx(1, "malloc");
+ fprintf (headerfile,
+ "/* Generated from %s */\n"
+ "/* Do not edit */\n\n",
+ filename);
+ fprintf (headerfile,
+ "#ifndef __%s_h__\n"
+ "#define __%s_h__\n\n", headerbase, headerbase);
+ fprintf (headerfile,
+ "#include <stddef.h>\n"
+ "#include <stdint.h>\n"
+ "#include <time.h>\n\n");
+ fprintf (headerfile,
+ "#ifndef __asn1_common_definitions__\n"
+ "#define __asn1_common_definitions__\n\n");
+ fprintf (headerfile,
+ "#ifndef __HEIM_BASE_DATA__\n"
+ "#define __HEIM_BASE_DATA__ 1\n"
+ "struct heim_base_data {\n"
+ " size_t length;\n"
+ " void *data;\n"
+ "};\n"
+ "typedef struct heim_base_data heim_octet_string;\n"
+ "#endif\n\n");
+ fprintf (headerfile,
+ "typedef struct heim_integer {\n"
+ " size_t length;\n"
+ " void *data;\n"
+ " int negative;\n"
+ "} heim_integer;\n\n");
+ fprintf (headerfile,
+ "typedef char *heim_general_string;\n\n"
+ );
+ fprintf (headerfile,
+ "typedef char *heim_utf8_string;\n\n"
+ );
+ fprintf (headerfile,
+ "typedef struct heim_base_data heim_printable_string;\n\n"
+ );
+ fprintf (headerfile,
+ "typedef struct heim_base_data heim_ia5_string;\n\n"
+ );
+ fprintf (headerfile,
+ "typedef struct heim_bmp_string {\n"
+ " size_t length;\n"
+ " uint16_t *data;\n"
+ "} heim_bmp_string;\n\n");
+ fprintf (headerfile,
+ "typedef struct heim_universal_string {\n"
+ " size_t length;\n"
+ " uint32_t *data;\n"
+ "} heim_universal_string;\n\n");
+ fprintf (headerfile,
+ "typedef char *heim_visible_string;\n\n"
+ );
+ fprintf (headerfile,
+ "typedef struct heim_oid {\n"
+ " size_t length;\n"
+ " unsigned *components;\n"
+ "} heim_oid;\n\n");
+ fprintf (headerfile,
+ "typedef struct heim_bit_string {\n"
+ " size_t length;\n"
+ " void *data;\n"
+ "} heim_bit_string;\n\n");
+ fprintf (headerfile,
+ "typedef struct heim_base_data heim_any;\n"
+ "typedef struct heim_base_data heim_any_set;\n"
+ "typedef struct heim_base_data HEIM_ANY;\n"
+ "typedef struct heim_base_data HEIM_ANY_SET;\n\n");
+
+ fprintf (headerfile,
+ "enum asn1_print_flags {\n"
+ " ASN1_PRINT_INDENT = 1,\n"
+ "};\n\n");
+ fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \\\n"
+ " do { \\\n"
+ " (BL) = length_##T((S)); \\\n"
+ " (B) = calloc(1, (BL)); \\\n"
+ " if((B) == NULL) { \\\n"
+ " *(L) = 0; \\\n"
+ " (R) = ENOMEM; \\\n"
+ " } else { \\\n"
+ " (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
+ " (S), (L)); \\\n"
+ " if((R) != 0) { \\\n"
+ " free((B)); \\\n"
+ " (B) = NULL; \\\n"
+ " *(L) = 0; \\\n"
+ " } \\\n"
+ " } \\\n"
+ " } while (0)\n\n",
+ headerfile);
+ fputs("#ifdef _WIN32\n"
+ "#ifndef ASN1_LIB\n"
+ "#define ASN1EXP __declspec(dllimport)\n"
+ "#else\n"
+ "#define ASN1EXP\n"
+ "#endif\n"
+ "#define ASN1CALL __stdcall\n"
+ "#else\n"
+ "#define ASN1EXP\n"
+ "#define ASN1CALL\n"
+ "#endif\n",
+ headerfile);
+ fputs("#ifndef ENOTSUP\n"
+ "/* Very old MSVC CRTs lack ENOTSUP */\n"
+ "#define ENOTSUP EINVAL\n"
+ "#endif\n",
+ headerfile);
+ fprintf (headerfile, "struct units;\n\n");
+ fprintf (headerfile, "#endif\n\n");
+ if (asprintf(&fn, "%s_files", base) < 0 || fn == NULL)
+ errx(1, "malloc");
+ logfile = fopen(fn, "w");
+ if (logfile == NULL)
+ err (1, "open %s", fn);
+ free(fn);
+ fn = NULL;
+
+ if (asprintf(&fn, "%s_oids.c", base) < 0 || fn == NULL)
+ errx(1, "malloc");
+ oidsfile = fopen(fn, "w");
+ if (oidsfile == NULL)
+ err (1, "open %s", fn);
+ if (asprintf(&fn, "%s_syms.c", base) < 0 || fn == NULL)
+ errx(1, "malloc");
+ symsfile = fopen(fn, "w");
+ if (symsfile == NULL)
+ err (1, "open %s", fn);
+ free(fn);
+ fn = NULL;
+
+ /* if one code file, write into the one codefile */
+ if (one_code_file)
+ return;
+
+ templatefile = fopen (template, "w");
+ if (templatefile == NULL)
+ err (1, "open %s", template);
+
+ fprintf (templatefile,
+ "/* Generated from %s */\n"
+ "/* Do not edit */\n\n"
+ "#include <stdio.h>\n"
+ "#include <stdlib.h>\n"
+ "#include <time.h>\n"
+ "#include <string.h>\n"
+ "#include <errno.h>\n"
+ "#include <limits.h>\n"
+ "#include <asn1_err.h>\n"
+ "#include <%s>\n",
+ filename,
+ type_file_string);
+
+ fprintf (templatefile,
+ "#include <%s>\n"
+ "#include <%s>\n"
+ "#include <der.h>\n"
+ "#include <asn1-template.h>\n",
+ header, privheader);
+
+
+}
+
+void
+close_generate (void)
+{
+ fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
+
+ if (headerfile && fclose(headerfile) == EOF)
+ err(1, "writes to public header file failed");
+ if (privheaderfile && fclose(privheaderfile) == EOF)
+ err(1, "writes to private header file failed");
+ if (templatefile && fclose(templatefile) == EOF)
+ err(1, "writes to template file failed");
+ if (!jsonfile) abort();
+ if (fclose(jsonfile) == EOF)
+ err(1, "writes to JSON file failed");
+ if (!oidsfile) abort();
+ if (fclose(oidsfile) == EOF)
+ err(1, "writes to OIDs file failed");
+ if (!symsfile) abort();
+ if (fclose(symsfile) == EOF)
+ err(1, "writes to symbols file failed");
+ if (!logfile) abort();
+ fprintf(logfile, "\n");
+ if (fclose(logfile) == EOF)
+ err(1, "writes to log file failed");
+}
+
+void
+gen_assign_defval(const char *var, struct value *val)
+{
+ switch(val->type) {
+ case stringvalue:
+ fprintf(codefile, "if((%s = strdup(\"%s\")) == NULL)\nreturn ENOMEM;\n", var, val->u.stringvalue);
+ break;
+ case integervalue:
+ fprintf(codefile, "%s = %lld;\n",
+ var, (long long)val->u.integervalue);
+ break;
+ case booleanvalue:
+ if(val->u.booleanvalue)
+ fprintf(codefile, "%s = 1;\n", var);
+ else
+ fprintf(codefile, "%s = 0;\n", var);
+ break;
+ default:
+ abort();
+ }
+}
+
+void
+gen_compare_defval(const char *var, struct value *val)
+{
+ switch(val->type) {
+ case stringvalue:
+ fprintf(codefile, "if(strcmp(%s, \"%s\") != 0)\n", var, val->u.stringvalue);
+ break;
+ case integervalue:
+ fprintf(codefile, "if(%s != %lld)\n",
+ var, (long long)val->u.integervalue);
+ break;
+ case booleanvalue:
+ if(val->u.booleanvalue)
+ fprintf(codefile, "if(!%s)\n", var);
+ else
+ fprintf(codefile, "if(%s)\n", var);
+ break;
+ default:
+ abort();
+ }
+}
+
+void
+generate_header_of_codefile(const char *name)
+{
+ char *filename = NULL;
+
+ if (codefile != NULL)
+ abort();
+
+ if (asprintf (&filename, "%s_%s.c", STEM, name) < 0 || filename == NULL)
+ errx(1, "malloc");
+ codefile = fopen (filename, "w");
+ if (codefile == NULL)
+ err (1, "fopen %s", filename);
+ if (logfile)
+ fprintf(logfile, "%s ", filename);
+ free(filename);
+ filename = NULL;
+ fprintf (codefile,
+ "/* Generated from %s */\n"
+ "/* Do not edit */\n\n"
+ "#if defined(_WIN32) && !defined(ASN1_LIB)\n"
+ "# error \"ASN1_LIB must be defined\"\n"
+ "#endif\n"
+ "#include <stdio.h>\n"
+ "#include <stdlib.h>\n"
+ "#include <time.h>\n"
+ "#include <string.h>\n"
+ "#include <errno.h>\n"
+ "#include <limits.h>\n"
+ "#include <%s>\n",
+ orig_filename,
+ type_file_string);
+
+ fprintf (codefile,
+ "#include \"%s\"\n"
+ "#include \"%s\"\n",
+ header, privheader);
+ fprintf (codefile,
+ "#include <asn1_err.h>\n"
+ "#include <der.h>\n"
+ "#include <asn1-template.h>\n\n");
+
+ if (parse_units_flag)
+ fprintf (codefile,
+ "#include <parse_units.h>\n\n");
+
+#ifdef _WIN32
+ fprintf(codefile, "#pragma warning(disable: 4101)\n\n");
+#endif
+}
+
+void
+close_codefile(void)
+{
+ if (codefile == NULL)
+ abort();
+
+ if (fclose(codefile) == EOF)
+ err(1, "writes to source code file failed");
+ codefile = NULL;
+}
+
+/* Object identifiers are parsed backwards; this reverses that */
+struct objid **
+objid2list(struct objid *o)
+{
+ struct objid *el, **list;
+ size_t i, len;
+
+ for (el = o, len = 0; el; el = el->next)
+ len++;
+ if (len == 0)
+ return NULL;
+ list = ecalloc(len + 1, sizeof(*list));
+
+ for (i = 0; o; o = o->next)
+ list[i++] = o;
+ list[i] = NULL;
+
+ /* Reverse the list */
+ for (i = 0; i < (len>>1); i++) {
+ el = list[i];
+ list[i] = list[len - (i + 1)];
+ list[len - (i + 1)] = el;
+ }
+ return list;
+}
+
+void
+generate_constant (const Symbol *s)
+{
+ switch(s->value->type) {
+ case booleanvalue:
+ break;
+ case integervalue:
+ /*
+ * Work around the fact that OpenSSL defines macros for PKIX constants
+ * that we want to generate as enums, which causes conflicts for things
+ * like ub-name (ub_name).
+ */
+ fprintf(headerfile,
+ "#ifdef %s\n"
+ "#undef %s\n"
+ "#endif\n"
+ "enum { %s = %lld };\n\n",
+ s->gen_name, s->gen_name, s->gen_name,
+ (long long)s->value->u.integervalue);
+ if (is_export(s->name))
+ fprintf(symsfile, "ASN1_SYM_INTVAL(\"%s\", \"%s\", %s, %lld)\n",
+ s->name, s->gen_name, s->gen_name,
+ (long long)s->value->u.integervalue);
+ fprintf(jsonfile,
+ "{\"name\":\"%s\",\"gen_name\":\"%s\",\"type\":\"INTEGER\","
+ "\"constant\":true,\"exported\":%s,\"value\":%lld}\n",
+ s->name, s->gen_name, is_export(s->name) ? "true" : "false",
+ (long long)s->value->u.integervalue);
+ break;
+ case nullvalue:
+ break;
+ case stringvalue:
+ break;
+ case objectidentifiervalue: {
+ struct objid *o, **list;
+ size_t i, len;
+ char *gen_upper;
+
+ if (!one_code_file)
+ generate_header_of_codefile(s->gen_name);
+
+ list = objid2list(s->value->u.objectidentifiervalue);
+ for (len = 0; list && list[len]; len++)
+ ;
+ if (len == 0) {
+ errx(1, "Empty OBJECT IDENTIFIER named %s\n", s->name);
+ break;
+ }
+
+ fprintf(jsonfile,
+ "{\"name\":\"%s\",\"gen_name\":\"%s\","
+ "\"type\":\"OBJECT IDENTIFIER\","
+ "\"constant\":true,\"exported\":%s,\"value\":[\n",
+ s->name, s->gen_name, is_export(s->name) ? "true" : "false");
+ fprintf (headerfile, "/* OBJECT IDENTIFIER %s ::= { ", s->name);
+ for (i = 0; i < len; i++) {
+ o = list[i];
+ fprintf(headerfile, "%s(%d) ",
+ o->label ? o->label : "label-less", o->value);
+ if (o->label == NULL)
+ fprintf(jsonfile, "%s{\"label\":null,\"value\":%d}",
+ i ? "," : "", o->value);
+ else
+ fprintf(jsonfile, "%s{\"label\":\"%s\",\"value\":%d}",
+ i ? "," : "", o->label, o->value);
+ }
+ fprintf(jsonfile, "]}\n");
+
+ fprintf (codefile, "static unsigned oid_%s_variable_num[%lu] = {",
+ s->gen_name, (unsigned long)len);
+ for (i = 0; list[i]; i++) {
+ fprintf(codefile, "%s %d", i ? "," : "", list[i]->value);
+ }
+ fprintf(codefile, "};\n");
+
+ fprintf (codefile, "const heim_oid asn1_oid_%s = "
+ "{ %lu, oid_%s_variable_num };\n\n",
+ s->gen_name, (unsigned long)len, s->gen_name);
+
+ fprintf(oidsfile, "DEFINE_OID_WITH_NAME(%s)\n", s->gen_name);
+ if (is_export(s->name))
+ fprintf(symsfile, "ASN1_SYM_OID(\"%s\", \"%s\", %s)\n",
+ s->name, s->gen_name, s->gen_name);
+
+ free(list);
+
+ /* header file */
+
+ gen_upper = strdup(s->gen_name);
+ len = strlen(gen_upper);
+ for (i = 0; i < len; i++)
+ gen_upper[i] = toupper((unsigned char)s->gen_name[i]);
+
+ fprintf (headerfile, "} */\n");
+ fprintf (headerfile,
+ "extern ASN1EXP const heim_oid asn1_oid_%s;\n"
+ "#define ASN1_OID_%s (&asn1_oid_%s)\n\n",
+ s->gen_name,
+ gen_upper,
+ s->gen_name);
+
+ free(gen_upper);
+
+ if (!one_code_file)
+ close_codefile();
+
+ break;
+ }
+ default:
+ abort();
+ }
+}
+
+int
+is_tagged_type(const Type *t)
+{
+ /*
+ * Start by chasing aliasings like this:
+ *
+ * Type0 ::= ...
+ * Type1 ::= Type0
+ * ..
+ * TypeN ::= TypeN-1
+ *
+ * to <Type0>, then check if <Type0> is tagged.
+ */
+ while (t->type == TType) {
+ if (t->subtype)
+ t = t->subtype;
+ else if (t->symbol && t->symbol->type)
+ t = t->symbol->type;
+ else
+ abort();
+
+ }
+ if (t->type == TTag && t->tag.tagenv == TE_EXPLICIT)
+ return 1;
+ if (t->type == TTag) {
+ if (t->subtype)
+ return is_tagged_type(t->subtype);
+ if (t->symbol && t->symbol->type)
+ return is_tagged_type(t->symbol->type);
+ /* This is the tag */
+ return 1;
+ }
+ return 0;
+}
+
+int
+is_primitive_type(const Type *t)
+{
+ /*
+ * Start by chasing aliasings like this:
+ *
+ * Type0 ::= ...
+ * Type1 ::= Type0
+ * ..
+ * TypeN ::= TypeN-1
+ *
+ * to <Type0>, then check if <Type0> is primitive.
+ */
+ while (t->type == TType &&
+ t->symbol &&
+ t->symbol->type) {
+ if (t->symbol->type->type == TType)
+ t = t->symbol->type; /* Alias */
+ else if (t->symbol->type->type == TTag &&
+ t->symbol->type->tag.tagenv == TE_IMPLICIT)
+ /*
+ * IMPLICIT-tagged alias, something like:
+ *
+ * Type0 ::= [0] IMPLICIT ...
+ *
+ * Just recurse.
+ */
+ return is_primitive_type(t->symbol->type);
+ else
+ break;
+
+ }
+ /* EXPLICIT non-UNIVERSAL tags are always constructed */
+ if (t->type == TTag && t->tag.tagclass != ASN1_C_UNIV &&
+ t->tag.tagenv == TE_EXPLICIT)
+ return 0;
+ if (t->symbol && t->symbol->type) {
+ /* EXPLICIT non-UNIVERSAL tags are constructed */
+ if (t->symbol->type->type == TTag &&
+ t->symbol->type->tag.tagclass != ASN1_C_UNIV &&
+ t->symbol->type->tag.tagenv == TE_EXPLICIT)
+ return 0;
+ /* EXPLICIT UNIVERSAL tags are constructed if they are SEQUENCE/SET */
+ if (t->symbol->type->type == TTag &&
+ t->symbol->type->tag.tagclass == ASN1_C_UNIV) {
+ switch (t->symbol->type->tag.tagvalue) {
+ case UT_Sequence: return 0;
+ case UT_Set: return 0;
+ default: return 1;
+ }
+ }
+ }
+ switch(t->type) {
+ case TInteger:
+ case TBoolean:
+ case TOctetString:
+ case TBitString:
+ case TEnumerated:
+ case TGeneralizedTime:
+ case TGeneralString:
+ case TTeletexString:
+ case TOID:
+ case TUTCTime:
+ case TUTF8String:
+ case TPrintableString:
+ case TIA5String:
+ case TBMPString:
+ case TUniversalString:
+ case TVisibleString:
+ case TNull:
+ return 1;
+ case TTag:
+ return is_primitive_type(t->subtype);
+ default:
+ return 0;
+ }
+}
+
+static void
+space(int level)
+{
+ while(level-- > 0)
+ fprintf(headerfile, " ");
+}
+
+static const char *
+last_member_p(struct member *m)
+{
+ struct member *n = HEIM_TAILQ_NEXT(m, members);
+ if (n == NULL)
+ return "";
+ if (n->ellipsis && HEIM_TAILQ_NEXT(n, members) == NULL)
+ return "";
+ return ",";
+}
+
+static struct member *
+have_ellipsis(Type *t)
+{
+ struct member *m;
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ if (m->ellipsis)
+ return m;
+ }
+ return NULL;
+}
+
+static void
+define_asn1 (int level, Type *t)
+{
+ switch (t->type) {
+ case TType:
+ if (!t->symbol && t->typeref.iosclass) {
+ fprintf(headerfile, "%s.&%s",
+ t->typeref.iosclass->symbol->name,
+ t->typeref.field->name);
+ } else if (t->symbol)
+ fprintf(headerfile, "%s", t->symbol->name);
+ else
+ abort();
+ break;
+ case TInteger:
+ if(t->members == NULL) {
+ fprintf (headerfile, "INTEGER");
+ if (t->range)
+ fprintf (headerfile, " (%lld..%lld)",
+ (long long)t->range->min,
+ (long long)t->range->max);
+ } else {
+ Member *m;
+ fprintf (headerfile, "INTEGER {\n");
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ space (level + 1);
+ fprintf(headerfile, "%s(%lld)%s\n", m->gen_name,
+ (long long)m->val, last_member_p(m));
+ }
+ space(level);
+ fprintf (headerfile, "}");
+ }
+ break;
+ case TBoolean:
+ fprintf (headerfile, "BOOLEAN");
+ break;
+ case TOctetString:
+ fprintf (headerfile, "OCTET STRING");
+ break;
+ case TEnumerated:
+ case TBitString: {
+ Member *m;
+
+ space(level);
+ if(t->type == TBitString)
+ fprintf (headerfile, "BIT STRING {\n");
+ else
+ fprintf (headerfile, "ENUMERATED {\n");
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ space(level + 1);
+ fprintf(headerfile, "%s(%lld)%s\n", m->name,
+ (long long)m->val, last_member_p(m));
+ }
+ space(level);
+ fprintf (headerfile, "}");
+ break;
+ }
+ case TChoice:
+ case TSet:
+ case TSequence: {
+ Member *m;
+ size_t max_width = 0;
+
+ if(t->type == TChoice)
+ fprintf(headerfile, "CHOICE {\n");
+ else if(t->type == TSet)
+ fprintf(headerfile, "SET {\n");
+ else
+ fprintf(headerfile, "SEQUENCE {\n");
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ if(strlen(m->name) > max_width)
+ max_width = strlen(m->name);
+ }
+ max_width += 3;
+ if(max_width < 16) max_width = 16;
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ size_t width = max_width;
+ space(level + 1);
+ if (m->ellipsis) {
+ fprintf (headerfile, "...");
+ } else {
+ width -= fprintf(headerfile, "%s", m->name);
+ fprintf(headerfile, "%*s", (int)width, "");
+ define_asn1(level + 1, m->type);
+ if(m->optional)
+ fprintf(headerfile, " OPTIONAL");
+ }
+ if(last_member_p(m))
+ fprintf (headerfile, ",");
+ fprintf (headerfile, "\n");
+ }
+ space(level);
+ fprintf (headerfile, "}");
+ break;
+ }
+ case TSequenceOf:
+ fprintf (headerfile, "SEQUENCE OF ");
+ define_asn1 (0, t->subtype);
+ break;
+ case TSetOf:
+ fprintf (headerfile, "SET OF ");
+ define_asn1 (0, t->subtype);
+ break;
+ case TGeneralizedTime:
+ fprintf (headerfile, "GeneralizedTime");
+ break;
+ case TGeneralString:
+ fprintf (headerfile, "GeneralString");
+ break;
+ case TTeletexString:
+ fprintf (headerfile, "TeletexString");
+ break;
+ case TTag: {
+ const char *classnames[] = { "UNIVERSAL ", "APPLICATION ",
+ "" /* CONTEXT */, "PRIVATE " };
+ if(t->tag.tagclass != ASN1_C_UNIV)
+ fprintf (headerfile, "[%s%d] ",
+ classnames[t->tag.tagclass],
+ t->tag.tagvalue);
+ if(t->tag.tagenv == TE_IMPLICIT)
+ fprintf (headerfile, "IMPLICIT ");
+ define_asn1 (level, t->subtype);
+ break;
+ }
+ case TUTCTime:
+ fprintf (headerfile, "UTCTime");
+ break;
+ case TUTF8String:
+ space(level);
+ fprintf (headerfile, "UTF8String");
+ break;
+ case TPrintableString:
+ space(level);
+ fprintf (headerfile, "PrintableString");
+ break;
+ case TIA5String:
+ space(level);
+ fprintf (headerfile, "IA5String");
+ break;
+ case TBMPString:
+ space(level);
+ fprintf (headerfile, "BMPString");
+ break;
+ case TUniversalString:
+ space(level);
+ fprintf (headerfile, "UniversalString");
+ break;
+ case TVisibleString:
+ space(level);
+ fprintf (headerfile, "VisibleString");
+ break;
+ case TOID :
+ space(level);
+ fprintf(headerfile, "OBJECT IDENTIFIER");
+ break;
+ case TNull:
+ space(level);
+ fprintf (headerfile, "NULL");
+ break;
+ default:
+ abort ();
+ }
+}
+
+static void
+getnewbasename(char **newbasename, int typedefp, const char *basename, const char *name)
+{
+ if (typedefp)
+ *newbasename = strdup(name);
+ else {
+ if (name[0] == '*')
+ name++;
+ if (asprintf(newbasename, "%s_%s", basename, name) < 0)
+ errx(1, "malloc");
+ }
+ if (*newbasename == NULL)
+ err(1, "malloc");
+}
+
+typedef enum define_type_options {
+ DEF_TYPE_NONE = 0,
+ DEF_TYPE_PRESERVE = 1,
+ DEF_TYPE_TYPEDEFP = 2,
+ DEF_TYPE_EMIT_NAME = 4
+} define_type_options;
+static void define_type(int, const char *, const char *, Type *, Type *, define_type_options);
+
+/*
+ * Get the SET/SEQUENCE member pair and CLASS field pair defining an open type.
+ *
+ * There are three cases:
+ *
+ * - open types embedded in OCTET STRING, with the open type object class
+ * relation declared via a constraint
+ *
+ * - open types not embedded in OCTET STRING, which are really more like ANY
+ * DEFINED BY types, so, HEIM_ANY
+ *
+ * - open types in a nested structure member where the type ID field is in a
+ * member of the ancestor structure (this happens in PKIX's `AttributeSet',
+ * where the open type is essentially a SET OF HEIM_ANY).
+ *
+ * In a type like PKIX's SingleAttribute the type ID member would be the one
+ * named "type" and the open type member would be the one named "value", and
+ * the corresponding fields of the ATTRIBUTE class would be named "id" and
+ * "Type".
+ *
+ * NOTE: We assume a single open type member pair in any SET/SEQUENCE. In
+ * principle there could be more pairs and we could iterate them, or
+ * better yet, we could be given the name of an open type member and then
+ * just find its related type ID member and fields, then our caller would
+ * iterate the SET/SEQUENCE type's members looking for open type members
+ * and would call this function for each one found.
+ */
+void
+get_open_type_defn_fields(const Type *t,
+ Member **typeidmember,
+ Member **opentypemember,
+ Field **typeidfield,
+ Field **opentypefield,
+ int *is_array_of)
+{
+ Member *m;
+ Field *junk1, *junk2;
+ char *idmembername = NULL;
+
+ if (!typeidfield) typeidfield = &junk1;
+ if (!opentypefield) opentypefield = &junk2;
+
+ *typeidfield = *opentypefield = NULL;
+ *typeidmember = *opentypemember = NULL;
+ *is_array_of = 0;
+
+ /* Look for the open type member */
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ Type *subtype = m->type;
+ Type *sOfType = NULL;
+
+ while (subtype->type == TTag ||
+ subtype->type == TSetOf ||
+ subtype->type == TSequenceOf) {
+ if (subtype->type == TTag && subtype->subtype) {
+ if (subtype->subtype->type == TOctetString ||
+ subtype->subtype->type == TBitString)
+ break;
+ subtype = subtype->subtype;
+ } else if (subtype->type == TSetOf || subtype->type == TSequenceOf) {
+ sOfType = subtype;
+ if (sOfType->symbol)
+ break;
+ if (subtype->subtype)
+ subtype = subtype->subtype;
+ } else
+ break;
+ }
+ /*
+ * If we traversed through a non-inlined SET OF or SEQUENCE OF type,
+ * then this cannot be an open type field.
+ */
+ if (sOfType && sOfType->symbol)
+ continue;
+ /*
+ * The type of the field we're interested in has to have an information
+ * object constraint.
+ */
+ if (!subtype->constraint)
+ continue;
+ if (subtype->type != TType && subtype->type != TTag)
+ continue;
+ /*
+ * Check if it's an ANY-like member or like an OCTET STRING CONTAINING
+ * member. Those are the only two possibilities.
+ */
+ if ((subtype->type == TTag || subtype->type == TType) &&
+ subtype->subtype &&
+ subtype->constraint->ctype == CT_CONTENTS &&
+ subtype->constraint->u.content.type &&
+ subtype->constraint->u.content.type->type == TType &&
+ !subtype->constraint->u.content.type->subtype &&
+ subtype->constraint->u.content.type->constraint &&
+ subtype->constraint->u.content.type->constraint->ctype == CT_TABLE_CONSTRAINT) {
+ /* Type like OCTET STRING or BIT STRING CONTAINING open type */
+ if (*opentypemember)
+ errx(1, "Multiple open type members %s and %s for the same "
+ "field %s?", (*opentypemember)->name, m->name,
+ (*opentypefield)->name);
+ *opentypemember = m;
+ *opentypefield = subtype->constraint->u.content.type->typeref.field;
+ *is_array_of = sOfType != NULL;
+ idmembername = subtype->constraint->u.content.type->constraint->u.content.crel.membername;
+ break;
+ } else if (subtype->symbol && strcmp(subtype->symbol->name, "HEIM_ANY") == 0) {
+ /* Open type, but NOT embedded in OCTET STRING or BIT STRING */
+ if (*opentypemember)
+ errx(1, "Multiple open type members %s and %s for the same "
+ "field %s?", (*opentypemember)->name, m->name,
+ (*opentypefield)->name);
+ *opentypemember = m;
+ *opentypefield = subtype->typeref.field;
+ *is_array_of = sOfType != NULL;
+ idmembername = subtype->constraint->u.content.crel.membername;
+ break;
+ }
+ }
+
+ if (!idmembername)
+ errx(1, "Missing open type id member in %s",
+ t->symbol ? t->symbol->name : "<unknown type>");
+ /* Look for the type ID member identified in the previous loop */
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ if (!m->type->subtype || strcmp(m->name, idmembername) != 0)
+ continue;
+ if (m->type->constraint &&
+ m->type->constraint->ctype == CT_TABLE_CONSTRAINT)
+ *typeidfield = m->type->typeref.field;
+ else if (m->type->subtype->constraint &&
+ m->type->subtype->constraint->ctype == CT_TABLE_CONSTRAINT)
+ *typeidfield = m->type->subtype->typeref.field;
+ else
+ continue;
+ /* This is the type ID field (because there _is_ a subtype) */
+ *typeidmember = m;
+ break;
+ }
+}
+
+/*
+ * Generate CHOICE-like struct fields for open types declared via
+ * X.681/682/683 syntax.
+ *
+ * We could support multiple open type members in a SET/SEQUENCE, but for now
+ * we support only one.
+ */
+static void
+define_open_type(int level, const char *newbasename, const char *name, const char *basename, Type *pt, Type *t)
+{
+ Member *opentypemember, *typeidmember;
+ Field *opentypefield, *typeidfield;
+ ObjectField *of;
+ IOSObjectSet *os = pt->actual_parameter;
+ IOSObject **objects;
+ size_t nobjs, i;
+ int is_array_of_open_type;
+
+ get_open_type_defn_fields(pt, &typeidmember, &opentypemember,
+ &typeidfield, &opentypefield,
+ &is_array_of_open_type);
+ if (!opentypemember || !typeidmember ||
+ !opentypefield || !typeidfield)
+ errx(1, "Open type specification in %s is incomplete", name);
+
+ sort_object_set(os, typeidfield, &objects, &nobjs);
+
+ fprintf(headerfile, "struct {\n");
+ fprintf(jsonfile, "{\"opentype\":true,\"arraytype\":%s,",
+ is_array_of_open_type ? "true" : "false");
+ fprintf(jsonfile, "\"classname\":\"%s\",", os->iosclass->symbol->name);
+ fprintf(jsonfile, "\"objectsetname\":\"%s\",", os->symbol->name);
+ fprintf(jsonfile, "\"typeidmember\":\"%s\",", typeidmember->name);
+ fprintf(jsonfile, "\"opentypemember\":\"%s\",", opentypemember->name);
+ fprintf(jsonfile, "\"typeidfield\":\"%s\",", typeidfield->name);
+ fprintf(jsonfile, "\"opentypefield\":\"%s\",", opentypefield->name);
+
+ /* Iterate objects in the object set, gen enum labels */
+ fprintf(headerfile, "enum { choice_%s_iosnumunknown = 0,\n",
+ newbasename);
+ fprintf(jsonfile, "\"opentypeids\":[");
+ for (i = 0; i < nobjs; i++) {
+ HEIM_TAILQ_FOREACH(of, objects[i]->objfields, objfields) {
+ if (strcmp(of->name, typeidfield->name) != 0)
+ continue;
+ if (!of->value || !of->value->s)
+ errx(1, "Unknown value in value field %s of object %s",
+ of->name, objects[i]->symbol->name);
+ fprintf(headerfile, "choice_%s_iosnum_%s,\n",
+ newbasename, of->value->s->gen_name);
+ fprintf(jsonfile, "\"%s\"", of->value->s->gen_name);
+ fprintf(jsonfile, "%s", (i + 1) < nobjs ? "," : "");
+ }
+ }
+ fprintf(jsonfile, "],\n");
+ fprintf(headerfile, "} element;\n");
+
+ if (is_array_of_open_type)
+ fprintf(headerfile, "unsigned int len;\n");
+
+ /* Iterate objects in the object set, gen union arms */
+ fprintf(headerfile, "union {\nvoid *_any;\n");
+ fprintf(jsonfile, "\"members\":[");
+ for (i = 0; i < nobjs; i++) {
+ HEIM_TAILQ_FOREACH(of, objects[i]->objfields, objfields) {
+ char *n = NULL;
+
+ /* XXX Print the type IDs into the jsonfile too pls */
+
+ if (strcmp(of->name, opentypefield->name) != 0)
+ continue;
+ if (!of->type || (!of->type->symbol && of->type->type != TTag) ||
+ of->type->tag.tagclass != ASN1_C_UNIV) {
+ warnx("Ignoring unknown or unset type field %s of object %s",
+ of->name, objects[i]->symbol->name);
+ continue;
+ }
+
+ if (asprintf(&n, "*%s", objects[i]->symbol->gen_name) < 0 || n == NULL)
+ err(1, "malloc");
+ define_type(level + 2, n, newbasename, NULL, of->type, DEF_TYPE_NONE);
+ fprintf(jsonfile, "%s", (i + 1) < nobjs ? "," : "");
+ free(n);
+ }
+ }
+ fprintf(jsonfile, "]}\n");
+ if (is_array_of_open_type) {
+ fprintf(headerfile, "} *val;\n} _ioschoice_%s;\n", opentypemember->gen_name);
+ } else {
+ fprintf(headerfile, "} u;\n");
+ fprintf(headerfile, "} _ioschoice_%s;\n", opentypemember->gen_name);
+ }
+ free(objects);
+}
+
+static const char * const tagclassnames[] = {
+ "UNIVERSAL", "APPLICATION", "CONTEXT", "PRIVATE"
+};
+
+static void
+define_type(int level, const char *name, const char *basename,
+ Type *pt, Type *t, define_type_options opts)
+{
+ const char *label_prefix = NULL;
+ const char *label_prefix_sep = NULL;
+ char *newbasename = NULL;
+
+ fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
+ "\"is_type\":true,\"exported\":%s,\"typedef\":%s,",
+ basename, name,
+ t->symbol && is_export(t->symbol->name) ? "true" : "false",
+ (opts & DEF_TYPE_TYPEDEFP) ? "true" : "false");
+
+ switch (t->type) {
+ case TType:
+ space(level);
+ if (!t->symbol && t->actual_parameter) {
+ define_open_type(level, newbasename, name, basename, t, t);
+ } else if (!t->symbol && pt->actual_parameter) {
+ define_open_type(level, newbasename, name, basename, pt, t);
+ } else if (t->symbol) {
+ fprintf(headerfile, "%s %s;\n", t->symbol->gen_name, name);
+ fprintf(jsonfile, "\"ttype\":\"%s\","
+ "\"alias\":true\n", t->symbol->gen_name);
+ } else
+ abort();
+ break;
+ case TInteger:
+ if (t->symbol && t->symbol->emitted_definition)
+ break;
+
+ space(level);
+ if(t->members) {
+ Member *m;
+
+ label_prefix = prefix_enum ? name : (enum_prefix ? enum_prefix : "");
+ label_prefix_sep = prefix_enum ? "_" : "";
+ fprintf (headerfile, "enum %s {\n", (opts & DEF_TYPE_TYPEDEFP) ? name : "");
+ fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"enum\","
+ "\"members\":[\n");
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ space (level + 1);
+ fprintf(headerfile, "%s%s%s = %lld%s\n",
+ label_prefix, label_prefix_sep,
+ m->gen_name, (long long)m->val, last_member_p(m));
+ fprintf(jsonfile, "{\"%s%s%s\":%lld}%s\n",
+ label_prefix, label_prefix_sep,
+ m->gen_name, (long long)m->val, last_member_p(m));
+ }
+ fprintf(headerfile, "} %s;\n", name);
+ fprintf(jsonfile, "]");
+ } else if (t->range == NULL) {
+ fprintf(headerfile, "heim_integer %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"heim_integer\"");
+ } else if (t->range->min < 0 &&
+ (t->range->min < INT_MIN || t->range->max > INT_MAX)) {
+ fprintf(headerfile, "int64_t %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"int64_t\"");
+ } else if (t->range->min < 0) {
+ fprintf (headerfile, "int %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"int\"");
+ } else if (t->range->max > UINT_MAX) {
+ fprintf (headerfile, "uint64_t %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"uint64_t\"");
+ } else {
+ fprintf (headerfile, "unsigned int %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"INTEGER\",\"ctype\":\"unsigned int\"");
+ }
+ break;
+ case TBoolean:
+ space(level);
+ fprintf (headerfile, "int %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"BOOLEAN\",\"ctype\":\"unsigned int\"");
+ break;
+ case TOctetString:
+ space(level);
+ fprintf (headerfile, "heim_octet_string %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"OCTET STRING\",\"ctype\":\"heim_octet_string\"");
+ break;
+ case TBitString: {
+ Member *m;
+ Type i;
+ struct range range = { 0, UINT_MAX };
+ size_t max_memno = 0;
+ size_t bitset_size;
+
+ if (t->symbol && t->symbol->emitted_definition)
+ break;
+ memset(&i, 0, sizeof(i));
+
+ /*
+ * range.max implies the size of the base unsigned integer used for the
+ * bitfield members. If it's less than or equal to UINT_MAX, then that
+ * will be unsigned int, otherwise it will be uint64_t.
+ *
+ * We could just use uint64_t, yes, but for now, and in case that any
+ * projects were exposing the BIT STRING types' C representations in
+ * ABIs prior to this compiler supporting BIT STRING with larger
+ * members, we stick to this.
+ */
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ if (m->val > max_memno)
+ max_memno = m->val;
+ }
+ if (max_memno > 63)
+ range.max = INT64_MAX;
+ else
+ range.max = 1ULL << max_memno;
+
+ i.type = TInteger;
+ i.range = &range;
+ i.members = NULL;
+ i.constraint = NULL;
+
+ space(level);
+ fprintf(jsonfile, "\"ttype\":\"BIT STRING\",");
+ if(HEIM_TAILQ_EMPTY(t->members)) {
+ fprintf (headerfile, "heim_bit_string %s;\n", name);
+ fprintf(jsonfile, "\"ctype\":\"heim_bit_string\"");
+ } else {
+ int64_t pos = 0;
+ getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
+
+ fprintf (headerfile, "struct %s {\n", newbasename);
+ fprintf(jsonfile, "\"ctype\":\"struct %s\",\"members\":[\n", newbasename);
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ char *n = NULL;
+
+ /*
+ * pad unused bits beween declared members (hopefully this
+ * forces the compiler to give us an obvious layout)
+ */
+ while (pos < m->val) {
+ if (asprintf (&n, "_unused%lld:1", (long long)pos) < 0 ||
+ n == NULL)
+ err(1, "malloc");
+ define_type(level + 1, n, newbasename, NULL, &i, DEF_TYPE_EMIT_NAME);
+ fprintf(jsonfile, ",");
+ free(n);
+ pos++;
+ }
+
+ n = NULL;
+ if (asprintf (&n, "%s:1", m->gen_name) < 0 || n == NULL)
+ errx(1, "malloc");
+ define_type(level + 1, n, newbasename, NULL, &i, DEF_TYPE_EMIT_NAME);
+ fprintf(jsonfile, "%s", last_member_p(m));
+ free (n);
+ n = NULL;
+ pos++;
+ }
+ /* pad unused tail (ditto) */
+ bitset_size = max_memno;
+ if (max_memno > 31)
+ bitset_size += 64 - (max_memno % 64);
+ else
+ bitset_size = 32;
+ if (pos < bitset_size)
+ fprintf(jsonfile, ",");
+ while (pos < bitset_size) {
+ char *n = NULL;
+ if (asprintf (&n, "_unused%lld:1", (long long)pos) < 0 ||
+ n == NULL)
+ errx(1, "malloc");
+ define_type(level + 1, n, newbasename, NULL, &i, DEF_TYPE_EMIT_NAME);
+ fprintf(jsonfile, "%s", (pos + 1) < bitset_size ? "," : "");
+ free(n);
+ pos++;
+ }
+
+ space(level);
+ fprintf(headerfile, "}%s%s;\n\n",
+ (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
+ (opts & DEF_TYPE_EMIT_NAME) ? name : "");
+ fprintf(jsonfile, "]");
+ }
+ break;
+ }
+ case TEnumerated: {
+ Member *m;
+
+ if (t->symbol && t->symbol->emitted_definition)
+ break;
+
+ label_prefix = prefix_enum ? name : (enum_prefix ? enum_prefix : "");
+ label_prefix_sep = prefix_enum ? "_" : "";
+ space(level);
+ fprintf (headerfile, "enum %s {\n", (opts & DEF_TYPE_TYPEDEFP) ? name : "");
+ fprintf(jsonfile, "\"ctype\":\"enum %s\",\"extensible\":%s,\"members\":[\n",
+ (opts & DEF_TYPE_TYPEDEFP) ? name : "", have_ellipsis(t) ? "true" : "false");
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ space(level + 1);
+ if (m->ellipsis) {
+ fprintf (headerfile, "/* ... */\n");
+ } else {
+ fprintf(headerfile, "%s%s%s = %lld%s\n",
+ label_prefix, label_prefix_sep,
+ m->gen_name, (long long)m->val, last_member_p(m));
+ fprintf(jsonfile, "{\"%s%s%s\":%lld%s}\n",
+ label_prefix, label_prefix_sep,
+ m->gen_name, (long long)m->val, last_member_p(m));
+ }
+ }
+ space(level);
+ fprintf(headerfile, "}%s%s;\n\n",
+ (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
+ (opts & DEF_TYPE_EMIT_NAME) ? name : "");
+ fprintf(jsonfile, "]");
+ break;
+ }
+ case TSet:
+ case TSequence: {
+ Member *m;
+ struct decoration deco;
+ ssize_t more_deco = -1;
+ int decorated = 0;
+
+ getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
+
+ space(level);
+
+ fprintf (headerfile, "struct %s {\n", newbasename);
+ fprintf(jsonfile, "\"ttype\":\"%s\",\"extensible\":%s,"
+ "\"ctype\":\"struct %s\"",
+ t->type == TSet ? "SET" : "SEQUENCE",
+ have_ellipsis(t) ? "true" : "false", newbasename);
+ if (t->type == TSequence && (opts & DEF_TYPE_PRESERVE)) {
+ space(level + 1);
+ fprintf(headerfile, "heim_octet_string _save;\n");
+ fprintf(jsonfile, ",\"preserve\":true");
+ }
+ fprintf(jsonfile, ",\"members\":[\n");
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ if (m->ellipsis) {
+ ;
+ } else if (m->optional || m->defval) {
+ char *n = NULL, *defval = NULL;
+ const char *namep, *defvalp;
+
+ if (m->defval) {
+ switch (m->defval->type) {
+ case stringvalue:
+ if (asprintf(&defval, "\"%s\"", m->defval->u.stringvalue) < 0 || defval == NULL)
+ errx(1, "malloc");
+ defvalp = defval;
+ break;
+ case integervalue:
+ if (asprintf(&defval, "%lld", (long long)m->defval->u.integervalue) < 0 || defval == NULL)
+ errx(1, "malloc");
+ defvalp = defval;
+ break;
+ case booleanvalue:
+ defvalp = m->defval->u.booleanvalue ? "true" : "false";
+ break;
+ default:
+ abort();
+ }
+ } else
+ defvalp = "null";
+
+ if (m->optional) {
+ if (asprintf(&n, "*%s", m->gen_name) < 0 || n == NULL)
+ errx(1, "malloc");
+ namep = n;
+ } else
+ namep = m->gen_name;
+
+ fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
+ "\"optional\":%s,\"defval\":%s,\"type\":",
+ m->name, m->gen_name, m->optional ? "true" : "false", defvalp);
+ define_type(level + 1, namep, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
+ fprintf(jsonfile, "}%s", last_member_p(m));
+ free (n);
+ free (defval);
+ } else {
+ fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
+ "\"optional\":false,\"type\":", m->name, m->gen_name);
+ define_type(level + 1, m->gen_name, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
+ fprintf(jsonfile, "}%s", last_member_p(m));
+ }
+ }
+ fprintf(jsonfile, "]");
+ if (t->actual_parameter && t->actual_parameter->objects) {
+ fprintf(jsonfile, ",\"opentype\":");
+ define_open_type(level, newbasename, name, basename, t, t);
+ }
+ while (decorate_type(newbasename, &deco, &more_deco)) {
+ decorated++;
+ space(level + 1);
+ fprintf(headerfile, "%s %s%s;\n", deco.field_type,
+ deco.opt ? "*" : "", deco.field_name);
+ if (deco.first)
+ fprintf(jsonfile, ",\"decorate\":[");
+ fprintf(jsonfile, "%s{"
+ "\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
+ "\"external\":%s,\"pointer\":%s,\"void_star\":%s,"
+ "\"struct_star\":%s,"
+ "\"copy_function\":\"%s\","
+ "\"free_function\":\"%s\",\"header_name\":%s%s%s"
+ "}",
+ deco.first ? "" : ",",
+ deco.field_type, deco.field_name,
+ deco.opt ? "true" : "false", deco.ext ? "true" : "false",
+ deco.ptr ? "true" : "false", deco.void_star ? "true" : "false",
+ deco.struct_star ? "true" : "false",
+ deco.copy_function_name ? deco.copy_function_name : "",
+ deco.free_function_name ? deco.free_function_name : "",
+ deco.header_name && deco.header_name[0] == '"' ? "" : "\"",
+ deco.header_name ? deco.header_name : "",
+ deco.header_name && deco.header_name[0] == '"' ? "" : "\""
+ );
+ }
+ if (decorated)
+ fprintf(jsonfile, "]");
+ space(level);
+ fprintf(headerfile, "}%s%s;\n",
+ (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
+ (opts & DEF_TYPE_EMIT_NAME) ? name : "");
+ free(deco.field_type);
+ break;
+ }
+ case TSetOf:
+ case TSequenceOf: {
+ Type i;
+ struct range range = { 0, UINT_MAX };
+
+ getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
+
+ memset(&i, 0, sizeof(i));
+ i.type = TInteger;
+ i.range = &range;
+
+ space(level);
+ fprintf (headerfile, "struct %s {\n", newbasename);
+ fprintf(jsonfile, "\"ttype\":\"%s\",\"ctype\":\"struct %s\",\"members\":[",
+ t->type == TSetOf ? "SET OF" : "SEQUENCE OF", newbasename);
+ define_type(level + 1, "len", newbasename, t, &i, DEF_TYPE_NONE);
+ fprintf(jsonfile, ",");
+ define_type(level + 1, "*val", newbasename, t, t->subtype, DEF_TYPE_NONE | DEF_TYPE_EMIT_NAME);
+ space(level);
+ fprintf(headerfile, "}%s%s;\n",
+ (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
+ (opts & DEF_TYPE_EMIT_NAME) ? name : "");
+ fprintf(jsonfile, "]");
+ break;
+ }
+ case TGeneralizedTime:
+ space(level);
+ fprintf (headerfile, "time_t %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"GeneralizedTime\",\"ctype\":\"time_t\"");
+ break;
+ case TGeneralString:
+ space(level);
+ fprintf (headerfile, "heim_general_string %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"GeneralString\",\"ctype\":\"heim_general_string\"");
+ break;
+ case TTeletexString:
+ space(level);
+ fprintf (headerfile, "heim_general_string %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"TeletexString\",\"ctype\":\"heim_general_string\"");
+ break;
+ case TTag:
+ if (t->implicit_choice) {
+ fprintf(jsonfile, "\"desired_tagenv\":\"IMPLICIT\",");
+ }
+ fprintf(jsonfile, "\"tagclass\":\"%s\",\"tagvalue\":%d,\"tagenv\":\"%s\",\n",
+ tagclassnames[t->tag.tagclass], t->tag.tagvalue,
+ t->tag.tagenv == TE_EXPLICIT ? "EXPLICIT" : "IMPLICIT");
+ fprintf(jsonfile, "\"ttype\":\n");
+ define_type(level, name, basename, t, t->subtype, opts);
+ break;
+ case TChoice: {
+ struct decoration deco;
+ ssize_t more_deco = -1;
+ int decorated = 0;
+ int first = 1;
+ Member *m;
+
+ getnewbasename(&newbasename, (opts & DEF_TYPE_TYPEDEFP) || level == 0, basename, name);
+
+ space(level);
+ fprintf (headerfile, "struct %s {\n", newbasename);
+ fprintf(jsonfile, "\"ttype\":\"CHOICE\",\"ctype\":\"struct %s\"",
+ newbasename);
+ if ((opts & DEF_TYPE_PRESERVE)) {
+ space(level + 1);
+ fprintf(headerfile, "heim_octet_string _save;\n");
+ fprintf(jsonfile, ",\"preserve\":true");
+ }
+ space(level + 1);
+ fprintf (headerfile, "enum %s_enum {\n", newbasename);
+ m = have_ellipsis(t);
+ if (m) {
+ space(level + 2);
+ fprintf (headerfile, "%s = 0,\n", m->label);
+ first = 0;
+ }
+ fprintf(jsonfile, ",\"extensible\":%s", m ? "true" : "false");
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ space(level + 2);
+ if (m->ellipsis)
+ fprintf (headerfile, "/* ... */\n");
+ else
+ fprintf (headerfile, "%s%s%s\n", m->label,
+ first ? " = 1" : "",
+ last_member_p(m));
+ first = 0;
+ }
+ space(level + 1);
+ fprintf (headerfile, "} element;\n");
+ space(level + 1);
+ fprintf (headerfile, "union {\n");
+ fprintf(jsonfile, ",\"members\":[\n");
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ if (m->ellipsis) {
+ space(level + 2);
+ fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
+ } else if (m->optional) {
+ char *n = NULL;
+
+ if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)
+ errx(1, "malloc");
+ fprintf(jsonfile, "{\"optional\":");
+ define_type(level + 2, n, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
+ fprintf(jsonfile, "}%s", last_member_p(m));
+ free (n);
+ } else {
+ define_type(level + 2, m->gen_name, newbasename, t, m->type, DEF_TYPE_EMIT_NAME);
+ fprintf(jsonfile, "%s", last_member_p(m));
+ }
+ }
+ space(level + 1);
+ fprintf (headerfile, "} u;\n");
+ fprintf(jsonfile, "]");
+
+ while (decorate_type(newbasename, &deco, &more_deco)) {
+ decorated++;
+ space(level + 1);
+ fprintf(headerfile, "%s %s%s;\n", deco.field_type,
+ deco.opt ? "*" : "", deco.field_name);
+ if (deco.first)
+ fprintf(jsonfile, ",\"decorate\":[");
+ fprintf(jsonfile, "%s{"
+ "\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
+ "\"external\":%s,\"pointer\":%s,\"void_star\":%s,"
+ "\"struct_star\":%s,"
+ "\"copy_function\":\"%s\","
+ "\"free_function\":\"%s\",\"header_name\":%s%s%s"
+ "}",
+ deco.first ? "" : ",",
+ deco.field_type, deco.field_name,
+ deco.opt ? "true" : "false", deco.ext ? "true" : "false",
+ deco.ptr ? "true" : "false", deco.void_star ? "true" : "false",
+ deco.struct_star ? "true" : "false",
+ deco.copy_function_name ? deco.copy_function_name : "",
+ deco.free_function_name ? deco.free_function_name : "",
+ deco.header_name && deco.header_name[0] == '"' ? "" : "\"",
+ deco.header_name ? deco.header_name : "",
+ deco.header_name && deco.header_name[0] == '"' ? "" : "\""
+ );
+ }
+ if (decorated)
+ fprintf(jsonfile, "]");
+
+ space(level);
+ fprintf(headerfile, "}%s%s;\n",
+ (opts & DEF_TYPE_EMIT_NAME) ? " " : "",
+ (opts & DEF_TYPE_EMIT_NAME) ? name : "");
+ break;
+ }
+ case TUTCTime:
+ space(level);
+ fprintf (headerfile, "time_t %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"UTCTime\",\"ctype\":\"time_t\"");
+ break;
+ case TUTF8String:
+ space(level);
+ fprintf (headerfile, "heim_utf8_string %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"UTF8String\",\"ctype\":\"heim_utf8_string\"");
+ break;
+ case TPrintableString:
+ space(level);
+ fprintf (headerfile, "heim_printable_string %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"PrintableString\",\"ctype\":\"heim_printable_string\"");
+ break;
+ case TIA5String:
+ space(level);
+ fprintf (headerfile, "heim_ia5_string %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"IA5String\",\"ctype\":\"heim_ia5_string\"");
+ break;
+ case TBMPString:
+ space(level);
+ fprintf (headerfile, "heim_bmp_string %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"BMPString\",\"ctype\":\"heim_bmp_string\"");
+ break;
+ case TUniversalString:
+ space(level);
+ fprintf (headerfile, "heim_universal_string %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"UniversalString\",\"ctype\":\"heim_universal_string\"");
+ break;
+ case TVisibleString:
+ space(level);
+ fprintf (headerfile, "heim_visible_string %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"VisibleString\",\"ctype\":\"heim_visible_string\"");
+ break;
+ case TOID :
+ space(level);
+ fprintf (headerfile, "heim_oid %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"OBJECT IDENTIFIER\",\"ctype\":\"heim_oid\"");
+ break;
+ case TNull:
+ space(level);
+ fprintf (headerfile, "int %s;\n", name);
+ fprintf(jsonfile, "\"ttype\":\"NULL\",\"ctype\":\"int\"");
+ break;
+ default:
+ abort ();
+ }
+ fprintf(jsonfile, "}\n");
+ free(newbasename);
+}
+
+static void
+declare_type(const Symbol *s, Type *t, int typedefp)
+{
+ char *newbasename = NULL;
+
+ if (typedefp)
+ fprintf(headerfile, "typedef ");
+
+ switch (t->type) {
+ case TType:
+ define_type(0, s->gen_name, s->gen_name, NULL, s->type,
+ DEF_TYPE_PRESERVE | DEF_TYPE_TYPEDEFP |
+ (s->emitted_declaration ? 0 : DEF_TYPE_EMIT_NAME));
+ if (template_flag && !s->emitted_declaration)
+ generate_template_type_forward(s->gen_name);
+ emitted_declaration(s);
+ return;
+ case TInteger:
+ case TBoolean:
+ case TOctetString:
+ case TBitString:
+ case TEnumerated:
+ case TGeneralizedTime:
+ case TGeneralString:
+ case TTeletexString:
+ case TUTCTime:
+ case TUTF8String:
+ case TPrintableString:
+ case TIA5String:
+ case TBMPString:
+ case TUniversalString:
+ case TVisibleString:
+ case TOID :
+ case TNull:
+ define_type(0, s->gen_name, s->gen_name, NULL, s->type,
+ DEF_TYPE_PRESERVE | DEF_TYPE_TYPEDEFP |
+ (s->emitted_declaration ? 0 : DEF_TYPE_EMIT_NAME));
+ if (template_flag && !s->emitted_declaration)
+ generate_template_type_forward(s->gen_name);
+ emitted_declaration(s);
+ emitted_definition(s);
+ return;
+ case TTag:
+ if (!s->emitted_declaration)
+ declare_type(s, t->subtype, FALSE);
+ emitted_declaration(s);
+ return;
+ default:
+ break;
+ }
+
+ switch (t->type) {
+ case TSet:
+ case TSequence: {
+ struct decoration deco;
+ ssize_t more_deco = -1;
+
+ getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
+ fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
+ while (decorate_type(newbasename, &deco, &more_deco)) {
+ if (deco.header_name)
+ fprintf(headerfile, "#include %s\n", deco.header_name);
+ free(deco.field_type);
+ }
+ break;
+ }
+ case TSetOf:
+ case TSequenceOf:
+ getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
+ fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
+ break;
+ case TChoice: {
+ struct decoration deco;
+ ssize_t more_deco = -1;
+
+ getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
+ fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
+ while (decorate_type(newbasename, &deco, &more_deco)) {
+ if (deco.header_name)
+ fprintf(headerfile, "#include %s\n", deco.header_name);
+ free(deco.field_type);
+ }
+ break;
+ }
+ default:
+ abort ();
+ }
+ free(newbasename);
+ emitted_declaration(s);
+}
+
+static void generate_subtypes_header_helper(const Member *m);
+static void generate_type_header(const Symbol *);
+
+static void
+generate_subtypes_header_helper(const Member *m)
+{
+ Member *sm;
+ Symbol *s;
+
+ if (m->ellipsis)
+ return;
+ if (m->type->symbol && (s = getsym(m->type->symbol->name)) &&
+ !s->emitted_definition) {
+ /* A field of some named type; recurse */
+ if (!m->optional && !m->defval)
+ generate_type_header(s);
+ return;
+ }
+ if (!m->type->subtype && !m->type->members)
+ return;
+ if (m->type->type == TTag &&
+ m->type->subtype && m->type->subtype->symbol &&
+ (s = getsym(m->type->subtype->symbol->name))) {
+ if (!m->optional && !m->defval)
+ generate_type_header(s);
+ return;
+ }
+ if (m->type->subtype) {
+ switch (m->type->subtype->type) {
+ case TSet:
+ case TSequence:
+ case TChoice:
+ break;
+ default:
+ return;
+ }
+ /* A field of some anonymous (inlined) structured type */
+ HEIM_TAILQ_FOREACH(sm, m->type->subtype->members, members) {
+ generate_subtypes_header_helper(sm);
+ }
+ }
+ if (m->type->members) {
+ HEIM_TAILQ_FOREACH(sm, m->type->members, members) {
+ generate_subtypes_header_helper(sm);
+ }
+ }
+}
+
+static void
+generate_subtypes_header(const Symbol *s)
+{
+ Type *t = s->type;
+ Member *m;
+
+ /*
+ * Recurse down structured types to make sure top-level types get
+ * defined before they are referenced.
+ *
+ * We'll take care to skip OPTIONAL member fields of constructed types so
+ * that we can have circular types like:
+ *
+ * Foo ::= SEQUENCE {
+ * bar Bar OPTIONAL
+ * }
+ *
+ * Bar ::= SEQUENCE {
+ * foo Foo OPTIONAL
+ * }
+ *
+ * not unlike XDR, which uses `*' to mean "optional", except in XDR it's
+ * called a "pointer". With some care we should be able to eventually
+ * support the silly XDR linked list example:
+ *
+ * ListOfFoo ::= SEQUENCE {
+ * someField SomeType,
+ * next ListOfFoo OPTIONAL
+ * }
+ *
+ * Not that anyone needs it -- just use a SEQUENCE OF and be done.
+ */
+
+ while (t->type == TTag && t->subtype) {
+ switch (t->subtype->type) {
+ case TTag:
+ case TSet:
+ case TSequence:
+ case TChoice:
+ t = t->subtype;
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+
+ switch (t->type) {
+ default: return;
+ case TType: {
+ Symbol *s2;
+ if (t->symbol && (s2 = getsym(t->symbol->name)) != s)
+ generate_type_header(s2);
+ return;
+ }
+ case TSet:
+ case TSequence:
+ case TChoice:
+ break;
+ }
+
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ generate_subtypes_header_helper(m);
+ }
+}
+
+static void
+generate_type_header (const Symbol *s)
+{
+ Type *t = s->type;
+
+ if (!s->type)
+ return;
+
+ /*
+ * Recurse down the types of member fields of `s' to make sure that
+ * referenced types have had their definitions emitted already if the
+ * member fields are not OPTIONAL/DEFAULTed.
+ */
+ generate_subtypes_header(s);
+ if (!s->emitted_asn1) {
+ fprintf(headerfile, "/*\n");
+ fprintf(headerfile, "%s ::= ", s->name);
+ define_asn1 (0, s->type);
+ fprintf(headerfile, "\n*/\n\n");
+ emitted_asn1(s);
+ }
+
+ /*
+ * Emit enums for the outermost tag of this type. These are needed for
+ * dealing with IMPLICIT tags so we know what to rewrite the tag to when
+ * decoding.
+ *
+ * See gen_encode.c and gen_decode.c for a complete explanation. Short
+ * version: we need to change the prototypes of the length/encode/decode
+ * functions to take an optional IMPLICIT tag to use instead of the type's
+ * outermost tag, but for now we hack it, and to do that we need to know
+ * the type's outermost tag outside the context of the bodies of the codec
+ * functions we generate for it. Using an enum means no extra space is
+ * needed in stripped objects.
+ */
+ if (!s->emitted_tag_enums) {
+ while (t->type == TType && s->type->symbol && s->type->symbol->type) {
+ if (t->subtype)
+ t = t->subtype;
+ else
+ t = s->type->symbol->type;
+ }
+
+ if (t->type == TType && t->symbol &&
+ strcmp(t->symbol->name, "HEIM_ANY") != 0) {
+ /*
+ * This type is ultimately an alias of an imported type, so we don't
+ * know its outermost tag here.
+ */
+ fprintf(headerfile,
+ "enum { asn1_tag_length_%s = asn1_tag_length_%s,\n"
+ " asn1_tag_class_%s = asn1_tag_class_%s,\n"
+ " asn1_tag_tag_%s = asn1_tag_tag_%s };\n",
+ s->gen_name, s->type->symbol->gen_name,
+ s->gen_name, s->type->symbol->gen_name,
+ s->gen_name, s->type->symbol->gen_name);
+ emitted_tag_enums(s);
+ } else if (t->type != TType) {
+ /* This type's outermost tag is known here */
+ fprintf(headerfile,
+ "enum { asn1_tag_length_%s = %lu,\n"
+ " asn1_tag_class_%s = %d,\n"
+ " asn1_tag_tag_%s = %d };\n",
+ s->gen_name, (unsigned long)length_tag(s->type->tag.tagvalue),
+ s->gen_name, s->type->tag.tagclass,
+ s->gen_name, s->type->tag.tagvalue);
+ emitted_tag_enums(s);
+ }
+ }
+
+ if (s->emitted_definition)
+ return;
+
+ if (is_export(s->name))
+ fprintf(symsfile, "ASN1_SYM_TYPE(\"%s\", \"%s\", %s)\n",
+ s->name, s->gen_name, s->gen_name);
+
+ if (!s->emitted_declaration) {
+ fprintf(headerfile, "typedef ");
+ define_type(0, s->gen_name, s->gen_name, NULL, s->type,
+ DEF_TYPE_TYPEDEFP | DEF_TYPE_EMIT_NAME |
+ (preserve_type(s->name) ? DEF_TYPE_PRESERVE : 0));
+ } else if (s->type->type == TType) {
+ /* This is a type alias and we've already declared it */
+ } else if (s->type->type == TTag &&
+ s->type->subtype != NULL &&
+ s->type->subtype->symbol != NULL) {
+ /* This is a type alias and we've already declared it */
+ } else {
+ define_type(0, s->gen_name, s->gen_name, NULL, s->type,
+ DEF_TYPE_TYPEDEFP |
+ (preserve_type(s->name) ? DEF_TYPE_PRESERVE : 0));
+ }
+ fprintf(headerfile, "\n");
+
+ emitted_definition(s);
+}
+
+void
+generate_type_header_forwards(const Symbol *s)
+{
+ declare_type(s, s->type, TRUE);
+ fprintf(headerfile, "\n");
+ if (template_flag)
+ generate_template_type_forward(s->gen_name);
+}
+
+void
+generate_type (const Symbol *s)
+{
+ FILE *h;
+ const char * exp;
+
+ if (!one_code_file)
+ generate_header_of_codefile(s->gen_name);
+
+ generate_type_header(s);
+
+ if (template_flag)
+ generate_template(s);
+
+ if (template_flag == 0 || is_template_compat(s) == 0) {
+ generate_type_encode (s);
+ generate_type_decode (s);
+ generate_type_free (s);
+ generate_type_length (s);
+ generate_type_copy (s);
+ generate_type_print_stub(s);
+ }
+ generate_type_seq (s);
+ generate_glue (s->type, s->gen_name);
+
+ /* generate prototypes */
+
+ if (is_export(s->name)) {
+ h = headerfile;
+ exp = "ASN1EXP ";
+ } else {
+ h = privheaderfile;
+ exp = "";
+ }
+
+ fprintf (h,
+ "%sint ASN1CALL "
+ "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
+ exp,
+ s->gen_name, s->gen_name);
+ fprintf (h,
+ "%sint ASN1CALL "
+ "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
+ exp,
+ s->gen_name, s->gen_name);
+ fprintf (h,
+ "%ssize_t ASN1CALL length_%s(const %s *);\n",
+ exp,
+ s->gen_name, s->gen_name);
+ fprintf (h,
+ "%sint ASN1CALL copy_%s (const %s *, %s *);\n",
+ exp,
+ s->gen_name, s->gen_name, s->gen_name);
+ fprintf (h,
+ "%svoid ASN1CALL free_%s (%s *);\n",
+ exp,
+ s->gen_name, s->gen_name);
+
+ fprintf(h,
+ "%schar * ASN1CALL print_%s (const %s *, int);\n",
+ exp,
+ s->gen_name, s->gen_name);
+
+ fprintf(h, "\n\n");
+
+ if (!one_code_file) {
+ fprintf(codefile, "\n\n");
+ close_codefile();
+ }
+}
diff --git a/third_party/heimdal/lib/asn1/gen_copy.c b/third_party/heimdal/lib/asn1/gen_copy.c
new file mode 100644
index 0000000..c6d420a
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/gen_copy.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gen_locl.h"
+
+RCSID("$Id$");
+
+static int used_fail;
+
+static void
+copy_primitive (const char *typename, const char *from, const char *to)
+{
+ fprintf (codefile, "if(der_copy_%s(%s, %s)) goto fail;\n",
+ typename, from, to);
+ used_fail++;
+}
+
+static void
+copy_type (const char *from, const char *to, const Type *t, int preserve)
+{
+ switch (t->type) {
+ case TType:
+#if 0
+ copy_type (from, to, t->symbol->type, preserve);
+#endif
+ fprintf (codefile, "if(copy_%s(%s, %s)) goto fail;\n",
+ t->symbol->gen_name, from, to);
+ used_fail++;
+ break;
+ case TInteger:
+ if (t->range == NULL && t->members == NULL) {
+ copy_primitive ("heim_integer", from, to);
+ break;
+ }
+ HEIM_FALLTHROUGH;
+ case TBoolean:
+ case TEnumerated :
+ fprintf(codefile, "*(%s) = *(%s);\n", to, from);
+ break;
+ case TOctetString:
+ copy_primitive ("octet_string", from, to);
+ break;
+ case TBitString:
+ if (HEIM_TAILQ_EMPTY(t->members))
+ copy_primitive ("bit_string", from, to);
+ else
+ fprintf(codefile, "*(%s) = *(%s);\n", to, from);
+ break;
+ case TSet:
+ case TSequence:
+ case TChoice: {
+ Member *m, *have_ellipsis = NULL;
+
+ if(t->members == NULL)
+ break;
+
+ if ((t->type == TSequence || t->type == TChoice) && preserve) {
+ fprintf(codefile,
+ "{ int ret;\n"
+ "ret = der_copy_octet_string(&(%s)->_save, &(%s)->_save);\n"
+ "if (ret) goto fail;\n"
+ "}\n",
+ from, to);
+ used_fail++;
+ }
+
+ if(t->type == TChoice) {
+ fprintf(codefile, "(%s)->element = (%s)->element;\n", to, from);
+ fprintf(codefile, "switch((%s)->element) {\n", from);
+ }
+
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ char *fs;
+ char *ts;
+
+ if (m->ellipsis) {
+ have_ellipsis = m;
+ continue;
+ }
+
+ if(t->type == TChoice)
+ fprintf(codefile, "case %s:\n", m->label);
+
+ if (asprintf (&fs, "%s(%s)->%s%s",
+ m->optional ? "" : "&", from,
+ t->type == TChoice ? "u." : "", m->gen_name) < 0)
+ errx(1, "malloc");
+ if (fs == NULL)
+ errx(1, "malloc");
+ if (asprintf (&ts, "%s(%s)->%s%s",
+ m->optional ? "" : "&", to,
+ t->type == TChoice ? "u." : "", m->gen_name) < 0)
+ errx(1, "malloc");
+ if (ts == NULL)
+ errx(1, "malloc");
+ if(m->optional){
+ fprintf(codefile, "if(%s) {\n", fs);
+ fprintf(codefile, "%s = calloc(1, sizeof(*%s));\n", ts, ts);
+ fprintf(codefile, "if(%s == NULL) goto fail;\n", ts);
+ used_fail++;
+ }
+ copy_type (fs, ts, m->type, FALSE);
+ if(m->optional){
+ fprintf(codefile, "}else\n");
+ fprintf(codefile, "%s = NULL;\n", ts);
+ }
+ free (fs);
+ free (ts);
+ if(t->type == TChoice)
+ fprintf(codefile, "break;\n");
+ }
+ if(t->type == TChoice) {
+ if (have_ellipsis) {
+ fprintf(codefile, "case %s: {\n"
+ "int ret;\n"
+ "ret=der_copy_octet_string(&(%s)->u.%s, &(%s)->u.%s);\n"
+ "if (ret) goto fail;\n"
+ "break;\n"
+ "}\n",
+ have_ellipsis->label,
+ from, have_ellipsis->gen_name,
+ to, have_ellipsis->gen_name);
+ used_fail++;
+ }
+ fprintf(codefile, "}\n");
+ }
+ break;
+ }
+ case TSetOf:
+ case TSequenceOf: {
+ char *f = NULL, *T = NULL;
+
+ fprintf (codefile, "if(((%s)->val = "
+ "calloc(1, (%s)->len * sizeof(*(%s)->val))) == NULL && (%s)->len != 0)\n",
+ to, from, to, from);
+ fprintf (codefile, "goto fail;\n");
+ used_fail++;
+ fprintf(codefile,
+ "for((%s)->len = 0; (%s)->len < (%s)->len; (%s)->len++){\n",
+ to, to, from, to);
+ if (asprintf(&f, "&(%s)->val[(%s)->len]", from, to) < 0)
+ errx(1, "malloc");
+ if (f == NULL)
+ errx(1, "malloc");
+ if (asprintf(&T, "&(%s)->val[(%s)->len]", to, to) < 0)
+ errx(1, "malloc");
+ if (T == NULL)
+ errx(1, "malloc");
+ copy_type(f, T, t->subtype, FALSE);
+ fprintf(codefile, "}\n");
+ free(f);
+ free(T);
+ break;
+ }
+ case TGeneralizedTime:
+ fprintf(codefile, "*(%s) = *(%s);\n", to, from);
+ break;
+ case TGeneralString:
+ copy_primitive ("general_string", from, to);
+ break;
+ case TTeletexString:
+ copy_primitive ("general_string", from, to);
+ break;
+ case TUTCTime:
+ fprintf(codefile, "*(%s) = *(%s);\n", to, from);
+ break;
+ case TUTF8String:
+ copy_primitive ("utf8string", from, to);
+ break;
+ case TPrintableString:
+ copy_primitive ("printable_string", from, to);
+ break;
+ case TIA5String:
+ copy_primitive ("ia5_string", from, to);
+ break;
+ case TBMPString:
+ copy_primitive ("bmp_string", from, to);
+ break;
+ case TUniversalString:
+ copy_primitive ("universal_string", from, to);
+ break;
+ case TVisibleString:
+ copy_primitive ("visible_string", from, to);
+ break;
+ case TTag:
+ copy_type (from, to, t->subtype, preserve);
+ break;
+ case TOID:
+ copy_primitive ("oid", from, to);
+ break;
+ case TNull:
+ break;
+ default :
+ abort ();
+ }
+}
+
+void
+generate_type_copy (const Symbol *s)
+{
+ struct decoration deco;
+ ssize_t more_deco = -1;
+ int preserve = preserve_type(s->name) ? TRUE : FALSE;
+ int save_used_fail = used_fail;
+
+ used_fail = 0;
+
+ fprintf (codefile, "int ASN1CALL\n"
+ "copy_%s(const %s *from, %s *to)\n"
+ "{\n"
+ "memset(to, 0, sizeof(*to));\n",
+ s->gen_name, s->gen_name, s->gen_name);
+ copy_type ("from", "to", s->type, preserve);
+ while (decorate_type(s->gen_name, &deco, &more_deco)) {
+ if (deco.ext && deco.copy_function_name == NULL) {
+ /* Decorated with field of external type but no copy function */
+ if (deco.ptr)
+ fprintf(codefile, "(to)->%s = 0;\n", deco.field_name);
+ else
+ fprintf(codefile, "memset(&(to)->%s, 0, sizeof((to)->%s));\n",
+ deco.field_name, deco.field_name);
+ } else if (deco.ext) {
+ /* Decorated with field of external type w/ copy function */
+ if (deco.ptr) {
+ fprintf(codefile, "if (from->%s) {\n", deco.field_name);
+ fprintf(codefile, "(to)->%s = calloc(1, sizeof(*(to)->%s));\n",
+ deco.field_name, deco.field_name);
+ fprintf(codefile, "if (%s((from)->%s, (to)->%s)) goto fail;\n",
+ deco.copy_function_name, deco.field_name, deco.field_name);
+ fprintf(codefile, "}\n");
+ } else {
+ fprintf(codefile, "if (%s(&(from)->%s, &(to)->%s)) goto fail;\n",
+ deco.copy_function_name, deco.field_name, deco.field_name);
+ }
+ } else if (deco.opt) {
+ /* Decorated with optional field of ASN.1 type */
+ fprintf(codefile, "if (from->%s) {\n", deco.field_name);
+ fprintf(codefile, "(to)->%s = calloc(1, sizeof(*(to)->%s));\n", deco.field_name, deco.field_name);
+ fprintf(codefile, "if (copy_%s((from)->%s, (to)->%s)) goto fail;\n", deco.field_type, deco.field_name, deco.field_name);
+ fprintf(codefile, "}\n");
+ } else {
+ /* Decorated with required field of ASN.1 type */
+ fprintf(codefile, "if (copy_%s(&(from)->%s, &(to)->%s)) goto fail;\n", deco.field_type, deco.field_name, deco.field_name);
+ }
+ used_fail++;
+ free(deco.field_type);
+ }
+ fprintf (codefile, "return 0;\n");
+
+ if (used_fail)
+ fprintf (codefile, "fail:\n"
+ "free_%s(to);\n"
+ "return ENOMEM;\n",
+ s->gen_name);
+
+ fprintf(codefile,
+ "}\n\n");
+ used_fail = save_used_fail;
+}
+
diff --git a/third_party/heimdal/lib/asn1/gen_decode.c b/third_party/heimdal/lib/asn1/gen_decode.c
new file mode 100644
index 0000000..fa9d79a
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/gen_decode.c
@@ -0,0 +1,841 @@
+/*
+ * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gen_locl.h"
+#include "lex.h"
+
+RCSID("$Id$");
+
+static void
+decode_primitive (const char *typename, const char *name, const char *forwstr)
+{
+#if 0
+ fprintf (codefile,
+ "e = decode_%s(p, len, %s, &l);\n"
+ "%s;\n",
+ typename,
+ name,
+ forwstr);
+#else
+ fprintf (codefile,
+ "e = der_get_%s(p, len, %s, &l);\n"
+ "if(e) %s;\np += l; len -= l; ret += l;\n",
+ typename,
+ name,
+ forwstr);
+#endif
+}
+
+static void
+find_tag (const Type *t,
+ Der_class *cl, Der_type *ty, unsigned *tag)
+{
+ switch (t->type) {
+ case TBitString:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_BitString;
+ break;
+ case TBoolean:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_Boolean;
+ break;
+ case TChoice:
+ errx(1, "Cannot have recursive CHOICE");
+ case TEnumerated:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_Enumerated;
+ break;
+ case TGeneralString:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_GeneralString;
+ break;
+ case TTeletexString:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_TeletexString;
+ break;
+ case TGeneralizedTime:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_GeneralizedTime;
+ break;
+ case TIA5String:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_IA5String;
+ break;
+ case TInteger:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_Integer;
+ break;
+ case TNull:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_Null;
+ break;
+ case TOID:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_OID;
+ break;
+ case TOctetString:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_OctetString;
+ break;
+ case TPrintableString:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_PrintableString;
+ break;
+ case TSequence:
+ case TSequenceOf:
+ *cl = ASN1_C_UNIV;
+ *ty = CONS;
+ *tag = UT_Sequence;
+ break;
+ case TSet:
+ case TSetOf:
+ *cl = ASN1_C_UNIV;
+ *ty = CONS;
+ *tag = UT_Set;
+ break;
+ case TTag:
+ *cl = t->tag.tagclass;
+ *ty = !(t->tag.tagclass != ASN1_C_UNIV &&
+ t->tag.tagenv == TE_EXPLICIT) &&
+ is_primitive_type(t->subtype) ? PRIM : CONS;
+ *tag = t->tag.tagvalue; /* XXX is this correct? */
+ break;
+ case TType:
+ if ((t->symbol->stype == Stype && t->symbol->type == NULL)
+ || t->symbol->stype == SUndefined) {
+ lex_error_message("%s is imported or still undefined, "
+ " can't generate tag checking data in CHOICE "
+ "without this information",
+ t->symbol->name);
+ exit(1);
+ }
+ find_tag(t->symbol->type, cl, ty, tag);
+ return;
+ case TUTCTime:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_UTCTime;
+ break;
+ case TUTF8String:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_UTF8String;
+ break;
+ case TBMPString:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_BMPString;
+ break;
+ case TUniversalString:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_UniversalString;
+ break;
+ case TVisibleString:
+ *cl = ASN1_C_UNIV;
+ *ty = PRIM;
+ *tag = UT_VisibleString;
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+range_check(const char *name,
+ const char *length,
+ const char *forwstr,
+ struct range *r)
+{
+ if (r->min == r->max + 2 || r->min < r->max)
+ fprintf (codefile,
+ "if ((%s)->%s > %lld) {\n"
+ "e = ASN1_MAX_CONSTRAINT; %s;\n"
+ "}\n",
+ name, length, (long long)r->max, forwstr);
+ if ((r->min - 1 == r->max || r->min < r->max) && r->min > 0)
+ fprintf (codefile,
+ "if ((%s)->%s < %lld) {\n"
+ "e = ASN1_MIN_CONSTRAINT; %s;\n"
+ "}\n",
+ name, length, (long long)r->min, forwstr);
+ if (r->max == r->min)
+ fprintf (codefile,
+ "if ((%s)->%s != %lld) {\n"
+ "e = ASN1_EXACT_CONSTRAINT; %s;\n"
+ "}\n",
+ name, length, (long long)r->min, forwstr);
+}
+
+static int
+decode_type(const char *name, const Type *t, int optional, struct value *defval,
+ const char *forwstr, const char *tmpstr, const char *dertype,
+ unsigned int depth)
+{
+ switch (t->type) {
+ case TType: {
+ if (optional)
+ fprintf(codefile,
+ "%s = calloc(1, sizeof(*%s));\n"
+ "if (%s == NULL) %s;\n",
+ name, name, name, forwstr);
+ fprintf (codefile,
+ "e = decode_%s(p, len, %s, &l);\n",
+ t->symbol->gen_name, name);
+ if (optional) {
+ fprintf (codefile,
+ "if(e == ASN1_MISSING_FIELD) {\n"
+ "free(%s);\n"
+ "%s = NULL;\n"
+ "} else if (e) { %s; \n"
+ "} else {\n"
+ "p += l; len -= l; ret += l;\n"
+ "}\n",
+ name, name, forwstr);
+ } else if (defval) {
+ fprintf(codefile,
+ "if (e == ASN1_MISSING_FIELD) {\n");
+ /*
+ * `name' starts with an ampersand here and is not an lvalue.
+ * We skip the ampersand and then it is an lvalue.
+ */
+ gen_assign_defval(name + 1, defval);
+ fprintf(codefile,
+ "} else if (e) { %s;\n"
+ "} else { p += l; len -= l; ret += l; }\n",
+ forwstr);
+ } else {
+ fprintf (codefile,
+ "if(e) %s;\n",
+ forwstr);
+ fprintf (codefile,
+ "p += l; len -= l; ret += l;\n");
+ }
+ break;
+ }
+ case TInteger:
+ if(t->members) {
+ /*
+ * This will produce a worning, how its hard to fix since:
+ * if its enum to an NameType, we can add appriate
+ * type-cast. If its not though, we have to figure out if
+ * there is negative enum enum and use appropriate
+ * signness and size on the intertype we cast the result
+ * too.
+ */
+ fprintf(codefile,
+ "{\n"
+ "int enumint;\n");
+ decode_primitive ("integer", "&enumint", forwstr);
+ fprintf(codefile,
+ "*%s = enumint;\n"
+ "}\n",
+ name);
+ } else if (t->range == NULL) {
+ decode_primitive ("heim_integer", name, forwstr);
+ } else if (t->range->min < 0 &&
+ (t->range->min < INT_MIN || t->range->max > INT_MAX)) {
+ decode_primitive ("integer64", name, forwstr);
+ } else if (t->range->min < 0) {
+ decode_primitive ("integer", name, forwstr);
+ } else if (t->range->max > UINT_MAX) {
+ decode_primitive ("unsigned64", name, forwstr);
+ } else {
+ decode_primitive ("unsigned", name, forwstr);
+ }
+ break;
+ case TBoolean:
+ decode_primitive ("boolean", name, forwstr);
+ break;
+ case TEnumerated:
+ decode_primitive ("enumerated", name, forwstr);
+ break;
+ case TOctetString:
+ if (dertype) {
+ fprintf(codefile,
+ "if (%s == CONS) {\n",
+ dertype);
+ decode_primitive("octet_string_ber", name, forwstr);
+ fprintf(codefile,
+ "} else {\n");
+ }
+ decode_primitive ("octet_string", name, forwstr);
+ if (dertype)
+ fprintf(codefile, "}\n");
+ if (t->range)
+ range_check(name, "length", forwstr, t->range);
+ break;
+ case TBitString: {
+ Member *m;
+ int pos = 0;
+
+ if (HEIM_TAILQ_EMPTY(t->members)) {
+ decode_primitive ("bit_string", name, forwstr);
+ break;
+ }
+ fprintf(codefile,
+ "if (len < 1) return ASN1_OVERRUN;\n"
+ "p++; len--; ret++;\n");
+ fprintf(codefile,
+ "do {\n"
+ "if (len < 1) break;\n");
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ while (m->val / 8 > pos / 8) {
+ fprintf (codefile,
+ "p++; len--; ret++;\n"
+ "if (len < 1) break;\n");
+ pos += 8;
+ }
+ fprintf(codefile,
+ "(%s)->%s = (*p >> %d) & 1;\n",
+ name, m->gen_name, (int)(7 - m->val % 8));
+ }
+ fprintf(codefile,
+ "} while(0);\n");
+ fprintf (codefile,
+ "p += len; ret += len;\n");
+ break;
+ }
+ case TSequence: {
+ Member *m;
+
+ if (t->members == NULL)
+ break;
+
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ char *s = NULL;
+
+ if (m->ellipsis)
+ continue;
+
+ if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&",
+ name, m->gen_name) < 0 || s == NULL)
+ errx(1, "malloc");
+ decode_type(s, m->type, m->optional, m->defval, forwstr,
+ m->gen_name, NULL, depth + 1);
+ free (s);
+ }
+
+ break;
+ }
+ case TSet: {
+ /*
+ * SET { ... } is the dumbest construct in ASN.1. It's semantically
+ * indistinguishable from SEQUENCE { ... } but in BER you can write the
+ * fields in any order you wish, and in DER you have to write them in
+ * lexicographic order. If you want a reason to hate ASN.1, this is
+ * certainly one, though the real reason to hate ASN.1 is BER/DER/CER,
+ * and, really, all tag-length-value (TLV) encodings ever invented,
+ * including Protocol Buffers. Fortunately not all ASN.1 encoding
+ * rules are TLV or otherwise self-describing. "Self-describing"
+ * encoding rules other than those meant to be [somewhat] readable by
+ * humans, such as XML and JSON, are simply dumb. But SET { ... } is a
+ * truly special sort of dumb. The only possible use of SET { ... }
+ * might well be for ASN.1 mappings of XML schemas(?).
+ */
+ Member *m;
+ unsigned int memno;
+
+ if(t->members == NULL)
+ break;
+
+ fprintf(codefile, "{\n");
+ fprintf(codefile, "uint64_t members = 0;\n");
+ fprintf(codefile, "while(len > 0) {\n");
+ fprintf(codefile,
+ "Der_class class;\n"
+ "Der_type type;\n"
+ "unsigned int tag;\n"
+ "e = der_get_tag (p, len, &class, &type, &tag, NULL);\n"
+ "if(e) %s;\n", forwstr);
+ fprintf(codefile, "switch (MAKE_TAG(class, type, tag)) {\n");
+ memno = 0;
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ Type *mst = m->type; /* Member sub-type */
+ char *s;
+
+ while (mst->type == TType) {
+ assert(mst->subtype || (mst->symbol && mst->symbol->type));
+ mst = mst->subtype ? mst->subtype : mst->symbol->type;
+ }
+ assert(mst->type == TTag);
+
+ fprintf(codefile, "case MAKE_TAG(%s, %s, %s):\n",
+ classname(mst->tag.tagclass),
+ (mst->tag.tagclass == ASN1_C_UNIV || mst->tag.tagenv == TE_IMPLICIT) &&
+ is_primitive_type(mst->subtype) ? "PRIM" : "CONS",
+ valuename(mst->tag.tagclass, mst->tag.tagvalue));
+
+ if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL)
+ errx(1, "malloc");
+ if(m->optional)
+ fprintf(codefile,
+ "%s = calloc(1, sizeof(*%s));\n"
+ "if (%s == NULL) { e = ENOMEM; %s; }\n",
+ s, s, s, forwstr);
+ decode_type (s, mst, 0, NULL, forwstr, m->gen_name, NULL, depth + 1);
+ free (s);
+
+ fprintf(codefile, "members |= (1ULL << %u);\n", memno);
+ memno++;
+ fprintf(codefile, "break;\n");
+ }
+ fprintf(codefile,
+ "default:\n"
+ "return ASN1_MISPLACED_FIELD;\n"
+ "break;\n");
+ fprintf(codefile, "}\n");
+ fprintf(codefile, "}\n");
+ memno = 0;
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ char *s;
+
+ if (asprintf (&s, "%s->%s", name, m->gen_name) < 0 || s == NULL)
+ errx(1, "malloc");
+ fprintf(codefile, "if((members & (1ULL << %u)) == 0)\n", memno);
+ if(m->optional)
+ fprintf(codefile, "%s = NULL;\n", s);
+ else if(m->defval)
+ gen_assign_defval(s, m->defval);
+ else
+ fprintf(codefile, "return ASN1_MISSING_FIELD;\n");
+ free(s);
+ memno++;
+ }
+ fprintf(codefile, "}\n");
+ break;
+ }
+ case TSetOf:
+ case TSequenceOf: {
+ char *n = NULL;
+ char *sname = NULL;
+
+ fprintf (codefile,
+ "{\n"
+ "size_t %s_origlen = len;\n"
+ "size_t %s_oldret = ret;\n"
+ "size_t %s_olen = 0;\n"
+ "void *%s_tmp;\n"
+ "ret = 0;\n"
+ "(%s)->len = 0;\n"
+ "(%s)->val = NULL;\n",
+ tmpstr,
+ tmpstr,
+ tmpstr,
+ tmpstr,
+ name,
+ name);
+
+ fprintf (codefile,
+ "while(ret < %s_origlen) {\n"
+ "size_t %s_nlen = %s_olen + sizeof(*((%s)->val));\n"
+ "if (%s_olen > %s_nlen) { e = ASN1_OVERFLOW; %s; }\n"
+ "%s_olen = %s_nlen;\n"
+ "%s_tmp = realloc((%s)->val, %s_olen);\n"
+ "if (%s_tmp == NULL) { e = ENOMEM; %s; }\n"
+ "(%s)->val = %s_tmp;\n",
+ tmpstr,
+ tmpstr, tmpstr, name,
+ tmpstr, tmpstr, forwstr,
+ tmpstr, tmpstr,
+ tmpstr, name, tmpstr,
+ tmpstr, forwstr,
+ name, tmpstr);
+
+ if (asprintf (&n, "&(%s)->val[(%s)->len]", name, name) < 0 || n == NULL)
+ errx(1, "malloc");
+ if (asprintf (&sname, "%s_s_of", tmpstr) < 0 || sname == NULL)
+ errx(1, "malloc");
+ decode_type(n, t->subtype, 0, NULL, forwstr, sname, NULL, depth + 1);
+ fprintf (codefile,
+ "(%s)->len++;\n"
+ "len = %s_origlen - ret;\n"
+ "}\n"
+ "ret += %s_oldret;\n"
+ "}\n",
+ name,
+ tmpstr, tmpstr);
+ if (t->range)
+ range_check(name, "len", forwstr, t->range);
+ free (n);
+ free (sname);
+ break;
+ }
+ case TGeneralizedTime:
+ decode_primitive ("generalized_time", name, forwstr);
+ break;
+ case TGeneralString:
+ decode_primitive ("general_string", name, forwstr);
+ break;
+ case TTeletexString:
+ decode_primitive ("general_string", name, forwstr);
+ break;
+ case TTag:{
+ char *tname = NULL, *typestring = NULL;
+ char *ide = NULL;
+ int replace_tag = 0;
+ int prim = !(t->tag.tagclass != ASN1_C_UNIV &&
+ t->tag.tagenv == TE_EXPLICIT) &&
+ is_primitive_type(t->subtype);
+
+ /*
+ * XXX See the comments in gen_encode() about this.
+ */
+ if (t->tag.tagenv == TE_IMPLICIT && !prim &&
+ t->subtype->type != TSequenceOf && t->subtype->type != TSetOf &&
+ t->subtype->type != TChoice) {
+ if (t->subtype->symbol &&
+ (t->subtype->type == TSequence ||
+ t->subtype->type == TSet))
+ replace_tag = 1;
+ else if (t->subtype->symbol &&
+ strcmp(t->subtype->symbol->name, "HEIM_ANY") != 0)
+ replace_tag = 1;
+ } else if (t->tag.tagenv == TE_IMPLICIT && prim && t->subtype->symbol)
+ replace_tag = is_tagged_type(t->subtype->symbol->type);
+
+ if (asprintf(&typestring, "%s_type", tmpstr) < 0 || typestring == NULL)
+ errx(1, "malloc");
+
+ fprintf(codefile,
+ "{\n"
+ "size_t %s_datalen;\n"
+ "Der_type %s;\n",
+ tmpstr, typestring);
+ if (replace_tag)
+ fprintf(codefile,
+ "const unsigned char *psave%u = p;\n"
+ "unsigned char *pcopy%u;\n"
+ "size_t lensave%u, lsave%u;\n",
+ depth, depth, depth, depth);
+ else if (support_ber)
+ fprintf(codefile,
+ "int is_indefinite%u;\n", depth);
+ if (!replace_tag)
+ fprintf(codefile,
+ "size_t %s_oldlen;\n", tmpstr);
+
+ fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, &%s, %s, "
+ "&%s_datalen, &l);\n",
+ classname(t->tag.tagclass),
+ typestring,
+ valuename(t->tag.tagclass, t->tag.tagvalue),
+ tmpstr);
+
+ /* XXX hardcode for now */
+ if (!replace_tag && support_ber && t->subtype->type == TOctetString) {
+ ide = typestring;
+ } else {
+ fprintf(codefile,
+ "if (e == 0 && %s != %s) { e = ASN1_BAD_ID; }\n",
+ typestring,
+ prim ? "PRIM" : "CONS");
+ }
+
+ if(optional) {
+ fprintf(codefile,
+ "if(e) {\n"
+ "%s = NULL;\n"
+ "} else {\n"
+ "%s = calloc(1, sizeof(*%s));\n"
+ "if (%s == NULL) { e = ENOMEM; %s; }\n",
+ name, name, name, name, forwstr);
+ } else if (defval) {
+ char *s;
+
+ if (asprintf(&s, "*(%s)", name) == -1 || s == NULL)
+ return ENOMEM;
+ fprintf(codefile, "if (e && e != ASN1_MISSING_FIELD) %s;\n", forwstr);
+ fprintf(codefile, "if (e == ASN1_MISSING_FIELD) {\n");
+ gen_assign_defval(s, defval);
+ free(s);
+ fprintf(codefile, "e = 0; l= 0;\n} else {\n");
+ } else {
+ fprintf(codefile, "if (e) %s;\n", forwstr);
+ }
+
+ if (replace_tag)
+ fprintf(codefile,
+ "lsave%u = %s_datalen + l;\n"
+ "lensave%u = len;\n"
+ "e = der_replace_tag(p, len, &pcopy%u, &len, asn1_tag_class_%s, %s, asn1_tag_tag_%s);\n"
+ "if (e) %s;\n"
+ "p = pcopy%u;\n",
+ depth, tmpstr, depth, depth, t->subtype->symbol->gen_name,
+ prim ? "PRIM" : "CONS",
+ t->subtype->symbol->gen_name,
+ forwstr, depth);
+ else
+ fprintf(codefile,
+ "p += l; len -= l; ret += l;\n");
+ if (!replace_tag)
+ fprintf(codefile,
+ "%s_oldlen = len;\n",
+ tmpstr);
+ if (support_ber && !replace_tag)
+ fprintf (codefile,
+ "if((is_indefinite%u = _heim_fix_dce(%s_datalen, &len)) < 0)\n"
+ "{ e = ASN1_BAD_FORMAT; %s; }\n"
+ "if (is_indefinite%u) { if (len < 2) { e = ASN1_OVERRUN; %s; } len -= 2; }",
+ depth, tmpstr, forwstr, depth, forwstr);
+ else if (!replace_tag)
+ fprintf(codefile,
+ "if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n"
+ "len = %s_datalen;\n", tmpstr, forwstr, tmpstr);
+ if (asprintf (&tname, "%s_Tag", tmpstr) < 0 || tname == NULL)
+ errx(1, "malloc");
+ /*
+ * If `replace_tag' then here `p' and `len' will be the copy mutated by
+ * der_replace_tag().
+ */
+ decode_type(name, t->subtype, 0, NULL, forwstr, tname, ide, depth + 1);
+ if (replace_tag)
+ fprintf(codefile,
+ "p = psave%u + lsave%u;\n"
+ "len = lensave%u - lsave%u;\n"
+ "ret += lsave%u - l;\n"
+ "free(pcopy%u);\n",
+ depth, depth, depth, depth, depth, depth);
+ else if(support_ber)
+ fprintf(codefile,
+ "if(is_indefinite%u){\n"
+ "len += 2;\n"
+ "e = der_match_tag_and_length(p, len, "
+ "(Der_class)0, &%s, UT_EndOfContent, "
+ "&%s_datalen, &l);\n"
+ "if(e) %s;\n"
+ "p += l; len -= l; ret += l;\n"
+ "if (%s != (Der_type)0) { e = ASN1_BAD_ID; %s; }\n"
+ "} else \n",
+ depth,
+ typestring,
+ tmpstr,
+ forwstr,
+ typestring, forwstr);
+ if (!replace_tag)
+ fprintf(codefile,
+ "len = %s_oldlen - %s_datalen;\n",
+ tmpstr, tmpstr);
+ if (optional)
+ fprintf(codefile, "}\n");
+ else if (defval)
+ fprintf(codefile, "}\n");
+ fprintf(codefile, "}\n");
+ free(tname);
+ free(typestring);
+ break;
+ }
+ case TChoice: {
+ Member *m, *have_ellipsis = NULL;
+ const char *els = "";
+
+ if (t->members == NULL)
+ break;
+
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ const Type *tt = m->type;
+ char *s = NULL;
+ Der_class cl;
+ Der_type ty;
+ unsigned tag;
+
+ if (m->ellipsis) {
+ have_ellipsis = m;
+ continue;
+ }
+
+ find_tag(tt, &cl, &ty, &tag);
+
+ fprintf(codefile,
+ "%sif (der_match_tag(p, len, %s, %s, %s, NULL) == 0) {\n",
+ els,
+ classname(cl),
+ ty ? "CONS" : "PRIM",
+ valuename(cl, tag));
+ fprintf(codefile,
+ "(%s)->element = %s;\n",
+ name, m->label);
+ if (asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&",
+ name, m->gen_name) < 0 || s == NULL)
+ errx(1, "malloc");
+ decode_type(s, m->type, m->optional, NULL, forwstr, m->gen_name,
+ NULL, depth + 1);
+ free(s);
+ fprintf(codefile,
+ "}\n");
+ els = "else ";
+ }
+ if (have_ellipsis) {
+ fprintf(codefile,
+ "else {\n"
+ "(%s)->element = %s;\n"
+ "(%s)->u.%s.data = calloc(1, len);\n"
+ "if ((%s)->u.%s.data == NULL) {\n"
+ "e = ENOMEM; %s;\n"
+ "}\n"
+ "(%s)->u.%s.length = len;\n"
+ "memcpy((%s)->u.%s.data, p, len);\n"
+ "p += len;\n"
+ "ret += len;\n"
+ "len = 0;\n"
+ "}\n",
+ name, have_ellipsis->label,
+ name, have_ellipsis->gen_name,
+ name, have_ellipsis->gen_name,
+ forwstr,
+ name, have_ellipsis->gen_name,
+ name, have_ellipsis->gen_name);
+ } else {
+ fprintf(codefile,
+ "else {\n"
+ "e = ASN1_PARSE_ERROR;\n"
+ "%s;\n"
+ "}\n",
+ forwstr);
+ }
+ break;
+ }
+ case TUTCTime:
+ decode_primitive ("utctime", name, forwstr);
+ break;
+ case TUTF8String:
+ decode_primitive ("utf8string", name, forwstr);
+ break;
+ case TPrintableString:
+ decode_primitive ("printable_string", name, forwstr);
+ break;
+ case TIA5String:
+ decode_primitive ("ia5_string", name, forwstr);
+ break;
+ case TBMPString:
+ decode_primitive ("bmp_string", name, forwstr);
+ break;
+ case TUniversalString:
+ decode_primitive ("universal_string", name, forwstr);
+ break;
+ case TVisibleString:
+ decode_primitive ("visible_string", name, forwstr);
+ break;
+ case TNull:
+ fprintf (codefile, "/* NULL */\n");
+ break;
+ case TOID:
+ decode_primitive ("oid", name, forwstr);
+ break;
+ default :
+ abort ();
+ }
+ return 0;
+}
+
+void
+generate_type_decode (const Symbol *s)
+{
+ int preserve = preserve_type(s->name) ? TRUE : FALSE;
+
+ fprintf (codefile, "int ASN1CALL\n"
+ "decode_%s(const unsigned char *p HEIMDAL_UNUSED_ATTRIBUTE,"
+ " size_t len HEIMDAL_UNUSED_ATTRIBUTE, %s *data, size_t *size)\n"
+ "{\n",
+ s->gen_name, s->gen_name);
+
+ switch (s->type->type) {
+ case TInteger:
+ case TBoolean:
+ case TOctetString:
+ case TOID:
+ case TGeneralizedTime:
+ case TGeneralString:
+ case TTeletexString:
+ case TUTF8String:
+ case TPrintableString:
+ case TIA5String:
+ case TBMPString:
+ case TUniversalString:
+ case TVisibleString:
+ case TUTCTime:
+ case TNull:
+ case TEnumerated:
+ case TBitString:
+ case TSequence:
+ case TSequenceOf:
+ case TSet:
+ case TSetOf:
+ case TTag:
+ case TType:
+ case TChoice:
+ fprintf (codefile,
+ "size_t ret = 0;\n"
+ "size_t l HEIMDAL_UNUSED_ATTRIBUTE;\n"
+ "int e HEIMDAL_UNUSED_ATTRIBUTE;\n");
+ if (preserve)
+ fprintf (codefile, "const unsigned char *begin = p;\n");
+
+ fprintf (codefile, "\n");
+ fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */
+
+ decode_type("data", s->type, 0, NULL, "goto fail", "Top", NULL, 1);
+ if (preserve)
+ fprintf (codefile,
+ "data->_save.data = calloc(1, ret);\n"
+ "if (data->_save.data == NULL) { \n"
+ "e = ENOMEM; goto fail; \n"
+ "}\n"
+ "data->_save.length = ret;\n"
+ "memcpy(data->_save.data, begin, ret);\n");
+ fprintf (codefile,
+ "if(size) *size = ret;\n"
+ "return 0;\n");
+ fprintf (codefile,
+ "fail:\n"
+ "free_%s(data);\n"
+ "return e;\n",
+ s->gen_name);
+ break;
+ default:
+ abort ();
+ }
+ fprintf (codefile, "}\n\n");
+}
diff --git a/third_party/heimdal/lib/asn1/gen_encode.c b/third_party/heimdal/lib/asn1/gen_encode.c
new file mode 100644
index 0000000..403ddac
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/gen_encode.c
@@ -0,0 +1,747 @@
+/*
+ * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gen_locl.h"
+
+/* XXX same as der_length_tag */
+static size_t
+length_tag(unsigned int tag)
+{
+ size_t len = 0;
+
+ if(tag <= 30)
+ return 1;
+ while(tag) {
+ tag /= 128;
+ len++;
+ }
+ return len + 1;
+}
+
+static void
+encode_primitive (const char *typename, const char *name)
+{
+ fprintf (codefile,
+ "e = der_put_%s(p, len, %s, &l);\n"
+ "if (e) return e;\np -= l; len -= l; ret += l;\n\n",
+ typename,
+ name);
+}
+
+const char *
+classname(Der_class class)
+{
+ const char *cn[] = { "ASN1_C_UNIV", "ASN1_C_APPL",
+ "ASN1_C_CONTEXT", "ASN1_C_PRIV" };
+ if ((int)class >= sizeof(cn) / sizeof(cn[0]))
+ return "???";
+ return cn[class];
+}
+
+
+const char *
+valuename(Der_class class, int value)
+{
+ static char s[32];
+ struct {
+ int value;
+ const char *s;
+ } *p, values[] = {
+#define X(Y) { Y, #Y }
+ X(UT_BMPString),
+ X(UT_BitString),
+ X(UT_Boolean),
+ X(UT_EmbeddedPDV),
+ X(UT_Enumerated),
+ X(UT_External),
+ X(UT_GeneralString),
+ X(UT_GeneralizedTime),
+ X(UT_GraphicString),
+ X(UT_IA5String),
+ X(UT_Integer),
+ X(UT_Null),
+ X(UT_NumericString),
+ X(UT_OID),
+ X(UT_ObjectDescriptor),
+ X(UT_OctetString),
+ X(UT_PrintableString),
+ X(UT_Real),
+ X(UT_RelativeOID),
+ X(UT_Sequence),
+ X(UT_Set),
+ X(UT_TeletexString),
+ X(UT_UTCTime),
+ X(UT_UTF8String),
+ X(UT_UniversalString),
+ X(UT_VideotexString),
+ X(UT_VisibleString),
+#undef X
+ { -1, NULL }
+ };
+ if(class == ASN1_C_UNIV) {
+ for(p = values; p->value != -1; p++)
+ if(p->value == value)
+ return p->s;
+ }
+ snprintf(s, sizeof(s), "%d", value);
+ return s;
+}
+
+static int
+encode_type (const char *name, const Type *t, const char *tmpstr)
+{
+ int constructed = 1;
+
+ switch (t->type) {
+ case TType:
+#if 0
+ encode_type (name, t->symbol->type);
+#endif
+ fprintf (codefile,
+ "e = encode_%s(p, len, %s, &l);\n"
+ "if (e) return e;\np -= l; len -= l; ret += l;\n\n",
+ t->symbol->gen_name, name);
+ constructed = !is_primitive_type(t);
+ break;
+ case TInteger:
+ if(t->members) {
+ fprintf(codefile,
+ "{\n"
+ "int enumint = (int)*%s;\n",
+ name);
+ encode_primitive("integer", "&enumint");
+ fprintf(codefile, "}\n;");
+ } else if (t->range == NULL) {
+ encode_primitive("heim_integer", name);
+ } else if (t->range->min < 0 &&
+ (t->range->min < INT_MIN || t->range->max > INT_MAX)) {
+ encode_primitive("integer64", name);
+ } else if (t->range->min < 0) {
+ encode_primitive("integer", name);
+ } else if (t->range->max > UINT_MAX) {
+ encode_primitive("unsigned64", name);
+ } else {
+ encode_primitive("unsigned", name);
+ }
+
+ constructed = 0;
+ break;
+ case TBoolean:
+ encode_primitive ("boolean", name);
+ constructed = 0;
+ break;
+ case TOctetString:
+ encode_primitive ("octet_string", name);
+ constructed = 0;
+ break;
+ case TBitString: {
+ Member *m;
+ int pos;
+
+ if (HEIM_TAILQ_EMPTY(t->members)) {
+ encode_primitive("bit_string", name);
+ constructed = 0;
+ break;
+ }
+
+ fprintf (codefile, "{\n"
+ "unsigned char c = 0;\n");
+ if (!rfc1510_bitstring)
+ fprintf (codefile,
+ "int rest = 0;\n"
+ "int bit_set = 0;\n");
+#if 0
+ pos = t->members->prev->val;
+ /* fix for buggy MIT (and OSF?) code */
+ if (pos > 31)
+ abort ();
+#endif
+ /*
+ * It seems that if we do not always set pos to 31 here, the MIT
+ * code will do the wrong thing.
+ *
+ * I hate ASN.1 (and DER), but I hate it even more when everybody
+ * has to screw it up differently.
+ */
+ pos = HEIM_TAILQ_LAST(t->members, memhead)->val;
+ if (rfc1510_bitstring) {
+ if (pos < 31)
+ pos = 31;
+ }
+
+ HEIM_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
+ while (m->val / 8 < pos / 8) {
+ if (!rfc1510_bitstring)
+ fprintf (codefile,
+ "if (c != 0 || bit_set) {\n");
+ fprintf (codefile,
+ "if (len < 1) return ASN1_OVERFLOW;\n"
+ "*p-- = c; len--; ret++;\n");
+ if (!rfc1510_bitstring)
+ fprintf (codefile,
+ "if (!bit_set) {\n"
+ "rest = 0;\n"
+ "while(c) { \n"
+ "if (c & 1) break;\n"
+ "c = c >> 1;\n"
+ "rest++;\n"
+ "}\n"
+ "bit_set = 1;\n"
+ "}\n"
+ "}\n");
+ fprintf (codefile,
+ "c = 0;\n");
+ pos -= 8;
+ }
+ fprintf (codefile,
+ "if((%s)->%s) {\n"
+ "c |= 1<<%d;\n",
+ name, m->gen_name, (int)(7 - m->val % 8));
+ fprintf (codefile,
+ "}\n");
+ }
+
+ if (!rfc1510_bitstring)
+ fprintf (codefile,
+ "if (c != 0 || bit_set) {\n");
+ fprintf (codefile,
+ "if (len < 1) return ASN1_OVERFLOW;\n"
+ "*p-- = c; len--; ret++;\n");
+ if (!rfc1510_bitstring)
+ fprintf (codefile,
+ "if (!bit_set) {\n"
+ "rest = 0;\n"
+ "if(c) { \n"
+ "while(c) { \n"
+ "if (c & 1) break;\n"
+ "c = c >> 1;\n"
+ "rest++;\n"
+ "}\n"
+ "}\n"
+ "}\n"
+ "}\n");
+
+ fprintf (codefile,
+ "if (len < 1) return ASN1_OVERFLOW;\n"
+ "*p-- = %s;\n"
+ "len -= 1;\n"
+ "ret += 1;\n"
+ "}\n\n",
+ rfc1510_bitstring ? "0" : "rest");
+ constructed = 0;
+ break;
+ }
+ case TEnumerated : {
+ encode_primitive ("enumerated", name);
+ constructed = 0;
+ break;
+ }
+
+ case TSet:
+ case TSequence: {
+ Member *m;
+
+ if (t->members == NULL)
+ break;
+
+ HEIM_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
+ char *s = NULL;
+
+ if (m->ellipsis)
+ continue;
+
+ if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL)
+ errx(1, "malloc");
+ fprintf(codefile, "/* %s */\n", m->name);
+ if (m->optional)
+ fprintf (codefile,
+ "if(%s) ",
+ s);
+ else if(m->defval)
+ gen_compare_defval(s + 1, m->defval);
+ fprintf (codefile, "{\n");
+ fprintf (codefile, "size_t %s_oldret HEIMDAL_UNUSED_ATTRIBUTE = ret;\n", tmpstr);
+ fprintf (codefile, "ret = 0;\n");
+ encode_type (s, m->type, m->gen_name);
+ fprintf (codefile, "ret += %s_oldret;\n", tmpstr);
+ fprintf (codefile, "}\n");
+ free (s);
+ }
+ break;
+ }
+ case TSetOf: {
+
+ fprintf(codefile,
+ "{\n"
+ "heim_octet_string *val;\n"
+ "size_t elen = 0, totallen = 0;\n"
+ "int eret = 0;\n");
+
+ fprintf(codefile,
+ "if ((%s)->len > UINT_MAX/sizeof(val[0]))\n"
+ "return ERANGE;\n",
+ name);
+
+ fprintf(codefile,
+ "val = calloc(1, sizeof(val[0]) * (%s)->len);\n"
+ "if (val == NULL && (%s)->len != 0) return ENOMEM;\n",
+ name, name);
+
+ fprintf(codefile,
+ "for(i = 0; i < (int)(%s)->len; i++) {\n",
+ name);
+
+ fprintf(codefile,
+ "ASN1_MALLOC_ENCODE(%s, val[i].data, "
+ "val[i].length, &(%s)->val[i], &elen, eret);\n",
+ t->subtype->symbol->gen_name,
+ name);
+
+ fprintf(codefile,
+ "if(eret) {\n"
+ "i--;\n"
+ "while (i >= 0) {\n"
+ "free(val[i].data);\n"
+ "i--;\n"
+ "}\n"
+ "free(val);\n"
+ "return eret;\n"
+ "}\n"
+ "totallen += elen;\n"
+ "}\n");
+
+ fprintf(codefile,
+ "if (totallen > len) {\n"
+ "for (i = 0; i < (int)(%s)->len; i++) {\n"
+ "free(val[i].data);\n"
+ "}\n"
+ "free(val);\n"
+ "return ASN1_OVERFLOW;\n"
+ "}\n",
+ name);
+
+ fprintf(codefile,
+ "qsort(val, (%s)->len, sizeof(val[0]), _heim_der_set_sort);\n",
+ name);
+
+ fprintf (codefile,
+ "for(i = (int)(%s)->len - 1; i >= 0; --i) {\n"
+ "p -= val[i].length;\n"
+ "ret += val[i].length;\n"
+ "memcpy(p + 1, val[i].data, val[i].length);\n"
+ "free(val[i].data);\n"
+ "}\n"
+ "free(val);\n"
+ "}\n",
+ name);
+ break;
+ }
+ case TSequenceOf: {
+ char *sname = NULL;
+ char *n = NULL;
+
+ fprintf (codefile,
+ "for(i = (int)(%s)->len - 1; i >= 0; --i) {\n"
+ "size_t %s_for_oldret = ret;\n"
+ "ret = 0;\n",
+ name, tmpstr);
+ if (asprintf (&n, "&(%s)->val[i]", name) < 0 || n == NULL)
+ errx(1, "malloc");
+ if (asprintf (&sname, "%s_S_Of", tmpstr) < 0 || sname == NULL)
+ errx(1, "malloc");
+ encode_type (n, t->subtype, sname);
+ fprintf (codefile,
+ "ret += %s_for_oldret;\n"
+ "}\n",
+ tmpstr);
+ free (n);
+ free (sname);
+ break;
+ }
+ case TGeneralizedTime:
+ encode_primitive ("generalized_time", name);
+ constructed = 0;
+ break;
+ case TGeneralString:
+ encode_primitive ("general_string", name);
+ constructed = 0;
+ break;
+ case TTeletexString:
+ encode_primitive ("general_string", name);
+ constructed = 0;
+ break;
+ case TTag: {
+ char *tname = NULL;
+ int replace_tag = 0;
+ int prim = !(t->tag.tagclass != ASN1_C_UNIV &&
+ t->tag.tagenv == TE_EXPLICIT) &&
+ is_primitive_type(t->subtype);
+ int c;
+ if (asprintf (&tname, "%s_tag", tmpstr) < 0 || tname == NULL)
+ errx(1, "malloc");
+ /*
+ * HACK HACK HACK
+ *
+ * This is part of the fix to the bug where we treated IMPLICIT tags of
+ * named types as EXPLICIT. I.e.
+ *
+ * Foo ::= SEQUENCE { ... }
+ * Bar ::= SEQUENCE { foo [0] IMPLICIT Foo }
+ *
+ * would get a context [0] constructed tag *and* a universal sequence
+ * constructed tag when it should get only the first tag.
+ *
+ * Properly fixing this would require changing the signatures of the
+ * encode, length, and decode functions we generate to take an optional
+ * tag to replace the one the encoder would generate / decoder would
+ * expect. That would change the ABI, which... isn't stable, but it's
+ * a bit soon to make that change.
+ *
+ * So, we're looking for IMPLICIT, and if we see any, we generate code
+ * to replace the tag.
+ *
+ * On the decode side we need to know what tag to restore. For this we
+ * generate enums in the generated header.
+ *
+ * NOTE: We *do* "replace" the tags of IMPLICIT-tagged primitive types,
+ * but our primitive codec functions leave those tags out, which
+ * is why we don't have to der_replace_tag() them here.
+ */
+ /*
+ * If the tag is IMPLICIT and it's not primitive and the subtype is not
+ * any kind of structure...
+ */
+ if (t->tag.tagenv == TE_IMPLICIT && !prim &&
+ t->subtype->type != TSequenceOf && t->subtype->type != TSetOf &&
+ t->subtype->type != TChoice) {
+ /* If it is a named type for a structured thing */
+ if (t->subtype->symbol &&
+ (t->subtype->type == TSequence ||
+ t->subtype->type == TSet))
+ replace_tag = 1;
+ else if (t->subtype->symbol && strcmp(t->subtype->symbol->name, "heim_any"))
+ replace_tag = 1;
+ } else if (t->tag.tagenv == TE_IMPLICIT && prim && t->subtype->symbol)
+ /*
+ * Because the subtype is named we are generating its codec
+ * functions, and those will be adding their UNIVERSAL or whatever
+ * tags unlike our raw primtive codec library.
+ */
+ replace_tag = is_tagged_type(t->subtype->symbol->type);
+
+ if (replace_tag)
+ fprintf(codefile,
+ "{ unsigned char *psave_%s = p, *pfree_%s = NULL;\n"
+ "size_t l2_%s, lensave_%s = len;\n"
+ "len = length_%s(%s);\n"
+ /* Allocate a temp buffer for the encoder */
+ "if ((p = pfree_%s = calloc(1, len)) == NULL) return ENOMEM;\n"
+ /* Make p point to the last byte of the allocated buf */
+ "p += len - 1;\n",
+ tmpstr, tmpstr, tmpstr, tmpstr,
+ t->subtype->symbol->gen_name, name, tmpstr);
+
+ /* XXX Currently we generate code that leaks `pfree_%s` here. */
+ c = encode_type (name, t->subtype, tname);
+ /* Explicit non-UNIVERSAL tags are always constructed */
+ if (!c && t->tag.tagclass != ASN1_C_UNIV && t->tag.tagenv == TE_EXPLICIT)
+ c = 1;
+ if (replace_tag)
+ fprintf(codefile,
+ "if (len) { free(pfree_%s); return EINVAL; }\n"
+ /*
+ * Here we have `p' pointing to one byte before the buffer
+ * we allocated above.
+ *
+ * [ T_wrong | LL | VVVV ] // temp buffer
+ * ^ ^
+ * | |
+ * | \
+ * \ +-- p + 1
+ * +-- p
+ *
+ * psave_<fieldName> still points to the last byte in the
+ * original buffer passed in where we should write the
+ * encoding of <fieldName>.
+ *
+ * We adjust psave_<fieldName> to point to before the TLV
+ * encoding of <fieldName> (with wrong tag) in the original
+ * buffer (this may NOT be a valid pointer, but we won't
+ * dereference it):
+ *
+ * [ ... | T_wrong | LL | VVVVV | ... ] // original buffer
+ * ^
+ * |
+ * \
+ * +-- psave_<fieldName>
+ */
+ "psave_%s -= l;\n"
+ /*
+ * We further adjust psave_<fieldName> to point to the last
+ * byte of what should be the T(ag) of the TLV encoding of
+ * <fieldName> (this is now a valid pointer), then...
+ *
+ * |<--->| (not written yet)
+ * | | |<-------->| (not written yet)
+ * [ ... | T_right | LL | VVVVV | ... ] // original buffer
+ * ^
+ * |
+ * \
+ * +-- psave_<fieldName>
+ */
+ "psave_%s += asn1_tag_length_%s;\n"
+ /*
+ * ...copy the L(ength)V(alue) of the TLV encoding of
+ * <fieldName>.
+ *
+ * [ ... | T_right | LL | VVVVV | ... ] // original buffer
+ * ^
+ * |
+ * \
+ * +-- psave_<fieldName> + 1
+ *
+ * |<----->| length is
+ * | | `l' - asn1_tag_length_<fieldName>
+ * [ T_wrong | LL | VVVV ] // temp buffer
+ * ^ ^
+ * | |
+ * | \
+ * \ +-- p + 1 + asn1_tag_length_%s
+ * +-- p + 1
+ */
+ "memcpy(psave_%s + 1, p + 1 + asn1_tag_length_%s, l - asn1_tag_length_%s);\n"
+ /*
+ * Encode the IMPLICIT tag. Recall that encoders like
+ * der_put_tag() take a pointer to the last byte they
+ * should write to, and a length of bytes to the left of
+ * that that they are allowed to write into.
+ *
+ * [ ... | T_right | LL | VVVVV | ... ] // original buffer
+ * ^
+ * |
+ * \
+ * +-- psave_<fieldName>
+ */
+ "e = der_put_tag(psave_%s, %zu, %s, %s, %d, &l2_%s);\n"
+ "if (e) { free(pfree_%s); return e; }\n"
+ /* Restore `len' and adjust it (see `p' below) */
+ "len = lensave_%s - (l + %zu - asn1_tag_length_%s);\n"
+ /*
+ * Adjust `ret' to account for the difference in size
+ * between the length of the right and wrong tags.
+ */
+ "ret += %zu - asn1_tag_length_%s;\n"
+ /* Free the buffer and restore `p' */
+ "free(pfree_%s);\n"
+ /*
+ * Make `p' point into the original buffer again, to one
+ * byte before the bytes we wrote:
+ *
+ * [ ... | T_right | LL | VVVVV | ... ] // original buffer
+ * ^
+ * |
+ * \
+ * +-- p
+ */
+ "p = psave_%s - (1 + %zu - asn1_tag_length_%s); }\n",
+ tmpstr, tmpstr, tmpstr, t->subtype->symbol->name,
+ tmpstr, t->subtype->symbol->name, t->subtype->symbol->name,
+ tmpstr, length_tag(t->tag.tagvalue),
+ classname(t->tag.tagclass),
+ c ? "CONS" : "PRIM",
+ t->tag.tagvalue,
+ tmpstr,
+
+ tmpstr, tmpstr, length_tag(t->tag.tagvalue), t->subtype->symbol->name,
+ length_tag(t->tag.tagvalue), t->subtype->symbol->name,
+ tmpstr, tmpstr, length_tag(t->tag.tagvalue), t->subtype->symbol->name);
+ else
+ fprintf(codefile,
+ "e = der_put_length_and_tag (p, len, ret, %s, %s, %s, &l);\n"
+ "if (e) return e;\np -= l; len -= l; ret += l;\n\n",
+ classname(t->tag.tagclass),
+ c ? "CONS" : "PRIM",
+ valuename(t->tag.tagclass, t->tag.tagvalue));
+ free(tname);
+ constructed = c;
+ break;
+ }
+ case TChoice:{
+ Member *m, *have_ellipsis = NULL;
+ char *s = NULL;
+
+ if (t->members == NULL)
+ break;
+
+ fprintf(codefile, "\n");
+
+ if (asprintf (&s, "(%s)", name) < 0 || s == NULL)
+ errx(1, "malloc");
+ fprintf(codefile, "switch(%s->element) {\n", s);
+
+ HEIM_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
+ char *s2 = NULL;
+
+ if (m->ellipsis) {
+ have_ellipsis = m;
+ continue;
+ }
+
+ fprintf (codefile, "case %s: {", m->label);
+ if (asprintf(&s2, "%s(%s)->u.%s", m->optional ? "" : "&",
+ s, m->gen_name) < 0 || s2 == NULL)
+ errx(1, "malloc");
+ if (m->optional)
+ fprintf (codefile, "if(%s) {\n", s2);
+ fprintf (codefile, "size_t %s_oldret = ret;\n", tmpstr);
+ fprintf (codefile, "ret = 0;\n");
+ constructed = encode_type (s2, m->type, m->gen_name);
+ fprintf (codefile, "ret += %s_oldret;\n", tmpstr);
+ if(m->optional)
+ fprintf (codefile, "}\n");
+ fprintf(codefile, "break;\n");
+ fprintf(codefile, "}\n");
+ free (s2);
+ }
+ free (s);
+ if (have_ellipsis) {
+ fprintf(codefile,
+ "case %s: {\n"
+ "if (len < (%s)->u.%s.length)\n"
+ "return ASN1_OVERFLOW;\n"
+ "p -= (%s)->u.%s.length;\n"
+ "ret += (%s)->u.%s.length;\n"
+ "memcpy(p + 1, (%s)->u.%s.data, (%s)->u.%s.length);\n"
+ "break;\n"
+ "}\n",
+ have_ellipsis->label,
+ name, have_ellipsis->gen_name,
+ name, have_ellipsis->gen_name,
+ name, have_ellipsis->gen_name,
+ name, have_ellipsis->gen_name,
+ name, have_ellipsis->gen_name);
+ }
+ fprintf(codefile, "};\n");
+ break;
+ }
+ case TOID:
+ encode_primitive ("oid", name);
+ constructed = 0;
+ break;
+ case TUTCTime:
+ encode_primitive ("utctime", name);
+ constructed = 0;
+ break;
+ case TUTF8String:
+ encode_primitive ("utf8string", name);
+ constructed = 0;
+ break;
+ case TPrintableString:
+ encode_primitive ("printable_string", name);
+ constructed = 0;
+ break;
+ case TIA5String:
+ encode_primitive ("ia5_string", name);
+ constructed = 0;
+ break;
+ case TBMPString:
+ encode_primitive ("bmp_string", name);
+ constructed = 0;
+ break;
+ case TUniversalString:
+ encode_primitive ("universal_string", name);
+ constructed = 0;
+ break;
+ case TVisibleString:
+ encode_primitive ("visible_string", name);
+ constructed = 0;
+ break;
+ case TNull:
+ fprintf (codefile, "/* NULL */\n");
+ constructed = 0;
+ break;
+ default:
+ abort ();
+ }
+ return constructed;
+}
+
+void
+generate_type_encode (const Symbol *s)
+{
+ fprintf (codefile, "int ASN1CALL\n"
+ "encode_%s(unsigned char *p HEIMDAL_UNUSED_ATTRIBUTE, size_t len HEIMDAL_UNUSED_ATTRIBUTE,"
+ " const %s *data, size_t *size)\n"
+ "{\n",
+ s->gen_name, s->gen_name);
+
+ switch (s->type->type) {
+ case TInteger:
+ case TBoolean:
+ case TOctetString:
+ case TGeneralizedTime:
+ case TGeneralString:
+ case TTeletexString:
+ case TUTCTime:
+ case TUTF8String:
+ case TPrintableString:
+ case TIA5String:
+ case TBMPString:
+ case TUniversalString:
+ case TVisibleString:
+ case TNull:
+ case TBitString:
+ case TEnumerated:
+ case TOID:
+ case TSequence:
+ case TSequenceOf:
+ case TSet:
+ case TSetOf:
+ case TTag:
+ case TType:
+ case TChoice:
+ fprintf (codefile,
+ "size_t ret HEIMDAL_UNUSED_ATTRIBUTE = 0;\n"
+ "size_t l HEIMDAL_UNUSED_ATTRIBUTE;\n"
+ "int i HEIMDAL_UNUSED_ATTRIBUTE, e HEIMDAL_UNUSED_ATTRIBUTE;\n\n");
+
+ encode_type("data", s->type, "Top");
+
+ fprintf (codefile, "*size = ret;\n"
+ "return 0;\n");
+ break;
+ default:
+ abort ();
+ }
+ fprintf (codefile, "}\n\n");
+}
diff --git a/third_party/heimdal/lib/asn1/gen_free.c b/third_party/heimdal/lib/asn1/gen_free.c
new file mode 100644
index 0000000..ff80063
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/gen_free.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gen_locl.h"
+
+RCSID("$Id$");
+
+static void
+free_primitive (const char *typename, const char *name)
+{
+ fprintf (codefile, "der_free_%s(%s);\n", typename, name);
+}
+
+static void
+free_type (const char *name, const Type *t, int preserve)
+{
+ switch (t->type) {
+ case TType:
+#if 0
+ free_type (name, t->symbol->type, preserve);
+#endif
+ fprintf (codefile, "free_%s(%s);\n", t->symbol->gen_name, name);
+ break;
+ case TInteger:
+ if (t->range == NULL && t->members == NULL) {
+ free_primitive ("heim_integer", name);
+ break;
+ }
+ HEIM_FALLTHROUGH;
+ case TBoolean:
+ case TEnumerated :
+ case TNull:
+ case TGeneralizedTime:
+ case TUTCTime:
+ /*
+ * This doesn't do much, but it leaves zeros where garbage might
+ * otherwise have been found. Gets us closer to having the equivalent
+ * of a memset()-to-zero data structure after calling the free
+ * functions.
+ */
+ fprintf(codefile, "*%s = 0;\n", name);
+ break;
+ case TBitString:
+ if (HEIM_TAILQ_EMPTY(t->members))
+ free_primitive("bit_string", name);
+ break;
+ case TOctetString:
+ free_primitive ("octet_string", name);
+ break;
+ case TChoice:
+ case TSet:
+ case TSequence: {
+ Member *m, *have_ellipsis = NULL;
+
+ if (t->members == NULL)
+ break;
+
+ if ((t->type == TSequence || t->type == TChoice) && preserve)
+ fprintf(codefile, "der_free_octet_string(&data->_save);\n");
+
+ if(t->type == TChoice)
+ fprintf(codefile, "switch((%s)->element) {\n", name);
+
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ char *s;
+
+ if (m->ellipsis){
+ have_ellipsis = m;
+ continue;
+ }
+
+ if(t->type == TChoice)
+ fprintf(codefile, "case %s:\n", m->label);
+ if (asprintf (&s, "%s(%s)->%s%s",
+ m->optional ? "" : "&", name,
+ t->type == TChoice ? "u." : "", m->gen_name) < 0 || s == NULL)
+ errx(1, "malloc");
+ if(m->optional)
+ fprintf(codefile, "if(%s) {\n", s);
+ free_type (s, m->type, FALSE);
+ if(m->optional)
+ fprintf(codefile,
+ "free(%s);\n"
+ "%s = NULL;\n"
+ "}\n",s, s);
+ free (s);
+ if(t->type == TChoice)
+ fprintf(codefile, "break;\n");
+ }
+
+ if(t->type == TChoice) {
+ if (have_ellipsis)
+ fprintf(codefile,
+ "case %s:\n"
+ "der_free_octet_string(&(%s)->u.%s);\n"
+ "break;",
+ have_ellipsis->label,
+ name, have_ellipsis->gen_name);
+ fprintf(codefile, "}\n");
+ }
+ break;
+ }
+ case TSetOf:
+ case TSequenceOf: {
+ char *n;
+
+ fprintf (codefile, "if ((%s)->val)\nwhile((%s)->len){\n", name, name);
+ if (asprintf (&n, "&(%s)->val[(%s)->len-1]", name, name) < 0 || n == NULL)
+ errx(1, "malloc");
+ free_type(n, t->subtype, FALSE);
+ fprintf(codefile,
+ "(%s)->len--;\n"
+ "} else (%s)->len = 0;\n",
+ name, name);
+ fprintf(codefile,
+ "free((%s)->val);\n"
+ "(%s)->val = NULL;\n", name, name);
+ free(n);
+ break;
+ }
+ case TGeneralString:
+ free_primitive ("general_string", name);
+ break;
+ case TTeletexString:
+ free_primitive ("general_string", name);
+ break;
+ case TUTF8String:
+ free_primitive ("utf8string", name);
+ break;
+ case TPrintableString:
+ free_primitive ("printable_string", name);
+ break;
+ case TIA5String:
+ free_primitive ("ia5_string", name);
+ break;
+ case TBMPString:
+ free_primitive ("bmp_string", name);
+ break;
+ case TUniversalString:
+ free_primitive ("universal_string", name);
+ break;
+ case TVisibleString:
+ free_primitive ("visible_string", name);
+ break;
+ case TTag:
+ free_type (name, t->subtype, preserve);
+ break;
+ case TOID :
+ free_primitive ("oid", name);
+ break;
+ default :
+ abort ();
+ }
+}
+
+void
+generate_type_free (const Symbol *s)
+{
+ struct decoration deco;
+ ssize_t more_deco = -1;
+ int preserve = preserve_type(s->name) ? TRUE : FALSE;
+
+ fprintf (codefile, "void ASN1CALL\n"
+ "free_%s(%s *data)\n"
+ "{\n",
+ s->gen_name, s->gen_name);
+
+ free_type ("data", s->type, preserve);
+ while (decorate_type(s->gen_name, &deco, &more_deco)) {
+ if (deco.ext && deco.free_function_name == NULL) {
+ /* Decorated with field of external type but no free function */
+ if (deco.ptr)
+ fprintf(codefile, "(data)->%s = 0;\n", deco.field_name);
+ else
+ fprintf(codefile,
+ "memset(&(data)->%s, 0, sizeof((data)->%s));\n",
+ deco.field_name, deco.field_name);
+ } else if (deco.ext) {
+ /* Decorated with field of external type w/ free function */
+ if (deco.ptr) {
+ fprintf(codefile, "if ((data)->%s) {\n", deco.field_name);
+ fprintf(codefile, "%s((data)->%s);\n",
+ deco.free_function_name, deco.field_name);
+ fprintf(codefile, "(data)->%s = 0;\n", deco.field_name);
+ fprintf(codefile, "}\n");
+ } else {
+ fprintf(codefile, "%s(&(data)->%s);\n",
+ deco.free_function_name, deco.field_name);
+ fprintf(codefile,
+ "memset(&(data)->%s, 0, sizeof((data)->%s));\n",
+ deco.field_name, deco.field_name);
+ }
+ } else if (deco.opt) {
+ /* Decorated with optional field of ASN.1 type */
+ fprintf(codefile, "if ((data)->%s) {\n", deco.field_name);
+ fprintf(codefile, "free_%s((data)->%s);\n",
+ deco.field_type, deco.field_name);
+ fprintf(codefile, "free((data)->%s);\n", deco.field_name);
+ fprintf(codefile, "(data)->%s = NULL;\n", deco.field_name);
+ fprintf(codefile, "}\n");
+ } else {
+ /* Decorated with required field of ASN.1 type */
+ fprintf(codefile, "free_%s(&(data)->%s);\n",
+ deco.field_type, deco.field_name);
+ }
+ free(deco.field_type);
+ }
+ fprintf (codefile, "}\n\n");
+}
diff --git a/third_party/heimdal/lib/asn1/gen_glue.c b/third_party/heimdal/lib/asn1/gen_glue.c
new file mode 100644
index 0000000..424e5de
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/gen_glue.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 1997, 1999, 2000, 2003 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gen_locl.h"
+
+RCSID("$Id$");
+
+static FILE *
+get_code_file(void)
+{
+ if (!one_code_file && template_flag && templatefile)
+ return templatefile;
+ return codefile;
+}
+
+static void
+generate_2int (const Type *t, const char *gen_name)
+{
+ Member *m;
+
+ fprintf (headerfile,
+ "uint64_t %s2int(%s);\n",
+ gen_name, gen_name);
+
+ fprintf (get_code_file(),
+ "uint64_t %s2int(%s f)\n"
+ "{\n"
+ "uint64_t r = 0;\n",
+ gen_name, gen_name);
+
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ fprintf (get_code_file(), "if(f.%s) r |= (1ULL << %d);\n",
+ m->gen_name, (int)m->val);
+ }
+ fprintf (get_code_file(), "return r;\n"
+ "}\n\n");
+}
+
+static void
+generate_int2 (const Type *t, const char *gen_name)
+{
+ Member *m;
+
+ fprintf (headerfile,
+ "%s int2%s(uint64_t);\n",
+ gen_name, gen_name);
+
+ fprintf (get_code_file(),
+ "%s int2%s(uint64_t n)\n"
+ "{\n"
+ "\t%s flags;\n\n"
+ "\tmemset(&flags, 0, sizeof(flags));\n\n",
+ gen_name, gen_name, gen_name);
+
+ if(t->members) {
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ fprintf (get_code_file(), "\tflags.%s = (n >> %d) & 1;\n",
+ m->gen_name, (int)m->val);
+ }
+ }
+ fprintf (get_code_file(), "\treturn flags;\n"
+ "}\n\n");
+}
+
+/*
+ * This depends on the bit string being declared in increasing order
+ */
+
+static void
+generate_units (const Type *t, const char *gen_name)
+{
+ Member *m;
+
+ fprintf (headerfile,
+ "const struct units * asn1_%s_units(void);\n",
+ gen_name);
+
+ fprintf (get_code_file(),
+ "static struct units %s_units[] = {\n",
+ gen_name);
+
+ if(t->members) {
+ HEIM_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
+ fprintf (get_code_file(),
+ "\t{\"%s\",\t1ULL << %d},\n", m->name, (int)m->val);
+ }
+ }
+
+ fprintf (get_code_file(),
+ "\t{NULL,\t0}\n"
+ "};\n\n");
+
+ fprintf (get_code_file(),
+ "const struct units * asn1_%s_units(void){\n"
+ "return %s_units;\n"
+ "}\n\n",
+ gen_name, gen_name);
+
+
+}
+
+void
+generate_glue (const Type *t, const char *gen_name)
+{
+ switch(t->type) {
+ case TTag:
+ generate_glue(t->subtype, gen_name);
+ break;
+ case TBitString : {
+ Member *m;
+
+ if (HEIM_TAILQ_EMPTY(t->members))
+ break;
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ if (m->val > 63) {
+ warnx("Not generating 2int, int2, or units for %s due to "
+ "having a member valued more than 63", gen_name);
+ return;
+ }
+ }
+ generate_2int (t, gen_name);
+ generate_int2 (t, gen_name);
+ if (parse_units_flag)
+ generate_units (t, gen_name);
+ break;
+ }
+ default :
+ break;
+ }
+}
diff --git a/third_party/heimdal/lib/asn1/gen_length.c b/third_party/heimdal/lib/asn1/gen_length.c
new file mode 100644
index 0000000..ab5c5f3
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/gen_length.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gen_locl.h"
+
+RCSID("$Id$");
+
+static void
+length_primitive (const char *typename,
+ const char *name,
+ const char *variable)
+{
+ fprintf (codefile, "%s += der_length_%s(%s);\n", variable, typename, name);
+}
+
+/* XXX same as der_length_tag */
+static size_t
+length_tag(unsigned int tag)
+{
+ size_t len = 0;
+
+ if(tag <= 30)
+ return 1;
+ while(tag) {
+ tag /= 128;
+ len++;
+ }
+ return len + 1;
+}
+
+
+static int
+length_type (const char *name, const Type *t,
+ const char *variable, const char *tmpstr)
+{
+ switch (t->type) {
+ case TType:
+#if 0
+ length_type (name, t->symbol->type);
+#endif
+ fprintf (codefile, "%s += length_%s(%s);\n",
+ variable, t->symbol->gen_name, name);
+ break;
+ case TInteger:
+ if(t->members) {
+ fprintf(codefile,
+ "{\n"
+ "int enumint = *%s;\n", name);
+ length_primitive ("integer", "&enumint", variable);
+ fprintf(codefile, "}\n");
+ } else if (t->range == NULL) {
+ length_primitive ("heim_integer", name, variable);
+ } else if (t->range->min < 0 &&
+ (t->range->min < INT_MIN || t->range->max > INT_MAX)) {
+ length_primitive ("integer64", name, variable);
+ } else if (t->range->min < 0) {
+ length_primitive ("integer", name, variable);
+ } else if (t->range->max > UINT_MAX) {
+ length_primitive ("unsigned64", name, variable);
+ } else {
+ length_primitive ("unsigned", name, variable);
+ }
+ break;
+ case TBoolean:
+ fprintf (codefile, "%s += 1;\n", variable);
+ break;
+ case TEnumerated :
+ length_primitive ("enumerated", name, variable);
+ break;
+ case TOctetString:
+ length_primitive ("octet_string", name, variable);
+ break;
+ case TBitString: {
+ if (HEIM_TAILQ_EMPTY(t->members))
+ length_primitive("bit_string", name, variable);
+ else {
+ if (!rfc1510_bitstring) {
+ Member *m;
+ int pos = HEIM_TAILQ_LAST(t->members, memhead)->val;
+
+ fprintf(codefile,
+ "do {\n");
+ HEIM_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
+ while (m->val / 8 < pos / 8) {
+ pos -= 8;
+ }
+ fprintf (codefile,
+ "if((%s)->%s) { %s += %d; break; }\n",
+ name, m->gen_name, variable, (pos + 8) / 8);
+ }
+ fprintf(codefile,
+ "} while(0);\n");
+ fprintf (codefile, "%s += 1;\n", variable);
+ } else {
+ fprintf (codefile, "%s += 5;\n", variable);
+ }
+ }
+ break;
+ }
+ case TSet:
+ case TSequence:
+ case TChoice: {
+ Member *m, *have_ellipsis = NULL;
+
+ if (t->members == NULL)
+ break;
+
+ if(t->type == TChoice)
+ fprintf (codefile, "switch((%s)->element) {\n", name);
+
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ char *s;
+
+ if (m->ellipsis) {
+ have_ellipsis = m;
+ continue;
+ }
+
+ if(t->type == TChoice)
+ fprintf(codefile, "case %s:\n", m->label);
+
+ if (asprintf (&s, "%s(%s)->%s%s",
+ m->optional ? "" : "&", name,
+ t->type == TChoice ? "u." : "", m->gen_name) < 0 || s == NULL)
+ errx(1, "malloc");
+ if (m->optional)
+ fprintf (codefile, "if(%s)", s);
+ else if(m->defval)
+ gen_compare_defval(s + 1, m->defval);
+ fprintf (codefile, "{\n"
+ "size_t %s_oldret = %s;\n"
+ "%s = 0;\n", tmpstr, variable, variable);
+ length_type (s, m->type, "ret", m->gen_name);
+ fprintf (codefile, "ret += %s_oldret;\n", tmpstr);
+ fprintf (codefile, "}\n");
+ free (s);
+ if(t->type == TChoice)
+ fprintf(codefile, "break;\n");
+ }
+ if(t->type == TChoice) {
+ if (have_ellipsis)
+ fprintf(codefile,
+ "case %s:\n"
+ "ret += (%s)->u.%s.length;\n"
+ "break;\n",
+ have_ellipsis->label,
+ name,
+ have_ellipsis->gen_name);
+ fprintf (codefile, "}\n"); /* switch */
+ }
+ break;
+ }
+ case TSetOf:
+ case TSequenceOf: {
+ char *n = NULL;
+ char *sname = NULL;
+
+ fprintf (codefile,
+ "{\n"
+ "size_t %s_oldret = %s;\n"
+ "unsigned int n_%s;\n"
+ "%s = 0;\n",
+ tmpstr, variable, tmpstr, variable);
+
+ fprintf (codefile, "for(n_%s = (%s)->len; n_%s > 0; --n_%s){\n",
+ tmpstr, name, tmpstr, tmpstr);
+ fprintf (codefile, "size_t %s_for_oldret = %s;\n"
+ "%s = 0;\n", tmpstr, variable, variable);
+ if (asprintf (&n, "&(%s)->val[n_%s - 1]", name, tmpstr) < 0 || n == NULL)
+ errx(1, "malloc");
+ if (asprintf (&sname, "%s_S_Of", tmpstr) < 0 || sname == NULL)
+ errx(1, "malloc");
+ length_type(n, t->subtype, variable, sname);
+ fprintf (codefile, "%s += %s_for_oldret;\n",
+ variable, tmpstr);
+ fprintf (codefile, "}\n");
+
+ fprintf (codefile,
+ "%s += %s_oldret;\n"
+ "}\n", variable, tmpstr);
+ free(n);
+ free(sname);
+ break;
+ }
+ case TGeneralizedTime:
+ length_primitive ("generalized_time", name, variable);
+ break;
+ case TGeneralString:
+ length_primitive ("general_string", name, variable);
+ break;
+ case TTeletexString:
+ length_primitive ("general_string", name, variable);
+ break;
+ case TUTCTime:
+ length_primitive ("utctime", name, variable);
+ break;
+ case TUTF8String:
+ length_primitive ("utf8string", name, variable);
+ break;
+ case TPrintableString:
+ length_primitive ("printable_string", name, variable);
+ break;
+ case TIA5String:
+ length_primitive ("ia5_string", name, variable);
+ break;
+ case TBMPString:
+ length_primitive ("bmp_string", name, variable);
+ break;
+ case TUniversalString:
+ length_primitive ("universal_string", name, variable);
+ break;
+ case TVisibleString:
+ length_primitive ("visible_string", name, variable);
+ break;
+ case TNull:
+ fprintf (codefile, "/* NULL */\n");
+ break;
+ case TTag:{
+ char *tname = NULL;
+ int replace_tag = 0;
+ int prim = !(t->tag.tagclass != ASN1_C_UNIV &&
+ t->tag.tagenv == TE_EXPLICIT) &&
+ is_primitive_type(t->subtype);
+
+ if (asprintf(&tname, "%s_tag", tmpstr) < 0 || tname == NULL)
+ errx(1, "malloc");
+ length_type (name, t->subtype, variable, tname);
+ /* See the comments in encode_type() about IMPLICIT tags */
+ if (t->tag.tagenv == TE_IMPLICIT && !prim &&
+ t->subtype->type != TSequenceOf && t->subtype->type != TSetOf &&
+ t->subtype->type != TChoice) {
+ if (t->subtype->symbol &&
+ (t->subtype->type == TSequence ||
+ t->subtype->type == TSet))
+ replace_tag = 1;
+ else if (t->subtype->symbol && strcmp(t->subtype->symbol->name, "heim_any"))
+ replace_tag = 1;
+ } else if (t->tag.tagenv == TE_IMPLICIT && prim && t->subtype->symbol)
+ replace_tag = is_tagged_type(t->subtype->symbol->type);
+ if (replace_tag)
+ /*
+ * We're replacing the tag of the underlying type. If that type is
+ * imported, then we don't know its tag, so we rely on the
+ * asn1_tag_tag_<TypeName> enum value we generated for it, and we
+ * use the asn1_tag_length_<TypeName> enum value to avoid having to
+ * call der_length_tag() at run-time.
+ */
+ fprintf(codefile, "ret += %lu - asn1_tag_length_%s;\n",
+ (unsigned long)length_tag(t->tag.tagvalue),
+ t->subtype->symbol->gen_name);
+ else
+ fprintf(codefile, "ret += %lu + der_length_len (ret);\n",
+ (unsigned long)length_tag(t->tag.tagvalue));
+ free(tname);
+ break;
+ }
+ case TOID:
+ length_primitive ("oid", name, variable);
+ break;
+ default :
+ abort ();
+ }
+ return 0;
+}
+
+void
+generate_type_length (const Symbol *s)
+{
+ fprintf (codefile,
+ "size_t ASN1CALL\n"
+ "length_%s(const %s *data)\n"
+ "{\n"
+ "size_t ret = 0;\n",
+ s->gen_name, s->gen_name);
+
+ length_type ("data", s->type, "ret", "Top");
+ fprintf (codefile, "return ret;\n}\n\n");
+}
+
diff --git a/third_party/heimdal/lib/asn1/gen_locl.h b/third_party/heimdal/lib/asn1/gen_locl.h
new file mode 100644
index 0000000..f37f149
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/gen_locl.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id$ */
+
+#ifndef __GEN_LOCL_H__
+#define __GEN_LOCL_H__
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <time.h>
+#include <errno.h>
+#include <err.h>
+#include <roken.h>
+#include <getarg.h>
+#include "hash.h"
+#include "symbol.h"
+#include "asn1-common.h"
+#include "der.h"
+#include "der-private.h"
+
+/*
+ * XXX We need to move all module state out of globals and into a struct that
+ * we pass around when parsing and compiling a module, and also that we keep on
+ * a linked list of parsed modules.
+ *
+ * This is needed to:
+ *
+ * - implement IMPORTS correctly, because we need to know the type of a symbol
+ * in order to emit an extern declaration of it
+ * - implement value parsing
+ * - implement an ASN.1 library that does value parsing
+ *
+ * Value parsing, in particular, would be fantastic. We could then have
+ * options in hxtool(1) to load arbitrary ASN.1 modules and then parse SAN
+ * values given in ASN.1 value syntax on the command-line or in files. Eat
+ * your heart out OpenSSL if we do this!
+ *
+ * As well we'll need a `-I' option to the compiler so it knows where to find
+ * modules to IMPORT FROM.
+ */
+typedef struct asn1_module {
+ /* Name of ASN.1 module file: */
+ const char *orig_filename;
+ /* Name of file to always include for common type definitions: */
+ const char *type_file_string;
+ /* Name of public header file for module: */
+ const char *header;
+ /* Name of private header file for module: */
+ const char *privheader;
+ /* Basename of module: */
+ const char *headerbase;
+ /* Open stdio file handles for output: */
+ FILE *jsonfile;
+ FILE *privheaderfile;
+ FILE *headerfile;
+ FILE *oidsfile;
+ FILE *codefile;
+ FILE *logfile;
+ FILE *templatefile;
+ /* Module contents: */
+ struct sexport *exports;
+ struct import *imports;
+ Hashtab *htab; /* symbols */
+ /* Template state: */
+ struct templatehead *template;
+ struct tlisthead *tlistmaster;
+ /* CLI options and flags needed everywhere: */
+ getarg_strings preserve;
+ getarg_strings seq;
+ const char *enum_prefix;
+ unsigned int one_code_file:1;
+ unsigned int support_ber:1;
+ unsigned int parse_units_flag:1;
+ unsigned int prefix_enum:1; /* Should be a getarg_strings of bitrsting types to do this for */
+ unsigned int rfc1510_bitstring:1; /* Should be a getarg_strings of bitrsting types to do this for */
+} *asn1_module;
+
+void generate_type (const Symbol *);
+void generate_type_header_forwards(const Symbol *);
+void generate_constant (const Symbol *);
+void generate_type_encode (const Symbol *);
+void generate_type_decode (const Symbol *);
+void generate_type_free (const Symbol *);
+void generate_type_length (const Symbol *);
+void generate_type_print_stub(const Symbol *);
+void generate_type_copy (const Symbol *);
+void generate_type_seq (const Symbol *);
+void generate_glue (const Type *, const char*);
+
+const char *classname(Der_class);
+const char *valuename(Der_class, int);
+
+void gen_compare_defval(const char *, struct value *);
+void gen_assign_defval(const char *, struct value *);
+
+int objid_cmp(struct objid *, struct objid *);
+
+void init_generate (const char *, const char *);
+const char *get_filename (void);
+void close_generate(void);
+void add_import(const char *);
+void add_export(const char *);
+int is_export(const char *);
+int yyparse(void);
+int is_primitive_type(const Type *);
+int is_tagged_type(const Type *);
+
+int preserve_type(const char *);
+int seq_type(const char *);
+
+struct decoration {
+ char *field_type; /* C type name */
+ char *field_name; /* C struct field name */
+ char *copy_function_name; /* copy constructor function name */
+ char *free_function_name; /* destructor function name */
+ char *header_name; /* header name */
+ unsigned int decorated:1;
+ unsigned int first:1; /* optional */
+ unsigned int opt:1; /* optional */
+ unsigned int ext:1; /* external */
+ unsigned int ptr:1; /* external, pointer */
+ unsigned int void_star:1; /* external, void * */
+ unsigned int struct_star:1; /* external, struct foo * */
+};
+int decorate_type(const char *, struct decoration *, ssize_t *);
+
+void generate_header_of_codefile(const char *);
+void close_codefile(void);
+
+void get_open_type_defn_fields(const Type *, Member **, Member **, Field **,
+ Field **, int *);
+void sort_object_set(IOSObjectSet *, Field *, IOSObject ***, size_t *);
+int object_cmp(const void *, const void *);
+
+int is_template_compat (const Symbol *);
+void generate_template(const Symbol *);
+void generate_template_type_forward(const char *);
+void generate_template_objectset_forwards(const Symbol *);
+void gen_template_import(const Symbol *);
+
+struct objid **objid2list(struct objid *);
+
+extern FILE *jsonfile, *privheaderfile, *headerfile, *codefile, *logfile, *templatefile;
+extern const char *fuzzer_string;
+extern int support_ber;
+extern int template_flag;
+extern int rfc1510_bitstring;
+extern int one_code_file;
+extern int original_order;
+extern int parse_units_flag;
+extern char *type_file_string;
+
+extern int error_flag;
+
+#endif /* __GEN_LOCL_H__ */
diff --git a/third_party/heimdal/lib/asn1/gen_print.c b/third_party/heimdal/lib/asn1/gen_print.c
new file mode 100644
index 0000000..4cca9e0
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/gen_print.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gen_locl.h"
+
+void
+generate_type_print_stub(const Symbol *s)
+{
+ fprintf(codefile, "char * ASN1CALL\n"
+ "print_%s(const %s *data, int flags)\n"
+ "{ errno = EINVAL; return 0; }\n\n",
+ s->gen_name, s->gen_name);
+}
diff --git a/third_party/heimdal/lib/asn1/gen_seq.c b/third_party/heimdal/lib/asn1/gen_seq.c
new file mode 100644
index 0000000..9762813
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/gen_seq.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gen_locl.h"
+
+RCSID("$Id$");
+
+static FILE *
+get_code_file(void)
+{
+ if (!one_code_file && template_flag && templatefile)
+ return templatefile;
+ return codefile;
+}
+
+void
+generate_type_seq (const Symbol *s)
+{
+ char *subname;
+ Type *type;
+
+ if (!seq_type(s->name))
+ return;
+ type = s->type;
+ while(type->type == TTag)
+ type = type->subtype;
+
+ if (type->type != TSequenceOf && type->type != TSetOf) {
+ fprintf(stderr, "%s not seq of %d\n", s->name, (int)type->type);
+ return;
+ }
+
+ /*
+ * Require the subtype to be a type so we can name it and use
+ * copy_/free_
+ */
+
+ if (type->subtype->type != TType) {
+ fprintf(stderr, "%s subtype is not a type, can't generate "
+ "sequence code for this case: %d\n",
+ s->name, (int)type->subtype->type);
+ exit(1);
+ }
+
+ subname = type->subtype->symbol->gen_name;
+
+ fprintf (headerfile,
+ "ASN1EXP int ASN1CALL add_%s (%s *, const %s *);\n"
+ "ASN1EXP int ASN1CALL remove_%s (%s *, unsigned int);\n",
+ s->gen_name, s->gen_name, subname,
+ s->gen_name, s->gen_name);
+
+ fprintf (get_code_file(), "int ASN1CALL\n"
+ "add_%s(%s *data, const %s *element)\n"
+ "{\n",
+ s->gen_name, s->gen_name, subname);
+
+ fprintf (get_code_file(),
+ "int ret;\n"
+ "void *ptr;\n"
+ "\n"
+ "ptr = realloc(data->val, \n"
+ "\t(data->len + 1) * sizeof(data->val[0]));\n"
+ "if (ptr == NULL) return ENOMEM;\n"
+ "data->val = ptr;\n\n"
+ "ret = copy_%s(element, &data->val[data->len]);\n"
+ "if (ret) return ret;\n"
+ "data->len++;\n"
+ "return 0;\n",
+ subname);
+
+ fprintf (get_code_file(), "}\n\n");
+
+ fprintf (get_code_file(), "int ASN1CALL\n"
+ "remove_%s(%s *data, unsigned int element)\n"
+ "{\n",
+ s->gen_name, s->gen_name);
+
+ fprintf (get_code_file(),
+ "void *ptr;\n"
+ "\n"
+ "if (data->len == 0 || element >= data->len)\n"
+ "\treturn ASN1_OVERRUN;\n"
+ "free_%s(&data->val[element]);\n"
+ "data->len--;\n"
+ /* don't move if its the last element */
+ "if (element < data->len)\n"
+ "\tmemmove(&data->val[element], &data->val[element + 1], \n"
+ "\t\tsizeof(data->val[0]) * (data->len - element));\n"
+ /* resize but don't care about failures since it doesn't matter */
+ "ptr = realloc(data->val, data->len * sizeof(data->val[0]));\n"
+ "if (ptr != NULL || data->len == 0) data->val = ptr;\n"
+ "return 0;\n",
+ subname);
+
+ fprintf (get_code_file(), "}\n\n");
+}
diff --git a/third_party/heimdal/lib/asn1/gen_template.c b/third_party/heimdal/lib/asn1/gen_template.c
new file mode 100644
index 0000000..67d18ec
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/gen_template.c
@@ -0,0 +1,1675 @@
+/*
+ * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 - 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Currently we generate C source code defining constant arrays of structures
+ * containing a sort of a "byte-coded" template of an ASN.1 compiler to be
+ * interpreted at run-time.
+ */
+
+#include "gen_locl.h"
+#include <vis.h>
+#include <vis-extras.h>
+
+static const char *symbol_name(const char *, const Type *);
+static void generate_template_type(const char *, const char **, const char *, const char *, const char *,
+ Type *, int, int, int);
+
+static const char *
+ttype_symbol(const char *basename, const Type *t)
+{
+ return t->symbol->gen_name;
+}
+
+static const char *
+integer_symbol(const char *basename, const Type *t)
+{
+ if (t->members)
+ /*
+ * XXX enum foo -- compute the size either from inspecting the members
+ * and applying the ABI's rules for enum size, OR infer the field
+ * size from a template by using the offsetof field. The latter is
+ * hard to do though.
+ */
+ return "int";
+ else if (t->range == NULL)
+ return "heim_integer";
+ else if (t->range->min < 0 &&
+ (t->range->min < INT_MIN || t->range->max > INT_MAX))
+ return "int64_t";
+ else if (t->range->min < 0)
+ return "int";
+ else if (t->range->max > UINT_MAX)
+ return "uint64_t";
+ else
+ return "unsigned";
+}
+
+static const char *
+boolean_symbol(const char *basename, const Type *t)
+{
+ return "int";
+}
+
+
+static const char *
+octetstring_symbol(const char *basename, const Type *t)
+{
+ return "heim_octet_string";
+}
+
+static const char *
+sequence_symbol(const char *basename, const Type *t)
+{
+ return basename;
+}
+
+static const char *
+time_symbol(const char *basename, const Type *t)
+{
+ return "time_t";
+}
+
+static const char *
+tag_symbol(const char *basename, const Type *t)
+{
+ return symbol_name(basename, t->subtype);
+}
+
+static const char *
+generalstring_symbol(const char *basename, const Type *t)
+{
+ return "heim_general_string";
+}
+
+static const char *
+printablestring_symbol(const char *basename, const Type *t)
+{
+ return "heim_printable_string";
+}
+
+static const char *
+ia5string_symbol(const char *basename, const Type *t)
+{
+ return "heim_ia5_string";
+}
+
+static const char *
+teletexstring_symbol(const char *basename, const Type *t)
+{
+ return "heim_general_string";
+}
+
+static const char *
+visiblestring_symbol(const char *basename, const Type *t)
+{
+ return "heim_visible_string";
+}
+
+static const char *
+utf8string_symbol(const char *basename, const Type *t)
+{
+ return "heim_utf8_string";
+}
+
+static const char *
+bmpstring_symbol(const char *basename, const Type *t)
+{
+ return "heim_bmp_string";
+}
+
+static const char *
+universalstring_symbol(const char *basename, const Type *t)
+{
+ return "heim_universal_string";
+}
+
+static const char *
+oid_symbol(const char *basename, const Type *t)
+{
+ return "heim_oid";
+}
+
+static const char *
+bitstring_symbol(const char *basename, const Type *t)
+{
+ if (t->members)
+ return basename;
+ return "heim_bit_string";
+}
+
+
+
+/* Keep this sorted by `type' so we can just index this by type */
+const struct {
+ enum typetype type;
+ const char *(*symbol_name)(const char *, const Type *);
+ int is_struct;
+} types[] = {
+ { TBitString, bitstring_symbol, 0 },
+ { TBoolean, boolean_symbol, 0 },
+ { TChoice, sequence_symbol, 1 },
+ { TEnumerated, integer_symbol, 0 },
+ { TGeneralString, generalstring_symbol, 0 },
+ { TTeletexString, teletexstring_symbol, 0 },
+ { TGeneralizedTime, time_symbol, 0 },
+ { TIA5String, ia5string_symbol, 0 },
+ { TInteger, integer_symbol, 0 },
+ { TNull, integer_symbol, 1 },
+ { TOID, oid_symbol, 0 },
+ { TOctetString, octetstring_symbol, 0 },
+ { TPrintableString, printablestring_symbol, 0 },
+ { TSequence, sequence_symbol, 1 },
+ { TSequenceOf, tag_symbol, 1 },
+ { TSet, sequence_symbol, 1 },
+ { TSetOf, tag_symbol, 1 },
+ { TTag, tag_symbol, 1 },
+ { TType, ttype_symbol, 1 },
+ { TUTCTime, time_symbol, 0 },
+ { TUTF8String, utf8string_symbol, 0 },
+ { TBMPString, bmpstring_symbol, 0 },
+ { TUniversalString, universalstring_symbol, 0 },
+ { TVisibleString, visiblestring_symbol, 0 },
+};
+
+static FILE *
+get_code_file(void)
+{
+ if (!one_code_file)
+ return templatefile;
+ return codefile;
+}
+
+
+static int
+is_supported_type_p(const Type *t)
+{
+ return t->type >= 0 && t->type <= TVisibleString &&
+ types[t->type].type == t->type;
+}
+
+int
+is_template_compat (const Symbol *s)
+{
+ return is_supported_type_p(s->type);
+}
+
+static const char *
+symbol_name(const char *basename, const Type *t)
+{
+ if (t->type >= 0 && t->type <= TVisibleString &&
+ types[t->type].type == t->type)
+ return (types[t->type].symbol_name)(basename, t);
+ if (t->type >= 0 && t->type <= TVisibleString)
+ errx(1, "types[] is not sorted");
+ errx(1, "unknown der type: %d\n", t->type);
+ return NULL;
+}
+
+
+static char *
+partial_offset(const char *basetype, const char *name, int need_offset, int isstruct)
+{
+ char *str;
+ if (name == NULL || need_offset == 0)
+ return strdup("0");
+ if (asprintf(&str, "offsetof(%s%s, %s)", isstruct ? "struct " : "", basetype, name) < 0 || str == NULL)
+ errx(1, "malloc");
+ return str;
+}
+
+struct template {
+ char *line;
+ char *tt;
+ char *offset;
+ char *ptr;
+ HEIM_TAILQ_ENTRY(template) members;
+};
+
+HEIM_TAILQ_HEAD(templatehead, template);
+
+struct tlist {
+ char *name;
+ char *header;
+ struct templatehead template;
+ HEIM_TAILQ_ENTRY(tlist) tmembers;
+};
+
+HEIM_TAILQ_HEAD(tlisthead, tlist);
+
+static void tlist_header(struct tlist *, const char *, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
+static struct template *
+ add_line(struct templatehead *, const char *, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
+static int tlist_cmp(const struct tlist *, const struct tlist *);
+
+static void add_line_pointer(struct templatehead *, const char *, const char *, const char *, ...)
+ __attribute__ ((__format__ (__printf__, 4, 5)));
+static void add_line_string(struct templatehead *, const char *, const char *, const char *, ...)
+ __attribute__ ((__format__ (__printf__, 4, 5)));
+static void add_line_pointer_reference(struct templatehead *, const char *, const char *, const char *, ...)
+ __attribute__ ((__format__ (__printf__, 4, 5)));
+
+
+static struct tlisthead tlistmaster = HEIM_TAILQ_HEAD_INITIALIZER(tlistmaster);
+static unsigned long numdups = 0;
+
+static struct tlist *
+tlist_new(const char *name)
+{
+ struct tlist *tl = calloc(1, sizeof(*tl));
+ tl->name = strdup(name);
+ HEIM_TAILQ_INIT(&tl->template);
+ return tl;
+}
+
+static void
+tlist_header(struct tlist *t, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (vasprintf(&t->header, fmt, ap) < 0 || t->header == NULL)
+ errx(1, "malloc");
+ va_end(ap);
+}
+
+static unsigned long
+tlist_count(struct tlist *tl)
+{
+ unsigned int count = 0;
+ struct template *q;
+
+ HEIM_TAILQ_FOREACH(q, &tl->template, members) {
+ count++;
+ }
+ return count;
+}
+
+static void
+tlist_add(struct tlist *tl)
+{
+ HEIM_TAILQ_INSERT_TAIL(&tlistmaster, tl, tmembers);
+}
+
+static void
+tlist_print(struct tlist *tl)
+{
+ struct template *q;
+ unsigned int i = 1;
+ FILE *f = get_code_file();
+
+ fprintf(f, "const struct asn1_template asn1_%s[] = {\n", tl->name);
+ fprintf(f, "/* 0 */ %s,\n", tl->header);
+ HEIM_TAILQ_FOREACH(q, &tl->template, members) {
+ int last = (HEIM_TAILQ_LAST(&tl->template, templatehead) == q);
+ fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
+ }
+ fprintf(f, "};\n");
+}
+
+static struct tlist *
+tlist_find_by_name(const char *name)
+{
+ struct tlist *ql;
+ HEIM_TAILQ_FOREACH(ql, &tlistmaster, tmembers) {
+ if (strcmp(ql->name, name) == 0)
+ return ql;
+ }
+ return NULL;
+}
+
+static int
+tlist_cmp_name(const char *tname, const char *qname)
+{
+ struct tlist *tl = tlist_find_by_name(tname);
+ struct tlist *ql = tlist_find_by_name(qname);
+ if (tl == NULL)
+ return 1;
+ if (ql == NULL)
+ return -1;
+ return tlist_cmp(tl, ql);
+}
+
+static int
+tlist_cmp(const struct tlist *tl, const struct tlist *ql)
+{
+ int ret;
+ struct template *t, *q;
+
+ if (tl == ql)
+ return 0;
+ ret = strcmp(tl->header, ql->header);
+ if (ret != 0) return ret;
+
+ q = HEIM_TAILQ_FIRST(&ql->template);
+ HEIM_TAILQ_FOREACH(t, &tl->template, members) {
+ if (q == NULL) return 1;
+
+ if (t->ptr == NULL || q->ptr == NULL) {
+ ret = strcmp(t->line, q->line);
+ if (ret != 0) return ret;
+ } else {
+ ret = strcmp(t->tt, q->tt);
+ if (ret != 0) return ret;
+
+ ret = strcmp(t->offset, q->offset);
+ if (ret != 0) return ret;
+
+ if ((ret = strcmp(t->ptr, q->ptr)) != 0 ||
+ (ret = tlist_cmp_name(t->ptr, q->ptr)) != 0)
+ return ret;
+ }
+ q = HEIM_TAILQ_NEXT(q, members);
+ }
+ if (q != NULL) return -1;
+ return 0;
+}
+
+
+static const char *
+tlist_find_dup(const struct tlist *tl)
+{
+ struct tlist *ql;
+
+ HEIM_TAILQ_FOREACH(ql, &tlistmaster, tmembers) {
+ if (tlist_cmp(ql, tl) == 0) {
+ numdups++;
+ return ql->name;
+ }
+ }
+ return NULL;
+}
+
+
+/*
+ * Add an entry to a template.
+ */
+
+static struct template *
+add_line(struct templatehead *t, const char *fmt, ...)
+{
+ struct template *q = calloc(1, sizeof(*q));
+ va_list ap;
+ va_start(ap, fmt);
+ if (vasprintf(&q->line, fmt, ap) < 0 || q->line == NULL)
+ errx(1, "malloc");
+ va_end(ap);
+ HEIM_TAILQ_INSERT_TAIL(t, q, members);
+ return q;
+}
+
+/*
+ * Add an entry to a template, with the pointer field being a symbol name of a
+ * template (i.e., an array, which decays to a pointer as usual in C).
+ */
+static void
+add_line_pointer(struct templatehead *t,
+ const char *ptr,
+ const char *offset,
+ const char *ttfmt,
+ ...)
+{
+ struct template *q;
+ va_list ap;
+ char *tt = NULL;
+
+ va_start(ap, ttfmt);
+ if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
+ errx(1, "malloc");
+ va_end(ap);
+
+ if (ptr[0] == '&')
+ q = add_line(t, "{ %s, %s, %s }", tt, offset, ptr);
+ else
+ q = add_line(t, "{ %s, %s, asn1_%s }", tt, offset, ptr);
+ q->tt = tt;
+ q->offset = strdup(offset);
+ q->ptr = strdup(ptr);
+}
+
+/*
+ * Add an entry to a template where the pointer field is a string literal.
+ */
+static void
+add_line_string(struct templatehead *t,
+ const char *str,
+ const char *offset,
+ const char *ttfmt,
+ ...)
+{
+ struct template *q;
+ va_list ap;
+ char *tt = NULL;
+
+ va_start(ap, ttfmt);
+ if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
+ errx(1, "malloc");
+ va_end(ap);
+
+ q = add_line(t, "{ %s, %s, \"%s\" }", tt, offset, str);
+ q->tt = tt;
+ q->offset = strdup(offset);
+ q->ptr = strdup(str);
+}
+
+/*
+ * Add an entry to a template, with the pointer field being a reference to
+ * named object of a type other than a template or other array type.
+ */
+static void
+add_line_pointer_reference(struct templatehead *t,
+ const char *ptr,
+ const char *offset,
+ const char *ttfmt,
+ ...)
+{
+ struct template *q;
+ va_list ap;
+ char *tt = NULL;
+
+ va_start(ap, ttfmt);
+ if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
+ errx(1, "malloc");
+ va_end(ap);
+
+ q = add_line(t, "{ %s, %s, (const void *)&asn1_%s }", tt, offset, ptr);
+ q->tt = tt;
+ q->offset = strdup(offset);
+ q->ptr = strdup(ptr);
+}
+
+static int
+use_extern(const Symbol *s)
+{
+ if (s->type == NULL)
+ return 1;
+ return 0;
+}
+
+static int
+is_struct(const Type *t, int isstruct)
+{
+ if (t->type == TType)
+ return 0;
+ if (t->type == TSequence || t->type == TSet || t->type == TChoice)
+ return 1;
+ if (t->type == TTag)
+ return is_struct(t->subtype, isstruct);
+
+ if (t->type >= 0 && t->type <= TVisibleString &&
+ types[t->type].type == t->type) {
+ if (types[t->type].is_struct == 0)
+ return 0;
+ return isstruct;
+ }
+ if (t->type >= 0 && t->type <= TVisibleString)
+ errx(1, "types[] is not sorted");
+ errx(1, "unknown der type: %d\n", t->type);
+ return isstruct;
+}
+
+static const Type *
+compact_tag(const Type *t)
+{
+ while (t->type == TTag)
+ t = t->subtype;
+ return t;
+}
+
+static void
+defval(struct templatehead *temp, Member *m)
+{
+ switch (m->defval->type) {
+ case booleanvalue:
+ add_line(temp, "{ A1_OP_DEFVAL|A1_DV_BOOLEAN, ~0, (void *)(uintptr_t)%u }",
+ m->defval->u.booleanvalue);
+ break;
+ case nullvalue:
+ add_line(temp, "{ A1_OP_DEFVAL|A1_DV_NULL, ~0, (void *)(uintptr_t)0 }");
+ break;
+ case integervalue: {
+ const char *dv = "A1_DV_INTEGER";
+ Type *t = m->type;
+
+ for (;;) {
+ if (t->range)
+ break;
+ if (t->type == TInteger && t->members)
+ break;
+ if (t->type == TEnumerated)
+ break;
+ if (t->subtype)
+ t = t->subtype;
+ else if (t->symbol && t->symbol->type)
+ t = t->symbol->type;
+ else
+ errx(1, "DEFAULT values for unconstrained INTEGER members not supported");
+ }
+
+ if (t->members)
+ dv = "A1_DV_INTEGER32"; /* XXX Enum size assumptions! No good! */
+ else if (t->range && t->range->min < 0 &&
+ (t->range->min < INT_MIN || t->range->max > INT_MAX))
+ dv = "A1_DV_INTEGER64";
+ else if (t->range && t->range->min < 0)
+ dv = "A1_DV_INTEGER32";
+ else if (t->range && t->range->max > UINT_MAX)
+ dv = "A1_DV_INTEGER64";
+ else
+ dv = "A1_DV_INTEGER32";
+ add_line(temp, "{ A1_OP_DEFVAL|%s, ~0, (void *)(uintptr_t)%llu }",
+ dv, (long long)m->defval->u.integervalue);
+ break;
+ }
+ case stringvalue: {
+ char *quoted;
+
+ if (rk_strasvis(&quoted, m->defval->u.stringvalue,
+ VIS_CSTYLE | VIS_NL, "\"") < 0)
+ err(1, "Could not quote a string");
+ add_line(temp, "{ A1_OP_DEFVAL|A1_DV_UTF8STRING, ~0, (void *)(uintptr_t)\"%s\" }",
+ quoted);
+ free(quoted);
+ break;
+ }
+ case objectidentifiervalue: {
+ struct objid *o;
+ size_t sz = sizeof("{ }");
+ char *s, *p;
+ int len;
+
+ for (o = m->defval->u.objectidentifiervalue; o != NULL; o = o->next) {
+ if ((len = snprintf(0, 0, " %d", o->value)) < 0)
+ err(1, "Could not format integer");
+ sz += len;
+ }
+
+ if ((p = s = malloc(sz)) == NULL)
+ err(1, "Could not allocate string");
+
+ len = snprintf(p, sz, "{");
+ sz -= len;
+ p += len;
+ for (o = m->defval->u.objectidentifiervalue; o != NULL; o = o->next) {
+ if ((len = snprintf(p, sz, " %d", o->value)) < 0 || len > sz - 1)
+ err(1, "Could not format integer");
+ sz -= len;
+ p += len;
+ }
+ if ((len = snprintf(p, sz, " }")) >= sz)
+ abort();
+ sz -= len;
+ if (sz != 0)
+ abort();
+
+ add_line(temp, "{ A1_OP_DEFVAL|A1_DV_INTEGER, ~0, (void *)(uintptr_t)\"%s\" }", s);
+ free(s);
+ break;
+ }
+ default: abort();
+ }
+}
+
+int
+objid_cmp(struct objid *oida, struct objid *oidb)
+{
+ struct objid *p;
+ size_t ai, bi, alen, blen;
+ int avals[20];
+ int bvals[20];
+ int c;
+
+ /*
+ * Our OID values are backwards here. Comparing them is hard.
+ */
+
+ for (p = oida, alen = 0;
+ p && alen < sizeof(avals)/sizeof(avals[0]);
+ p = p->next)
+ avals[alen++] = p->value;
+ for (p = oidb, blen = 0;
+ p && blen < sizeof(bvals)/sizeof(bvals[0]);
+ p = p->next)
+ bvals[blen++] = p->value;
+ if (alen >= sizeof(avals)/sizeof(avals[0]) ||
+ blen >= sizeof(bvals)/sizeof(bvals[0]))
+ err(1, "OIDs with more components than %llu not supported",
+ (unsigned long long)sizeof(avals)/sizeof(avals[0]));
+
+ for (ai = 0, bi = 0; ai < alen && bi < blen;)
+ if ((c = avals[(alen-1)-(ai++)] - bvals[(blen-1)-(bi++)]))
+ return c;
+
+ if (ai == alen && bi == blen)
+ return 0;
+ if (ai == alen)
+ return 1;
+ return -1;
+}
+
+int
+object_cmp(const void *va, const void *vb)
+{
+ const IOSObject *oa = *(const IOSObject * const *)va;
+ const IOSObject *ob = *(const IOSObject * const *)vb;
+
+ switch (oa->typeidf->value->type) {
+ case booleanvalue:
+ return oa->typeidf->value->u.booleanvalue -
+ ob->typeidf->value->u.booleanvalue;
+ case nullvalue:
+ return 0;
+ case integervalue:
+ return oa->typeidf->value->u.integervalue -
+ ob->typeidf->value->u.integervalue;
+ case stringvalue:
+ return strcmp(oa->typeidf->value->u.stringvalue,
+ ob->typeidf->value->u.stringvalue);
+ case objectidentifiervalue: {
+ return objid_cmp(oa->typeidf->value->u.objectidentifiervalue,
+ ob->typeidf->value->u.objectidentifiervalue);
+ }
+ default:
+ abort();
+ return -1;
+ }
+}
+
+void
+sort_object_set(IOSObjectSet *os, /* Object set to sort fields of */
+ Field *typeidfield, /* Field to sort by */
+ IOSObject ***objectsp, /* Output: array of objects */
+ size_t *nobjsp) /* Output: count of objects */
+{
+ IOSObject **objects;
+ IOSObject *o;
+ size_t i, nobjs = 0;
+
+ *objectsp = NULL;
+
+ HEIM_TAILQ_FOREACH(o, os->objects, objects) {
+ ObjectField *typeidobjf = NULL;
+ ObjectField *of;
+
+ HEIM_TAILQ_FOREACH(of, o->objfields, objfields) {
+ if (strcmp(of->name, typeidfield->name) == 0)
+ typeidobjf = of;
+ }
+ if (!typeidobjf) {
+ warnx("Ignoring incomplete object specification of %s "
+ "(missing type ID field)",
+ o->symbol ? o->symbol->name : "<unknown>");
+ continue;
+ }
+ o->typeidf = typeidobjf;
+ nobjs++;
+ }
+ *nobjsp = nobjs;
+
+ if (nobjs == 0)
+ return;
+
+ if ((objects = calloc(nobjs, sizeof(*objects))) == NULL)
+ err(1, "Out of memory");
+ *objectsp = objects;
+
+ i = 0;
+ HEIM_TAILQ_FOREACH(o, os->objects, objects) {
+ ObjectField *typeidobjf = NULL;
+ ObjectField *of;
+
+ HEIM_TAILQ_FOREACH(of, o->objfields, objfields) {
+ if (strcmp(of->name, typeidfield->name) == 0)
+ typeidobjf = of;
+ }
+ if (typeidobjf)
+ objects[i++] = o;
+ }
+ qsort(objects, nobjs, sizeof(*objects), object_cmp);
+}
+
+static void
+template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield)
+{
+ IOSObject **objects = NULL;
+ IOSObject *o;
+ struct tlist *tl;
+ size_t nobjs, i;
+
+ if (os->symbol->emitted_template)
+ return;
+
+ sort_object_set(os, typeidfield, &objects, &nobjs);
+
+ tl = tlist_new(os->symbol->name);
+ add_line(&tl->template, "{ A1_OP_NAME, 0, \"%s\" }", os->symbol->name);
+ for (i = 0; i < nobjs; i++) {
+ ObjectField *typeidobjf = NULL, *opentypeobjf = NULL;
+ ObjectField *of;
+ char *s = NULL;
+
+ o = objects[i];
+
+ HEIM_TAILQ_FOREACH(of, o->objfields, objfields) {
+ if (strcmp(of->name, typeidfield->name) == 0)
+ typeidobjf = of;
+ else if (strcmp(of->name, opentypefield->name) == 0)
+ opentypeobjf = of;
+ }
+ if (!typeidobjf)
+ continue; /* We've warned about this one already when sorting */
+ if (!opentypeobjf) {
+ warnx("Ignoring incomplete object specification of %s "
+ "(missing open type field)",
+ o->symbol ? o->symbol->name : "<unknown>");
+ continue;
+ }
+
+ add_line(&tl->template, "{ A1_OP_NAME, 0, \"%s\" }", o->symbol->name);
+ /*
+ * Some of this logic could stand to move into sanity checks of object
+ * definitions in asn1parse.y.
+ */
+ switch (typeidobjf->value->type) {
+ case integervalue:
+ add_line(&tl->template,
+ "{ A1_OP_OPENTYPE_ID | A1_OTI_IS_INTEGER, 0, (void *)(uintptr_t)%lld }",
+ (long long)typeidobjf->value->u.integervalue);
+ break;
+ case objectidentifiervalue:
+ if (asprintf(&s, "oid_%s",
+ typeidobjf->value->s->gen_name) == -1 || !s)
+ err(1, "Out of memory");
+ add_line_pointer_reference(&tl->template, s, "0", "A1_OP_OPENTYPE_ID");
+ free(s);
+ s = NULL;
+ break;
+ default:
+ errx(1, "Only integer and OID types supported "
+ "for open type type-ID fields");
+ }
+
+ if (asprintf(&s, "sizeof(%s)",
+ opentypeobjf->type->symbol->gen_name) == -1 || !s)
+ err(1, "Out of memory");
+ add_line_pointer_reference(&tl->template,
+ opentypeobjf->type->symbol->gen_name, s,
+ "A1_OP_OPENTYPE");
+ free(s);
+ }
+ free(objects);
+
+ tlist_header(tl, "{ 0, 0, ((void *)(uintptr_t)%zu) }", nobjs);
+ tlist_print(tl);
+ tlist_add(tl);
+ os->symbol->emitted_template = 1;
+}
+
+static void
+template_open_type(struct templatehead *temp,
+ const char *basetype,
+ const Type *t,
+ size_t typeididx,
+ size_t opentypeidx,
+ Field *typeidfield,
+ Field *opentypefield,
+ Member *m,
+ int is_array_of_open_type)
+{
+ char *s = NULL;
+
+ if (typeididx >= 1<<10 || opentypeidx >= 1<<10)
+ errx(1, "SET/SEQUENCE with too many members (%s)", basetype);
+
+ if (asprintf(&s, "offsetof(%s, _ioschoice_%s)",
+ basetype, m->gen_name) == -1 || !s)
+ err(1, "Out of memory");
+
+ template_object_set(t->actual_parameter, typeidfield, opentypefield);
+ add_line_pointer(temp, t->actual_parameter->symbol->gen_name, s,
+ /*
+ * We always sort object sets for now as we can't import
+ * values yet, so they must all be known.
+ */
+ "A1_OP_OPENTYPE_OBJSET | A1_OS_IS_SORTED |%s | (%llu << 10) | %llu",
+ is_array_of_open_type ? "A1_OS_OT_IS_ARRAY" : "0",
+ (unsigned long long)opentypeidx,
+ (unsigned long long)typeididx);
+ free(s);
+}
+
+static void
+template_names(struct templatehead *temp, const char *basetype, const Type *t)
+{
+ Member *m;
+
+ add_line_string(temp, basetype, "0", "A1_OP_NAME");
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ add_line_string(temp, m->name, "0", "A1_OP_NAME");
+ }
+}
+
+static void
+template_members(struct templatehead *temp,
+ const char *basetype,
+ const char *name,
+ const Type *t,
+ int optional,
+ int defaulted,
+ int implicit,
+ int isstruct,
+ int need_offset)
+{
+ char *poffset = NULL;
+
+ if (optional && t->type != TTag && t->type != TType)
+ errx(1, "%s...%s is optional and not a (TTag or TType)", basetype, name);
+
+ poffset = partial_offset(basetype, name, need_offset, isstruct);
+
+ switch (t->type) {
+ case TType:
+ if (use_extern(t->symbol)) {
+ add_line(temp, "{ A1_OP_TYPE_EXTERN %s%s%s, %s, &asn1_extern_%s}",
+ optional ? "|A1_FLAG_OPTIONAL" : "",
+ defaulted ? "|A1_FLAG_DEFAULT" : "",
+ implicit ? "|A1_FLAG_IMPLICIT" : "",
+ poffset, t->symbol->gen_name);
+ } else {
+ add_line_pointer(temp, t->symbol->gen_name, poffset,
+ "A1_OP_TYPE %s%s%s",
+ optional ? "|A1_FLAG_OPTIONAL" : "",
+ defaulted ? "|A1_FLAG_DEFAULT" : "",
+ implicit ? "|A1_FLAG_IMPLICIT" : "");
+
+ }
+ break;
+ case TEnumerated:
+ case TInteger: {
+ char *varname = NULL;
+ char *itype = NULL;
+
+ if (t->members)
+ itype = "IMEMBER";
+ else if (t->range == NULL)
+ itype = "HEIM_INTEGER";
+ else if (t->range->min < 0 &&
+ (t->range->min < INT_MIN || t->range->max > INT_MAX))
+ itype = "INTEGER64";
+ else if (t->range->min < 0)
+ itype = "INTEGER";
+ else if (t->range->max > UINT_MAX)
+ itype = "UNSIGNED64";
+ else
+ itype = "UNSIGNED";
+
+ /*
+ * If `t->members' then we should generate a template for those
+ * members.
+ *
+ * We don't know the name of this field, and the type may not have a
+ * name. If it has no name, we should generate a name for it, and if
+ * it does have a name, use it, to name a template for its members.
+ *
+ * Then we could use that in _asn1_print() to pretty-print values of
+ * enumerations.
+ */
+ if (t->members && t->symbol) {
+ struct tlist *tl;
+ Member *m;
+ size_t nmemb = 0;
+
+ if (asprintf(&varname, "%s_enum_names", t->symbol->gen_name) == -1 ||
+ varname == NULL)
+ err(1, "Out of memory");
+
+ tl = tlist_new(varname);
+ /*
+ * XXX We're going to assume that t->members is sorted in
+ * numerically ascending order in the module source. We should
+ * really sort it here.
+ */
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ if (m->val > UINT32_MAX)
+ errx(1, "Cannot handle %s type %s with named bit %s "
+ "larger than 63",
+ t->type == TEnumerated ? "ENUMERATED" : "INTEGER",
+ name, m->gen_name);
+ add_line(&tl->template,
+ "{ A1_OP_NAME, %d, \"%s\" }", (int)m->val, m->name);
+ nmemb++;
+ }
+ tlist_header(tl, "{ 0, 0, ((void *)(uintptr_t)%zu) }", nmemb);
+ /* XXX Accidentally O(N^2)? */
+ if (!tlist_find_dup(tl)) {
+ tlist_print(tl);
+ tlist_add(tl);
+ }
+ add_line(temp, "{ A1_PARSE_T(A1T_%s), %s, asn1_%s }", itype, poffset, varname);
+ } else {
+ add_line(temp, "{ A1_PARSE_T(A1T_%s), %s, NULL }", itype, poffset);
+ }
+ break;
+ }
+ case TGeneralString:
+ add_line(temp, "{ A1_PARSE_T(A1T_GENERAL_STRING), %s, NULL }", poffset);
+ break;
+ case TTeletexString:
+ add_line(temp, "{ A1_PARSE_T(A1T_TELETEX_STRING), %s, NULL }", poffset);
+ break;
+ case TPrintableString:
+ add_line(temp, "{ A1_PARSE_T(A1T_PRINTABLE_STRING), %s, NULL }", poffset);
+ break;
+ case TOctetString:
+ add_line(temp, "{ A1_PARSE_T(A1T_OCTET_STRING), %s, NULL }", poffset);
+ break;
+ case TIA5String:
+ add_line(temp, "{ A1_PARSE_T(A1T_IA5_STRING), %s, NULL }", poffset);
+ break;
+ case TBMPString:
+ add_line(temp, "{ A1_PARSE_T(A1T_BMP_STRING), %s, NULL }", poffset);
+ break;
+ case TUniversalString:
+ add_line(temp, "{ A1_PARSE_T(A1T_UNIVERSAL_STRING), %s, NULL }", poffset);
+ break;
+ case TVisibleString:
+ add_line(temp, "{ A1_PARSE_T(A1T_VISIBLE_STRING), %s, NULL }", poffset);
+ break;
+ case TUTF8String:
+ add_line(temp, "{ A1_PARSE_T(A1T_UTF8_STRING), %s, NULL }", poffset);
+ break;
+ case TGeneralizedTime:
+ add_line(temp, "{ A1_PARSE_T(A1T_GENERALIZED_TIME), %s, NULL }", poffset);
+ break;
+ case TUTCTime:
+ add_line(temp, "{ A1_PARSE_T(A1T_UTC_TIME), %s, NULL }", poffset);
+ break;
+ case TBoolean:
+ add_line(temp, "{ A1_PARSE_T(A1T_BOOLEAN), %s, NULL }", poffset);
+ break;
+ case TOID:
+ add_line(temp, "{ A1_PARSE_T(A1T_OID), %s, NULL }", poffset);
+ break;
+ case TNull:
+ break;
+ case TBitString: {
+ struct templatehead template;
+ struct template *q;
+ Member *m;
+ size_t count = 0, i;
+ char *bname = NULL;
+ FILE *f = get_code_file();
+ static unsigned long bmember_counter = 0;
+
+ HEIM_TAILQ_INIT(&template);
+
+ if (HEIM_TAILQ_EMPTY(t->members)) {
+ add_line(temp, "{ A1_PARSE_T(A1T_HEIM_BIT_STRING), %s, NULL }", poffset);
+ break;
+ }
+
+ if (asprintf(&bname, "bmember_%s_%lu", name ? name : "", bmember_counter++) < 0 || bname == NULL)
+ errx(1, "malloc");
+ output_name(bname);
+
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ if (m->val > UINT32_MAX)
+ errx(1, "Cannot handle BIT STRING type %s with named bit %s "
+ "larger than 63", name, m->gen_name);
+ add_line(&template, "{ 0, %d, \"%s\" }", (int)m->val, m->gen_name);
+ }
+
+ HEIM_TAILQ_FOREACH(q, &template, members) {
+ count++;
+ }
+
+ fprintf(f, "static const struct asn1_template asn1_%s_%s[] = {\n", basetype, bname);
+ fprintf(f, "/* 0 */ { 0%s, sizeof(%s), ((void *)(uintptr_t)%lu) },\n",
+ rfc1510_bitstring ? "|A1_HBF_RFC1510" : "",
+ basetype, (unsigned long)count);
+ i = 1;
+ HEIM_TAILQ_FOREACH(q, &template, members) {
+ int last = (HEIM_TAILQ_LAST(&template, templatehead) == q);
+ fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
+ }
+ fprintf(f, "};\n");
+
+ add_line(temp, "{ A1_OP_BMEMBER, %s, asn1_%s_%s }", poffset, basetype, bname);
+
+ free(bname);
+
+ break;
+ }
+ case TSet: {
+ Member *opentypemember = NULL;
+ Member *typeidmember = NULL;
+ Field *opentypefield = NULL;
+ Field *typeidfield = NULL;
+ Member *m;
+ struct decoration deco;
+ ssize_t more_deco = -1;
+ size_t i = 0, typeididx = 0, opentypeidx = 0;
+ int is_array_of_open_type = 0;
+
+ if (isstruct && t->actual_parameter)
+ get_open_type_defn_fields(t, &typeidmember, &opentypemember,
+ &typeidfield, &opentypefield,
+ &is_array_of_open_type);
+
+ fprintf(get_code_file(), "/* tset: members isstruct: %d */\n", isstruct);
+
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ char *newbasename = NULL;
+
+ if (m->ellipsis)
+ continue;
+
+ if (typeidmember == m) typeididx = i;
+ if (opentypemember == m) opentypeidx = i;
+
+ if (name) {
+ if (asprintf(&newbasename, "%s_%s", basetype, name) < 0)
+ errx(1, "malloc");
+ } else
+ newbasename = strdup(basetype);
+ if (newbasename == NULL)
+ errx(1, "malloc");
+
+ if (m->defval)
+ defval(temp, m);
+
+ template_members(temp, newbasename, m->gen_name, m->type, m->optional, m->defval ? 1 : 0, 0, isstruct, 1);
+
+ free(newbasename);
+ i++;
+ }
+
+ if (isstruct && t->actual_parameter)
+ template_open_type(temp, basetype, t, typeididx, opentypeidx,
+ typeidfield, opentypefield, opentypemember,
+ is_array_of_open_type);
+
+ while (decorate_type(basetype, &deco, &more_deco)) {
+ char *poffset2;
+
+ poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
+
+ if (deco.ext) {
+ char *ptr = NULL;
+
+ /* Decorated with external C type */
+ if (asprintf(&ptr, "&asn1_extern_%s_%s",
+ basetype, deco.field_name) == -1 || ptr == NULL)
+ err(1, "out of memory");
+ add_line_pointer(temp, ptr, poffset2,
+ "A1_OP_TYPE_DECORATE_EXTERN %s",
+ deco.opt ? "|A1_FLAG_OPTIONAL" : "");
+ free(ptr);
+ } else
+ /* Decorated with a templated ASN.1 type */
+ add_line_pointer(temp, deco.field_type, poffset2,
+ "A1_OP_TYPE_DECORATE %s",
+ deco.opt ? "|A1_FLAG_OPTIONAL" : "");
+ free(poffset2);
+ free(deco.field_type);
+ }
+
+ if (isstruct)
+ template_names(temp, basetype, t);
+ break;
+ }
+ case TSequence: {
+ Member *opentypemember = NULL;
+ Member *typeidmember = NULL;
+ Field *opentypefield = NULL;
+ Field *typeidfield = NULL;
+ Member *m;
+ struct decoration deco;
+ ssize_t more_deco = -1;
+ size_t i = 0, typeididx = 0, opentypeidx = 0;
+ int is_array_of_open_type = 0;
+
+ if (isstruct && t->actual_parameter)
+ get_open_type_defn_fields(t, &typeidmember, &opentypemember,
+ &typeidfield, &opentypefield,
+ &is_array_of_open_type);
+
+ fprintf(get_code_file(), "/* tsequence: members isstruct: %d */\n", isstruct);
+
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ char *newbasename = NULL;
+
+ if (m->ellipsis)
+ continue;
+
+ if (typeidmember == m) typeididx = i;
+ if (opentypemember == m) opentypeidx = i;
+
+ if (name) {
+ if (asprintf(&newbasename, "%s_%s", basetype, name) < 0)
+ errx(1, "malloc");
+ } else
+ newbasename = strdup(basetype);
+ if (newbasename == NULL)
+ errx(1, "malloc");
+
+ if (m->defval)
+ defval(temp, m);
+
+ template_members(temp, newbasename, m->gen_name, m->type, m->optional, m->defval ? 1 : 0, 0, isstruct, 1);
+
+ free(newbasename);
+ i++;
+ }
+
+ if (isstruct && t->actual_parameter)
+ template_open_type(temp, basetype, t, typeididx, opentypeidx,
+ typeidfield, opentypefield, opentypemember,
+ is_array_of_open_type);
+
+ while (decorate_type(basetype, &deco, &more_deco)) {
+ char *poffset2;
+
+ poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
+
+ if (deco.ext) {
+ char *ptr = NULL;
+
+ /* Decorated with external C type */
+ if (asprintf(&ptr, "&asn1_extern_%s_%s",
+ basetype, deco.field_name) == -1 || ptr == NULL)
+ err(1, "out of memory");
+ add_line_pointer(temp, ptr, poffset2,
+ "A1_OP_TYPE_DECORATE_EXTERN %s",
+ deco.opt ? "|A1_FLAG_OPTIONAL" : "");
+ free(ptr);
+ } else
+ /* Decorated with a templated ASN.1 type */
+ add_line_pointer(temp, deco.field_type, poffset2,
+ "A1_OP_TYPE_DECORATE %s",
+ deco.opt ? "|A1_FLAG_OPTIONAL" : "");
+ free(poffset2);
+ free(deco.field_type);
+ }
+
+ if (isstruct)
+ template_names(temp, basetype, t);
+ break;
+ }
+ case TTag: {
+ char *tname = NULL, *elname = NULL;
+ const char *sename, *dupname;
+ int subtype_is_struct = is_struct(t->subtype, isstruct);
+ static unsigned long tag_counter = 0;
+ int tagimplicit = 0;
+ int prim = !(t->tag.tagclass != ASN1_C_UNIV &&
+ t->tag.tagenv == TE_EXPLICIT) &&
+ is_primitive_type(t->subtype);
+
+ if (t->tag.tagenv == TE_IMPLICIT) {
+ Type *t2 = t->subtype;
+
+ while (t2->type == TType && (t2->subtype || t2->symbol->type))
+ t2 = t2->subtype ? t2->subtype : t2->symbol->type;
+ if (t2->type != TChoice)
+ tagimplicit = 1;
+ }
+
+ fprintf(get_code_file(), "/* template_members: %s %s %s */\n", basetype, implicit ? "imp" : "exp", tagimplicit ? "imp" : "exp");
+
+ if (subtype_is_struct)
+ sename = basetype;
+ else
+ sename = symbol_name(basetype, t->subtype);
+
+ if (asprintf(&tname, "tag_%s_%lu", name ? name : "", tag_counter++) < 0 || tname == NULL)
+ errx(1, "malloc");
+ output_name(tname);
+
+ if (asprintf(&elname, "%s_%s", basetype, tname) < 0 || elname == NULL)
+ errx(1, "malloc");
+
+ generate_template_type(elname, &dupname, NULL, sename, name,
+ t->subtype, 0, subtype_is_struct, 0);
+
+ add_line_pointer(temp, dupname, poffset,
+ "A1_TAG_T(%s,%s,%s)%s%s%s",
+ classname(t->tag.tagclass),
+ prim ? "PRIM" : "CONS",
+ valuename(t->tag.tagclass, t->tag.tagvalue),
+ optional ? "|A1_FLAG_OPTIONAL" : "",
+ defaulted ? "|A1_FLAG_DEFAULT" : "",
+ tagimplicit ? "|A1_FLAG_IMPLICIT" : "");
+
+ free(tname);
+ free(elname);
+
+ break;
+ }
+ case TSetOf:
+ case TSequenceOf: {
+ const char *type = NULL, *tname, *dupname;
+ char *sename = NULL, *elname = NULL;
+ int subtype_is_struct = is_struct(t->subtype, 0);
+ static unsigned long seof_counter = 0;
+
+ if (name && subtype_is_struct) {
+ tname = "seofTstruct";
+ if (asprintf(&sename, "%s_%s_val", basetype, name) < 0)
+ errx(1, "malloc");
+ } else if (subtype_is_struct) {
+ tname = "seofTstruct";
+ if (asprintf(&sename, "%s_val", symbol_name(basetype, t->subtype)) < 0)
+ errx(1, "malloc");
+ } else {
+ if (name)
+ tname = name;
+ else
+ tname = "seofTstruct";
+ sename = strdup(symbol_name(basetype, t->subtype));
+ }
+ if (sename == NULL)
+ errx(1, "malloc");
+
+ if (t->type == TSetOf) type = "A1_OP_SETOF";
+ else if (t->type == TSequenceOf) type = "A1_OP_SEQOF";
+ else abort();
+
+ if (asprintf(&elname, "%s_%s_%lu", basetype, tname, seof_counter++) < 0 || elname == NULL)
+ errx(1, "malloc");
+
+ generate_template_type(elname, &dupname, NULL, sename, NULL, t->subtype,
+ 0, subtype_is_struct, need_offset);
+
+ add_line(temp, "{ %s, %s, asn1_%s }", type, poffset, dupname);
+ free(sename);
+ break;
+ }
+ case TChoice: {
+ struct decoration deco;
+ ssize_t more_deco = -1;
+ struct templatehead template;
+ struct template *q;
+ size_t count = 0, i;
+ char *tname = NULL;
+ FILE *f = get_code_file();
+ Member *m;
+ int ellipsis = 0;
+ char *e;
+ static unsigned long choice_counter = 0;
+
+ HEIM_TAILQ_INIT(&template);
+
+ if (asprintf(&tname, "asn1_choice_%s_%s%lu",
+ basetype, name ? name : "", choice_counter++) < 0 || tname == NULL)
+ errx(1, "malloc");
+
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ const char *dupname;
+ char *elname = NULL;
+ char *newbasename = NULL;
+ int subtype_is_struct;
+
+ if (m->ellipsis) {
+ ellipsis = 1;
+ continue;
+ }
+
+ subtype_is_struct = is_struct(m->type, 0);
+
+ if (asprintf(&elname, "%s_choice_%s", basetype, m->gen_name) < 0 || elname == NULL)
+ errx(1, "malloc");
+
+ if (subtype_is_struct) {
+ if (asprintf(&newbasename, "%s_%s", basetype, m->gen_name) < 0)
+ errx(1, "malloc");
+ } else
+ newbasename = strdup(basetype);
+
+ if (newbasename == NULL)
+ errx(1, "malloc");
+
+
+ generate_template_type(elname, &dupname, NULL,
+ symbol_name(newbasename, m->type),
+ NULL, m->type, 0, subtype_is_struct, 1);
+
+ add_line(&template, "{ %s, offsetof(%s%s, u.%s), asn1_%s }",
+ m->label, isstruct ? "struct " : "",
+ basetype, m->gen_name,
+ dupname);
+
+ free(elname);
+ free(newbasename);
+ }
+
+ HEIM_TAILQ_FOREACH(m, t->members, members) {
+ add_line(&template, "{ 0, 0, \"%s\" }", m->name);
+ }
+
+ e = NULL;
+ if (ellipsis) {
+ if (asprintf(&e, "offsetof(%s%s, u.asn1_ellipsis)", isstruct ? "struct " : "", basetype) < 0 || e == NULL)
+ errx(1, "malloc");
+ }
+
+ HEIM_TAILQ_FOREACH(q, &template, members) {
+ count++;
+ }
+
+ fprintf(f, "static const struct asn1_template %s[] = {\n", tname);
+ fprintf(f, "/* 0 */ { %s, offsetof(%s%s, element), ((void *)(uintptr_t)%lu) },\n",
+ e ? e : "0", isstruct ? "struct " : "", basetype, (unsigned long)count);
+ i = 1;
+ HEIM_TAILQ_FOREACH(q, &template, members) {
+ int last = (HEIM_TAILQ_LAST(&template, templatehead) == q);
+ fprintf(f, "/* %lu */ %s%s\n", (unsigned long)i++, q->line, last ? "" : ",");
+ }
+ fprintf(f, "};\n");
+
+ add_line(temp, "{ A1_OP_CHOICE, %s, %s }", poffset, tname);
+
+ while (decorate_type(basetype, &deco, &more_deco)) {
+ char *poffset2;
+
+ poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
+
+ if (deco.ext) {
+ char *ptr = NULL;
+
+ /* Decorated with external C type */
+ if (asprintf(&ptr, "&asn1_extern_%s_%s",
+ basetype, deco.field_name) == -1 || ptr == NULL)
+ err(1, "out of memory");
+ add_line_pointer(temp, ptr, poffset2,
+ "A1_OP_TYPE_DECORATE_EXTERN %s",
+ deco.opt ? "|A1_FLAG_OPTIONAL" : "");
+ free(ptr);
+ } else
+ /* Decorated with a templated ASN.1 type */
+ add_line_pointer(temp, deco.field_type, poffset2,
+ "A1_OP_TYPE_DECORATE %s",
+ deco.opt ? "|A1_FLAG_OPTIONAL" : "");
+ free(poffset2);
+ free(deco.field_type);
+ }
+
+ free(e);
+ free(tname);
+ break;
+ }
+ default:
+ abort ();
+ }
+ if (poffset)
+ free(poffset);
+}
+
+static void
+gen_extern_stubs(FILE *f, const char *name)
+{
+ fprintf(f,
+ "static const struct asn1_type_func asn1_extern_%s = {\n"
+ "\t(asn1_type_encode)encode_%s,\n"
+ "\t(asn1_type_decode)decode_%s,\n"
+ "\t(asn1_type_length)length_%s,\n"
+ "\t(asn1_type_copy)copy_%s,\n"
+ "\t(asn1_type_release)free_%s,\n"
+ "\t(asn1_type_print)print_%s,\n"
+ "\tsizeof(%s)\n"
+ "};\n",
+ name, name, name, name,
+ name, name, name, name);
+}
+
+void
+gen_template_import(const Symbol *s)
+{
+ FILE *f = get_code_file();
+
+ if (template_flag == 0)
+ return;
+
+ gen_extern_stubs(f, s->gen_name);
+}
+
+void
+generate_template_type_forward(const char *name)
+{
+ fprintf(get_code_file(), "extern const struct asn1_template asn1_%s[];\n", name);
+}
+
+void
+generate_template_objectset_forwards(const Symbol *s)
+{
+ if (!template_flag)
+ return;
+ fprintf(get_code_file(), "extern const struct asn1_template asn1_%s[];\n",
+ s->gen_name);
+}
+
+static void
+generate_template_type(const char *varname,
+ const char **dupname,
+ const char *symname,
+ const char *basetype,
+ const char *name,
+ Type *type,
+ int optional,
+ int isstruct,
+ int need_offset)
+{
+ struct tlist *tl;
+ const char *d;
+ char *szt = NULL;
+ int have_ellipsis = 0;
+ int implicit = 0;
+ int n;
+
+ tl = tlist_new(varname);
+
+ if (type->type == TTag && type->tag.tagenv == TE_IMPLICIT) {
+ Type *t = type->subtype ? type->subtype : type->symbol->type;
+
+ while (t->type == TType && (t->subtype || t->symbol->type))
+ t = t->subtype ? t->subtype : t->symbol->type;
+ if (t->type != TChoice)
+ implicit = (type->tag.tagenv == TE_IMPLICIT);
+ }
+
+ template_members(&tl->template, basetype, name, type, optional, 0,
+ implicit, isstruct, need_offset);
+
+ /* if its a sequence or set type, check if there is a ellipsis */
+ if (type->type == TSequence || type->type == TSet) {
+ Member *m;
+ HEIM_TAILQ_FOREACH(m, type->members, members) {
+ if (m->ellipsis)
+ have_ellipsis = 1;
+ }
+ }
+
+ if (isstruct)
+ if (name)
+ n = asprintf(&szt, "struct %s_%s", basetype, name);
+ else
+ n = asprintf(&szt, "struct %s", basetype);
+ else
+ n = asprintf(&szt, "%s", basetype);
+ if (n < 0 || szt == NULL)
+ errx(1, "malloc");
+
+ if (HEIM_TAILQ_EMPTY(&tl->template) && compact_tag(type)->type != TNull)
+ errx(1, "Tag %s...%s with no content ?", basetype, name ? name : "");
+
+ fprintf(get_code_file(), "/* generate_template_type: %s */\n", tl->name);
+
+ tlist_header(tl, "{ 0%s%s, sizeof(%s), ((void *)(uintptr_t)%lu) }",
+ (symname && preserve_type(symname)) ? "|A1_HF_PRESERVE" : "",
+ have_ellipsis ? "|A1_HF_ELLIPSIS" : "", szt, tlist_count(tl));
+
+ free(szt);
+
+ /* XXX Accidentally O(N^2)? */
+ d = tlist_find_dup(tl);
+ if (d) {
+#if 0
+ if (strcmp(d, tl->name) == 0)
+ errx(1, "found dup of ourself: %s", d);
+#endif
+ *dupname = d;
+ } else {
+ *dupname = tl->name;
+ tlist_print(tl);
+ tlist_add(tl);
+ }
+}
+
+
+void
+generate_template(const Symbol *s)
+{
+ FILE *f = get_code_file();
+ const char *dupname;
+ struct decoration deco;
+ ssize_t more_deco = -1;
+
+ if (use_extern(s)) {
+ gen_extern_stubs(f, s->gen_name);
+ return;
+ }
+
+ while (decorate_type(s->gen_name, &deco, &more_deco)) {
+ if (!deco.ext)
+ continue;
+ if (deco.void_star && deco.header_name)
+ fprintf(f, "#include %s\n", deco.header_name);
+ fprintf(f,
+ "static const struct asn1_type_func asn1_extern_%s_%s = {\n"
+ "\t(asn1_type_encode)0,\n"
+ "\t(asn1_type_decode)0,\n"
+ "\t(asn1_type_length)0,\n"
+ "\t(asn1_type_copy)%s,\n"
+ "\t(asn1_type_release)%s,\n"
+ "\t(asn1_type_print)0,\n"
+ "\tsizeof(%s)\n"
+ "};\n", s->gen_name, deco.field_name,
+ deco.copy_function_name && deco.copy_function_name[0] ?
+ deco.copy_function_name : "0",
+ deco.free_function_name && deco.free_function_name[0] ?
+ deco.free_function_name : "0",
+ deco.void_star ? "void *" : deco.field_type);
+ free(deco.field_type);
+ }
+
+ generate_template_type(s->gen_name, &dupname, s->name, s->gen_name, NULL, s->type, 0, 0, 1);
+
+ fprintf(f,
+ "\n"
+ "int ASN1CALL\n"
+ "decode_%s(const unsigned char *p, size_t len, %s *data, size_t *size)\n"
+ "{\n"
+ " memset(data, 0, sizeof(*data));\n"
+ " return _asn1_decode_top(asn1_%s, 0|%s, p, len, data, size);\n"
+ "}\n"
+ "\n",
+ s->gen_name,
+ s->gen_name,
+ dupname,
+ support_ber ? "A1_PF_ALLOW_BER" : "0");
+
+ fprintf(f,
+ "\n"
+ "int ASN1CALL\n"
+ "encode_%s(unsigned char *p, size_t len, const %s *data, size_t *size)\n"
+ "{\n"
+ " return _asn1_encode%s(asn1_%s, p, len, data, size);\n"
+ "}\n"
+ "\n",
+ s->gen_name,
+ s->gen_name,
+ fuzzer_string,
+ dupname);
+
+ fprintf(f,
+ "\n"
+ "size_t ASN1CALL\n"
+ "length_%s(const %s *data)\n"
+ "{\n"
+ " return _asn1_length%s(asn1_%s, data);\n"
+ "}\n"
+ "\n",
+ s->gen_name,
+ s->gen_name,
+ fuzzer_string,
+ dupname);
+
+
+ fprintf(f,
+ "\n"
+ "void ASN1CALL\n"
+ "free_%s(%s *data)\n"
+ "{\n"
+ " _asn1_free_top(asn1_%s, data);\n"
+ "}\n"
+ "\n",
+ s->gen_name,
+ s->gen_name,
+ dupname);
+
+ fprintf(f,
+ "\n"
+ "int ASN1CALL\n"
+ "copy_%s(const %s *from, %s *to)\n"
+ "{\n"
+ " return _asn1_copy_top(asn1_%s, from, to);\n"
+ "}\n"
+ "\n",
+ s->gen_name,
+ s->gen_name,
+ s->gen_name,
+ dupname);
+
+ fprintf(f,
+ "\n"
+ "char * ASN1CALL\n"
+ "print_%s(const %s *data, int flags)\n"
+ "{\n"
+ " return _asn1_print_top(asn1_%s, flags, data);\n"
+ "}\n"
+ "\n",
+ s->gen_name,
+ s->gen_name,
+ dupname);
+}
diff --git a/third_party/heimdal/lib/asn1/hash.c b/third_party/heimdal/lib/asn1/hash.c
new file mode 100644
index 0000000..73b6cf9
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/hash.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Hash table functions
+ */
+
+#include "gen_locl.h"
+
+RCSID("$Id$");
+
+static Hashentry *_search(Hashtab * htab, /* The hash table */
+ void *ptr); /* And key */
+
+Hashtab *
+hashtabnew(int sz,
+ int (*cmp) (void *, void *),
+ unsigned (*hash) (void *))
+{
+ Hashtab *htab;
+ int i;
+
+ assert(sz > 0);
+
+ htab = (Hashtab *) malloc(sizeof(Hashtab) + (sz - 1) * sizeof(Hashentry *));
+ if (htab == NULL)
+ return NULL;
+
+ for (i = 0; i < sz; ++i)
+ htab->tab[i] = NULL;
+
+ htab->cmp = cmp;
+ htab->hash = hash;
+ htab->sz = sz;
+ return htab;
+}
+
+/* Intern search function */
+
+static Hashentry *
+_search(Hashtab * htab, void *ptr)
+{
+ Hashentry *hptr;
+
+ assert(htab && ptr);
+
+ for (hptr = htab->tab[(*htab->hash) (ptr) % htab->sz];
+ hptr;
+ hptr = hptr->next)
+ if ((*htab->cmp) (ptr, hptr->ptr) == 0)
+ break;
+ return hptr;
+}
+
+/* Search for element in hash table */
+
+void *
+hashtabsearch(Hashtab * htab, void *ptr)
+{
+ Hashentry *tmp;
+
+ tmp = _search(htab, ptr);
+ return tmp ? tmp->ptr : tmp;
+}
+
+/* add element to hash table */
+/* if already there, set new value */
+/* !NULL if succesful */
+
+void *
+hashtabadd(Hashtab * htab, void *ptr)
+{
+ Hashentry *h = _search(htab, ptr);
+ Hashentry **tabptr;
+
+ assert(htab && ptr);
+
+ if (h)
+ free((void *) h->ptr);
+ else {
+ h = (Hashentry *) malloc(sizeof(Hashentry));
+ if (h == NULL) {
+ return NULL;
+ }
+ tabptr = &htab->tab[(*htab->hash) (ptr) % htab->sz];
+ h->next = *tabptr;
+ *tabptr = h;
+ h->prev = tabptr;
+ if (h->next)
+ h->next->prev = &h->next;
+ }
+ h->ptr = ptr;
+ return h;
+}
+
+/* delete element with key key. Iff freep, free Hashentry->ptr */
+
+int
+_hashtabdel(Hashtab * htab, void *ptr, int freep)
+{
+ Hashentry *h;
+
+ assert(htab && ptr);
+
+ h = _search(htab, ptr);
+ if (h) {
+ if (freep)
+ free(h->ptr);
+ if ((*(h->prev) = h->next))
+ h->next->prev = h->prev;
+ free(h);
+ return 0;
+ } else
+ return -1;
+}
+
+/* Do something for each element */
+
+void
+hashtabforeach(Hashtab * htab, int (*func) (void *ptr, void *arg),
+ void *arg)
+{
+ Hashentry **h, *g;
+
+ assert(htab);
+
+ for (h = htab->tab; h < &htab->tab[htab->sz]; ++h)
+ for (g = *h; g; g = g->next)
+ if ((*func) (g->ptr, arg))
+ return;
+}
+
+/* standard hash-functions for strings */
+
+unsigned
+hashadd(const char *s)
+{ /* Standard hash function */
+ unsigned i;
+
+ assert(s);
+
+ for (i = 0; *s; ++s)
+ i += *s;
+ return i;
+}
+
+unsigned
+hashcaseadd(const char *s)
+{ /* Standard hash function */
+ unsigned i;
+
+ assert(s);
+
+ for (i = 0; *s; ++s)
+ i += toupper((unsigned char)*s);
+ return i;
+}
+
+#define TWELVE (sizeof(unsigned))
+#define SEVENTYFIVE (6*sizeof(unsigned))
+#define HIGH_BITS (~((unsigned)(~0) >> TWELVE))
+
+unsigned
+hashjpw(const char *ss)
+{ /* another hash function */
+ unsigned h = 0;
+ unsigned g;
+ const unsigned char *s = (const unsigned char *)ss;
+
+ for (; *s; ++s) {
+ h = (h << TWELVE) + *s;
+ if ((g = h & HIGH_BITS))
+ h = (h ^ (g >> SEVENTYFIVE)) & ~HIGH_BITS;
+ }
+ return h;
+}
diff --git a/third_party/heimdal/lib/asn1/hash.h b/third_party/heimdal/lib/asn1/hash.h
new file mode 100644
index 0000000..f37bdbb
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/hash.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * hash.h. Header file for hash table functions
+ */
+
+/* $Id$ */
+
+struct hashentry { /* Entry in bucket */
+ struct hashentry **prev;
+ struct hashentry *next;
+ void *ptr;
+};
+
+typedef struct hashentry Hashentry;
+
+struct hashtab { /* Hash table */
+ int (*cmp)(void *, void *); /* Compare function */
+ unsigned (*hash)(void *); /* hash function */
+ int sz; /* Size */
+ Hashentry *tab[1]; /* The table */
+};
+
+typedef struct hashtab Hashtab;
+
+/* prototypes */
+
+Hashtab *hashtabnew(int sz,
+ int (*cmp)(void *, void *),
+ unsigned (*hash)(void *)); /* Make new hash table */
+
+void *hashtabsearch(Hashtab *htab, /* The hash table */
+ void *ptr); /* The key */
+
+
+void *hashtabadd(Hashtab *htab, /* The hash table */
+ void *ptr); /* The element */
+
+int _hashtabdel(Hashtab *htab, /* The table */
+ void *ptr, /* Key */
+ int freep); /* Free data part? */
+
+void hashtabforeach(Hashtab *htab,
+ int (*func)(void *ptr, void *arg),
+ void *arg);
+
+unsigned hashadd(const char *s); /* Standard hash function */
+unsigned hashcaseadd(const char *s); /* Standard hash function */
+unsigned hashjpw(const char *s); /* another hash function */
+
+/* macros */
+
+ /* Don't free space */
+#define hashtabdel(htab,key) _hashtabdel(htab,key,FALSE)
+
+#define hashtabfree(htab,key) _hashtabdel(htab,key,TRUE) /* Do! */
diff --git a/third_party/heimdal/lib/asn1/heim_asn1.h b/third_party/heimdal/lib/asn1/heim_asn1.h
new file mode 100644
index 0000000..072ff15
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/heim_asn1.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2003-2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __HEIM_ANY_H__
+#define __HEIM_ANY_H__ 1
+
+int ASN1CALL encode_heim_any(unsigned char *, size_t, const heim_any *, size_t *);
+int ASN1CALL decode_heim_any(const unsigned char *, size_t, heim_any *, size_t *);
+void ASN1CALL free_heim_any(heim_any *);
+char *ASN1CALL print_heim_any(const heim_any *, int);
+size_t ASN1CALL length_heim_any(const heim_any *);
+int ASN1CALL copy_heim_any(const heim_any *, heim_any *);
+
+int ASN1CALL encode_heim_any_set(unsigned char *, size_t,
+ const heim_any_set *, size_t *);
+int ASN1CALL decode_heim_any_set(const unsigned char *, size_t,
+ heim_any_set *,size_t *);
+void ASN1CALL free_heim_any_set(heim_any_set *);
+char *ASN1CALL print_heim_any_set(const heim_any_set *, int);
+size_t ASN1CALL length_heim_any_set(const heim_any_set *);
+int ASN1CALL copy_heim_any_set(const heim_any_set *, heim_any_set *);
+int ASN1CALL heim_any_cmp(const heim_any_set *, const heim_any_set *);
+
+int ASN1CALL encode_HEIM_ANY(unsigned char *, size_t, const heim_any *, size_t *);
+int ASN1CALL decode_HEIM_ANY(const unsigned char *, size_t, heim_any *, size_t *);
+void ASN1CALL free_HEIM_ANY(heim_any *);
+char *ASN1CALL print_HEIM_ANY(const heim_any *, int);
+size_t ASN1CALL length_HEIM_ANY(const heim_any *);
+int ASN1CALL copy_HEIM_ANY(const heim_any *, heim_any *);
+
+int ASN1CALL encode_HEIM_ANY_SET(unsigned char *, size_t,
+ const heim_any_set *, size_t *);
+int ASN1CALL decode_HEIM_ANY_SET(const unsigned char *, size_t,
+ heim_any_set *,size_t *);
+void ASN1CALL free_HEIM_ANY_SET(heim_any_set *);
+char *ASN1CALL print_HEIM_ANY_SET(const heim_any_set *, int);
+size_t ASN1CALL length_HEIM_ANY_SET(const heim_any_set *);
+int ASN1CALL copy_HEIM_ANY_SET(const heim_any_set *, heim_any_set *);
+int ASN1CALL heim_any_cmp(const heim_any_set *, const heim_any_set *);
+
+#endif /* __HEIM_ANY_H__ */
diff --git a/third_party/heimdal/lib/asn1/krb5.asn1 b/third_party/heimdal/lib/asn1/krb5.asn1
new file mode 100644
index 0000000..bf279a4
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/krb5.asn1
@@ -0,0 +1,1066 @@
+-- $Id$
+
+KERBEROS5 DEFINITIONS ::=
+BEGIN
+EXPORTS
+ AD-AND-OR,
+ AD-IF-RELEVANT,
+ AD-KDCIssued,
+ AD-LoginAlias,
+ AP-REP,
+ AP-REQ,
+ AS-REP,
+ AS-REQ,
+ AUTHDATA-TYPE,
+ Authenticator,
+ AuthorizationData,
+ AuthorizationDataElement,
+ CKSUMTYPE,
+ ChangePasswdDataMS,
+ Checksum,
+ CompositePrincipal,
+ ENCTYPE,
+ ETYPE-INFO,
+ ETYPE-INFO-ENTRY,
+ ETYPE-INFO2,
+ ETYPE-INFO2-ENTRY,
+ EncAPRepPart,
+ EncASRepPart,
+ EncKDCRepPart,
+ EncKrbCredPart,
+ EncKrbPrivPart,
+ EncTGSRepPart,
+ EncTicketPart,
+ EncryptedData,
+ EncryptionKey,
+ EtypeList,
+ HostAddress,
+ HostAddresses,
+ KDC-REQ-BODY,
+ KDCOptions,
+ KDC-REP,
+ KRB-CRED,
+ KRB-ERROR,
+ KRB-PRIV,
+ KRB-SAFE,
+ KRB-SAFE-BODY,
+ KerberosString,
+ KerberosTime,
+ KrbCredInfo,
+ LR-TYPE,
+ LastReq,
+ METHOD-DATA,
+ NAME-TYPE,
+ PA-ClientCanonicalized,
+ PA-ClientCanonicalizedNames,
+ PA-DATA,
+ PA-ENC-TS-ENC,
+ PA-KERB-KEY-LIST-REP,
+ PA-KERB-KEY-LIST-REQ,
+ PA-PAC-OPTIONS,
+ PA-PAC-REQUEST,
+ PA-S4U2Self,
+ PA-S4U-X509-USER,
+ PA-SERVER-REFERRAL-DATA,
+ PA-ServerReferralData,
+ PA-SvrReferralData,
+ PADATA-TYPE,
+ PA-FX-FAST-REQUEST,
+ PA-FX-FAST-REPLY,
+ Principal,
+ PrincipalName,
+ Principals,
+ Realm,
+ TGS-REP,
+ TGS-REQ,
+ Ticket,
+ TicketFlags,
+ TransitedEncoding,
+ TypedData,
+ KrbFastResponse,
+ KrbFastFinished,
+ KrbFastReq,
+ KrbFastArmor,
+ KrbFastArmoredReq,
+ KDCFastState,
+ KDCFastCookie,
+ KDC-PROXY-MESSAGE,
+ KERB-AD-RESTRICTION-ENTRY,
+ KERB-TIMES,
+ KERB-CRED,
+ KERB-TGS-REQ-IN,
+ KERB-TGS-REQ-OUT,
+ KERB-ARMOR-SERVICE-REPLY,
+ KERB-ERROR-DATA
+ ;
+
+NAME-TYPE ::= INTEGER {
+ KRB5_NT_UNKNOWN(0), -- Name type not known
+ KRB5_NT_PRINCIPAL(1), -- Just the name of the principal as in
+ KRB5_NT_SRV_INST(2), -- Service and other unique instance (krbtgt)
+ KRB5_NT_SRV_HST(3), -- Service with host name as instance
+ KRB5_NT_SRV_XHST(4), -- Service with host as remaining components
+ KRB5_NT_UID(5), -- Unique ID
+ KRB5_NT_X500_PRINCIPAL(6), -- PKINIT
+ KRB5_NT_SMTP_NAME(7), -- Name in form of SMTP email name
+ KRB5_NT_ENTERPRISE_PRINCIPAL(10), -- Windows 2000 UPN
+ KRB5_NT_WELLKNOWN(11), -- Wellknown
+ KRB5_NT_SRV_HST_DOMAIN(12), -- Domain based service with host name as instance (RFC5179)
+ KRB5_NT_ENT_PRINCIPAL_AND_ID(-130), -- Windows 2000 UPN and SID
+ KRB5_NT_MS_PRINCIPAL(-128), -- NT 4 style name
+ KRB5_NT_MS_PRINCIPAL_AND_ID(-129), -- NT style name and SID
+ KRB5_NT_NTLM(-1200), -- NTLM name, realm is domain
+ KRB5_NT_X509_GENERAL_NAME(-1201), -- x509 general name (base64 encoded)
+ KRB5_NT_GSS_HOSTBASED_SERVICE(-1202), -- not used; remove
+ KRB5_NT_CACHE_UUID(-1203), -- name is actually a uuid pointing to ccache, use client name in cache
+ KRB5_NT_SRV_HST_NEEDS_CANON (-195894762) -- Internal: indicates that name canonicalization is needed
+}
+
+-- message types
+
+MESSAGE-TYPE ::= INTEGER {
+ krb-as-req(10), -- Request for initial authentication
+ krb-as-rep(11), -- Response to KRB_AS_REQ request
+ krb-tgs-req(12), -- Request for authentication based on TGT
+ krb-tgs-rep(13), -- Response to KRB_TGS_REQ request
+ krb-ap-req(14), -- application request to server
+ krb-ap-rep(15), -- Response to KRB_AP_REQ_MUTUAL
+ krb-safe(20), -- Safe (checksummed) application message
+ krb-priv(21), -- Private (encrypted) application message
+ krb-cred(22), -- Private (encrypted) message to forward credentials
+ krb-error(30) -- Error response
+}
+
+
+-- pa-data types
+
+PADATA-TYPE ::= INTEGER {
+ KRB5-PADATA-NONE(0),
+ KRB5-PADATA-TGS-REQ(1),
+ KRB5-PADATA-AP-REQ(1),
+ KRB5-PADATA-ENC-TIMESTAMP(2),
+ KRB5-PADATA-PW-SALT(3),
+ KRB5-PADATA-ENC-UNIX-TIME(5),
+ KRB5-PADATA-SANDIA-SECUREID(6),
+ KRB5-PADATA-SESAME(7),
+ KRB5-PADATA-OSF-DCE(8),
+ KRB5-PADATA-CYBERSAFE-SECUREID(9),
+ KRB5-PADATA-AFS3-SALT(10),
+ KRB5-PADATA-ETYPE-INFO(11),
+ KRB5-PADATA-SAM-CHALLENGE(12), -- (sam/otp)
+ KRB5-PADATA-SAM-RESPONSE(13), -- (sam/otp)
+ KRB5-PADATA-PK-AS-REQ-19(14), -- (PKINIT-19)
+ KRB5-PADATA-PK-AS-REP-19(15), -- (PKINIT-19)
+ KRB5-PADATA-PK-AS-REQ-WIN(15), -- (PKINIT - old number)
+ KRB5-PADATA-PK-AS-REQ(16), -- (PKINIT-25)
+ KRB5-PADATA-PK-AS-REP(17), -- (PKINIT-25)
+ KRB5-PADATA-PA-PK-OCSP-RESPONSE(18),
+ KRB5-PADATA-ETYPE-INFO2(19),
+ KRB5-PADATA-USE-SPECIFIED-KVNO(20),
+ KRB5-PADATA-SVR-REFERRAL-INFO(20), --- old ms referral number
+ KRB5-PADATA-SAM-REDIRECT(21), -- (sam/otp)
+ KRB5-PADATA-GET-FROM-TYPED-DATA(22),
+ KRB5-PADATA-SAM-ETYPE-INFO(23),
+ KRB5-PADATA-SERVER-REFERRAL(25),
+ KRB5-PADATA-ALT-PRINC(24), -- (crawdad@fnal.gov)
+ KRB5-PADATA-SAM-CHALLENGE2(30), -- (kenh@pobox.com)
+ KRB5-PADATA-SAM-RESPONSE2(31), -- (kenh@pobox.com)
+ KRB5-PA-EXTRA-TGT(41), -- Reserved extra TGT
+ KRB5-PADATA-FX-FAST-ARMOR(71), -- fast armor
+ KRB5-PADATA-TD-KRB-PRINCIPAL(102), -- PrincipalName
+ KRB5-PADATA-PK-TD-TRUSTED-CERTIFIERS(104), -- PKINIT
+ KRB5-PADATA-PK-TD-CERTIFICATE-INDEX(105), -- PKINIT
+ KRB5-PADATA-TD-APP-DEFINED-ERROR(106), -- application specific
+ KRB5-PADATA-TD-REQ-NONCE(107), -- INTEGER
+ KRB5-PADATA-TD-REQ-SEQ(108), -- INTEGER
+ KRB5-PADATA-PA-PAC-REQUEST(128), -- jbrezak@exchange.microsoft.com
+ KRB5-PADATA-FOR-USER(129), -- MS-KILE
+ KRB5-PADATA-FOR-X509-USER(130), -- MS-KILE
+ KRB5-PADATA-FOR-CHECK-DUPS(131), -- MS-KILE
+ KRB5-PADATA-AS-CHECKSUM(132), -- MS-KILE
+ KRB5-PADATA-PK-AS-09-BINDING(132), -- client send this to
+ -- tell KDC that is supports
+ -- the asCheckSum in the
+ -- PK-AS-REP
+ KRB5-PADATA-FX-COOKIE(133), -- krb-wg-preauth-framework
+ KRB5-PADATA-AUTHENTICATION-SET(134), -- krb-wg-preauth-framework
+ KRB5-PADATA-AUTH-SET-SELECTED(135), -- krb-wg-preauth-framework
+ KRB5-PADATA-FX-FAST(136), -- krb-wg-preauth-framework
+ KRB5-PADATA-FX-ERROR(137), -- krb-wg-preauth-framework
+ KRB5-PADATA-ENCRYPTED-CHALLENGE(138), -- krb-wg-preauth-framework
+ KRB5-PADATA-OTP-CHALLENGE(141), -- (gareth.richards@rsa.com)
+ KRB5-PADATA-OTP-REQUEST(142), -- (gareth.richards@rsa.com)
+ KBB5-PADATA-OTP-CONFIRM(143), -- (gareth.richards@rsa.com)
+ KRB5-PADATA-OTP-PIN-CHANGE(144), -- (gareth.richards@rsa.com)
+ KRB5-PADATA-EPAK-AS-REQ(145),
+ KRB5-PADATA-EPAK-AS-REP(146),
+ KRB5-PADATA-PKINIT-KX(147), -- krb-wg-anon
+ KRB5-PADATA-PKU2U-NAME(148), -- zhu-pku2u
+ KRB5-PADATA-REQ-ENC-PA-REP(149), --
+ KRB5-PADATA-AS-FRESHNESS(150), -- RFC 8070
+ KER5-PADATA-KERB-KEY-LIST-REQ(161), -- MS-KILE
+ KER5-PADATA-KERB-PAKEY-LIST-REP(162), -- MS-KILE
+ KRB5-PADATA-SUPPORTED-ETYPES(165), -- MS-KILE
+ KRB5-PADATA-PAC-OPTIONS(167), -- MS-KILE
+ KRB5-PADATA-GSS(655) -- krb-wg-gss-preauth
+
+}
+
+AUTHDATA-TYPE ::= INTEGER {
+ KRB5-AUTHDATA-IF-RELEVANT(1),
+ KRB5-AUTHDATA-INTENDED-FOR_SERVER(2),
+ KRB5-AUTHDATA-INTENDED-FOR-APPLICATION-CLASS(3),
+ KRB5-AUTHDATA-KDC-ISSUED(4),
+ KRB5-AUTHDATA-AND-OR(5),
+ KRB5-AUTHDATA-MANDATORY-TICKET-EXTENSIONS(6),
+ KRB5-AUTHDATA-IN-TICKET-EXTENSIONS(7),
+ KRB5-AUTHDATA-MANDATORY-FOR-KDC(8),
+ KRB5-AUTHDATA-INITIAL-VERIFIED-CAS(9),
+ KRB5-AUTHDATA-OSF-DCE(64),
+ KRB5-AUTHDATA-SESAME(65),
+ KRB5-AUTHDATA-OSF-DCE-PKI-CERTID(66),
+ KRB5-AUTHDATA-AUTHENTICATION-STRENGTH(70),
+ KRB5-AUTHDATA-FX-FAST-ARMOR(71),
+ KRB5-AUTHDATA-FX-FAST-USED(72),
+ KRB5-AUTHDATA-WIN2K-PAC(128),
+ KRB5-AUTHDATA-GSS-API-ETYPE-NEGOTIATION(129), -- Authenticator only
+ KRB5-AUTHDATA-SIGNTICKET-OLDER(-17),
+ KRB5-AUTHDATA-SIGNTICKET-OLD(142),
+ KRB5-AUTHDATA-SIGNTICKET(512),
+ KRB5-AUTHDATA-SYNTHETIC-PRINC-USED(513), -- principal was synthetised
+ KRB5-AUTHDATA-KERB-LOCAL(141), -- MS-KILE
+ KRB5-AUTHDATA-TOKEN-RESTRICTIONS(142), -- MS-KILE
+ KRB5-AUTHDATA-AP-OPTIONS(143), -- MS-KILE
+ KRB5-AUTHDATA-TARGET-PRINCIPAL(144), -- MS-KILE
+ -- N.B. these assignments have not been confirmed yet.
+ --
+ -- DO NOT USE in production yet!
+ KRB5-AUTHDATA-ON-BEHALF-OF(580), -- UTF8String princ name
+ KRB5-AUTHDATA-BEARER-TOKEN-JWT(581), -- JWT token
+ KRB5-AUTHDATA-BEARER-TOKEN-SAML(582), -- SAML token
+ KRB5-AUTHDATA-BEARER-TOKEN-OIDC(583), -- OIDC token
+ KRB5-AUTHDATA-CSR-AUTHORIZED(584), -- Proxy has authorized client
+ -- to requested exts in CSR
+ KRB5-AUTHDATA-GSS-COMPOSITE-NAME(655) -- gss_export_name_composite
+}
+
+-- checksumtypes
+
+CKSUMTYPE ::= INTEGER {
+ CKSUMTYPE_NONE(0),
+ CKSUMTYPE_CRC32(1),
+ CKSUMTYPE_RSA_MD4(2),
+ CKSUMTYPE_RSA_MD4_DES(3),
+ CKSUMTYPE_DES_MAC(4),
+ CKSUMTYPE_DES_MAC_K(5),
+ CKSUMTYPE_RSA_MD4_DES_K(6),
+ CKSUMTYPE_RSA_MD5(7),
+ CKSUMTYPE_RSA_MD5_DES(8),
+ CKSUMTYPE_RSA_MD5_DES3(9),
+ CKSUMTYPE_SHA1_OTHER(10),
+ CKSUMTYPE_HMAC_SHA1_DES3(12),
+ CKSUMTYPE_SHA1(14),
+ CKSUMTYPE_HMAC_SHA1_96_AES_128(15),
+ CKSUMTYPE_HMAC_SHA1_96_AES_256(16),
+ CKSUMTYPE_HMAC_SHA256_128_AES128(19),
+ CKSUMTYPE_HMAC_SHA384_192_AES256(20),
+ CKSUMTYPE_GSSAPI(0x8003),
+ CKSUMTYPE_HMAC_MD5(-138), -- unofficial microsoft number
+ CKSUMTYPE_HMAC_MD5_ENC(-1138), -- even more unofficial
+ CKSUMTYPE_SHA256(-21),
+ CKSUMTYPE_SHA384(-22),
+ CKSUMTYPE_SHA512(-23)
+}
+
+--enctypes
+ENCTYPE ::= INTEGER {
+ KRB5_ENCTYPE_NULL(0),
+ KRB5_ENCTYPE_DES_CBC_CRC(1),
+ KRB5_ENCTYPE_DES_CBC_MD4(2),
+ KRB5_ENCTYPE_DES_CBC_MD5(3),
+ KRB5_ENCTYPE_DES3_CBC_MD5(5),
+ KRB5_ENCTYPE_OLD_DES3_CBC_SHA1(7),
+ KRB5_ENCTYPE_SIGN_DSA_GENERATE(8),
+ KRB5_ENCTYPE_ENCRYPT_RSA_PRIV(9),
+ KRB5_ENCTYPE_ENCRYPT_RSA_PUB(10),
+ KRB5_ENCTYPE_DES3_CBC_SHA1(16), -- with key derivation
+ KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96(17),
+ KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96(18),
+ KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128(19),
+ KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192(20),
+ KRB5_ENCTYPE_ARCFOUR_HMAC_MD5(23),
+ KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56(24),
+ KRB5_ENCTYPE_ENCTYPE_PK_CROSS(48),
+-- some "old" windows types
+ KRB5_ENCTYPE_ARCFOUR_MD4(-128),
+ KRB5_ENCTYPE_ARCFOUR_HMAC_OLD(-133),
+ KRB5_ENCTYPE_ARCFOUR_HMAC_OLD_EXP(-135),
+-- these are for Heimdal internal use
+ KRB5_ENCTYPE_DES_CBC_NONE(-0x1000),
+ KRB5_ENCTYPE_DES3_CBC_NONE(-0x1001),
+ KRB5_ENCTYPE_DES_CFB64_NONE(-0x1002),
+ KRB5_ENCTYPE_DES_PCBC_NONE(-0x1003),
+ KRB5_ENCTYPE_DIGEST_MD5_NONE(-0x1004), -- private use, lukeh@padl.com
+ KRB5_ENCTYPE_CRAM_MD5_NONE(-0x1005) -- private use, lukeh@padl.com
+}
+
+
+
+
+-- this is sugar to make something ASN1 does not have: unsigned
+
+Krb5UInt32 ::= INTEGER (0..4294967295)
+Krb5Int32 ::= INTEGER (-2147483648..2147483647)
+
+KerberosString ::= GeneralString
+
+Realm ::= GeneralString
+PrincipalName ::= SEQUENCE {
+ name-type[0] NAME-TYPE,
+ name-string[1] SEQUENCE OF GeneralString
+}
+
+HostAddress ::= SEQUENCE {
+ addr-type[0] Krb5Int32,
+ address[1] OCTET STRING
+}
+
+-- This is from RFC1510.
+--
+-- HostAddresses ::= SEQUENCE OF SEQUENCE {
+-- addr-type[0] Krb5Int32,
+-- address[1] OCTET STRING
+-- }
+
+-- This seems much better.
+HostAddresses ::= SEQUENCE OF HostAddress
+
+
+KerberosTime ::= GeneralizedTime -- Specifying UTC time zone (Z)
+
+AuthorizationDataElement ::= SEQUENCE {
+ ad-type[0] Krb5Int32,
+ ad-data[1] OCTET STRING
+}
+
+AuthorizationData ::= SEQUENCE OF AuthorizationDataElement
+
+APOptions ::= BIT STRING {
+ reserved(0),
+ use-session-key(1),
+ mutual-required(2)
+}
+
+TicketFlags ::= BIT STRING {
+ reserved(0),
+ forwardable(1),
+ forwarded(2),
+ proxiable(3),
+ proxy(4),
+ may-postdate(5),
+ postdated(6),
+ invalid(7),
+ renewable(8),
+ initial(9),
+ pre-authent(10),
+ hw-authent(11),
+ transited-policy-checked(12),
+ ok-as-delegate(13),
+ enc-pa-rep(15),
+ anonymous(16)
+}
+
+KDCOptions ::= BIT STRING {
+ reserved(0),
+ forwardable(1),
+ forwarded(2),
+ proxiable(3),
+ proxy(4),
+ allow-postdate(5),
+ postdated(6),
+ renewable(8),
+ cname-in-addl-tkt(14), -- ms extension
+ canonicalize(15),
+ request-anonymous(16),
+ disable-transited-check(26),
+ renewable-ok(27),
+ enc-tkt-in-skey(28),
+ renew(30),
+ validate(31)
+}
+
+LR-TYPE ::= INTEGER {
+ LR_NONE(0), -- no information
+ LR_INITIAL_TGT(1), -- last initial TGT request
+ LR_INITIAL(2), -- last initial request
+ LR_ISSUE_USE_TGT(3), -- time of newest TGT used
+ LR_RENEWAL(4), -- time of last renewal
+ LR_REQUEST(5), -- time of last request (of any type)
+ LR_PW_EXPTIME(6), -- expiration time of password
+ LR_ACCT_EXPTIME(7) -- expiration time of account
+}
+
+LastReq ::= SEQUENCE OF SEQUENCE {
+ lr-type[0] LR-TYPE,
+ lr-value[1] KerberosTime
+}
+
+
+EncryptedData ::= SEQUENCE {
+ etype[0] ENCTYPE, -- EncryptionType
+ kvno[1] Krb5Int32 OPTIONAL,
+ cipher[2] OCTET STRING -- ciphertext
+}
+
+EncryptionKey ::= SEQUENCE {
+ keytype[0] Krb5Int32,
+ keyvalue[1] OCTET STRING
+}
+
+-- encoded Transited field
+TransitedEncoding ::= SEQUENCE {
+ tr-type[0] Krb5Int32, -- must be registered
+ contents[1] OCTET STRING
+}
+
+Ticket ::= [APPLICATION 1] SEQUENCE {
+ tkt-vno[0] Krb5Int32,
+ realm[1] Realm,
+ sname[2] PrincipalName,
+ enc-part[3] EncryptedData
+}
+-- Encrypted part of ticket
+EncTicketPart ::= [APPLICATION 3] SEQUENCE {
+ flags[0] TicketFlags,
+ key[1] EncryptionKey,
+ crealm[2] Realm,
+ cname[3] PrincipalName,
+ transited[4] TransitedEncoding,
+ authtime[5] KerberosTime,
+ starttime[6] KerberosTime OPTIONAL,
+ endtime[7] KerberosTime,
+ renew-till[8] KerberosTime OPTIONAL,
+ caddr[9] HostAddresses OPTIONAL,
+ authorization-data[10] AuthorizationData OPTIONAL
+}
+
+Checksum ::= SEQUENCE {
+ cksumtype[0] CKSUMTYPE,
+ checksum[1] OCTET STRING
+}
+
+-- For GSS name attributes [RFC6680] we'll decorate Principal (which is not an
+-- RFC4120 type, but which we use a) in HDB, b) in the API as that which
+-- krb5_principal points to) with PrincipalNameAttrs.
+--
+-- Attributes have three possible sources in Heimdal Kerberos at this time:
+--
+-- - the EncKDCRepPart (for the client's attributes on the client side)
+-- - the EncTicketPart (for the client's attributes on the server side)
+-- - the Authenticator's AuthorizationData (if any; server-side)
+--
+-- In principle there can be more:
+--
+-- - locally-set (asserted) attributes
+-- - locally-looked-up attributes (e.g., in LDAP)
+-- - locally-transformed attributes (e.g., local groups, filtered SIDs from a
+-- PAC, etc.)
+--
+-- We could also cache "cooked" attributes as reported by the RFC6680 API given
+-- the sources we have.
+--
+-- For now we'll only support authenticated attributes where those come from
+-- the KDC, and attributes asserted in Authenticator authz-data.
+PrincipalNameAttrSrc ::= CHOICE {
+ enc-kdc-rep-part [0] EncKDCRepPart, -- minus session key
+ enc-ticket-part [1] EncTicketPart -- minus session key
+}
+PrincipalNameAttrs ::= SEQUENCE {
+ -- True if this name was authenticated via an AP-REQ or a KDC-REP
+ authenticated [0] BOOLEAN,
+ -- These are compiled from the Ticket, KDC-REP, and/or Authenticator
+ source [1] PrincipalNameAttrSrc OPTIONAL,
+ authenticator-ad [2] AuthorizationData OPTIONAL,
+ -- For the server on the client side we should keep track of the
+ -- transit path taken to reach it (if absent -> unknown).
+ --
+ -- We don't learn much more about the server from the KDC.
+ peer-realm [3] Realm OPTIONAL,
+ transited [4] TransitedEncoding OPTIONAL,
+ -- True if the PAC was verified
+ pac-verified [5] BOOLEAN,
+ -- True if any AD-KDC-ISSUEDs in the Ticket were validated
+ kdc-issued-verified [6] BOOLEAN,
+ -- TODO: Add requested attributes, for gss_set_name_attribute(), which
+ -- should cause corresponding authz-data elements to be added to
+ -- any TGS-REQ or to the AP-REQ's Authenticator as appropriate.
+ want-ad [7] AuthorizationData OPTIONAL
+}
+-- This is our type for exported composite name tokens for GSS [RFC6680].
+-- It's the same as Principal (below) as decorated with (see krb5.opt file and
+-- asn1_compile usage), except it's not decorated, so the name attributes are
+-- encoded/decoded.
+CompositePrincipal ::= [APPLICATION 48] SEQUENCE {
+ name[0] PrincipalName,
+ realm[1] Realm,
+ nameattrs[2] PrincipalNameAttrs OPTIONAL
+}
+
+-- This is not part of RFC1510/RFC4120. We use this internally as our
+-- krb5_principal (which is a typedef of *Principal), and in HDB entries.
+Principal ::= SEQUENCE {
+ name[0] PrincipalName,
+ realm[1] Realm
+ -- This will be decorated with an optional nameattrs field of
+ -- PrincipalNameAttrs type that doesn't get encoded. Same as
+ -- CompositePrincipal above, except that CompositePrincipal's
+ -- nameattrs field does get encoded, while Principal's does not:
+ --
+ -- nameattrs[2] PrincipalNameAttrs OPTIONAL
+}
+
+Principals ::= SEQUENCE OF Principal
+
+Authenticator ::= [APPLICATION 2] SEQUENCE {
+ authenticator-vno[0] Krb5Int32,
+ crealm[1] Realm,
+ cname[2] PrincipalName,
+ cksum[3] Checksum OPTIONAL,
+ cusec[4] Krb5Int32,
+ ctime[5] KerberosTime,
+ subkey[6] EncryptionKey OPTIONAL,
+ seq-number[7] Krb5UInt32 OPTIONAL,
+ authorization-data[8] AuthorizationData OPTIONAL
+}
+
+PA-DATA ::= SEQUENCE {
+ -- might be encoded AP-REQ
+ padata-type[1] PADATA-TYPE,
+ padata-value[2] OCTET STRING
+}
+
+ETYPE-INFO-ENTRY ::= SEQUENCE {
+ etype[0] ENCTYPE,
+ salt[1] OCTET STRING OPTIONAL,
+ salttype[2] Krb5Int32 OPTIONAL
+}
+
+ETYPE-INFO ::= SEQUENCE OF ETYPE-INFO-ENTRY
+
+ETYPE-INFO2-ENTRY ::= SEQUENCE {
+ etype[0] ENCTYPE,
+ salt[1] KerberosString OPTIONAL,
+ s2kparams[2] OCTET STRING OPTIONAL
+}
+
+ETYPE-INFO2 ::= SEQUENCE SIZE (1..MAX) OF ETYPE-INFO2-ENTRY
+
+METHOD-DATA ::= SEQUENCE OF PA-DATA
+
+TypedData ::= SEQUENCE {
+ data-type[0] Krb5Int32,
+ data-value[1] OCTET STRING OPTIONAL
+}
+
+TYPED-DATA ::= SEQUENCE SIZE (1..MAX) OF TypedData
+
+KDC-REQ-BODY ::= SEQUENCE {
+ kdc-options[0] KDCOptions,
+ cname[1] PrincipalName OPTIONAL, -- Used only in AS-REQ
+ realm[2] Realm, -- Server's realm
+ -- Also client's in AS-REQ
+ sname[3] PrincipalName OPTIONAL,
+ from[4] KerberosTime OPTIONAL,
+ till[5] KerberosTime OPTIONAL,
+ rtime[6] KerberosTime OPTIONAL,
+ nonce[7] Krb5Int32,
+ etype[8] SEQUENCE OF ENCTYPE, -- EncryptionType,
+ -- in preference order
+ addresses[9] HostAddresses OPTIONAL,
+ enc-authorization-data[10] EncryptedData OPTIONAL,
+ -- Encrypted AuthorizationData encoding
+ additional-tickets[11] SEQUENCE OF Ticket OPTIONAL
+}
+
+KDC-REQ ::= SEQUENCE {
+ pvno[1] Krb5Int32,
+ msg-type[2] MESSAGE-TYPE,
+ padata[3] METHOD-DATA OPTIONAL,
+ req-body[4] KDC-REQ-BODY
+}
+
+AS-REQ ::= [APPLICATION 10] KDC-REQ
+TGS-REQ ::= [APPLICATION 12] KDC-REQ
+
+-- padata-type ::= PA-ENC-TIMESTAMP
+-- padata-value ::= EncryptedData - PA-ENC-TS-ENC
+
+PA-ENC-TS-ENC ::= SEQUENCE {
+ patimestamp[0] KerberosTime, -- client's time
+ pausec[1] Krb5Int32 OPTIONAL
+}
+
+-- draft-brezak-win2k-krb-authz-01
+PA-PAC-REQUEST ::= SEQUENCE {
+ include-pac[0] BOOLEAN -- Indicates whether a PAC
+ -- should be included or not
+}
+
+-- MS-KILE
+
+KERB-ERROR-DATA ::= SEQUENCE {
+ data-type [1] KerbErrorDataType,
+ data-value [2] OCTET STRING OPTIONAL
+}
+
+KerbErrorDataType ::= INTEGER {
+ kERB-AP-ERR-TYPE-SKEW-RECOVERY(2),
+ kERB-ERR-TYPE-EXTENDED(3)
+}
+
+-- MS-KILE/MS-SFU
+PAC-OPTIONS-FLAGS ::= BIT STRING {
+ claims(0),
+ branch-aware(1),
+ forward-to-full-dc(2),
+ resource-based-constrained-delegation(3)
+}
+
+-- MS-KILE
+PA-PAC-OPTIONS ::= SEQUENCE {
+ flags [0] PAC-OPTIONS-FLAGS
+}
+
+-- MS-KILE
+-- captures show that [UNIVERSAL 16] is required to parse it
+KERB-AD-RESTRICTION-ENTRY ::= [UNIVERSAL 16] SEQUENCE {
+ restriction-type [0] Krb5Int32,
+ restriction [1] OCTET STRING -- LSAP_TOKEN_INFO_INTEGRITY structure
+}
+
+-- MS-KILE Section 2.2.11
+PA-KERB-KEY-LIST-REQ ::= SEQUENCE OF ENCTYPE
+
+-- MS-KILE Section 2.2.12
+
+PA-KERB-KEY-LIST-REP ::= SEQUENCE OF ENCTYPE -- EncryptionType,
+
+-- PacketCable provisioning server location, PKT-SP-SEC-I09-030728.pdf
+PROV-SRV-LOCATION ::= GeneralString
+
+KDC-REP ::= SEQUENCE {
+ pvno[0] Krb5Int32,
+ msg-type[1] MESSAGE-TYPE,
+ padata[2] METHOD-DATA OPTIONAL,
+ crealm[3] Realm,
+ cname[4] PrincipalName,
+ ticket[5] Ticket,
+ enc-part[6] EncryptedData
+}
+
+AS-REP ::= [APPLICATION 11] KDC-REP
+TGS-REP ::= [APPLICATION 13] KDC-REP
+
+EncKDCRepPart ::= SEQUENCE {
+ key[0] EncryptionKey,
+ last-req[1] LastReq,
+ nonce[2] Krb5Int32,
+ key-expiration[3] KerberosTime OPTIONAL,
+ flags[4] TicketFlags,
+ authtime[5] KerberosTime,
+ starttime[6] KerberosTime OPTIONAL,
+ endtime[7] KerberosTime,
+ renew-till[8] KerberosTime OPTIONAL,
+ srealm[9] Realm,
+ sname[10] PrincipalName,
+ caddr[11] HostAddresses OPTIONAL,
+ encrypted-pa-data[12] METHOD-DATA OPTIONAL
+}
+
+EncASRepPart ::= [APPLICATION 25] EncKDCRepPart
+EncTGSRepPart ::= [APPLICATION 26] EncKDCRepPart
+
+AP-REQ ::= [APPLICATION 14] SEQUENCE {
+ pvno[0] Krb5Int32,
+ msg-type[1] MESSAGE-TYPE,
+ ap-options[2] APOptions,
+ ticket[3] Ticket,
+ authenticator[4] EncryptedData
+}
+
+AP-REP ::= [APPLICATION 15] SEQUENCE {
+ pvno[0] Krb5Int32,
+ msg-type[1] MESSAGE-TYPE,
+ enc-part[2] EncryptedData
+}
+
+EncAPRepPart ::= [APPLICATION 27] SEQUENCE {
+ ctime[0] KerberosTime,
+ cusec[1] Krb5Int32,
+ subkey[2] EncryptionKey OPTIONAL,
+ seq-number[3] Krb5UInt32 OPTIONAL
+}
+
+KRB-SAFE-BODY ::= SEQUENCE {
+ user-data[0] OCTET STRING,
+ timestamp[1] KerberosTime OPTIONAL,
+ usec[2] Krb5Int32 OPTIONAL,
+ seq-number[3] Krb5UInt32 OPTIONAL,
+ s-address[4] HostAddress OPTIONAL,
+ r-address[5] HostAddress OPTIONAL
+}
+
+KRB-SAFE ::= [APPLICATION 20] SEQUENCE {
+ pvno[0] Krb5Int32,
+ msg-type[1] MESSAGE-TYPE,
+ safe-body[2] KRB-SAFE-BODY,
+ cksum[3] Checksum
+}
+
+KRB-PRIV ::= [APPLICATION 21] SEQUENCE {
+ pvno[0] Krb5Int32,
+ msg-type[1] MESSAGE-TYPE,
+ enc-part[3] EncryptedData
+}
+EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE {
+ user-data[0] OCTET STRING,
+ timestamp[1] KerberosTime OPTIONAL,
+ usec[2] Krb5Int32 OPTIONAL,
+ seq-number[3] Krb5UInt32 OPTIONAL,
+ s-address[4] HostAddress OPTIONAL, -- sender's addr
+ r-address[5] HostAddress OPTIONAL -- recip's addr
+}
+
+KRB-CRED ::= [APPLICATION 22] SEQUENCE {
+ pvno[0] Krb5Int32,
+ msg-type[1] MESSAGE-TYPE, -- KRB_CRED
+ tickets[2] SEQUENCE OF Ticket,
+ enc-part[3] EncryptedData
+}
+
+KrbCredInfo ::= SEQUENCE {
+ key[0] EncryptionKey,
+ prealm[1] Realm OPTIONAL,
+ pname[2] PrincipalName OPTIONAL,
+ flags[3] TicketFlags OPTIONAL,
+ authtime[4] KerberosTime OPTIONAL,
+ starttime[5] KerberosTime OPTIONAL,
+ endtime[6] KerberosTime OPTIONAL,
+ renew-till[7] KerberosTime OPTIONAL,
+ srealm[8] Realm OPTIONAL,
+ sname[9] PrincipalName OPTIONAL,
+ caddr[10] HostAddresses OPTIONAL
+}
+
+EncKrbCredPart ::= [APPLICATION 29] SEQUENCE {
+ ticket-info[0] SEQUENCE OF KrbCredInfo,
+ nonce[1] Krb5Int32 OPTIONAL,
+ timestamp[2] KerberosTime OPTIONAL,
+ usec[3] Krb5Int32 OPTIONAL,
+ s-address[4] HostAddress OPTIONAL,
+ r-address[5] HostAddress OPTIONAL
+}
+
+KRB-ERROR ::= [APPLICATION 30] SEQUENCE {
+ pvno[0] Krb5Int32,
+ msg-type[1] MESSAGE-TYPE,
+ ctime[2] KerberosTime OPTIONAL,
+ cusec[3] Krb5Int32 OPTIONAL,
+ stime[4] KerberosTime,
+ susec[5] Krb5Int32,
+ error-code[6] Krb5Int32,
+ crealm[7] Realm OPTIONAL,
+ cname[8] PrincipalName OPTIONAL,
+ realm[9] Realm, -- Correct realm
+ sname[10] PrincipalName, -- Correct name
+ e-text[11] GeneralString OPTIONAL,
+ e-data[12] OCTET STRING OPTIONAL
+}
+
+ChangePasswdDataMS ::= SEQUENCE {
+ newpasswd[0] OCTET STRING,
+ targname[1] PrincipalName OPTIONAL,
+ targrealm[2] Realm OPTIONAL
+}
+
+EtypeList ::= SEQUENCE OF ENCTYPE
+ -- the client's proposed enctype list in
+ -- decreasing preference order, favorite choice first
+
+krb5-pvno Krb5Int32 ::= 5 -- current Kerberos protocol version number
+
+-- transited encodings
+
+domain-X500-Compress Krb5Int32 ::= 1
+
+-- authorization data primitives
+
+AD-IF-RELEVANT ::= AuthorizationData
+
+AD-KDCIssued ::= SEQUENCE {
+ ad-checksum[0] Checksum,
+ i-realm[1] Realm OPTIONAL,
+ i-sname[2] PrincipalName OPTIONAL,
+ elements[3] AuthorizationData
+}
+
+AD-AND-OR ::= SEQUENCE {
+ condition-count[0] Krb5Int32,
+ elements[1] AuthorizationData
+}
+
+AD-MANDATORY-FOR-KDC ::= AuthorizationData
+
+-- PA-SAM-RESPONSE-2/PA-SAM-RESPONSE-2
+
+PA-SAM-TYPE ::= INTEGER {
+ PA_SAM_TYPE_ENIGMA(1), -- Enigma Logic
+ PA_SAM_TYPE_DIGI_PATH(2), -- Digital Pathways
+ PA_SAM_TYPE_SKEY_K0(3), -- S/key where KDC has key 0
+ PA_SAM_TYPE_SKEY(4), -- Traditional S/Key
+ PA_SAM_TYPE_SECURID(5), -- Security Dynamics
+ PA_SAM_TYPE_CRYPTOCARD(6) -- CRYPTOCard
+}
+
+PA-SAM-REDIRECT ::= HostAddresses
+
+SAMFlags ::= BIT STRING {
+ use-sad-as-key(0),
+ send-encrypted-sad(1),
+ must-pk-encrypt-sad(2)
+}
+
+PA-SAM-CHALLENGE-2-BODY ::= SEQUENCE {
+ sam-type[0] Krb5Int32,
+ sam-flags[1] SAMFlags,
+ sam-type-name[2] GeneralString OPTIONAL,
+ sam-track-id[3] GeneralString OPTIONAL,
+ sam-challenge-label[4] GeneralString OPTIONAL,
+ sam-challenge[5] GeneralString OPTIONAL,
+ sam-response-prompt[6] GeneralString OPTIONAL,
+ sam-pk-for-sad[7] EncryptionKey OPTIONAL,
+ sam-nonce[8] Krb5Int32,
+ sam-etype[9] Krb5Int32,
+ ...
+}
+
+PA-SAM-CHALLENGE-2 ::= SEQUENCE {
+ sam-body[0] PA-SAM-CHALLENGE-2-BODY,
+ sam-cksum[1] SEQUENCE OF Checksum, -- (1..MAX)
+ ...
+}
+
+PA-SAM-RESPONSE-2 ::= SEQUENCE {
+ sam-type[0] Krb5Int32,
+ sam-flags[1] SAMFlags,
+ sam-track-id[2] GeneralString OPTIONAL,
+ sam-enc-nonce-or-sad[3] EncryptedData, -- PA-ENC-SAM-RESPONSE-ENC
+ sam-nonce[4] Krb5Int32,
+ ...
+}
+
+PA-ENC-SAM-RESPONSE-ENC ::= SEQUENCE {
+ sam-nonce[0] Krb5Int32,
+ sam-sad[1] GeneralString OPTIONAL,
+ ...
+}
+
+PA-S4U2Self ::= SEQUENCE {
+ name[0] PrincipalName,
+ realm[1] Realm,
+ cksum[2] Checksum,
+ auth[3] GeneralString
+}
+
+PA-S4U-X509-USER::= SEQUENCE {
+ user-id[0] S4UUserID,
+ checksum[1] Checksum
+}
+
+S4UUserID ::= SEQUENCE {
+ nonce [0] Krb5UInt32, -- the nonce in KDC-REQ-BODY
+ cname [1] PrincipalName OPTIONAL, -- Certificate mapping hints
+ crealm [2] Realm,
+ subject-certificate [3] OCTET STRING OPTIONAL,
+ options [4] BIT STRING OPTIONAL,
+ ...
+}
+
+AD-LoginAlias ::= SEQUENCE { -- ad-type number TBD --
+ login-alias [0] PrincipalName,
+ checksum [1] Checksum
+}
+
+-- old ms referral
+PA-SvrReferralData ::= SEQUENCE {
+ referred-name [1] PrincipalName OPTIONAL,
+ referred-realm [0] Realm
+}
+
+PA-SERVER-REFERRAL-DATA ::= EncryptedData
+
+PA-ServerReferralData ::= SEQUENCE {
+ referred-realm [0] Realm OPTIONAL,
+ true-principal-name [1] PrincipalName OPTIONAL,
+ requested-principal-name [2] PrincipalName OPTIONAL,
+ referral-valid-until [3] KerberosTime OPTIONAL,
+ ...
+}
+
+FastOptions ::= BIT STRING {
+ reserved(0),
+ hide-client-names(1),
+ critical2(2),
+ critical3(3),
+ critical4(4),
+ critical5(5),
+ critical6(6),
+ critical7(7),
+ critical8(8),
+ critical9(9),
+ critical10(10),
+ critical11(11),
+ critical12(12),
+ critical13(13),
+ critical14(14),
+ critical15(15),
+ kdc-follow-referrals(16)
+}
+
+KrbFastReq ::= SEQUENCE {
+ fast-options [0] FastOptions,
+ padata [1] METHOD-DATA,
+ req-body [2] KDC-REQ-BODY,
+ ...
+}
+
+KrbFastArmor ::= SEQUENCE {
+ armor-type [0] Krb5Int32,
+ armor-value [1] OCTET STRING,
+ ...
+}
+
+KrbFastArmoredReq ::= SEQUENCE {
+ armor [0] KrbFastArmor OPTIONAL,
+ req-checksum [1] Checksum,
+ enc-fast-req [2] EncryptedData -- KrbFastReq --
+}
+
+PA-FX-FAST-REQUEST ::= CHOICE {
+ armored-data [0] KrbFastArmoredReq,
+ ...
+}
+
+KrbFastFinished ::= SEQUENCE {
+ timestamp [0] KerberosTime,
+ usec [1] Krb5Int32,
+ crealm [2] Realm,
+ cname [3] PrincipalName,
+ ticket-checksum [4] Checksum,
+ ...
+}
+
+KrbFastResponse ::= SEQUENCE {
+ padata [0] METHOD-DATA,
+ strengthen-key [1] EncryptionKey OPTIONAL,
+ finished [2] KrbFastFinished OPTIONAL,
+ nonce [3] Krb5UInt32,
+ ...
+}
+
+KrbFastArmoredRep ::= SEQUENCE {
+ enc-fast-rep [0] EncryptedData, -- KrbFastResponse --
+ ...
+}
+
+PA-FX-FAST-REPLY ::= CHOICE {
+ armored-data [0] KrbFastArmoredRep,
+ ...
+}
+
+KDCFastFlags ::= BIT STRING {
+ use-reply-key(0),
+ reply-key-used(1),
+ reply-key-replaced(2),
+ kdc-verified(3),
+ requested-hidden-names(4)
+}
+
+-- KDCFastState is stored in FX_COOKIE
+KDCFastState ::= SEQUENCE {
+ flags [0] KDCFastFlags,
+ expiration [1] GeneralizedTime,
+ fast-state [2] METHOD-DATA,
+ expected-pa-types [3] SEQUENCE OF PADATA-TYPE OPTIONAL
+}
+
+KDCFastCookie ::= SEQUENCE {
+ version [0] UTF8String,
+ cookie [1] EncryptedData
+}
+
+KDC-PROXY-MESSAGE ::= SEQUENCE {
+ kerb-message [0] OCTET STRING,
+ target-domain [1] Realm OPTIONAL,
+ dclocator-hint [2] INTEGER OPTIONAL
+}
+
+-- these messages are used in the GSSCred communication and is not part of Kerberos propper
+
+KERB-TIMES ::= SEQUENCE {
+ authtime [0] KerberosTime,
+ starttime [1] KerberosTime,
+ endtime [2] KerberosTime,
+ renew_till [3] KerberosTime
+}
+
+KERB-CRED ::= SEQUENCE {
+ client [0] Principal,
+ server [1] Principal,
+ keyblock [2] EncryptionKey,
+ times [3] KERB-TIMES,
+ ticket [4] OCTET STRING,
+ authdata [5] OCTET STRING,
+ addresses [6] HostAddresses,
+ flags [7] TicketFlags
+}
+
+KERB-TGS-REQ-IN ::= SEQUENCE {
+ cache [0] OCTET STRING SIZE (16),
+ addrs [1] HostAddresses,
+ flags [2] Krb5UInt32,
+ imp [3] Principal OPTIONAL,
+ ticket [4] OCTET STRING OPTIONAL,
+ in_cred [5] KERB-CRED,
+ krbtgt [6] KERB-CRED,
+ padata [7] METHOD-DATA
+}
+
+KERB-TGS-REQ-OUT ::= SEQUENCE {
+ subkey [0] EncryptionKey OPTIONAL,
+ t [1] TGS-REQ
+}
+
+
+
+KERB-TGS-REP-IN ::= SEQUENCE {
+ cache [0] OCTET STRING SIZE (16),
+ subkey [1] EncryptionKey OPTIONAL,
+ in_cred [2] KERB-CRED,
+ t [3] TGS-REP
+}
+
+KERB-TGS-REP-OUT ::= SEQUENCE {
+ cache [0] OCTET STRING SIZE (16),
+ cred [1] KERB-CRED,
+ subkey [2] EncryptionKey
+}
+
+KERB-ARMOR-SERVICE-REPLY ::= SEQUENCE {
+ armor [0] KrbFastArmor,
+ armor-key [1] EncryptionKey
+}
+
+END
+
+-- etags -r '/\([A-Za-z][-A-Za-z0-9]*\).*::=/\1/' k5.asn1
diff --git a/third_party/heimdal/lib/asn1/krb5.opt b/third_party/heimdal/lib/asn1/krb5.opt
new file mode 100644
index 0000000..a8bd85c
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/krb5.opt
@@ -0,0 +1,9 @@
+--encode-rfc1510-bit-string
+--sequence=Principals
+--sequence=AuthorizationData
+--sequence=METHOD-DATA
+--sequence=ETYPE-INFO
+--sequence=ETYPE-INFO2
+--preserve-binary=KDC-REQ-BODY
+--decorate=PrincipalNameAttrs:void *:pac
+--decorate=Principal:PrincipalNameAttrs:nameattrs?
diff --git a/third_party/heimdal/lib/asn1/kx509.asn1 b/third_party/heimdal/lib/asn1/kx509.asn1
new file mode 100644
index 0000000..af8a4d6
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/kx509.asn1
@@ -0,0 +1,204 @@
+-- $Id$
+
+-- Version 2 of the kx509 protocol is documented in RFC6717.
+--
+-- Our version here has extensions without changing the version number on the
+-- wire.
+
+KX509 DEFINITIONS ::= BEGIN
+IMPORTS Extensions FROM rfc2459
+ KerberosTime FROM krb5;
+
+KX509-ERROR-CODE ::= INTEGER {
+ KX509-STATUS-GOOD(0),
+ KX509-STATUS-CLIENT-BAD(1),
+ KX509-STATUS-CLIENT-FIX(2),
+ KX509-STATUS-CLIENT-TEMP(3),
+ KX509-STATUS-SERVER-BAD(4),
+ KX509-STATUS-SERVER-TEMP(5),
+ -- 6 is used internally in the umich client, avoid that
+ KX509-STATUS-SERVER-KEY(7),
+ -- CSR use negotiation:
+ KX509-STATUS-CLIENT-USE-CSR(8)
+ -- Let us reserve 1000+ for Kebreros protocol wire error codes -Nico
+}
+
+-- Originally kx509 requests carried only a public key. We'd like to have
+-- proof of possession, and the ability to carry additional options, both, in
+-- cleartext and otherwise.
+--
+-- We'll use a CSR for proof of posession and desired certificate extensions.
+--
+-- We'll also provide a non-CSR-based method of conveying desired certificate
+-- extensions. The reason for this is simply that we may want to have a [e.g.,
+-- RESTful HTTP] proxy for the kx509 service, and we want clients to be able to
+-- be as simple as possible -cargo-culted even- with support for attributes
+-- (desired certificate extensions) as parameters outside the CSR that the
+-- proxy can encode without having the private key for the CSR (naturally).
+--
+-- I.e., ultimately we'll have a REST endpoint, /kx509, say, with query
+-- parameters like:
+--
+-- - csr=<base64-encoding-of-DER-encoded-CSR>
+-- - eku=<OID>
+-- - ku=<key-usage-flag-name>
+-- - rfc822Name=<URL-escaped-email-address>
+-- - xMPPName=<URL-escaped-jabber-address>
+-- - dNSName=<URL-escaped-FQDN>
+-- - dNSSrv=<URL-escaped-_service.FQDN>
+-- - registeredID=<OID>
+-- - principalName=<URL-escaped-RFC1964-format-Kerberos-Principal-Name>
+--
+-- with exactly one CSR and zero, one, or more of the other parameters.
+--
+-- We'll even have a way to convey a bearer token from the REST proxy so that
+-- we may have a way to get PKIX credentials using bearer tokens. And then,
+-- using PKINIT, we may have a way to get Kerberos credentials using bearer
+-- tokens.
+--
+-- To do this we define a Kx509CSRPlus that we can use in the `pk-key' field of
+-- Kx509Request (see below):
+Kx509CSRPlus ::= [APPLICATION 35] SEQUENCE {
+ -- PKCS#10, DER-encoded CSR, with or without meaningful attributes
+ csr OCTET STRING,
+ -- Desired certificate Extensions such as KeyUsage, ExtKeyUsage, or
+ -- subjectAlternativeName (SAN)
+ exts Extensions OPTIONAL,
+ -- Desired certificate lifetime
+ req-life KerberosTime OPTIONAL,
+ ...
+}
+
+-- Version 2
+Kx509Request ::= SEQUENCE {
+ authenticator OCTET STRING,
+ pk-hash OCTET STRING, -- HMAC(ticket_session_key, pk-key)
+ pk-key OCTET STRING -- one of:
+ -- - the public key, DER-encoded (RSA, basically)
+ -- - a Kx509CSRPlus
+}
+
+-- Kx509ErrorCode is a Heimdal-specific enhancement with no change on the wire,
+-- and really only just so the error-code field below can fit on one line.
+Kx509ErrorCode ::= INTEGER (-2147483648..2147483647)
+
+Kx509Response ::= SEQUENCE {
+ error-code[0] Kx509ErrorCode DEFAULT 0,
+ hash[1] OCTET STRING OPTIONAL, -- HMAC(session_key, ...)
+ certificate[2] OCTET STRING OPTIONAL, -- DER-encoded Certificate
+ -- if client sent raw RSA SPK
+ -- or DER-encoded Certificates
+ -- (i.e., SEQ. OF Certificate)
+ -- if client used a
+ -- Kx509CSRPlus
+ e-text[3] VisibleString OPTIONAL
+}
+
+-- Offset for Kerberos protocol errors when error-code set to one:
+kx509-krb5-error-base INTEGER ::= 1000
+
+-- RFC6717 says this about error codes:
+--
+-- +------------+-----------------------------+------------------------+
+-- | error-code | Condition | Example |
+-- +------------+-----------------------------+------------------------+
+-- | 1 | Permanent problem with | Incompatible version |
+-- | | client request | |
+-- | 2 | Solvable problem with | Expired Kerberos |
+-- | | client request | credentials |
+-- | 3 | Temporary problem with | Packet loss |
+-- | | client request | |
+-- | 4 | Permanent problem with the | Internal |
+-- | | server | misconfiguration |
+-- | 5 | Temporary problem with the | Server overloaded |
+-- | | server | |
+-- +------------+-----------------------------+------------------------+
+--
+-- Looking at UMich CITI's kca (server-side of kx509) implementation, it always
+-- sends 0 as the status code, and the UMich CITI kx509 client never checks it.
+-- All of these error codes are local only in the UMich CITI implementation.
+--
+-- Meanwhile, Heimdal used to never send error responses at all.
+--
+-- As a result we can use whatever error codes we want. We'll send Kerberos
+-- protocol errors + 1000. And we'll never use RFC6717 error codes at all.
+--
+-- Looking at umich source...
+--
+-- #define KX509_STATUS_GOOD 0 /* No problems handling client request */
+-- #define KX509_STATUS_CLNT_BAD 1 /* Client-side permanent problem */
+-- /* ex. version incompatible */
+-- #define KX509_STATUS_CLNT_FIX 2 /* Client-side solvable problem */
+-- /* ex. re-authenticate */
+-- #define KX509_STATUS_CLNT_TMP 3 /* Client-side temporary problem */
+-- /* ex. packet loss */
+-- #define KX509_STATUS_SRVR_BAD 4 /* Server-side permanent problem */
+-- /* ex. server broken */
+-- #define KX509_STATUS_SRVR_TMP 5 /* Server-side temporary problem */
+-- /* ex. server overloaded */
+-- #define KX509_STATUS_SRVR_CANT_CLNT_VERS 6 /* Server-side doesn't handle */
+-- /* existence of client_version */
+-- /* field in KX509_REQUEST */
+--
+-- The umich server uses these errors in these situations:
+--
+-- - KX509_STATUS_SRVR_TMP is for:
+-- - request decode errors
+-- - krb5_is_ap_req() errors
+-- - wrong Kerberos protocol vno in AP-REQ
+-- - some ENOMEMs
+-- - UDP read errors (??)
+-- - LDAP issues (they use LDAP to map realm-chopped user princ names to
+-- full names)
+-- - pk decode errors
+-- - KX509_STATUS_CLNT_TMP is for:
+-- - HMAC mismatch
+-- - some ENOMEMs
+-- - failure to accept AP-REQ
+-- - failure to unparse princ names from AP-REQ's Ticket
+-- - KX509_STATUS_SRVR_BAD is for:
+-- - configuration issues (missing issuer creds)
+-- - serial number transaction issues (we should randomize)
+-- - subjectName construction issues
+-- - certificate construction issues (ENOMEM, say)
+-- - failure to authenticate (never happens, since KX509_STATUS_CLNT_TMP is
+-- used earlier when krb5_rd_req() fails)
+-- - KX509_STATUS_CLNT_FIX is for:
+-- - more than one component client principals
+-- - client princ name component zero string length shorter than 3 or
+-- longer than 8 (WTF)
+-- - other policy issues
+-- - KX509_STATUS_CLNT_BAD
+-- - wrong protocol version number (version_2_0)
+
+-- Possible new version designs:
+--
+-- - keep the protocol the same but use a CSR instead of a raw RSA public key
+-- - on the server try decoding first a CSR, then a raw RSA public key
+--
+-- - keep the protocol the same but use either a CSR or a self-signed cert
+-- - on the server try decoding first a Certificate, then a CSR, then a raw
+-- RSA public key
+--
+-- CSRs are a pain to deal with. Self-signed certificates can act as a
+-- CSR of a sort. Use notBefore == 1970-01-01T00:00:00Z and an EKU
+-- denoting "this certificate is really a much-easier-to-work-with CSR
+-- alternative".
+--
+-- - keep the protocol similar, but use the checksum field of the
+-- Authenticator to authenticate the request data; use a KRB-PRIV for the
+-- reply
+--
+-- - extend the KDC/AS/TGS protocols to support certificate issuance, either
+-- at the same time as ticket acquisition, or as an alternative
+-- - send a CSR as a authz-data element
+-- - expect an EncryptedData with the issued Certificate inside as the
+-- Ticket in the result (again, ugly hack)
+-- - or maybe just add new messages, but, the thing is that the existing
+-- "AP-REP + stuff" kx509 protocol is a fine design pattern, there's no
+-- need to radically change it, just slightly.
+--
+-- The main benefit of using an extension to the KDC/AS/TGS protocols is that
+-- we could then use FAST for confidentiality protection.
+
+END
diff --git a/third_party/heimdal/lib/asn1/lex.h b/third_party/heimdal/lib/asn1/lex.h
new file mode 100644
index 0000000..1ee5341
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/lex.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id$ */
+
+#include <roken.h>
+
+void lex_error_message (const char *, ...)
+__attribute__ ((format (printf, 1, 2)));
+extern int error_flag;
+
+int yylex(void);
diff --git a/third_party/heimdal/lib/asn1/lex.l b/third_party/heimdal/lib/asn1/lex.l
new file mode 100644
index 0000000..4554a94
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/lex.l
@@ -0,0 +1,310 @@
+%{
+/*
+ * Copyright (c) 1997 - 2017 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#undef ECHO
+#include "symbol.h"
+#include "asn1parse.h"
+#include "lex.h"
+#include "gen_locl.h"
+
+static unsigned lineno = 1;
+
+#undef ECHO
+
+static void unterminated(const char *, unsigned);
+
+%}
+
+/* This is for broken old lexes (solaris 10 and hpux) */
+%e 2000
+%p 5000
+%a 5000
+%n 1000
+%o 10000
+
+%%
+ABSENT { return kw_ABSENT; }
+ABSTRACT-SYNTAX { return kw_ABSTRACT_SYNTAX; }
+ALL { return kw_ALL; }
+APPLICATION { return kw_APPLICATION; }
+AUTOMATIC { return kw_AUTOMATIC; }
+BEGIN { return kw_BEGIN; }
+BIT { return kw_BIT; }
+BMPString { return kw_BMPString; }
+BOOLEAN { return kw_BOOLEAN; }
+BY { return kw_BY; }
+CHARACTER { return kw_CHARACTER; }
+CHOICE { return kw_CHOICE; }
+CLASS { return kw_CLASS; }
+COMPONENT { return kw_COMPONENT; }
+COMPONENTS { return kw_COMPONENTS; }
+CONSTRAINED { return kw_CONSTRAINED; }
+CONTAINING { return kw_CONTAINING; }
+DEFAULT { return kw_DEFAULT; }
+DEFINITIONS { return kw_DEFINITIONS; }
+EMBEDDED { return kw_EMBEDDED; }
+ENCODED { return kw_ENCODED; }
+END { return kw_END; }
+ENUMERATED { return kw_ENUMERATED; }
+EXCEPT { return kw_EXCEPT; }
+EXPLICIT { return kw_EXPLICIT; }
+EXPORTS { return kw_EXPORTS; }
+EXTENSIBILITY { return kw_EXTENSIBILITY; }
+EXTERNAL { return kw_EXTERNAL; }
+FALSE { return kw_FALSE; }
+FROM { return kw_FROM; }
+GeneralString { return kw_GeneralString; }
+GeneralizedTime { return kw_GeneralizedTime; }
+GraphicString { return kw_GraphicString; }
+IA5String { return kw_IA5String; }
+IDENTIFIER { return kw_IDENTIFIER; }
+IMPLICIT { return kw_IMPLICIT; }
+IMPLIED { return kw_IMPLIED; }
+IMPORTS { return kw_IMPORTS; }
+INCLUDES { return kw_INCLUDES; }
+INSTANCE { return kw_INSTANCE; }
+INTEGER { return kw_INTEGER; }
+INTERSECTION { return kw_INTERSECTION; }
+ISO646String { return kw_ISO646String; }
+MAX { return kw_MAX; }
+MIN { return kw_MIN; }
+MINUS-INFINITY { return kw_MINUS_INFINITY; }
+NULL { return kw_NULL; }
+NumericString { return kw_NumericString; }
+OBJECT { return kw_OBJECT; }
+OCTET { return kw_OCTET; }
+OF { return kw_OF; }
+OPTIONAL { return kw_OPTIONAL; }
+ObjectDescriptor { return kw_ObjectDescriptor; }
+PATTERN { return kw_PATTERN; }
+PDV { return kw_PDV; }
+PLUS-INFINITY { return kw_PLUS_INFINITY; }
+PRESENT { return kw_PRESENT; }
+PRIVATE { return kw_PRIVATE; }
+PrintableString { return kw_PrintableString; }
+REAL { return kw_REAL; }
+RELATIVE_OID { return kw_RELATIVE_OID; }
+SEQUENCE { return kw_SEQUENCE; }
+SET { return kw_SET; }
+SIZE { return kw_SIZE; }
+STRING { return kw_STRING; }
+SYNTAX { return kw_SYNTAX; }
+T61String { return kw_T61String; }
+TAGS { return kw_TAGS; }
+TRUE { return kw_TRUE; }
+TYPE-IDENTIFIER { return kw_TYPE_IDENTIFIER; }
+TeletexString { return kw_TeletexString; }
+UNION { return kw_UNION; }
+UNIQUE { return kw_UNIQUE; }
+UNIVERSAL { return kw_UNIVERSAL; }
+UTCTime { return kw_UTCTime; }
+UTF8String { return kw_UTF8String; }
+UniversalString { return kw_UniversalString; }
+VideotexString { return kw_VideotexString; }
+VisibleString { return kw_VisibleString; }
+WITH { return kw_WITH; }
+[-,;{}()|] { return *yytext; }
+"[" { return *yytext; }
+"]" { return *yytext; }
+"&" { return *yytext; }
+"." { return *yytext; }
+":" { return *yytext; }
+"@" { return *yytext; }
+::= { return EEQUAL; }
+-- {
+ int c, start_lineno = lineno;
+ int f = 0;
+ while((c = input()) != EOF) {
+ if(f && c == '-')
+ break;
+ if(c == '-') {
+ f = 1;
+ continue;
+ }
+ if(c == '\n') {
+ lineno++;
+ break;
+ }
+ f = 0;
+ }
+ if(c == EOF)
+ unterminated("comment", start_lineno);
+ }
+\/\* {
+ int c, start_lineno = lineno;
+ int level = 1;
+ int seen_star = 0;
+ int seen_slash = 0;
+ while((c = input()) != EOF) {
+ if(c == '/') {
+ if(seen_star) {
+ if(--level == 0)
+ break;
+ seen_star = 0;
+ continue;
+ }
+ seen_slash = 1;
+ continue;
+ }
+ if(seen_star && c == '/') {
+ if(--level == 0)
+ break;
+ seen_star = 0;
+ continue;
+ }
+ if(c == '*') {
+ if(seen_slash) {
+ level++;
+ seen_star = seen_slash = 0;
+ continue;
+ }
+ seen_star = 1;
+ continue;
+ }
+ seen_star = seen_slash = 0;
+ if(c == '\n') {
+ lineno++;
+ continue;
+ }
+ }
+ if(c == EOF)
+ unterminated("comment", start_lineno);
+ }
+"\"" {
+ int start_lineno = lineno;
+ int c;
+ char buf[1024];
+ char *p = buf;
+ int f = 0;
+ int skip_ws = 0;
+
+ while((c = input()) != EOF) {
+ if(isspace(c) && skip_ws) {
+ if(c == '\n')
+ lineno++;
+ continue;
+ }
+ skip_ws = 0;
+
+ if(c == '"') {
+ if(f) {
+ *p++ = '"';
+ f = 0;
+ } else
+ f = 1;
+ continue;
+ }
+ if(f == 1) {
+ unput(c);
+ break;
+ }
+ if(c == '\n') {
+ lineno++;
+ while(p > buf && isspace((unsigned char)p[-1]))
+ p--;
+ skip_ws = 1;
+ continue;
+ }
+ *p++ = c;
+ }
+ if(c == EOF)
+ unterminated("string", start_lineno);
+ *p++ = '\0';
+ yylval.name = estrdup(buf);
+ return STRING;
+ }
+
+-?0x[0-9A-Fa-f]+|-?[0-9]+ { char *e, *y = yytext;
+ yylval.constant = strtoll((const char *)yytext,
+ &e, 0);
+ if(e == y)
+ lex_error_message("malformed constant (%s)", yytext);
+ else
+ return NUMBER;
+ }
+[_][-A-Z0-9]* {
+ yylval.name = estrdup ((const char *)yytext);
+ return CLASS_IDENTIFIER;
+ }
+[A-Z][-A-Za-z0-9_]* {
+ yylval.name = estrdup ((const char *)yytext);
+ return TYPE_IDENTIFIER;
+ }
+[a-z][-A-Za-z0-9_]* {
+ yylval.name = estrdup ((const char *)yytext);
+ return VALUE_IDENTIFIER;
+ }
+[ \t] ;
+\n { ++lineno; }
+\.\.\. { return ELLIPSIS; }
+\.\. { return RANGE; }
+. { lex_error_message("Ignoring char(%c)\n", *yytext); }
+%%
+
+int
+yywrap ()
+{
+ return 1;
+}
+
+void
+lex_error_message (const char *format, ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ fprintf (stderr, "%s:%d: ", get_filename(), lineno);
+ vfprintf (stderr, format, args);
+ va_end (args);
+ error_flag++;
+}
+
+static void
+unterminated(const char *type, unsigned start_lineno)
+{
+ lex_error_message("unterminated %s, possibly started on line %d\n", type, start_lineno);
+}
diff --git a/third_party/heimdal/lib/asn1/libasn1-exports.def b/third_party/heimdal/lib/asn1/libasn1-exports.def
new file mode 100644
index 0000000..76a568f
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/libasn1-exports.def
@@ -0,0 +1,2655 @@
+EXPORTS
+ _asn1_decode_top
+ _asn1_encode
+ _asn1_length
+ _asn1_free_top
+ _asn1_copy_top
+ _asn1_bmember_isset_bit
+ _asn1_bmember_put_bit
+ _asn1_copy
+ _asn1_copy_top
+ _asn1_decode
+ _asn1_decode_top
+ _asn1_encode
+ _asn1_free
+ _asn1_free_top
+ _asn1_length
+ _asn1_print_top
+ _asn1_sizeofType
+ add_AttributeValues
+ add_AuthorizationData
+ add_CertificatePolicies
+ add_Certificates
+ add_CRLDistributionPoints
+ add_DigestAlgorithmIdentifiers
+ add_ETYPE_INFO
+ add_ETYPE_INFO2
+ add_Extensions
+ add_GeneralNames
+ add_METHOD_DATA
+ add_PolicyMappings
+ add_PolicyQualifierInfos
+ add_Principals
+ add_RDNSequence
+ APOptions2int
+ asn1_APOptions_units
+ asn1_DigestTypes_units
+ asn1_DistributionPointReasonFlags_units
+ asn1_FastOptions_units
+ asn1_KDCFastFlags_units
+ asn1_KDCOptions_units
+ asn1_KeyUsage_units
+ asn1_oid_id_aa_communityIdentifiers DATA
+ asn1_oid_id_aa_decryptKeyID DATA
+ asn1_oid_id_aa_firmwarePackageID DATA
+ asn1_oid_id_aa_firmwarePackageInfo DATA
+ asn1_oid_id_aa_implCompressAlgs DATA
+ asn1_oid_id_aa_implCryptoAlgs DATA
+ asn1_oid_id_aa_targetHardwareIDs DATA
+ asn1_oid_id_aa_wrappedFirmwareKey DATA
+ asn1_oid_id_aes_128_cbc DATA
+ asn1_oid_id_aes_192_cbc DATA
+ asn1_oid_id_aes_256_cbc DATA
+ asn1_oid_id_apple_system_id DATA
+ asn1_oid_id_at_commonName DATA
+ asn1_oid_id_at_countryName DATA
+ asn1_oid_id_at_description DATA
+ asn1_oid_id_at_dnQualifier DATA
+ asn1_oid_id_at_emailAddress DATA
+ asn1_oid_id_at_generationQualifier DATA
+ asn1_oid_id_at_givenName DATA
+ asn1_oid_id_at_initials DATA
+ asn1_oid_id_at_localityName DATA
+ asn1_oid_id_at_name DATA
+ asn1_oid_id_at_organizationalUnitName DATA
+ asn1_oid_id_at_organizationName DATA
+ asn1_oid_id_at_pseudonym DATA
+ asn1_oid_id_at_serialNumber DATA
+ asn1_oid_id_at_stateOrProvinceName DATA
+ asn1_oid_id_at_streetAddress DATA
+ asn1_oid_id_at_surname DATA
+ asn1_oid_id_at_title DATA
+ asn1_oid_id_ct_firmwareLoadError DATA
+ asn1_oid_id_ct_firmwareLoadReceipt DATA
+ asn1_oid_id_ct_firmwarePackage DATA
+ asn1_oid_id_dhpublicnumber DATA
+ asn1_oid_id_domainComponent DATA
+ asn1_oid_id_dsa DATA
+ asn1_oid_id_dsa_with_sha1 DATA
+ asn1_oid_id_ecDH DATA
+ asn1_oid_id_ecdsa_with_SHA1 DATA
+ asn1_oid_id_ecdsa_with_SHA224 DATA
+ asn1_oid_id_ecdsa_with_SHA256 DATA
+ asn1_oid_id_ecdsa_with_SHA384 DATA
+ asn1_oid_id_ecdsa_with_SHA512 DATA
+ asn1_oid_id_ec_group_secp160r1 DATA
+ asn1_oid_id_ec_group_secp160r2 DATA
+ asn1_oid_id_ec_group_secp224r1 DATA
+ asn1_oid_id_ec_group_secp256r1 DATA
+ asn1_oid_id_ec_group_secp384r1 DATA
+ asn1_oid_id_ec_group_secp521r1 DATA
+ asn1_oid_id_ecMQV DATA
+ asn1_oid_id_ecPublicKey DATA
+ asn1_oid_id_heim_rsa_pkcs1_x509 DATA
+ asn1_oid_id_ms_cert_enroll_domaincontroller DATA
+ asn1_oid_id_msft DATA
+ asn1_oid_id_msft_kp_msCodeCom DATA
+ asn1_oid_id_msft_kp_msCodeInd DATA
+ asn1_oid_id_msft_kp_msCTLSign DATA
+ asn1_oid_id_msft_kp_msEFS DATA
+ asn1_oid_id_msft_kp_msSGC DATA
+ asn1_oid_id_msft_kp_msSmartcardLogin DATA
+ asn1_oid_id_msft_kp_msUPN DATA
+ asn1_oid_id_netscape_cert_comment DATA
+ asn1_oid_id_netscape DATA
+ asn1_oid_id_nist_aes_algs DATA
+ asn1_oid_id_nistAlgorithm DATA
+ asn1_oid_id_nist_sha_algs DATA
+ asn1_oid_id_on_hardwareModuleName DATA
+ asn1_oid_id_pbeWithSHAAnd128BitRC2_CBC DATA
+ asn1_oid_id_pbeWithSHAAnd128BitRC4 DATA
+ asn1_oid_id_pbeWithSHAAnd2_KeyTripleDES_CBC DATA
+ asn1_oid_id_pbeWithSHAAnd3_KeyTripleDES_CBC DATA
+ asn1_oid_id_pbewithSHAAnd40BitRC2_CBC DATA
+ asn1_oid_id_pbeWithSHAAnd40BitRC4 DATA
+ asn1_oid_id_pkauthdata DATA
+ asn1_oid_id_pkcs12_bagtypes DATA
+ asn1_oid_id_pkcs12_certBag DATA
+ asn1_oid_id_pkcs12_crlBag DATA
+ asn1_oid_id_pkcs_12 DATA
+ asn1_oid_id_pkcs12_keyBag DATA
+ asn1_oid_id_pkcs_12PbeIds DATA
+ asn1_oid_id_pkcs12_pkcs8ShroudedKeyBag DATA
+ asn1_oid_id_pkcs12_safeContentsBag DATA
+ asn1_oid_id_pkcs12_secretBag DATA
+ asn1_oid_id_pkcs_1 DATA
+ asn1_oid_id_pkcs1_md2WithRSAEncryption DATA
+ asn1_oid_id_pkcs1_md5WithRSAEncryption DATA
+ asn1_oid_id_pkcs1_rsaEncryption DATA
+ asn1_oid_id_pkcs1_sha1WithRSAEncryption DATA
+ asn1_oid_id_pkcs1_sha256WithRSAEncryption DATA
+ asn1_oid_id_pkcs1_sha384WithRSAEncryption DATA
+ asn1_oid_id_pkcs1_sha512WithRSAEncryption DATA
+ asn1_oid_id_pkcs_2 DATA
+ asn1_oid_id_pkcs2_md2 DATA
+ asn1_oid_id_pkcs2_md4 DATA
+ asn1_oid_id_pkcs2_md5 DATA
+ asn1_oid_id_pkcs_3 DATA
+ asn1_oid_id_pkcs3_des_ede3_cbc DATA
+ asn1_oid_id_pkcs3_rc2_cbc DATA
+ asn1_oid_id_pkcs3_rc4 DATA
+ asn1_oid_id_pkcs7 DATA
+ asn1_oid_id_pkcs7_data DATA
+ asn1_oid_id_pkcs7_digestedData DATA
+ asn1_oid_id_pkcs7_encryptedData DATA
+ asn1_oid_id_pkcs7_envelopedData DATA
+ asn1_oid_id_pkcs7_signedAndEnvelopedData DATA
+ asn1_oid_id_pkcs7_signedData DATA
+ asn1_oid_id_pkcs_9_at_certTypes DATA
+ asn1_oid_id_pkcs_9_at_certTypes_x509 DATA
+ asn1_oid_id_pkcs_9_at_friendlyName DATA
+ asn1_oid_id_pkcs_9_at_localKeyId DATA
+ asn1_oid_id_pkcs9_contentType DATA
+ asn1_oid_id_pkcs9_countersignature DATA
+ asn1_oid_id_pkcs_9 DATA
+ asn1_oid_id_pkcs9_emailAddress DATA
+ asn1_oid_id_pkcs9_extReq DATA
+ asn1_oid_id_pkcs9_messageDigest DATA
+ asn1_oid_id_pkcs9_signingTime DATA
+ asn1_oid_id_pkdhkeydata DATA
+ asn1_oid_id_pkekuoid DATA
+ asn1_oid_id_pkinit DATA
+ asn1_oid_id_pkinit_kdf_ah_sha1 DATA
+ asn1_oid_id_pkinit_kdf_ah_sha256 DATA
+ asn1_oid_id_pkinit_kdf_ah_sha512 DATA
+ asn1_oid_id_pkinit_kdf DATA
+ asn1_oid_id_pkinit_ms_eku DATA
+ asn1_oid_id_pkinit_ms_san DATA
+ asn1_oid_id_pkinit_san DATA
+ asn1_oid_id_pkix_ad_caIssuers DATA
+ asn1_oid_id_pkix_ad_caRepository DATA
+ asn1_oid_id_pkix_ad DATA
+ asn1_oid_id_pkix_ad_ocsp DATA
+ asn1_oid_id_pkix_ad_timeStamping DATA
+ asn1_oid_id_pkix DATA
+ asn1_oid_id_pkix_kp_bgpsec_router DATA
+ asn1_oid_id_pkix_kp_capwapAC DATA
+ asn1_oid_id_pkix_kp_capwapWTP DATA
+ asn1_oid_id_pkix_kp_clientAuth DATA
+ asn1_oid_id_pkix_kp_cmcArchive DATA
+ asn1_oid_id_pkix_kp_cmcCA DATA
+ asn1_oid_id_pkix_kp_cmcRA DATA
+ asn1_oid_id_pkix_kp_codeSigning DATA
+ asn1_oid_id_pkix_kp DATA
+ asn1_oid_id_pkix_kp_DVCS DATA
+ asn1_oid_id_pkix_kp_emailProtection DATA
+ asn1_oid_id_pkix_kp_ipsecEndSystem DATA
+ asn1_oid_id_pkix_kp_ipsecIKE DATA
+ asn1_oid_id_pkix_kp_ipsecTunnel DATA
+ asn1_oid_id_pkix_kp_ipsecUser DATA
+ asn1_oid_id_pkix_kp_OCSPSigning DATA
+ asn1_oid_id_pkix_kp_secureShellClient DATA
+ asn1_oid_id_pkix_kp_secureShellServer DATA
+ asn1_oid_id_pkix_kp_sendOwner DATA
+ asn1_oid_id_pkix_kp_sendProxiedOwner DATA
+ asn1_oid_id_pkix_kp_sendProxiedRouter DATA
+ asn1_oid_id_pkix_kp_sendRouter DATA
+ asn1_oid_id_pkix_kp_serverAuth DATA
+ asn1_oid_id_pkix_kp_sipDomain DATA
+ asn1_oid_id_pkix_kp_timeStamping DATA
+ asn1_oid_id_pkix_ocsp_basic DATA
+ asn1_oid_id_pkix_ocsp DATA
+ asn1_oid_id_pkix_ocsp_nonce DATA
+ asn1_oid_id_pkix_on DATA
+ asn1_oid_id_pkix_on_dnsSRV DATA
+ asn1_oid_id_pkix_on_hardwareModuleName DATA
+ asn1_oid_id_pkix_on_permanentIdentifier DATA
+ asn1_oid_id_pkix_on_pkinit_ms_san DATA
+ asn1_oid_id_pkix_on_pkinit_san DATA
+ asn1_oid_id_pkix_on_xmppAddr DATA
+ asn1_oid_id_pkix_pe_authorityInfoAccess DATA
+ asn1_oid_id_pkix_pe DATA
+ asn1_oid_id_pkix_pe_proxyCertInfo DATA
+ asn1_oid_id_pkix_pe_subjectInfoAccess DATA
+ asn1_oid_id_pkix_ppl_anyLanguage DATA
+ asn1_oid_id_pkix_ppl DATA
+ asn1_oid_id_pkix_ppl_independent DATA
+ asn1_oid_id_pkix_ppl_inheritAll DATA
+ asn1_oid_id_pkix_qt_cps DATA
+ asn1_oid_id_pkix_qt DATA
+ asn1_oid_id_pkix_qt_unotice DATA
+ asn1_oid_id_pkkdcekuoid DATA
+ asn1_oid_id_pkrkeydata DATA
+ asn1_oid_id_rsa_digestAlgorithm DATA
+ asn1_oid_id_rsa_digest_md2 DATA
+ asn1_oid_id_rsa_digest_md4 DATA
+ asn1_oid_id_rsa_digest_md5 DATA
+ asn1_oid_id_rsadsi_des_ede3_cbc DATA
+ asn1_oid_id_rsadsi_encalg DATA
+ asn1_oid_id_rsadsi_rc2_cbc DATA
+ asn1_oid_id_secsig_sha_1 DATA
+ asn1_oid_id_secsig_sha_1WithRSAEncryption DATA
+ asn1_oid_id_sha224 DATA
+ asn1_oid_id_sha256 DATA
+ asn1_oid_id_sha384 DATA
+ asn1_oid_id_sha512 DATA
+ asn1_oid_id_Userid DATA
+ asn1_oid_id_uspkicommon_card_id DATA
+ asn1_oid_id_uspkicommon_piv_interim DATA
+ asn1_oid_id_x509_ce_anyExtendedKeyUsage DATA
+ asn1_oid_id_x509_ce_authorityKeyIdentifier DATA
+ asn1_oid_id_x509_ce_basicConstraints DATA
+ asn1_oid_id_x509_ce_certificateIssuer DATA
+ asn1_oid_id_x509_ce_certificatePolicies_anyPolicy DATA
+ asn1_oid_id_x509_ce_certificatePolicies DATA
+ asn1_oid_id_x509_ce_cRLDistributionPoints DATA
+ asn1_oid_id_x509_ce_cRLNumber DATA
+ asn1_oid_id_x509_ce_cRLReason DATA
+ asn1_oid_id_x509_ce_cRLReasons DATA
+ asn1_oid_id_x509_ce DATA
+ asn1_oid_id_x509_ce_deltaCRLIndicator DATA
+ asn1_oid_id_x509_ce_extKeyUsage DATA
+ asn1_oid_id_x509_ce_freshestCRL DATA
+ asn1_oid_id_x509_ce_holdInstructionCode DATA
+ asn1_oid_id_x509_ce_inhibitAnyPolicy DATA
+ asn1_oid_id_x509_ce_invalidityDate DATA
+ asn1_oid_id_x509_ce_issuerAltName DATA
+ asn1_oid_id_x509_ce_issuingDistributionPoint DATA
+ asn1_oid_id_x509_ce_keyUsage DATA
+ asn1_oid_id_x509_ce_nameConstraints DATA
+ asn1_oid_id_x509_ce_policyConstraints DATA
+ asn1_oid_id_x509_ce_policyMappings DATA
+ asn1_oid_id_x509_ce_privateKeyUsagePeriod DATA
+ asn1_oid_id_x509_ce_subjectAltName DATA
+ asn1_oid_id_x509_ce_subjectDirectoryAttributes DATA
+ asn1_oid_id_x509_ce_subjectKeyIdentifier DATA
+ asn1_oid_id_x520_at DATA
+ asn1_oid_id_x9_57 DATA
+ asn1_oid_tcg_at_tpmManufacturer DATA
+ asn1_oid_tcg_at_tpmModel DATA
+ asn1_oid_tcg_at_tpmSecurityAssertions DATA
+ asn1_oid_tcg_at_tpmSpecification DATA
+ asn1_oid_tcg_at_tpmVersion DATA
+ asn1_oid_tcg_attribute DATA
+ asn1_oid_tcg_cap_verifiedTPMFixed DATA
+ asn1_oid_tcg_cap_verifiedTPMResidency DATA
+ asn1_oid_tcg_cap_verifiedTPMRestricted DATA
+ asn1_oid_tcg DATA
+ asn1_oid_tcg_kp DATA
+ asn1_oid_tcg_kp_EKCertificate DATA
+ asn1_oid_tcg_on_ekPermIdSha256 DATA
+ asn1_oid_tcg_tpm20 DATA
+ asn1_SAMFlags_units
+ asn1_TicketFlags_units
+ copy_AccessDescription
+ copy_AD_AND_OR
+ copy_AD_IF_RELEVANT
+ copy_AD_INITIAL_VERIFIED_CAS
+ copy_AD_KDCIssued
+ copy_AD_LoginAlias
+ copy_AD_MANDATORY_FOR_KDC
+ copy_AlgorithmIdentifier
+ copy_AliasIA5String
+ copy_AliasPrintableString
+ copy_AliasUTF8String
+ copy_APOptions
+ copy_AP_REP
+ copy_AP_REQ
+ copy_AS_REP
+ copy_AS_REQ
+ copy_Attribute
+ copy_AttributeSet
+ copy_AttributeType
+ copy_AttributeTypeAndValue
+ copy_AttributeValue
+ copy_AttributeValues
+ copy_AUTHDATA_TYPE
+ copy_Authenticator
+ copy_AuthorityInfoAccessSyntax
+ copy_AuthorityKeyIdentifier
+ copy_AuthorizationData
+ copy_AuthorizationDataElement
+ copy_AuthPack
+ copy_AuthPack_Win2k
+ copy_BaseDistance
+ copy_BasicConstraints
+ copy_Certificate
+ copy_CertificateList
+ copy_CertificatePolicies
+ copy_CertificateRevocationLists
+ copy_Certificates
+ copy_CertificateSerialNumber
+ copy_CertificateSet
+ copy_CertificationRequest
+ copy_CertificationRequestInfo
+ copy_CertPolicyId
+ copy_ChangePasswdDataMS
+ copy_Checksum
+ copy_CKSUMTYPE
+ copy_CMSAttributes
+ copy_CMSCBCParameter
+ copy_CMSEncryptedData
+ copy_CMSIdentifier
+ copy_CMSRC2CBCParameter
+ copy_CMSVersion
+ copy_CommonCriteriaMeasures
+ copy_CommunityIdentifier
+ copy_CommunityIdentifiers
+ copy_CompositePrincipal
+ copy_ContentEncryptionAlgorithmIdentifier
+ copy_ContentInfo
+ copy_ContentType
+ copy_CPSuri
+ copy_CRIAttributeSet
+ copy_CRIExtensions
+ copy_CRLCertificateList
+ copy_CRLDistributionPoints
+ copy_CRLReason
+ copy_CurrentFWConfig
+ copy_DecryptKeyIdentifier
+ copy_DHNonce
+ copy_DHParameter
+ copy_DHPublicKey
+ copy_DHRepInfo
+ copy_DigestAlgorithmIdentifier
+ copy_DigestAlgorithmIdentifiers
+ copy_DigestError
+ copy_DigestInfo
+ copy_DigestInit
+ copy_DigestInitReply
+ copy_DigestREP
+ copy_DigestRepInner
+ copy_DigestREQ
+ copy_DigestReqInner
+ copy_DigestRequest
+ copy_DigestResponse
+ copy_DigestTypes
+ copy_DirectoryString
+ copy_DisplayText
+ copy_DistributionPoint
+ copy_DistributionPointName
+ copy_DistributionPointReasonFlags
+ copy_DomainParameters
+ copy_DSAParams
+ copy_DSAPublicKey
+ copy_DSASigValue
+ copy_ECDSA_Sig_Value
+ copy_ECParameters
+ copy_ECPoint
+ copy_EKCertificateGenerationLocation
+ copy_EKGenerationLocation
+ copy_EKGenerationType
+ copy_EncAPRepPart
+ copy_EncapsulatedContentInfo
+ copy_EncASRepPart
+ copy_EncKDCRepPart
+ copy_EncKrbCredPart
+ copy_EncKrbPrivPart
+ copy_EncryptedContent
+ copy_EncryptedContentInfo
+ copy_EncryptedData
+ copy_EncryptedKey
+ copy_EncryptionKey
+ copy_EncTGSRepPart
+ copy_EncTicketPart
+ copy_ENCTYPE
+ copy_EnvelopedData
+ copy_ETYPE_INFO
+ copy_ETYPE_INFO2
+ copy_ETYPE_INFO2_ENTRY
+ copy_ETYPE_INFO_ENTRY
+ copy_EtypeList
+ copy_EvaluationAssuranceLevel
+ copy_EvaluationStatus
+ copy_Extension
+ copy_Extensions
+ copy_ExternalPrincipalIdentifier
+ copy_ExternalPrincipalIdentifiers
+ copy_ExtKeyUsage
+ copy_FastOptions
+ copy_FIPSLevel
+ copy_FirmwarePackageIdentifier
+ copy_FirmwarePackageInfo
+ copy_FirmwarePackageLoadError
+ copy_FirmwarePackageLoadErrorCode
+ copy_FirmwarePackageLoadReceipt
+ copy_FirmwarePkgData
+ copy_FWErrorVersion
+ copy_FWReceiptVersion
+ copy_GeneralName
+ copy_GeneralNames
+ copy_GeneralSubtree
+ copy_GeneralSubtrees
+ copy_HardwareModuleName
+ copy_HardwareModules
+ copy_HardwareSerialEntry
+ copy_heim_any
+ copy_HEIM_ANY
+ copy_heim_any_set
+ copy_HEIM_ANY_SET
+ copy_HostAddress
+ copy_HostAddresses
+ copy_ImplementedCompressAlgorithms
+ copy_ImplementedCryptoAlgorithms
+ copy_IOSCertificationRequest
+ copy_IOSCertificationRequestInfo
+ copy_IssuerAndSerialNumber
+ copy_KDCDHKeyInfo
+ copy_KDCDHKeyInfo_Win2k
+ copy_KDCFastCookie
+ copy_KDCFastFlags
+ copy_KDCFastState
+ copy_KDCOptions
+ copy_KDC_PROXY_MESSAGE
+ copy_KDC_REP
+ copy_KDC_REQ
+ copy_KDC_REQ_BODY
+ copy_KDFAlgorithmId
+ copy_KERB_AD_RESTRICTION_ENTRY
+ copy_KERB_ARMOR_SERVICE_REPLY
+ copy_KERB_CRED
+ copy_KerberosString
+ copy_KerberosTime
+ copy_KERB_ERROR_DATA
+ copy_KERB_TGS_REP_IN
+ copy_KERB_TGS_REP_OUT
+ copy_KERB_TGS_REQ_IN
+ copy_KERB_TGS_REQ_OUT
+ copy_KERB_TIMES
+ copy_KeyEncryptionAlgorithmIdentifier
+ copy_KeyIdentifier
+ copy_KeyTransRecipientInfo
+ copy_KeyUsage
+ copy_Krb5Int32
+ copy_KRB5PrincipalName
+ copy_Krb5UInt32
+ copy_KRB_CRED
+ copy_KrbCredInfo
+ copy_KRB_ERROR
+ copy_KrbFastArmor
+ copy_KrbFastArmoredRep
+ copy_KrbFastArmoredReq
+ copy_KrbFastFinished
+ copy_KrbFastReq
+ copy_KrbFastResponse
+ copy_KRB_PRIV
+ copy_KRB_SAFE
+ copy_KRB_SAFE_BODY
+ copy_Kx509CSRPlus
+ copy_Kx509ErrorCode
+ copy_KX509_ERROR_CODE
+ copy_Kx509Request
+ copy_Kx509Response
+ copy_LastReq
+ copy_LR_TYPE
+ copy_MessageDigest
+ copy_MESSAGE_TYPE
+ copy_METHOD_DATA
+ copy_MS_UPN_SAN
+ copy_Name
+ copy_NameConstraints
+ copy_NAME_TYPE
+ copy_NoticeReference
+ copy_NTLMInit
+ copy_NTLMInitReply
+ copy_NTLMReply
+ copy_NTLMRequest
+ copy_NTLMRequest2
+ copy_NTLMResponse
+ copy_OCSPBasicOCSPResponse
+ copy_OCSPCertID
+ copy_OCSPCertStatus
+ copy_OCSPInnerRequest
+ copy_OCSPKeyHash
+ copy_OCSPRequest
+ copy_OCSPResponderID
+ copy_OCSPResponse
+ copy_OCSPResponseBytes
+ copy_OCSPResponseData
+ copy_OCSPResponseStatus
+ copy_OCSPSignature
+ copy_OCSPSingleResponse
+ copy_OCSPTBSRequest
+ copy_OCSPVersion
+ copy_OriginatorInfo
+ copy_OtherName
+ copy_PA_DATA
+ copy_PADATA_TYPE
+ copy_PA_ENC_SAM_RESPONSE_ENC
+ copy_PA_ENC_TS_ENC
+ copy_PA_FX_FAST_REPLY
+ copy_PA_FX_FAST_REQUEST
+ copy_PA_KERB_KEY_LIST_REP
+ copy_PA_KERB_KEY_LIST_REQ
+ copy_PA_PAC_OPTIONS
+ copy_PA_PAC_REQUEST
+ copy_PA_PK_AS_REP
+ copy_PA_PK_AS_REP_BTMM
+ copy_PA_PK_AS_REP_Win2k
+ copy_PA_PK_AS_REQ
+ copy_PA_PK_AS_REQ_Win2k
+ copy_PA_S4U_X509_USER
+ copy_PA_S4U2Self
+ copy_PA_SAM_CHALLENGE_2
+ copy_PA_SAM_CHALLENGE_2_BODY
+ copy_PA_SAM_REDIRECT
+ copy_PA_SAM_RESPONSE_2
+ copy_PA_SAM_TYPE
+ copy_PA_ServerReferralData
+ copy_PA_SERVER_REFERRAL_DATA
+ copy_PA_SvrReferralData
+ copy_PermanentIdentifier
+ copy_PKAuthenticator
+ copy_PKAuthenticator_Win2k
+ copy_PKCS12_Attribute
+ copy_PKCS12_Attributes
+ copy_PKCS12_AuthenticatedSafe
+ copy_PKCS12_CertBag
+ copy_PKCS12_MacData
+ copy_PKCS12_OctetString
+ copy_PKCS12_PBEParams
+ copy_PKCS12_PFX
+ copy_PKCS12_SafeBag
+ copy_PKCS12_SafeContents
+ copy_PKCS8Attributes
+ copy_PKCS8EncryptedData
+ copy_PKCS8EncryptedPrivateKeyInfo
+ copy_PKCS8PrivateKey
+ copy_PKCS8PrivateKeyAlgorithmIdentifier
+ copy_PKCS8PrivateKeyInfo
+ copy_PKCS9_BMPString
+ copy_PKCS9_friendlyName
+ copy_PkinitSP80056AOtherInfo
+ copy_PkinitSuppPubInfo
+ copy_PKIXXmppAddr
+ copy_PolicyConstraints
+ copy_PolicyInformation
+ copy_PolicyMapping
+ copy_PolicyMappings
+ copy_PolicyQualifierId
+ copy_PolicyQualifierInfo
+ copy_PolicyQualifierInfos
+ copy_PreferredOrLegacyPackageIdentifier
+ copy_PreferredOrLegacyStalePackageIdentifier
+ copy_PreferredPackageIdentifier
+ copy_Principal
+ copy_PrincipalName
+ copy_Principals
+ copy_PrivateKeyUsagePeriod
+ copy_PROV_SRV_LOCATION
+ copy_ProxyCertInfo
+ copy_ProxyPolicy
+ copy_RDNSequence
+ copy_Realm
+ copy_RecipientIdentifier
+ copy_RecipientInfo
+ copy_RecipientInfos
+ copy_RelativeDistinguishedName
+ copy_ReplyKeyPack
+ copy_ReplyKeyPack_Win2k
+ copy_RSAPrivateKey
+ copy_RSAPublicKey
+ copy_SAMFlags
+ copy_SecurityLevel
+ copy_SignatureAlgorithmIdentifier
+ copy_SignatureValue
+ copy_SignedData
+ copy_SignerIdentifier
+ copy_SignerInfo
+ copy_SignerInfos
+ copy_SingleAttribute
+ copy_SkipCerts
+ copy_SRVName
+ copy_StrengthOfFunction
+ copy_SubjectDirectoryAttributes
+ copy_SubjectInfoAccessSyntax
+ copy_SubjectKeyIdentifier
+ copy_SubjectPublicKeyInfo
+ copy_TargetHardwareIdentifiers
+ copy_TBSCertificate
+ copy_TBSCRLCertList
+ copy_TD_DH_PARAMETERS
+ copy_TD_INVALID_CERTIFICATES
+ copy_TD_TRUSTED_CERTIFIERS
+ copy_TGS_REP
+ copy_TGS_REQ
+ copy_Ticket
+ copy_TicketFlags
+ copy_Time
+ copy_TPMSecurityAssertions
+ copy_TPMSpecification
+ copy_TPMVersion
+ copy_TransitedEncoding
+ copy_TrustedCA
+ copy_TrustedCA_Win2k
+ copy_TypedData
+ copy_TYPED_DATA
+ copy_UniqueIdentifier
+ copy_UnprotectedAttributes
+ copy_URIReference
+ copy_UserNotice
+ copy_ValidationParms
+ copy_Validity
+ copy_VendorLoadErrorCode
+ copy_Version
+ copy_WrappedFirmwareKey
+ copy_X520CommonName
+ copy_X520LocalityName
+ copy_X520name
+ copy_X520OrganizationalUnitName
+ copy_X520OrganizationName
+ copy_X520StateOrProvinceName
+ copy_X690SampleChildInformation
+ copy_X690SampleDate
+ copy_X690SampleEmployeeNumber
+ copy_X690SampleName
+ copy_X690SamplePersonnelRecord
+ decode_AccessDescription
+ decode_AD_AND_OR
+ decode_AD_IF_RELEVANT
+ decode_AD_INITIAL_VERIFIED_CAS
+ decode_AD_KDCIssued
+ decode_AD_LoginAlias
+ decode_AD_MANDATORY_FOR_KDC
+ decode_AlgorithmIdentifier
+ decode_AliasIA5String
+ decode_AliasPrintableString
+ decode_AliasUTF8String
+ decode_APOptions
+ decode_AP_REP
+ decode_AP_REQ
+ decode_AS_REP
+ decode_AS_REQ
+ decode_Attribute
+ decode_AttributeSet
+ decode_AttributeType
+ decode_AttributeTypeAndValue
+ decode_AttributeValue
+ decode_AttributeValues
+ decode_AUTHDATA_TYPE
+ decode_Authenticator
+ decode_AuthorityInfoAccessSyntax
+ decode_AuthorityKeyIdentifier
+ decode_AuthorizationData
+ decode_AuthorizationDataElement
+ decode_AuthPack
+ decode_AuthPack_Win2k
+ decode_BaseDistance
+ decode_BasicConstraints
+ decode_Certificate
+ decode_CertificateList
+ decode_CertificatePolicies
+ decode_CertificateRevocationLists
+ decode_Certificates
+ decode_CertificateSerialNumber
+ decode_CertificateSet
+ decode_CertificationRequest
+ decode_CertificationRequestInfo
+ decode_CertPolicyId
+ decode_ChangePasswdDataMS
+ decode_Checksum
+ decode_CKSUMTYPE
+ decode_CMSAttributes
+ decode_CMSCBCParameter
+ decode_CMSEncryptedData
+ decode_CMSIdentifier
+ decode_CMSRC2CBCParameter
+ decode_CMSVersion
+ decode_CommonCriteriaMeasures
+ decode_CommunityIdentifier
+ decode_CommunityIdentifiers
+ decode_CompositePrincipal
+ decode_ContentEncryptionAlgorithmIdentifier
+ decode_ContentInfo
+ decode_ContentType
+ decode_CPSuri
+ decode_CRIAttributeSet
+ decode_CRIExtensions
+ decode_CRIExtensions
+ decode_CRLCertificateList
+ decode_CRLDistributionPoints
+ decode_CRLReason
+ decode_CurrentFWConfig
+ decode_DecryptKeyIdentifier
+ decode_DHNonce
+ decode_DHParameter
+ decode_DHPublicKey
+ decode_DHRepInfo
+ decode_DigestAlgorithmIdentifier
+ decode_DigestAlgorithmIdentifiers
+ decode_DigestError
+ decode_DigestInfo
+ decode_DigestInit
+ decode_DigestInitReply
+ decode_DigestREP
+ decode_DigestRepInner
+ decode_DigestREQ
+ decode_DigestReqInner
+ decode_DigestRequest
+ decode_DigestResponse
+ decode_DigestTypes
+ decode_DirectoryString
+ decode_DisplayText
+ decode_DistributionPoint
+ decode_DistributionPointName
+ decode_DistributionPointReasonFlags
+ decode_DomainParameters
+ decode_DSAParams
+ decode_DSAPublicKey
+ decode_DSASigValue
+ decode_ECDSA_Sig_Value
+ decode_ECParameters
+ decode_ECPoint
+ decode_EKCertificateGenerationLocation
+ decode_EKGenerationLocation
+ decode_EKGenerationType
+ decode_EncAPRepPart
+ decode_EncapsulatedContentInfo
+ decode_EncASRepPart
+ decode_EncKDCRepPart
+ decode_EncKrbCredPart
+ decode_EncKrbPrivPart
+ decode_EncryptedContent
+ decode_EncryptedContentInfo
+ decode_EncryptedData
+ decode_EncryptedKey
+ decode_EncryptionKey
+ decode_EncTGSRepPart
+ decode_EncTicketPart
+ decode_ENCTYPE
+ decode_EnvelopedData
+ decode_ETYPE_INFO
+ decode_ETYPE_INFO2
+ decode_ETYPE_INFO2_ENTRY
+ decode_ETYPE_INFO_ENTRY
+ decode_EtypeList
+ decode_EvaluationAssuranceLevel
+ decode_EvaluationStatus
+ decode_Extension
+ decode_Extensions
+ decode_ExternalPrincipalIdentifier
+ decode_ExternalPrincipalIdentifiers
+ decode_ExtKeyUsage
+ decode_FastOptions
+ decode_FIPSLevel
+ decode_FirmwarePackageIdentifier
+ decode_FirmwarePackageInfo
+ decode_FirmwarePackageLoadError
+ decode_FirmwarePackageLoadErrorCode
+ decode_FirmwarePackageLoadReceipt
+ decode_FirmwarePkgData
+ decode_FWErrorVersion
+ decode_FWReceiptVersion
+ decode_GeneralName
+ decode_GeneralNames
+ decode_GeneralSubtree
+ decode_GeneralSubtrees
+ decode_HardwareModuleName
+ decode_HardwareModules
+ decode_HardwareSerialEntry
+ decode_heim_any
+ decode_HEIM_ANY
+ decode_heim_any_set
+ decode_HEIM_ANY_SET
+ decode_HostAddress
+ decode_HostAddresses
+ decode_ImplementedCompressAlgorithms
+ decode_ImplementedCryptoAlgorithms
+ decode_IOSCertificationRequest
+ decode_IOSCertificationRequest
+ decode_IOSCertificationRequestInfo
+ decode_IOSCertificationRequestInfo
+ decode_IssuerAndSerialNumber
+ decode_KDCDHKeyInfo
+ decode_KDCDHKeyInfo_Win2k
+ decode_KDCFastCookie
+ decode_KDCFastFlags
+ decode_KDCFastState
+ decode_KDCOptions
+ decode_KDC_PROXY_MESSAGE
+ decode_KDC_REP
+ decode_KDC_REQ
+ decode_KDC_REQ_BODY
+ decode_KDFAlgorithmId
+ decode_KERB_AD_RESTRICTION_ENTRY
+ decode_KERB_ARMOR_SERVICE_REPLY
+ decode_KERB_CRED
+ decode_KerberosString
+ decode_KerberosTime
+ decode_KERB_ERROR_DATA
+ decode_KERB_TGS_REP_IN
+ decode_KERB_TGS_REP_OUT
+ decode_KERB_TGS_REQ_IN
+ decode_KERB_TGS_REQ_OUT
+ decode_KERB_TIMES
+ decode_KeyEncryptionAlgorithmIdentifier
+ decode_KeyIdentifier
+ decode_KeyTransRecipientInfo
+ decode_KeyUsage
+ decode_Krb5Int32
+ decode_KRB5PrincipalName
+ decode_Krb5UInt32
+ decode_KRB_CRED
+ decode_KrbCredInfo
+ decode_KRB_ERROR
+ decode_KrbFastArmor
+ decode_KrbFastArmoredRep
+ decode_KrbFastArmoredReq
+ decode_KrbFastFinished
+ decode_KrbFastReq
+ decode_KrbFastResponse
+ decode_KRB_PRIV
+ decode_KRB_SAFE
+ decode_KRB_SAFE_BODY
+ decode_Kx509CSRPlus
+ decode_Kx509ErrorCode
+ decode_KX509_ERROR_CODE
+ decode_Kx509Request
+ decode_Kx509Response
+ decode_LastReq
+ decode_LR_TYPE
+ decode_MessageDigest
+ decode_MESSAGE_TYPE
+ decode_METHOD_DATA
+ decode_MS_UPN_SAN
+ decode_Name
+ decode_NameConstraints
+ decode_NAME_TYPE
+ decode_NoticeReference
+ decode_NTLMInit
+ decode_NTLMInitReply
+ decode_NTLMReply
+ decode_NTLMRequest
+ decode_NTLMRequest2
+ decode_NTLMResponse
+ decode_OCSPBasicOCSPResponse
+ decode_OCSPCertID
+ decode_OCSPCertStatus
+ decode_OCSPInnerRequest
+ decode_OCSPKeyHash
+ decode_OCSPRequest
+ decode_OCSPResponderID
+ decode_OCSPResponse
+ decode_OCSPResponseBytes
+ decode_OCSPResponseData
+ decode_OCSPResponseStatus
+ decode_OCSPSignature
+ decode_OCSPSingleResponse
+ decode_OCSPTBSRequest
+ decode_OCSPVersion
+ decode_OriginatorInfo
+ decode_OtherName
+ decode_PA_DATA
+ decode_PADATA_TYPE
+ decode_PA_ENC_SAM_RESPONSE_ENC
+ decode_PA_ENC_TS_ENC
+ decode_PA_FX_FAST_REPLY
+ decode_PA_FX_FAST_REQUEST
+ decode_PA_KERB_KEY_LIST_REP
+ decode_PA_KERB_KEY_LIST_REQ
+ decode_PA_PAC_OPTIONS
+ decode_PA_PAC_REQUEST
+ decode_PA_PK_AS_REP
+ decode_PA_PK_AS_REP_BTMM
+ decode_PA_PK_AS_REP_Win2k
+ decode_PA_PK_AS_REQ
+ decode_PA_PK_AS_REQ_Win2k
+ decode_PA_S4U_X509_USER
+ decode_PA_S4U2Self
+ decode_PA_SAM_CHALLENGE_2
+ decode_PA_SAM_CHALLENGE_2_BODY
+ decode_PA_SAM_REDIRECT
+ decode_PA_SAM_RESPONSE_2
+ decode_PA_SAM_TYPE
+ decode_PA_ServerReferralData
+ decode_PA_SERVER_REFERRAL_DATA
+ decode_PA_SvrReferralData
+ decode_PermanentIdentifier
+ decode_PKAuthenticator
+ decode_PKAuthenticator_Win2k
+ decode_PKCS12_Attribute
+ decode_PKCS12_Attributes
+ decode_PKCS12_AuthenticatedSafe
+ decode_PKCS12_CertBag
+ decode_PKCS12_MacData
+ decode_PKCS12_OctetString
+ decode_PKCS12_PBEParams
+ decode_PKCS12_PFX
+ decode_PKCS12_SafeBag
+ decode_PKCS12_SafeContents
+ decode_PKCS8Attributes
+ decode_PKCS8EncryptedData
+ decode_PKCS8EncryptedPrivateKeyInfo
+ decode_PKCS8PrivateKey
+ decode_PKCS8PrivateKeyAlgorithmIdentifier
+ decode_PKCS8PrivateKeyInfo
+ decode_PKCS9_BMPString
+ decode_PKCS9_friendlyName
+ decode_PkinitSP80056AOtherInfo
+ decode_PkinitSuppPubInfo
+ decode_PKIXXmppAddr
+ decode_PolicyConstraints
+ decode_PolicyInformation
+ decode_PolicyMapping
+ decode_PolicyMappings
+ decode_PolicyQualifierId
+ decode_PolicyQualifierInfo
+ decode_PolicyQualifierInfos
+ decode_PreferredOrLegacyPackageIdentifier
+ decode_PreferredOrLegacyStalePackageIdentifier
+ decode_PreferredPackageIdentifier
+ decode_Principal
+ decode_PrincipalName
+ decode_Principals
+ decode_PrivateKeyUsagePeriod
+ decode_PROV_SRV_LOCATION
+ decode_ProxyCertInfo
+ decode_ProxyPolicy
+ decode_RDNSequence
+ decode_Realm
+ decode_RecipientIdentifier
+ decode_RecipientInfo
+ decode_RecipientInfos
+ decode_RelativeDistinguishedName
+ decode_ReplyKeyPack
+ decode_ReplyKeyPack_Win2k
+ decode_RSAPrivateKey
+ decode_RSAPublicKey
+ decode_SAMFlags
+ decode_SecurityLevel
+ decode_SignatureAlgorithmIdentifier
+ decode_SignatureValue
+ decode_SignedData
+ decode_SignerIdentifier
+ decode_SignerInfo
+ decode_SignerInfos
+ decode_SingleAttribute
+ decode_SkipCerts
+ decode_SRVName
+ decode_StrengthOfFunction
+ decode_SubjectDirectoryAttributes
+ decode_SubjectInfoAccessSyntax
+ decode_SubjectKeyIdentifier
+ decode_SubjectPublicKeyInfo
+ decode_TargetHardwareIdentifiers
+ decode_TBSCertificate
+ decode_TBSCRLCertList
+ decode_TD_DH_PARAMETERS
+ decode_TD_INVALID_CERTIFICATES
+ decode_TD_TRUSTED_CERTIFIERS
+ decode_TGS_REP
+ decode_TGS_REQ
+ decode_Ticket
+ decode_TicketFlags
+ decode_Time
+ decode_TPMSecurityAssertions
+ decode_TPMSpecification
+ decode_TPMVersion
+ decode_TransitedEncoding
+ decode_TrustedCA
+ decode_TrustedCA_Win2k
+ decode_TypedData
+ decode_TYPED_DATA
+ decode_UniqueIdentifier
+ decode_UnprotectedAttributes
+ decode_URIReference
+ decode_UserNotice
+ decode_ValidationParms
+ decode_Validity
+ decode_VendorLoadErrorCode
+ decode_Version
+ decode_WrappedFirmwareKey
+ decode_X520CommonName
+ decode_X520LocalityName
+ decode_X520name
+ decode_X520OrganizationalUnitName
+ decode_X520OrganizationName
+ decode_X520StateOrProvinceName
+ decode_X690SampleChildInformation
+ decode_X690SampleDate
+ decode_X690SampleEmployeeNumber
+ decode_X690SampleName
+ decode_X690SamplePersonnelRecord
+ der_copy_bit_string
+ der_copy_bmp_string
+ der_copy_generalized_time
+ der_copy_general_string
+ der_copy_heim_integer
+ der_copy_ia5_string
+ der_copy_integer
+ der_copy_integer64
+ der_copy_octet_string
+ der_copy_oid
+ der_copy_printable_string
+ der_copy_universal_string
+ der_copy_unsigned
+ der_copy_unsigned64
+ der_copy_utctime
+ der_copy_utf8string
+ der_copy_visible_string
+ der_find_heim_oid_by_name
+ der_find_heim_oid_by_oid
+ der_find_or_parse_heim_oid
+ der_free_bit_string
+ der_free_bmp_string
+ der_free_generalized_time
+ der_free_general_string
+ der_free_heim_integer
+ der_free_ia5_string
+ der_free_integer
+ der_free_integer64
+ der_free_octet_string
+ der_free_oid
+ der_free_printable_string
+ der_free_universal_string
+ der_free_unsigned
+ der_free_unsigned64
+ der_free_utctime
+ der_free_utf8string
+ der_free_visible_string
+ der_get_bit_string
+ der_get_bmp_string
+ der_get_boolean
+ der_get_class_name
+ der_get_class_num
+ der_get_generalized_time
+ der_get_general_string
+ der_get_heim_integer
+ der_get_ia5_string
+ der_get_integer
+ der_get_integer64
+ der_get_length
+ der_get_octet_string
+ der_get_octet_string_ber
+ der_get_oid
+ der_get_printable_string
+ der_get_tag
+ der_get_tag_name
+ der_get_tag_num
+ der_get_type_name
+ der_get_type_num
+ der_get_universal_string
+ der_get_unsigned
+ der_get_unsigned64
+ der_get_utctime
+ der_get_utf8string
+ der_get_visible_string
+ _der_gmtime
+ der_heim_bit_string_cmp
+ der_heim_bmp_string_cmp
+ der_heim_integer_cmp
+ der_heim_octet_string_cmp
+ der_heim_oid_cmp
+ der_heim_universal_string_cmp
+ der_ia5_string_cmp
+ der_length_bit_string
+ der_length_bmp_string
+ der_length_boolean
+ der_length_enumerated
+ der_length_generalized_time
+ der_length_general_string
+ der_length_heim_integer
+ der_length_ia5_string
+ der_length_integer
+ der_length_integer64
+ der_length_len
+ der_length_octet_string
+ der_length_oid
+ der_length_printable_string
+ der_length_tag
+ der_length_universal_string
+ der_length_unsigned
+ der_length_unsigned64
+ der_length_utctime
+ der_length_utf8string
+ der_length_visible_string
+ der_match_heim_oid_by_name
+ der_match_tag
+ der_match_tag2
+ der_match_tag_and_length
+ der_parse_heim_oid
+ der_parse_hex_heim_integer
+ der_printable_string_cmp
+ der_print_bit_string
+ der_print_bmp_string
+ der_print_boolean
+ der_print_generalized_time
+ der_print_general_string
+ der_print_heim_integer
+ der_print_heim_oid
+ der_print_heim_oid_sym
+ der_print_hex_heim_integer
+ der_print_ia5_string
+ der_print_integer
+ der_print_integer64
+ der_print_octet_string
+ der_print_oid
+ der_print_printable_string
+ der_print_universal_string
+ der_print_unsigned
+ der_print_unsigned64
+ der_print_utctime
+ der_print_utf8string
+ der_print_visible_string
+ der_put_bit_string
+ der_put_bmp_string
+ der_put_boolean
+ der_put_generalized_time
+ der_put_general_string
+ der_put_heim_integer
+ der_put_ia5_string
+ der_put_integer
+ der_put_integer64
+ der_put_length
+ der_put_length_and_tag
+ der_put_octet_string
+ der_put_oid
+ der_put_printable_string
+ der_put_tag
+ der_put_universal_string
+ der_put_unsigned
+ der_put_unsigned64
+ der_put_utctime
+ der_put_utf8string
+ der_put_visible_string
+ der_replace_tag
+ _der_timegm
+ DigestTypes2int
+ DistributionPointReasonFlags2int
+ encode_AccessDescription
+ encode_AD_AND_OR
+ encode_AD_IF_RELEVANT
+ encode_AD_INITIAL_VERIFIED_CAS
+ encode_AD_KDCIssued
+ encode_AD_LoginAlias
+ encode_AD_MANDATORY_FOR_KDC
+ encode_AlgorithmIdentifier
+ encode_AliasIA5String
+ encode_AliasPrintableString
+ encode_AliasUTF8String
+ encode_APOptions
+ encode_AP_REP
+ encode_AP_REQ
+ encode_AS_REP
+ encode_AS_REQ
+ encode_Attribute
+ encode_AttributeSet
+ encode_AttributeType
+ encode_AttributeTypeAndValue
+ encode_AttributeValue
+ encode_AttributeValues
+ encode_AUTHDATA_TYPE
+ encode_Authenticator
+ encode_AuthorityInfoAccessSyntax
+ encode_AuthorityKeyIdentifier
+ encode_AuthorizationData
+ encode_AuthorizationDataElement
+ encode_AuthPack
+ encode_AuthPack_Win2k
+ encode_BaseDistance
+ encode_BasicConstraints
+ encode_Certificate
+ encode_CertificateList
+ encode_CertificatePolicies
+ encode_CertificateRevocationLists
+ encode_Certificates
+ encode_CertificateSerialNumber
+ encode_CertificateSet
+ encode_CertificationRequest
+ encode_CertificationRequestInfo
+ encode_CertPolicyId
+ encode_ChangePasswdDataMS
+ encode_Checksum
+ encode_CKSUMTYPE
+ encode_CMSAttributes
+ encode_CMSCBCParameter
+ encode_CMSEncryptedData
+ encode_CMSIdentifier
+ encode_CMSRC2CBCParameter
+ encode_CMSVersion
+ encode_CommonCriteriaMeasures
+ encode_CommunityIdentifier
+ encode_CommunityIdentifiers
+ encode_CompositePrincipal
+ encode_ContentEncryptionAlgorithmIdentifier
+ encode_ContentInfo
+ encode_ContentType
+ encode_CPSuri
+ encode_CRIAttributeSet
+ encode_CRIExtensions
+ encode_CRIExtensions
+ encode_CRLCertificateList
+ encode_CRLDistributionPoints
+ encode_CRLReason
+ encode_CurrentFWConfig
+ encode_DecryptKeyIdentifier
+ encode_DHNonce
+ encode_DHParameter
+ encode_DHPublicKey
+ encode_DHRepInfo
+ encode_DigestAlgorithmIdentifier
+ encode_DigestAlgorithmIdentifiers
+ encode_DigestError
+ encode_DigestInfo
+ encode_DigestInit
+ encode_DigestInitReply
+ encode_DigestREP
+ encode_DigestRepInner
+ encode_DigestREQ
+ encode_DigestReqInner
+ encode_DigestRequest
+ encode_DigestResponse
+ encode_DigestTypes
+ encode_DirectoryString
+ encode_DisplayText
+ encode_DistributionPoint
+ encode_DistributionPointName
+ encode_DistributionPointReasonFlags
+ encode_DomainParameters
+ encode_DSAParams
+ encode_DSAPublicKey
+ encode_DSASigValue
+ encode_ECDSA_Sig_Value
+ encode_ECParameters
+ encode_ECPoint
+ encode_EKCertificateGenerationLocation
+ encode_EKGenerationLocation
+ encode_EKGenerationType
+ encode_EncAPRepPart
+ encode_EncapsulatedContentInfo
+ encode_EncASRepPart
+ encode_EncKDCRepPart
+ encode_EncKrbCredPart
+ encode_EncKrbPrivPart
+ encode_EncryptedContent
+ encode_EncryptedContentInfo
+ encode_EncryptedData
+ encode_EncryptedKey
+ encode_EncryptionKey
+ encode_EncTGSRepPart
+ encode_EncTicketPart
+ encode_ENCTYPE
+ encode_EnvelopedData
+ encode_ETYPE_INFO
+ encode_ETYPE_INFO2
+ encode_ETYPE_INFO2_ENTRY
+ encode_ETYPE_INFO_ENTRY
+ encode_EtypeList
+ encode_EvaluationAssuranceLevel
+ encode_EvaluationStatus
+ encode_Extension
+ encode_Extensions
+ encode_ExternalPrincipalIdentifier
+ encode_ExternalPrincipalIdentifiers
+ encode_ExtKeyUsage
+ encode_FastOptions
+ encode_FIPSLevel
+ encode_FirmwarePackageIdentifier
+ encode_FirmwarePackageInfo
+ encode_FirmwarePackageLoadError
+ encode_FirmwarePackageLoadErrorCode
+ encode_FirmwarePackageLoadReceipt
+ encode_FirmwarePkgData
+ encode_FWErrorVersion
+ encode_FWReceiptVersion
+ encode_GeneralName
+ encode_GeneralNames
+ encode_GeneralSubtree
+ encode_GeneralSubtrees
+ encode_HardwareModuleName
+ encode_HardwareModules
+ encode_HardwareSerialEntry
+ encode_heim_any
+ encode_HEIM_ANY
+ encode_heim_any_set
+ encode_HEIM_ANY_SET
+ encode_HostAddress
+ encode_HostAddresses
+ encode_ImplementedCompressAlgorithms
+ encode_ImplementedCryptoAlgorithms
+ encode_IOSCertificationRequest
+ encode_IOSCertificationRequest
+ encode_IOSCertificationRequestInfo
+ encode_IOSCertificationRequestInfo
+ encode_IssuerAndSerialNumber
+ encode_KDCDHKeyInfo
+ encode_KDCDHKeyInfo_Win2k
+ encode_KDCFastCookie
+ encode_KDCFastFlags
+ encode_KDCFastState
+ encode_KDCOptions
+ encode_KDC_PROXY_MESSAGE
+ encode_KDC_REP
+ encode_KDC_REQ
+ encode_KDC_REQ_BODY
+ encode_KDFAlgorithmId
+ encode_KERB_AD_RESTRICTION_ENTRY
+ encode_KERB_ARMOR_SERVICE_REPLY
+ encode_KERB_CRED
+ encode_KerberosString
+ encode_KerberosTime
+ encode_KERB_ERROR_DATA
+ encode_KERB_TGS_REP_IN
+ encode_KERB_TGS_REP_OUT
+ encode_KERB_TGS_REQ_IN
+ encode_KERB_TGS_REQ_OUT
+ encode_KERB_TIMES
+ encode_KeyEncryptionAlgorithmIdentifier
+ encode_KeyIdentifier
+ encode_KeyTransRecipientInfo
+ encode_KeyUsage
+ encode_Krb5Int32
+ encode_KRB5PrincipalName
+ encode_Krb5UInt32
+ encode_KRB_CRED
+ encode_KrbCredInfo
+ encode_KRB_ERROR
+ encode_KrbFastArmor
+ encode_KrbFastArmoredRep
+ encode_KrbFastArmoredReq
+ encode_KrbFastFinished
+ encode_KrbFastReq
+ encode_KrbFastResponse
+ encode_KRB_PRIV
+ encode_KRB_SAFE
+ encode_KRB_SAFE_BODY
+ encode_Kx509CSRPlus
+ encode_Kx509ErrorCode
+ encode_KX509_ERROR_CODE
+ encode_Kx509Request
+ encode_Kx509Response
+ encode_LastReq
+ encode_LR_TYPE
+ encode_MessageDigest
+ encode_MESSAGE_TYPE
+ encode_METHOD_DATA
+ encode_MS_UPN_SAN
+ encode_Name
+ encode_NameConstraints
+ encode_NAME_TYPE
+ encode_NoticeReference
+ encode_NTLMInit
+ encode_NTLMInitReply
+ encode_NTLMReply
+ encode_NTLMRequest
+ encode_NTLMRequest2
+ encode_NTLMResponse
+ encode_OCSPBasicOCSPResponse
+ encode_OCSPCertID
+ encode_OCSPCertStatus
+ encode_OCSPInnerRequest
+ encode_OCSPKeyHash
+ encode_OCSPRequest
+ encode_OCSPResponderID
+ encode_OCSPResponse
+ encode_OCSPResponseBytes
+ encode_OCSPResponseData
+ encode_OCSPResponseStatus
+ encode_OCSPSignature
+ encode_OCSPSingleResponse
+ encode_OCSPTBSRequest
+ encode_OCSPVersion
+ encode_OriginatorInfo
+ encode_OtherName
+ encode_PA_DATA
+ encode_PADATA_TYPE
+ encode_PA_ENC_SAM_RESPONSE_ENC
+ encode_PA_ENC_TS_ENC
+ encode_PA_FX_FAST_REPLY
+ encode_PA_FX_FAST_REQUEST
+ encode_PA_KERB_KEY_LIST_REP
+ encode_PA_KERB_KEY_LIST_REQ
+ encode_PA_PAC_OPTIONS
+ encode_PA_PAC_REQUEST
+ encode_PA_PK_AS_REP
+ encode_PA_PK_AS_REP_BTMM
+ encode_PA_PK_AS_REP_Win2k
+ encode_PA_PK_AS_REQ
+ encode_PA_PK_AS_REQ_Win2k
+ encode_PA_S4U_X509_USER
+ encode_PA_S4U2Self
+ encode_PA_SAM_CHALLENGE_2
+ encode_PA_SAM_CHALLENGE_2_BODY
+ encode_PA_SAM_REDIRECT
+ encode_PA_SAM_RESPONSE_2
+ encode_PA_SAM_TYPE
+ encode_PA_ServerReferralData
+ encode_PA_SERVER_REFERRAL_DATA
+ encode_PA_SvrReferralData
+ encode_PermanentIdentifier
+ encode_PKAuthenticator
+ encode_PKAuthenticator_Win2k
+ encode_PKCS12_Attribute
+ encode_PKCS12_Attributes
+ encode_PKCS12_AuthenticatedSafe
+ encode_PKCS12_CertBag
+ encode_PKCS12_MacData
+ encode_PKCS12_OctetString
+ encode_PKCS12_PBEParams
+ encode_PKCS12_PFX
+ encode_PKCS12_SafeBag
+ encode_PKCS12_SafeContents
+ encode_PKCS8Attributes
+ encode_PKCS8EncryptedData
+ encode_PKCS8EncryptedPrivateKeyInfo
+ encode_PKCS8PrivateKey
+ encode_PKCS8PrivateKeyAlgorithmIdentifier
+ encode_PKCS8PrivateKeyInfo
+ encode_PKCS9_BMPString
+ encode_PKCS9_friendlyName
+ encode_PkinitSP80056AOtherInfo
+ encode_PkinitSuppPubInfo
+ encode_PKIXXmppAddr
+ encode_PolicyConstraints
+ encode_PolicyInformation
+ encode_PolicyMapping
+ encode_PolicyMappings
+ encode_PolicyQualifierId
+ encode_PolicyQualifierInfo
+ encode_PolicyQualifierInfos
+ encode_PreferredOrLegacyPackageIdentifier
+ encode_PreferredOrLegacyStalePackageIdentifier
+ encode_PreferredPackageIdentifier
+ encode_Principal
+ encode_PrincipalName
+ encode_Principals
+ encode_PrivateKeyUsagePeriod
+ encode_PROV_SRV_LOCATION
+ encode_ProxyCertInfo
+ encode_ProxyPolicy
+ encode_RDNSequence
+ encode_Realm
+ encode_RecipientIdentifier
+ encode_RecipientInfo
+ encode_RecipientInfos
+ encode_RelativeDistinguishedName
+ encode_ReplyKeyPack
+ encode_ReplyKeyPack_Win2k
+ encode_RSAPrivateKey
+ encode_RSAPublicKey
+ encode_SAMFlags
+ encode_SecurityLevel
+ encode_SignatureAlgorithmIdentifier
+ encode_SignatureValue
+ encode_SignedData
+ encode_SignerIdentifier
+ encode_SignerInfo
+ encode_SignerInfos
+ encode_SingleAttribute
+ encode_SkipCerts
+ encode_SRVName
+ encode_StrengthOfFunction
+ encode_SubjectDirectoryAttributes
+ encode_SubjectInfoAccessSyntax
+ encode_SubjectKeyIdentifier
+ encode_SubjectPublicKeyInfo
+ encode_TargetHardwareIdentifiers
+ encode_TBSCertificate
+ encode_TBSCRLCertList
+ encode_TD_DH_PARAMETERS
+ encode_TD_INVALID_CERTIFICATES
+ encode_TD_TRUSTED_CERTIFIERS
+ encode_TGS_REP
+ encode_TGS_REQ
+ encode_Ticket
+ encode_TicketFlags
+ encode_Time
+ encode_TPMSecurityAssertions
+ encode_TPMSpecification
+ encode_TPMVersion
+ encode_TransitedEncoding
+ encode_TrustedCA
+ encode_TrustedCA_Win2k
+ encode_TypedData
+ encode_TYPED_DATA
+ encode_UniqueIdentifier
+ encode_UnprotectedAttributes
+ encode_URIReference
+ encode_UserNotice
+ encode_ValidationParms
+ encode_Validity
+ encode_VendorLoadErrorCode
+ encode_Version
+ encode_WrappedFirmwareKey
+ encode_X520CommonName
+ encode_X520LocalityName
+ encode_X520name
+ encode_X520OrganizationalUnitName
+ encode_X520OrganizationName
+ encode_X520StateOrProvinceName
+ encode_X690SampleChildInformation
+ encode_X690SampleDate
+ encode_X690SampleEmployeeNumber
+ encode_X690SampleName
+ encode_X690SamplePersonnelRecord
+ FastOptions2int
+ free_AccessDescription
+ free_AD_AND_OR
+ free_AD_IF_RELEVANT
+ free_AD_INITIAL_VERIFIED_CAS
+ free_AD_KDCIssued
+ free_AD_LoginAlias
+ free_AD_MANDATORY_FOR_KDC
+ free_AlgorithmIdentifier
+ free_AliasIA5String
+ free_AliasPrintableString
+ free_AliasUTF8String
+ free_APOptions
+ free_AP_REP
+ free_AP_REQ
+ free_AS_REP
+ free_AS_REQ
+ free_Attribute
+ free_AttributeSet
+ free_AttributeType
+ free_AttributeTypeAndValue
+ free_AttributeValue
+ free_AttributeValues
+ free_AUTHDATA_TYPE
+ free_Authenticator
+ free_AuthorityInfoAccessSyntax
+ free_AuthorityKeyIdentifier
+ free_AuthorizationData
+ free_AuthorizationDataElement
+ free_AuthPack
+ free_AuthPack_Win2k
+ free_BaseDistance
+ free_BasicConstraints
+ free_Certificate
+ free_CertificateList
+ free_CertificatePolicies
+ free_CertificateRevocationLists
+ free_Certificates
+ free_CertificateSerialNumber
+ free_CertificateSet
+ free_CertificationRequest
+ free_CertificationRequestInfo
+ free_CertPolicyId
+ free_ChangePasswdDataMS
+ free_Checksum
+ free_CKSUMTYPE
+ free_CMSAttributes
+ free_CMSCBCParameter
+ free_CMSEncryptedData
+ free_CMSIdentifier
+ free_CMSRC2CBCParameter
+ free_CMSVersion
+ free_CommonCriteriaMeasures
+ free_CommunityIdentifier
+ free_CommunityIdentifiers
+ free_CompositePrincipal
+ free_ContentEncryptionAlgorithmIdentifier
+ free_ContentInfo
+ free_ContentType
+ free_CPSuri
+ free_CRIAttributeSet
+ free_CRIExtensions
+ free_CRIExtensions
+ free_CRLCertificateList
+ free_CRLDistributionPoints
+ free_CRLReason
+ free_CurrentFWConfig
+ free_DecryptKeyIdentifier
+ free_DHNonce
+ free_DHParameter
+ free_DHPublicKey
+ free_DHRepInfo
+ free_DigestAlgorithmIdentifier
+ free_DigestAlgorithmIdentifiers
+ free_DigestError
+ free_DigestInfo
+ free_DigestInit
+ free_DigestInitReply
+ free_DigestREP
+ free_DigestRepInner
+ free_DigestREQ
+ free_DigestReqInner
+ free_DigestRequest
+ free_DigestResponse
+ free_DigestTypes
+ free_DirectoryString
+ free_DisplayText
+ free_DistributionPoint
+ free_DistributionPointName
+ free_DistributionPointReasonFlags
+ free_DomainParameters
+ free_DSAParams
+ free_DSAPublicKey
+ free_DSASigValue
+ free_ECDSA_Sig_Value
+ free_ECParameters
+ free_ECPoint
+ free_EKCertificateGenerationLocation
+ free_EKGenerationLocation
+ free_EKGenerationType
+ free_EncAPRepPart
+ free_EncapsulatedContentInfo
+ free_EncASRepPart
+ free_EncKDCRepPart
+ free_EncKrbCredPart
+ free_EncKrbPrivPart
+ free_EncryptedContent
+ free_EncryptedContentInfo
+ free_EncryptedData
+ free_EncryptedKey
+ free_EncryptionKey
+ free_EncTGSRepPart
+ free_EncTicketPart
+ free_ENCTYPE
+ free_EnvelopedData
+ free_ETYPE_INFO
+ free_ETYPE_INFO2
+ free_ETYPE_INFO2_ENTRY
+ free_ETYPE_INFO_ENTRY
+ free_EtypeList
+ free_EvaluationAssuranceLevel
+ free_EvaluationStatus
+ free_Extension
+ free_Extensions
+ free_ExternalPrincipalIdentifier
+ free_ExternalPrincipalIdentifiers
+ free_ExtKeyUsage
+ free_FastOptions
+ free_FIPSLevel
+ free_FirmwarePackageIdentifier
+ free_FirmwarePackageInfo
+ free_FirmwarePackageLoadError
+ free_FirmwarePackageLoadErrorCode
+ free_FirmwarePackageLoadReceipt
+ free_FirmwarePkgData
+ free_FWErrorVersion
+ free_FWReceiptVersion
+ free_GeneralName
+ free_GeneralNames
+ free_GeneralSubtree
+ free_GeneralSubtrees
+ free_HardwareModuleName
+ free_HardwareModules
+ free_HardwareSerialEntry
+ free_heim_any
+ free_HEIM_ANY
+ free_heim_any_set
+ free_HEIM_ANY_SET
+ free_HostAddress
+ free_HostAddresses
+ free_ImplementedCompressAlgorithms
+ free_ImplementedCryptoAlgorithms
+ free_IOSCertificationRequest
+ free_IOSCertificationRequest
+ free_IOSCertificationRequestInfo
+ free_IOSCertificationRequestInfo
+ free_IssuerAndSerialNumber
+ free_KDCDHKeyInfo
+ free_KDCDHKeyInfo_Win2k
+ free_KDCFastCookie
+ free_KDCFastFlags
+ free_KDCFastState
+ free_KDCOptions
+ free_KDC_PROXY_MESSAGE
+ free_KDC_REP
+ free_KDC_REQ
+ free_KDC_REQ_BODY
+ free_KDFAlgorithmId
+ free_KERB_AD_RESTRICTION_ENTRY
+ free_KERB_ARMOR_SERVICE_REPLY
+ free_KERB_CRED
+ free_KerberosString
+ free_KerberosTime
+ free_KERB_ERROR_DATA
+ free_KERB_TGS_REP_IN
+ free_KERB_TGS_REP_OUT
+ free_KERB_TGS_REQ_IN
+ free_KERB_TGS_REQ_OUT
+ free_KERB_TIMES
+ free_KeyEncryptionAlgorithmIdentifier
+ free_KeyIdentifier
+ free_KeyTransRecipientInfo
+ free_KeyUsage
+ free_Krb5Int32
+ free_KRB5PrincipalName
+ free_Krb5UInt32
+ free_KRB_CRED
+ free_KrbCredInfo
+ free_KRB_ERROR
+ free_KrbFastArmor
+ free_KrbFastArmoredRep
+ free_KrbFastArmoredReq
+ free_KrbFastFinished
+ free_KrbFastReq
+ free_KrbFastResponse
+ free_KRB_PRIV
+ free_KRB_SAFE
+ free_KRB_SAFE_BODY
+ free_Kx509CSRPlus
+ free_Kx509ErrorCode
+ free_KX509_ERROR_CODE
+ free_Kx509Request
+ free_Kx509Response
+ free_LastReq
+ free_LR_TYPE
+ free_MessageDigest
+ free_MESSAGE_TYPE
+ free_METHOD_DATA
+ free_MS_UPN_SAN
+ free_Name
+ free_NameConstraints
+ free_NAME_TYPE
+ free_NoticeReference
+ free_NTLMInit
+ free_NTLMInitReply
+ free_NTLMReply
+ free_NTLMRequest
+ free_NTLMRequest2
+ free_NTLMResponse
+ free_OCSPBasicOCSPResponse
+ free_OCSPCertID
+ free_OCSPCertStatus
+ free_OCSPInnerRequest
+ free_OCSPKeyHash
+ free_OCSPRequest
+ free_OCSPResponderID
+ free_OCSPResponse
+ free_OCSPResponseBytes
+ free_OCSPResponseData
+ free_OCSPResponseStatus
+ free_OCSPSignature
+ free_OCSPSingleResponse
+ free_OCSPTBSRequest
+ free_OCSPVersion
+ free_OriginatorInfo
+ free_OtherName
+ free_PA_DATA
+ free_PADATA_TYPE
+ free_PA_ENC_SAM_RESPONSE_ENC
+ free_PA_ENC_TS_ENC
+ free_PA_FX_FAST_REPLY
+ free_PA_FX_FAST_REQUEST
+ free_PA_KERB_KEY_LIST_REP
+ free_PA_KERB_KEY_LIST_REQ
+ free_PA_PAC_OPTIONS
+ free_PA_PAC_REQUEST
+ free_PA_PK_AS_REP
+ free_PA_PK_AS_REP_BTMM
+ free_PA_PK_AS_REP_Win2k
+ free_PA_PK_AS_REQ
+ free_PA_PK_AS_REQ_Win2k
+ free_PA_S4U_X509_USER
+ free_PA_S4U2Self
+ free_PA_SAM_CHALLENGE_2
+ free_PA_SAM_CHALLENGE_2_BODY
+ free_PA_SAM_REDIRECT
+ free_PA_SAM_RESPONSE_2
+ free_PA_SAM_TYPE
+ free_PA_ServerReferralData
+ free_PA_SERVER_REFERRAL_DATA
+ free_PA_SvrReferralData
+ free_PermanentIdentifier
+ free_PKAuthenticator
+ free_PKAuthenticator_Win2k
+ free_PKCS12_Attribute
+ free_PKCS12_Attributes
+ free_PKCS12_AuthenticatedSafe
+ free_PKCS12_CertBag
+ free_PKCS12_MacData
+ free_PKCS12_OctetString
+ free_PKCS12_PBEParams
+ free_PKCS12_PFX
+ free_PKCS12_SafeBag
+ free_PKCS12_SafeContents
+ free_PKCS8Attributes
+ free_PKCS8EncryptedData
+ free_PKCS8EncryptedPrivateKeyInfo
+ free_PKCS8PrivateKey
+ free_PKCS8PrivateKeyAlgorithmIdentifier
+ free_PKCS8PrivateKeyInfo
+ free_PKCS9_BMPString
+ free_PKCS9_friendlyName
+ free_PkinitSP80056AOtherInfo
+ free_PkinitSuppPubInfo
+ free_PKIXXmppAddr
+ free_PolicyConstraints
+ free_PolicyInformation
+ free_PolicyMapping
+ free_PolicyMappings
+ free_PolicyQualifierId
+ free_PolicyQualifierInfo
+ free_PolicyQualifierInfos
+ free_PreferredOrLegacyPackageIdentifier
+ free_PreferredOrLegacyStalePackageIdentifier
+ free_PreferredPackageIdentifier
+ free_Principal
+ free_PrincipalName
+ free_Principals
+ free_PrivateKeyUsagePeriod
+ free_PROV_SRV_LOCATION
+ free_ProxyCertInfo
+ free_ProxyPolicy
+ free_RDNSequence
+ free_Realm
+ free_RecipientIdentifier
+ free_RecipientInfo
+ free_RecipientInfos
+ free_RelativeDistinguishedName
+ free_ReplyKeyPack
+ free_ReplyKeyPack_Win2k
+ free_RSAPrivateKey
+ free_RSAPublicKey
+ free_SAMFlags
+ free_SecurityLevel
+ free_SignatureAlgorithmIdentifier
+ free_SignatureValue
+ free_SignedData
+ free_SignerIdentifier
+ free_SignerInfo
+ free_SignerInfos
+ free_SingleAttribute
+ free_SkipCerts
+ free_SRVName
+ free_StrengthOfFunction
+ free_SubjectDirectoryAttributes
+ free_SubjectInfoAccessSyntax
+ free_SubjectKeyIdentifier
+ free_SubjectPublicKeyInfo
+ free_TargetHardwareIdentifiers
+ free_TBSCertificate
+ free_TBSCRLCertList
+ free_TD_DH_PARAMETERS
+ free_TD_INVALID_CERTIFICATES
+ free_TD_TRUSTED_CERTIFIERS
+ free_TGS_REP
+ free_TGS_REQ
+ free_Ticket
+ free_TicketFlags
+ free_Time
+ free_TPMSecurityAssertions
+ free_TPMSpecification
+ free_TPMVersion
+ free_TransitedEncoding
+ free_TrustedCA
+ free_TrustedCA_Win2k
+ free_TypedData
+ free_TYPED_DATA
+ free_UniqueIdentifier
+ free_UnprotectedAttributes
+ free_URIReference
+ free_UserNotice
+ free_ValidationParms
+ free_Validity
+ free_VendorLoadErrorCode
+ free_Version
+ free_WrappedFirmwareKey
+ free_X520CommonName
+ free_X520LocalityName
+ free_X520name
+ free_X520OrganizationalUnitName
+ free_X520OrganizationName
+ free_X520StateOrProvinceName
+ free_X690SampleChildInformation
+ free_X690SampleDate
+ free_X690SampleEmployeeNumber
+ free_X690SampleName
+ free_X690SamplePersonnelRecord
+ heim_any_cmp
+ HEIM_ANY_cmp
+ _heim_der_set_sort
+ _heim_fix_dce
+ _heim_len_int
+ _heim_len_int64
+ _heim_len_unsigned
+ _heim_len_unsigned64
+ _heim_time2generalizedtime
+ initialize_asn1_error_table
+ initialize_asn1_error_table_r
+ int2APOptions
+ int2DigestTypes
+ int2DistributionPointReasonFlags
+ int2FastOptions
+ int2KDCFastFlags
+ int2KDCOptions
+ int2KeyUsage
+ int2SAMFlags
+ int2TicketFlags
+ KDCFastFlags2int
+ KDCOptions2int
+ KeyUsage2int
+ length_AccessDescription
+ length_AD_AND_OR
+ length_AD_IF_RELEVANT
+ length_AD_INITIAL_VERIFIED_CAS
+ length_AD_KDCIssued
+ length_AD_LoginAlias
+ length_AD_MANDATORY_FOR_KDC
+ length_AlgorithmIdentifier
+ length_AliasIA5String
+ length_AliasPrintableString
+ length_AliasUTF8String
+ length_APOptions
+ length_AP_REP
+ length_AP_REQ
+ length_AS_REP
+ length_AS_REQ
+ length_Attribute
+ length_AttributeSet
+ length_AttributeType
+ length_AttributeTypeAndValue
+ length_AttributeValue
+ length_AttributeValues
+ length_AUTHDATA_TYPE
+ length_Authenticator
+ length_AuthorityInfoAccessSyntax
+ length_AuthorityKeyIdentifier
+ length_AuthorizationData
+ length_AuthorizationDataElement
+ length_AuthPack
+ length_AuthPack_Win2k
+ length_BaseDistance
+ length_BasicConstraints
+ length_Certificate
+ length_CertificateList
+ length_CertificatePolicies
+ length_CertificateRevocationLists
+ length_Certificates
+ length_CertificateSerialNumber
+ length_CertificateSet
+ length_CertificationRequest
+ length_CertificationRequestInfo
+ length_CertPolicyId
+ length_ChangePasswdDataMS
+ length_Checksum
+ length_CKSUMTYPE
+ length_CMSAttributes
+ length_CMSCBCParameter
+ length_CMSEncryptedData
+ length_CMSIdentifier
+ length_CMSRC2CBCParameter
+ length_CMSVersion
+ length_CommonCriteriaMeasures
+ length_CommunityIdentifier
+ length_CommunityIdentifiers
+ length_CompositePrincipal
+ length_ContentEncryptionAlgorithmIdentifier
+ length_ContentInfo
+ length_ContentType
+ length_CPSuri
+ length_CRIAttributeSet
+ length_CRIExtensions
+ length_CRLCertificateList
+ length_CRLDistributionPoints
+ length_CRLReason
+ length_CurrentFWConfig
+ length_DecryptKeyIdentifier
+ length_DHNonce
+ length_DHParameter
+ length_DHPublicKey
+ length_DHRepInfo
+ length_DigestAlgorithmIdentifier
+ length_DigestAlgorithmIdentifiers
+ length_DigestError
+ length_DigestInfo
+ length_DigestInit
+ length_DigestInitReply
+ length_DigestREP
+ length_DigestRepInner
+ length_DigestREQ
+ length_DigestReqInner
+ length_DigestRequest
+ length_DigestResponse
+ length_DigestTypes
+ length_DirectoryString
+ length_DisplayText
+ length_DistributionPoint
+ length_DistributionPointName
+ length_DistributionPointReasonFlags
+ length_DomainParameters
+ length_DSAParams
+ length_DSAPublicKey
+ length_DSASigValue
+ length_ECDSA_Sig_Value
+ length_ECParameters
+ length_ECPoint
+ length_EKCertificateGenerationLocation
+ length_EKGenerationLocation
+ length_EKGenerationType
+ length_EncAPRepPart
+ length_EncapsulatedContentInfo
+ length_EncASRepPart
+ length_EncKDCRepPart
+ length_EncKrbCredPart
+ length_EncKrbPrivPart
+ length_EncryptedContent
+ length_EncryptedContentInfo
+ length_EncryptedData
+ length_EncryptedKey
+ length_EncryptionKey
+ length_EncTGSRepPart
+ length_EncTicketPart
+ length_ENCTYPE
+ length_EnvelopedData
+ length_ETYPE_INFO
+ length_ETYPE_INFO2
+ length_ETYPE_INFO2_ENTRY
+ length_ETYPE_INFO_ENTRY
+ length_EtypeList
+ length_EvaluationAssuranceLevel
+ length_EvaluationStatus
+ length_Extension
+ length_Extensions
+ length_ExternalPrincipalIdentifier
+ length_ExternalPrincipalIdentifiers
+ length_ExtKeyUsage
+ length_FastOptions
+ length_FIPSLevel
+ length_FirmwarePackageIdentifier
+ length_FirmwarePackageInfo
+ length_FirmwarePackageLoadError
+ length_FirmwarePackageLoadErrorCode
+ length_FirmwarePackageLoadReceipt
+ length_FirmwarePkgData
+ length_FWErrorVersion
+ length_FWReceiptVersion
+ length_GeneralName
+ length_GeneralNames
+ length_GeneralSubtree
+ length_GeneralSubtrees
+ length_HardwareModuleName
+ length_HardwareModules
+ length_HardwareSerialEntry
+ length_heim_any
+ length_HEIM_ANY
+ length_heim_any_set
+ length_HEIM_ANY_SET
+ length_HostAddress
+ length_HostAddresses
+ length_ImplementedCompressAlgorithms
+ length_ImplementedCryptoAlgorithms
+ length_IOSCertificationRequest
+ length_IOSCertificationRequestInfo
+ length_IssuerAndSerialNumber
+ length_KDCDHKeyInfo
+ length_KDCDHKeyInfo_Win2k
+ length_KDCFastCookie
+ length_KDCFastFlags
+ length_KDCFastState
+ length_KDCOptions
+ length_KDC_PROXY_MESSAGE
+ length_KDC_REP
+ length_KDC_REQ
+ length_KDC_REQ_BODY
+ length_KDFAlgorithmId
+ length_KERB_AD_RESTRICTION_ENTRY
+ length_KERB_ARMOR_SERVICE_REPLY
+ length_KERB_CRED
+ length_KerberosString
+ length_KerberosTime
+ length_KERB_ERROR_DATA
+ length_KERB_TGS_REP_IN
+ length_KERB_TGS_REP_OUT
+ length_KERB_TGS_REQ_IN
+ length_KERB_TGS_REQ_OUT
+ length_KERB_TIMES
+ length_KeyEncryptionAlgorithmIdentifier
+ length_KeyIdentifier
+ length_KeyTransRecipientInfo
+ length_KeyUsage
+ length_Krb5Int32
+ length_KRB5PrincipalName
+ length_Krb5UInt32
+ length_KRB_CRED
+ length_KrbCredInfo
+ length_KRB_ERROR
+ length_KrbFastArmor
+ length_KrbFastArmoredRep
+ length_KrbFastArmoredReq
+ length_KrbFastFinished
+ length_KrbFastReq
+ length_KrbFastResponse
+ length_KRB_PRIV
+ length_KRB_SAFE
+ length_KRB_SAFE_BODY
+ length_Kx509CSRPlus
+ length_Kx509ErrorCode
+ length_KX509_ERROR_CODE
+ length_Kx509Request
+ length_Kx509Response
+ length_LastReq
+ length_LR_TYPE
+ length_MessageDigest
+ length_MESSAGE_TYPE
+ length_METHOD_DATA
+ length_MS_UPN_SAN
+ length_Name
+ length_NameConstraints
+ length_NAME_TYPE
+ length_NoticeReference
+ length_NTLMInit
+ length_NTLMInitReply
+ length_NTLMReply
+ length_NTLMRequest
+ length_NTLMRequest2
+ length_NTLMResponse
+ length_OCSPBasicOCSPResponse
+ length_OCSPCertID
+ length_OCSPCertStatus
+ length_OCSPInnerRequest
+ length_OCSPKeyHash
+ length_OCSPRequest
+ length_OCSPResponderID
+ length_OCSPResponse
+ length_OCSPResponseBytes
+ length_OCSPResponseData
+ length_OCSPResponseStatus
+ length_OCSPSignature
+ length_OCSPSingleResponse
+ length_OCSPTBSRequest
+ length_OCSPVersion
+ length_OriginatorInfo
+ length_OtherName
+ length_PA_DATA
+ length_PADATA_TYPE
+ length_PA_ENC_SAM_RESPONSE_ENC
+ length_PA_ENC_TS_ENC
+ length_PA_FX_FAST_REPLY
+ length_PA_FX_FAST_REQUEST
+ length_PA_KERB_KEY_LIST_REP
+ length_PA_KERB_KEY_LIST_REQ
+ length_PA_PAC_OPTIONS
+ length_PA_PAC_REQUEST
+ length_PA_PK_AS_REP
+ length_PA_PK_AS_REP_BTMM
+ length_PA_PK_AS_REP_Win2k
+ length_PA_PK_AS_REQ
+ length_PA_PK_AS_REQ_Win2k
+ length_PA_S4U_X509_USER
+ length_PA_S4U2Self
+ length_PA_SAM_CHALLENGE_2
+ length_PA_SAM_CHALLENGE_2_BODY
+ length_PA_SAM_REDIRECT
+ length_PA_SAM_RESPONSE_2
+ length_PA_SAM_TYPE
+ length_PA_ServerReferralData
+ length_PA_SERVER_REFERRAL_DATA
+ length_PA_SvrReferralData
+ length_PermanentIdentifier
+ length_PKAuthenticator
+ length_PKAuthenticator_Win2k
+ length_PKCS12_Attribute
+ length_PKCS12_Attributes
+ length_PKCS12_AuthenticatedSafe
+ length_PKCS12_CertBag
+ length_PKCS12_MacData
+ length_PKCS12_OctetString
+ length_PKCS12_PBEParams
+ length_PKCS12_PFX
+ length_PKCS12_SafeBag
+ length_PKCS12_SafeContents
+ length_PKCS8Attributes
+ length_PKCS8EncryptedData
+ length_PKCS8EncryptedPrivateKeyInfo
+ length_PKCS8PrivateKey
+ length_PKCS8PrivateKeyAlgorithmIdentifier
+ length_PKCS8PrivateKeyInfo
+ length_PKCS9_BMPString
+ length_PKCS9_friendlyName
+ length_PkinitSP80056AOtherInfo
+ length_PkinitSuppPubInfo
+ length_PKIXXmppAddr
+ length_PolicyConstraints
+ length_PolicyInformation
+ length_PolicyMapping
+ length_PolicyMappings
+ length_PolicyQualifierId
+ length_PolicyQualifierInfo
+ length_PolicyQualifierInfos
+ length_PreferredOrLegacyPackageIdentifier
+ length_PreferredOrLegacyStalePackageIdentifier
+ length_PreferredPackageIdentifier
+ length_Principal
+ length_PrincipalName
+ length_Principals
+ length_PrivateKeyUsagePeriod
+ length_PROV_SRV_LOCATION
+ length_ProxyCertInfo
+ length_ProxyPolicy
+ length_RDNSequence
+ length_Realm
+ length_RecipientIdentifier
+ length_RecipientInfo
+ length_RecipientInfos
+ length_RelativeDistinguishedName
+ length_ReplyKeyPack
+ length_ReplyKeyPack_Win2k
+ length_RSAPrivateKey
+ length_RSAPublicKey
+ length_SAMFlags
+ length_SecurityLevel
+ length_SignatureAlgorithmIdentifier
+ length_SignatureValue
+ length_SignedData
+ length_SignerIdentifier
+ length_SignerInfo
+ length_SignerInfos
+ length_SingleAttribute
+ length_SkipCerts
+ length_SRVName
+ length_StrengthOfFunction
+ length_SubjectDirectoryAttributes
+ length_SubjectInfoAccessSyntax
+ length_SubjectKeyIdentifier
+ length_SubjectPublicKeyInfo
+ length_TargetHardwareIdentifiers
+ length_TBSCertificate
+ length_TBSCRLCertList
+ length_TD_DH_PARAMETERS
+ length_TD_INVALID_CERTIFICATES
+ length_TD_TRUSTED_CERTIFIERS
+ length_TGS_REP
+ length_TGS_REQ
+ length_Ticket
+ length_TicketFlags
+ length_Time
+ length_TPMSecurityAssertions
+ length_TPMSpecification
+ length_TPMVersion
+ length_TransitedEncoding
+ length_TrustedCA
+ length_TrustedCA_Win2k
+ length_TypedData
+ length_TYPED_DATA
+ length_UniqueIdentifier
+ length_UnprotectedAttributes
+ length_URIReference
+ length_UserNotice
+ length_ValidationParms
+ length_Validity
+ length_VendorLoadErrorCode
+ length_Version
+ length_WrappedFirmwareKey
+ length_X520CommonName
+ length_X520LocalityName
+ length_X520name
+ length_X520OrganizationalUnitName
+ length_X520OrganizationName
+ length_X520StateOrProvinceName
+ length_X690SampleChildInformation
+ length_X690SampleDate
+ length_X690SampleEmployeeNumber
+ length_X690SampleName
+ length_X690SamplePersonnelRecord
+ print_AccessDescription
+ print_AD_AND_OR
+ print_AD_IF_RELEVANT
+ print_AD_INITIAL_VERIFIED_CAS
+ print_AD_KDCIssued
+ print_AD_LoginAlias
+ print_AD_MANDATORY_FOR_KDC
+ print_AlgorithmIdentifier
+ print_AliasIA5String
+ print_AliasPrintableString
+ print_AliasUTF8String
+ print_APOptions
+ print_AP_REP
+ print_AP_REQ
+ print_AS_REP
+ print_AS_REQ
+ print_Attribute
+ print_AttributeSet
+ print_AttributeType
+ print_AttributeTypeAndValue
+ print_AttributeValue
+ print_AttributeValues
+ print_AUTHDATA_TYPE
+ print_Authenticator
+ print_AuthorityInfoAccessSyntax
+ print_AuthorityKeyIdentifier
+ print_AuthorizationData
+ print_AuthorizationDataElement
+ print_AuthPack
+ print_AuthPack_Win2k
+ print_BaseDistance
+ print_BasicConstraints
+ print_Certificate
+ print_CertificateList
+ print_CertificatePolicies
+ print_CertificateRevocationLists
+ print_Certificates
+ print_CertificateSerialNumber
+ print_CertificateSet
+ print_CertificationRequest
+ print_CertificationRequestInfo
+ print_CertPolicyId
+ print_ChangePasswdDataMS
+ print_Checksum
+ print_CKSUMTYPE
+ print_CMSAttributes
+ print_CMSCBCParameter
+ print_CMSEncryptedData
+ print_CMSIdentifier
+ print_CMSRC2CBCParameter
+ print_CMSVersion
+ print_CommonCriteriaMeasures
+ print_CommunityIdentifier
+ print_CommunityIdentifiers
+ print_CompositePrincipal
+ print_ContentEncryptionAlgorithmIdentifier
+ print_ContentInfo
+ print_ContentType
+ print_CPSuri
+ print_CRIAttributeSet
+ print_CRIExtensions
+ print_CRIExtensions
+ print_CRLCertificateList
+ print_CRLDistributionPoints
+ print_CRLReason
+ print_CurrentFWConfig
+ print_DecryptKeyIdentifier
+ print_DHNonce
+ print_DHParameter
+ print_DHPublicKey
+ print_DHRepInfo
+ print_DigestAlgorithmIdentifier
+ print_DigestAlgorithmIdentifiers
+ print_DigestError
+ print_DigestInfo
+ print_DigestInit
+ print_DigestInitReply
+ print_DigestREP
+ print_DigestRepInner
+ print_DigestREQ
+ print_DigestReqInner
+ print_DigestRequest
+ print_DigestResponse
+ print_DigestTypes
+ print_DirectoryString
+ print_DisplayText
+ print_DistributionPoint
+ print_DistributionPointName
+ print_DistributionPointReasonFlags
+ print_DomainParameters
+ print_DSAParams
+ print_DSAPublicKey
+ print_DSASigValue
+ print_ECDSA_Sig_Value
+ print_ECParameters
+ print_ECPoint
+ print_EKCertificateGenerationLocation
+ print_EKGenerationLocation
+ print_EKGenerationType
+ print_EncAPRepPart
+ print_EncapsulatedContentInfo
+ print_EncASRepPart
+ print_EncKDCRepPart
+ print_EncKrbCredPart
+ print_EncKrbPrivPart
+ print_EncryptedContent
+ print_EncryptedContentInfo
+ print_EncryptedData
+ print_EncryptedKey
+ print_EncryptionKey
+ print_EncTGSRepPart
+ print_EncTicketPart
+ print_ENCTYPE
+ print_EnvelopedData
+ print_ETYPE_INFO
+ print_ETYPE_INFO2
+ print_ETYPE_INFO2_ENTRY
+ print_ETYPE_INFO_ENTRY
+ print_EtypeList
+ print_EvaluationAssuranceLevel
+ print_EvaluationStatus
+ print_Extension
+ print_Extensions
+ print_ExternalPrincipalIdentifier
+ print_ExternalPrincipalIdentifiers
+ print_ExtKeyUsage
+ print_FastOptions
+ print_FIPSLevel
+ print_FirmwarePackageIdentifier
+ print_FirmwarePackageInfo
+ print_FirmwarePackageLoadError
+ print_FirmwarePackageLoadErrorCode
+ print_FirmwarePackageLoadReceipt
+ print_FirmwarePkgData
+ print_FWErrorVersion
+ print_FWReceiptVersion
+ print_GeneralName
+ print_GeneralNames
+ print_GeneralSubtree
+ print_GeneralSubtrees
+ print_HardwareModuleName
+ print_HardwareModules
+ print_HardwareSerialEntry
+ print_heim_any
+ print_HEIM_ANY
+ print_heim_any_set
+ print_HEIM_ANY_SET
+ print_HostAddress
+ print_HostAddresses
+ print_ImplementedCompressAlgorithms
+ print_ImplementedCryptoAlgorithms
+ print_IOSCertificationRequest
+ print_IOSCertificationRequest
+ print_IOSCertificationRequestInfo
+ print_IOSCertificationRequestInfo
+ print_IssuerAndSerialNumber
+ print_KDCDHKeyInfo
+ print_KDCDHKeyInfo_Win2k
+ print_KDCFastCookie
+ print_KDCFastFlags
+ print_KDCFastState
+ print_KDCOptions
+ print_KDC_PROXY_MESSAGE
+ print_KDC_REP
+ print_KDC_REQ
+ print_KDC_REQ_BODY
+ print_KDFAlgorithmId
+ print_KERB_ARMOR_SERVICE_REPLY
+ print_KERB_CRED
+ print_KerberosString
+ print_KerberosTime
+ print_KERB_ERROR_DATA
+ print_KERB_TGS_REP_IN
+ print_KERB_TGS_REP_OUT
+ print_KERB_TGS_REQ_IN
+ print_KERB_TGS_REQ_OUT
+ print_KERB_TIMES
+ print_KeyEncryptionAlgorithmIdentifier
+ print_KeyIdentifier
+ print_KeyTransRecipientInfo
+ print_KeyUsage
+ print_Krb5Int32
+ print_KRB5PrincipalName
+ print_Krb5UInt32
+ print_KRB_CRED
+ print_KrbCredInfo
+ print_KRB_ERROR
+ print_KrbFastArmor
+ print_KrbFastArmoredRep
+ print_KrbFastArmoredReq
+ print_KrbFastFinished
+ print_KrbFastReq
+ print_KrbFastResponse
+ print_KRB_PRIV
+ print_KRB_SAFE
+ print_KRB_SAFE_BODY
+ print_Kx509CSRPlus
+ print_Kx509ErrorCode
+ print_KX509_ERROR_CODE
+ print_Kx509Request
+ print_Kx509Response
+ print_LastReq
+ print_LR_TYPE
+ print_MessageDigest
+ print_MESSAGE_TYPE
+ print_METHOD_DATA
+ print_MS_UPN_SAN
+ print_Name
+ print_NameConstraints
+ print_NAME_TYPE
+ print_NoticeReference
+ print_NTLMInit
+ print_NTLMInitReply
+ print_NTLMReply
+ print_NTLMRequest
+ print_NTLMRequest2
+ print_NTLMResponse
+ print_OCSPBasicOCSPResponse
+ print_OCSPCertID
+ print_OCSPCertStatus
+ print_OCSPInnerRequest
+ print_OCSPKeyHash
+ print_OCSPRequest
+ print_OCSPResponderID
+ print_OCSPResponse
+ print_OCSPResponseBytes
+ print_OCSPResponseData
+ print_OCSPResponseStatus
+ print_OCSPSignature
+ print_OCSPSingleResponse
+ print_OCSPTBSRequest
+ print_OCSPVersion
+ print_OriginatorInfo
+ print_OtherName
+ print_PA_DATA
+ print_PADATA_TYPE
+ print_PA_ENC_SAM_RESPONSE_ENC
+ print_PA_ENC_TS_ENC
+ print_PA_FX_FAST_REPLY
+ print_PA_FX_FAST_REQUEST
+ print_PA_PAC_REQUEST
+ print_PA_PK_AS_REP
+ print_PA_PK_AS_REP_BTMM
+ print_PA_PK_AS_REP_Win2k
+ print_PA_PK_AS_REQ
+ print_PA_PK_AS_REQ_Win2k
+ print_PA_S4U2Self
+ print_PA_SAM_CHALLENGE_2
+ print_PA_SAM_CHALLENGE_2_BODY
+ print_PA_SAM_REDIRECT
+ print_PA_SAM_RESPONSE_2
+ print_PA_SAM_TYPE
+ print_PA_ServerReferralData
+ print_PA_SERVER_REFERRAL_DATA
+ print_PA_SvrReferralData
+ print_PermanentIdentifier
+ print_PKAuthenticator
+ print_PKAuthenticator_Win2k
+ print_PKCS12_Attribute
+ print_PKCS12_Attributes
+ print_PKCS12_AuthenticatedSafe
+ print_PKCS12_CertBag
+ print_PKCS12_MacData
+ print_PKCS12_OctetString
+ print_PKCS12_PBEParams
+ print_PKCS12_PFX
+ print_PKCS12_SafeBag
+ print_PKCS12_SafeContents
+ print_PKCS8Attributes
+ print_PKCS8EncryptedData
+ print_PKCS8EncryptedPrivateKeyInfo
+ print_PKCS8PrivateKey
+ print_PKCS8PrivateKeyAlgorithmIdentifier
+ print_PKCS8PrivateKeyInfo
+ print_PKCS9_BMPString
+ print_PKCS9_friendlyName
+ print_PkinitSP80056AOtherInfo
+ print_PkinitSuppPubInfo
+ print_PKIXXmppAddr
+ print_PolicyConstraints
+ print_PolicyInformation
+ print_PolicyMapping
+ print_PolicyMappings
+ print_PolicyQualifierId
+ print_PolicyQualifierInfo
+ print_PolicyQualifierInfos
+ print_PreferredOrLegacyPackageIdentifier
+ print_PreferredOrLegacyStalePackageIdentifier
+ print_PreferredPackageIdentifier
+ print_Principal
+ print_PrincipalName
+ print_Principals
+ print_PrivateKeyUsagePeriod
+ print_PROV_SRV_LOCATION
+ print_ProxyCertInfo
+ print_ProxyPolicy
+ print_RDNSequence
+ print_Realm
+ print_RecipientIdentifier
+ print_RecipientInfo
+ print_RecipientInfos
+ print_RelativeDistinguishedName
+ print_ReplyKeyPack
+ print_ReplyKeyPack_Win2k
+ print_RSAPrivateKey
+ print_RSAPublicKey
+ print_SAMFlags
+ print_SecurityLevel
+ print_SignatureAlgorithmIdentifier
+ print_SignatureValue
+ print_SignedData
+ print_SignerIdentifier
+ print_SignerInfo
+ print_SignerInfos
+ print_SingleAttribute
+ print_SkipCerts
+ print_SRVName
+ print_StrengthOfFunction
+ print_SubjectDirectoryAttributes
+ print_SubjectInfoAccessSyntax
+ print_SubjectKeyIdentifier
+ print_SubjectPublicKeyInfo
+ print_TargetHardwareIdentifiers
+ print_TBSCertificate
+ print_TBSCRLCertList
+ print_TD_DH_PARAMETERS
+ print_TD_INVALID_CERTIFICATES
+ print_TD_TRUSTED_CERTIFIERS
+ print_TGS_REP
+ print_TGS_REQ
+ print_Ticket
+ print_TicketFlags
+ print_Time
+ print_TPMSecurityAssertions
+ print_TPMSpecification
+ print_TPMVersion
+ print_TransitedEncoding
+ print_TrustedCA
+ print_TrustedCA_Win2k
+ print_TypedData
+ print_TYPED_DATA
+ print_UniqueIdentifier
+ print_UnprotectedAttributes
+ print_URIReference
+ print_UserNotice
+ print_ValidationParms
+ print_Validity
+ print_VendorLoadErrorCode
+ print_Version
+ print_WrappedFirmwareKey
+ print_X520CommonName
+ print_X520LocalityName
+ print_X520name
+ print_X520OrganizationalUnitName
+ print_X520OrganizationName
+ print_X520StateOrProvinceName
+ print_X690SampleChildInformation
+ print_X690SampleDate
+ print_X690SampleEmployeeNumber
+ print_X690SampleName
+ print_X690SamplePersonnelRecord
+ remove_AttributeValues
+ remove_AuthorizationData
+ remove_CertificatePolicies
+ remove_Certificates
+ remove_CRLDistributionPoints
+ remove_DigestAlgorithmIdentifiers
+ remove_ETYPE_INFO
+ remove_ETYPE_INFO2
+ remove_Extensions
+ remove_GeneralNames
+ remove_METHOD_DATA
+ remove_PolicyMappings
+ remove_PolicyQualifierInfos
+ remove_Principals
+ remove_RDNSequence
+ SAMFlags2int
+ TicketFlags2int
diff --git a/third_party/heimdal/lib/asn1/main.c b/third_party/heimdal/lib/asn1/main.c
new file mode 100644
index 0000000..babcc00
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/main.c
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gen_locl.h"
+#include <getarg.h>
+#include "lex.h"
+
+extern FILE *yyin;
+
+static getarg_strings preserve;
+static getarg_strings seq;
+static getarg_strings decorate;
+
+static int
+strcmp4mergesort_r(const void *ap, const void *bp, void *d)
+{
+ const char *a = *(const char **)ap;
+ const char *b = *(const char **)bp;
+ char sep = *(const char *)d;
+ int cmp;
+
+ if (sep) {
+ const char *sepa = strchr(a, sep);
+ const char *sepb = strchr(b, sep);
+ size_t alen, blen;
+
+ if (sepa == NULL) sepa = a + strlen(a);
+ if (sepb == NULL) sepb = b + strlen(b);
+ alen = sepa - a;
+ blen = sepb - b;
+ cmp = strncmp(a, b, alen > blen ? alen : blen);
+ if (cmp == 0)
+ cmp = alen - blen;
+ } else
+ cmp = strcmp(a, b);
+ if (cmp == 0)
+ return (uintptr_t)ap - (uintptr_t)bp; /* stable sort */
+ return cmp;
+}
+
+static int
+prefix_check(const char *s, const char *p, size_t plen, char sep, int *cmp)
+{
+ if ((*cmp = strncmp(p, s, plen)) == 0 && s[plen] == sep)
+ return 1;
+ if (*cmp == 0)
+ *cmp = 1;
+ return 0;
+}
+
+static ssize_t
+bsearch_strings(struct getarg_strings *strs, const char *p,
+ char sep, ssize_t *more)
+{
+ ssize_t right = (ssize_t)strs->num_strings - 1;
+ ssize_t left = 0;
+ ssize_t plen = 0;
+ int cmp;
+
+ if (sep)
+ plen = strlen(p);
+
+ if (strs->num_strings == 0)
+ return -1;
+
+ if (sep && more && *more > -1) {
+ /* If *more > -1 we're continuing an iteration */
+ if (*more > right)
+ return -1;
+ if (prefix_check(strs->strings[*more], p, plen, sep, &cmp))
+ return (*more)++;
+ (*more)++;
+ return -1;
+ }
+
+ while (left <= right) {
+ ssize_t mid = left + (right - left) / 2;
+
+ if (sep) {
+ int cmp2;
+
+ while (prefix_check(strs->strings[mid], p, plen, sep, &cmp) &&
+ mid > 0 &&
+ prefix_check(strs->strings[mid - 1], p, plen, sep, &cmp2))
+ mid--;
+ } else
+ cmp = strcmp(p, strs->strings[mid]);
+ if (cmp == 0) {
+ if (more)
+ *more = mid + 1;
+ return mid;
+ }
+ if (cmp < 0)
+ right = mid - 1; /* -1 if `p' is smaller than smallest in strs */
+ else
+ left = mid + 1;
+ }
+ return -1;
+}
+
+int
+preserve_type(const char *p)
+{
+ return bsearch_strings(&preserve, p, '\0', 0) > -1;
+}
+
+int
+seq_type(const char *p)
+{
+ return bsearch_strings(&seq, p, '\0', 0) > -1;
+}
+
+/*
+ * Split `s' on `sep' and fill fs[] with pointers to the substrings.
+ *
+ * Only the first substring is to be freed -- the rest share the same
+ * allocation.
+ *
+ * The last element may contain `sep' chars if there are more fields in `s'
+ * than output locations in `fs[]'.
+ */
+static void
+split_str(const char *s, char sep, char ***fs)
+{
+ size_t i;
+
+ fs[0][0] = estrdup(s);
+ for (i = 1; fs[i]; i++) {
+ char *q;
+
+ if ((q = strchr(fs[i-1][0], sep)) == NULL)
+ break;
+ *(q++) = '\0';
+ fs[i][0] = q;
+ }
+ for (; fs[i]; i++)
+ fs[i][0] = NULL;
+}
+
+/*
+ * If `p' is "decorated" with a not-to-be-encoded-or-decoded field,
+ * output the field's typename and fieldname, whether it's optional, whether
+ * it's an ASN.1 type or an "external" type, and if external the names of
+ * functions to copy and free values of that type.
+ */
+int
+decorate_type(const char *p, struct decoration *deco, ssize_t *more)
+{
+ ssize_t i;
+ char **s[7];
+ char *junk = NULL;
+ char *cp;
+
+ deco->first = *more == -1;
+ deco->decorated = 0;
+ deco->field_type = NULL;
+ if ((i = bsearch_strings(&decorate, p, ':', more)) == -1)
+ return 0;
+
+ deco->decorated = 1;
+ deco->opt = deco->ext = deco->ptr = 0;
+ deco->void_star = deco->struct_star = 0;
+ deco->field_name = deco->copy_function_name = deco->free_function_name =
+ deco->header_name = NULL;
+
+ s[0] = &deco->field_type;
+ s[1] = &deco->field_name;
+ s[2] = &deco->copy_function_name;
+ s[3] = &deco->free_function_name;
+ s[4] = &deco->header_name;
+ s[5] = &junk;
+ s[6] = NULL;
+ split_str(decorate.strings[i] + strlen(p) + 1, ':', s);
+
+ if (junk || deco->field_type[0] == '\0' || !deco->field_name ||
+ deco->field_name[0] == '\0' || deco->field_name[0] == '?') {
+ errx(1, "Invalidate type decoration specification: --decorate=\"%s\"",
+ decorate.strings[i]);
+ }
+ if ((cp = strchr(deco->field_name, '?'))) {
+ deco->opt = 1;
+ *cp = '\0';
+ }
+ if (strcmp(deco->field_type, "void*") == 0 ||
+ strcmp(deco->field_type, "void *") == 0) {
+ deco->ext = deco->ptr = deco->void_star = 1;
+ deco->opt = 1;
+ deco->header_name = NULL;
+ } else if (strncmp(deco->field_type, "struct ", sizeof("struct ") - 1) == 0 &&
+ deco->field_type[strlen(deco->field_type) - 1] == '*')
+ deco->ptr = deco->struct_star = 1;
+ if (deco->ptr || deco->copy_function_name)
+ deco->ext = 1;
+ if (deco->ext && deco->copy_function_name && !deco->copy_function_name[0])
+ deco->copy_function_name = NULL;
+ if (deco->ext && deco->free_function_name && !deco->free_function_name[0])
+ deco->free_function_name = NULL;
+ if (deco->header_name && !deco->header_name[0])
+ deco->header_name = NULL;
+ if (deco->ptr)
+ deco->opt = 0;
+ return 1;
+}
+
+static const char *
+my_basename(const char *fn)
+{
+ const char *base, *p;
+
+ for (p = base = fn; *p; p++) {
+#ifdef WIN32
+ if (*p == '/' || *p == '\\')
+ base = p + 1;
+#else
+ if (*p == '/')
+ base = p + 1;
+#endif
+ }
+ return base;
+}
+
+const char *fuzzer_string = "";
+const char *enum_prefix;
+const char *name;
+int prefix_enum;
+int fuzzer_flag;
+int support_ber;
+int template_flag;
+int rfc1510_bitstring;
+int one_code_file;
+char *option_file;
+int parse_units_flag = 1;
+char *type_file_string = "krb5-types.h";
+int original_order;
+int version_flag;
+int help_flag;
+struct getargs args[] = {
+ { "fuzzer", 0, arg_flag, &fuzzer_flag, NULL, NULL },
+ { "template", 0, arg_flag, &template_flag, NULL, NULL },
+ { "prefix-enum", 0, arg_flag, &prefix_enum,
+ "prefix C enum labels for ENUMERATED types and INTEGER types with the "
+ "type's name", NULL },
+ { "enum-prefix", 0, arg_string, &enum_prefix,
+ "prefix for C enum labels for ENUMERATED types and INTEGER types with "
+ "enumerated values", "PREFIX" },
+ { "encode-rfc1510-bit-string", 0, arg_flag, &rfc1510_bitstring,
+ "Use RFC1510 incorrect BIT STRING handling for all BIT STRING types "
+ "in the module", NULL },
+ { "decode-dce-ber", 0, arg_flag, &support_ber,
+ "Allow DCE-style BER on decode", NULL },
+ { "support-ber", 0, arg_flag, &support_ber, "Allow BER on decode", NULL },
+ { "preserve-binary", 0, arg_strings, &preserve,
+ "Names of types for which to generate _save fields, saving original "
+ "encoding, in containing structures (useful for signature "
+ "verification)", "TYPE" },
+ { "sequence", 0, arg_strings, &seq,
+ "Generate add/remove functions for SEQUENCE OF types", "TYPE" },
+ { "decorate", 0, arg_strings, &decorate,
+ "Generate private field for SEQUENCE/SET type", "DECORATION" },
+ { "one-code-file", 0, arg_flag, &one_code_file, NULL, NULL },
+ { "gen-name", 0, arg_string, &name,
+ "Name of generated module", "NAME" },
+ { "option-file", 0, arg_string, &option_file,
+ "File with additional compiler CLI options", "FILE" },
+ { "original-order", 0, arg_flag, &original_order,
+ "Define C types and functions in the order in which they appear in "
+ "the ASN.1 module instead of topologically sorting types. This "
+ "is useful for comparing output to earlier compiler versions.",
+ NULL },
+ { "parse-units", 0, arg_negative_flag, &parse_units_flag,
+ "Do not generate roken-style units", NULL },
+ { "type-file", 0, arg_string, &type_file_string,
+ "Name of a C header file to generate includes of for base types",
+ "FILE" },
+ { "version", 0, arg_flag, &version_flag, NULL, NULL },
+ { "help", 0, arg_flag, &help_flag, NULL, NULL }
+};
+int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int code)
+{
+ if (code)
+ dup2(STDERR_FILENO, STDOUT_FILENO);
+ else
+ dup2(STDOUT_FILENO, STDERR_FILENO);
+ arg_printusage(args, num_args, NULL, "[asn1-file [name]]");
+ fprintf(stderr,
+ "\nA DECORATION is one of:\n\n"
+ "\tTYPE:FTYPE:fname[?]\n"
+ "\tTYPE:FTYPE:fname[?]:[copy_function]:[free_function]:header\n"
+ "\tTYPE:void:fname:::\n"
+ "\nSee the manual page.\n");
+ exit(code);
+}
+
+int error_flag;
+
+int
+main(int argc, char **argv)
+{
+ int ret;
+ const char *file;
+ FILE *opt = NULL;
+ int optidx = 0;
+ char **arg = NULL;
+ size_t len = 0;
+ size_t sz = 0;
+ int i;
+
+ setprogname(argv[0]);
+ if (getarg(args, num_args, argc, argv, &optidx))
+ usage(1);
+ if (help_flag)
+ usage(0);
+ if (version_flag) {
+ print_version(NULL);
+ exit(0);
+ }
+ if (argc == optidx) {
+ /* Compile the module on stdin */
+ file = "stdin";
+ name = "stdin";
+ yyin = stdin;
+ } else {
+ /* Compile a named module */
+ file = argv[optidx];
+
+ /*
+ * If the .asn1 stem is not given, then assume it, and also assume
+ * --option-file was given if the .opt file exists
+ */
+ if (strchr(file, '.') == NULL) {
+ char *s = NULL;
+
+ if (asprintf(&s, "%s.opt", file) == -1 || s == NULL)
+ err(1, "Out of memory");
+ if ((opt = fopen(s, "r")))
+ option_file = s;
+ else
+ free(s);
+ if (asprintf(&s, "%s.asn1", file) == -1 || s == NULL)
+ err(1, "Out of memory");
+ file = s;
+ }
+ yyin = fopen (file, "r");
+ if (yyin == NULL)
+ err (1, "open %s", file);
+ if (argc == optidx + 1) {
+ char *p;
+
+ /* C module name substring not given; derive from file name */
+ name = my_basename(estrdup(file));
+ p = strrchr(name, '.');
+ if (p)
+ *p = '\0';
+ } else
+ name = argv[optidx + 1];
+ }
+
+ /*
+ * Parse extra options file
+ */
+ if (option_file) {
+ char buf[1024];
+
+ if (opt == NULL &&
+ (opt = fopen(option_file, "r")) == NULL)
+ err(1, "Could not open given option file %s", option_file);
+
+ arg = calloc(2, sizeof(arg[0]));
+ if (arg == NULL) {
+ perror("calloc");
+ exit(1);
+ }
+ arg[0] = option_file;
+ arg[1] = NULL;
+ len = 1;
+ sz = 2;
+
+ while (fgets(buf, sizeof(buf), opt) != NULL) {
+ size_t buflen, ws;
+
+ buf[strcspn(buf, "\n\r")] = '\0';
+
+ buflen = strlen(buf);
+ if ((ws = strspn(buf, " \t")))
+ memmove(buf, buf + ws, buflen - ws);
+ if (buf[0] == '\0' || buf[0] == '#')
+ continue;
+
+ if (len + 1 >= sz) {
+ arg = realloc(arg, (sz + (sz>>1) + 2) * sizeof(arg[0]));
+ if (arg == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ sz += (sz>>1) + 2;
+ }
+ arg[len] = strdup(buf);
+ if (arg[len] == NULL) {
+ perror("strdup");
+ exit(1);
+ }
+ arg[len + 1] = NULL;
+ len++;
+ }
+ fclose(opt);
+
+ optidx = 0;
+ if(getarg(args, num_args, len, arg, &optidx))
+ usage(1);
+
+ if (len != optidx) {
+ fprintf(stderr, "extra args");
+ exit(1);
+ }
+ }
+
+ if (fuzzer_flag) {
+ if (!template_flag) {
+ printf("can't do fuzzer w/o --template");
+ exit(1);
+ }
+#ifdef ASN1_FUZZER
+ fuzzer_string = "_fuzzer";
+#endif
+ }
+
+ if (preserve.num_strings)
+ mergesort_r(preserve.strings, preserve.num_strings,
+ sizeof(preserve.strings[0]), strcmp4mergesort_r, "");
+ if (seq.num_strings)
+ mergesort_r(seq.strings, seq.num_strings, sizeof(seq.strings[0]),
+ strcmp4mergesort_r, "");
+ if (decorate.num_strings)
+ mergesort_r(decorate.strings, decorate.num_strings,
+ sizeof(decorate.strings[0]), strcmp4mergesort_r, ":");
+
+ init_generate(file, name);
+
+ if (one_code_file)
+ generate_header_of_codefile(name);
+
+ initsym ();
+ ret = yyparse ();
+ if(ret != 0 || error_flag != 0)
+ exit(1);
+ if (!original_order)
+ generate_types();
+ if (argc != optidx)
+ fclose(yyin);
+
+ if (one_code_file)
+ close_codefile();
+ close_generate();
+
+ if (arg) {
+ for (i = 1; i < len; i++)
+ free(arg[i]);
+ free(arg);
+ }
+
+ return 0;
+}
diff --git a/third_party/heimdal/lib/asn1/ocsp.asn1 b/third_party/heimdal/lib/asn1/ocsp.asn1
new file mode 100644
index 0000000..eb090a4
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/ocsp.asn1
@@ -0,0 +1,113 @@
+-- From rfc2560
+-- $Id$
+OCSP DEFINITIONS EXPLICIT TAGS::=
+
+BEGIN
+
+IMPORTS
+ Certificate, AlgorithmIdentifier, CRLReason,
+ Name, GeneralName, CertificateSerialNumber, Extensions
+ FROM rfc2459;
+
+OCSPVersion ::= INTEGER { ocsp-v1(0) }
+
+OCSPCertStatus ::= CHOICE {
+ good [0] IMPLICIT NULL,
+ revoked [1] IMPLICIT -- OCSPRevokedInfo -- SEQUENCE {
+ revocationTime GeneralizedTime,
+ revocationReason[0] EXPLICIT CRLReason OPTIONAL
+ },
+ unknown [2] IMPLICIT NULL }
+
+OCSPCertID ::= SEQUENCE {
+ hashAlgorithm AlgorithmIdentifier,
+ issuerNameHash OCTET STRING, -- Hash of Issuer's DN
+ issuerKeyHash OCTET STRING, -- Hash of Issuers public key
+ serialNumber CertificateSerialNumber }
+
+OCSPSingleResponse ::= SEQUENCE {
+ certID OCSPCertID,
+ certStatus OCSPCertStatus,
+ thisUpdate GeneralizedTime,
+ nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
+ singleExtensions [1] EXPLICIT Extensions OPTIONAL }
+
+OCSPInnerRequest ::= SEQUENCE {
+ reqCert OCSPCertID,
+ singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL }
+
+OCSPTBSRequest ::= SEQUENCE {
+ version [0] EXPLICIT OCSPVersion -- DEFAULT v1 -- OPTIONAL,
+ requestorName [1] EXPLICIT GeneralName OPTIONAL,
+ requestList SEQUENCE OF OCSPInnerRequest,
+ requestExtensions [2] EXPLICIT Extensions OPTIONAL }
+
+OCSPSignature ::= SEQUENCE {
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING,
+ certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+
+OCSPRequest ::= SEQUENCE {
+ tbsRequest OCSPTBSRequest,
+ optionalSignature [0] EXPLICIT OCSPSignature OPTIONAL }
+
+OCSPResponseBytes ::= SEQUENCE {
+ responseType OBJECT IDENTIFIER,
+ response OCTET STRING }
+
+OCSPResponseStatus ::= ENUMERATED {
+ successful (0), --Response has valid confirmations
+ malformedRequest (1), --Illegal confirmation request
+ internalError (2), --Internal error in issuer
+ tryLater (3), --Try again later
+ --(4) is not used
+ sigRequired (5), --Must sign the request
+ unauthorized (6) --Request unauthorized
+}
+
+OCSPResponse ::= SEQUENCE {
+ responseStatus OCSPResponseStatus,
+ responseBytes [0] EXPLICIT OCSPResponseBytes OPTIONAL }
+
+OCSPKeyHash ::= OCTET STRING --SHA-1 hash of responder's public key
+ --(excluding the tag and length fields)
+
+OCSPResponderID ::= CHOICE {
+ byName [1] Name,
+ byKey [2] OCSPKeyHash }
+
+OCSPResponseData ::= SEQUENCE {
+ version [0] EXPLICIT OCSPVersion -- DEFAULT v1 -- OPTIONAL,
+ responderID OCSPResponderID,
+ producedAt GeneralizedTime,
+ responses SEQUENCE OF OCSPSingleResponse,
+ responseExtensions [1] EXPLICIT Extensions OPTIONAL }
+
+OCSPBasicOCSPResponse ::= SEQUENCE {
+ tbsResponseData OCSPResponseData,
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING,
+ certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+
+-- ArchiveCutoff ::= GeneralizedTime
+
+-- AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER
+
+-- Object Identifiers
+
+id-pkix-ocsp OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) dod(6) internet(1)
+ security(5) mechanisms(5) pkix(7) pkix-ad(48) 1
+}
+
+id-pkix-ocsp-basic OBJECT IDENTIFIER ::= { id-pkix-ocsp 1 }
+id-pkix-ocsp-nonce OBJECT IDENTIFIER ::= { id-pkix-ocsp 2 }
+-- id-pkix-ocsp-crl OBJECT IDENTIFIER ::= { id-pkix-ocsp 3 }
+-- id-pkix-ocsp-response OBJECT IDENTIFIER ::= { id-pkix-ocsp 4 }
+-- id-pkix-ocsp-nocheck OBJECT IDENTIFIER ::= { id-pkix-ocsp 5 }
+-- id-pkix-ocsp-archive-cutoff OBJECT IDENTIFIER ::= { id-pkix-ocsp 6 }
+-- id-pkix-ocsp-service-locator OBJECT IDENTIFIER ::= { id-pkix-ocsp 7 }
+
+
+END
+
diff --git a/third_party/heimdal/lib/asn1/ocsp.opt b/third_party/heimdal/lib/asn1/ocsp.opt
new file mode 100644
index 0000000..697aa03
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/ocsp.opt
@@ -0,0 +1,2 @@
+--preserve-binary=OCSPTBSRequest
+--preserve-binary=OCSPResponseData
diff --git a/third_party/heimdal/lib/asn1/oid_resolution.c b/third_party/heimdal/lib/asn1/oid_resolution.c
new file mode 100644
index 0000000..db11b11
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/oid_resolution.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2019 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+#include <hex.h>
+
+#include "cms_asn1.h"
+#include "crmf_asn1.h"
+#include "digest_asn1.h"
+#include "krb5_asn1.h"
+#include "kx509_asn1.h"
+#include "ocsp_asn1.h"
+#include "pkcs10_asn1.h"
+#include "pkcs12_asn1.h"
+#include "pkcs8_asn1.h"
+#include "pkcs9_asn1.h"
+#include "pkinit_asn1.h"
+#include "rfc2459_asn1.h"
+#include "rfc4108_asn1.h"
+
+
+struct sym_oid {
+ const char *sym;
+ const heim_oid *oid;
+};
+
+#ifndef WIN32
+#define DEFINE_OID_WITH_NAME(sym) \
+ { #sym, &asn1_oid_ ## sym },
+
+static const struct sym_oid sym_oids[] = {
+#include "cms_asn1_oids.c"
+#include "crmf_asn1_oids.c"
+#include "digest_asn1_oids.c"
+#include "krb5_asn1_oids.c"
+#include "kx509_asn1_oids.c"
+#include "ocsp_asn1_oids.c"
+#include "pkcs10_asn1_oids.c"
+#include "pkcs12_asn1_oids.c"
+#include "pkcs8_asn1_oids.c"
+#include "pkcs9_asn1_oids.c"
+#include "pkinit_asn1_oids.c"
+#include "rfc2459_asn1_oids.c"
+#include "rfc4108_asn1_oids.c"
+};
+
+static size_t num_sym_oids = sizeof(sym_oids) / sizeof(sym_oids[0]);
+
+#undef DEFINE_OID_WITH_NAME
+
+#define init_sym_oids()
+
+#else
+
+/*
+ * We can't use C99 non-literal initializers for static objects in the Windows
+ * build...
+ */
+
+static struct sym_oid *sym_oids;
+static size_t num_sym_oids;
+
+#define DEFINE_OID_WITH_NAME(sym) (c++);
+static size_t
+count_sym_oids(void)
+{
+ size_t c = 0;
+#include "cms_asn1_oids.c"
+#include "crmf_asn1_oids.c"
+#include "digest_asn1_oids.c"
+#include "krb5_asn1_oids.c"
+#include "kx509_asn1_oids.c"
+#include "ocsp_asn1_oids.c"
+#include "pkcs10_asn1_oids.c"
+#include "pkcs12_asn1_oids.c"
+#include "pkcs8_asn1_oids.c"
+#include "pkcs9_asn1_oids.c"
+#include "pkinit_asn1_oids.c"
+#include "rfc2459_asn1_oids.c"
+ return c;
+}
+#undef DEFINE_OID_WITH_NAME
+
+#define DEFINE_OID_WITH_NAME(s) \
+ tmp[i].sym = #s; \
+ tmp[i++].oid = &asn1_oid_ ## s;
+
+static void
+init_sym_oids(void)
+{
+ static struct sym_oid *tmp;
+ size_t i = 0;
+ size_t c;
+
+ if (!sym_oids &&
+ (c = count_sym_oids()) &&
+ (tmp = calloc(c, sizeof(tmp[0])))) {
+#include "cms_asn1_oids.c"
+#include "crmf_asn1_oids.c"
+#include "digest_asn1_oids.c"
+#include "krb5_asn1_oids.c"
+#include "kx509_asn1_oids.c"
+#include "ocsp_asn1_oids.c"
+#include "pkcs10_asn1_oids.c"
+#include "pkcs12_asn1_oids.c"
+#include "pkcs8_asn1_oids.c"
+#include "pkcs9_asn1_oids.c"
+#include "pkinit_asn1_oids.c"
+#include "rfc2459_asn1_oids.c"
+ num_sym_oids = c;
+ sym_oids = tmp;
+ }
+}
+#undef DEFINE_OID_WITH_NAME
+
+#endif
+
+static struct sym_oid *sym_oids_sorted_by_name;
+static struct sym_oid *sym_oids_sorted_by_oid;
+
+static int
+sym_cmp_name(const void *va, const void *vb)
+{
+ const struct sym_oid *a = va;
+ const struct sym_oid *b = vb;
+
+ return (strcmp(a->sym, b->sym));
+}
+
+static int
+sym_cmp_oid(const void *va, const void *vb)
+{
+ const struct sym_oid *a = va;
+ const struct sym_oid *b = vb;
+
+ return der_heim_oid_cmp(a->oid, b->oid);
+}
+
+static struct sym_oid *
+sort_sym_oids(int (*cmp)(const void *, const void *))
+{
+ struct sym_oid *tmp;
+
+ init_sym_oids();
+ if ((tmp = calloc(num_sym_oids, sizeof(tmp[0]))) == NULL)
+ return NULL;
+
+ memcpy(tmp, sym_oids, num_sym_oids * sizeof(tmp[0]));
+ qsort(tmp, num_sym_oids, sizeof(struct sym_oid), cmp);
+ return tmp;
+}
+
+static int
+fix_oid_name(const char **namep, char **freeme)
+{
+ char *dash = strchr(*namep, '-');
+
+ *freeme = NULL;
+ if (dash == NULL)
+ return 0;
+ if ((*freeme = strdup(*namep)) == NULL)
+ return ENOMEM;
+ *namep = *freeme;
+ for (dash = strchr(*namep, '-'); dash; dash = strchr(dash, '-'))
+ *dash = '_';
+ return 0;
+}
+
+int ASN1CALL
+der_find_heim_oid_by_name(const char *str, const heim_oid **oid)
+{
+ size_t right = num_sym_oids - 1;
+ size_t left = 0;
+ char *s = NULL;
+ int ret;
+
+ *oid = NULL;
+ if (sym_oids_sorted_by_name == NULL &&
+ (sym_oids_sorted_by_name = sort_sym_oids(sym_cmp_name)) == NULL)
+ return ENOMEM;
+
+ if ((ret = fix_oid_name(&str, &s)))
+ return ret;
+
+ while (left <= right) {
+ size_t mid = left + (right - left) / 2;
+ int cmp;
+
+ cmp = strcmp(str, sym_oids_sorted_by_name[mid].sym);
+ if (cmp == 0) {
+ *oid = sym_oids_sorted_by_name[mid].oid;
+ free(s);
+ return 0;
+ }
+ if (cmp < 0 && mid > 0) {/* avoid underflow */
+ right = mid - 1;
+ } else if (cmp < 0) {
+ free(s);
+ return -1;
+ } else {
+ left = mid + 1;
+ }
+ }
+ free(s);
+ return -1;
+}
+
+int ASN1CALL
+der_find_or_parse_heim_oid(const char *str, const char *sep, heim_oid *oid)
+{
+ const heim_oid *found = NULL;
+
+ switch (der_find_heim_oid_by_name(str, &found)) {
+ case 0: return der_copy_oid(found, oid);
+ case -1: return der_parse_heim_oid(str, sep, oid);
+ default: return ENOMEM;
+ }
+}
+
+int ASN1CALL
+der_find_heim_oid_by_oid(const heim_oid *oid, const char **name)
+{
+ size_t right = num_sym_oids;
+ size_t left = 0;
+
+ *name = NULL;
+ if (sym_oids_sorted_by_oid == NULL &&
+ (sym_oids_sorted_by_oid = sort_sym_oids(sym_cmp_oid)) == NULL)
+ return ENOMEM;
+
+ while (left <= right) {
+ size_t mid = (left + right) >> 1;
+ int cmp;
+
+ cmp = der_heim_oid_cmp(oid, sym_oids_sorted_by_oid[mid].oid);
+ if (cmp == 0) {
+ *name = sym_oids_sorted_by_oid[mid].sym;
+ return 0;
+ }
+ if (cmp < 0 && mid)
+ right = mid - 1;
+ else if (cmp < 0)
+ return -1;
+ else if (mid < num_sym_oids - 1)
+ left = mid + 1;
+ else
+ return -1;
+ }
+ return -1;
+}
+
+int ASN1CALL
+der_match_heim_oid_by_name(const char *str, int *c, const heim_oid **oid)
+{
+ size_t i;
+ char *s = NULL;
+ int ret;
+
+ if ((ret = fix_oid_name(&str, &s)))
+ return ret;
+
+ if (*c < 0)
+ *c = 0;
+
+ init_sym_oids();
+ for (i = (size_t)*c; i < num_sym_oids; i++) {
+ /*
+ * XXX We need a lib/roken strcasestr(), or maybe we should support
+ * globbing here.
+ */
+ if (strstr(sym_oids[i].sym, str)) {
+ *oid = sym_oids[i].oid;
+ free(s);
+ if (i >= INT_MAX)
+ return -1;
+ *c = i + 1; /* num_sym_oids is much less than INT_MAX */
+ return 0;
+ }
+ }
+ free(s);
+ return -1;
+}
+
+/* Warning: der_print_heim_oid_sym() will not round-trip */
+
+int ASN1CALL
+der_print_heim_oid_sym(const heim_oid *oid, char delim, char **strp)
+{
+ const char *sym;
+ char *s1 = NULL;
+ char *s2 = NULL;
+ char *p;
+ int ret;
+
+ if (der_find_heim_oid_by_oid(oid, &sym))
+ return der_print_heim_oid(oid, delim, strp);
+
+ if ((ret = der_print_heim_oid(oid, delim, &s1)))
+ return ret;
+ if (asprintf(&s2, "%s (%s)", s1, sym) == -1 || s2 == NULL) {
+ *strp = s1;
+ return 0;
+ }
+ for (p = s2 + strlen(s1) + 1; *p; p++) {
+ if (*p == '_')
+ *p = '-';
+ }
+ *strp = s2;
+ free(s1);
+ return 0;
+}
diff --git a/third_party/heimdal/lib/asn1/pkcs10.asn1 b/third_party/heimdal/lib/asn1/pkcs10.asn1
new file mode 100644
index 0000000..04cda4e
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/pkcs10.asn1
@@ -0,0 +1,64 @@
+-- $Id$
+PKCS10 DEFINITIONS ::=
+
+BEGIN
+
+IMPORTS
+ Name, SubjectPublicKeyInfo, AlgorithmIdentifier, Attribute, Extensions
+ FROM rfc2459
+ HEIM_ANY FROM heim;
+
+PKCS10-Version ::= INTEGER { pkcs10-v1(0) }
+
+CertificationRequestInfo ::= SEQUENCE {
+ version PKCS10-Version,
+ subject Name,
+ subjectPKInfo SubjectPublicKeyInfo,
+ attributes [0] IMPLICIT SET OF Attribute OPTIONAL
+}
+
+CertificationRequest ::= SEQUENCE {
+ certificationRequestInfo CertificationRequestInfo,
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING
+}
+
+IOSCertificationRequestInfo ::= SEQUENCE {
+ version PKCS10-Version,
+ subject Name,
+ subjectPKInfo SubjectPublicKeyInfo,
+ attributes [0] IMPLICIT SET OF CRIAttributeSet OPTIONAL
+}
+
+IOSCertificationRequest ::= SEQUENCE {
+ certificationRequestInfo IOSCertificationRequestInfo,
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING
+}
+
+-- Copied from rfc2459.asn1 because we can't IMPORT classes and parameterized
+-- types yet.
+_ATTRIBUTE ::= CLASS {
+ &id OBJECT IDENTIFIER UNIQUE,
+ &Type OPTIONAL,
+ &minCount INTEGER DEFAULT 1,
+ &maxCount INTEGER OPTIONAL
+}
+
+id-pkcs9-extReq-copy OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) 14
+}
+
+-- Workaround compiler limitation:
+CRIExtensions ::= Extensions
+
+at-extReq _ATTRIBUTE ::= { &Type CRIExtensions, &id id-pkcs9-extReq-copy }
+CRIAttributes _ATTRIBUTE ::= { at-extReq }
+CRIAttributeSet{_ATTRIBUTE:AttrSet} ::= SEQUENCE {
+ type _ATTRIBUTE.&id({AttrSet}),
+ values SET --SIZE (1..MAX)-- OF _ATTRIBUTE.&Type({AttrSet}{@type})
+}
+CRIAttributeSet ::= CRIAttributeSet{CRIAttributes}
+
+END
+
diff --git a/third_party/heimdal/lib/asn1/pkcs10.opt b/third_party/heimdal/lib/asn1/pkcs10.opt
new file mode 100644
index 0000000..499fab2
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/pkcs10.opt
@@ -0,0 +1 @@
+--preserve-binary=CertificationRequestInfo
diff --git a/third_party/heimdal/lib/asn1/pkcs12.asn1 b/third_party/heimdal/lib/asn1/pkcs12.asn1
new file mode 100644
index 0000000..61d3e2c
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/pkcs12.asn1
@@ -0,0 +1,81 @@
+-- $Id$ --
+
+PKCS12 DEFINITIONS ::=
+
+BEGIN
+
+IMPORTS ContentInfo FROM cms
+ DigestInfo FROM rfc2459
+ HEIM_ANY, HEIM_ANY_SET FROM heim;
+
+-- The PFX PDU
+
+id-pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
+ rsadsi(113549) pkcs(1) pkcs-12(12) }
+
+id-pkcs-12PbeIds OBJECT IDENTIFIER ::= { id-pkcs-12 1}
+id-pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= { id-pkcs-12PbeIds 1}
+id-pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= { id-pkcs-12PbeIds 2}
+id-pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= { id-pkcs-12PbeIds 3}
+id-pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= { id-pkcs-12PbeIds 4}
+id-pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= { id-pkcs-12PbeIds 5}
+id-pbewithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= { id-pkcs-12PbeIds 6}
+
+id-pkcs12-bagtypes OBJECT IDENTIFIER ::= { id-pkcs-12 10 1}
+
+id-pkcs12-keyBag OBJECT IDENTIFIER ::= { id-pkcs12-bagtypes 1 }
+id-pkcs12-pkcs8ShroudedKeyBag OBJECT IDENTIFIER ::= { id-pkcs12-bagtypes 2 }
+id-pkcs12-certBag OBJECT IDENTIFIER ::= { id-pkcs12-bagtypes 3 }
+id-pkcs12-crlBag OBJECT IDENTIFIER ::= { id-pkcs12-bagtypes 4 }
+id-pkcs12-secretBag OBJECT IDENTIFIER ::= { id-pkcs12-bagtypes 5 }
+id-pkcs12-safeContentsBag OBJECT IDENTIFIER ::= { id-pkcs12-bagtypes 6 }
+
+
+PKCS12-MacData ::= SEQUENCE {
+ mac DigestInfo,
+ macSalt OCTET STRING,
+ iterations INTEGER OPTIONAL
+}
+
+PKCS12-PFX ::= SEQUENCE {
+ version INTEGER,
+ authSafe ContentInfo,
+ macData PKCS12-MacData OPTIONAL
+}
+
+PKCS12-AuthenticatedSafe ::= SEQUENCE OF ContentInfo
+ -- Data if unencrypted
+ -- EncryptedData if password-encrypted
+ -- EnvelopedData if public key-encrypted
+
+PKCS12-Attribute ::= SEQUENCE {
+ attrId OBJECT IDENTIFIER,
+ attrValues -- SET OF -- HEIM_ANY_SET
+}
+
+PKCS12-Attributes ::= SET OF PKCS12-Attribute
+
+PKCS12-SafeBag ::= SEQUENCE {
+ bagId OBJECT IDENTIFIER,
+ bagValue [0] HEIM_ANY,
+ bagAttributes PKCS12-Attributes OPTIONAL
+}
+
+PKCS12-SafeContents ::= SEQUENCE OF PKCS12-SafeBag
+
+PKCS12-CertBag ::= SEQUENCE {
+ certType OBJECT IDENTIFIER,
+ certValue [0] HEIM_ANY
+}
+
+PKCS12-PBEParams ::= SEQUENCE {
+ salt OCTET STRING,
+ iterations INTEGER (0..4294967295) OPTIONAL
+}
+
+PKCS12-OctetString ::= OCTET STRING
+
+-- KeyBag ::= PrivateKeyInfo
+-- PKCS8ShroudedKeyBag ::= EncryptedPrivateKeyInfo
+
+END
diff --git a/third_party/heimdal/lib/asn1/pkcs8.asn1 b/third_party/heimdal/lib/asn1/pkcs8.asn1
new file mode 100644
index 0000000..6227033
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/pkcs8.asn1
@@ -0,0 +1,29 @@
+-- $Id$ --
+
+PKCS8 DEFINITIONS ::=
+
+BEGIN
+
+IMPORTS Attribute, AlgorithmIdentifier FROM rfc2459;
+
+PKCS8PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
+
+PKCS8PrivateKey ::= OCTET STRING
+
+PKCS8Attributes ::= SET OF Attribute
+
+PKCS8PrivateKeyInfo ::= SEQUENCE {
+ version INTEGER,
+ privateKeyAlgorithm PKCS8PrivateKeyAlgorithmIdentifier,
+ privateKey PKCS8PrivateKey,
+ attributes [0] IMPLICIT SET OF Attribute OPTIONAL
+}
+
+PKCS8EncryptedData ::= OCTET STRING
+
+PKCS8EncryptedPrivateKeyInfo ::= SEQUENCE {
+ encryptionAlgorithm AlgorithmIdentifier,
+ encryptedData PKCS8EncryptedData
+}
+
+END
diff --git a/third_party/heimdal/lib/asn1/pkcs9.asn1 b/third_party/heimdal/lib/asn1/pkcs9.asn1
new file mode 100644
index 0000000..43b4a9d
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/pkcs9.asn1
@@ -0,0 +1,29 @@
+-- $Id$ --
+
+PKCS9 DEFINITIONS ::=
+
+BEGIN
+
+-- The PFX PDU
+
+id-pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
+ rsadsi(113549) pkcs(1) pkcs-9(9) }
+
+id-pkcs9-emailAddress OBJECT IDENTIFIER ::= {id-pkcs-9 1 }
+id-pkcs9-contentType OBJECT IDENTIFIER ::= {id-pkcs-9 3 }
+id-pkcs9-messageDigest OBJECT IDENTIFIER ::= {id-pkcs-9 4 }
+id-pkcs9-signingTime OBJECT IDENTIFIER ::= {id-pkcs-9 5 }
+id-pkcs9-countersignature OBJECT IDENTIFIER ::= {id-pkcs-9 6 }
+id-pkcs9-extReq OBJECT IDENTIFIER ::= {id-pkcs-9 14}
+
+id-pkcs-9-at-friendlyName OBJECT IDENTIFIER ::= {id-pkcs-9 20}
+id-pkcs-9-at-localKeyId OBJECT IDENTIFIER ::= {id-pkcs-9 21}
+id-pkcs-9-at-certTypes OBJECT IDENTIFIER ::= {id-pkcs-9 22}
+id-pkcs-9-at-certTypes-x509 OBJECT IDENTIFIER ::= {id-pkcs-9-at-certTypes 1}
+
+PKCS9-BMPString ::= BMPString
+
+PKCS9-friendlyName ::= SET OF PKCS9-BMPString
+
+END
+
diff --git a/third_party/heimdal/lib/asn1/pkinit.asn1 b/third_party/heimdal/lib/asn1/pkinit.asn1
new file mode 100644
index 0000000..99dda00
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/pkinit.asn1
@@ -0,0 +1,201 @@
+-- $Id$ --
+
+PKINIT DEFINITIONS ::= BEGIN
+
+IMPORTS EncryptionKey, PrincipalName, Realm, KerberosTime, Checksum, Ticket FROM krb5
+ IssuerAndSerialNumber FROM cms
+ SubjectPublicKeyInfo, AlgorithmIdentifier FROM rfc2459
+ HEIM_ANY FROM heim;
+
+id-pkinit OBJECT IDENTIFIER ::=
+ { iso (1) org (3) dod (6) internet (1) security (5)
+ kerberosv5 (2) pkinit (3) }
+
+id-pkauthdata OBJECT IDENTIFIER ::= { id-pkinit 1 }
+id-pkdhkeydata OBJECT IDENTIFIER ::= { id-pkinit 2 }
+id-pkrkeydata OBJECT IDENTIFIER ::= { id-pkinit 3 }
+id-pkekuoid OBJECT IDENTIFIER ::= { id-pkinit 4 }
+id-pkkdcekuoid OBJECT IDENTIFIER ::= { id-pkinit 5 }
+
+id-heim-eku-pkinit-certlife-is-max-life OBJECT IDENTIFIER ::=
+ { iso(1) member-body(2) se(752) su(43) heim-pkix(16) 3 }
+
+id-apple-system-id OBJECT IDENTIFIER ::= { 1 2 840 113635 100 4 4 }
+
+id-pkinit-kdf OBJECT IDENTIFIER ::= { id-pkinit 6 }
+id-pkinit-kdf-ah-sha1 OBJECT IDENTIFIER ::= { id-pkinit-kdf 1 }
+id-pkinit-kdf-ah-sha256 OBJECT IDENTIFIER ::= { id-pkinit-kdf 2 }
+id-pkinit-kdf-ah-sha512 OBJECT IDENTIFIER ::= { id-pkinit-kdf 3 }
+
+id-pkinit-san OBJECT IDENTIFIER ::=
+ { iso(1) org(3) dod(6) internet(1) security(5) kerberosv5(2)
+ x509-sanan(2) }
+
+id-pkinit-ms-eku OBJECT IDENTIFIER ::=
+ { iso(1) org(3) dod(6) internet(1) private(4)
+ enterprise(1) microsoft(311) 20 2 2 }
+
+id-pkinit-ms-san OBJECT IDENTIFIER ::=
+ { iso(1) org(3) dod(6) internet(1) private(4)
+ enterprise(1) microsoft(311) 20 2 3 }
+
+MS-UPN-SAN ::= UTF8String
+
+pa-pk-as-req INTEGER ::= 16
+pa-pk-as-rep INTEGER ::= 17
+
+td-trusted-certifiers INTEGER ::= 104
+td-invalid-certificates INTEGER ::= 105
+td-dh-parameters INTEGER ::= 109
+
+DHNonce ::= OCTET STRING
+
+KDFAlgorithmId ::= SEQUENCE {
+ kdf-id [0] OBJECT IDENTIFIER,
+ ...
+}
+
+TrustedCA ::= SEQUENCE {
+ caName [0] IMPLICIT OCTET STRING,
+ certificateSerialNumber [1] INTEGER OPTIONAL,
+ subjectKeyIdentifier [2] OCTET STRING OPTIONAL,
+ ...
+}
+
+ExternalPrincipalIdentifier ::= SEQUENCE {
+ subjectName [0] IMPLICIT OCTET STRING OPTIONAL,
+ issuerAndSerialNumber [1] IMPLICIT OCTET STRING OPTIONAL,
+ subjectKeyIdentifier [2] IMPLICIT OCTET STRING OPTIONAL,
+ ...
+}
+
+ExternalPrincipalIdentifiers ::= SEQUENCE OF ExternalPrincipalIdentifier
+
+PA-PK-AS-REQ ::= SEQUENCE {
+ signedAuthPack [0] IMPLICIT OCTET STRING,
+ trustedCertifiers [1] ExternalPrincipalIdentifiers OPTIONAL,
+ kdcPkId [2] IMPLICIT OCTET STRING OPTIONAL,
+ ...
+}
+
+PKAuthenticator ::= SEQUENCE {
+ cusec [0] INTEGER -- (0..999999) --,
+ ctime [1] KerberosTime,
+ nonce [2] INTEGER (0..4294967295),
+ paChecksum [3] OCTET STRING OPTIONAL,
+ freshnessToken [4] OCTET STRING OPTIONAL,
+ ...
+}
+
+AuthPack ::= SEQUENCE {
+ pkAuthenticator [0] PKAuthenticator,
+ clientPublicValue [1] SubjectPublicKeyInfo OPTIONAL,
+ supportedCMSTypes [2] SEQUENCE OF AlgorithmIdentifier OPTIONAL,
+ clientDHNonce [3] DHNonce OPTIONAL,
+ ...,
+ supportedKDFs [4] SEQUENCE OF KDFAlgorithmId OPTIONAL,
+ ...
+}
+
+TD-TRUSTED-CERTIFIERS ::= ExternalPrincipalIdentifiers
+TD-INVALID-CERTIFICATES ::= ExternalPrincipalIdentifiers
+
+AD-INITIAL-VERIFIED-CAS ::= SEQUENCE OF ExternalPrincipalIdentifier
+
+DHRepInfo ::= SEQUENCE {
+ dhSignedData [0] IMPLICIT OCTET STRING,
+ serverDHNonce [1] DHNonce OPTIONAL,
+ ...,
+ kdf [2] KDFAlgorithmId OPTIONAL,
+ ...
+}
+
+PA-PK-AS-REP ::= CHOICE {
+ dhInfo [0] DHRepInfo,
+ encKeyPack [1] IMPLICIT OCTET STRING,
+ ...
+}
+
+KDCDHKeyInfo ::= SEQUENCE {
+ subjectPublicKey [0] BIT STRING,
+ nonce [1] INTEGER (0..4294967295),
+ dhKeyExpiration [2] KerberosTime OPTIONAL,
+ ...
+}
+
+ReplyKeyPack ::= SEQUENCE {
+ replyKey [0] EncryptionKey,
+ asChecksum [1] Checksum,
+ ...
+}
+
+TD-DH-PARAMETERS ::= SEQUENCE OF AlgorithmIdentifier
+
+
+-- Windows compat glue --
+
+PKAuthenticator-Win2k ::= SEQUENCE {
+ kdcName [0] PrincipalName,
+ kdcRealm [1] Realm,
+ cusec [2] INTEGER (0..4294967295),
+ ctime [3] KerberosTime,
+ nonce [4] INTEGER (-2147483648..2147483647)
+}
+
+AuthPack-Win2k ::= SEQUENCE {
+ pkAuthenticator [0] PKAuthenticator-Win2k,
+ clientPublicValue [1] SubjectPublicKeyInfo OPTIONAL
+}
+
+
+TrustedCA-Win2k ::= CHOICE {
+ caName [1] HEIM_ANY,
+ issuerAndSerial [2] IssuerAndSerialNumber
+}
+
+PA-PK-AS-REQ-Win2k ::= SEQUENCE {
+ signed-auth-pack [0] IMPLICIT OCTET STRING,
+ trusted-certifiers [2] SEQUENCE OF TrustedCA-Win2k OPTIONAL,
+ kdc-cert [3] IMPLICIT OCTET STRING OPTIONAL,
+ encryption-cert [4] IMPLICIT OCTET STRING OPTIONAL
+}
+
+PA-PK-AS-REP-Win2k ::= CHOICE {
+ dhSignedData [0] IMPLICIT OCTET STRING,
+ encKeyPack [1] IMPLICIT OCTET STRING
+}
+
+KDCDHKeyInfo-Win2k ::= SEQUENCE {
+ nonce [0] INTEGER (-2147483648..2147483647),
+ subjectPublicKey [2] BIT STRING
+}
+
+ReplyKeyPack-Win2k ::= SEQUENCE {
+ replyKey [0] EncryptionKey,
+ nonce [1] INTEGER (-2147483648..2147483647),
+ ...
+}
+
+PA-PK-AS-REP-BTMM ::= SEQUENCE {
+ dhSignedData [0] HEIM_ANY OPTIONAL,
+ encKeyPack [1] HEIM_ANY OPTIONAL
+}
+
+
+PkinitSP80056AOtherInfo ::= SEQUENCE {
+ algorithmID AlgorithmIdentifier,
+ partyUInfo [0] OCTET STRING,
+ partyVInfo [1] OCTET STRING,
+ suppPubInfo [2] OCTET STRING OPTIONAL,
+ suppPrivInfo [3] OCTET STRING OPTIONAL
+}
+
+PkinitSuppPubInfo ::= SEQUENCE {
+ enctype [0] INTEGER (-2147483648..2147483647),
+ as-REQ [1] OCTET STRING,
+ pk-as-rep [2] OCTET STRING,
+ ticket [3] Ticket,
+ ...
+}
+
+END
diff --git a/third_party/heimdal/lib/asn1/pku2u.asn1 b/third_party/heimdal/lib/asn1/pku2u.asn1
new file mode 100644
index 0000000..ca3a91f
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/pku2u.asn1
@@ -0,0 +1,30 @@
+-- $Id$
+
+PKU2U DEFINITIONS ::= BEGIN
+
+IMPORTS Checksum FROM krb5
+ GeneralName FROM rfc2459;
+
+GSS_KRB5_FINISHED ::= SEQUENCE {
+ gss-mic [1] Checksum,
+ ...
+}
+
+InitiatorName ::= CHOICE {
+ sanIndex INTEGER (-2147483648..2147483647),
+ nameNotInCert [0] GeneralName,
+ ...
+}
+
+TargetName ::= CHOICE {
+ exportedTargName OCTET STRING,
+ generalName [0] GeneralName,
+ ...
+}
+
+InitiatorNameAssertion ::= SEQUENCE {
+ initiatorName [0] InitiatorName OPTIONAL,
+ targetName [1] TargetName OPTIONAL
+}
+
+END
diff --git a/third_party/heimdal/lib/asn1/rfc2459.asn1 b/third_party/heimdal/lib/asn1/rfc2459.asn1
new file mode 100644
index 0000000..7ceefe3
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/rfc2459.asn1
@@ -0,0 +1,1210 @@
+-- $Id$ --
+-- Definitions from RFCs 2459, 3280, 5280
+--
+-- Note that those RFCs come with *two* ASN.1 modules, one being a default-
+-- EXPLICIT tagged module, and the other being default-IMPLICIT. Some types
+-- are in one module, while others are in the other. Here the two modules
+-- are merged into a single default-EXPLICIT tagged module, with IMPLICIT added
+-- for all tags for types in the default-IMPLICIT module.
+
+RFC2459 DEFINITIONS ::= BEGIN
+
+IMPORTS HEIM_ANY FROM heim
+ PrincipalName, Realm FROM krb5;
+ -- For OtherName we really want to also import:
+ -- KRB5PrincipalName FROM pkinit
+ -- PermanentIdentifier FROM rfc4043
+ -- HardwareModuleName FROM rfc4108;
+ -- But we can't because that creates circular dependencies.
+
+Version ::= INTEGER {
+ rfc3280_version_1(0),
+ rfc3280_version_2(1),
+ rfc3280_version_3(2)
+}
+
+id-pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
+ rsadsi(113549) pkcs(1) 1 }
+id-pkcs1-rsaEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 1 }
+id-pkcs1-md2WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 2 }
+id-pkcs1-md5WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 4 }
+id-pkcs1-sha1WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 5 }
+id-pkcs1-sha256WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 11 }
+id-pkcs1-sha384WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 12 }
+id-pkcs1-sha512WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 13 }
+
+id-heim-rsa-pkcs1-x509 OBJECT IDENTIFIER ::= { 1 2 752 43 16 1 }
+
+id-pkcs-2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
+ rsadsi(113549) pkcs(1) 2 }
+id-pkcs2-md2 OBJECT IDENTIFIER ::= { id-pkcs-2 2 }
+id-pkcs2-md4 OBJECT IDENTIFIER ::= { id-pkcs-2 4 }
+id-pkcs2-md5 OBJECT IDENTIFIER ::= { id-pkcs-2 5 }
+
+id-rsa-digestAlgorithm OBJECT IDENTIFIER ::=
+{ iso(1) member-body(2) us(840) rsadsi(113549) 2 }
+
+id-rsa-digest-md2 OBJECT IDENTIFIER ::= { id-rsa-digestAlgorithm 2 }
+id-rsa-digest-md4 OBJECT IDENTIFIER ::= { id-rsa-digestAlgorithm 4 }
+id-rsa-digest-md5 OBJECT IDENTIFIER ::= { id-rsa-digestAlgorithm 5 }
+
+id-pkcs-3 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
+ rsadsi(113549) pkcs(1) 3 }
+
+id-pkcs3-rc2-cbc OBJECT IDENTIFIER ::= { id-pkcs-3 2 }
+id-pkcs3-rc4 OBJECT IDENTIFIER ::= { id-pkcs-3 4 }
+id-pkcs3-des-ede3-cbc OBJECT IDENTIFIER ::= { id-pkcs-3 7 }
+
+id-rsadsi-encalg OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
+ rsadsi(113549) 3 }
+
+id-rsadsi-rc2-cbc OBJECT IDENTIFIER ::= { id-rsadsi-encalg 2 }
+id-rsadsi-des-ede3-cbc OBJECT IDENTIFIER ::= { id-rsadsi-encalg 7 }
+
+id-secsig-sha-1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+ oiw(14) secsig(3) algorithm(2) 26 }
+
+id-secsig-sha-1WithRSAEncryption OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+ oiw(14) secsig(3) algorithm(2) 29 }
+
+id-nistAlgorithm OBJECT IDENTIFIER ::= {
+ joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) 4 }
+
+id-nist-aes-algs OBJECT IDENTIFIER ::= { id-nistAlgorithm 1 }
+
+id-aes-128-cbc OBJECT IDENTIFIER ::= { id-nist-aes-algs 2 }
+id-aes-192-cbc OBJECT IDENTIFIER ::= { id-nist-aes-algs 22 }
+id-aes-256-cbc OBJECT IDENTIFIER ::= { id-nist-aes-algs 42 }
+
+id-nist-sha-algs OBJECT IDENTIFIER ::= { id-nistAlgorithm 2 }
+
+id-sha256 OBJECT IDENTIFIER ::= { id-nist-sha-algs 1 }
+id-sha224 OBJECT IDENTIFIER ::= { id-nist-sha-algs 4 }
+id-sha384 OBJECT IDENTIFIER ::= { id-nist-sha-algs 2 }
+id-sha512 OBJECT IDENTIFIER ::= { id-nist-sha-algs 3 }
+
+id-dhpublicnumber OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) ansi-x942(10046)
+ number-type(2) 1 }
+
+-- ECC
+
+id-ecPublicKey OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 }
+
+id-ecDH OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) certicom(132) schemes(1)
+ ecdh(12) }
+
+id-ecMQV OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) certicom(132) schemes(1)
+ ecmqv(13) }
+
+id-ecdsa-with-SHA512 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ ecdsa-with-SHA2(3) 4 }
+
+id-ecdsa-with-SHA384 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ ecdsa-with-SHA2(3) 3 }
+
+id-ecdsa-with-SHA256 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ ecdsa-with-SHA2(3) 2 }
+
+id-ecdsa-with-SHA224 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ ecdsa-with-SHA2(3) 1 }
+
+id-ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 }
+
+-- some EC group ids
+
+id-ec-group-secp256r1 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3)
+ prime(1) 7 }
+
+id-ec-group-secp160r1 OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) certicom(132) 0 8 }
+
+id-ec-group-secp160r2 OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) certicom(132) 0 30 }
+
+id-ec-group-secp224r1 OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) certicom(132) 0 33 }
+
+id-ec-group-secp384r1 OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) certicom(132) 0 34 }
+
+id-ec-group-secp521r1 OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) certicom(132) 0 35 }
+
+-- DSA
+
+id-x9-57 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) ansi-x942(10046) 4 }
+
+id-dsa OBJECT IDENTIFIER ::= { id-x9-57 1 }
+id-dsa-with-sha1 OBJECT IDENTIFIER ::= { id-x9-57 3 }
+
+-- x.520 names types
+
+id-x520-at OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 4 }
+
+id-at-commonName OBJECT IDENTIFIER ::= { id-x520-at 3 }
+id-at-surname OBJECT IDENTIFIER ::= { id-x520-at 4 }
+id-at-serialNumber OBJECT IDENTIFIER ::= { id-x520-at 5 }
+id-at-countryName OBJECT IDENTIFIER ::= { id-x520-at 6 }
+id-at-localityName OBJECT IDENTIFIER ::= { id-x520-at 7 }
+id-at-stateOrProvinceName OBJECT IDENTIFIER ::= { id-x520-at 8 }
+id-at-streetAddress OBJECT IDENTIFIER ::= { id-x520-at 9 }
+id-at-organizationName OBJECT IDENTIFIER ::= { id-x520-at 10 }
+id-at-organizationalUnitName OBJECT IDENTIFIER ::= { id-x520-at 11 }
+id-at-title OBJECT IDENTIFIER ::= { id-x520-at 12 }
+id-at-description OBJECT IDENTIFIER ::= { id-x520-at 13 }
+id-at-name OBJECT IDENTIFIER ::= { id-x520-at 41 }
+id-at-givenName OBJECT IDENTIFIER ::= { id-x520-at 42 }
+id-at-initials OBJECT IDENTIFIER ::= { id-x520-at 43 }
+id-at-generationQualifier OBJECT IDENTIFIER ::= { id-x520-at 44 }
+id-at-dnQualifier OBJECT IDENTIFIER ::= { id-x520-at 46 }
+id-at-pseudonym OBJECT IDENTIFIER ::= { id-x520-at 65 }
+-- RFC 2247
+id-Userid OBJECT IDENTIFIER ::=
+ { 0 9 2342 19200300 100 1 1 }
+id-domainComponent OBJECT IDENTIFIER ::=
+ { 0 9 2342 19200300 100 1 25 }
+
+id-at-emailAddress AttributeType ::=
+ { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 1 }
+
+
+
+-- rfc3280
+
+id-x509-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29}
+
+AlgorithmIdentifier ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER,
+ parameters HEIM_ANY OPTIONAL
+}
+
+AttributeType ::= OBJECT IDENTIFIER
+
+AttributeValue ::= HEIM_ANY
+
+DirectoryString ::= CHOICE {
+ ia5String IA5String,
+ teletexString TeletexString,
+ printableString PrintableString,
+ universalString UniversalString,
+ utf8String UTF8String,
+ bmpString BMPString
+}
+
+AttributeValues ::= SET OF AttributeValue
+
+Attribute ::= SEQUENCE {
+ type AttributeType,
+ value AttributeValues
+}
+
+AttributeTypeAndValue ::= SEQUENCE {
+ type AttributeType,
+ value DirectoryString
+}
+
+-- RDNs really should be SET OF SingleAttribute per the RFCs, but making that
+-- change will affect lib/hx509 code, so we'll wait. The issue is that there
+-- is code in lib/hx509 and in lib/asn1/check-gen.c that assumes that the
+-- `value` of an rdn is a `DirectoryString` and not an open type.
+--
+-- Also, it's really not worth making this change, as a) it will increase the
+-- amount of code needed in lib/hx509, and b) it really is useful to be able to
+-- assume RDN values are ultimately only strings, c) we don't have any attrs
+-- for RDNs that aren't strings, and d) the non-string attributes from TCG that
+-- are used in SubjectDirectoryAttributes will never be used here (so we hope).
+--
+-- Until we fix this lib/hx509 cannot support name attributes whose type isn't
+-- DirectoryString. For example, the UID attribute is broken at this time, as
+-- that wants NumericString.
+--
+RelativeDistinguishedName ::= SET OF AttributeTypeAndValue -- XXX SingleAttribute
+
+RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+
+Name ::= CHOICE {
+ rdnSequence RDNSequence
+}
+
+CertificateSerialNumber ::= INTEGER
+
+Time ::= CHOICE {
+ utcTime UTCTime,
+ generalTime GeneralizedTime
+}
+
+Validity ::= SEQUENCE {
+ notBefore Time,
+ notAfter Time
+}
+
+UniqueIdentifier ::= BIT STRING
+
+SubjectPublicKeyInfo ::= SEQUENCE {
+ algorithm AlgorithmIdentifier,
+ subjectPublicKey BIT STRING
+}
+
+-- XXX Should be _OTHER-NAME ::= _TYPE-IDENTIFIER
+_OTHER-NAME ::= CLASS {
+ &id OBJECT IDENTIFIER UNIQUE,
+ &Type
+}
+
+OtherName{_OTHER-NAME:OtherNameSet} ::= SEQUENCE {
+ type-id _OTHER-NAME.&id({OtherNameSet}),
+ value [0] _OTHER-NAME.&Type({OtherNameSet}{@type-id})
+}
+
+_ATTRIBUTE ::= CLASS {
+ &id OBJECT IDENTIFIER UNIQUE,
+ &Type OPTIONAL,
+ -- &equality-match MATCHING-RULE OPTIONAL,
+ &minCount INTEGER DEFAULT 1,
+ &maxCount INTEGER OPTIONAL
+}
+
+SingleAttribute{_ATTRIBUTE:AttrSet} ::= SEQUENCE {
+ type _ATTRIBUTE.&id({AttrSet}),
+ value _ATTRIBUTE.&Type({AttrSet}{@type})
+}
+
+AttributeSet{_ATTRIBUTE:AttrSet} ::= SEQUENCE {
+ type _ATTRIBUTE.&id({AttrSet}),
+ values SET --SIZE (1..MAX)-- OF _ATTRIBUTE.&Type({AttrSet}{@type})
+}
+
+_EXTENSION ::= CLASS {
+ &id OBJECT IDENTIFIER UNIQUE,
+ &ExtnType,
+ &Critical BOOLEAN DEFAULT FALSE
+}
+
+Extension{_EXTENSION:ExtensionSet} ::= SEQUENCE {
+ extnID _EXTENSION.&id({ExtensionSet}),
+ critical BOOLEAN
+-- (EXTENSION.&Critical({ExtensionSet}{@extnID}))
+ DEFAULT FALSE,
+ extnValue OCTET STRING (CONTAINING
+ _EXTENSION.&ExtnType({ExtensionSet}{@extnID}))
+}
+
+Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+
+TBSCertificate ::= SEQUENCE {
+ version [0] Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1,
+ serialNumber CertificateSerialNumber,
+ signature AlgorithmIdentifier,
+ issuer Name,
+ validity Validity,
+ subject Name,
+ subjectPublicKeyInfo SubjectPublicKeyInfo,
+ issuerUniqueID [1] IMPLICIT BIT STRING -- UniqueIdentifier -- OPTIONAL,
+ -- If present, version shall be v2 or v3
+ subjectUniqueID [2] IMPLICIT BIT STRING -- UniqueIdentifier -- OPTIONAL,
+ -- If present, version shall be v2 or v3
+ extensions [3] EXPLICIT Extensions OPTIONAL
+ -- If present, version shall be v3
+}
+
+Certificate ::= SEQUENCE {
+ tbsCertificate TBSCertificate,
+ signatureAlgorithm AlgorithmIdentifier,
+ signatureValue BIT STRING
+}
+
+Certificates ::= SEQUENCE OF Certificate
+
+ValidationParms ::= SEQUENCE {
+ seed BIT STRING,
+ pgenCounter INTEGER
+}
+
+DomainParameters ::= SEQUENCE {
+ p INTEGER, -- odd prime, p=jq +1
+ g INTEGER, -- generator, g
+ q INTEGER OPTIONAL, -- factor of p-1
+ j INTEGER OPTIONAL, -- subgroup factor
+ validationParms ValidationParms OPTIONAL -- ValidationParms
+}
+
+-- As defined by PKCS3
+DHParameter ::= SEQUENCE {
+ prime INTEGER, -- odd prime, p=jq +1
+ base INTEGER, -- generator, g
+ privateValueLength INTEGER OPTIONAL
+}
+
+DHPublicKey ::= INTEGER
+
+GeneralName ::= CHOICE {
+ otherName [0] IMPLICIT OtherName,
+ rfc822Name [1] IMPLICIT IA5String,
+ dNSName [2] IMPLICIT IA5String,
+-- x400Address [3] IMPLICIT ORAddress,--
+ directoryName [4] IMPLICIT Name,
+-- ediPartyName [5] IMPLICIT EDIPartyName, --
+ uniformResourceIdentifier [6] IMPLICIT IA5String,
+ iPAddress [7] IMPLICIT OCTET STRING,
+ registeredID [8] IMPLICIT OBJECT IDENTIFIER
+}
+
+GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+
+id-x509-ce-keyUsage OBJECT IDENTIFIER ::= { id-x509-ce 15 }
+
+KeyUsage ::= BIT STRING {
+ digitalSignature (0),
+ nonRepudiation (1),
+ keyEncipherment (2),
+ dataEncipherment (3),
+ keyAgreement (4),
+ keyCertSign (5),
+ cRLSign (6),
+ encipherOnly (7),
+ decipherOnly (8)
+}
+
+-- private key usage period extension OID and syntax
+
+PrivateKeyUsagePeriod ::= SEQUENCE {
+ notBefore [0] IMPLICIT GeneralizedTime OPTIONAL,
+ notAfter [1] IMPLICIT GeneralizedTime OPTIONAL
+ -- either notBefore or notAfter MUST be present
+}
+
+-- certificate policies extension OID and syntax
+
+_POLICYQUALIFIERINFO ::= CLASS { -- Heimdal extension
+ &id OBJECT IDENTIFIER UNIQUE,
+ &Type
+}
+
+CertPolicyId ::= OBJECT IDENTIFIER
+PolicyQualifierId ::= OBJECT IDENTIFIER -- ( id-qt-cps | id-qt-unotice )
+
+PolicyQualifierInfo{_POLICYQUALIFIERINFO:PolicyQualifierSet} ::= SEQUENCE {
+ policyQualifierId _POLICYQUALIFIERINFO.&id({PolicyQualifierSet}),
+ qualifier _POLICYQUALIFIERINFO.&Type({PolicyQualifierSet}{@policyQualifierId})
+}
+
+PolicyQualifierInfos ::= SEQUENCE SIZE (1..MAX) OF PolicyQualifierInfo
+
+PolicyInformation ::= SEQUENCE {
+ policyIdentifier CertPolicyId,
+ policyQualifiers PolicyQualifierInfos OPTIONAL
+}
+
+CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
+
+-- CPS pointer qualifier
+
+CPSuri ::= IA5String
+
+-- user notice qualifier
+
+DisplayText ::= CHOICE {
+ ia5String IA5String, --(SIZE (1..200))
+ visibleString VisibleString, --(SIZE (1..200))
+ bmpString BMPString, --(SIZE (1..200))
+ utf8String UTF8String --(SIZE (1..200))
+}
+
+NoticeReference ::= SEQUENCE {
+ organization DisplayText,
+ noticeNumbers SEQUENCE OF INTEGER
+}
+
+UserNotice ::= SEQUENCE {
+ noticeRef NoticeReference OPTIONAL,
+ explicitText DisplayText OPTIONAL
+}
+
+-- policy mapping extension OID and syntax
+
+PolicyMapping ::= SEQUENCE {
+ issuerDomainPolicy CertPolicyId,
+ subjectDomainPolicy CertPolicyId
+}
+
+PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF PolicyMapping
+
+-- subject key identifier OID and syntax
+
+id-x509-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-x509-ce 35 }
+
+KeyIdentifier ::= OCTET STRING
+
+AuthorityKeyIdentifier ::= SEQUENCE {
+ keyIdentifier [0] IMPLICIT OCTET STRING OPTIONAL,
+ authorityCertIssuer [1] IMPLICIT -- GeneralName --
+ SEQUENCE -- SIZE (1..MAX) -- OF GeneralName OPTIONAL,
+ authorityCertSerialNumber [2] IMPLICIT INTEGER OPTIONAL
+}
+
+id-x509-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-x509-ce 14 }
+
+SubjectKeyIdentifier ::= KeyIdentifier
+
+id-x509-ce-basicConstraints OBJECT IDENTIFIER ::= { id-x509-ce 19 }
+
+BasicConstraints ::= SEQUENCE {
+ cA BOOLEAN DEFAULT FALSE,
+ pathLenConstraint INTEGER (0..4294967295) OPTIONAL
+}
+
+id-x509-ce-nameConstraints OBJECT IDENTIFIER ::= { id-x509-ce 30 }
+
+BaseDistance ::= INTEGER (0..4294967295)
+
+GeneralSubtree ::= SEQUENCE {
+ base GeneralName,
+ minimum [0] IMPLICIT BaseDistance DEFAULT 0,
+ maximum [1] IMPLICIT BaseDistance OPTIONAL
+}
+
+GeneralSubtrees ::= SEQUENCE -- SIZE (1..MAX) -- OF GeneralSubtree
+
+NameConstraints ::= SEQUENCE {
+ permittedSubtrees [0] IMPLICIT -- GeneralSubtrees -- SEQUENCE OF GeneralSubtree OPTIONAL,
+ excludedSubtrees [1] IMPLICIT -- GeneralSubtrees -- SEQUENCE OF GeneralSubtree OPTIONAL
+}
+
+id-x509-ce-privateKeyUsagePeriod OBJECT IDENTIFIER ::= { id-x509-ce 16 }
+id-x509-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-x509-ce 32 }
+id-x509-ce-certificatePolicies-anyPolicy OBJECT IDENTIFIER ::= { id-x509-ce-certificatePolicies 0 }
+id-x509-ce-policyMappings OBJECT IDENTIFIER ::= { id-x509-ce 33 }
+id-x509-ce-subjectAltName OBJECT IDENTIFIER ::= { id-x509-ce 17 }
+id-x509-ce-issuerAltName OBJECT IDENTIFIER ::= { id-x509-ce 18 }
+id-x509-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-x509-ce 9 }
+id-x509-ce-policyConstraints OBJECT IDENTIFIER ::= { id-x509-ce 36 }
+
+id-x509-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-x509-ce 37}
+id-x509-ce-anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-x509-ce-extKeyUsage 0 }
+
+ExtKeyUsage ::= SEQUENCE OF OBJECT IDENTIFIER
+
+id-x509-ce-cRLReasons OBJECT IDENTIFIER ::= { id-x509-ce 21 }
+id-x509-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-x509-ce 31 }
+id-x509-ce-deltaCRLIndicator OBJECT IDENTIFIER ::= { id-x509-ce 27 }
+id-x509-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-x509-ce 28 }
+id-x509-ce-holdInstructionCode OBJECT IDENTIFIER ::= { id-x509-ce 23 }
+id-x509-ce-invalidityDate OBJECT IDENTIFIER ::= { id-x509-ce 24 }
+id-x509-ce-certificateIssuer OBJECT IDENTIFIER ::= { id-x509-ce 29 }
+id-x509-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-x509-ce 54 }
+
+-- Heimdal extension
+id-heim-ce-pkinit-princ-max-life OBJECT IDENTIFIER ::=
+ { iso(1) member-body(2) se(752) su(43) heim-pkix(16) 4 }
+
+
+DistributionPointReasonFlags ::= BIT STRING {
+ unused (0),
+ keyCompromise (1),
+ cACompromise (2),
+ affiliationChanged (3),
+ superseded (4),
+ cessationOfOperation (5),
+ certificateHold (6),
+ privilegeWithdrawn (7),
+ aACompromise (8)
+}
+
+DistributionPointName ::= CHOICE {
+ fullName [0] IMPLICIT -- GeneralNames -- SEQUENCE SIZE (1..MAX) OF GeneralName,
+ nameRelativeToCRLIssuer [1] RelativeDistinguishedName
+}
+
+DistributionPoint ::= SEQUENCE {
+ distributionPoint [0] IMPLICIT DistributionPointName OPTIONAL,
+ reasons [1] IMPLICIT DistributionPointReasonFlags OPTIONAL,
+ cRLIssuer [2] IMPLICIT GeneralNames OPTIONAL
+}
+
+CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
+
+
+-- rfc3279
+
+DSASigValue ::= SEQUENCE {
+ r INTEGER,
+ s INTEGER
+}
+
+DSAPublicKey ::= INTEGER
+
+DSAParams ::= SEQUENCE {
+ p INTEGER,
+ q INTEGER,
+ g INTEGER
+}
+
+-- draft-ietf-pkix-ecc-subpubkeyinfo-11
+
+ECPoint ::= OCTET STRING
+
+ECParameters ::= CHOICE {
+ namedCurve OBJECT IDENTIFIER
+ -- implicitCurve NULL
+ -- specifiedCurve SpecifiedECDomain
+}
+
+ECDSA-Sig-Value ::= SEQUENCE {
+ r INTEGER,
+ s INTEGER
+}
+
+-- really pkcs1
+
+RSAPublicKey ::= SEQUENCE {
+ modulus INTEGER, -- n
+ publicExponent INTEGER -- e
+}
+
+RSAPrivateKey ::= SEQUENCE {
+ version INTEGER (0..4294967295),
+ modulus INTEGER, -- n
+ publicExponent INTEGER, -- e
+ privateExponent INTEGER, -- d
+ prime1 INTEGER, -- p
+ prime2 INTEGER, -- q
+ exponent1 INTEGER, -- d mod (p-1)
+ exponent2 INTEGER, -- d mod (q-1)
+ coefficient INTEGER -- (inverse of q) mod p
+}
+
+DigestInfo ::= SEQUENCE {
+ digestAlgorithm AlgorithmIdentifier,
+ digest OCTET STRING
+}
+
+-- some ms ext
+
+-- szOID_ENROLL_CERTTYPE_EXTENSION "1.3.6.1.4.1.311.20.2" is Encoded as a
+
+-- UNICODESTRING (0x1E tag)
+
+-- szOID_CERTIFICATE_TEMPLATE "1.3.6.1.4.1.311.21.7" is Encoded as:
+
+-- TemplateVersion ::= INTEGER (0..4294967295)
+
+-- CertificateTemplate ::= SEQUENCE {
+-- templateID OBJECT IDENTIFIER,
+-- templateMajorVersion TemplateVersion,
+-- templateMinorVersion TemplateVersion OPTIONAL
+-- }
+
+
+--
+-- CRL
+--
+
+TBSCRLCertList ::= SEQUENCE {
+ version Version OPTIONAL, -- if present, MUST be v2
+ signature AlgorithmIdentifier,
+ issuer Name,
+ thisUpdate Time,
+ nextUpdate Time OPTIONAL,
+ revokedCertificates SEQUENCE OF SEQUENCE {
+ userCertificate CertificateSerialNumber,
+ revocationDate Time,
+ crlEntryExtensions Extensions OPTIONAL
+ -- if present, MUST be v2
+ } OPTIONAL,
+ crlExtensions [0] EXPLICIT Extensions OPTIONAL
+ -- if present, MUST be v2
+}
+
+
+CRLCertificateList ::= SEQUENCE {
+ tbsCertList TBSCRLCertList,
+ signatureAlgorithm AlgorithmIdentifier,
+ signatureValue BIT STRING
+}
+
+id-x509-ce-cRLNumber OBJECT IDENTIFIER ::= { id-x509-ce 20 }
+id-x509-ce-freshestCRL OBJECT IDENTIFIER ::= { id-x509-ce 46 }
+id-x509-ce-cRLReason OBJECT IDENTIFIER ::= { id-x509-ce 21 }
+
+CRLReason ::= ENUMERATED {
+ unspecified (0),
+ keyCompromise (1),
+ cACompromise (2),
+ affiliationChanged (3),
+ superseded (4),
+ cessationOfOperation (5),
+ certificateHold (6),
+ removeFromCRL (8),
+ privilegeWithdrawn (9),
+ aACompromise (10)
+}
+
+PKIXXmppAddr ::= UTF8String
+
+SRVName ::= IA5String -- (SIZE (1..MAX)), but our compiler doesn't do that
+
+id-pkix OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+ dod(6) internet(1) security(5) mechanisms(5) pkix(7) }
+
+id-pkix-on OBJECT IDENTIFIER ::= { id-pkix 8 }
+id-pkix-on-xmppAddr OBJECT IDENTIFIER ::= { id-pkix-on 5 }
+id-pkix-on-dnsSRV OBJECT IDENTIFIER ::= { id-pkix-on 7 }
+
+-- From RFC4108
+id-pkix-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-pkix-on 4 }
+HardwareModuleName ::= SEQUENCE {
+ hwType OBJECT IDENTIFIER,
+ hwSerialNum OCTET STRING
+}
+
+-- XXX Not really the right name
+id-pkix-on-pkinit-san OBJECT IDENTIFIER ::=
+ { iso(1) org(3) dod(6) internet(1) security(5) kerberosv5(2)
+ x509-sanan(2) }
+KRB5PrincipalName ::= SEQUENCE {
+ realm [0] Realm,
+ principalName [1] PrincipalName
+}
+
+-- From RFC4043:
+-- Permanent identifier Object Identifier and Syntax
+id-pkix-on-permanentIdentifier OBJECT IDENTIFIER ::= { id-pkix-on 3 }
+
+PermanentIdentifier ::= SEQUENCE {
+ identifierValue UTF8String OPTIONAL,
+ -- if absent, use the serialNumber attribute
+ -- if there is a single such attribute present
+ -- in the subject DN
+ assigner OBJECT IDENTIFIER OPTIONAL
+ -- if absent, the assigner is
+ -- the certificate issuer
+}
+
+-- EKUs
+id-pkix-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
+id-pkix-kp-serverAuth OBJECT IDENTIFIER ::= { id-pkix-kp 1 }
+id-pkix-kp-clientAuth OBJECT IDENTIFIER ::= { id-pkix-kp 2 }
+id-pkix-kp-codeSigning OBJECT IDENTIFIER ::= { id-pkix-kp 3 }
+id-pkix-kp-emailProtection OBJECT IDENTIFIER ::= { id-pkix-kp 4 }
+id-pkix-kp-ipsecEndSystem OBJECT IDENTIFIER ::= { id-pkix-kp 5 }
+id-pkix-kp-ipsecTunnel OBJECT IDENTIFIER ::= { id-pkix-kp 6 }
+id-pkix-kp-ipsecUser OBJECT IDENTIFIER ::= { id-pkix-kp 7 }
+id-pkix-kp-timeStamping OBJECT IDENTIFIER ::= { id-pkix-kp 8 }
+id-pkix-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-pkix-kp 9 }
+-- The following are taken from RFC7299 and others
+id-pkix-kp-DVCS OBJECT IDENTIFIER ::= { id-pkix-kp 10 }
+id-pkix-kp-ipsecIKE OBJECT IDENTIFIER ::= { id-pkix-kp 17 }
+id-pkix-kp-capwapAC OBJECT IDENTIFIER ::= { id-pkix-kp 18 }
+id-pkix-kp-capwapWTP OBJECT IDENTIFIER ::= { id-pkix-kp 19 }
+id-pkix-kp-sipDomain OBJECT IDENTIFIER ::= { id-pkix-kp 20 } -- RFC5924
+id-pkix-kp-secureShellClient OBJECT IDENTIFIER ::= { id-pkix-kp 21 }
+id-pkix-kp-secureShellServer OBJECT IDENTIFIER ::= { id-pkix-kp 22 }
+id-pkix-kp-sendRouter OBJECT IDENTIFIER ::= { id-pkix-kp 23 }
+id-pkix-kp-sendProxiedRouter OBJECT IDENTIFIER ::= { id-pkix-kp 24 }
+id-pkix-kp-sendOwner OBJECT IDENTIFIER ::= { id-pkix-kp 25 }
+id-pkix-kp-sendProxiedOwner OBJECT IDENTIFIER ::= { id-pkix-kp 26 }
+id-pkix-kp-cmcCA OBJECT IDENTIFIER ::= { id-pkix-kp 27 } -- RFC6402
+id-pkix-kp-cmcRA OBJECT IDENTIFIER ::= { id-pkix-kp 28 } -- RFC6402
+id-pkix-kp-cmcArchive OBJECT IDENTIFIER ::= { id-pkix-kp 29 } -- RFC6402
+id-pkix-kp-bgpsec-router OBJECT IDENTIFIER ::= { id-pkix-kp 30 } -- RFC8209
+-- The following are MSFT EKUs taken from OpenSSL
+id-msft OBJECT IDENTIFIER ::= { 1 3 6 1 4 1 311 }
+id-msft-kp-msCodeInd OBJECT IDENTIFIER ::= { id-msft 2 1 21 }
+id-msft-kp-msCodeCom OBJECT IDENTIFIER ::= { id-msft 2 1 22 }
+id-msft-kp-msCTLSign OBJECT IDENTIFIER ::= { id-msft 10 3 1 }
+id-msft-kp-msSGC OBJECT IDENTIFIER ::= { id-msft 10 3 3 }
+id-msft-kp-msEFS OBJECT IDENTIFIER ::= { id-msft 10 3 4 }
+id-msft-kp-msSmartcardLogin OBJECT IDENTIFIER ::= { id-msft 20 2 2 }
+id-msft-kp-msUPN OBJECT IDENTIFIER ::= { id-msft 20 2 3 }
+
+id-pkix-pe OBJECT IDENTIFIER ::= { id-pkix 1 }
+id-pkix-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pkix-pe 1 }
+
+AccessDescription ::= SEQUENCE {
+ accessMethod OBJECT IDENTIFIER,
+ accessLocation GeneralName
+}
+
+AuthorityInfoAccessSyntax ::= SEQUENCE SIZE (1..MAX) OF AccessDescription
+
+-- RFC 3820 Proxy Certificate Profile
+
+id-pkix-pe-proxyCertInfo OBJECT IDENTIFIER ::= { id-pkix-pe 14 }
+
+id-pkix-pe-subjectInfoAccess OBJECT IDENTIFIER ::= { id-pkix-pe 11 }
+
+SubjectInfoAccessSyntax ::=
+ SEQUENCE SIZE (1..MAX) OF AccessDescription
+
+id-pkix-ppl OBJECT IDENTIFIER ::= { id-pkix 21 }
+
+id-pkix-ppl-anyLanguage OBJECT IDENTIFIER ::= { id-pkix-ppl 0 }
+id-pkix-ppl-inheritAll OBJECT IDENTIFIER ::= { id-pkix-ppl 1 }
+id-pkix-ppl-independent OBJECT IDENTIFIER ::= { id-pkix-ppl 2 }
+
+ProxyPolicy ::= SEQUENCE {
+ policyLanguage OBJECT IDENTIFIER,
+ policy OCTET STRING OPTIONAL
+}
+
+ProxyCertInfo ::= SEQUENCE {
+ pCPathLenConstraint INTEGER (0..4294967295) OPTIONAL, -- really MAX
+ proxyPolicy ProxyPolicy
+}
+
+-- TCG contents:
+
+-- See tcg.asn1 for commentary.
+
+--TCG specific OIDs
+tcg OBJECT IDENTIFIER ::= {joint-iso-itu-t(2) international-organizations(23) tcg(133)}
+tcg-attribute OBJECT IDENTIFIER ::= {tcg 2}
+tcg-kp OBJECT IDENTIFIER ::= {tcg 8}
+
+--TCG Attribute OIDs
+tcg-at-tpmManufacturer OBJECT IDENTIFIER ::= {tcg-attribute 1}
+tcg-at-tpmModel OBJECT IDENTIFIER ::= {tcg-attribute 2}
+tcg-at-tpmVersion OBJECT IDENTIFIER ::= {tcg-attribute 3}
+tcg-at-tpmSpecification OBJECT IDENTIFIER ::= {tcg-attribute 16}
+tcg-at-tpmSecurityAssertions OBJECT IDENTIFIER ::= {tcg-attribute 18}
+
+--TCG Attribute objects
+at-TPMSecurityAssertions _ATTRIBUTE ::= { &Type TPMSecurityAssertions, &id tcg-at-tpmSecurityAssertions }
+at-TPMManufacturer _ATTRIBUTE ::= { &Type AliasUTF8String, --(SIZE (1..STRMAX))-- &id tcg-at-tpmManufacturer }
+at-TPMModel _ATTRIBUTE ::= { &Type AliasUTF8String, --(SIZE (1..STRMAX))-- &id tcg-at-tpmModel }
+at-TPMVersion _ATTRIBUTE ::= { &Type AliasUTF8String, --(SIZE (1..STRMAX))-- &id tcg-at-tpmVersion }
+at-TPMSpecification _ATTRIBUTE ::= { &Type TPMSpecification, &id tcg-at-tpmSpecification }
+
+--TCG Extended Key Usage OIDs
+tcg-kp-EKCertificate OBJECT IDENTIFIER ::= {tcg-kp 1}
+
+-- OIDs not in the module in TCG_IWG_EKCredentialProfile_v2p3_r2_pub but in
+-- TCG_IWG_DevID_v1r2_02dec2020 (missing arc names not mentioned in the TCG
+-- specs):
+tcg-tpm20 OBJECT IDENTIFIER ::= {tcg 1 2} -- this OID is not named in the TCG specs
+tcg-on-ekPermIdSha256 OBJECT IDENTIFIER ::= {tcg 12 1} -- assigner value for PermanentIdentifier SAN
+tcg-cap-verifiedTPMResidency OBJECT IDENTIFIER ::= {tcg 11 1 1} -- policy OID
+tcg-cap-verifiedTPMFixed OBJECT IDENTIFIER ::= {tcg 11 1 2} -- policy OID
+tcg-cap-verifiedTPMRestricted OBJECT IDENTIFIER ::= {tcg 11 1 3} -- policy OID
+
+EKGenerationType ::= ENUMERATED {
+ ekgt-internal (0),
+ ekgt-injected (1),
+ ekgt-internalRevocable(2),
+ ekgt-injectedRevocable(3)
+}
+EKGenerationLocation ::= ENUMERATED {
+ tpmManufacturer (0),
+ platformManufacturer (1),
+ ekCertSigner (2)
+}
+EKCertificateGenerationLocation ::= EKGenerationLocation -- XXX
+EvaluationAssuranceLevel ::= ENUMERATED {
+ ealevell (1),
+ ealevel2 (2),
+ ealevel3 (3),
+ ealevel4 (4),
+ ealevel5 (5),
+ ealevel6 (6),
+ ealevel7 (7)
+}
+SecurityLevel ::= ENUMERATED {
+ sllevel1 (1),
+ sllevel2 (2),
+ sllevel3 (3),
+ sllevel4 (4)
+}
+StrengthOfFunction ::= ENUMERATED {
+ sof-basic (0),
+ sof-medium (1),
+ sof-high (2)
+}
+URIReference ::= SEQUENCE {
+ uniformResourceIdentifier IA5String, -- (SIZE (1..URIMAX))
+ hashAlgorithm AlgorithmIdentifier OPTIONAL,
+ hashValue BIT STRING OPTIONAL
+}
+EvaluationStatus ::= ENUMERATED {
+ designedToMeet (0),
+ evaluationInProgress (1),
+ evaluationCompleted (2)
+}
+
+--tcg specification attributes for tpm
+TPMSpecification ::= SEQUENCE {
+ family UTF8String, -- (SIZE (1..STRMAX))
+ level INTEGER (0..4294967295),
+ revision INTEGER (0..4294967295),
+ ...
+}
+
+
+--common criteria evaluation
+CommonCriteriaMeasures ::= SEQUENCE {
+ version IA5String, -- (SIZE (1..STRMAX)) “2.2” or “3.1”;future syntax defined by CC
+ assurancelevel EvaluationAssuranceLevel,
+ evaluationStatus EvaluationStatus,
+ plus BOOLEAN DEFAULT FALSE,
+ strengthOfFunction [0] IMPLICIT StrengthOfFunction OPTIONAL,
+ profileOid [1] IMPLICIT OBJECT IDENTIFIER OPTIONAL,
+ profileUri [2] IMPLICIT URIReference OPTIONAL,
+ targetOid [3] IMPLICIT OBJECT IDENTIFIER OPTIONAL,
+ targetUri [4] IMPLICIT URIReference OPTIONAL,
+ ...
+}
+
+--fips evaluation
+FIPSLevel ::= SEQUENCE {
+ version IA5String, -- (SIZE (1..STRMAX)) “140-1” or “140-2”
+ level SecurityLevel,
+ plus BOOLEAN DEFAULT FALSE,
+ ...
+}
+
+--tpm security assertions
+TPMVersion ::= INTEGER { tpm-v1(0) }
+TPMSecurityAssertions ::= SEQUENCE {
+ version TPMVersion DEFAULT 0, -- v1
+ fieldUpgradable BOOLEAN DEFAULT FALSE,
+ -- The TCG EK cert profile spec says all these context tags are IMPLICIT,
+ -- but samples in the field have them as EXPLICIT.
+ ekGenerationType [0] EXPLICIT EKGenerationType OPTIONAL,
+ ekGenerationLocation [1] EXPLICIT EKGenerationLocation OPTIONAL,
+ ekCertificateGenerationLocation [2] EXPLICIT EKCertificateGenerationLocation OPTIONAL,
+ ccInfo [3] EXPLICIT CommonCriteriaMeasures OPTIONAL,
+ fipsLevel [4] EXPLICIT FIPSLevel OPTIONAL,
+ iso9000Certified [5] EXPLICIT BOOLEAN DEFAULT FALSE,
+ iso9000Uri IA5String OPTIONAL, -- (SIZE (1..URIMAX))
+ ...
+}
+
+-- Back to OtherName, SingleAttribute, AttributeSet, and Extension
+
+-- XXX Not really the right name for this OID:
+id-pkix-on-pkinit-ms-san OBJECT IDENTIFIER ::=
+ { iso(1) org(3) dod(6) internet(1) private(4)
+ enterprise(1) microsoft(311) 20 2 3 }
+
+-- XXX Work around bug (where we don't know the names of universal types in the
+-- template backend) by creating aliases for universal types we use in IOS
+-- objects.
+AliasUTF8String ::= UTF8String
+AliasIA5String ::= UTF8String
+AliasPrintableString ::= PrintableString
+on-xmppAddr _OTHER-NAME ::= { &id id-pkix-on-xmppAddr, &Type AliasUTF8String }
+on-dnsSRV _OTHER-NAME ::= { &id id-pkix-on-dnsSRV, &Type AliasIA5String }
+on-hardwareModuleName _OTHER-NAME ::= {
+ &id id-pkix-on-hardwareModuleName,
+ &Type HardwareModuleName
+}
+on-permanentIdentifier _OTHER-NAME ::= {
+ &id id-pkix-on-permanentIdentifier,
+ &Type PermanentIdentifier
+}
+on-krb5PrincipalName _OTHER-NAME ::= {
+ &id id-pkix-on-pkinit-san,
+ &Type KRB5PrincipalName
+}
+on-pkinit-ms-san _OTHER-NAME ::= {
+ &id id-pkix-on-pkinit-ms-san,
+ &Type AliasUTF8String
+}
+
+KnownOtherNameTypes _OTHER-NAME ::= {
+ on-xmppAddr
+ | on-dnsSRV
+ | on-hardwareModuleName
+ | on-permanentIdentifier
+ | on-krb5PrincipalName
+ | on-pkinit-ms-san
+}
+
+OtherName ::= OtherName{KnownOtherNameTypes}
+
+X520name ::= DirectoryString --{ub-name}
+X520CommonName ::= DirectoryString --{ub-common-name}
+X520LocalityName ::= DirectoryString --{ub-locality-name}
+X520OrganizationName ::= DirectoryString --{ub-organization-name}
+X520StateOrProvinceName ::= DirectoryString --{ub-state-name}
+X520OrganizationalUnitName ::= DirectoryString --{ub-organizational-unit-name}
+
+at-name _ATTRIBUTE ::= { &Type X520name, &id id-at-name }
+at-surname _ATTRIBUTE ::= { &Type X520name, &id id-at-surname }
+at-givenName _ATTRIBUTE ::= { &Type X520name, &id id-at-givenName }
+at-initials _ATTRIBUTE ::= { &Type X520name, &id id-at-initials }
+at-generationQualifier _ATTRIBUTE ::= { &Type X520name, &id id-at-generationQualifier }
+at-x520CommonName _ATTRIBUTE ::= {&Type X520CommonName, &id id-at-commonName }
+at-x520LocalityName _ATTRIBUTE ::= { &Type X520LocalityName, &id id-at-localityName }
+at-x520StateOrProvinceName _ATTRIBUTE ::= { &Type DirectoryString --{ub-state-name}--, &id id-at-stateOrProvinceName }
+at-x520OrganizationName _ATTRIBUTE ::= { &Type DirectoryString --{ub-organization-name}--, &id id-at-organizationName }
+at-x520OrganizationalUnitName _ATTRIBUTE ::= { &Type DirectoryString --{ub-organizational-unit-name}--, &id id-at-organizationalUnitName }
+at-x520Title _ATTRIBUTE ::= { &Type DirectoryString --{ub-title}--, &id id-at-title }
+at-x520dnQualifier _ATTRIBUTE ::= { &Type AliasPrintableString, &id id-at-dnQualifier }
+at-x520countryName _ATTRIBUTE ::= { &Type AliasPrintableString --(SIZE (2))--, &id id-at-countryName }
+at-x520SerialNumber _ATTRIBUTE ::= {&Type AliasPrintableString --(SIZE (1..ub-serial-number))--, &id id-at-serialNumber }
+at-x520Pseudonym _ATTRIBUTE ::= { &Type DirectoryString --{ub-pseudonym}--, &id id-at-pseudonym }
+at-domainComponent _ATTRIBUTE ::= { &Type AliasIA5String, &id id-domainComponent }
+at-emailAddress _ATTRIBUTE ::= { &Type AliasIA5String --(SIZE (1..ub-emailaddress-length))--, &id id-at-emailAddress }
+
+SupportedAttributes _ATTRIBUTE ::= {
+ at-name
+ | at-surname
+ | at-givenName
+ | at-initials
+ | at-generationQualifier
+ | at-x520CommonName
+ | at-x520LocalityName
+ | at-x520StateOrProvinceName
+ | at-x520OrganizationName
+ | at-x520OrganizationalUnitName
+ | at-x520Title
+ | at-x520dnQualifier
+ | at-x520countryName
+ | at-x520SerialNumber
+ | at-x520Pseudonym
+ | at-domainComponent
+ | at-emailAddress
+ | at-TPMSecurityAssertions
+ | at-TPMManufacturer
+ | at-TPMModel
+ | at-TPMVersion
+ | at-TPMSpecification
+}
+
+SingleAttribute ::= SingleAttribute{SupportedAttributes}
+AttributeSet ::= AttributeSet{SupportedAttributes}
+SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF AttributeSet
+
+ext-AuthorityKeyIdentifier _EXTENSION ::= {
+ &id id-x509-ce-authorityKeyIdentifier,
+ &Critical FALSE,
+ &ExtnType AuthorityKeyIdentifier
+}
+ext-KeyUsage _EXTENSION ::= {
+ &id id-x509-ce-keyUsage,
+ &Critical FALSE,
+ &ExtnType KeyUsage
+}
+ext-SubjectKeyIdentifier _EXTENSION ::= {
+ &id id-x509-ce-subjectKeyIdentifier,
+ &Critical FALSE,
+ &ExtnType SubjectKeyIdentifier
+}
+ext-PrivateKeyUsagePeriod _EXTENSION ::= {
+ &id id-x509-ce-privateKeyUsagePeriod,
+ &Critical FALSE,
+ &ExtnType PrivateKeyUsagePeriod
+}
+ext-CertificatePolicies _EXTENSION ::= {
+ &id id-x509-ce-certificatePolicies,
+ &Critical FALSE,
+ &ExtnType CertificatePolicies
+}
+ext-PolicyMappings _EXTENSION ::= {
+ &id id-x509-ce-policyMappings,
+ &Critical FALSE,
+ &ExtnType PolicyMappings
+}
+ext-SubjectAltName _EXTENSION ::= {
+ &id id-x509-ce-subjectAltName,
+ &Critical FALSE,
+ &ExtnType GeneralNames
+}
+ext-IssuerAltName _EXTENSION ::= {
+ &id id-x509-ce-issuerAltName,
+ &Critical FALSE,
+ &ExtnType GeneralNames
+}
+ext-SubjectDirectoryAttributes _EXTENSION ::= {
+ &id id-x509-ce-subjectDirectoryAttributes,
+ &Critical FALSE,
+ &ExtnType SubjectDirectoryAttributes
+}
+ext-BasicConstraints _EXTENSION ::= {
+ &id id-x509-ce-basicConstraints,
+ &Critical FALSE,
+ &ExtnType BasicConstraints
+}
+ext-NameConstraints _EXTENSION ::= {
+ &id id-x509-ce-nameConstraints,
+ &Critical FALSE,
+ &ExtnType NameConstraints
+}
+SkipCerts ::= INTEGER (0..4294967295)
+PolicyConstraints ::= SEQUENCE {
+ requireExplicitPolicy [0] IMPLICIT SkipCerts OPTIONAL,
+ inhibitPolicyMapping [1] IMPLICIT SkipCerts OPTIONAL
+}
+ext-PolicyConstraints _EXTENSION ::= {
+ &id id-x509-ce-policyConstraints,
+ &Critical FALSE,
+ &ExtnType PolicyConstraints
+}
+ext-ExtKeyUsage _EXTENSION ::= {
+ &id id-x509-ce-extKeyUsage,
+ &Critical FALSE,
+ &ExtnType ExtKeyUsage
+}
+ext-CRLDistributionPoints _EXTENSION ::= {
+ &id id-x509-ce-cRLDistributionPoints,
+ &Critical FALSE,
+ &ExtnType CRLDistributionPoints
+}
+ext-InhibitAnyPolicy _EXTENSION ::= {
+ &id id-x509-ce-inhibitAnyPolicy,
+ &Critical FALSE,
+ &ExtnType SkipCerts
+}
+ext-FreshestCRL _EXTENSION ::= {
+ &id id-x509-ce-freshestCRL,
+ &Critical FALSE,
+ &ExtnType CRLDistributionPoints
+}
+ext-AuthorityInfoAccess _EXTENSION ::= {
+ &id id-pkix-pe-authorityInfoAccess,
+ &Critical FALSE,
+ &ExtnType AuthorityInfoAccessSyntax
+}
+ext-SubjectInfoAccessSyntax _EXTENSION ::= {
+ &id id-pkix-pe-subjectInfoAccess,
+ &Critical FALSE,
+ &ExtnType SubjectInfoAccessSyntax
+}
+ext-ProxyCertInfo _EXTENSION ::= {
+ &id id-pkix-pe-proxyCertInfo,
+ &Critical FALSE,
+ &ExtnType ProxyCertInfo
+}
+HeimPkinitPrincMaxLifeSecs ::= INTEGER (0..4294967295)
+ext-HeimPkinitPrincMaxLife _EXTENSION ::= {
+ &id id-heim-ce-pkinit-princ-max-life,
+ &Critical FALSE,
+ &ExtnType HeimPkinitPrincMaxLifeSecs
+}
+CertExtensions _EXTENSION ::= {
+ ext-AuthorityKeyIdentifier
+ | ext-SubjectKeyIdentifier
+ | ext-KeyUsage
+ | ext-PrivateKeyUsagePeriod
+ | ext-CertificatePolicies
+ | ext-PolicyMappings
+ | ext-SubjectAltName
+ | ext-IssuerAltName
+ | ext-SubjectDirectoryAttributes
+ | ext-BasicConstraints
+ | ext-NameConstraints
+ | ext-PolicyConstraints
+ | ext-ExtKeyUsage
+ | ext-CRLDistributionPoints
+ | ext-InhibitAnyPolicy
+ | ext-FreshestCRL
+ | ext-AuthorityInfoAccess
+ | ext-SubjectInfoAccessSyntax
+ | ext-ProxyCertInfo
+ | ext-HeimPkinitPrincMaxLife
+}
+
+Extension ::= Extension { CertExtensions }
+
+--- U.S. Federal PKI Common Policy Framework
+-- Card Authentication key
+id-uspkicommon-card-id OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 6 6 }
+id-uspkicommon-piv-interim OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 6 9 1 }
+
+--- Netscape extensions
+
+id-netscape OBJECT IDENTIFIER ::=
+ { joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730) }
+id-netscape-cert-comment OBJECT IDENTIFIER ::= { id-netscape 1 13 }
+
+--- MS extensions
+
+id-ms-cert-enroll-domaincontroller OBJECT IDENTIFIER ::=
+ { 1 3 6 1 4 1 311 20 2 }
+
+-- This is a duplicate of id-pkix-kp-clientAuth
+-- id-ms-client-authentication OBJECT IDENTIFIER ::=
+-- { 1 3 6 1 5 5 7 3 2 }
+
+-- DER:1e:20:00:44:00:6f:00:6d:00:61:00:69:00:6e:00:43:00:6f:00:6e:00:74:00:72:00:6f:00:6c:00:6c:00:65:00:72
+
+-- Upper bounds:
+
+ub-name INTEGER ::= 32768
+ub-common-name INTEGER ::= 64
+ub-locality-name INTEGER ::= 128
+ub-state-name INTEGER ::= 128
+ub-organization-name INTEGER ::= 64
+ub-organizational-unit-name INTEGER ::= 64
+ub-title INTEGER ::= 64
+ub-serial-number INTEGER ::= 64
+ub-match INTEGER ::= 128
+ub-emailaddress-length INTEGER ::= 255
+ub-common-name-length INTEGER ::= 64
+ub-country-name-alpha-length INTEGER ::= 2
+ub-country-name-numeric-length INTEGER ::= 3
+ub-domain-defined-attributes INTEGER ::= 4
+ub-domain-defined-attribute-type-length INTEGER ::= 8
+ub-domain-defined-attribute-value-length INTEGER ::= 128
+ub-domain-name-length INTEGER ::= 16
+ub-extension-attributes INTEGER ::= 256
+ub-e163-4-number-length INTEGER ::= 15
+ub-e163-4-sub-address-length INTEGER ::= 40
+ub-generation-qualifier-length INTEGER ::= 3
+ub-given-name-length INTEGER ::= 16
+ub-initials-length INTEGER ::= 5
+ub-integer-options INTEGER ::= 256
+ub-numeric-user-id-length INTEGER ::= 32
+ub-organization-name-length INTEGER ::= 64
+ub-organizational-unit-name-length INTEGER ::= 32
+ub-organizational-units INTEGER ::= 4
+ub-pds-name-length INTEGER ::= 16
+ub-pds-parameter-length INTEGER ::= 30
+ub-pds-physical-address-lines INTEGER ::= 6
+ub-postal-code-length INTEGER ::= 16
+ub-pseudonym INTEGER ::= 128
+ub-surname-length INTEGER ::= 40
+ub-terminal-id-length INTEGER ::= 24
+ub-unformatted-address-length INTEGER ::= 180
+ub-x121-address-length INTEGER ::= 16
+
+-- Misc OIDs from RFC5280. We should add related types as well.
+
+-- Policy qualifiers
+id-pkix-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
+id-pkix-qt-cps OBJECT IDENTIFIER ::= { id-pkix-qt 1 }
+id-pkix-qt-unotice OBJECT IDENTIFIER ::= { id-pkix-qt 2 }
+
+-- Access description
+id-pkix-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
+id-pkix-ad-ocsp OBJECT IDENTIFIER ::= { id-pkix-ad 1 }
+id-pkix-ad-caIssuers OBJECT IDENTIFIER ::= { id-pkix-ad 2 }
+id-pkix-ad-timeStamping OBJECT IDENTIFIER ::= { id-pkix-ad 3 }
+id-pkix-ad-caRepository OBJECT IDENTIFIER ::= { id-pkix-ad 5 }
+
+pq-CPS _POLICYQUALIFIERINFO ::= {
+ &id id-pkix-qt-cps,
+ &Type AliasIA5String
+}
+pq-UserNotice _POLICYQUALIFIERINFO ::= {
+ &id id-pkix-qt-unotice,
+ &Type UserNotice
+}
+KnownPolicyQualifiers _POLICYQUALIFIERINFO ::= {
+ pq-CPS
+ | pq-UserNotice
+}
+PolicyQualifierInfo ::= PolicyQualifierInfo{KnownPolicyQualifiers}
+
+END
diff --git a/third_party/heimdal/lib/asn1/rfc2459.opt b/third_party/heimdal/lib/asn1/rfc2459.opt
new file mode 100644
index 0000000..2070568
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/rfc2459.opt
@@ -0,0 +1,12 @@
+--preserve-binary=Name
+--preserve-binary=TBSCertificate
+--preserve-binary=TBSCRLCertList
+--sequence=AttributeValues
+--sequence=CRLDistributionPoints
+--sequence=Extensions
+--sequence=GeneralNames
+--sequence=RDNSequence
+--sequence=Certificates
+--sequence=CertificatePolicies
+--sequence=PolicyQualifierInfos
+--sequence=PolicyMappings
diff --git a/third_party/heimdal/lib/asn1/rfc4108.asn1 b/third_party/heimdal/lib/asn1/rfc4108.asn1
new file mode 100644
index 0000000..34f9396
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/rfc4108.asn1
@@ -0,0 +1,207 @@
+CMSFirmwareWrapper
+ { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
+ pkcs-9(9) smime(16) modules(0) cms-firmware-wrap(22) }
+
+DEFINITIONS IMPLICIT TAGS ::= BEGIN
+
+IMPORTS
+ -- We moved HardwareModuleName to avoid circular dependencies if
+ -- we have to have rfc2459 import it from here so we can define an
+ -- object set of OTHER-NAME class.
+ EnvelopedData
+ FROM cms -- [CMS]
+ { iso(1) member-body(2) us(840) rsadsi(113549)
+ pkcs(1) pkcs-9(9) smime(16) modules(0) cms-2004(24) };
+
+
+-- Firmware Package Content Type and Object Identifier
+
+id-ct-firmwarePackage OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ smime(16) ct(1) 16 }
+
+FirmwarePkgData ::= OCTET STRING
+
+
+-- Firmware Package Signed Attributes and Object Identifiers
+
+id-aa-firmwarePackageID OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ smime(16) aa(2) 35 }
+
+PreferredPackageIdentifier ::= SEQUENCE {
+ fwPkgID OBJECT IDENTIFIER,
+ verNum INTEGER (0..MAX) }
+
+PreferredOrLegacyPackageIdentifier ::= CHOICE {
+ preferred PreferredPackageIdentifier,
+ legacy OCTET STRING }
+
+PreferredOrLegacyStalePackageIdentifier ::= CHOICE {
+ preferredStaleVerNum INTEGER (0..MAX),
+ legacyStaleVersion OCTET STRING }
+
+FirmwarePackageIdentifier ::= SEQUENCE {
+ name PreferredOrLegacyPackageIdentifier,
+ stale PreferredOrLegacyStalePackageIdentifier OPTIONAL }
+
+
+id-aa-targetHardwareIDs OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ smime(16) aa(2) 36 }
+
+TargetHardwareIdentifiers ::= SEQUENCE OF OBJECT IDENTIFIER
+
+
+id-aa-decryptKeyID OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ smime(16) aa(2) 37 }
+
+DecryptKeyIdentifier ::= OCTET STRING
+
+
+id-aa-implCryptoAlgs OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ smime(16) aa(2) 38 }
+
+ImplementedCryptoAlgorithms ::= SEQUENCE OF OBJECT IDENTIFIER
+
+id-aa-implCompressAlgs OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ smime(16) aa(2) 43 }
+
+ImplementedCompressAlgorithms ::= SEQUENCE OF OBJECT IDENTIFIER
+
+
+id-aa-communityIdentifiers OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ smime(16) aa(2) 40 }
+
+HardwareSerialEntry ::= CHOICE {
+ all NULL,
+ single OCTET STRING,
+ block SEQUENCE {
+ low OCTET STRING,
+ high OCTET STRING } }
+
+HardwareModules ::= SEQUENCE {
+ hwType OBJECT IDENTIFIER,
+ hwSerialEntries SEQUENCE OF HardwareSerialEntry }
+
+CommunityIdentifier ::= CHOICE {
+ communityOID OBJECT IDENTIFIER,
+ hwModuleList HardwareModules }
+
+CommunityIdentifiers ::= SEQUENCE OF CommunityIdentifier
+
+id-aa-firmwarePackageInfo OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ smime(16) aa(2) 42 }
+
+FirmwarePackageInfo ::= SEQUENCE {
+ fwPkgType INTEGER OPTIONAL,
+ dependencies SEQUENCE OF
+ PreferredOrLegacyPackageIdentifier OPTIONAL }
+
+
+-- Firmware Package Unsigned Attributes and Object Identifiers
+
+id-aa-wrappedFirmwareKey OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ smime(16) aa(2) 39 }
+
+WrappedFirmwareKey ::= EnvelopedData
+
+
+-- Firmware Package Load Receipt Content Type and Object Identifier
+
+id-ct-firmwareLoadReceipt OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ smime(16) ct(1) 17 }
+
+FWReceiptVersion ::= INTEGER { rfc4108-v1(1) }
+
+FirmwarePackageLoadReceipt ::= SEQUENCE {
+ version FWReceiptVersion DEFAULT 1, -- v1, but asn1_compile doesn't handle this
+ hwType OBJECT IDENTIFIER,
+ hwSerialNum OCTET STRING,
+ fwPkgName PreferredOrLegacyPackageIdentifier,
+ trustAnchorKeyID OCTET STRING OPTIONAL,
+ decryptKeyID [1] OCTET STRING OPTIONAL }
+
+-- Firmware Package Load Error Report Content Type
+-- and Object Identifier
+
+id-ct-firmwareLoadError OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ smime(16) ct(1) 18 }
+
+FWErrorVersion ::= FWReceiptVersion
+
+FirmwarePackageLoadErrorCode ::= ENUMERATED {
+ decodeFailure (1),
+ badContentInfo (2),
+ badSignedData (3),
+ badEncapContent (4),
+ badCertificate (5),
+ badSignerInfo (6),
+ badSignedAttrs (7),
+ badUnsignedAttrs (8),
+ missingContent (9),
+ noTrustAnchor (10),
+ notAuthorized (11),
+ badDigestAlgorithm (12),
+ badSignatureAlgorithm (13),
+ unsupportedKeySize (14),
+ signatureFailure (15),
+ contentTypeMismatch (16),
+ badEncryptedData (17),
+ unprotectedAttrsPresent (18),
+ badEncryptContent (19),
+ badEncryptAlgorithm (20),
+ missingCiphertext (21),
+ noDecryptKey (22),
+ decryptFailure (23),
+ badCompressAlgorithm (24),
+ missingCompressedContent (25),
+ decompressFailure (26),
+ wrongHardware (27),
+ stalePackage (28),
+ notInCommunity (29),
+ unsupportedPackageType (30),
+ missingDependency (31),
+ wrongDependencyVersion (32),
+ insufficientMemory (33),
+ badFirmware (34),
+ unsupportedParameters (35),
+ breaksDependency (36),
+ otherError (99) }
+
+VendorLoadErrorCode ::= INTEGER
+
+CurrentFWConfig ::= SEQUENCE {
+ fwPkgType INTEGER OPTIONAL,
+ fwPkgName PreferredOrLegacyPackageIdentifier }
+
+FirmwarePackageLoadError ::= SEQUENCE {
+ version FWErrorVersion DEFAULT 1, -- v1, but see above
+ hwType OBJECT IDENTIFIER,
+ hwSerialNum OCTET STRING,
+ errorCode FirmwarePackageLoadErrorCode,
+ vendorErrorCode VendorLoadErrorCode OPTIONAL,
+ fwPkgName PreferredOrLegacyPackageIdentifier OPTIONAL,
+ config [1] SEQUENCE OF CurrentFWConfig OPTIONAL }
+
+-- Other Name syntax for Hardware Module Name
+
+id-on-hardwareModuleName OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) dod(6) internet(1) security(5)
+ mechanisms(5) pkix(7) on(8) 4 }
+
+-- Moved to rfc2459.asn1 so we can have the OtherName type decode it
+-- automatically:
+--HardwareModuleName ::= SEQUENCE {
+-- hwType OBJECT IDENTIFIER,
+-- hwSerialNum OCTET STRING }
+
+END
diff --git a/third_party/heimdal/lib/asn1/roken_rename.h b/third_party/heimdal/lib/asn1/roken_rename.h
new file mode 100644
index 0000000..76e108a
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/roken_rename.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id$ */
+
+#ifndef __roken_rename_h__
+#define __roken_rename_h__
+
+#ifndef HAVE_STRTOLL
+#define strtoll rk_strtoll
+#endif
+#ifndef HAVE_STRTOULL
+#define strtoull rk_strtoull
+#endif
+
+#endif /* __roken_rename_h__ */
diff --git a/third_party/heimdal/lib/asn1/setchgpw2.asn1 b/third_party/heimdal/lib/asn1/setchgpw2.asn1
new file mode 100644
index 0000000..2f52cb1
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/setchgpw2.asn1
@@ -0,0 +1,193 @@
+-- $Id$
+
+SETCHGPW2 DEFINITIONS ::=
+BEGIN
+
+IMPORTS PrincipalName, Realm, ENCTYPE FROM krb5;
+
+ProtocolErrorCode ::= ENUMERATED {
+ generic-error(0),
+ unsupported-major-version(1),
+ unsupported-minor-version(2),
+ unsupported-operation(3),
+ authorization-failed(4),
+ initial-ticket-required(5),
+ target-principal-unknown(6),
+ ...
+}
+
+Key ::= SEQUENCE {
+ enc-type[0] INTEGER,
+ key[1] OCTET STRING,
+ ...
+}
+
+Language-Tag ::= UTF8String -- Constrained by RFC3066
+
+LangTaggedText ::= SEQUENCE {
+ language[0] Language-Tag OPTIONAL,
+ text[1] UTF8String,
+ ...
+}
+
+-- NULL Op
+
+Req-null ::= NULL
+Rep-null ::= NULL
+Err-null ::= NULL
+
+-- Change password
+Req-change-pw ::= SEQUENCE {
+ old-pw[0] UTF8String,
+ new-pw[1] UTF8String OPTIONAL,
+ etypes[2] SEQUENCE OF ENCTYPE OPTIONAL,
+ ...
+}
+
+Rep-change-pw ::= SEQUENCE {
+ info-text[0] UTF8String OPTIONAL,
+ new-pw[1] UTF8String OPTIONAL,
+ etypes[2] SEQUENCE OF ENCTYPE OPTIONAL
+}
+
+Err-change-pw ::= SEQUENCE {
+ help-text[0] UTF8String OPTIONAL,
+ code[1] ENUMERATED {
+ generic(0),
+ wont-generate-new-pw(1),
+ old-pw-incorrect(2),
+ new-pw-rejected-geneneric(3),
+ pw-change-too-short(4),
+ ...
+ },
+ suggested-new-pw[2] UTF8String OPTIONAL,
+ ...
+}
+
+-- Change/Set keys
+Req-set-keys ::= SEQUENCE {
+ etypes[0] SEQUENCE OF ENCTYPE,
+ entropy[1] OCTET STRING,
+ ...
+}
+
+Rep-set-keys ::= SEQUENCE {
+ info-text[0] UTF8String OPTIONAL,
+ kvno[1] INTEGER,
+ keys[2] SEQUENCE OF Key,
+ aliases[3] SEQUENCE OF SEQUENCE {
+ name[0] PrincipalName,
+ realm[1] Realm OPTIONAL,
+ ...
+ },
+ ...
+}
+
+Err-set-keys ::= SEQUENCE {
+ help-text[0] UTF8String OPTIONAL,
+ enctypes[1] SEQUENCE OF ENCTYPE OPTIONAL,
+ code[1] ENUMERATED {
+ etype-no-support(0),
+ ...
+ },
+ ...
+}
+
+-- Get password policy
+Req-get-pw-policy ::= NULL
+
+Rep-get-pw-policy ::= SEQUENCE {
+ help-text[0] UTF8String OPTIONAL,
+ policy-name[1] UTF8String OPTIONAL,
+ description[2] UTF8String OPTIONAL,
+ ...
+}
+
+Err-get-pw-policy ::= NULL
+
+-- Get principal aliases
+Req-get-princ-aliases ::= NULL
+
+Rep-get-princ-aliases ::= SEQUENCE {
+ help-text[0] UTF8String OPTIONAL,
+ aliases[1] SEQUENCE OF SEQUENCE {
+ name[0] PrincipalName,
+ realm[1] Realm OPTIONAL,
+ ...
+ } OPTIONAL,
+ ...
+}
+
+Err-get-princ-aliases ::= NULL
+
+-- Get list of encryption types supported by KDC for new types
+Req-get-supported-etypes ::= NULL
+
+Rep-get-supported-etypes ::= SEQUENCE OF ENCTYPE
+
+Err-get-supported-etypes ::= NULL
+
+-- Choice switch
+
+Op-req ::= CHOICE {
+ null[0] Req-null,
+ change-pw[1] Req-change-pw,
+ set-keys[2] Req-set-keys,
+ get-pw-policy[3] Req-get-pw-policy,
+ get-princ-aliases[4] Req-get-princ-aliases,
+ get-supported-etypes[5] Req-get-supported-etypes,
+ ...
+}
+
+Op-rep ::= CHOICE {
+ null[0] Rep-null,
+ change-pw[1] Rep-change-pw,
+ set-keys[2] Rep-set-keys,
+ get-pw-policy[3] Rep-get-pw-policy,
+ get-princ-aliases[4] Rep-get-princ-aliases,
+ get-supported-etypes[5] Rep-get-supported-etypes,
+ ...
+}
+
+Op-error ::= CHOICE {
+ null[0] Err-null,
+ change-pw[1] Err-change-pw,
+ set-keys[2] Err-set-keys,
+ get-pw-policy[3] Err-get-pw-policy,
+ get-princ-aliases[4] Err-get-princ-aliases,
+ get-supported-etypes[5] Err-get-supported-etypes,
+ ...
+}
+
+
+Request ::= [ APPLICATION 0 ] SEQUENCE {
+ pvno-major[0] INTEGER DEFAULT 2,
+ pvno-minor[1] INTEGER DEFAULT 0,
+ languages[2] SEQUENCE OF Language-Tag OPTIONAL,
+ targ-name[3] PrincipalName OPTIONAL,
+ targ-realm[4] Realm OPTIONAL,
+ operation[5] Op-Req,
+ ...
+}
+
+Response ::= [ APPLICATION 1 ] SEQUENCE {
+ pvno-major[0] INTEGER DEFAULT 2,
+ pvno-minor[1] INTEGER DEFAULT 0,
+ language[2] Language-Tag DEFAULT "i-default",
+ result[3] Op-rep OPTIONAL,
+ ...
+}
+
+Error-Response ::= [ APPLICATION 2 ] SEQUENCE {
+ pvno-major[0] INTEGER DEFAULT 2,
+ pvno-minor[1] INTEGER DEFAULT 0,
+ language[2] Language-Tag DEFAULT "i-default",
+ error-code[3] ProtocolErrorCode,
+ help-text[4] UTF8String OPTIONAL,
+ op-error[5] Op-error OP-ERROR,
+ ...
+}
+
+END
+
+-- etags -r '/\([A-Za-z][-A-Za-z0-9]*\).*::=/\1/' setchgpw2.asn1
diff --git a/third_party/heimdal/lib/asn1/symbol.c b/third_party/heimdal/lib/asn1/symbol.c
new file mode 100644
index 0000000..b472ebd
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/symbol.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gen_locl.h"
+#include "lex.h"
+#include "lex.h"
+
+static Hashtab *htab;
+
+struct symhead symbols;
+
+static int
+cmp(void *a, void *b)
+{
+ Symbol *s1 = (Symbol *) a;
+ Symbol *s2 = (Symbol *) b;
+
+ return strcmp(s1->name, s2->name);
+}
+
+static unsigned
+hash(void *a)
+{
+ Symbol *s = (Symbol *) a;
+
+ return hashjpw(s->name);
+}
+
+void
+initsym(void)
+{
+ htab = hashtabnew(101, cmp, hash);
+}
+
+
+void
+output_name(char *s)
+{
+ char *p;
+
+ for (p = s; *p; ++p)
+ if (*p == '-' || *p == '.')
+ *p = '_';
+}
+
+Symbol *
+addsym(char *name)
+{
+ Symbol key, *s;
+
+ key.name = name;
+ s = (Symbol *) hashtabsearch(htab, (void *) &key);
+ if (s == NULL) {
+ s = (Symbol *) ecalloc(1, sizeof(*s));
+ s->name = name;
+ s->gen_name = estrdup(name);
+ output_name(s->gen_name);
+ s->stype = SUndefined;
+ hashtabadd(htab, s);
+ //HEIM_TAILQ_INSERT_TAIL(&symbols, s, symlist);
+ do {
+ if (((s)->symlist.tqe_next = (&symbols)->tqh_first) != NULL)
+ (&symbols)->tqh_first->symlist.tqe_prev = &(s)->symlist.tqe_next;
+ else
+ (&symbols)->tqh_last = &(s)->symlist.tqe_next;
+ (&symbols)->tqh_first = (s);
+ (s)->symlist.tqe_prev = &(&symbols)->tqh_first;
+ } while (0);
+ }
+ return s;
+}
+
+Symbol *
+getsym(char *name)
+{
+ Symbol key;
+
+ key.name = name;
+ return (Symbol *) hashtabsearch(htab, (void *) &key);
+}
+
+static int
+checkfunc(void *ptr, void *arg)
+{
+ Symbol *s = ptr;
+ if (s->stype == SUndefined) {
+ lex_error_message("%s is still undefined\n", s->name);
+ *(int *) arg = 1;
+ }
+ return 0;
+}
+
+int
+checkundefined(void)
+{
+ int f = 0;
+ hashtabforeach(htab, checkfunc, &f);
+ return f;
+}
+
+#if 0
+static int
+generate_1type(void *ptr, void *arg)
+{
+ Symbol *s = ptr;
+
+ if (s->stype == Stype && s->type)
+ generate_type(s);
+ return 0;
+}
+#endif
+
+void
+generate_types(void)
+{
+ Symbol *s;
+
+ if (checkundefined())
+ errx(1, "Some types are undefined");
+ HEIM_TAILQ_FOREACH_REVERSE(s, &symbols, symhead, symlist) {
+ if (s->stype == Stype && s->type)
+ generate_type(s);
+ }
+ //hashtabforeach(htab, generate_1type, NULL);
+}
+
+void
+emitted_declaration(const Symbol *s)
+{
+ ((Symbol *)(uintptr_t)s)->emitted_declaration = 1;
+}
+
+void
+emitted_definition(const Symbol *s)
+{
+ ((Symbol *)(uintptr_t)s)->emitted_definition = 1;
+}
+
+void
+emitted_tag_enums(const Symbol *s)
+{
+ ((Symbol *)(uintptr_t)s)->emitted_tag_enums = 1;
+}
+
+void
+emitted_asn1(const Symbol *s)
+{
+ ((Symbol *)(uintptr_t)s)->emitted_asn1 = 1;
+}
diff --git a/third_party/heimdal/lib/asn1/symbol.h b/third_party/heimdal/lib/asn1/symbol.h
new file mode 100644
index 0000000..108749b
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/symbol.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id$ */
+
+#ifndef _SYMBOL_H
+#define _SYMBOL_H
+
+#include <heimqueue.h>
+
+enum typetype {
+ TBitString,
+ TBoolean,
+ TChoice,
+ TEnumerated,
+ TGeneralString,
+ TTeletexString,
+ TGeneralizedTime,
+ TIA5String,
+ TInteger,
+ TNull,
+ TOID,
+ TOctetString,
+ TPrintableString,
+ TSequence,
+ TSequenceOf,
+ TSet,
+ TSetOf,
+ TTag,
+ TType,
+ TUTCTime,
+ TUTF8String,
+ TBMPString,
+ TUniversalString,
+ TVisibleString
+};
+
+typedef enum typetype Typetype;
+
+struct type;
+struct value;
+struct typereference;
+
+struct value {
+ enum { booleanvalue,
+ nullvalue,
+ integervalue,
+ stringvalue,
+ objectidentifiervalue
+ } type;
+ union {
+ int booleanvalue;
+ int64_t integervalue;
+ char *stringvalue;
+ struct objid *objectidentifiervalue;
+ } u;
+ struct symbol *s;
+};
+
+struct member {
+ char *name;
+ char *gen_name;
+ char *label;
+ int64_t val;
+ int optional;
+ int ellipsis;
+ struct type *type;
+ HEIM_TAILQ_ENTRY(member) members;
+ struct value *defval;
+};
+
+typedef struct member Member;
+
+HEIM_TAILQ_HEAD(memhead, member);
+
+struct symbol;
+
+struct tagtype {
+ int tagclass;
+ int tagvalue;
+ enum { TE_IMPLICIT, TE_EXPLICIT } tagenv;
+};
+
+struct range {
+ /*
+ * We can't represent unsigned 64-bit ranges because max might be
+ * negative...
+ */
+ int64_t min;
+ int64_t max;
+};
+
+enum ctype { CT_CONTENTS, CT_USER, CT_TABLE_CONSTRAINT, CT_RANGE } ;
+
+struct constraint_spec;
+
+struct iosclassfield {
+ char *name;
+ struct type *type;
+ struct value *defval;
+ HEIM_TAILQ_ENTRY(iosclassfield) fields;
+ unsigned long id;
+ unsigned int optional:1;
+ unsigned int unique:1;
+};
+
+typedef struct iosclassfield Field;
+HEIM_TAILQ_HEAD(fieldhead, iosclassfield);
+
+struct iosobjectfield {
+ char *name;
+ struct type *type;
+ struct value *value;
+ HEIM_TAILQ_ENTRY(iosobjectfield) objfields;
+ unsigned long id;
+};
+
+typedef struct iosobjectfield ObjectField;
+HEIM_TAILQ_HEAD(objfieldhead, iosobjectfield);
+
+struct iosclass {
+ struct symbol *symbol;
+ struct fieldhead *fields;
+ unsigned long id;
+};
+
+typedef struct iosclass IOSClass;
+
+struct iosobject {
+ struct symbol *symbol;
+ struct objfieldhead *objfields;
+ ObjectField *typeidf;
+ IOSClass *iosclass;
+ HEIM_TAILQ_ENTRY(iosobject) objects;
+ unsigned long id;
+ unsigned int ellipsis:1;
+ unsigned int optional:1;
+};
+
+typedef struct iosobject IOSObject;
+HEIM_TAILQ_HEAD(objectshead, iosobject);
+
+struct iosobjectset {
+ struct symbol *symbol;
+ IOSClass *iosclass;
+ struct objectshead *objects;
+ unsigned long id;
+};
+
+typedef struct iosobjectset IOSObjectSet;
+
+struct typereference {
+ /*
+ * For now we don't support link fields, so we don't support chains of more
+ * than one field.
+ */
+ IOSClass *iosclass;
+ Field *field;
+};
+
+struct type {
+ Typetype type;
+ struct memhead *members;
+ struct symbol *symbol;
+ struct type *subtype;
+ struct typereference typeref; /* For type fields */
+ IOSClass *formal_parameter;
+ IOSObjectSet *actual_parameter;
+ struct tagtype tag;
+ struct range *range;
+ struct constraint_spec *constraint;
+ unsigned long id;
+ unsigned int implicit_choice:1;
+};
+
+typedef struct type Type;
+
+struct component_relation_constraint {
+ char *objectname;
+ char *membername;
+};
+
+struct constraint_spec {
+ enum ctype ctype;
+ union {
+ struct {
+ Type *type;
+ struct value *encoding;
+ struct component_relation_constraint crel;
+ } content;
+ struct range *range;
+ } u;
+};
+
+struct objid {
+ const char *label;
+ int value;
+ struct objid *next;
+};
+
+struct symbol {
+ char *name;
+ char *gen_name;
+ enum { SUndefined, SValue, Stype, Sparamtype, Sclass, Sobj, Sobjset } stype;
+ struct value *value;
+ Type *type;
+ IOSClass *iosclass;
+ IOSObject *object;
+ IOSObjectSet *objectset;
+ HEIM_TAILQ_ENTRY(symbol) symlist;
+ unsigned int emitted_asn1:1;
+ unsigned int emitted_declaration:1;
+ unsigned int emitted_definition:1;
+ unsigned int emitted_tag_enums:1;
+ unsigned int emitted_template:1;
+};
+
+typedef struct symbol Symbol;
+
+//HEIM_TAILQ_HEAD(symhead, symbol);
+struct symhead {
+ struct symbol *tqh_first;
+ struct symbol **tqh_last;
+};
+
+extern struct symhead symbols;
+
+void initsym (void);
+Symbol *addsym (char *);
+Symbol *getsym(char *name);
+void output_name (char *);
+int checkundefined(void);
+void generate_types(void);
+void emitted_asn1(const Symbol *);
+void emitted_declaration(const Symbol *);
+void emitted_definition(const Symbol *);
+void emitted_tag_enums(const Symbol *);
+#endif
diff --git a/third_party/heimdal/lib/asn1/tcg.asn1 b/third_party/heimdal/lib/asn1/tcg.asn1
new file mode 100644
index 0000000..14129b0
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/tcg.asn1
@@ -0,0 +1,42 @@
+TCG DEFINITIONS ::= BEGIN
+
+-- BEGIN Heimdal commentary
+--
+-- Copy-pasted from section 4 of
+-- https://trustedcomputinggroup.org/wp-content/uploads/TCG_IWG_EKCredentialProfile_v2p3_r2_pub.pdf
+-- https://trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf
+-- and adjusted to compile as follows:
+--
+-- - Due to limitations of the Heimdal compiler we've moved all of this
+-- module's contents to rfc2459.asn1.
+--
+-- - Extensibility markers added to all SEQUENCEs as per the TCG's spec they
+-- reserve the right to add fields in the future.
+-- - Information Object System annotations commented out (Heimdal does not
+-- support them)
+--
+-- - Types sorted topologically (at the time I did that the Heimdal ASN.1
+-- compiler wouldn't do that on its own)
+--
+-- - Two otherwise equal ENUMERATED types share a definition now (at the time
+-- the Heimdal ASN.1 compiler did not prefix labels of ENUMERATED types)
+--
+-- A small note for anyone whoever finds this: do not add complex structures as
+-- DN attributes, or, indeed, never add DN attributes again. If some metadata
+-- is name-like, then add a subjectAlternativeName otherName for it, otherwise
+-- add a certificate extension to carry that metadata. And, for any name-like
+-- metadata, always always include query and display syntax for it.
+--
+-- Anyone designing anything but the simplest schema in ASN.1 should have to
+-- learn a bit more about ASN.1 and/or get a review from ASN.1 experts.
+--
+-- Anyone designing anything but the simplest x.509 extensions should have to
+-- learn a bit more about ASN.1 and x.509 and/or get a review from x.509
+-- experts.
+--
+-- Note that a module OID was not provided. Indeed, a valid, complete ASN.1
+-- module was not provided.
+--
+-- END Heimdal commentary (though some minor Heimdal commentary appears below)
+
+END
diff --git a/third_party/heimdal/lib/asn1/template.c b/third_party/heimdal/lib/asn1/template.c
new file mode 100644
index 0000000..ed215d8
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/template.c
@@ -0,0 +1,3104 @@
+/*
+ * Copyright (c) 2009 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 - 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+#include <com_err.h>
+#include <vis.h>
+#include <vis-extras.h>
+#include <heimbase.h>
+
+#ifndef ENOTSUP
+/* Very old MSVC CRTs don't have ENOTSUP */
+#define ENOTSUP EINVAL
+#endif
+
+struct asn1_type_func asn1_template_prim[A1T_NUM_ENTRY] = {
+#define el(name, type) { \
+ (asn1_type_encode)der_put_##name, \
+ (asn1_type_decode)der_get_##name, \
+ (asn1_type_length)der_length_##name, \
+ (asn1_type_copy)der_copy_##name, \
+ (asn1_type_release)der_free_##name, \
+ (asn1_type_print)der_print_##name, \
+ sizeof(type) \
+ }
+#define elber(name, type) { \
+ (asn1_type_encode)der_put_##name, \
+ (asn1_type_decode)der_get_##name##_ber, \
+ (asn1_type_length)der_length_##name, \
+ (asn1_type_copy)der_copy_##name, \
+ (asn1_type_release)der_free_##name, \
+ (asn1_type_print)der_print_##name, \
+ sizeof(type) \
+ }
+ el(integer, int),
+ el(heim_integer, heim_integer),
+ el(integer, int),
+ el(integer64, int64_t),
+ el(unsigned, unsigned),
+ el(unsigned64, uint64_t),
+ el(general_string, heim_general_string),
+ el(octet_string, heim_octet_string),
+ elber(octet_string, heim_octet_string),
+ el(ia5_string, heim_ia5_string),
+ el(bmp_string, heim_bmp_string),
+ el(universal_string, heim_universal_string),
+ el(printable_string, heim_printable_string),
+ el(visible_string, heim_visible_string),
+ el(utf8string, heim_utf8_string),
+ el(generalized_time, time_t),
+ el(utctime, time_t),
+ el(bit_string, heim_bit_string),
+ { (asn1_type_encode)der_put_boolean, (asn1_type_decode)der_get_boolean,
+ (asn1_type_length)der_length_boolean, (asn1_type_copy)der_copy_integer,
+ (asn1_type_release)der_free_integer, (asn1_type_print)der_print_boolean,
+ sizeof(int)
+ },
+ el(oid, heim_oid),
+ el(general_string, heim_general_string),
+#undef el
+#undef elber
+};
+
+size_t
+_asn1_sizeofType(const struct asn1_template *t)
+{
+ return t->offset;
+}
+
+/*
+ * Here is abstraction to not so well evil fact of bit fields in C,
+ * they are endian dependent, so when getting and setting bits in the
+ * host local structure we need to know the endianness of the host.
+ *
+ * Its not the first time in Heimdal this have bitten us, and some day
+ * we'll grow up and use #defined constant, but bit fields are still
+ * so pretty and shiny.
+ */
+
+static void
+_asn1_bmember_get_bit(const unsigned char *p, void *data,
+ unsigned int bit, size_t size)
+{
+ unsigned int localbit = bit % 8;
+ if ((*p >> (7 - localbit)) & 1) {
+#ifdef WORDS_BIGENDIAN
+ *(unsigned int *)data |= (1u << ((size * 8) - bit - 1));
+#else
+ *(unsigned int *)data |= (1u << bit);
+#endif
+ }
+}
+
+int
+_asn1_bmember_isset_bit(const void *data, unsigned int bit, size_t size)
+{
+#ifdef WORDS_BIGENDIAN
+ if ((*(unsigned int *)data) & (1u << ((size * 8) - bit - 1)))
+ return 1;
+ return 0;
+#else
+ if ((*(unsigned int *)data) & (1u << bit))
+ return 1;
+ return 0;
+#endif
+}
+
+void
+_asn1_bmember_put_bit(unsigned char *p, const void *data, unsigned int bit,
+ size_t size, unsigned int *bitset)
+{
+ unsigned int localbit = bit % 8;
+
+ if (_asn1_bmember_isset_bit(data, bit, size)) {
+ *p |= (1u << (7 - localbit));
+ if (*bitset == 0)
+ *bitset = (7 - localbit) + 1;
+ }
+}
+
+/*
+ * Utility function to tell us if the encoding of some type per its template
+ * will have an outer tag. This is needed when the caller wants to slap on an
+ * IMPLICIT tag: if the inner type has a tag then we need to replace it.
+ */
+static int
+is_tagged(const struct asn1_template *t)
+{
+ size_t elements = A1_HEADER_LEN(t);
+
+ t += A1_HEADER_LEN(t);
+ if (elements != 1)
+ return 0;
+ switch (t->tt & A1_OP_MASK) {
+ case A1_OP_SEQOF: return 0;
+ case A1_OP_SETOF: return 0;
+ case A1_OP_BMEMBER: return 0;
+ case A1_OP_PARSE: return 0;
+ case A1_OP_TAG: return 1;
+ case A1_OP_CHOICE: return 1;
+ case A1_OP_TYPE: return 1;
+ case A1_OP_TYPE_EXTERN: {
+ const struct asn1_type_func *f = t->ptr;
+
+ /*
+ * XXX Add a boolean to struct asn1_type_func to tell us if the type is
+ * tagged or not. Basically, it's not tagged if it's primitive.
+ */
+ if (f->encode == (asn1_type_encode)encode_heim_any ||
+ f->encode == (asn1_type_encode)encode_HEIM_ANY)
+ return 0;
+ abort(); /* XXX */
+ }
+ default: abort();
+ }
+}
+
+static size_t
+inner_type_taglen(const struct asn1_template *t)
+{
+ size_t elements = A1_HEADER_LEN(t);
+
+ t += A1_HEADER_LEN(t);
+ if (elements != 1)
+ return 0;
+ switch (t->tt & A1_OP_MASK) {
+ case A1_OP_SEQOF: return 0;
+ case A1_OP_SETOF: return 0;
+ case A1_OP_BMEMBER: return 0;
+ case A1_OP_PARSE: return 0;
+ case A1_OP_CHOICE: return 1;
+ case A1_OP_TYPE: return inner_type_taglen(t->ptr);
+ case A1_OP_TAG: return der_length_tag(A1_TAG_TAG(t->tt));
+ case A1_OP_TYPE_EXTERN: {
+ const struct asn1_type_func *f = t->ptr;
+
+ /*
+ * XXX Add a boolean to struct asn1_type_func to tell us if the type is
+ * tagged or not. Basically, it's not tagged if it's primitive.
+ */
+ if (f->encode == (asn1_type_encode)encode_heim_any ||
+ f->encode == (asn1_type_encode)encode_HEIM_ANY)
+ return 0;
+ abort(); /* XXX */
+ }
+ default: abort();
+#ifdef WIN32
+ _exit(0); /* Quiet VC */
+#endif
+ }
+}
+
+/*
+ * Compare some int of unknown size in a type ID field to the int value in
+ * some IOS object's type ID template entry.
+ *
+ * This should be called with a `A1_TAG_T(ASN1_C_UNIV, PRIM, UT_Integer)'
+ * template as the `ttypeid'.
+ */
+static int
+typeid_int_cmp(const void *intp,
+ int64_t i,
+ const struct asn1_template *ttypeid)
+{
+ const struct asn1_template *tint = ttypeid->ptr;
+
+ if ((tint[1].tt & A1_OP_MASK) != A1_OP_PARSE)
+ return -1;
+ if (A1_PARSE_TYPE(tint[1].tt) != A1T_INTEGER &&
+ A1_PARSE_TYPE(tint[1].tt) != A1T_UNSIGNED &&
+ A1_PARSE_TYPE(tint[1].tt) != A1T_INTEGER64 &&
+ A1_PARSE_TYPE(tint[1].tt) != A1T_UNSIGNED64 &&
+ A1_PARSE_TYPE(tint[1].tt) != A1T_IMEMBER)
+ return -1;
+ switch (tint[0].offset) {
+ case 8: return i - *(const int64_t *)intp;
+ case 4: return i - *(const int32_t *)intp;
+ default: return -1;
+ }
+}
+
+/*
+ * Map a logical SET/SEQUENCE member to a template entry.
+ *
+ * This should really have been done by the compiler, but clearly it wasn't.
+ *
+ * The point is that a struct type's template may be littered with entries that
+ * don't directly correspond to a struct field (SET/SEQUENCE member), so we
+ * have to count just the ones that do to get to the one we want.
+ */
+static const struct asn1_template *
+template4member(const struct asn1_template *t, size_t f)
+{
+ size_t n = (uintptr_t)t->ptr;
+ size_t i;
+
+ for (i = 0, t++; i < n; t++, i++) {
+ switch (t->tt & A1_OP_MASK) {
+ case A1_OP_TAG:
+ case A1_OP_TYPE:
+ case A1_OP_TYPE_EXTERN:
+ if (f-- == 0)
+ return t;
+ continue;
+ case A1_OP_OPENTYPE_OBJSET:
+ case A1_OP_NAME:
+ return NULL;
+ default:
+ continue;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Attempt to decode known open type alternatives into a CHOICE-like
+ * discriminated union.
+ *
+ * Arguments:
+ *
+ * - object set template
+ * - decoder flags
+ * - pointer to memory object (C struct) to decode into
+ * - template for type ID field of `data'
+ * - template for open type field of `data' (an octet string or HEIM_ANY)
+ *
+ * Returns:
+ *
+ * - 0
+ * - ENOMEM
+ *
+ * Other errors in decoding open type values are ignored, but applications can
+ * note that an error must have occurred. (Perhaps we should generate a `ret'
+ * field for the discriminated union we decode into that we could use to
+ * indicate what went wrong with decoding an open type value? The application
+ * can always try to decode itself to find out what the error was, but the
+ * whole point is to save the developer the bother of writing code to decode
+ * open type values. Then again, the specific cause of any one decode failure
+ * is not usually very important to users, so it's not very important to
+ * applications either.)
+ *
+ * Here `data' is something like this:
+ *
+ * typedef struct SingleAttribute {
+ * heim_oid type; // <--- decoded already
+ * HEIM_ANY value; // <--- decoded already
+ * // We must set this:
+ * // vvvvvvvv
+ * struct {
+ * enum {
+ * choice_SingleAttribute_iosnumunknown = 0,
+ * choice_SingleAttribute_iosnum_id_at_name,
+ * ..
+ * choice_SingleAttribute_iosnum_id_at_emailAddress,
+ * } element; // <--- map type ID to enum
+ * union {
+ * X520name* at_name;
+ * X520name* at_surname;
+ * ..
+ * AliasIA5String* at_emailAddress;
+ * } u; // <--- alloc and decode val above into this
+ * } _ioschoice_value;
+ * } SingleAttribute;
+ *
+ * or
+ *
+ * typedef struct AttributeSet {
+ * heim_oid type; // <--- decoded already
+ * struct AttributeSet_values {
+ * unsigned int len; // <--- decoded already
+ * HEIM_ANY *val; // <--- decoded already
+ * } values;
+ * // We must set this:
+ * // vvvvvvvv
+ * struct {
+ * enum { choice_AttributeSet_iosnumunknown = 0,
+ * choice_AttributeSet_iosnum_id_at_name,
+ * choice_AttributeSet_iosnum_id_at_surname,
+ * ..
+ * choice_AttributeSet_iosnum_id_at_emailAddress,
+ * } element; // <--- map type ID to enum
+ * unsigned int len; // <--- set len to len as above
+ * union {
+ * X520name *at_name;
+ * X520name *at_surname;
+ * ..
+ * AliasIA5String *at_emailAddress;
+ * } *val; // <--- alloc and decode vals above into this
+ * } _ioschoice_values;
+ * } AttributeSet;
+ */
+static int
+_asn1_decode_open_type(const struct asn1_template *t,
+ unsigned flags,
+ void *data,
+ const struct asn1_template *ttypeid,
+ const struct asn1_template *topentype)
+{
+ const struct asn1_template *ttypeid_univ = ttypeid;
+ const struct asn1_template *tactual_type;
+ const struct asn1_template *tos = t->ptr;
+ size_t sz, n;
+ size_t i = 0;
+ unsigned int *lenp = NULL; /* Pointer to array length field */
+ unsigned int len = 1; /* Array length */
+ void **dp = NULL; /* Decoded open type struct pointer */
+ int *elementp; /* Choice enum pointer */
+ int typeid_is_oid = 0;
+ int typeid_is_int = 0;
+ int ret = 0;
+
+ /*
+ * NOTE: Here expressions like `DPO(data, t->offset + ...)' refer to parts
+ * of a _ioschoice_<fieldName> struct field of `data'.
+ *
+ * Expressions like `DPO(data, topentype->offset + ...)' refer to
+ * the open type field in `data', which is either a `heim_any', a
+ * `heim_octet_string', or an array of one of those.
+ *
+ * Expressions like `DPO(data, ttypeid->offset)' refer to the open
+ * type's type ID field in `data'.
+ */
+
+ /*
+ * Minimal setup:
+ *
+ * - set type choice to choice_<type>_iosnumunknown (zero).
+ * - set union value to zero
+ *
+ * We need a pointer to the choice ID:
+ *
+ * typedef struct AttributeSet {
+ * heim_oid type; // <--- decoded already
+ * struct AttributeSet_values {
+ * unsigned int len; // <--- decoded already
+ * HEIM_ANY *val; // <--- decoded already
+ * } values;
+ * struct {
+ * enum { choice_AttributeSet_iosnumunknown = 0,
+ * -----------> ...
+ * } element; // HERE
+ * ...
+ * } ...
+ * }
+ *
+ * XXX NOTE: We're assuming that sizeof(enum) == sizeof(int)!
+ */
+ elementp = DPO(data, t->offset);
+ *elementp = 0; /* Set the choice to choice_<type>_iosnumunknown */
+ if (t->tt & A1_OS_OT_IS_ARRAY) {
+ /*
+ * The open type is a SET OF / SEQUENCE OF -- an array.
+ *
+ * Get the number of elements to decode from:
+ *
+ * typedef struct AttributeSet {
+ * heim_oid type;
+ * struct AttributeSet_values {
+ * ------------>unsigned int len; // HERE
+ * HEIM_ANY *val;
+ * } values;
+ * ...
+ * }
+ */
+ len = *((unsigned int *)DPO(data, topentype->offset));
+
+ /*
+ * Set the number of decoded elements to zero for now:
+ *
+ * typedef struct AttributeSet {
+ * heim_oid type;
+ * struct AttributeSet_values {
+ * unsigned int len;
+ * HEIM_ANY *val;
+ * } values;
+ * struct {
+ * enum { ... } element;
+ * ------------>unsigned int len; // HERE
+ * ...
+ * } _ioschoice_values;
+ * }
+ */
+ lenp = DPO(data, t->offset + sizeof(*elementp));
+ *lenp = 0;
+ /*
+ * Get a pointer to the place where we must put the decoded value:
+ *
+ * typedef struct AttributeSet {
+ * heim_oid type;
+ * struct AttributeSet_values {
+ * unsigned int len;
+ * HEIM_ANY *val;
+ * } values;
+ * struct {
+ * enum { ... } element;
+ * unsigned int len;
+ * struct {
+ * union { SomeType *some_choice; ... } u;
+ * ------------>} *val; // HERE
+ * } _ioschoice_values;
+ * } AttributeSet;
+ */
+ dp = DPO(data, t->offset + sizeof(*elementp) + sizeof(*lenp));
+ } else {
+ /*
+ * Get a pointer to the place where we must put the decoded value:
+ *
+ * typedef struct SingleAttribute {
+ * heim_oid type;
+ * HEIM_ANY value;
+ * struct {
+ * enum { ... } element;
+ * ------------>union { SomeType *some_choice; ... } u; // HERE
+ * } _ioschoice_value;
+ * } SingleAttribute;
+ */
+ dp = DPO(data, t->offset + sizeof(*elementp));
+ }
+
+ /* Align `dp' */
+ while (sizeof(void *) != sizeof(*elementp) &&
+ ((uintptr_t)dp) % sizeof(void *) != 0)
+ dp = (void *)(((char *)dp) + sizeof(*elementp));
+ *dp = NULL;
+
+ /*
+ * Find out the type of the type ID member. We currently support only
+ * integers and OIDs.
+ *
+ * Chase through any tags to get to the type.
+ */
+ while (((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TAG &&
+ A1_TAG_CLASS(ttypeid_univ->tt) == ASN1_C_CONTEXT) ||
+ ((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TYPE)) {
+ ttypeid_univ = ttypeid_univ->ptr;
+ ttypeid_univ++;
+ }
+ switch (ttypeid_univ->tt & A1_OP_MASK) {
+ case A1_OP_TAG:
+ if (A1_TAG_CLASS(ttypeid_univ->tt) != ASN1_C_UNIV)
+ return 0; /* Do nothing, silently */
+ switch (A1_TAG_TAG(ttypeid_univ->tt)) {
+ case UT_OID:
+ typeid_is_oid = 1;
+ break;
+ case UT_Integer: {
+ const struct asn1_template *tint = ttypeid_univ->ptr;
+
+ tint++;
+
+ if ((tint->tt & A1_OP_MASK) != A1_OP_PARSE)
+ return 0; /* Do nothing, silently */
+ if (A1_PARSE_TYPE(tint->tt) != A1T_INTEGER &&
+ A1_PARSE_TYPE(tint->tt) != A1T_UNSIGNED &&
+ A1_PARSE_TYPE(tint->tt) != A1T_INTEGER64 &&
+ A1_PARSE_TYPE(tint->tt) != A1T_UNSIGNED64 &&
+ A1_PARSE_TYPE(tint->tt) != A1T_IMEMBER)
+ return 0; /* Do nothing, silently (maybe a large int) */
+ typeid_is_int = 1;
+ break;
+ }
+ /* It might be cool to support string types as type ID types */
+ default: return 0; /* Do nothing, silently */
+ }
+ break;
+ default: return 0; /* Do nothing, silently */
+ }
+
+ /*
+ * Find the type of the open type.
+ *
+ * An object set template looks like:
+ *
+ * const struct asn1_template asn1_ObjectSetName[] = {
+ * // Header entry (in this case it says there's 17 objects):
+ * { 0, 0, ((void*)17) },
+ *
+ * // here's the name of the object set:
+ * { A1_OP_NAME, 0, "ObjectSetName" },
+ *
+ * // then three entries per object: object name, object type ID,
+ * // object type:
+ * { A1_OP_NAME, 0, "ext-AuthorityInfoAccess" },
+ * { A1_OP_OPENTYPE_ID, 0, (const void*)&asn1_oid_oidName },
+ * { A1_OP_OPENTYPE, sizeof(SomeType), (const void*)&asn1_SomeType },
+ * ...
+ * };
+ *
+ * `i' being a logical object offset, i*3+3 would be the index of the
+ * A1_OP_OPENTYPE_ID entry for the current object, and i*3+4 the index of
+ * the A1_OP_OPENTYPE entry for the current object.
+ */
+ if (t->tt & A1_OS_IS_SORTED) {
+ size_t left = 0;
+ size_t right = A1_HEADER_LEN(tos);
+ const void *vp = DPO(data, ttypeid->offset);
+ int c = -1;
+
+ while (left < right) {
+ size_t mid = (left + right) >> 1;
+
+ if ((tos[3 + mid * 3].tt & A1_OP_MASK) != A1_OP_OPENTYPE_ID)
+ return 0;
+ if (typeid_is_int)
+ c = typeid_int_cmp(vp, (intptr_t)tos[3 + mid * 3].ptr,
+ ttypeid_univ);
+ else if (typeid_is_oid)
+ c = der_heim_oid_cmp(vp, tos[3 + mid * 3].ptr);
+ if (c < 0) {
+ right = mid;
+ } else if (c > 0) {
+ left = mid + 1;
+ } else {
+ i = mid;
+ break;
+ }
+ }
+ if (c)
+ return 0; /* No match */
+ } else {
+ for (i = 0, n = A1_HEADER_LEN(tos); i < n; i++) {
+ /* We add 1 to `i' because we're skipping the header */
+ if ((tos[3 + i*3].tt & A1_OP_MASK) != A1_OP_OPENTYPE_ID)
+ return 0;
+ if (typeid_is_int &&
+ typeid_int_cmp(DPO(data, ttypeid->offset),
+ (intptr_t)tos[3 + i*3].ptr,
+ ttypeid_univ))
+ continue;
+ if (typeid_is_oid &&
+ der_heim_oid_cmp(DPO(data, ttypeid->offset), tos[3 + i*3].ptr))
+ continue;
+ break;
+ }
+ if (i == n)
+ return 0; /* No match */
+ }
+
+ /* Match! */
+ *elementp = i+1; /* Zero is the "unknown" choice, so add 1 */
+
+ /*
+ * We want the A1_OP_OPENTYPE template entry. Its `offset' is the sizeof
+ * the object we'll be decoding into, and its `ptr' is the pointer to the
+ * template for decoding that type.
+ */
+ tactual_type = &tos[i*3 + 4];
+
+ /* Decode the encoded open type value(s) */
+ if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
+ /*
+ * Not a SET OF/SEQUENCE OF open type, just singular.
+ *
+ * We need the address of the octet string / ANY field containing the
+ * encoded open type value:
+ *
+ * typedef struct SingleAttribute {
+ * heim_oid type;
+ * -------->HEIM_ANY value; // HERE
+ * struct {
+ * ...
+ * } ...
+ * }
+ */
+ const struct heim_base_data *d = DPOC(data, topentype->offset);
+ void *o;
+
+ if (d->data && d->length) {
+ if ((o = calloc(1, tactual_type->offset)) == NULL)
+ return ENOMEM;
+
+ /* Re-enter to decode the encoded open type value */
+ ret = _asn1_decode(tactual_type->ptr, flags, d->data, d->length, o, &sz);
+ /*
+ * Store the decoded object in the union:
+ *
+ * typedef struct SingleAttribute {
+ * heim_oid type;
+ * HEIM_ANY value;
+ * struct {
+ * enum { ... } element;
+ * ------------>union { SomeType *some_choice; ... } u; // HERE
+ * } _ioschoice_value;
+ * } SingleAttribute;
+ *
+ * All the union arms are pointers.
+ */
+ if (ret) {
+ _asn1_free(tactual_type->ptr, o);
+ free(o);
+ /*
+ * So we failed to decode the open type -- that should not be fatal
+ * to decoding the rest of the input. Only ENOMEM should be fatal.
+ */
+ ret = 0;
+ } else {
+ *dp = o;
+ }
+ }
+ return ret;
+ } else {
+ const struct heim_base_data * const *d;
+ void **val; /* Array of pointers */
+
+ /*
+ * A SET OF/SEQUENCE OF open type, plural.
+ *
+ * We need the address of the octet string / ANY array pointer field
+ * containing the encoded open type values:
+ *
+ * typedef struct AttributeSet {
+ * heim_oid type;
+ * struct AttributeSet_values {
+ * unsigned int len;
+ * ------------>HEIM_ANY *val; // HERE
+ * } values;
+ * ...
+ * }
+ *
+ * We already know the value of the `len' field.
+ */
+ d = DPOC(data, topentype->offset + sizeof(unsigned int));
+ while (sizeof(void *) != sizeof(len) &&
+ ((uintptr_t)d) % sizeof(void *) != 0)
+ d = (const void *)(((const char *)d) + sizeof(len));
+
+ if ((val = calloc(len, sizeof(*val))) == NULL)
+ ret = ENOMEM;
+
+ /* Increment the count of decoded values as we decode */
+ *lenp = len;
+ for (i = 0; ret != ENOMEM && i < len; i++) {
+ if ((val[i] = calloc(1, tactual_type->offset)) == NULL)
+ ret = ENOMEM;
+ if (ret == 0)
+ /* Re-enter to decode the encoded open type value */
+ ret = _asn1_decode(tactual_type->ptr, flags, d[0][i].data,
+ d[0][i].length, val[i], &sz);
+ if (ret) {
+ _asn1_free(tactual_type->ptr, val[i]);
+ free(val[i]);
+ val[i] = NULL;
+ }
+ }
+ if (ret != ENOMEM)
+ ret = 0; /* See above */
+ *dp = val;
+ return ret;
+ }
+}
+
+int
+_asn1_decode(const struct asn1_template *t, unsigned flags,
+ const unsigned char *p, size_t len, void *data, size_t *size)
+{
+ const struct asn1_template *tbase = t;
+ const struct asn1_template *tdefval = NULL;
+ size_t elements = A1_HEADER_LEN(t);
+ size_t oldlen = len;
+ int ret = 0;
+ const unsigned char *startp = NULL;
+ unsigned int template_flags = t->tt;
+
+ /*
+ * Important notes:
+ *
+ * - by and large we don't call _asn1_free() on error, except when we're
+ * decoding optional things or choices, then we do call _asn1_free()
+ * here
+ *
+ * instead we leave it to _asn1_decode_top() to call _asn1_free() on
+ * error
+ *
+ * - on error all fields of whatever we didn't _asn1_free() must have been
+ * initialized to sane values because _asn1_decode_top() will call
+ * _asn1_free() on error, so we must have left everything initialized
+ * that _asn1_free() could possibly look at
+ *
+ * - so we must initialize everything
+ *
+ * FIXME? but we mostly rely on calloc() to do this...
+ *
+ * - we don't use malloc() unless we're going to write over the whole
+ * thing with memcpy() or whatever
+ */
+
+ /* skip over header */
+ t++;
+
+ if (template_flags & A1_HF_PRESERVE)
+ startp = p;
+
+ while (elements) {
+ switch (t->tt & A1_OP_MASK) {
+ case A1_OP_OPENTYPE_OBJSET: {
+ size_t opentypeid = t->tt & ((1<<10)-1);
+ size_t opentype = (t->tt >> 10) & ((1<<10)-1);
+
+ /* Note that the only error returned here would be ENOMEM */
+ ret = _asn1_decode_open_type(t, flags, data,
+ template4member(tbase, opentypeid),
+ template4member(tbase, opentype));
+ if (ret)
+ return ret;
+ break;
+ }
+ case A1_OP_TYPE_DECORATE_EXTERN: break;
+ case A1_OP_TYPE_DECORATE: break;
+ case A1_OP_NAME: break;
+ case A1_OP_DEFVAL:
+ tdefval = t;
+ break;
+ case A1_OP_TYPE:
+ case A1_OP_TYPE_EXTERN: {
+ size_t newsize, elsize;
+ void *el = DPO(data, t->offset);
+ void **pel = (void **)el;
+
+ if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
+ elsize = _asn1_sizeofType(t->ptr);
+ } else {
+ const struct asn1_type_func *f = t->ptr;
+ elsize = f->size;
+ }
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ *pel = calloc(1, elsize);
+ if (*pel == NULL)
+ return ENOMEM;
+ el = *pel;
+ if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
+ ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize);
+ } else {
+ const struct asn1_type_func *f = t->ptr;
+ ret = (f->decode)(p, len, el, &newsize);
+ }
+ if (ret) {
+ /*
+ * Optional field not present in encoding, presumably,
+ * though we should really look more carefully at `ret'.
+ */
+ if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
+ _asn1_free(t->ptr, el);
+ } else {
+ const struct asn1_type_func *f = t->ptr;
+ f->release(el);
+ }
+ free(*pel);
+ *pel = NULL;
+ break;
+ }
+ } else {
+ if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
+ ret = _asn1_decode(t->ptr, flags, p, len, el, &newsize);
+ } else {
+ const struct asn1_type_func *f = t->ptr;
+ ret = (f->decode)(p, len, el, &newsize);
+ }
+ }
+ if (ret) {
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ } else if (t->tt & A1_FLAG_DEFAULT) {
+ if (!tdefval)
+ return ASN1_PARSE_ERROR; /* Can't happen */
+ /*
+ * Defaulted field not present in encoding, presumably,
+ * though we should really look more carefully at `ret'.
+ */
+ if (tdefval->tt & A1_DV_BOOLEAN) {
+ int *i = (void *)(char *)el;
+
+ *i = tdefval->ptr ? 1 : 0;
+ } else if (tdefval->tt & A1_DV_INTEGER64) {
+ int64_t *i = (void *)(char *)el;
+
+ *i = (int64_t)(intptr_t)tdefval->ptr;
+ } else if (tdefval->tt & A1_DV_INTEGER32) {
+ int32_t *i = (void *)(char *)el;
+
+ *i = (int32_t)(intptr_t)tdefval->ptr;
+ } else if (tdefval->tt & A1_DV_INTEGER) {
+ struct heim_integer *i = (void *)(char *)el;
+
+ if ((ret = der_copy_heim_integer(tdefval->ptr, i)))
+ return ret;
+ } else if (tdefval->tt & A1_DV_UTF8STRING) {
+ char **s = el;
+
+ if ((*s = strdup(tdefval->ptr)) == NULL)
+ return ENOMEM;
+ } else {
+ abort();
+ }
+ break;
+ }
+ return ret; /* Error decoding required field */
+ }
+ p += newsize; len -= newsize;
+
+ break;
+ }
+ case A1_OP_TAG: {
+ Der_type dertype;
+ size_t newsize = 0;
+ size_t datalen, l = 0;
+ void *olddata = data;
+ int is_indefinite = 0;
+ int subflags = flags;
+ int replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
+ void *el = data = DPO(data, t->offset);
+ void **pel = (void **)el;
+
+ /*
+ * XXX If this type (chasing t->ptr through IMPLICIT tags, if this
+ * one is too, till we find a non-TTag) is a [UNIVERSAL SET] type,
+ * then we have to accept fields out of order. For each field tag
+ * we see we'd have to do a linear search of the SET's template
+ * because it won't be sorted (or we could sort a copy and do a
+ * binary search on that, but these SETs will always be small so it
+ * won't be worthwhile). We'll need a utility function to do all
+ * of this.
+ */
+ ret = der_match_tag_and_length(p, len, A1_TAG_CLASS(t->tt),
+ &dertype, A1_TAG_TAG(t->tt),
+ &datalen, &l);
+ if (ret) {
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ data = olddata;
+ break;
+ } else if (t->tt & A1_FLAG_DEFAULT) {
+ if (!tdefval)
+ return ASN1_PARSE_ERROR; /* Can't happen */
+ /*
+ * Defaulted field not present in encoding, presumably,
+ * though we should really look more carefully at `ret'.
+ */
+ if (tdefval->tt & A1_DV_BOOLEAN) {
+ int *i = (void *)(char *)data;
+
+ *i = tdefval->ptr ? 1 : 0;
+ } else if (tdefval->tt & A1_DV_INTEGER64) {
+ int64_t *i = (void *)(char *)data;
+
+ *i = (int64_t)(intptr_t)tdefval->ptr;
+ } else if (tdefval->tt & A1_DV_INTEGER32) {
+ int32_t *i = (void *)(char *)data;
+
+ *i = (int32_t)(intptr_t)tdefval->ptr;
+ } else if (tdefval->tt & A1_DV_INTEGER) {
+ struct heim_integer *i = (void *)(char *)data;
+
+ if ((ret = der_copy_heim_integer(tdefval->ptr, i)))
+ return ret;
+ } else if (tdefval->tt & A1_DV_UTF8STRING) {
+ char **s = data;
+
+ if ((*s = strdup(tdefval->ptr)) == NULL)
+ return ENOMEM;
+ } else {
+ abort();
+ }
+ data = olddata;
+ break;
+ }
+ return ret; /* Error decoding required field */
+ }
+
+ p += l; len -= l;
+
+ /*
+ * Only allow indefinite encoding for OCTET STRING and BER
+ * for now. Should handle BIT STRING too.
+ */
+
+ if (dertype != A1_TAG_TYPE(t->tt) && (flags & A1_PF_ALLOW_BER)) {
+ const struct asn1_template *subtype = t->ptr;
+ subtype++; /* skip header */
+
+ if (((subtype->tt & A1_OP_MASK) == A1_OP_PARSE) &&
+ A1_PARSE_TYPE(subtype->tt) == A1T_OCTET_STRING)
+ subflags |= A1_PF_INDEFINTE;
+ }
+
+ if (datalen == ASN1_INDEFINITE) {
+ if ((flags & A1_PF_ALLOW_BER) == 0)
+ return ASN1_GOT_BER;
+ is_indefinite = 1;
+ datalen = len;
+ if (datalen < 2)
+ return ASN1_OVERRUN;
+ /* hide EndOfContent for sub-decoder, catching it below */
+ datalen -= 2;
+ } else if (datalen > len)
+ return ASN1_OVERRUN;
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ size_t ellen = _asn1_sizeofType(t->ptr);
+
+ *pel = calloc(1, ellen);
+ if (*pel == NULL)
+ return ENOMEM;
+ data = *pel;
+ }
+
+ if (replace_tag) {
+ const struct asn1_template *subtype = t->ptr;
+ int have_tag = 0;
+
+ /*
+ * So, we have an IMPLICIT tag. What we want to do is find the
+ * template for the body of the type so-tagged. That's going
+ * to be a template that has a tag that isn't itself IMPLICIT.
+ *
+ * So we chase the pointer in the template until we find such a
+ * thing, then decode using that template.
+ */
+ while (!have_tag) {
+ subtype++;
+ if ((subtype->tt & A1_OP_MASK) == A1_OP_TAG)
+ replace_tag = (subtype->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
+ if (replace_tag) {
+ subtype = subtype->ptr;
+ continue;
+ }
+ if ((subtype->tt & A1_OP_MASK) == A1_OP_TAG) {
+ ret = _asn1_decode(subtype->ptr, subflags, p, datalen, data, &newsize);
+ have_tag = 1;
+ } else {
+ subtype = subtype->ptr;
+ }
+ }
+ } else {
+ ret = _asn1_decode(t->ptr, subflags, p, datalen, data, &newsize);
+ }
+ if (ret == 0 && !is_indefinite && newsize != datalen)
+ /* Hidden data */
+ ret = ASN1_EXTRA_DATA;
+
+ if (ret == 0) {
+ if (is_indefinite) {
+ /* If we use indefinite encoding, the newsize is the datasize. */
+ datalen = newsize;
+ }
+
+ len -= datalen;
+ p += datalen;
+
+ /*
+ * Indefinite encoding needs a trailing EndOfContent,
+ * check for that.
+ */
+ if (is_indefinite) {
+ ret = der_match_tag_and_length(p, len, ASN1_C_UNIV,
+ &dertype, UT_EndOfContent,
+ &datalen, &l);
+ if (ret == 0 && dertype != PRIM)
+ ret = ASN1_BAD_ID;
+ else if (ret == 0 && datalen != 0)
+ ret = ASN1_INDEF_EXTRA_DATA;
+ if (ret == 0) {
+ p += l; len -= l;
+ }
+ }
+ }
+ if (ret) {
+ if (!(t->tt & A1_FLAG_OPTIONAL))
+ return ret;
+
+ _asn1_free(t->ptr, data);
+ free(data);
+ *pel = NULL;
+ return ret;
+ }
+ data = olddata;
+
+ break;
+ }
+ case A1_OP_PARSE: {
+ unsigned int type = A1_PARSE_TYPE(t->tt);
+ size_t newsize;
+ void *el = DPO(data, t->offset);
+
+ /*
+ * INDEFINITE primitive types are one element after the
+ * same type but non-INDEFINITE version.
+ */
+ if (flags & A1_PF_INDEFINTE)
+ type++;
+
+ if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
+ ABORT_ON_ERROR();
+ return ASN1_PARSE_ERROR;
+ }
+
+ ret = (asn1_template_prim[type].decode)(p, len, el, &newsize);
+ if (ret)
+ return ret;
+ p += newsize; len -= newsize;
+
+ break;
+ }
+ case A1_OP_SETOF:
+ case A1_OP_SEQOF: {
+ struct template_of *el = DPO(data, t->offset);
+ size_t newsize;
+ size_t ellen = _asn1_sizeofType(t->ptr);
+ size_t vallength = 0;
+
+ while (len > 0) {
+ void *tmp;
+ size_t newlen = vallength + ellen;
+ if (vallength > newlen)
+ return ASN1_OVERFLOW;
+
+ /* XXX Slow */
+ tmp = realloc(el->val, newlen);
+ if (tmp == NULL)
+ return ENOMEM;
+
+ memset(DPO(tmp, vallength), 0, ellen);
+ el->val = tmp;
+
+ el->len++;
+ ret = _asn1_decode(t->ptr, flags & (~A1_PF_INDEFINTE), p, len,
+ DPO(el->val, vallength), &newsize);
+ if (ret)
+ return ret;
+ vallength = newlen;
+ p += newsize; len -= newsize;
+ }
+
+ break;
+ }
+ case A1_OP_BMEMBER: {
+ const struct asn1_template *bmember = t->ptr;
+ size_t bsize = bmember->offset;
+ size_t belements = A1_HEADER_LEN(bmember);
+ size_t pos = 0;
+
+ bmember++;
+
+ memset(data, 0, bsize);
+
+ if (len < 1)
+ return ASN1_OVERRUN;
+ p++; len--;
+
+ while (belements && len) {
+ while (bmember->offset / 8 > pos / 8) {
+ if (len < 1)
+ break;
+ p++; len--;
+ pos += 8;
+ }
+ if (len) {
+ _asn1_bmember_get_bit(p, data, bmember->offset, bsize);
+ belements--; bmember++;
+ }
+ }
+ len = 0;
+ break;
+ }
+ case A1_OP_CHOICE: {
+ const struct asn1_template *choice = t->ptr;
+ unsigned int *element = DPO(data, choice->offset);
+ size_t datalen;
+ unsigned int i;
+
+ /*
+ * CHOICE element IDs are assigned in monotonically increasing
+ * fashion. Therefore any unrealistic value is a suitable invalid
+ * CHOICE value. The largest binary value (or -1 if treating the
+ * enum as signed on a twos-complement system, or...) will do.
+ */
+ *element = ~0;
+
+ for (i = 1; i < A1_HEADER_LEN(choice) + 1 && choice[i].tt; i++) {
+ /*
+ * This is more permissive than is required. CHOICE
+ * alternatives must have different outer tags, so in principle
+ * we should just match the tag at `p' and `len' in sequence to
+ * the choice alternatives.
+ *
+ * Trying every alternative instead happens to do this anyways
+ * because each one will first match the tag at `p' and `len',
+ * but if there are CHOICE altnernatives with the same outer
+ * tag, then we'll allow it, and they had better be unambiguous
+ * in their internal details, otherwise there would be some
+ * aliasing.
+ *
+ * Arguably the *compiler* should detect ambiguous CHOICE types
+ * and raise an error, then we don't have to be concerned here
+ * at all.
+ */
+ ret = _asn1_decode(choice[i].ptr, 0, p, len,
+ DPO(data, choice[i].offset), &datalen);
+ if (ret == 0) {
+ *element = i;
+ p += datalen; len -= datalen;
+ break;
+ }
+ _asn1_free(choice[i].ptr, DPO(data, choice[i].offset));
+ if (ret != ASN1_BAD_ID && ret != ASN1_MISPLACED_FIELD &&
+ ret != ASN1_MISSING_FIELD)
+ return ret;
+ }
+ if (i >= A1_HEADER_LEN(choice) + 1 || !choice[i].tt) {
+ /*
+ * If this is an extensible CHOICE, then choice->tt will be the
+ * offset to u.ellipsis. If it's not, then this "extension" is
+ * an error and must stop parsing it. (We could be permissive
+ * and throw away the extension, though one might as well just
+ * mark such a CHOICE as extensible.)
+ */
+ if (choice->tt == 0)
+ return ASN1_BAD_ID;
+
+ /* This is the ellipsis case */
+ *element = 0;
+ ret = der_get_octet_string(p, len,
+ DPO(data, choice->tt), &datalen);
+ if (ret)
+ return ret;
+ p += datalen; len -= datalen;
+ }
+
+ break;
+ }
+ default:
+ ABORT_ON_ERROR();
+ return ASN1_PARSE_ERROR;
+ }
+ t++;
+ elements--;
+ }
+ /* if we are using padding, eat up read of context */
+ if (template_flags & A1_HF_ELLIPSIS)
+ len = 0;
+
+ oldlen -= len;
+
+ if (size)
+ *size = oldlen;
+
+ /*
+ * saved the raw bits if asked for it, useful for signature
+ * verification.
+ */
+ if (startp) {
+ heim_octet_string *save = data;
+
+ save->data = malloc(oldlen);
+ if (save->data == NULL)
+ return ENOMEM;
+ else {
+ save->length = oldlen;
+ memcpy(save->data, startp, oldlen);
+ }
+ }
+ return 0;
+}
+
+/*
+ * This should be called with a `A1_TAG_T(ASN1_C_UNIV, PRIM, UT_Integer)'
+ * template as the `ttypeid'.
+ */
+static int
+typeid_int_copy(void *intp,
+ int64_t i,
+ const struct asn1_template *ttypeid)
+{
+ const struct asn1_template *tint = ttypeid->ptr;
+
+ if ((tint[1].tt & A1_OP_MASK) != A1_OP_PARSE)
+ return -1;
+ if (A1_PARSE_TYPE(tint[1].tt) != A1T_INTEGER)
+ return -1;
+ switch (tint[0].offset) {
+ case 8: *((int64_t *)intp) = i; return 0;
+ case 4: *((int32_t *)intp) = i; return 0;
+ default: memset(intp, 0, tint[0].offset); return 0;
+ }
+}
+
+/* See commentary in _asn1_decode_open_type() */
+static int
+_asn1_encode_open_type(const struct asn1_template *t,
+ const void *data, /* NOTE: Not really const */
+ const struct asn1_template *ttypeid,
+ const struct asn1_template *topentype)
+{
+ const struct asn1_template *ttypeid_univ = ttypeid;
+ const struct asn1_template *tactual_type;
+ const struct asn1_template *tos = t->ptr;
+ size_t sz, i;
+ unsigned int *lenp = NULL;
+ unsigned int len = 1;
+ int element = *(const int *)DPOC(data, t->offset);
+ int typeid_is_oid = 0;
+ int typeid_is_int = 0;
+ int enotsup = 0;
+ int ret = 0;
+
+ if (element == 0 || element >= A1_HEADER_LEN(tos) + 1)
+ return 0;
+
+ if (t->tt & A1_OS_OT_IS_ARRAY) {
+ /* The actual `len' is from the decoded open type field */
+ len = *(const unsigned int *)DPOC(data, t->offset + sizeof(element));
+
+ if (!len)
+ return 0; /* The app may be encoding the open type by itself */
+ }
+
+ /* Work out the type ID field's type */
+ while (((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TAG &&
+ A1_TAG_CLASS(ttypeid_univ->tt) == ASN1_C_CONTEXT) ||
+ ((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TYPE)) {
+ ttypeid_univ = ttypeid_univ->ptr;
+ ttypeid_univ++;
+ }
+ switch (ttypeid_univ->tt & A1_OP_MASK) {
+ case A1_OP_TAG:
+ if (A1_TAG_CLASS(ttypeid_univ->tt) != ASN1_C_UNIV) {
+ enotsup = 1;
+ break;
+ }
+ switch (A1_TAG_TAG(ttypeid_univ->tt)) {
+ case UT_OID:
+ typeid_is_oid = 1;
+ break;
+ case UT_Integer: {
+ const struct asn1_template *tint = ttypeid_univ->ptr;
+
+ tint++;
+ if ((tint->tt & A1_OP_MASK) != A1_OP_PARSE ||
+ A1_PARSE_TYPE(tint->tt) != A1T_INTEGER) {
+ enotsup = 1;
+ break;
+ }
+ typeid_is_int = 1;
+ break;
+ }
+ default: enotsup = 1; break;
+ }
+ break;
+ default: enotsup = 1; break;
+ }
+
+ /*
+ * The app may not be aware of our automatic open type handling, so if the
+ * open type already appears to have been encoded, then ignore the decoded
+ * values.
+ */
+ if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
+ struct heim_base_data *os = DPO(data, topentype->offset);
+
+ if (os->length && os->data)
+ return 0;
+ } else {
+ struct heim_base_data **os = DPO(data, topentype->offset + sizeof(len));
+
+ while (sizeof(void *) != sizeof(unsigned int) &&
+ ((uintptr_t)os) % sizeof(void *) != 0)
+ os = (void *)(((char *)os) + sizeof(unsigned int));
+
+ lenp = DPO(data, topentype->offset);
+ if (*lenp == len && os[0]->length && os[0]->data)
+ return 0;
+ }
+
+ if (typeid_is_int) {
+ /*
+ * Copy the int from the type ID object field to the type ID struct
+ * field.
+ */
+ ret = typeid_int_copy(DPO(data, ttypeid->offset),
+ (intptr_t)tos[3 + (element-1)*3].ptr, ttypeid_univ);
+ } else if (typeid_is_oid) {
+ /*
+ * Copy the OID from the type ID object field to the type ID struct
+ * field.
+ */
+ ret = der_copy_oid(tos[3 + (element-1)*3].ptr, DPO(data, ttypeid->offset));
+ } else
+ enotsup = 1;
+
+ /*
+ * If the app did not already encode the open type, we can't help it if we
+ * don't know what it is.
+ */
+ if (enotsup)
+ return ENOTSUP;
+
+ tactual_type = &tos[(element-1)*3 + 4];
+
+ if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
+ struct heim_base_data *os = DPO(data, topentype->offset);
+ const void * const *d = DPOC(data, t->offset + sizeof(element));
+
+ while (sizeof(void *) != sizeof(element) &&
+ ((uintptr_t)d) % sizeof(void *) != 0) {
+ d = (void *)(((char *)d) + sizeof(element));
+ }
+
+ os->length = _asn1_length(tactual_type->ptr, *d);
+ if ((os->data = malloc(os->length)) == NULL)
+ return ENOMEM;
+ ret = _asn1_encode(tactual_type->ptr, (os->length - 1) + (unsigned char *)os->data, os->length, *d, &sz);
+ } else {
+ struct heim_base_data *os;
+ const void * const *val =
+ DPOC(data, t->offset + sizeof(element) + sizeof(*lenp));
+
+ if ((os = calloc(len, sizeof(*os))) == NULL)
+ return ENOMEM;
+
+ *lenp = len;
+ for (i = 0; ret == 0 && i < len; i++) {
+ os[i].length = _asn1_length(tactual_type->ptr, val[i]);
+ if ((os[i].data = malloc(os[i].length)) == NULL)
+ ret = ENOMEM;
+ if (ret == 0)
+ ret = _asn1_encode(tactual_type->ptr, (os[i].length - 1) + (unsigned char *)os[i].data, os[i].length,
+ val[i], &sz);
+ }
+ if (ret) {
+ for (i = 0; i < (*lenp); i++)
+ free(os[i].data);
+ free(os);
+ *lenp = 0;
+ return ret;
+ }
+ *(struct heim_base_data **)DPO(data, topentype->offset + sizeof(len)) = os;
+ }
+ return ret;
+}
+
+int
+_asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const void *data, size_t *size)
+{
+ const struct asn1_template *tbase = t;
+ size_t elements = A1_HEADER_LEN(t);
+ int ret = 0;
+ size_t oldlen = len;
+
+ t += A1_HEADER_LEN(t);
+
+ while (elements) {
+ switch (t->tt & A1_OP_MASK) {
+ case A1_OP_OPENTYPE_OBJSET: {
+ size_t opentypeid = t->tt & ((1<<10)-1);
+ size_t opentype = (t->tt >> 10) & ((1<<10)-1);
+ ret = _asn1_encode_open_type(t, data,
+ template4member(tbase, opentypeid),
+ template4member(tbase, opentype));
+ if (ret)
+ return ret;
+ break;
+ }
+ case A1_OP_NAME: break;
+ case A1_OP_DEFVAL: break;
+ case A1_OP_TYPE_DECORATE_EXTERN: break;
+ case A1_OP_TYPE_DECORATE: break;
+ case A1_OP_TYPE:
+ case A1_OP_TYPE_EXTERN: {
+ size_t newsize;
+ const void *el = DPOC(data, t->offset);
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ void **pel = (void **)el;
+ if (*pel == NULL)
+ break;
+ el = *pel;
+ } else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
+ const struct asn1_template *tdefval = t - 1;
+ /* Compare tdefval to whatever's at `el' */
+ if (tdefval->tt & A1_DV_BOOLEAN) {
+ const int *i = (void *)(char *)el;
+
+ if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
+ break;
+ } else if (tdefval->tt & A1_DV_INTEGER64) {
+ const int64_t *i = (void *)(char *)el;
+
+ if (*i == (int64_t)(intptr_t)tdefval->ptr)
+ break;
+ } else if (tdefval->tt & A1_DV_INTEGER32) {
+ const int32_t *i = (void *)(char *)el;
+
+ if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
+ (int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
+ *i == (int32_t)(intptr_t)tdefval->ptr)
+ break;
+ } else if (tdefval->tt & A1_DV_INTEGER) {
+ const struct heim_integer *i = (void *)(char *)el;
+
+ if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
+ break;
+ } else if (tdefval->tt & A1_DV_UTF8STRING) {
+ const char * const *s = el;
+
+ if (*s && strcmp(*s, tdefval->ptr) == 0)
+ break;
+ } else {
+ abort();
+ }
+ }
+
+ if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
+ ret = _asn1_encode(t->ptr, p, len, el, &newsize);
+ } else {
+ const struct asn1_type_func *f = t->ptr;
+ ret = (f->encode)(p, len, el, &newsize);
+ }
+
+ if (ret)
+ return ret;
+ p -= newsize; len -= newsize;
+
+ break;
+ }
+ case A1_OP_TAG: {
+ const void *olddata = data;
+ size_t l, datalen = 0;
+ int replace_tag = 0;
+
+ /*
+ * XXX If this type (chasing t->ptr through IMPLICIT tags, if this
+ * one is too) till we find a non-TTag) is a [UNIVERSAL SET] type,
+ * then we have to sort [a copy of] its template by tag, then
+ * encode the SET using that sorted template. These SETs will
+ * generally be small, so when they are we might want to allocate
+ * the copy on the stack and insertion sort it. We'll need a
+ * utility function to do all of this.
+ */
+
+ data = DPOC(data, t->offset);
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ void **el = (void **)data;
+ if (*el == NULL) {
+ data = olddata;
+ break;
+ }
+ data = *el;
+ } else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
+ const struct asn1_template *tdefval = t - 1;
+ int exclude = 0;
+
+ /* Compare tdefval to whatever's at `data' */
+ if (tdefval->tt & A1_DV_BOOLEAN) {
+ const int *i = (void *)(char *)data;
+
+ if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
+ exclude = 1;
+ } else if (tdefval->tt & A1_DV_INTEGER64) {
+ const int64_t *i = (void *)(char *)data;
+
+ if (*i == (int64_t)(intptr_t)tdefval->ptr)
+ exclude = 1;
+ } else if (tdefval->tt & A1_DV_INTEGER32) {
+ const int32_t *i = (void *)(char *)data;
+
+ if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
+ (int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
+ *i == (int32_t)(intptr_t)tdefval->ptr)
+ exclude = 1;
+ } else if (tdefval->tt & A1_DV_INTEGER) {
+ const struct heim_integer *i = (void *)(char *)data;
+
+ if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
+ break;
+ } else if (tdefval->tt & A1_DV_UTF8STRING) {
+ const char * const *s = data;
+
+ if (*s && strcmp(*s, tdefval->ptr) == 0)
+ exclude = 1;
+ } else {
+ abort();
+ }
+ if (exclude) {
+ data = olddata;
+ break;
+ }
+ }
+
+ replace_tag = (t->tt & A1_FLAG_IMPLICIT) && is_tagged(t->ptr);
+
+ /* IMPLICIT tags need special handling (see gen_encode.c) */
+ if (replace_tag) {
+ unsigned char *pfree, *psave = p;
+ Der_class found_class;
+ Der_type found_type = 0;
+ unsigned int found_tag;
+ size_t lensave = len;
+ size_t oldtaglen = 0;
+ size_t taglen = der_length_tag(A1_TAG_TAG(t->tt));;
+
+ /* Allocate a buffer at least as big as we need */
+ len = _asn1_length(t->ptr, data) + taglen;
+ if ((p = pfree = malloc(len)) == NULL) {
+ ret = ENOMEM;
+ } else {
+ /*
+ * Encode into it (with the wrong tag, which we'll replace
+ * below).
+ */
+ p += len - 1;
+ ret = _asn1_encode(t->ptr, p, len, data, &datalen);
+ }
+ if (ret == 0) {
+ /* Get the old tag and, critically, its length */
+ len -= datalen; p -= datalen;
+ ret = der_get_tag(p + 1, datalen, &found_class, &found_type,
+ &found_tag, &oldtaglen);
+ }
+ if (ret == 0) {
+ /* Drop the old tag */
+ len += oldtaglen; p += oldtaglen;
+ /* Put the new tag */
+ ret = der_put_tag(p, len,
+ A1_TAG_CLASS(t->tt),
+ found_type,
+ A1_TAG_TAG(t->tt), &l);
+ }
+ if (ret == 0) {
+ /* Copy the encoding where it belongs */
+ psave -= (datalen + l - oldtaglen);
+ lensave -= (datalen + l - oldtaglen);
+ memcpy(psave + 1, p + 1 - l, datalen + l - oldtaglen);
+ p = psave;
+ len = lensave;
+ }
+ free(pfree);
+ } else {
+ /* Easy case */
+ ret = _asn1_encode(t->ptr, p, len, data, &datalen);
+ if (ret)
+ return ret;
+
+ len -= datalen; p -= datalen;
+
+ ret = der_put_length_and_tag(p, len, datalen,
+ A1_TAG_CLASS(t->tt),
+ A1_TAG_TYPE(t->tt),
+ A1_TAG_TAG(t->tt), &l);
+ if (ret == 0) {
+ p -= l; len -= l;
+ }
+ }
+ if (ret)
+ return ret;
+
+ data = olddata;
+
+ break;
+ }
+ case A1_OP_PARSE: {
+ unsigned int type = A1_PARSE_TYPE(t->tt);
+ size_t newsize;
+ const void *el = DPOC(data, t->offset);
+
+ if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
+ ABORT_ON_ERROR();
+ return ASN1_PARSE_ERROR;
+ }
+
+ ret = (asn1_template_prim[type].encode)(p, len, el, &newsize);
+ if (ret)
+ return ret;
+ p -= newsize; len -= newsize;
+
+ break;
+ }
+ case A1_OP_SETOF: {
+ const struct template_of *el = DPOC(data, t->offset);
+ size_t ellen = _asn1_sizeofType(t->ptr);
+ heim_octet_string *val;
+ unsigned char *elptr = el->val;
+ size_t i, totallen;
+
+ if (el->len == 0)
+ break;
+
+ if (el->len > UINT_MAX/sizeof(val[0]))
+ return ERANGE;
+
+ val = calloc(el->len, sizeof(val[0]));
+ if (val == NULL)
+ return ENOMEM;
+
+ for(totallen = 0, i = 0; i < el->len; i++) {
+ unsigned char *next;
+ size_t l;
+
+ val[i].length = _asn1_length(t->ptr, elptr);
+ if (val[i].length) {
+ val[i].data = malloc(val[i].length);
+ if (val[i].data == NULL) {
+ ret = ENOMEM;
+ break;
+ }
+ }
+
+ ret = _asn1_encode(t->ptr, DPO(val[i].data, val[i].length - 1),
+ val[i].length, elptr, &l);
+ if (ret)
+ break;
+
+ next = elptr + ellen;
+ if (next < elptr) {
+ ret = ASN1_OVERFLOW;
+ break;
+ }
+ elptr = next;
+ totallen += val[i].length;
+ }
+ if (ret == 0 && totallen > len)
+ ret = ASN1_OVERFLOW;
+ if (ret) {
+ for (i = 0; i < el->len; i++)
+ free(val[i].data);
+ free(val);
+ return ret;
+ }
+
+ len -= totallen;
+
+ qsort(val, el->len, sizeof(val[0]), _heim_der_set_sort);
+
+ i = el->len - 1;
+ do {
+ p -= val[i].length;
+ memcpy(p + 1, val[i].data, val[i].length);
+ free(val[i].data);
+ } while(i-- > 0);
+ free(val);
+
+ break;
+
+ }
+ case A1_OP_SEQOF: {
+ struct template_of *el = DPO(data, t->offset);
+ size_t ellen = _asn1_sizeofType(t->ptr);
+ size_t newsize;
+ unsigned int i;
+ unsigned char *elptr = el->val;
+
+ if (el->len == 0)
+ break;
+
+ elptr += ellen * (el->len - 1);
+
+ for (i = 0; i < el->len; i++) {
+ ret = _asn1_encode(t->ptr, p, len,
+ elptr,
+ &newsize);
+ if (ret)
+ return ret;
+ p -= newsize; len -= newsize;
+ elptr -= ellen;
+ }
+
+ break;
+ }
+ case A1_OP_BMEMBER: {
+ const struct asn1_template *bmember = t->ptr;
+ size_t bsize = bmember->offset;
+ size_t belements = A1_HEADER_LEN(bmember);
+ size_t pos;
+ unsigned char c = 0;
+ unsigned int bitset = 0;
+ int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
+
+ bmember += belements;
+
+ if (rfc1510)
+ pos = 31;
+ else
+ pos = bmember->offset;
+
+ while (belements && len) {
+ while (bmember->offset / 8 < pos / 8) {
+ if (rfc1510 || bitset || c) {
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = c; len--;
+ }
+ c = 0;
+ pos -= 8;
+ }
+ _asn1_bmember_put_bit(&c, data, bmember->offset, bsize, &bitset);
+ belements--; bmember--;
+ }
+ if (rfc1510 || bitset) {
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = c; len--;
+ }
+
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ if (rfc1510 || bitset == 0)
+ *p-- = 0;
+ else
+ *p-- = bitset - 1;
+
+ len--;
+
+ break;
+ }
+ case A1_OP_CHOICE: {
+ const struct asn1_template *choice = t->ptr;
+ const unsigned int *element = DPOC(data, choice->offset);
+ size_t datalen;
+ const void *el;
+
+ if (*element > A1_HEADER_LEN(choice)) {
+ printf("element: %d\n", *element);
+ return ASN1_PARSE_ERROR;
+ }
+
+ if (*element == 0) {
+ if (choice->tt) {
+ /* This is an extensible CHOICE */
+ ret += der_put_octet_string(p, len,
+ DPOC(data, choice->tt), &datalen);
+ len -= datalen; p -= datalen;
+ } /* else this is really an error -- XXX what to do? */
+ } else {
+ choice += *element;
+ el = DPOC(data, choice->offset);
+ ret = _asn1_encode(choice->ptr, p, len, el, &datalen);
+ if (ret)
+ return ret;
+ len -= datalen; p -= datalen;
+ }
+
+ break;
+ }
+ default:
+ ABORT_ON_ERROR();
+ }
+ t--;
+ elements--;
+ }
+ if (size)
+ *size = oldlen - len;
+
+ return 0;
+}
+
+static size_t
+_asn1_length_open_type_helper(const struct asn1_template *t,
+ size_t sz)
+{
+ const struct asn1_template *tinner = t->ptr;
+
+ switch (t->tt & A1_OP_MASK) {
+ case A1_OP_TAG:
+ /* XXX Not tail-recursive :( */
+ sz = _asn1_length_open_type_helper(tinner, sz);
+ sz += der_length_len(sz);
+ sz += der_length_tag(A1_TAG_TAG(t->tt));
+ return sz;
+ default:
+ return sz;
+ }
+}
+
+static size_t
+_asn1_length_open_type_id(const struct asn1_template *t,
+ const void *data)
+{
+ struct asn1_template pretend[2] = {
+ { 0, 0, ((void*)(uintptr_t)1) },
+ };
+ pretend[1] = *t;
+ while ((t->tt & A1_OP_MASK) == A1_OP_TAG)
+ t = t->ptr;
+ pretend[0].offset = t->offset;
+ return _asn1_length(pretend, data);
+}
+
+/* See commentary in _asn1_encode_open_type() */
+static size_t
+_asn1_length_open_type(const struct asn1_template *tbase,
+ const struct asn1_template *t,
+ const void *data,
+ const struct asn1_template *ttypeid,
+ const struct asn1_template *topentype)
+{
+ const struct asn1_template *ttypeid_univ = ttypeid;
+ const struct asn1_template *tactual_type;
+ const struct asn1_template *tos = t->ptr;
+ const unsigned int *lenp = NULL;
+ unsigned int len = 1;
+ size_t sz = 0;
+ size_t i;
+ int element = *(const int *)DPOC(data, t->offset);
+ int typeid_is_oid = 0;
+ int typeid_is_int = 0;
+
+ /* If nothing to encode, we add nothing to the length */
+ if (element == 0 || element >= A1_HEADER_LEN(tos) + 1)
+ return 0;
+ if (t->tt & A1_OS_OT_IS_ARRAY) {
+ len = *(const unsigned int *)DPOC(data, t->offset + sizeof(element));
+ if (!len)
+ return 0;
+ }
+
+ /* Work out the type ID field's type */
+ while (((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TAG &&
+ A1_TAG_CLASS(ttypeid_univ->tt) == ASN1_C_CONTEXT) ||
+ ((ttypeid_univ->tt & A1_OP_MASK) == A1_OP_TYPE)) {
+ ttypeid_univ = ttypeid_univ->ptr;
+ ttypeid_univ++;
+ }
+ switch (ttypeid_univ->tt & A1_OP_MASK) {
+ case A1_OP_TAG:
+ if (A1_TAG_CLASS(ttypeid_univ->tt) != ASN1_C_UNIV)
+ return 0;
+ switch (A1_TAG_TAG(ttypeid_univ->tt)) {
+ case UT_OID:
+ typeid_is_oid = 1;
+ break;
+ case UT_Integer: {
+ const struct asn1_template *tint = ttypeid_univ->ptr;
+
+ tint++;
+ if ((tint->tt & A1_OP_MASK) != A1_OP_PARSE ||
+ A1_PARSE_TYPE(tint->tt) != A1T_INTEGER)
+ return 0;
+ typeid_is_int = 1;
+ break;
+ }
+ default: return 0;
+ }
+ break;
+ default: return 0;
+ }
+ if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
+ struct heim_base_data *os = DPO(data, topentype->offset);
+
+ if (os->length && os->data)
+ return 0;
+ } else {
+ struct heim_base_data **os = DPO(data, topentype->offset + sizeof(len));
+
+ while (sizeof(void *) != sizeof(unsigned int) &&
+ ((uintptr_t)os) % sizeof(void *) != 0)
+ os = (void *)(((char *)os) + sizeof(unsigned int));
+
+ lenp = DPOC(data, topentype->offset);
+ if (*lenp == len && os[0]->length && os[0]->data)
+ return 0;
+ }
+
+ /* Compute the size of the type ID field */
+ if (typeid_is_int) {
+ int64_t i8;
+ int32_t i4;
+
+ switch (ttypeid_univ->offset) {
+ case 8:
+ i8 = (intptr_t)t->ptr;
+ sz = _asn1_length_open_type_id(ttypeid, &i8);
+ i8 = 0;
+ sz -= _asn1_length_open_type_id(ttypeid, &i8);
+ break;
+ case 4:
+ i4 = (intptr_t)t->ptr;
+ sz = _asn1_length_open_type_id(ttypeid, &i4);
+ i4 = 0;
+ sz -= _asn1_length_open_type_id(ttypeid, &i8);
+ break;
+ default:
+ return 0;
+ }
+ } else if (typeid_is_oid) {
+ heim_oid no_oid = { 0, 0 };
+
+ sz = _asn1_length_open_type_id(ttypeid, tos[3 + (element - 1)*3].ptr);
+ sz -= _asn1_length_open_type_id(ttypeid, &no_oid);
+ }
+
+ tactual_type = &tos[(element-1)*3 + 4];
+
+ /* Compute the size of the encoded value(s) */
+ if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
+ const void * const *d = DPOC(data, t->offset + sizeof(element));
+
+ while (sizeof(void *) != sizeof(element) &&
+ ((uintptr_t)d) % sizeof(void *) != 0)
+ d = (void *)(((char *)d) + sizeof(element));
+ if (*d)
+ sz += _asn1_length(tactual_type->ptr, *d);
+ } else {
+ size_t bodysz;
+ const void * const * val =
+ DPOC(data, t->offset + sizeof(element) + sizeof(*lenp));
+
+ /* Compute the size of the encoded SET OF / SEQUENCE OF body */
+ for (i = 0, bodysz = 0; i < len; i++) {
+ if (val[i])
+ bodysz += _asn1_length(tactual_type->ptr, val[i]);
+ }
+
+ /*
+ * We now know the size of the body of the SET OF or SEQUENCE OF. Now
+ * we just need to count the length of all the TLs on the outside.
+ */
+ sz += _asn1_length_open_type_helper(topentype, bodysz);
+ }
+ return sz;
+}
+
+size_t
+_asn1_length(const struct asn1_template *t, const void *data)
+{
+ const struct asn1_template *tbase = t;
+ size_t elements = A1_HEADER_LEN(t);
+ size_t ret = 0;
+
+ t += A1_HEADER_LEN(t);
+
+ while (elements) {
+ switch (t->tt & A1_OP_MASK) {
+ case A1_OP_OPENTYPE_OBJSET: {
+ size_t opentypeid = t->tt & ((1<<10)-1);
+ size_t opentype = (t->tt >> 10) & ((1<<10)-1);
+ ret += _asn1_length_open_type(tbase, t, data,
+ template4member(tbase, opentypeid),
+ template4member(tbase, opentype));
+ break;
+ }
+ case A1_OP_NAME: break;
+ case A1_OP_DEFVAL: break;
+ case A1_OP_TYPE_DECORATE_EXTERN: break;
+ case A1_OP_TYPE_DECORATE: break;
+ case A1_OP_TYPE:
+ case A1_OP_TYPE_EXTERN: {
+ const void *el = DPOC(data, t->offset);
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ void **pel = (void **)el;
+ if (*pel == NULL)
+ break;
+ el = *pel;
+ } else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
+ const struct asn1_template *tdefval = t - 1;
+
+ /* Compare tdefval to whatever's at `el' */
+ if (tdefval->tt & A1_DV_BOOLEAN) {
+ const int *i = (void *)(char *)el;
+
+ if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
+ break;
+ } else if (tdefval->tt & A1_DV_INTEGER64) {
+ const int64_t *i = (void *)(char *)el;
+
+ if (*i == (int64_t)(intptr_t)tdefval->ptr)
+ break;
+ } else if (tdefval->tt & A1_DV_INTEGER32) {
+ const int32_t *i = (void *)(char *)el;
+
+ if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
+ (int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
+ *i == (int32_t)(intptr_t)tdefval->ptr)
+ break;
+ } else if (tdefval->tt & A1_DV_INTEGER) {
+ const struct heim_integer *i = (void *)(char *)el;
+
+ if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
+ break;
+ } else if (tdefval->tt & A1_DV_UTF8STRING) {
+ const char * const *s = el;
+
+ if (*s && strcmp(*s, tdefval->ptr) == 0)
+ break;
+ } else {
+ abort();
+ }
+ }
+
+ if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
+ ret += _asn1_length(t->ptr, el);
+ } else {
+ const struct asn1_type_func *f = t->ptr;
+ ret += (f->length)(el);
+ }
+ break;
+ }
+ case A1_OP_TAG: {
+ size_t datalen;
+ const void *olddata = data;
+ size_t oldtaglen = 0;
+
+ data = DPO(data, t->offset);
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ void **el = (void **)data;
+ if (*el == NULL) {
+ data = olddata;
+ break;
+ }
+ data = *el;
+ } else if ((t->tt & A1_FLAG_DEFAULT) && elements > 1) {
+ const struct asn1_template *tdefval = t - 1;
+ int exclude = 0;
+
+ /* Compare tdefval to whatever's at `data' */
+ if (tdefval->tt & A1_DV_BOOLEAN) {
+ const int *i = (void *)(char *)data;
+
+ if ((*i && tdefval->ptr) || (!*i && !tdefval->ptr))
+ exclude = 1;
+ } else if (tdefval->tt & A1_DV_INTEGER64) {
+ const int64_t *i = (void *)(char *)data;
+
+ if (*i == (int64_t)(intptr_t)tdefval->ptr)
+ exclude = 1;
+ } else if (tdefval->tt & A1_DV_INTEGER32) {
+ const int32_t *i = (void *)(char *)data;
+
+ if ((int64_t)(intptr_t)tdefval->ptr <= INT_MAX &&
+ (int64_t)(intptr_t)tdefval->ptr >= INT_MIN &&
+ *i == (int32_t)(intptr_t)tdefval->ptr)
+ exclude = 1;
+ } else if (tdefval->tt & A1_DV_INTEGER) {
+ const struct heim_integer *i = (void *)(char *)data;
+
+ if (der_heim_integer_cmp(i, tdefval->ptr) == 0)
+ exclude = 1;
+ } else if (tdefval->tt & A1_DV_UTF8STRING) {
+ const char * const *s = data;
+
+ if (*s && strcmp(*s, tdefval->ptr) == 0)
+ exclude = 1;
+ } else {
+ abort();
+ }
+ if (exclude) {
+ data = olddata;
+ break;
+ }
+ }
+
+ if (t->tt & A1_FLAG_IMPLICIT)
+ oldtaglen = inner_type_taglen(t->ptr);
+
+ datalen = _asn1_length(t->ptr, data);
+ ret += datalen;
+ ret += der_length_tag(A1_TAG_TAG(t->tt));
+ ret += oldtaglen ? -oldtaglen : der_length_len(datalen);
+ data = olddata;
+ break;
+ }
+ case A1_OP_PARSE: {
+ unsigned int type = A1_PARSE_TYPE(t->tt);
+ const void *el = DPOC(data, t->offset);
+
+ if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
+ ABORT_ON_ERROR();
+ break;
+ }
+ ret += (asn1_template_prim[type].length)(el);
+ break;
+ }
+ case A1_OP_SETOF:
+ case A1_OP_SEQOF: {
+ const struct template_of *el = DPOC(data, t->offset);
+ size_t ellen = _asn1_sizeofType(t->ptr);
+ const unsigned char *element = el->val;
+ unsigned int i;
+
+ for (i = 0; i < el->len; i++) {
+ ret += _asn1_length(t->ptr, element);
+ element += ellen;
+ }
+
+ break;
+ }
+ case A1_OP_BMEMBER: {
+ const struct asn1_template *bmember = t->ptr;
+ size_t size = bmember->offset;
+ size_t belements = A1_HEADER_LEN(bmember);
+ int rfc1510 = (bmember->tt & A1_HBF_RFC1510);
+
+ if (rfc1510) {
+ ret += 5;
+ } else {
+
+ ret += 1;
+
+ bmember += belements;
+
+ while (belements) {
+ if (_asn1_bmember_isset_bit(data, bmember->offset, size)) {
+ ret += (bmember->offset / 8) + 1;
+ break;
+ }
+ belements--; bmember--;
+ }
+ }
+ break;
+ }
+ case A1_OP_CHOICE: {
+ const struct asn1_template *choice = t->ptr;
+ const unsigned int *element = DPOC(data, choice->offset);
+
+ if (*element > A1_HEADER_LEN(choice))
+ break;
+
+ if (*element == 0) {
+ if (choice->tt)
+ ret += der_length_octet_string(DPOC(data, choice->tt));
+ } else {
+ choice += *element;
+ ret += _asn1_length(choice->ptr, DPOC(data, choice->offset));
+ }
+ break;
+ }
+ default:
+ ABORT_ON_ERROR();
+ break;
+ }
+ elements--;
+ t--;
+ }
+ return ret;
+}
+
+/* See commentary in _asn1_decode_open_type() */
+static void
+_asn1_free_open_type(const struct asn1_template *t, /* object set template */
+ void *data)
+{
+ const struct asn1_template *tactual_type;
+ const struct asn1_template *tos = t->ptr;
+ unsigned int *lenp = NULL; /* Pointer to array length field */
+ unsigned int len = 1; /* Array length */
+ size_t i;
+ void **dp;
+ void **val;
+ int *elementp = DPO(data, t->offset); /* Choice enum pointer */
+
+ /* XXX We assume sizeof(enum) == sizeof(int) */
+ if (!*elementp || *elementp >= A1_HEADER_LEN(tos) + 1)
+ return; /* Unknown choice -> it's not decoded, nothing to free here */
+ tactual_type = tos[3*(*elementp - 1) + 4].ptr;
+
+ if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
+ dp = DPO(data, t->offset + sizeof(*elementp));
+ while (sizeof(void *) != sizeof(*elementp) &&
+ ((uintptr_t)dp) % sizeof(void *) != 0)
+ dp = (void *)(((char *)dp) + sizeof(*elementp));
+ if (*dp) {
+ _asn1_free(tactual_type, *dp);
+ free(*dp);
+ *dp = NULL;
+ }
+ return;
+ }
+
+ lenp = DPO(data, t->offset + sizeof(*elementp));
+ len = *lenp;
+ dp = DPO(data, t->offset + sizeof(*elementp) + sizeof(*lenp));
+ while (sizeof(void *) != sizeof(*elementp) &&
+ ((uintptr_t)dp) % sizeof(void *) != 0)
+ dp = (void *)(((char *)dp) + sizeof(*elementp));
+ val = *dp;
+
+ for (i = 0; i < len; i++) {
+ if (val[i]) {
+ _asn1_free(tactual_type, val[i]);
+ free(val[i]);
+ }
+ }
+ free(val);
+ *lenp = 0;
+ *dp = NULL;
+}
+
+void
+_asn1_free(const struct asn1_template *t, void *data)
+{
+ size_t elements = A1_HEADER_LEN(t);
+
+ if (t->tt & A1_HF_PRESERVE)
+ der_free_octet_string(data);
+
+ t++;
+
+ while (elements) {
+ switch (t->tt & A1_OP_MASK) {
+ case A1_OP_OPENTYPE_OBJSET: {
+ _asn1_free_open_type(t, data);
+ break;
+ }
+ case A1_OP_NAME: break;
+ case A1_OP_DEFVAL: break;
+ case A1_OP_TYPE_DECORATE_EXTERN:
+ case A1_OP_TYPE_DECORATE:
+ case A1_OP_TYPE:
+ case A1_OP_TYPE_EXTERN: {
+ void *el = DPO(data, t->offset);
+ void **pel = (void **)el;
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ if (*pel == NULL)
+ break;
+ el = *pel;
+ }
+
+ if ((t->tt & A1_OP_MASK) == A1_OP_TYPE || (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
+ _asn1_free(t->ptr, el);
+ } else if ((t->tt & A1_OP_MASK) == A1_OP_TYPE_EXTERN) {
+ const struct asn1_type_func *f = t->ptr;
+ (f->release)(el);
+ } else {
+ /* A1_OP_TYPE_DECORATE_EXTERN */
+ const struct asn1_type_func *f = t->ptr;
+
+ if (f && f->release)
+ (f->release)(el);
+ else if (f)
+ memset(el, 0, f->size);
+ }
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ free(el);
+ *pel = NULL;
+ }
+
+ break;
+ }
+ case A1_OP_PARSE: {
+ unsigned int type = A1_PARSE_TYPE(t->tt);
+ void *el = DPO(data, t->offset);
+
+ if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
+ ABORT_ON_ERROR();
+ break;
+ }
+ (asn1_template_prim[type].release)(el);
+ break;
+ }
+ case A1_OP_TAG: {
+ void *el = DPO(data, t->offset);
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ void **pel = (void **)el;
+
+ if (*pel == NULL)
+ break;
+ _asn1_free(t->ptr, *pel);
+ free(*pel);
+ *pel = NULL;
+ } else {
+ _asn1_free(t->ptr, el);
+ }
+
+ break;
+ }
+ case A1_OP_SETOF:
+ case A1_OP_SEQOF: {
+ struct template_of *el = DPO(data, t->offset);
+ size_t ellen = _asn1_sizeofType(t->ptr);
+ unsigned char *element = el->val;
+ unsigned int i;
+
+ for (i = 0; i < el->len; i++) {
+ _asn1_free(t->ptr, element);
+ element += ellen;
+ }
+ free(el->val);
+ el->val = NULL;
+ el->len = 0;
+
+ break;
+ }
+ case A1_OP_BMEMBER:
+ break;
+ case A1_OP_CHOICE: {
+ const struct asn1_template *choice = t->ptr;
+ const unsigned int *element = DPOC(data, choice->offset);
+
+ if (*element > A1_HEADER_LEN(choice))
+ break;
+
+ if (*element == 0) {
+ /*
+ * If choice->tt != 0 then this is an extensible choice, and
+ * the offset choice->tt is the offset to u.ellipsis.
+ */
+ if (choice->tt != 0)
+ der_free_octet_string(DPO(data, choice->tt));
+ /*
+ * Else this was a not-fully initialized CHOICE. We could
+ * stand to memset clear the rest of it though...
+ */
+ } else {
+ choice += *element;
+ _asn1_free(choice->ptr, DPO(data, choice->offset));
+ }
+ break;
+ }
+ default:
+ ABORT_ON_ERROR();
+ break;
+ }
+ t++;
+ elements--;
+ }
+}
+
+static char *
+getindent(int flags, unsigned int i)
+{
+ char *s;
+
+ if (!(flags & ASN1_PRINT_INDENT) || i == 0)
+ return NULL;
+ if (i > 128)
+ i = 128;
+ if ((s = malloc(i * 2 + 2)) == NULL)
+ return NULL;
+ s[0] = '\n';
+ s[i * 2 + 1] = '\0';
+ memset(s + 1, ' ', i * 2);
+ return s;
+}
+
+static struct rk_strpool *_asn1_print(const struct asn1_template *,
+ struct rk_strpool *,
+ int,
+ unsigned int,
+ const void *,
+ const heim_octet_string *);
+
+/* See commentary in _asn1_decode_open_type() */
+static struct rk_strpool *
+_asn1_print_open_type(const struct asn1_template *t, /* object set template */
+ struct rk_strpool *r,
+ int flags,
+ unsigned int indent,
+ const void *data,
+ const char *opentype_name)
+{
+ const struct asn1_template *tactual_type;
+ const struct asn1_template *tos = t->ptr;
+ const unsigned int *lenp = NULL; /* Pointer to array length field */
+ unsigned int len = 1; /* Array length */
+ size_t i;
+ const void * const *dp;
+ const void * const *val;
+ const int *elementp = DPOC(data, t->offset); /* Choice enum pointer */
+ char *indents = getindent(flags, indent);
+
+ /* XXX We assume sizeof(enum) == sizeof(int) */
+ if (!*elementp || *elementp >= A1_HEADER_LEN(tos) + 1) {
+ r = rk_strpoolprintf(r, ",%s\"_%s_choice\":\"_ERROR_DECODING_\"",
+ indents ? indents : "", opentype_name);
+ free(indents);
+ return r;
+ }
+ tactual_type = tos[3*(*elementp - 1) + 4].ptr;
+
+ r = rk_strpoolprintf(r, ",%s\"_%s_choice\":\"%s\"",
+ indents ? indents : "", opentype_name,
+ (const char *)tos[3*(*elementp - 1) + 2].ptr);
+ if (!r) {
+ free(indents);
+ return r;
+ }
+
+ if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
+ dp = DPOC(data, t->offset + sizeof(*elementp));
+ while (sizeof(void *) != sizeof(*elementp) &&
+ ((uintptr_t)dp) % sizeof(void *) != 0)
+ dp = (void *)(((char *)dp) + sizeof(*elementp));
+ if (*dp) {
+ struct rk_strpool *r2 = NULL;
+ char *s = NULL;
+
+ r2 = _asn1_print(tactual_type, r2, flags, indent + 1, *dp, NULL);
+ if (r2 == NULL) {
+ r = rk_strpoolprintf(r, ",%s\"_%s\":\"_ERROR_FORMATTING_\"",
+ indents ? indents : "", opentype_name);
+ free(indents);
+ return r;
+ }
+ s = rk_strpoolcollect(r2);
+ if (s)
+ r = rk_strpoolprintf(r, ",%s\"_%s\":%s",
+ indents ? indents : "", opentype_name, s);
+ free(s);
+ }
+ free(indents);
+ return r;
+ }
+
+ lenp = DPOC(data, t->offset + sizeof(*elementp));
+ len = *lenp;
+ dp = DPOC(data, t->offset + sizeof(*elementp) + sizeof(*lenp));
+ while (sizeof(void *) != sizeof(*elementp) &&
+ ((uintptr_t)dp) % sizeof(void *) != 0)
+ dp = (void *)(((char *)dp) + sizeof(*elementp));
+ val = *dp;
+
+ r = rk_strpoolprintf(r, ",%s\"_%s\":[", indents ? indents : "",
+ opentype_name);
+ free(indents);
+ indents = getindent(flags, indent + 1);
+ r = rk_strpoolprintf(r, "%s", indents ? indents : "");
+ for (i = 0; r && i < len; i++) {
+ struct rk_strpool *r2 = NULL;
+ char *s = NULL;;
+
+ if (val[i]) {
+ r2 = _asn1_print(tactual_type, r2, flags, indent + 2, val[i], NULL);
+ if (r2 == NULL) {
+ rk_strpoolfree(r);
+ free(indents);
+ return NULL;
+ }
+ }
+ if (i)
+ r = rk_strpoolprintf(r, ",%s", indents ? indents : "");
+ if (r)
+ r = rk_strpoolprintf(r, "%s", (s = rk_strpoolcollect(r2)));
+ free(s);
+ }
+ free(indents);
+ return rk_strpoolprintf(r, "]");
+}
+
+static struct rk_strpool *
+_asn1_print(const struct asn1_template *t,
+ struct rk_strpool *r,
+ int flags,
+ unsigned int indent,
+ const void *data,
+ const heim_octet_string *saved)
+{
+ const struct asn1_template *tbase = t;
+ const struct asn1_template *tnames;
+ size_t nelements = A1_HEADER_LEN(t);
+ size_t elements = nelements;
+ size_t nnames = 0;
+ char *indents = getindent(flags, indent);
+
+ for (t += nelements; t > tbase && (t->tt & A1_OP_MASK) == A1_OP_NAME; t--)
+ nnames++;
+
+ tnames = tbase + nelements - nnames + 1;
+
+ if (!r)
+ r = rk_strpoolprintf(r, "%s", "");
+
+ if (nnames)
+ r = rk_strpoolprintf(r, "%s{\"_type\":\"%s\"",
+ indents ? indents : "",
+ (const char *)(tnames++)->ptr);
+ if (saved && r) {
+ char *s = der_print_octet_string(data, 0);
+
+ if (!s) {
+ rk_strpoolfree(r);
+ free(indents);
+ return NULL;
+ }
+ r = rk_strpoolprintf(r, ",%s\"_save\":\"%s\"",
+ indents ? indents : "", s);
+ free(s);
+ }
+ saved = NULL;
+ if (tbase->tt & A1_HF_PRESERVE)
+ saved = data;
+
+ t = tbase + 1;
+ while (r && elements && (t->tt & A1_OP_MASK) != A1_OP_NAME) {
+ switch (t->tt & A1_OP_MASK) {
+ case A1_OP_NAME:
+ continue;
+ case A1_OP_DEFVAL:
+ t++;
+ elements--;
+ continue;
+ case A1_OP_OPENTYPE_OBJSET: {
+ size_t opentype = (t->tt >> 10) & ((1<<10)-1);
+ r = _asn1_print_open_type(t, r, flags, indent + 1, data,
+ tbase[(nelements - nnames) + 2 + opentype].ptr);
+ t++;
+ elements--;
+ continue;
+ }
+ default: break;
+ }
+ if (nnames &&
+ (t->tt & A1_OP_MASK) != A1_OP_TYPE_DECORATE_EXTERN &&
+ (t->tt & A1_OP_MASK) != A1_OP_TYPE_DECORATE)
+ r = rk_strpoolprintf(r, ",%s\"%s\":",
+ indents ? indents : "",
+ (const char *)(tnames++)->ptr);
+ switch (t->tt & A1_OP_MASK) {
+ case A1_OP_OPENTYPE_OBJSET:
+ break;
+ case A1_OP_NAME: break;
+ case A1_OP_DEFVAL: break;
+ case A1_OP_TYPE_DECORATE_EXTERN: break;
+ case A1_OP_TYPE_DECORATE: break; /* We could probably print this though */
+ case A1_OP_TYPE:
+ case A1_OP_TYPE_EXTERN: {
+ const void *el = DPOC(data, t->offset);
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ const void * const *pel = (const void *const *)el;
+ if (*pel == NULL) {
+ r = rk_strpoolprintf(r, "null");
+ break;
+ }
+ el = *pel;
+ }
+
+ if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
+ r = _asn1_print(t->ptr, r, flags, indent + 1, el, saved);
+ } else {
+ const struct asn1_type_func *f = t->ptr;
+ char *s = NULL;
+
+ s = (f->print)(el, 0);
+ if (s == NULL) {
+ rk_strpoolfree(r);
+ free(indents);
+ return NULL;
+ }
+ r = rk_strpoolprintf(r, "%s", s);
+ free(s);
+ }
+ break;
+ }
+ case A1_OP_PARSE: {
+ unsigned int type = A1_PARSE_TYPE(t->tt);
+ const void *el = DPOC(data, t->offset);
+ char *s = NULL;
+
+ if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
+ ABORT_ON_ERROR();
+ break;
+ }
+
+ if (type == A1T_IMEMBER && t->ptr) {
+ /* Enumeration. Use the symbolic name of this value */
+ const struct asn1_template *tenum = t->ptr;
+ size_t left = 0;
+ size_t right = A1_HEADER_LEN(tenum);
+ size_t mid;
+ uint32_t v = *(unsigned int *)el;
+ int c = -1;
+
+ while (left <= right) {
+ mid = (left + right) >> 1;
+
+ if ((tenum[mid].tt & A1_OP_MASK) != A1_OP_NAME)
+ break;
+ c = v - tenum[mid].offset;
+ if (c < 0) {
+ if (mid)
+ right = mid - 1;
+ else
+ break;
+ } else if (c > 0) {
+ left = mid + 1;
+ } else {
+ break;
+ }
+ }
+ if (c == 0) {
+ r = rk_strpoolprintf(r, "\"%s\"", (const char *)tenum[mid].ptr);
+ break;
+ }
+ }
+ s = (asn1_template_prim[type].print)(el, flags);
+ switch (type) {
+ case A1T_OID:
+ case A1T_IMEMBER:
+ case A1T_BOOLEAN:
+ case A1T_INTEGER:
+ case A1T_INTEGER64:
+ case A1T_UNSIGNED:
+ case A1T_UNSIGNED64:
+ if (s)
+ r = rk_strpoolprintf(r, "%s", s);
+ break;
+ default: {
+ char *s2 = NULL;
+
+ if (s)
+ (void) rk_strasvis(&s2, s, VIS_CSTYLE|VIS_TAB|VIS_NL, "\"");
+ free(s);
+ s = s2;
+ if (s)
+ r = rk_strpoolprintf(r, "\"%s\"", s);
+ }
+ }
+ if (!s) {
+ rk_strpoolfree(r);
+ free(indents);
+ return NULL;
+ }
+ free(s);
+ break;
+ }
+ case A1_OP_TAG: {
+ const void *el = DPOC(data, t->offset);
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ const void * const *pel = (const void * const *)el;
+ if (*pel == NULL) {
+ r = rk_strpoolprintf(r, "null");
+ break;
+ }
+ el = *pel;
+ }
+
+ r = _asn1_print(t->ptr, r, flags, indent + 1, el, saved);
+ break;
+ }
+ case A1_OP_SETOF:
+ case A1_OP_SEQOF: {
+ const struct template_of *el = DPOC(data, t->offset);
+ size_t ellen = _asn1_sizeofType(t->ptr);
+ const unsigned char *element = el->val;
+ unsigned int i;
+
+ r = rk_strpoolprintf(r, "%s[", indents ? indents : "");
+ for (i = 0; r && i < el->len; i++) {
+ if (i)
+ r = rk_strpoolprintf(r, ",%s", indents ? indents : "");
+ r = _asn1_print(t->ptr, r, flags, indent + 1, element, saved);
+ element += ellen;
+ }
+ if (r)
+ r = rk_strpoolprintf(r, "]");
+ break;
+ }
+ case A1_OP_BMEMBER: {
+ const struct asn1_template *bmember = t->ptr;
+ size_t size = bmember->offset;
+ size_t belements = A1_HEADER_LEN(bmember);
+ int first = 1;
+
+ bmember += belements;
+ r = rk_strpoolprintf(r, "%s[", indents ? indents : "");
+ while (r && belements) {
+ if (r && _asn1_bmember_isset_bit(data, bmember->offset, size)) {
+ if (!first)
+ r = rk_strpoolprintf(r, ",");
+ first = 0;
+ r = rk_strpoolprintf(r, "%s\"%s\"", indents ? indents : "",
+ (const char *)bmember->ptr);
+ }
+ belements--; bmember--;
+ }
+ if (r)
+ r = rk_strpoolprintf(r, "]");
+ break;
+ }
+ case A1_OP_CHOICE: {
+ const struct asn1_template *choice = t->ptr;
+ const unsigned int *element = DPOC(data, choice->offset);
+ unsigned int nchoices = ((uintptr_t)choice->ptr) >> 1;
+
+ if (*element > A1_HEADER_LEN(choice)) {
+ r = rk_strpoolprintf(r, "null");
+ } else if (*element == 0) {
+ /* XXX If choice->tt then we should print the u.ellipsis */
+ r = rk_strpoolprintf(r, "null");
+ } else {
+ choice += *element;
+ r = rk_strpoolprintf(r, "%s{\"_choice\":\"%s\",%s\"value\":",
+ indents ? indents : "",
+ (const char *)choice[nchoices].ptr,
+ indents ? indents : "");
+ if (r)
+ r = _asn1_print(choice->ptr, r, flags, indent + 1,
+ DPOC(data, choice->offset), NULL);
+ if (r)
+ r = rk_strpoolprintf(r, "}");
+ }
+ break;
+ }
+ default:
+ ABORT_ON_ERROR();
+ break;
+ }
+ t++;
+ elements--;
+ }
+ free(indents);
+ if (nnames && r)
+ return rk_strpoolprintf(r, "}");
+ return r;
+}
+
+char *
+_asn1_print_top(const struct asn1_template *t,
+ int flags,
+ const void *data)
+{
+ struct rk_strpool *r = _asn1_print(t, NULL, flags, 0, data, NULL);
+
+ if (r == NULL)
+ return NULL;
+ return rk_strpoolcollect(r);
+}
+
+/* See commentary in _asn1_decode_open_type() */
+static int
+_asn1_copy_open_type(const struct asn1_template *t, /* object set template */
+ const void *from,
+ void *to)
+{
+ const struct asn1_template *tactual_type;
+ const struct asn1_template *tos = t->ptr;
+ size_t i;
+ const void * const *dfromp;
+ const void * const *valfrom;
+ const unsigned int *lenfromp;
+ void **dtop;
+ void **valto;
+ unsigned int *lentop;
+ unsigned int len;
+ const int *efromp = DPO(from, t->offset);
+ int *etop = DPO(to, t->offset);
+ int ret = 0;
+
+ /* XXX We assume sizeof(enum) == sizeof(int) */
+ if (!*efromp || *efromp >= A1_HEADER_LEN(tos) + 1) {
+ if ((t->tt & A1_OS_OT_IS_ARRAY))
+ memset(etop, 0, sizeof(int) + sizeof(unsigned int) + sizeof(void *));
+ else
+ memset(etop, 0, sizeof(int) + sizeof(void *));
+ return 0; /* Unknown choice -> not copied */
+ }
+ tactual_type = &tos[3*(*efromp - 1) + 4];
+
+ if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
+ dfromp = DPO(from, t->offset + sizeof(*efromp));
+ while (sizeof(void *) != sizeof(*efromp) &&
+ ((uintptr_t)dfromp) % sizeof(void *) != 0)
+ dfromp = (void *)(((char *)dfromp) + sizeof(*efromp));
+ if (!*dfromp)
+ return 0;
+
+ dtop = DPO(to, t->offset + sizeof(*etop));
+ while (sizeof(void *) != sizeof(*etop) &&
+ ((uintptr_t)dtop) % sizeof(void *) != 0)
+ dtop = (void *)(((char *)dtop) + sizeof(*etop));
+
+ if ((*dtop = calloc(1, tactual_type->offset)) == NULL)
+ ret = ENOMEM;
+ if (ret == 0)
+ ret = _asn1_copy(tactual_type->ptr, *dfromp, *dtop);
+ if (ret == 0)
+ *etop = *efromp;
+ return ret;
+ }
+
+ lenfromp = DPO(from, t->offset + sizeof(*efromp));
+ dfromp = DPO(from, t->offset + sizeof(*efromp) + sizeof(*lenfromp));
+ valfrom = *dfromp;
+ lentop = DPO(to, t->offset + sizeof(*etop));
+ dtop = DPO(to, t->offset + sizeof(*etop) + sizeof(*lentop));
+
+ *etop = *efromp;
+
+ len = *lenfromp;
+ *lentop = 0;
+ *dtop = NULL;
+ if ((valto = calloc(len, sizeof(valto[0]))) == NULL)
+ ret = ENOMEM;
+ for (i = 0, len = *lenfromp; ret == 0 && i < len; i++) {
+ if (valfrom[i] == NULL) {
+ valto[i] = NULL;
+ continue;
+ }
+ if ((valto[i] = calloc(1, tactual_type->offset)) == NULL)
+ ret = ENOMEM;
+ else
+ ret = _asn1_copy(tactual_type->ptr, valfrom[i], valto[i]);
+ (*lentop)++;
+ }
+
+ for (i = 0; ret && i < (*lentop); i++) {
+ if (valto[i]) {
+ _asn1_free(tactual_type->ptr, valto[i]);
+ free(valto[i]);
+ }
+ }
+ if (ret) {
+ free(valto);
+ *lentop = 0;
+ } else
+ *dtop = valto;
+ return ret;
+}
+
+int
+_asn1_copy(const struct asn1_template *t, const void *from, void *to)
+{
+ size_t elements = A1_HEADER_LEN(t);
+ int ret = 0;
+ int preserve = (t->tt & A1_HF_PRESERVE);
+
+ t++;
+
+ if (preserve) {
+ ret = der_copy_octet_string(from, to);
+ if (ret)
+ return ret;
+ }
+
+ while (elements) {
+ switch (t->tt & A1_OP_MASK) {
+ case A1_OP_OPENTYPE_OBJSET: {
+ _asn1_copy_open_type(t, from, to);
+ break;
+ }
+ case A1_OP_NAME: break;
+ case A1_OP_DEFVAL: break;
+ case A1_OP_TYPE_DECORATE_EXTERN:
+ case A1_OP_TYPE_DECORATE:
+ case A1_OP_TYPE:
+ case A1_OP_TYPE_EXTERN: {
+ const void *fel = DPOC(from, t->offset);
+ void *tel = DPO(to, t->offset);
+ void **ptel = (void **)tel;
+ size_t size;
+
+ if ((t->tt & A1_OP_MASK) == A1_OP_TYPE ||
+ (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
+ size = _asn1_sizeofType(t->ptr);
+ } else {
+ const struct asn1_type_func *f = t->ptr;
+ size = f->size;
+ }
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ void **pfel = (void **)fel;
+ if (*pfel == NULL)
+ break;
+ fel = *pfel;
+
+ tel = *ptel = calloc(1, size);
+ if (tel == NULL)
+ return ENOMEM;
+ }
+
+ if ((t->tt & A1_OP_MASK) == A1_OP_TYPE ||
+ (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
+ ret = _asn1_copy(t->ptr, fel, tel);
+ } else if ((t->tt & A1_OP_MASK) == A1_OP_TYPE_EXTERN) {
+ const struct asn1_type_func *f = t->ptr;
+ ret = (f->copy)(fel, tel);
+ } else {
+ const struct asn1_type_func *f = t->ptr;
+
+ /* A1_OP_TYPE_DECORATE_EXTERN */
+ if (f && f->copy)
+ ret = (f->copy)(fel, tel);
+ else if (f)
+ memset(tel, 0, f->size);
+ }
+
+ if (ret) {
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ free(*ptel);
+ *ptel = NULL;
+ }
+ return ret;
+ }
+ break;
+ }
+ case A1_OP_PARSE: {
+ unsigned int type = A1_PARSE_TYPE(t->tt);
+ const void *fel = DPOC(from, t->offset);
+ void *tel = DPO(to, t->offset);
+
+ if (type >= sizeof(asn1_template_prim)/sizeof(asn1_template_prim[0])) {
+ ABORT_ON_ERROR();
+ return ASN1_PARSE_ERROR;
+ }
+ ret = (asn1_template_prim[type].copy)(fel, tel);
+ if (ret)
+ return ret;
+ break;
+ }
+ case A1_OP_TAG: {
+ const void *oldfrom = from;
+ void *oldto = to;
+ void **tel = NULL;
+
+ from = DPOC(from, t->offset);
+ to = DPO(to, t->offset);
+
+ if (t->tt & A1_FLAG_OPTIONAL) {
+ void **fel = (void **)from;
+ tel = (void **)to;
+ if (*fel == NULL) {
+ from = oldfrom;
+ to = oldto;
+ break;
+ }
+ from = *fel;
+
+ to = *tel = calloc(1, _asn1_sizeofType(t->ptr));
+ if (to == NULL)
+ return ENOMEM;
+ }
+
+ ret = _asn1_copy(t->ptr, from, to);
+ if (ret) {
+ if (tel) {
+ free(*tel);
+ *tel = NULL;
+ }
+ return ret;
+ }
+
+ from = oldfrom;
+ to = oldto;
+
+ break;
+ }
+ case A1_OP_SETOF:
+ case A1_OP_SEQOF: {
+ const struct template_of *fel = DPOC(from, t->offset);
+ struct template_of *tel = DPO(to, t->offset);
+ size_t ellen = _asn1_sizeofType(t->ptr);
+ unsigned int i;
+
+ tel->val = calloc(fel->len, ellen);
+ if (tel->val == NULL && fel->len > 0)
+ return ENOMEM;
+
+ tel->len = fel->len;
+
+ for (i = 0; i < fel->len; i++) {
+ ret = _asn1_copy(t->ptr,
+ DPOC(fel->val, (i * ellen)),
+ DPO(tel->val, (i *ellen)));
+ if (ret)
+ return ret;
+ }
+ break;
+ }
+ case A1_OP_BMEMBER: {
+ const struct asn1_template *bmember = t->ptr;
+ size_t size = bmember->offset;
+ memcpy(to, from, size);
+ break;
+ }
+ case A1_OP_CHOICE: {
+ const struct asn1_template *choice = t->ptr;
+ const unsigned int *felement = DPOC(from, choice->offset);
+ unsigned int *telement = DPO(to, choice->offset);
+
+ if (*felement > A1_HEADER_LEN(choice))
+ return ASN1_PARSE_ERROR;
+
+ *telement = *felement;
+
+ if (*felement == 0) {
+ if (choice->tt)
+ ret = der_copy_octet_string(DPOC(from, choice->tt), DPO(to, choice->tt));
+ /*
+ * Else we should really memset clear the rest of this choice,
+ * but we don't really know its size.
+ */
+ } else {
+ choice += *felement;
+ ret = _asn1_copy(choice->ptr,
+ DPOC(from, choice->offset),
+ DPO(to, choice->offset));
+ }
+ if (ret)
+ return ret;
+ break;
+ }
+ default:
+ ABORT_ON_ERROR();
+ break;
+ }
+ t++;
+ elements--;
+ }
+ return 0;
+}
+
+int
+_asn1_decode_top(const struct asn1_template *t, unsigned flags, const unsigned char *p, size_t len, void *data, size_t *size)
+{
+ int ret;
+ memset(data, 0, t->offset);
+ ret = _asn1_decode(t, flags, p, len, data, size);
+ if (ret)
+ _asn1_free_top(t, data);
+
+ return ret;
+}
+
+int
+_asn1_copy_top(const struct asn1_template *t, const void *from, void *to)
+{
+ int ret;
+ memset(to, 0, t->offset);
+ ret = _asn1_copy(t, from, to);
+ if (ret)
+ _asn1_free_top(t, to);
+
+ return ret;
+}
+
+void
+_asn1_free_top(const struct asn1_template *t, void *data)
+{
+ _asn1_free(t, data);
+ memset(data, 0, t->offset);
+}
diff --git a/third_party/heimdal/lib/asn1/test.asn1 b/third_party/heimdal/lib/asn1/test.asn1
new file mode 100644
index 0000000..08c7dcd
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/test.asn1
@@ -0,0 +1,309 @@
+-- $Id$ --
+
+TEST DEFINITIONS ::=
+
+BEGIN
+
+IMPORTS HEIM_ANY FROM heim;
+
+-- Check that we handle out of order definitions.
+-- The compiler should emit the definition of TESTOutOfOrderBar before that of
+-- TESTOutOfOrderFoo.
+TESTOutOfOrderFoo ::= SEQUENCE {
+ bar TESTOutOfOrderBar
+}
+
+TESTOutOfOrderBar ::= SEQUENCE {
+ aMember INTEGER
+}
+
+-- Check that we can handle rpc.mountd style "lists". This is unnecessarily
+-- inefficient in its encoding, and there's no point to using this over
+-- SEQUENCE OF (arrays), but it's neat that we can do this now that we can do
+-- out of order definitions.
+--
+-- This could be useful if we ever extend asn1_compile to also handle XDR,
+-- which we well might since XDR's syntax is a dual of a strict subset of
+-- ASN.1, and since XDR the encoding is fairly straightforward.
+--
+-- Note that the `next' member has to be OPTIONAL for this to work.
+TESTCircular ::= SEQUENCE {
+ name UTF8String,
+ next TESTCircular OPTIONAL
+}
+
+TESTDefault ::= SEQUENCE {
+ name UTF8String DEFAULT "Heimdal",
+ version [0] TESTuint32 DEFAULT 8,
+ maxint TESTuint64 DEFAULT 9223372036854775807,
+ works BOOLEAN DEFAULT TRUE
+}
+
+TESTuint32 ::= INTEGER (0..4294967295)
+TESTuint64 ::= INTEGER(0..9223372036854775807)
+TESTint64 ::= INTEGER(-9223372036854775808..9223372036854775807)
+
+TESTLargeTag ::= SEQUENCE {
+ foo[127] INTEGER (-2147483648..2147483647),
+ bar[128] INTEGER (-2147483648..2147483647)
+}
+
+TESTSeq ::= SEQUENCE {
+ tag0[0] INTEGER (-2147483648..2147483647),
+ tag1[1] TESTLargeTag,
+ tagless INTEGER (-2147483648..2147483647),
+ tag3[2] INTEGER (-2147483648..2147483647)
+}
+
+TESTChoice1 ::= CHOICE {
+ i1[1] INTEGER (-2147483648..2147483647),
+ i2[2] INTEGER (-2147483648..2147483647),
+ ...
+}
+
+TESTChoice2 ::= CHOICE {
+ i1[1] INTEGER (-2147483648..2147483647),
+ ...
+}
+
+TESTInteger ::= INTEGER (-2147483648..2147483647)
+
+TESTInteger2 ::= [4] IMPLICIT TESTInteger
+TESTInteger3 ::= [5] IMPLICIT TESTInteger2
+
+TESTImplicit ::= SEQUENCE {
+ ti1[0] IMPLICIT INTEGER (-2147483648..2147483647),
+ ti2[1] IMPLICIT SEQUENCE {
+ foo[127] INTEGER (-2147483648..2147483647)
+ },
+ ti3[2] IMPLICIT [5] IMPLICIT [4] IMPLICIT INTEGER (-2147483648..2147483647)
+}
+
+TESTImplicit2 ::= SEQUENCE {
+ ti1[0] IMPLICIT TESTInteger,
+-- ti2[1] IMPLICIT TESTLargeTag, this is disabled since the IMPLICT encoder does't get the types right when stepping inside an structure --
+ ti3[2] IMPLICIT TESTInteger3,
+ ti4[51] IMPLICIT TESTInteger OPTIONAL
+}
+
+TESTImplicit3 ::= CHOICE {
+ ti1[0] IMPLICIT INTEGER (-2147483648..2147483647),
+ ti2[5] IMPLICIT CHOICE { i1[1] INTEGER (-2147483648..2147483647) }
+}
+
+TESTImplicit4 ::= CHOICE {
+ ti1[0] IMPLICIT INTEGER (-2147483648..2147483647),
+ ti2[5] IMPLICIT TESTChoice2
+}
+
+TESTAllocInner ::= SEQUENCE {
+ ai[0] TESTInteger
+}
+
+TESTAlloc ::= SEQUENCE {
+ tagless TESTAllocInner OPTIONAL,
+ three [1] INTEGER (-2147483648..2147483647),
+ tagless2 HEIM_ANY OPTIONAL
+}
+
+TESTOptional ::= SEQUENCE {
+ zero [0] INTEGER (-2147483648..2147483647) OPTIONAL,
+ one [1] INTEGER (-2147483648..2147483647) OPTIONAL
+}
+
+
+TESTCONTAINING ::= OCTET STRING ( CONTAINING INTEGER )
+TESTENCODEDBY ::= OCTET STRING ( ENCODED BY
+ { joint-iso-itu-t(2) asn(1) ber-derived(2) distinguished-encoding(1) }
+)
+
+testDer OBJECT IDENTIFIER ::= {
+ joint-iso-itu-t(2) asn(1) ber-derived(2) distinguished-encoding(1)
+}
+
+testContainingEncodedBy ::= OCTET STRING ( CONTAINING INTEGER ENCODED BY
+ { joint-iso-itu-t(2) asn(1) ber-derived(2) distinguished-encoding(1) }
+)
+
+testContainingEncodedBy2 ::= OCTET STRING (
+ CONTAINING INTEGER ENCODED BY testDer
+)
+
+
+testValue1 INTEGER ::= 1
+
+testUserConstrained ::= OCTET STRING (CONSTRAINED BY { -- meh -- })
+-- TESTUSERCONSTRAINED2 ::= OCTET STRING (CONSTRAINED BY { TESTInteger })
+-- TESTUSERCONSTRAINED3 ::= OCTET STRING (CONSTRAINED BY { INTEGER })
+-- TESTUSERCONSTRAINED4 ::= OCTET STRING (CONSTRAINED BY { INTEGER : 1 })
+
+TESTSeqOf ::= SEQUENCE OF TESTInteger
+
+TESTSeqSizeOf1 ::= SEQUENCE SIZE (2) OF TESTInteger
+TESTSeqSizeOf2 ::= SEQUENCE SIZE (1..2) OF TESTInteger
+TESTSeqSizeOf3 ::= SEQUENCE SIZE (1..MAX) OF TESTInteger
+TESTSeqSizeOf4 ::= SEQUENCE SIZE (0..2) OF TESTInteger
+
+TESTOSSize1 ::= OCTET STRING SIZE (1..2)
+
+TESTSeqOfSeq ::= SEQUENCE OF SEQUENCE {
+ zero [0] TESTInteger
+}
+
+TESTSeqOfSeq2 ::= SEQUENCE OF SEQUENCE {
+ string [0] GeneralString
+}
+
+TESTSeqOfSeq3 ::= SEQUENCE OF SEQUENCE {
+ zero [0] TESTInteger,
+ string [0] GeneralString
+}
+
+TESTSeqOf2 ::= SEQUENCE {
+ strings SEQUENCE OF GeneralString
+}
+
+TESTSeqOf3 ::= SEQUENCE {
+ strings SEQUENCE OF GeneralString OPTIONAL
+}
+
+-- Larger/more complex to increase odds of out-of-bounds
+-- read/writes if miscoded
+
+TESTSeqOf4 ::= SEQUENCE {
+ b1 [0] SEQUENCE OF SEQUENCE {
+ s1 OCTET STRING,
+ s2 OCTET STRING,
+ u1 TESTuint64,
+ u2 TESTuint64
+ } OPTIONAL,
+ b2 [1] IMPLICIT SEQUENCE OF SEQUENCE {
+ u1 TESTuint64,
+ u2 TESTuint64,
+ u3 TESTuint64,
+ s1 OCTET STRING,
+ s2 OCTET STRING,
+ s3 OCTET STRING
+ } OPTIONAL,
+ b3 [2] IMPLICIT SEQUENCE OF SEQUENCE {
+ s1 OCTET STRING,
+ u1 TESTuint64,
+ s2 OCTET STRING,
+ u2 TESTuint64,
+ s3 OCTET STRING,
+ u3 TESTuint64,
+ s4 OCTET STRING,
+ u4 TESTuint64
+ } OPTIONAL
+}
+
+TESTSeqOf5 ::= SEQUENCE {
+ outer SEQUENCE {
+ inner SEQUENCE {
+ u0 TESTuint64,
+ s0 OCTET STRING,
+ u1 TESTuint64,
+ s1 OCTET STRING,
+ u2 TESTuint64,
+ s2 OCTET STRING,
+ u3 TESTuint64,
+ s3 OCTET STRING,
+ u4 TESTuint64,
+ s4 OCTET STRING,
+ u5 TESTuint64,
+ s5 OCTET STRING,
+ u6 TESTuint64,
+ s6 OCTET STRING,
+ u7 TESTuint64,
+ s7 OCTET STRING
+ }
+ }
+ OPTIONAL
+}
+
+TESTPreserve ::= SEQUENCE {
+ zero [0] TESTInteger,
+ one [1] TESTInteger
+}
+
+TESTBitString ::= BIT STRING {
+ zero(0),
+ eight(8),
+ thirtyone(31)
+}
+
+TESTBitString64 ::= BIT STRING {
+ zero(0),
+ eight(8),
+ thirtyone(31),
+ thirtytwo(32),
+ sixtythree(63)
+}
+
+TESTLargeBitString ::= BIT STRING {
+ zero(0),
+ eight(8),
+ thirtyone(31),
+ onehundredtwenty(120)
+}
+
+TESTMechType::= OBJECT IDENTIFIER
+TESTMechTypeList ::= SEQUENCE OF TESTMechType
+
+
+-- IOS stuff
+_EXTENSION ::= CLASS {
+ &id OBJECT IDENTIFIER UNIQUE,
+ &ExtnType,
+ &Critical BOOLEAN DEFAULT FALSE
+}
+
+TESTExtension{_EXTENSION:ExtensionSet} ::= SEQUENCE {
+ extnID _EXTENSION.&id({ExtensionSet}),
+ critical BOOLEAN
+-- (EXTENSION.&Critical({ExtensionSet}{@extnID}))
+ DEFAULT FALSE,
+ extnValue OCTET STRING (CONTAINING
+ _EXTENSION.&ExtnType({ExtensionSet}{@extnID}))
+}
+
+id-test-default OBJECT IDENTIFIER ::= { 1 2 3 4 }
+testext-TESTDefault _EXTENSION ::= {
+ &id id-test-default,
+ &Critical FALSE,
+ &ExtnType TESTDefault
+}
+
+-- And Here's an object set for the EXTENSION CLASS collecting a bunch of
+-- related extensions (here they are the extensions that certificates can
+-- carry in their extensions member):
+TestExtensions _EXTENSION ::= { testext-TESTDefault }
+
+TESTExtension ::= TESTExtension { TestExtensions }
+
+TESTExtensible ::= SEQUENCE {
+ version INTEGER,
+ extensions SEQUENCE OF TESTExtension
+}
+
+TESTDecorated ::= SEQUENCE {
+ version TESTuint32
+ -- gets decorated with varius fields (see test.opt)
+}
+
+TESTNotDecorated ::= SEQUENCE {
+ version TESTuint32
+ -- should have the same encoding as TESTDecorated
+}
+
+TESTDecoratedChoice ::= CHOICE {
+ version TESTuint32
+ -- gets decorated with varius fields (see test.opt)
+}
+
+TESTNotDecoratedChoice ::= CHOICE {
+ version TESTuint32
+ -- should have the same encoding as TESTDecoratedChoice
+}
+
+END
diff --git a/third_party/heimdal/lib/asn1/test.gen b/third_party/heimdal/lib/asn1/test.gen
new file mode 100644
index 0000000..bfb0486
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/test.gen
@@ -0,0 +1,14 @@
+# $Id$
+# Sample for TESTSeq in test.asn1
+#
+
+UNIV CONS Sequence 23
+ CONTEXT CONS 0 3
+ UNIV PRIM Integer 1 01
+ CONTEXT CONS 1 8
+ UNIV CONS Sequence 6
+ CONTEXT CONS 127 3
+ UNIV PRIM Integer 1 01
+ UNIV PRIM Integer 1 01
+ CONTEXT CONS 2 3
+ UNIV PRIM Integer 1 01
diff --git a/third_party/heimdal/lib/asn1/test.opt b/third_party/heimdal/lib/asn1/test.opt
new file mode 100644
index 0000000..755eba0
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/test.opt
@@ -0,0 +1,7 @@
+--sequence=TESTSeqOf
+--decorate=TESTDecorated:TESTuint32:version2?
+--decorate=TESTDecorated:my_vers:version3:my_copy_vers:my_free_vers:"check-gen.h"
+--decorate=TESTDecorated:void *:privthing
+--decorate=TESTDecoratedChoice:TESTuint32:version2?
+--decorate=TESTDecoratedChoice:my_vers:version3:my_copy_vers:my_free_vers:"check-gen.h"
+--decorate=TESTDecoratedChoice:void *:privthing
diff --git a/third_party/heimdal/lib/asn1/timegm.c b/third_party/heimdal/lib/asn1/timegm.c
new file mode 100644
index 0000000..4746fa8
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/timegm.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "der_locl.h"
+
+#define ASN1_MAX_YEAR 2000
+
+static int
+is_leap(unsigned y)
+{
+ y += 1900;
+ return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
+}
+
+static const unsigned ndays[2][12] ={
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
+
+/*
+ * This is a simplifed version of timegm(3) that doesn't accept out of
+ * bound values that timegm(3) normally accepts but those are not
+ * valid in asn1 encodings.
+ */
+
+time_t
+_der_timegm (struct tm *tm)
+{
+ time_t res = 0;
+ int i;
+
+ /*
+ * See comment in _der_gmtime
+ */
+ if (tm->tm_year > ASN1_MAX_YEAR)
+ return 0;
+
+ if (tm->tm_year < 0)
+ return -1;
+ if (tm->tm_mon < 0 || tm->tm_mon > 11)
+ return -1;
+ if (tm->tm_mday < 1 || tm->tm_mday > (int)ndays[is_leap(tm->tm_year)][tm->tm_mon])
+ return -1;
+ if (tm->tm_hour < 0 || tm->tm_hour > 23)
+ return -1;
+ if (tm->tm_min < 0 || tm->tm_min > 59)
+ return -1;
+ if (tm->tm_sec < 0 || tm->tm_sec > 59)
+ return -1;
+
+ for (i = 70; i < tm->tm_year; ++i)
+ res += is_leap(i) ? 366 : 365;
+
+ for (i = 0; i < tm->tm_mon; ++i)
+ res += ndays[is_leap(tm->tm_year)][i];
+ res += tm->tm_mday - 1;
+ res *= 24;
+ res += tm->tm_hour;
+ res *= 60;
+ res += tm->tm_min;
+ res *= 60;
+ res += tm->tm_sec;
+ return res;
+}
+
+struct tm *
+_der_gmtime(time_t t, struct tm *tm)
+{
+ time_t secday = t % (3600 * 24);
+ time_t days = t / (3600 * 24);
+
+ memset(tm, 0, sizeof(*tm));
+
+ tm->tm_sec = secday % 60;
+ tm->tm_min = (secday % 3600) / 60;
+ tm->tm_hour = (int)(secday / 3600);
+
+ /*
+ * Refuse to calculate time ~ 2000 years into the future, this is
+ * not possible for systems where time_t is a int32_t, however,
+ * when time_t is a int64_t, that can happen, and this becomes a
+ * denial of sevice.
+ */
+ if (days > (ASN1_MAX_YEAR * 365))
+ return NULL;
+
+ tm->tm_year = 70;
+ while(1) {
+ unsigned dayinyear = (is_leap(tm->tm_year) ? 366 : 365);
+ if (days < dayinyear)
+ break;
+ tm->tm_year += 1;
+ days -= dayinyear;
+ }
+ tm->tm_mon = 0;
+
+ while (1) {
+ unsigned daysinmonth = ndays[is_leap(tm->tm_year)][tm->tm_mon];
+ if (days < daysinmonth)
+ break;
+ days -= daysinmonth;
+ tm->tm_mon++;
+ }
+ tm->tm_mday = (int)(days + 1);
+
+ return tm;
+}
diff --git a/third_party/heimdal/lib/asn1/version-script.map b/third_party/heimdal/lib/asn1/version-script.map
new file mode 100644
index 0000000..67f9ff0
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/version-script.map
@@ -0,0 +1,6 @@
+# Export everything, but put a tag on is so that we make ourself incompatible with older versions
+
+HEIMDAL_ASN1_1.0 {
+ global:
+ *;
+};
diff --git a/third_party/heimdal/lib/asn1/x690sample.asn1 b/third_party/heimdal/lib/asn1/x690sample.asn1
new file mode 100644
index 0000000..18954a4
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/x690sample.asn1
@@ -0,0 +1,181 @@
+x690sample DEFINITIONS ::= BEGIN
+
+-- This is taken from Appendix A of X.690. The same module is used by all
+-- X.690 series specifications of ASN.1 Encoding Rules.
+--
+-- This doesn't exercise every feature, like OPTIONAL, not really DEFAULT, not
+-- EXPLICIT tagging, extensibility markers, etc., but it exercises some hard
+-- ones like SET and IMPLICIT tagging.
+--
+-- Because we don't yet have an option to add a namespace prefix to generated
+-- symbols, to avoid conflicts with rfc2459's Name we're prefixing the type
+-- names here manually.
+--
+-- WARNING: The encoding rules used for the sample encoding given in Appendix A
+-- of X.690, and used in lib/asn1/check-gen.c, is not specified in
+-- X.690! It seems very likely that it is neither CER nor DER but BER
+-- because the tags in the X690SamplePersonnelRecord (a SET { ... })
+-- are not in canonical order:
+--
+-- APPL CONS tag 0 = 133 bytes [0]
+-- APPL CONS tag 1 = 16 bytes [1]
+-- UNIV PRIM VisibleString = "John"
+-- UNIV PRIM VisibleString = "P"
+-- UNIV PRIM VisibleString = "Smith"
+-- -> CONTEXT CONS tag 0 = 10 bytes [0]
+-- UNIV PRIM VisibleString = "Director"
+-- -> APPL PRIM tag 2 = 1 bytes [2] IMPLICIT content
+-- ...
+--
+-- The canonical ordering of members in SET { ... } types is by tag,
+-- with UNIVERSAL tags before APPLICATION tags, those before CONTEXT,
+-- and those before PRIVATE, and within each class from lowest to
+-- highest numeric tag value. See X.680, section 8.6, which is
+-- referenced from X.690, section 10.3.
+--
+-- Here we can see that the `title` member should come _after_ the
+-- `number` member, but it does not.
+--
+-- Our test relies on our compiler producing the same test data when
+-- encoding the structure that the given test data decodes to. That
+-- works here only because our compiler does NOT sort SET { ... }
+-- members as it should (since we always produce DER).
+--
+-- Sorting SET members in the compiler is hard currently because we
+-- don't parse imported modules, so we don't know the tags of imported
+-- types, so we can only sort at run-time, which we don't do.
+--
+-- There is an obvious workaround, however: sort the SET { ... }
+-- definition manually!
+
+X690SamplePersonnelRecord ::= [APPLICATION 0] IMPLICIT SET {
+ name X690SampleName,
+ title [0] VisibleString,
+ number X690SampleEmployeeNumber,
+ dateOfHire [1] X690SampleDate,
+ nameOfSpouse [2] X690SampleName,
+ -- Heimdal's ASN.1 compiler doesn't handle DEFAULT values for types for
+ -- which it doesn't support literal values.
+ children [3] IMPLICIT SEQUENCE OF X690SampleChildInformation -- DEFAULT {}
+}
+
+X690SampleChildInformation ::= SET {
+ name X690SampleName,
+ dateOfBirth [0] X690SampleDate
+}
+
+X690SampleName ::= [APPLICATION 1] IMPLICIT SEQUENCE {
+ givenName VisibleString,
+ initial VisibleString,
+ familyName VisibleString
+}
+
+-- Range added for test convenience.
+X690SampleEmployeeNumber ::= [APPLICATION 2] IMPLICIT INTEGER (0..4294967295)
+
+X690SampleDate::= [APPLICATION 3] IMPLICIT VisibleString --YYYYMMDD
+
+-- The following is value syntax for the above, but Heimdal's ASN.1 compiler
+-- does not yet support value syntax for anything other than OIDs, booleans,
+-- integers, and UTF-8 strings:
+--
+-- { name { givenName "John", initial "P", familyName "Smith" },
+-- title "Director",
+-- number 51,
+-- dateOfHire "19710917",
+-- nameOfSpouse {givenName "Mary", initial "T", familyName "Smith" },
+-- children {
+-- {name {givenName "Ralph", initial "T", familyName "Smith" },
+-- dateOfBirth "19571111"},
+-- {name {givenName "Susan", initial "B", familyName "Jones" },
+-- I dateOfBirth "19590717"}
+-- }
+-- }
+--
+-- The encoding of this value is supposed to be (all hex) (adapted from X.690
+-- Appendix A):
+--
+-- 60818561101A044A6F686E1A01501A05536D697468A00A1A084469726563746F
+-- 72420133A10A43083139373130393137A21261101A044D6172791A01541A0553
+-- 6D697468A342311F61111A0552616C70681A01541A05536D697468A00A430831
+-- 39353731313131311F61111A05537573616E1A01421A05536D697468A00A4308
+-- 3139353930373137
+--
+-- And a rough visualization of this is (adapted from X.690 Appendix A):
+--
+-- T L
+-- 60 8185 # 3
+-- Name
+-- T L
+-- 61 10 # 2
+-- T L "John"
+-- 1A 04 4A6F686E # 6
+-- T L "P"
+-- 1A 01 50 # 3
+-- T L "Smith"
+-- 1A 05 536D697468 # 7
+-- Title
+-- T L T L "Director"
+-- A0 0A 1A 08 4469726563746F72 #12
+-- Emp. #
+-- 42 01 33 # 3
+-- Date of hire
+-- A1 0A 43 08 3139373130393137 #12
+-- Spouse
+-- A2 12 # 2
+-- Name
+-- 61 10 # 2
+-- 1A 04 4D617279 # 6
+-- 1A 01 54 # 3
+-- 1A 05 536D697468 # 7
+-- Children
+-- A3 42 # 2
+-- 31 1F # 2
+-- Name
+-- 61 11 1A 05 52616C7068 # 9
+-- 1A 01 54 # 3
+-- 1A 05 536D697468 # 7
+-- DoB
+-- A0 0A 43 08 3139353731313131 #12
+-- 31 1F # 2 bytes
+-- 61 11 1A 05 537573616E # 9 bytes
+-- 1A 01 42 # 3 bytes
+-- 1A 05 536D697468 # 7 bytes
+-- A0 0A 43 08 3139353930373137 #12 bytes
+--
+-- Our asn1_print program dumps this as follows, which looks correct:
+--
+-- APPL CONS tag 0 = 133 bytes [0]
+-- APPL CONS tag 1 = 16 bytes [1]
+-- UNIV PRIM VisibleString = "John"
+-- UNIV PRIM VisibleString = "P"
+-- UNIV PRIM VisibleString = "Smith"
+-- CONTEXT CONS tag 0 = 10 bytes [0]
+-- UNIV PRIM VisibleString = "Director"
+-- APPL PRIM tag 2 = 1 bytes [2] IMPLICIT content
+-- CONTEXT CONS tag 1 = 10 bytes [1]
+-- APPL PRIM tag 3 = 8 bytes [3] IMPLICIT content
+-- CONTEXT CONS tag 2 = 18 bytes [2]
+-- APPL CONS tag 1 = 16 bytes [1]
+-- UNIV PRIM VisibleString = "Mary"
+-- UNIV PRIM VisibleString = "T"
+-- UNIV PRIM VisibleString = "Smith"
+-- CONTEXT CONS tag 3 = 66 bytes [3]
+-- UNIV CONS Set = 31 bytes {
+-- APPL CONS tag 1 = 17 bytes [1]
+-- UNIV PRIM VisibleString = "Ralph"
+-- UNIV PRIM VisibleString = "T"
+-- UNIV PRIM VisibleString = "Smith"
+-- CONTEXT CONS tag 0 = 10 bytes [0]
+-- APPL PRIM tag 3 = 8 bytes [3] IMPLICIT content
+-- }
+-- UNIV CONS Set = 31 bytes {
+-- APPL CONS tag 1 = 17 bytes [1]
+-- UNIV PRIM VisibleString = "Susan"
+-- UNIV PRIM VisibleString = "B"
+-- UNIV PRIM VisibleString = "Smith"
+-- CONTEXT CONS tag 0 = 10 bytes [0]
+-- APPL PRIM tag 3 = 8 bytes [3] IMPLICIT content
+-- }
+
+END