• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_DER_PARSER_H_
6 #define NET_DER_PARSER_H_
7 
8 #include <stdint.h>
9 
10 #include "net/base/net_export.h"
11 #include "net/der/input.h"
12 #include "net/der/tag.h"
13 #include "third_party/abseil-cpp/absl/types/optional.h"
14 #include "third_party/boringssl/src/include/openssl/bytestring.h"
15 
16 namespace net::der {
17 
18 class BitString;
19 struct GeneralizedTime;
20 
21 // Parses a DER-encoded ASN.1 structure. DER (distinguished encoding rules)
22 // encodes each data value with a tag, length, and value (TLV). The tag
23 // indicates the type of the ASN.1 value. Depending on the type of the value,
24 // it could contain arbitrary bytes, so the length of the value is encoded
25 // after the tag and before the value to indicate how many bytes of value
26 // follow. DER also defines how the values are encoded for particular types.
27 //
28 // This Parser places a few restrictions on the DER encoding it can parse. The
29 // largest restriction is that it only supports tags which have a tag number
30 // no greater than 30 - these are the tags that fit in a single octet. The
31 // second restriction is that the maximum length for a value that can be parsed
32 // is 4GB. Both of these restrictions should be fine for any reasonable input.
33 //
34 // The Parser class is mainly focused on parsing the TLV structure of DER
35 // encoding, and does not directly handle parsing primitive values (other
36 // functions in the net::der namespace are provided for this.) When a Parser
37 // is created, it is passed in a reference to the encoded data. Because the
38 // encoded data is not owned by the Parser, the data cannot change during the
39 // lifespan of the Parser. The Parser functions by keeping a pointer to the
40 // current TLV which starts at the beginning of the input and advancing through
41 // the input as each TLV is read. As such, a Parser instance is thread-unsafe.
42 //
43 // Most methods for using the Parser write the current tag and/or value to
44 // the output parameters provided and then advance the input to the next TLV.
45 // None of the methods explicitly expose the length because it is part of the
46 // value. All methods return a boolean indicating whether there was a parsing
47 // error with the current TLV.
48 //
49 // Some methods are provided in the Parser class as convenience to both read
50 // the current TLV from the input and also parse the DER encoded value,
51 // converting it to a corresponding C++ type. These methods simply combine
52 // ReadTag() with the appropriate ParseType() free function.
53 //
54 // The design of DER encoding allows for nested data structures with
55 // constructed values, where the value is a series of TLVs. The Parser class
56 // is not designed to traverse through a nested encoding from a single object,
57 // but it does facilitate parsing nested data structures through the
58 // convenience methods ReadSequence() and the more general ReadConstructed(),
59 // which provide the user with another Parser object to traverse the next
60 // level of TLVs.
61 //
62 // For a brief example of how to use the Parser, suppose we have the following
63 // ASN.1 type definition:
64 //
65 //   Foo ::= SEQUENCE {
66 //     bar OCTET STRING OPTIONAL,
67 //     quux OCTET STRING }
68 //
69 // If we have a DER-encoded Foo in an Input |encoded_value|, the
70 // following code shows an example of how to parse the quux field from the
71 // encoded data.
72 //
73 //   bool ReadQuux(const Input& encoded_value, Input* quux_out) {
74 //     Parser parser(encoded_value);
75 //     Parser foo_parser;
76 //     if (!parser.ReadSequence(&foo_parser))
77 //       return false;
78 //     if (!foo_parser->SkipOptionalTag(kOctetString))
79 //       return false;
80 //     if (!foo_parser->ReadTag(kOctetString, quux_out))
81 //       return false;
82 //     return true;
83 //   }
84 class NET_EXPORT Parser {
85  public:
86   // Default constructor; equivalent to calling Parser(Input()). This only
87   // exists so that a Parser can be stack allocated and passed in to
88   // ReadConstructed() and similar methods.
89   Parser();
90 
91   // Creates a parser to parse over the data represented by input. This class
92   // assumes that the underlying data will not change over the lifetime of
93   // the Parser object.
94   explicit Parser(const Input& input);
95 
96   Parser(const Parser&) = default;
97   Parser& operator=(const Parser&) = default;
98 
99   // Returns whether there is any more data left in the input to parse. This
100   // does not guarantee that the data is parseable.
101   bool HasMore();
102 
103   // Reads the current TLV from the input and advances. If the tag or length
104   // encoding for the current value is invalid, this method returns false and
105   // does not advance the input. Otherwise, it returns true, putting the
106   // read tag in |tag| and the value in |out|.
107   [[nodiscard]] bool ReadTagAndValue(Tag* tag, Input* out);
108 
109   // Reads the current TLV from the input and advances. Unlike ReadTagAndValue
110   // where only the value is put in |out|, this puts the raw bytes from the
111   // tag, length, and value in |out|.
112   [[nodiscard]] bool ReadRawTLV(Input* out);
113 
114   // Basic methods for reading or skipping the current TLV, with an
115   // expectation of what the current tag should be. It should be possible
116   // to parse any structure with these 4 methods; convenience methods are also
117   // provided to make some cases easier.
118 
119   // If the current tag in the input is |tag|, it puts the corresponding value
120   // in |out| and advances the input to the next TLV. If the current tag is
121   // something else, then |out| is set to nullopt and the input is not
122   // advanced. Like ReadTagAndValue, it returns false if the encoding is
123   // invalid and does not advance the input.
124   [[nodiscard]] bool ReadOptionalTag(Tag tag, absl::optional<Input>* out);
125 
126   // If the current tag in the input is |tag|, it puts the corresponding value
127   // in |out|, sets |was_present| to true, and advances the input to the next
128   // TLV. If the current tag is something else, then |was_present| is set to
129   // false and the input is not advanced. Like ReadTagAndValue, it returns
130   // false if the encoding is invalid and does not advance the input.
131   // DEPRECATED: use the absl::optional version above in new code.
132   // TODO(mattm): convert the existing callers and remove this override.
133   [[nodiscard]] bool ReadOptionalTag(Tag tag, Input* out, bool* was_present);
134 
135   // Like ReadOptionalTag, but the value is discarded.
136   [[nodiscard]] bool SkipOptionalTag(Tag tag, bool* was_present);
137 
138   // If the current tag matches |tag|, it puts the current value in |out|,
139   // advances the input, and returns true. Otherwise, it returns false.
140   [[nodiscard]] bool ReadTag(Tag tag, Input* out);
141 
142   // Advances the input and returns true if the current tag matches |tag|;
143   // otherwise it returns false.
144   [[nodiscard]] bool SkipTag(Tag tag);
145 
146   // Convenience methods to combine parsing the TLV with parsing the DER
147   // encoding for a specific type.
148 
149   // Reads the current TLV from the input, checks that the tag matches |tag|
150   // and is a constructed tag, and creates a new Parser from the value.
151   [[nodiscard]] bool ReadConstructed(Tag tag, Parser* out);
152 
153   // A more specific form of ReadConstructed that expects the current tag
154   // to be 0x30 (SEQUENCE).
155   [[nodiscard]] bool ReadSequence(Parser* out);
156 
157   // Expects the current tag to be kInteger, and calls ParseUint8 on the
158   // current value. Note that DER-encoded integers are arbitrary precision,
159   // so this method will fail for valid input that represents an integer
160   // outside the range of an uint8_t.
161   //
162   // Note that on failure the Parser is left in an undefined state (the
163   // input may or may not have been advanced).
164   [[nodiscard]] bool ReadUint8(uint8_t* out);
165 
166   // Expects the current tag to be kInteger, and calls ParseUint64 on the
167   // current value. Note that DER-encoded integers are arbitrary precision,
168   // so this method will fail for valid input that represents an integer
169   // outside the range of an uint64_t.
170   //
171   // Note that on failure the Parser is left in an undefined state (the
172   // input may or may not have been advanced).
173   [[nodiscard]] bool ReadUint64(uint64_t* out);
174 
175   // Reads a BIT STRING. On success returns BitString. On failure, returns
176   // absl::nullopt.
177   //
178   // Note that on failure the Parser is left in an undefined state (the
179   // input may or may not have been advanced).
180   [[nodiscard]] absl::optional<BitString> ReadBitString();
181 
182   // Reads a GeneralizeTime. On success fills |out| and returns true.
183   //
184   // Note that on failure the Parser is left in an undefined state (the
185   // input may or may not have been advanced).
186   [[nodiscard]] bool ReadGeneralizedTime(GeneralizedTime* out);
187 
188   // Lower level methods. The previous methods couple reading data from the
189   // input with advancing the Parser's internal pointer to the next TLV; these
190   // lower level methods decouple those two steps into methods that read from
191   // the current TLV and a method that advances the internal pointer to the
192   // next TLV.
193 
194   // Reads the current TLV from the input, putting the tag in |tag| and the raw
195   // value in |out|, but does not advance the input. Returns true if the tag
196   // and length are successfully read and the output exists.
197   [[nodiscard]] bool PeekTagAndValue(Tag* tag, Input* out);
198 
199   // Advances the input to the next TLV. This method only needs to be called
200   // after PeekTagAndValue; all other methods will advance the input if they
201   // read something.
202   bool Advance();
203 
204  private:
205   CBS cbs_;
206   size_t advance_len_ = 0;
207 };
208 
209 }  // namespace net::der
210 
211 #endif  // NET_DER_PARSER_H_
212