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