Let der_iterate_first() return success
[quick-der] / USING.MD
1 # Quick DER parsing support
2
3 <img alt="Quick DER logo" src="quick-der-logo.png" style="float: right;"/>
4
5 > *Quick DER parsing aims to get you started with the parsing of DER (and most
6 > BER) encoded ASN.1 data really quickly.  It also aims to makes quick parsers,
7 > by using shared data structures whenever possible.*
8
9 **Note: This is a preview of features to come; for now, it is no promise, but merely a rough sketch of what is to come.**
10
11 ## Outline of using this library
12
13 Working with the quick DER library is really quick to learn.
14
15 ### Preparing your build environment
16
17 The first thing you do, is parse an ASN.1 specification that you may have gotten
18 from any source -- for example, from an RFC.  You map it to a header file and a
19 parser specification file:
20
21     qder_from_asn1 myspec.asn1 myderparser.c myderparser.h
22
23 Your source code dealing with DER should read the entire block, and pass it to
24 the DER parser.  Initially, it would include:
25
26     #include <der/qparse.h>
27     #include "myderparser.h"
28
29 and builing should include:
30
31     gcc -o myparser.o myparser.c
32     gcc ... myderparser.o -lqder
33
34 You may be lucky, and find your favourite spec precompiled.  In that case, you
35 can limit yourself to things like:
36
37     #define RFC5280_PREFIX pkix_
38     #include <der/qparse.h>
39     #include <der/rfc5280.h>
40
41 and link with simply:
42
43     gcc ... -lqder
44
45
46 ### Parsing DER structures
47
48 Before you get to parse DER-encoded structures that match the ASN.1 syntax,
49 you should read the entire data into memory.  The parser output will not
50 clone bits and pieces of data, but instead point into it with cursors; these
51 are little structures with a pointer and a length.  Note that this means that
52 strings are not NUL-terminated; printing them may be different than what you
53 are accustomed to:
54
55     printf ("%s\n", derelem->ptr);                  // Unbounded string
56     printf ("%.*s\n", derelem->len, derelem->ptr);  // Perfect printing
57
58 Now, to invoke the parser, you setup a cursor describing the entire content,
59
60    dercursor_t thelot;
61    thelot.derptr = ...pointer-to-data...;
62    thelot.derlen = ...length-of-data...;
63
64 then you invoke the parser, providing it with storage space and the
65 precompiled structure to follow while parsing:
66
67    struct pkix_Certificate crt;
68    int prsok = der_unpack (&thelot, asn1_pkix_Certificate, &crt, 1);
69
70 This will parse the DER-encoded data in `thelot` and store the various fields
71 in `crt`, so it becomes available as individual cursor structures such as
72 `crt.tbsCertificate.validity.notAfter`.  This follows the structure of the
73 ASN.1 syntax, and uses field names defined in it, to gradually move into
74 the structure.  The header file defines those names as part of the
75 `asn1_pkix_Certificate`.
76
77 Something else that can now be done, is switch behaviour based on the the
78 various fields that contain an `OBJECT IDENTIFIER` for that purposes.  These
79 can usually be treated as binary settings to be compared as binaries.  The
80 `dercmp()` utility does this by looking at the length as well as binary
81 contents of such fields, as in
82
83     if (dercmp (&crt.signatureAlgorith.algorithm, RSA_WITH_SHA1) == 0) {
84        ...the OIDs matched...
85     } else ...other cases...
86
87
88 ## Iterating over repeating structures
89
90 Many structures in ASN.1 are variable in the sizes of primitive data types, but
91 have a fixed composition structure.  And `OPTIONAL` parts can be parsed and their
92 respective structure fields set to NULL when they are absent.  This also happens
93 to values setup with a `DEFAULT` value in ASN.1 (note that their default value
94 is not filled in by the parser).
95
96 But some structures are not parsed immediately, because they might have a
97 repeated structure, and thus won't fit into a structure; not if the assumption
98 is that dynamic allocation should not be done by the parser.  For such
99 repeating structure, there are two options, namely iterating over their
100 contents or allocating memory and having them filled by the parser.
101
102 To iterate over a repeated structure, simply use the two routines setup for
103 that in quick DER, as in:
104
105     if (der_iterate_first (&crt.tbsCertificate.extensions.packed, &iter)) do {
106        ...treat extension pointed to by iter...
107     } while (der_iterate_next (&crt.tbsCertificate.extensions.packed, &iter));
108
109 This requires no dynamic allocation, and simply handles each of the extensions
110 in a certificate one by one.
111
112 ## Allocating space for a repeating structure
113
114 The structures that repeat are limited to the ASN.1 constructs
115 `SEQUENCE OF` and `SET OF`.  When these occur, the parser will not unfold
116 the contained structure, but simply store the whole structure.  We will
117 refer to that as "packed" representation, meaning the binary DER format.
118
119 It is possible to replace packed notation by unpacked, by assigning to it
120 an array of suitable size to contain the required number of elements,
121 and then unfold the repeated structure into it:
122
123     size_t count = der_countelements (&crt.tbsCertificate.extensions.packed);
124     pkix_Extensions *exts = calloc (count, sizeof (pkcix_Extensions));
125     if (exts === NULL) {
126        ...handle error...
127     }
128     prsok = der_unpack (&crt.tbsCertificate.extensions.packed, asn1_pkix_Extension, exts, count);
129
130 This will unpack `count` times the structure described by `asn1_pkix_Extension` and place the output in `count` structures in the array `exts`; note that the earlier
131 call the `der_unpack` had a parameter `1` in the position of `count`.
132
133 When successful, the `der_unpack()` routine replaces the `extensions.packed`
134 structure, which is a plain `dercursor_t`, with an unpacked structure
135 `unpacked` which has elements `derray` pointing to an array of cursors and
136 an element `dercnt` with the number of cursors in that array.  When this
137 is setup, the `.packed` version of the data is destroyed; the `.packed` and
138 `.unpacked` versions are in fact labels of a union.
139
140 Note that structures such as `crt` may hold a lot of useful naming, but they
141 are just a cleverly constructed overlay form for an array of `dercursor_t` fields,
142 which is exactly how `der_unpack` treats them.  The ASN.1 parsing instructions
143 are matched to the structures so that no data will be sticking out of these
144 array-like structures.
145
146 ## Composing DER output
147
148 The composition of DER output uses the same ASN.1 structural descriptions as
149 the unpacking process.  It is possible to use `.packed` structures, but once
150 they are unpacked it becomes necessary to prepare repeating structures for
151 repackaging.  This uses the `der_prepack()` function:
152
153     int prsok = der_prepack (TODO);
154
155 This sets up a third flavour of the repeated structure, namely `.prepacked`.
156 In this form, the `derlen` value has been set to the eventual length of
157 the to-be-formed DER structure, but the `derray` value still points to the
158 array of `dercursor_t` holding the to-be-filled data.  This `derlen` field
159 can subsequently be used during the future packing process.
160
161 TODO: How to distinguish packed, unpacked and prepacked lengths?  Tag or size bits?
162