1 # Syntax for Walking Paths
3 <img alt="Quick DER logo" src="quick-der-logo.png" style="float: right;"/>
5 This specification describes how to make `der_walk()` traverse the path in DER
6 binaries that you intend it to take.
8 ## Declaring and Using a Walking Path
10 The walk path is described as a sequence of values that ends in `DER_WALK_END`:
12 #include <quick-der/api.h>
14 derwalk path_demo [] = {
19 which is then used to move a `dercursor crs` with
22 prsok = der_walk (&crs, path_demo);
24 The output is -1 for hard errors or 0 for success. If it fails to parse the path
25 at some point, the return value is a positive integer, indicating how much of
26 `path_demo` was left unprocessed before `DER_WALK_END`.
28 The `crs` value is updated by this call to point to the end of the `path_demo`
31 ## Entering and Skipping
33 There are two basic actions that `der_walk()` takes at each position along the
34 path; it may either enter or skip a DER element. This is defined in the path
35 with `DER_WALK_ENTER` and `DER_WALK_SKIP`, respectively, as in
37 derwalk path_demo [] = {
46 The tag found in the DER code must be matched, or otherwise a validation error
47 is raised (and a positive integer returned from `der_walk()` to indicate where
48 the problem was encountered).
50 Tags are quite simply matched by mentioning them after the enter-or-skip choice,
53 derwalk path_demo [] = {
54 DER_WALK_ENTER | DER_TAG_SEQUENCE,
55 DER_WALK_SKIP | DER_TAG_CONTEXT (0),
56 DER_WALK_ENTER | DER_TAG_OCTETSTRING,
60 The two statements shown could be used to get to the `OCTET STRING` in
62 demoStruct ::= SEQUENCE {
63 demoCounter [0] INTEGER,
67 This relates to the DER sequence for this structure; let's say the `INTEGER`
68 value is `7` and the `OCTET STRING` is `Quick DER`, then the encoding would be
70 30 16 -- tag SEQUENCE, length 16
71 a0 03 -- tag a0 for [0], length 3
72 02 01 07 -- tag INTEGER, length 1, value 7
73 04 09 51 75 69 63 6b 20 44 45 52 -- tag 4, length 9, "Quick DER"
75 From the start of this structure, we need to:
77 * Enter the `SEQUENCE`
78 * Skip the `[0]` rather then entering it
79 * Enter the `OCTET STRING`
82 This is precisely what the path walk describes. Although *some* understanding
83 of the mapping to DER is helpful, you can generally derive the path to walk
84 directly from the ASN.1 structure.
86 When done, `der_walk()` returns the pointer to the string "Quick DER" with a
87 length of 9, and you can continue to process it:
89 printf ("Found \"%.*s\"\n", crs.derlen, crs.derptr);
92 ## Optionals, Choices and the ANYs
94 There is a possibility in ASN.1 to specify an element as `OPTIONAL`, perhaps
95 even having a `DEFAULT` value (which is ignored by Quick DER). To mark an
96 entry as optional, precede it with `DER_WALK_OPTIONAL`.
98 Choices are barely interesting during a walk; in fact, the only purpose they
99 serve is as something to skip over (since we obviously have no idea how to get
100 into a structure if we don't know yet what that structure is like). So,
101 specify `DER_WALK_SKIP | DER_WALK_CHOICE` to skip an arbitrary element;
102 there will be no validation of that particular tag.
104 The forms `ANY` and `ANY DEFINED BY` receive the same treatment as `CHOICE`,
105 but can be declare with a separate symbol `DER_WALK_ANY`.
110 Also have a look at the individual steps that can be taken with
111 `der_enter()` and `der_skip()`. And take a look at
112 `der_iterate_first()` and `der_iterate_next()` if you need iterators.
114 Where `der_walk()` is ideally suited to retrieve a single bit of information
115 from the repository, the `der_unpack()` routine can unpack a complete DER
116 structure (only deferring dynamically-sized parts to later calls). The latter
117 also has a reverse routine `der_pack()`. You will want to read the
118 [PACK SYNTAX](PACK-SYNTAX.MD) for the walking paths used with those routines.