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