1 # Heimdal's ASN.1 Compiler
3 This is a new README, and it's not very rich in contents yet. Be sure to check
4 out the [README on the template backend](/lib/asn1/README-template.md) and the [README
5 on automatic open type decoding via X.681/X.682/X.683
6 annotations](/lib/asn1/README-X681.md).
10 1. [Introduction](#Introduction)
11 2. [ASN.1 Support in Heimdal](#asn1-support-in-heimdal)
13 4. [Features](#Features)
14 5. [Limitations](#Limitations)
15 6. [Compiler Usage](#Compiler-usage)
16 7. [APIs Generated by the Compiler](#APIs-generated-by-the-compiler)
17 8. [asn1_print Usage](#asn1_print-usage)
18 9. [Implementation](#implementation)
19 10. [Moving From C](#moving-from-c)
23 ASN.1 is a... some would say baroque, perhaps obsolete, archaic even, "syntax"
24 for expressing data type schemas, and also a set of "encoding rules" (ERs) that
25 specify many ways to encode values of those types for interchange.
27 Some ERs are binary, others are textual. Some binary ERs are tag-length-value
28 (TLV), others have no need for tagging. Some of the ERs are roundly and
29 rightly disliked, but then there are XER (XML Encoding Rules) and JER (JSON
30 Encoding Rules) that really illustrate how the syntax and the encoding rules
31 really are separate and distinct things.
33 ASN.1 is a wheel that everyone loves to reinvent, and often badly. It's worth
34 knowing a bit about it before reinventing this wheel badly yet again.
36 It's also worth pondering that there appears to be ways to map most data
37 exchange metaschemas and schemas onto others, and therefore too, transliterate
38 most encodings onto others.
40 First, an example of the syntax:
43 -- This is what a certificate looks like (as in TLS server certificates, or
45 Certificate ::= SEQUENCE {
46 tbsCertificate TBSCertificate,
47 signatureAlgorithm AlgorithmIdentifier,
48 signatureValue BIT STRING
51 -- The main body of a certificate is here though:
52 TBSCertificate ::= SEQUENCE {
53 version [0] Version DEFAULT 1,
54 serialNumber CertificateSerialNumber,
55 signature AlgorithmIdentifier,
59 subjectPublicKeyInfo SubjectPublicKeyInfo,
60 issuerUniqueID [1] IMPLICIT BIT STRING OPTIONAL,
61 subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL,
62 extensions [3] EXPLICIT Extensions OPTIONAL
66 Here we see something akin to a "structure" or "record" with various named
67 fields of various types. Some of these are optional, which means they can have
68 no value given in encodings. One is defaulted, which means that if no values
69 is given in encodings then the default value is intended.
71 Those `[0]` things are called tags and are decidedly obsolete, along with all
72 "tag-length-value" (TLV) or "self-describing" encoding rules. Tags appear as
73 lexical tokens in ASN.1 only because a) in the early 80s TLV encodings were
74 thought fantastic, and b) automatic tagging wasn't invented and implemented
75 until it was too late. New ASN.1 modules should never need to have those tags
78 ASN.1 has a lot of competition, and may even be obsolete. Obsolete
79 technologies take decades to die out because of the need to interoperate with
80 the installed base. So even if ASN.1 is obsolete, we find ourselves needing to
81 implement a large subset of it in order to implement certain important network
84 Encoding rules? There are many:
86 - JSON Encoding Rules (JER) ([X.697](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.697))
88 Use JSON instead of some binary scheme like DER (see below).
90 - XML Encoding Rules (XER) ([X.693](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.693))
92 - Generic String Encoding Rules (GSER) ([RFC3641](https://tools.ietf.org/html/rfc3641))
94 - 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)
96 These are the dreaded tag-length-value encoding rules. They are redundant,
97 wasteful, and inefficient in spite of being non-textual (i.e., binary)!
99 The descriptor "tag-length-value" is due to all values being encoded as some
100 bytes for a "tag", then some bytes for the length of the encoded value, then
101 the encoded value itself. The body of a structured type (e.g.,
102 `Certificate`) is itself a concatenation of the TLV encodings of the fields
103 of that structured type, in order.
105 DER and CER are alternative canonical forms of BER.
107 - 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))
109 These are a lot like eXternal Data Representation
110 ([XDR](https://tools.ietf.org/html/rfc4506.html)), but with 1-octet
111 alignment instead of 4-octet alignment.
113 There is also a meta encoding rule system, the Encoding Control Notation (ECN)
114 ([X.692](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.692))
115 intended to be able to express all sorts of kinds of encodings.
117 Heimdal currently only supports DER for encoding, and DER and BER for decoding,
118 but soon may support JER as well, and can print values as JSON, though not
121 The syntax itself is specified by
122 [X.680](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.680),
124 [X.681](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.681),
125 [X.682](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.682),
127 [X.683](https://www.itu.int/rec/T-REC-X/recommendation.asp?lang=en&parent=T-REC-X.683),.
129 ## ASN.1 Support in Heimdal
131 Heimdal contains an implementation of:
136 - misc. Heimdal-specific protocols related to PKIX and Kerberos, such as:
138 - Online certification authority protocols
139 - Kerberos KDC replication protocols
140 - Kerberos administration protocols
142 PKIX and Kerberos both require ASN.1 and DER support.
144 For historical reasons many ASN.1-using projects have used hand-rolled codecs
145 that have proven difficult to implement, maintain, and extend, and, of course,
146 buggy. Heimdal has its own ASN.1 module compiler and library in order to avoid
147 the pitfalls of hand-rolled codecs, and to satisfy Heimdal's internal needs.
149 There are other ASN.1 compilers and libraries out there, of course, but it
150 would prove difficult to switch compilers as generally ASN.1 compilers lack
151 sufficient control over generated types and APIs for programming languages.
153 Heimdal's ASN.1 compiler supports a large subset of X.680, X.681, X.682, and
154 X.683, as well as a large subset of X.690, with an architecture that should
155 make it easy to add support for encoding rules other than X.690.
159 In recent times the following features have been added:
161 - Feature parity for the "template" backend, even superiority, as the codegen
162 backend does not yet support automatic open type decoding/encoding.
164 - IMPLICIT tagging support is finally complete.
166 - Automatic open type traversal, using a subset of X.681/X.682/X.683 for
167 expressing the requisite metadata.
175 - Generate comparators? (lib/hx509 has a half-baked Certificate comparator)
179 - Most of X.680 is supported.
181 - Most of X.690 is supported for decoding, with only DER supported for
184 - We have an `asn1_print` program that can decode DER from any exported types
185 from any ASN.1 modules committed in Heimdal:
188 $ ./asn1_print ek.crt Certificate |
189 jq '.tbsCertificate.extensions[3]._extnValue[]._values'
195 "_type": "TPMSpecification",
203 "_type": "TPMSecurityAssertions",
205 "fieldUpgradable": true,
206 "ekGenerationType": "ekgt-injected",
207 "ekGenerationLocation": "tpmManufacturer",
208 "ekCertificateGenerationLocation": "tpmManufacturer",
210 "_type": "CommonCriteriaMeasures",
212 "assurancelevel": "ealevel4",
213 "evaluationStatus": "evaluationCompleted",
215 "strengthOfFunction": null,
222 "_type": "FIPSLevel",
227 "iso9000Certified": false,
233 A complete dump of such a certificate:
236 $ ./asn1_print ek.crt Certificate | jq .
241 "_type": "Certificate",
243 "_type": "TBSCertificate",
244 "_save": "30820376A00302010202146A0597BA71D7E6D3AC0EDC9EDC95A15B998DE40A300D06092A864886F70D01010B05003055310B3009060355040613024348311E301C060355040A131553544D6963726F656C656374726F6E696373204E56312630240603550403131D53544D2054504D20454B20496E7465726D656469617465204341203035301E170D3138313231343030303030305A170D3238313231343030303030305A300030820122300D06092A864886F70D01010105000382010F003082010A0282010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E905B097012B5BDE50380C355B1A2A721BBC3D08DD21796CDB239FA95310651B1B56FD2CFE53C87352EBD996E33256160404CE9302A08066801E786A2F86E181F949966F492A85B58EAA4A6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E8F266BF1EA5EB271FDCF374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A294973FEDCCF0C340AFFD14B64F041165581ACA34147C1C75617047058F7ED7D603E032508094FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040FC1D2927C7657414490D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A18AFE59F9D6F149744E5F0D559B10203010001A38201A9308201A5301F0603551D230418301680141ADB994AB58BE57A0CC9B900E7851E1A43C0866030420603551D20043B303930370604551D2000302F302D06082B060105050702011621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F30590603551D110101FF044F304DA44B304931163014060567810502010C0B69643A353335343444323031173015060567810502020C0C53543333485450484148433031163014060567810502030C0B69643A303034393030303830670603551D090460305E301706056781050210310E300C0C03322E300201000202008A304306056781050212313A30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100300E0603551D0F0101FF040403020520300C0603551D130101FF0402300030100603551D250409300706056781050801304A06082B06010505070101043E303C303A06082B06010505073002862E687474703A2F2F7365637572652E676C6F62616C7369676E2E636F6D2F73746D74706D656B696E7430352E637274",
245 "version": "rfc3280_version_3",
246 "serialNumber": "6A0597BA71D7E6D3AC0EDC9EDC95A15B998DE40A",
248 "_type": "AlgorithmIdentifier",
250 "_type": "OBJECT IDENTIFIER",
251 "oid": "1.2.840.113549.1.1.11",
261 "name": "id-pkcs1-sha256WithRSAEncryption"
266 "_choice": "rdnSequence",
270 "_type": "AttributeTypeAndValue",
272 "_type": "OBJECT IDENTIFIER",
280 "name": "id-at-countryName"
283 "_choice": "printableString",
290 "_type": "AttributeTypeAndValue",
292 "_type": "OBJECT IDENTIFIER",
300 "name": "id-at-organizationName"
303 "_choice": "printableString",
304 "value": "STMicroelectronics NV"
310 "_type": "AttributeTypeAndValue",
312 "_type": "OBJECT IDENTIFIER",
320 "name": "id-at-commonName"
323 "_choice": "printableString",
324 "value": "STM TPM EK Intermediate CA 05"
333 "_choice": "utcTime",
334 "value": "2018-12-14T00:00:00Z"
337 "_choice": "utcTime",
338 "value": "2028-12-14T00:00:00Z"
342 "_choice": "rdnSequence",
345 "subjectPublicKeyInfo": {
346 "_type": "SubjectPublicKeyInfo",
348 "_type": "AlgorithmIdentifier",
350 "_type": "OBJECT IDENTIFIER",
351 "oid": "1.2.840.113549.1.1.1",
361 "name": "id-pkcs1-rsaEncryption"
365 "subjectPublicKey": "2160:3082010A0282010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E905B097012B5BDE50380C355B1A2A721BBC3D08DD21796CDB239FA95310651B1B56FD2CFE53C87352EBD996E33256160404CE9302A08066801E786A2F86E181F949966F492A85B58EAA4A6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E8F266BF1EA5EB271FDCF374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A294973FEDCCF0C340AFFD14B64F041165581ACA34147C1C75617047058F7ED7D603E032508094FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040FC1D2927C7657414490D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A18AFE59F9D6F149744E5F0D559B10203010001"
367 "issuerUniqueID": null,
368 "subjectUniqueID": null,
371 "_type": "Extension",
373 "_type": "OBJECT IDENTIFIER",
381 "name": "id-x509-ce-authorityKeyIdentifier"
384 "extnValue": "301680141ADB994AB58BE57A0CC9B900E7851E1A43C08660",
385 "_extnValue_choice": "ext-AuthorityKeyIdentifier",
387 "_type": "AuthorityKeyIdentifier",
388 "keyIdentifier": "1ADB994AB58BE57A0CC9B900E7851E1A43C08660",
389 "authorityCertIssuer": null,
390 "authorityCertSerialNumber": null
394 "_type": "Extension",
396 "_type": "OBJECT IDENTIFIER",
404 "name": "id-x509-ce-certificatePolicies"
407 "extnValue": "303930370604551D2000302F302D06082B060105050702011621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F",
408 "_extnValue_choice": "ext-CertificatePolicies",
411 "_type": "PolicyInformation",
412 "policyIdentifier": {
413 "_type": "OBJECT IDENTIFIER",
414 "oid": "2.5.29.32.0",
422 "name": "id-x509-ce-certificatePolicies-anyPolicy"
424 "policyQualifiers": [
426 "_type": "PolicyQualifierInfo",
427 "policyQualifierId": {
428 "_type": "OBJECT IDENTIFIER",
429 "oid": "1.3.6.1.5.5.7.2.1",
441 "name": "id-pkix-qt-cps"
443 "qualifier": "1621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F"
450 "_type": "Extension",
452 "_type": "OBJECT IDENTIFIER",
460 "name": "id-x509-ce-subjectAltName"
463 "extnValue": "304DA44B304931163014060567810502010C0B69643A353335343444323031173015060567810502020C0C53543333485450484148433031163014060567810502030C0B69643A3030343930303038",
464 "_extnValue_choice": "ext-SubjectAltName",
467 "_choice": "directoryName",
469 "_choice": "rdnSequence",
473 "_type": "AttributeTypeAndValue",
475 "_type": "OBJECT IDENTIFIER",
476 "oid": "2.23.133.2.1",
484 "name": "tcg-at-tpmManufacturer"
487 "_choice": "utf8String",
488 "value": "id:53544D20"
494 "_type": "AttributeTypeAndValue",
496 "_type": "OBJECT IDENTIFIER",
497 "oid": "2.23.133.2.2",
505 "name": "tcg-at-tpmModel"
508 "_choice": "utf8String",
509 "value": "ST33HTPHAHC0"
515 "_type": "AttributeTypeAndValue",
517 "_type": "OBJECT IDENTIFIER",
518 "oid": "2.23.133.2.3",
526 "name": "tcg-at-tpmVersion"
529 "_choice": "utf8String",
530 "value": "id:00490008"
540 "_type": "Extension",
542 "_type": "OBJECT IDENTIFIER",
550 "name": "id-x509-ce-subjectDirectoryAttributes"
553 "extnValue": "305E301706056781050210310E300C0C03322E300201000202008A304306056781050212313A30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100",
554 "_extnValue_choice": "ext-SubjectDirectoryAttributes",
557 "_type": "AttributeSet",
559 "_type": "OBJECT IDENTIFIER",
560 "oid": "2.23.133.2.16",
568 "name": "tcg-at-tpmSpecification"
571 "300C0C03322E300201000202008A"
573 "_values_choice": "at-TPMSpecification",
576 "_type": "TPMSpecification",
584 "_type": "AttributeSet",
586 "_type": "OBJECT IDENTIFIER",
587 "oid": "2.23.133.2.18",
595 "name": "tcg-at-tpmSecurityAssertions"
598 "30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100"
600 "_values_choice": "at-TPMSecurityAssertions",
603 "_type": "TPMSecurityAssertions",
605 "fieldUpgradable": true,
606 "ekGenerationType": "ekgt-injected",
607 "ekGenerationLocation": "tpmManufacturer",
608 "ekCertificateGenerationLocation": "tpmManufacturer",
610 "_type": "CommonCriteriaMeasures",
612 "assurancelevel": "ealevel4",
613 "evaluationStatus": "evaluationCompleted",
615 "strengthOfFunction": null,
622 "_type": "FIPSLevel",
627 "iso9000Certified": false,
635 "_type": "Extension",
637 "_type": "OBJECT IDENTIFIER",
645 "name": "id-x509-ce-keyUsage"
648 "extnValue": "03020520",
649 "_extnValue_choice": "ext-KeyUsage",
655 "_type": "Extension",
657 "_type": "OBJECT IDENTIFIER",
665 "name": "id-x509-ce-basicConstraints"
669 "_extnValue_choice": "ext-BasicConstraints",
671 "_type": "BasicConstraints",
673 "pathLenConstraint": null
677 "_type": "Extension",
679 "_type": "OBJECT IDENTIFIER",
687 "name": "id-x509-ce-extKeyUsage"
690 "extnValue": "300706056781050801",
691 "_extnValue_choice": "ext-ExtKeyUsage",
694 "_type": "OBJECT IDENTIFIER",
695 "oid": "2.23.133.8.1",
703 "name": "tcg-kp-EKCertificate"
708 "_type": "Extension",
710 "_type": "OBJECT IDENTIFIER",
711 "oid": "1.3.6.1.5.5.7.1.1",
723 "name": "id-pkix-pe-authorityInfoAccess"
726 "extnValue": "303C303A06082B06010505073002862E687474703A2F2F7365637572652E676C6F62616C7369676E2E636F6D2F73746D74706D656B696E7430352E637274",
727 "_extnValue_choice": "ext-AuthorityInfoAccess",
730 "_type": "AccessDescription",
732 "_type": "OBJECT IDENTIFIER",
733 "oid": "1.3.6.1.5.5.7.48.2",
745 "name": "id-pkix-ad-caIssuers"
748 "_choice": "uniformResourceIdentifier",
749 "value": "http://secure.globalsign.com/stmtpmekint05.crt"
756 "signatureAlgorithm": {
757 "_type": "AlgorithmIdentifier",
759 "_type": "OBJECT IDENTIFIER",
760 "oid": "1.2.840.113549.1.1.11",
770 "name": "id-pkcs1-sha256WithRSAEncryption"
774 "signatureValue": "2048:3D4C381E5B4F1BCBE09C63D52F1F04570CAEA142FD9CD942043B11F8E3BDCF50007AE16CF8869013041E92CDD3280BA4B51FBBD40582ED750219E261A695095674855AACEB520ADAFF9E7E908480A39CDCF900462D9171960FFE55D3AC49E8C981341BBD2EFBCC252A4C18A4F3B7C84CCE42CE70A208C84D2630A7ABFBE72D6271E75B9FF1C971D20EB3DBD763F1E04D834EAA692D2E4001BBF4730A3E3FDA9711AE386524D91C63BE0E516D00D5C6141FCCF6C539F3518E180049865BE16B69CAE1F8CB7FDC474B38F7EE56CBE7D8A89D9BA99B65D5265AEF32AA62426B10E6D75BB8677EC44F755BBC2806FD2B4E04BDF5D44259DBEAA42B6F563DF7AA7506"
778 (Notice that OID names look a bit weird. For reasons that may have been
779 lost to time and may no longer be relevant, these OIDs are defined with
780 slightly different names in the ASN.1 modules in Heimdal's source tree.
781 We'll fix this eventually.)
783 - Unconstrained integer types have a large integer representation in C that is
784 not terribly useful in common cases. Range constraints on integer types
785 cause the compiler to use `int32_t`, `int64_t`, `uint32_t`, and/or
788 - The Heimdal ASN.1 compiler currently handles a large subset of X.680, and
789 (in a branch) a small subset of X.681, X.682, and X.683, which manifests as
790 automatic handling of all open types contained in `SET`/`SEQUENCE` types
791 that are parameterized with information object sets. This allows all open
792 types in PKIX certificates, for example, to get decoded automatically no
793 matter how deeply nested. We use a TCG EK certificate that has eight
794 certificate extensions, including subject alternative names and subject
795 directory attributes where the attribute values are not string types, and
796 all of these things get decoded automatically.
798 - The template backend dedups templates to save space. This is an O(N^2) kind
799 of feature that we need to make optional, but it works. (When we implement
800 JER this will have the side-effect of printing the wrong type names in some
801 cases because two or more types have the same templates and get deduped.)
803 - There is an _experimental_ ASN.1 -> JSON feature in the compiler. It
804 currently dumps type and value definitions, but not class, or object set
805 definitions. Even for types, it is not complete, and the JSON schema used
806 is subject to change *WITHOUT NOTICE*.
808 Perhaps eventually we can re-write the compiler as a C-coded ASN.1 -> JSON
809 stage followed by a jq-coded code and template generator state, which would
810 make it much easier to extend the compiler.
816 - `asn1_print`'s JSON support is not X.697 (JER) compatible.
818 - Control over C types generated is very limited, mainly only for integer
821 - When using the template backend, `SET { .. }` types are currently not sorted
822 by tag as they should be, but if the module author sorts them by hand then
823 DER will be produced.
825 - `REAL` is not supported.
827 - `EmbeddedPDV` is not supported.
829 - `BMPString` is not supported.
831 - IA5String is not properly supported -- it's essentially treated as a
832 `UTF8String` with a different tag. This is true of all the string types.
834 - Only types can be imported at this time. Without some rototilling we likely
835 will not be able to import anything other than types, values, and object
838 - Only simple value syntax is supported. Constructed value syntax (i.e.,
839 values of `SET`, `SEQUENCE`, `SET OF`, and `SEQUENCE OF`), is not supported.
840 Values of `CHOICE` types are also not supported.
846 The various options for the Heimdal ASN.1 compiler are described in its manual
847 page, which is included below.
849 The `--option-file=FILE` option is particularly useful, as it allows additional
850 compiler options to be read from a file.
852 The `--preserve-binary=TYPE-NAME` option is critical for signature validation
853 as it causes the decoder to save the encoding of the given type so that
854 signature validation code can easily find the original encoding and thus avoid
855 having to re-encode or resort to other hacks. E.g., we use this for preserving
856 the original encoding of the `tbsCertificate` field of `Certificate`.
858 The `--sequence=TYPE-NAME` causes the compiler to generate additional utility
859 functions for adding or removing items from the named type when it is a
860 `SEQUENCE OF` or `SET OF` type.
862 See the manual page `asn1_compile.1`:
865 ASN1_COMPILE(1) HEIMDAL General Commands Manual ASN1_COMPILE(1)
868 asn1_compile — compile ASN.1 modules
871 asn1_compile [--template] [--prefix-enum] [--enum-prefix=PREFIX]
872 [--encode-rfc1510-bit-string] [--decode-dce-ber]
873 [--support-ber] [--preserve-binary=TYPE-NAME]
874 [--sequence=TYPE-NAME] [--one-code-file] [--gen-name=NAME]
875 [--decorate=TYPE-NAME:FIELD-TYPE:field-name[?]]
876 [--option-file=FILE] [--original-order] [--no-parse-units]
877 [--type-file=C-HEADER-FILE] [--version] [--help]
881 asn1_compile Compiles an ASN.1 module into C source code and header
887 Use the “template” backend instead of the “codegen” backend
888 (which is the default backend). The template backend generates
889 “templates” which are akin to bytecode, and which are interpreted
890 at run-time. The codegen backend generates C code for all func-
891 tions directly, with no template interpretation. The template
892 backend scales better than the codegen backend because as we add
893 support for more encoding rules the templates stay mostly the
894 same, thus scaling linearly with size of module. Whereas the
895 codegen backend scales linear with the product of module size and
896 number of encoding rules supported. More importantly, currently
897 only the template backend supports automatic decoding of open
898 types via X.681/X.682/X.683 annotations.
901 This option should be removed because ENUMERATED types should
902 always have their labels prefixed.
905 This option should be removed because ENUMERATED types should
906 always have their labels prefixed.
908 --encode-rfc1510-bit-string
909 Use RFC1510, non-standard handling of “BIT STRING” types.
914 --preserve-binary=TYPE-NAME
915 Generate ‘_save’ fields in structs to preserve the original
916 encoding of some sub-value. This is useful for cryptographic
917 applications to avoid having to re-encode values to check signa-
921 Generate add/remove functions for ‘SET OF’ and ‘SEQUENCE OF’
924 --decorate=TYPE-NAME:FIELD-TYPE:field-name[?]
925 Add to the TYPE-NAME SET or SEQUENCE type a field of the given
926 FIELD-TYPE and field-name, but do not encode or decode this
927 field. If the field-name ends in a question mark, then treat the
928 field as OPTIONAL for the purposes of copy/free function stubs.
929 This is useful for adding fields to existing types that can be
930 used for internal bookkeeping but which do not affect interoper-
931 ability because they are not encoded.
934 Generate a single source code file. Otherwise a separate code
935 file will be generated for every type.
938 Use NAME to form the names of the files generated.
941 Take additional command-line options from FILE.
944 Attempt to preserve the original order of type definition in the
945 ASN.1 module. By default the compiler generates types in a topo-
949 Do not generate to-int / from-int functions for enumeration
952 --type-file=C-HEADER-FILE
953 Generate an include of the named header file that might be needed
954 for common type defintions.
960 HEIMDAL February 22, 2021 HEIMDAL
964 ## APIs Generated by the Compiler
966 Every named type in an ASN.1 module gets a corresponding type in C.
967 Em-dashes in symbols become underscores.
969 Every named type in an ASN.1 module also gets several functions generated
972 - `int decode_TypeName(const unsigned char *, size_t, TypeName *, size_t *);`
974 Decodes a value of `TypeName` in the given byte array of the given size,
975 into the given `TypeName` object, and outputs the number of bytes parsed.
977 Returns 0 on success, or an error that can be formatted as a string using
978 the `com_err` library.
980 - `int encode_TypeName(unsigned char *, size_t, const TypeName *, size_t *);`
982 Encodes the given object of `TypeName` type into the given byte array of the
983 given size, outputting the number of bytes used.
985 NOTE WELL: the `unsigned char *` pointer must point to the _last_ byte of
988 Returns 0 on success, or an error that can be formatted as a string using
989 the `com_err` library, including system errors such as `ENOMEM`.
991 - `int length_TypeName(const TypeName *);`
993 Returns the number of bytes needed to encode the given object.
995 - `void free_TypeName(TypeName *);`
997 Releases the memory associated with the content of the given object, but
998 note that the object itself is _not_ released.
1000 - `int copy_TypeName(const TypeName *, TypeName *);`
1002 Copies the content of the given `const` object to the destination,
1005 Returns 0 on success, or an error that can be formatted as a string using
1006 the `com_err` library, including system errors such as `ENOMEM`.
1008 - `char *print_TypeName(const TypeName *, int);`
1010 Returns a string (JSON) representation of the given object. The `int`
1011 argument is a bitset of flags:
1013 - `ASN1_PRINT_INDENT`
1015 Indent the JSON. If not given the the JSON will have no interstitial
1016 whitespace, including newlines.
1018 You will want to review the data structures generated. They look like:
1021 typedef struct TBSCertificate TBSCertificate;
1022 typedef struct AlgorithmIdentifier AlgorithmIdentifier;
1023 typedef struct ... ...;
1026 Certificate ::= SEQUENCE {
1027 tbsCertificate TBSCertificate,
1028 signatureAlgorithm AlgorithmIdentifier,
1029 signatureValue BIT STRING {
1034 typedef struct Certificate {
1035 TBSCertificate tbsCertificate;
1036 AlgorithmIdentifier signatureAlgorithm;
1037 heim_bit_string signatureValue;
1041 TBSCertificate ::= SEQUENCE {
1042 version [0] Version OPTIONAL,
1043 serialNumber CertificateSerialNumber,
1044 signature AlgorithmIdentifier,
1048 subjectPublicKeyInfo SubjectPublicKeyInfo,
1049 issuerUniqueID [1] IMPLICIT BIT STRING {
1051 subjectUniqueID [2] IMPLICIT BIT STRING {
1053 extensions [3] Extensions OPTIONAL,
1057 typedef struct TBSCertificate {
1058 heim_octet_string _save;
1060 CertificateSerialNumber serialNumber;
1061 AlgorithmIdentifier signature;
1065 SubjectPublicKeyInfo subjectPublicKeyInfo;
1066 heim_bit_string *issuerUniqueID;
1067 heim_bit_string *subjectUniqueID;
1068 Extensions *extensions;
1072 Note how trivial the mapping onto C is.
1074 `OPTIONAL` fields become pointer fields, with `NULL` indicating
1075 absence and non-NULL indicating presence.
1082 ASN1_PRINT(1) BSD General Commands Manual ASN1_PRINT(1)
1085 asn1_print — dump ASN.1 DER encoded values
1088 asn1_print [-i | --no-indent] [-I | --inner] [-l | --list-types]
1089 [-A | --try-all-types] [-S | --raw-sequence] [-n | --no-print]
1090 [-q | --quiet] [--test-encode] [--test-copy]
1091 [-l -v | --version] [-l -h | --help] [FILE [TypeName...]]
1094 asn1_print Dumps ASN.1 DER-encoded values. If one or more TypeName argu-
1095 ments are given, then asn1_print will print the value in a JSON-like for-
1096 mat using its knowledge of the ASN.1 modules defining those types, stop-
1097 ping at the first type for which it can successfully decode the value.
1098 If TypeNames are given, they must be the names of ASN.1 types exported by
1099 an ASN.1 modules that are compiled into asn1_print. Use the
1100 --try-all-types option to attempt decoding as all ASN.1 types known to
1101 asn1_print. If neither any TypeName nor --try-all-types are given, then
1102 the value will be parsed and displayed using just the self-describing
1111 Try to parse inner structures of OCTET STRING and constructed
1115 List all types known to asn1_print.
1118 Attempt to decode the value as any of all types known to
1122 If a value parses as a given TypeName but any bytes are left
1123 over, try to parse those separately as well until all bytes are
1124 consumed or an error occurs.
1127 For the case where -A or --try-all-types or where a TypeName is
1128 given, do not output a JSON representation of the value, just
1129 attempt to decode it. This is useful for fuzzing.
1132 Similar to -n, --no-print but JSON output will be formatted, just
1133 not output. As with -n, --no-print, this option requires -A -/
1134 --try-all-types or that a TypeName be given. This is useful for
1138 Check that encoding produces the same value as decoding. Useful
1142 Test copy functions. Useful for fuzzing.
1148 HEIMDAL February 22, 2021 HEIMDAL
1155 - `lib/asn1/main.c` for the `main()` function of the compiler
1156 - `lib/asn1/asn1parse.y` for the grammar and most of the parsing into an AST
1157 - `lib/asn1/symbol.h` for the types making up the AST
1158 - `lib/asn1/{hash,symbol}.c` for compiler AST supporting functionality
1159 - `lib/asn1/gen.c` for the C header file generator
1160 - `lib/asn1/gen_template.c` for the template generator
1161 - `lib/asn1/gen_{decode,encode,length,copy,free}.c` for the C code generator
1162 - `lib/asn1/gen_{glue,seq}.c` for misc code generator
1163 - `lib/asn1/template.c` for the template interpreter
1164 - `lib/asn1/der*.c` for primitive type primitives
1165 - `lib/asn1/extra.c` for primitives related to `ANY`
1171 - Add JER support so we can convert between JER and DER?
1179 - Perhaps third parties will contribute more control over generate types?
1183 - Generate and output a JSON representation of the compiled ASN.1 module.
1185 - Code codegen/templategen backends in jq or Haskell or whatever.
1187 - Code template interpreters in some host language.
1189 - Eventually rewrite the compiler itself in Rust or whatever.