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 #include "net/der/parser.h"
6
7 #include "base/check.h"
8 #include "net/der/parse_values.h"
9
10 namespace net::der {
11
Parser()12 Parser::Parser() {
13 CBS_init(&cbs_, nullptr, 0);
14 }
15
Parser(const Input & input)16 Parser::Parser(const Input& input) {
17 CBS_init(&cbs_, input.UnsafeData(), input.Length());
18 }
19
PeekTagAndValue(Tag * tag,Input * out)20 bool Parser::PeekTagAndValue(Tag* tag, Input* out) {
21 CBS peeker = cbs_;
22 CBS tmp_out;
23 size_t header_len;
24 unsigned tag_value;
25 if (!CBS_get_any_asn1_element(&peeker, &tmp_out, &tag_value, &header_len) ||
26 !CBS_skip(&tmp_out, header_len)) {
27 return false;
28 }
29 advance_len_ = CBS_len(&tmp_out) + header_len;
30 *tag = tag_value;
31 *out = Input(CBS_data(&tmp_out), CBS_len(&tmp_out));
32 return true;
33 }
34
Advance()35 bool Parser::Advance() {
36 if (advance_len_ == 0)
37 return false;
38 bool ret = !!CBS_skip(&cbs_, advance_len_);
39 advance_len_ = 0;
40 return ret;
41 }
42
HasMore()43 bool Parser::HasMore() {
44 return CBS_len(&cbs_) > 0;
45 }
46
ReadRawTLV(Input * out)47 bool Parser::ReadRawTLV(Input* out) {
48 CBS tmp_out;
49 if (!CBS_get_any_asn1_element(&cbs_, &tmp_out, nullptr, nullptr))
50 return false;
51 *out = Input(CBS_data(&tmp_out), CBS_len(&tmp_out));
52 return true;
53 }
54
ReadTagAndValue(Tag * tag,Input * out)55 bool Parser::ReadTagAndValue(Tag* tag, Input* out) {
56 if (!PeekTagAndValue(tag, out))
57 return false;
58 CHECK(Advance());
59 return true;
60 }
61
ReadOptionalTag(Tag tag,absl::optional<Input> * out)62 bool Parser::ReadOptionalTag(Tag tag, absl::optional<Input>* out) {
63 if (!HasMore()) {
64 *out = absl::nullopt;
65 return true;
66 }
67 Tag actual_tag;
68 Input value;
69 if (!PeekTagAndValue(&actual_tag, &value)) {
70 return false;
71 }
72 if (actual_tag == tag) {
73 CHECK(Advance());
74 *out = value;
75 } else {
76 advance_len_ = 0;
77 *out = absl::nullopt;
78 }
79 return true;
80 }
81
ReadOptionalTag(Tag tag,Input * out,bool * present)82 bool Parser::ReadOptionalTag(Tag tag, Input* out, bool* present) {
83 absl::optional<Input> tmp_out;
84 if (!ReadOptionalTag(tag, &tmp_out))
85 return false;
86 *present = tmp_out.has_value();
87 *out = tmp_out.value_or(der::Input());
88 return true;
89 }
90
SkipOptionalTag(Tag tag,bool * present)91 bool Parser::SkipOptionalTag(Tag tag, bool* present) {
92 Input out;
93 return ReadOptionalTag(tag, &out, present);
94 }
95
ReadTag(Tag tag,Input * out)96 bool Parser::ReadTag(Tag tag, Input* out) {
97 Tag actual_tag;
98 Input value;
99 if (!PeekTagAndValue(&actual_tag, &value) || actual_tag != tag) {
100 return false;
101 }
102 CHECK(Advance());
103 *out = value;
104 return true;
105 }
106
SkipTag(Tag tag)107 bool Parser::SkipTag(Tag tag) {
108 Input out;
109 return ReadTag(tag, &out);
110 }
111
112 // Type-specific variants of ReadTag
113
ReadConstructed(Tag tag,Parser * out)114 bool Parser::ReadConstructed(Tag tag, Parser* out) {
115 if (!IsConstructed(tag))
116 return false;
117 Input data;
118 if (!ReadTag(tag, &data))
119 return false;
120 *out = Parser(data);
121 return true;
122 }
123
ReadSequence(Parser * out)124 bool Parser::ReadSequence(Parser* out) {
125 return ReadConstructed(kSequence, out);
126 }
127
ReadUint8(uint8_t * out)128 bool Parser::ReadUint8(uint8_t* out) {
129 Input encoded_int;
130 if (!ReadTag(kInteger, &encoded_int))
131 return false;
132 return ParseUint8(encoded_int, out);
133 }
134
ReadUint64(uint64_t * out)135 bool Parser::ReadUint64(uint64_t* out) {
136 Input encoded_int;
137 if (!ReadTag(kInteger, &encoded_int))
138 return false;
139 return ParseUint64(encoded_int, out);
140 }
141
ReadBitString()142 absl::optional<BitString> Parser::ReadBitString() {
143 Input value;
144 if (!ReadTag(kBitString, &value))
145 return absl::nullopt;
146 return ParseBitString(value);
147 }
148
ReadGeneralizedTime(GeneralizedTime * out)149 bool Parser::ReadGeneralizedTime(GeneralizedTime* out) {
150 Input value;
151 if (!ReadTag(kGeneralizedTime, &value))
152 return false;
153 return ParseGeneralizedTime(value, out);
154 }
155
156 } // namespace net::der
157