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 #include "base/logging.h"
6 #include "base/numerics/safe_math.h"
7 #include "net/der/parse_values.h"
8 #include "net/der/parser.h"
14 Parser::Parser() : input_(Input()), advance_mark_(Mark::NullMark()) {
17 Parser::Parser(const Input
& input
)
18 : input_(input
), advance_mark_(Mark::NullMark()) {
21 bool Parser::PeekTagAndValue(Tag
* tag
, Input
* out
) {
22 ByteReader reader
= input_
;
24 // Don't support tags > 30.
26 if (!reader
.ReadByte(&tag_byte
))
29 // ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a
30 // tag number no greater than 30. This parser only supports tag numbers up
32 // If the tag number is 31 (0x1F, the largest value that fits in the allotted
33 // bytes), then the tag is more than one byte long and the continuation bytes
34 // contain the real tag number. We only support tag numbers < 31 (and thus
36 if ((tag_byte
& kTagNumberMask
) == 31)
39 // Parse length. The format for the length encoding is specified in
40 // ITU-T X.690 section 8.1.3.
41 size_t value_len
= 0; // Number of bytes used to encode just the value.
43 uint8_t length_first_byte
;
44 if (!reader
.ReadByte(&length_first_byte
))
46 if ((length_first_byte
& 0x80) == 0) {
47 // Short form for length - it's only one byte long.
48 value_len
= length_first_byte
& 0x7f;
50 // Long form for length - it's encoded across multiple bytes.
51 if (length_first_byte
== 0xff) {
52 // ITU-T X.690 clause 8.1.3.5.c specifies the value 0xff shall not be
56 // The high bit indicated that this is the long form, while the next 7 bits
57 // encode the number of subsequent octets used to encode the length
58 // (ITU-T X.690 clause 8.1.3.5.b).
59 size_t length_len
= length_first_byte
& 0x7f;
60 if (length_len
== 0) {
61 // ITU-T X.690 section 10.1 (DER length forms) requires encoding the
62 // length with the minimum number of octets. Besides, it makes no sense
63 // for the length to be encoded in 0 octets.
66 if (length_len
> sizeof(value_len
)) {
67 // The length is encoded in multiple octets, with the first octet
68 // indicating how many octets follow. Those octets need to be combined
69 // to form a size_t, so the number of octets to follow (length_len)
70 // must be small enough so that they fit in a size_t.
74 for (size_t i
= 0; i
< length_len
; i
++) {
75 if (!reader
.ReadByte(&length_byte
))
77 // A first length byte of all zeroes means the length was not encoded in
79 if (i
== 0 && length_byte
== 0)
82 value_len
+= length_byte
;
84 if (value_len
< 0x80) {
85 // If value_len is < 0x80, then it could have been encoded in a single
86 // byte, meaning it was not encoded in minimum length.
91 if (!reader
.ReadBytes(value_len
, out
))
93 advance_mark_
= reader
.NewMark();
98 bool Parser::Advance() {
99 if (advance_mark_
.IsEmpty())
101 if (!input_
.AdvanceToMark(advance_mark_
))
103 advance_mark_
= Mark::NullMark();
107 bool Parser::HasMore() {
108 return input_
.HasMore();
111 bool Parser::ReadRawTLV(Input
* out
) {
114 if (!PeekTagAndValue(&tag
, &value
))
116 if (!input_
.ReadToMark(advance_mark_
, out
))
118 advance_mark_
= Mark::NullMark();
123 bool Parser::ReadTagAndValue(Tag
* tag
, Input
* out
) {
124 if (!PeekTagAndValue(tag
, out
))
130 bool Parser::ReadOptionalTag(Tag tag
, Input
* out
, bool* present
) {
138 if (!PeekTagAndValue(&read_tag
, &value
))
141 if (read_tag
== tag
) {
146 advance_mark_
= Mark::NullMark();
151 bool Parser::SkipOptionalTag(Tag tag
, bool* present
) {
153 return ReadOptionalTag(tag
, &out
, present
);
156 bool Parser::ReadTag(Tag tag
, Input
* out
) {
158 return ReadOptionalTag(tag
, out
, &present
) && present
;
161 bool Parser::SkipTag(Tag tag
) {
163 return ReadTag(tag
, &out
);
166 // Type-specific variants of ReadTag
168 bool Parser::ReadConstructed(Tag tag
, Parser
* out
) {
169 if (!IsConstructed(tag
))
172 if (!ReadTag(tag
, &data
))
178 bool Parser::ReadSequence(Parser
* out
) {
179 return ReadConstructed(kSequence
, out
);
182 bool Parser::ReadUint64(uint64_t* out
) {
184 if (!ReadTag(kInteger
, &encoded_int
))
186 return ParseUint64(encoded_int
, out
);
189 bool Parser::ReadBitString(BitString
* bit_string
) {
191 if (!ReadTag(kBitString
, &value
))
193 return ParseBitString(value
, bit_string
);