Update navigator.services API to use the new services.onconnect event [2/3].
[chromium-blink-merge.git] / net / der / parser.h
blob901413363e3835c5bc16a6cf4038109184038fca
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef NET_DER_PARSER_H_
6 #define NET_DER_PARSER_H_
8 #include "base/compiler_specific.h"
9 #include "base/time/time.h"
10 #include "net/base/net_export.h"
11 #include "net/der/input.h"
12 #include "net/der/tag.h"
14 namespace net {
16 namespace der {
18 // Parses a DER-encoded ASN.1 structure. DER (distinguished encoding rules)
19 // encodes each data value with a tag, length, and value (TLV). The tag
20 // indicates the type of the ASN.1 value. Depending on the type of the value,
21 // it could contain arbitrary bytes, so the length of the value is encoded
22 // after the tag and before the value to indicate how many bytes of value
23 // follow. DER also defines how the values are encoded for particular types.
25 // This Parser places a few restrictions on the DER encoding it can parse. The
26 // largest restriction is that it only supports tags which have a tag number
27 // no greater than 30 - these are the tags that fit in a single octet. The
28 // second restriction is that the maximum length for a value that can be parsed
29 // is 4GB. Both of these restrictions should be fine for any reasonable input.
31 // The Parser class is mainly focused on parsing the TLV structure of DER
32 // encoding, and does not directly handle parsing primitive values (other
33 // functions in the net::der namespace are provided for this.) When a Parser
34 // is created, it is passed in a reference to the encoded data. Because the
35 // encoded data is not owned by the Parser, the data cannot change during the
36 // lifespan of the Parser. The Parser functions by keeping a pointer to the
37 // current TLV which starts at the beginning of the input and advancing through
38 // the input as each TLV is read. As such, a Parser instance is thread-unsafe.
40 // Most methods for using the Parser write the current tag and/or value to
41 // the output parameters provided and then advance the input to the next TLV.
42 // None of the methods explicitly expose the length because it is part of the
43 // value. All methods return a boolean indicating whether there was a parsing
44 // error with the current TLV.
46 // Some methods are provided in the Parser class as convenience to both read
47 // the current TLV from the input and also parse the DER encoded value,
48 // converting it to a corresponding C++ type. These methods simply combine
49 // ReadTag() with the appropriate ParseType() free function.
51 // The design of DER encoding allows for nested data structures with
52 // constructed values, where the value is a series of TLVs. The Parser class
53 // is not designed to traverse through a nested encoding from a single object,
54 // but it does facilitate parsing nested data structures through the
55 // convenience methods ReadSequence() and the more general ReadConstructed(),
56 // which provide the user with another Parser object to traverse the next
57 // level of TLVs.
59 // For a brief example of how to use the Parser, suppose we have the following
60 // ASN.1 type definition:
62 // Foo ::= SEQUENCE {
63 // bar OCTET STRING OPTIONAL,
64 // quux OCTET STRING }
66 // If we have a DER-encoded Foo in an Input |encoded_value|, the
67 // following code shows an example of how to parse the quux field from the
68 // encoded data.
70 // bool ReadQuux(const Input& encoded_value, Input* quux_out) {
71 // Parser parser(encoded_value);
72 // Parser foo_parser;
73 // if (!parser.ReadSequence(&foo_parser))
74 // return false;
75 // if (!foo_parser->SkipOptionalTag(kOctetString))
76 // return false;
77 // if (!foo_parser->ReadTag(kOctetString, quux_out))
78 // return false;
79 // return true;
80 // }
81 class NET_EXPORT Parser {
82 public:
83 // Default constructor; equivalent to calling Parser(Input()). This only
84 // exists so that a Parser can be stack allocated and passed in to
85 // ReadConstructed() and similar methods.
86 Parser();
88 // Creates a parser to parse over the data represented by input. This class
89 // assumes that the underlying data will not change over the lifetime of
90 // the Parser object.
91 explicit Parser(const Input& input);
93 // Returns whether there is any more data left in the input to parse. This
94 // does not guarantee that the data is parseable.
95 bool HasMore();
97 // Reads the current TLV from the input and advances. If the tag or length
98 // encoding for the current value is invalid, this method returns false and
99 // does not advance the input. Otherwise, it returns true, putting the
100 // read tag in |tag| and the value in |out|.
101 bool ReadTagAndValue(Tag* tag, Input* out) WARN_UNUSED_RESULT;
103 // Reads the current TLV from the input and advances. Unlike ReadTagAndValue
104 // where only the value is put in |out|, this puts the raw bytes from the
105 // tag, length, and value in |out|.
106 bool ReadRawTLV(Input* out) WARN_UNUSED_RESULT;
108 // Basic methods for reading or skipping the current TLV, with an
109 // expectation of what the current tag should be. It should be possible
110 // to parse any structure with these 4 methods; convenience methods are also
111 // provided to make some cases easier.
113 // If the current tag in the input is |tag|, it puts the corresponding value
114 // in |out|, sets |was_present| to true, and advances the input to the next
115 // TLV. If the current tag is something else, then |was_present| is set to
116 // false and the input is not advanced. Like ReadTagAndValue, it returns
117 // false if the encoding is invalid and does not advance the input.
118 bool ReadOptionalTag(Tag tag,
119 Input* out,
120 bool* was_present) WARN_UNUSED_RESULT;
122 // Like ReadOptionalTag, but the value is discarded.
123 bool SkipOptionalTag(Tag tag, bool* was_present) WARN_UNUSED_RESULT;
125 // If the current tag matches |tag|, it puts the current value in |out|,
126 // advances the input, and returns true. Otherwise, it returns false.
127 bool ReadTag(Tag tag, Input* out) WARN_UNUSED_RESULT;
129 // Advances the input and returns true if the current tag matches |tag|;
130 // otherwise it returns false.
131 bool SkipTag(Tag tag) WARN_UNUSED_RESULT;
133 // Convenience methods to combine parsing the TLV with parsing the DER
134 // encoding for a specific type.
136 // Reads the current TLV from the input, checks that the tag matches |tag|
137 // and is a constructed tag, and creates a new Parser from the value.
138 bool ReadConstructed(Tag tag, Parser* out) WARN_UNUSED_RESULT;
140 // A more specific form of ReadConstructed that expects the current tag
141 // to be 0x30 (SEQUENCE).
142 bool ReadSequence(Parser* out) WARN_UNUSED_RESULT;
144 // Expects the current tag to be kInteger, and calls ParseUint64 on the
145 // current value. Note that DER-encoded integers are arbitrary precision,
146 // so this method will fail for valid input that represents an integer
147 // outside the range of an int64.
148 bool ReadUint64(uint64_t* out) WARN_UNUSED_RESULT;
150 // Lower level methods. The previous methods couple reading data from the
151 // input with advancing the Parser's internal pointer to the next TLV; these
152 // lower level methods decouple those two steps into methods that read from
153 // the current TLV and a method that advances the internal pointer to the
154 // next TLV.
156 // Reads the current TLV from the input, putting the tag in |tag| and the raw
157 // value in |out|, but does not advance the input. Returns true if the tag
158 // and length are successfully read and the output exists.
159 bool PeekTagAndValue(Tag* tag, Input* out) WARN_UNUSED_RESULT;
161 // Advances the input to the next TLV. This method only needs to be called
162 // after PeekTagAndValue; all other methods will advance the input if they
163 // read something.
164 bool Advance();
166 private:
167 ByteReader input_;
168 Mark advance_mark_;
170 DISALLOW_COPY(Parser);
173 } // namespace der
175 } // namespace net
177 #endif // NET_DER_PARSER_H_