diff --git a/lib/asn1/README.md b/lib/asn1/README.md index f5dc59885..640da8be4 100644 --- a/lib/asn1/README.md +++ b/lib/asn1/README.md @@ -13,9 +13,10 @@ annotations](/lib/asn1/README-X681.md). 4. [Features](#Features) 5. [Limitations](#Limitations) 6. [Compiler Usage](#Compiler-usage) - 7. [asn1_print Usage](#asn1_print-usage) - 8. [Implementation](#implementation) - 9. [Moving From C](#moving-from-c) + 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 @@ -828,7 +829,7 @@ In recent times the following features have been added: ## Compiler Usage -See the manual page `asn1_compile.1`: +First, see the manual page `asn1_compile.1`: ``` ASN1_COMPILE(1) HEIMDAL General Commands Manual ASN1_COMPILE(1) @@ -920,6 +921,121 @@ 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 ``` @@ -962,6 +1078,20 @@ 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