blob: 01ea3f0a4faf49a49ee7119cdf3023067e12d781 [file] [log] [blame]
Avi Drissman64595482022-09-14 20:52:291// Copyright 2015 The Chromium Authors
nharper00e51a362015-04-22 23:13:502// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
nharper00e51a362015-04-22 23:13:505#include "net/der/parser.h"
6
Hans Wennborg0924470b2020-04-27 21:08:057#include "base/check.h"
davidben32016b72016-12-08 22:39:468#include "net/der/parse_values.h"
9
Tsuyoshi Horo4f516be2022-06-14 11:53:1310namespace net::der {
nharper00e51a362015-04-22 23:13:5011
Tsuyoshi Horo432981d52022-06-09 09:50:1312Parser::Parser() {
nharper48a41ffa2016-05-27 18:41:4613 CBS_init(&cbs_, nullptr, 0);
nharper00e51a362015-04-22 23:13:5014}
eromanbd8fa8e2015-05-07 21:39:1215
Tsuyoshi Horo432981d52022-06-09 09:50:1316Parser::Parser(const Input& input) {
nharper48a41ffa2016-05-27 18:41:4617 CBS_init(&cbs_, input.UnsafeData(), input.Length());
nharper00e51a362015-04-22 23:13:5018}
19
nharper00e51a362015-04-22 23:13:5020bool Parser::PeekTagAndValue(Tag* tag, Input* out) {
nharper48a41ffa2016-05-27 18:41:4621 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) ||
David Benjamin836f8382017-12-15 22:30:1126 !CBS_skip(&tmp_out, header_len)) {
nharper00e51a362015-04-22 23:13:5027 return false;
nharper00e51a362015-04-22 23:13:5028 }
nharper48a41ffa2016-05-27 18:41:4629 advance_len_ = CBS_len(&tmp_out) + header_len;
David Benjamin836f8382017-12-15 22:30:1130 *tag = tag_value;
nharper48a41ffa2016-05-27 18:41:4631 *out = Input(CBS_data(&tmp_out), CBS_len(&tmp_out));
nharper00e51a362015-04-22 23:13:5032 return true;
33}
34
35bool Parser::Advance() {
nharper48a41ffa2016-05-27 18:41:4636 if (advance_len_ == 0)
nharper00e51a362015-04-22 23:13:5037 return false;
nharper48a41ffa2016-05-27 18:41:4638 bool ret = !!CBS_skip(&cbs_, advance_len_);
39 advance_len_ = 0;
40 return ret;
nharper00e51a362015-04-22 23:13:5041}
42
43bool Parser::HasMore() {
nharper48a41ffa2016-05-27 18:41:4644 return CBS_len(&cbs_) > 0;
nharper00e51a362015-04-22 23:13:5045}
46
47bool Parser::ReadRawTLV(Input* out) {
nharper48a41ffa2016-05-27 18:41:4648 CBS tmp_out;
49 if (!CBS_get_any_asn1_element(&cbs_, &tmp_out, nullptr, nullptr))
nharper00e51a362015-04-22 23:13:5050 return false;
nharper48a41ffa2016-05-27 18:41:4651 *out = Input(CBS_data(&tmp_out), CBS_len(&tmp_out));
nharper00e51a362015-04-22 23:13:5052 return true;
53}
54
55bool Parser::ReadTagAndValue(Tag* tag, Input* out) {
56 if (!PeekTagAndValue(tag, out))
57 return false;
58 CHECK(Advance());
59 return true;
60}
61
Anton Bikineev068d2912021-05-15 20:43:5262bool Parser::ReadOptionalTag(Tag tag, absl::optional<Input>* out) {
David Benjaminc64293e72017-11-22 03:03:4063 if (!HasMore()) {
Anton Bikineev068d2912021-05-15 20:43:5264 *out = absl::nullopt;
David Benjaminc64293e72017-11-22 03:03:4065 return true;
66 }
67 Tag actual_tag;
68 Input value;
69 if (!PeekTagAndValue(&actual_tag, &value)) {
nharper00e51a362015-04-22 23:13:5070 return false;
David Benjaminc64293e72017-11-22 03:03:4071 }
72 if (actual_tag == tag) {
73 CHECK(Advance());
David Benjaminc64293e72017-11-22 03:03:4074 *out = value;
75 } else {
76 advance_len_ = 0;
Anton Bikineev068d2912021-05-15 20:43:5277 *out = absl::nullopt;
David Benjaminc64293e72017-11-22 03:03:4078 }
nharper00e51a362015-04-22 23:13:5079 return true;
80}
81
Matt Mueller7304edd2019-06-06 22:57:3682bool Parser::ReadOptionalTag(Tag tag, Input* out, bool* present) {
Anton Bikineev068d2912021-05-15 20:43:5283 absl::optional<Input> tmp_out;
Matt Mueller7304edd2019-06-06 22:57:3684 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
nharper00e51a362015-04-22 23:13:5091bool Parser::SkipOptionalTag(Tag tag, bool* present) {
92 Input out;
93 return ReadOptionalTag(tag, &out, present);
94}
95
96bool Parser::ReadTag(Tag tag, Input* out) {
David Benjaminc64293e72017-11-22 03:03:4097 Tag actual_tag;
98 Input value;
99 if (!PeekTagAndValue(&actual_tag, &value) || actual_tag != tag) {
nharper48a41ffa2016-05-27 18:41:46100 return false;
David Benjaminc64293e72017-11-22 03:03:40101 }
102 CHECK(Advance());
103 *out = value;
nharper48a41ffa2016-05-27 18:41:46104 return true;
nharper00e51a362015-04-22 23:13:50105}
106
107bool Parser::SkipTag(Tag tag) {
108 Input out;
109 return ReadTag(tag, &out);
110}
111
112// Type-specific variants of ReadTag
113
114bool 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
124bool Parser::ReadSequence(Parser* out) {
125 return ReadConstructed(kSequence, out);
126}
127
svaldezbe481782016-03-24 17:16:32128bool 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
nharper00e51a362015-04-22 23:13:50135bool Parser::ReadUint64(uint64_t* out) {
eroman67dc5e72015-07-01 19:31:54136 Input encoded_int;
137 if (!ReadTag(kInteger, &encoded_int))
nharper00e51a362015-04-22 23:13:50138 return false;
eroman67dc5e72015-07-01 19:31:54139 return ParseUint64(encoded_int, out);
nharper00e51a362015-04-22 23:13:50140}
141
Hubert Chaoef833572022-04-21 20:58:39142absl::optional<BitString> Parser::ReadBitString() {
eroman5915fe2e2015-07-27 23:05:50143 Input value;
144 if (!ReadTag(kBitString, &value))
Hubert Chaoef833572022-04-21 20:58:39145 return absl::nullopt;
146 return ParseBitString(value);
eroman5915fe2e2015-07-27 23:05:50147}
148
svaldezbe481782016-03-24 17:16:32149bool Parser::ReadGeneralizedTime(GeneralizedTime* out) {
150 Input value;
151 if (!ReadTag(kGeneralizedTime, &value))
152 return false;
153 return ParseGeneralizedTime(value, out);
154}
155
Tsuyoshi Horo4f516be2022-06-14 11:53:13156} // namespace net::der