asn1: Add a GitHub Markdown manual (more)
This commit is contained in:
@@ -577,17 +577,22 @@ values mean "absent", while non-`NULL` values mean "present").
|
|||||||
|
|
||||||
Tags are of no consequence to the C types generated.
|
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:
|
Thus `Certificate` becomes:
|
||||||
|
|
||||||
```C
|
```C
|
||||||
typedef struct TBSCertificate TBSCertificate;
|
|
||||||
|
|
||||||
typedef struct Certificate {
|
|
||||||
TBSCertificate tbsCertificate;
|
|
||||||
AlgorithmIdentifier signatureAlgorithm;
|
|
||||||
heim_bit_string signatureValue;
|
|
||||||
} Certificate;
|
|
||||||
|
|
||||||
typedef struct TBSCertificate {
|
typedef struct TBSCertificate {
|
||||||
heim_octet_string _save; /* see below! */
|
heim_octet_string _save; /* see below! */
|
||||||
Version *version;
|
Version *version;
|
||||||
@@ -601,6 +606,12 @@ typedef struct TBSCertificate {
|
|||||||
heim_bit_string *subjectUniqueID;
|
heim_bit_string *subjectUniqueID;
|
||||||
Extensions *extensions;
|
Extensions *extensions;
|
||||||
} TBSCertificate;
|
} 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
|
The `_save` field in `TBSCertificate` is generated when the compiler is invoked
|
||||||
@@ -644,6 +655,75 @@ code-generators do, of course, so it's not surprising. But you can see that
|
|||||||
- in C we use `typedef`s to make the type names usable without having to add
|
- in C we use `typedef`s to make the type names usable without having to add
|
||||||
`struct`
|
`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
|
## Generated APIs For Any Given Type T
|
||||||
|
|
||||||
The C functions generated for ASN.1 types are all of the same form, for any
|
The C functions generated for ASN.1 types are all of the same form, for any
|
||||||
@@ -674,16 +754,20 @@ written.
|
|||||||
> last byte in the buffer into which the encoder will encode the value. This
|
> 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.
|
> 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
|
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.
|
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
|
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
|
memory resources will be released. Note that the C object _itself_ is not
|
||||||
freed, only its _content_.
|
freed, only its _content_.
|
||||||
|
|
||||||
The `print_T()` functions encode the value of a C object of type `T` in JSON
|
See [sample usage](#Using-the-Generated-APIs).
|
||||||
(though not in JER-compliant JSON). A sample printing of a complex PKIX
|
|
||||||
`Certificate` can be seen in [README.md#features](README.md#features).
|
|
||||||
|
|
||||||
These functions are all recursive.
|
These functions are all recursive.
|
||||||
|
|
||||||
@@ -1179,18 +1263,18 @@ HEIMDAL February 22, 2021 HEIMDAL
|
|||||||
|
|
||||||
The Heimdal ASN.1 compiler is focused on PKIX and Kerberos, and is almost
|
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
|
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 implement
|
X.681/X.682/X.683 elements that would allow the compiler to understand
|
||||||
`Certificate ::= SIGNED{TBSCertificate}`, particularly the ability to
|
`Certificate ::= SIGNED{TBSCertificate}`, particularly the ability to
|
||||||
automatically validate cryptographic algorithm parameters. However, this is
|
automatically validate cryptographic algorithm parameters. However, this is
|
||||||
not that important.
|
not that important.
|
||||||
|
|
||||||
Another feature that might be nice is the ability of callers to specify smaller
|
Another feature that might be nice is the ability of callers to specify smaller
|
||||||
information object sets when decoding values of types like `Certificate`,
|
information object sets when decoding values of types like `Certificate`,
|
||||||
mainly to avoid decoding types in typed holes that are not of interest to the
|
mainly to avoid spending CPU cycles and memory allocations on decoding types in
|
||||||
application.
|
typed holes that are not of interest to the application.
|
||||||
|
|
||||||
For testing, a JSON reader to go with the JSON printer might be nice, and
|
For testing purposes, a JSON reader to go with the JSON printer might be nice,
|
||||||
anyways, would make for a generally useful tool.
|
and anyways, would make for a generally useful tool.
|
||||||
|
|
||||||
Another feature that would be nice would to automatically generate SQL and LDAP
|
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
|
code for HDB based on `lib/hdb/hdb.asn1` (with certain usage conventions and/or
|
||||||
|
Reference in New Issue
Block a user