diff --git a/AGENTS.md b/AGENTS.md index dbe93e6e1c..b4181e54a3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -150,6 +150,7 @@ set the macros in `user_settings.h` or your build flags. | `wolfssl/internal.h` | Internal -- do not use from applications | | `src/` | TLS implementation (ssl.c, tls13.c, dtls13.c, internal.c) | | `wolfcrypt/src/` | Crypto implementations | +| `wolfcrypt/src/ASN_TEMPLATE.md` | How ASN.1 structures are described and parsed/encoded -- read before touching `asn.c` | | `wolfcrypt/src/port/` | ~30 hardware/OS crypto ports: arm, intel, Espressif, Renesas, st, nxp, atmel, silabs, psa, kcapi, caam, liboqs, ... | | `examples/client/`, `examples/server/` | Full-featured reference apps; run with `-h` for all flags | | `examples/tls13/` | Minimal TLS 1.3 samples, incl. in-memory I/O (no sockets) | diff --git a/wolfcrypt/src/ASN_TEMPLATE.md b/wolfcrypt/src/ASN_TEMPLATE.md index 5fa3fce320..a56ddf514a 100644 --- a/wolfcrypt/src/ASN_TEMPLATE.md +++ b/wolfcrypt/src/ASN_TEMPLATE.md @@ -1,5 +1,65 @@ # Writing an ASN Template +wolfSSL describes each ASN.1 structure once, as a static table of `ASNItem`, +and uses that one table for both directions: + +| Direction | Entry points | +|---|---| +| Decode | `GetASN_Items()` | +| Encode | `SizeASN_Items()` then `SetASN_Items()` | + +The types and helpers are declared in `wolfssl/wolfcrypt/asn.h` and implemented +in `wolfcrypt/src/asn.c`. All of it is compiled only when +`WOLFSSL_ASN_TEMPLATE` is defined, which is the default (see +`wolfssl/wolfcrypt/settings.h`); the alternative implementation lives in +`wolfcrypt/src/asn_orig.c` and is selected with `WOLFSSL_ASN_ORIGINAL` +(`./configure --enable-asn=original`). A change to a template usually needs a +matching change to the original implementation, and both need building. + +Only definite-length encodings are supported. A template describes DER, and +the BER it will read is BER with definite lengths - an indefinite length +(a length byte of 0x80, terminated by an end-of-contents pair) cannot be +described with a template and is not handled by the parser. Convert such an +encoding with `wc_BerToDer()` first and parse the result, as `pkcs7.c` and +`pkcs12.c` do. + +Describing a structure once has a few consequences worth knowing before +writing one. The encoder and the decoder read the same table, so they cannot +drift apart the way two hand-written functions can - which is what the +original implementation has for each structure. A template is `static const`, +so it holds no state, lives in read-only memory rather than RAM, and can be +used from any number of threads at once. All the per-call state is in the +separate `ASNGetData` or `ASNSetData` array, which is why that array is +declared through macros that can put it on the stack or the heap depending on +the build. + +## Adding a template + +The rest of this file is reference material; this is the order to do things in. + +1. Write the table - one `ASNItem` per ASN.1 item, in encoding order, with + `depth` following the nesting. See "Template" and "Examples of ASN.1 items". +2. Write the index enum beside it, ending with + `WOLF_ENUM_DUMMY_LAST_ELEMENT`. Repeat every `#if` from the table around the + matching enumerator. +3. Add the `