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