• 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 #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