Avi Drissman | 6459548 | 2022-09-14 20:52:29 | [diff] [blame^] | 1 | // Copyright 2015 The Chromium Authors |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 5 | #include "net/der/parser.h" |
| 6 | |
Hans Wennborg | 0924470b | 2020-04-27 21:08:05 | [diff] [blame] | 7 | #include "base/check.h" |
davidben | 32016b7 | 2016-12-08 22:39:46 | [diff] [blame] | 8 | #include "net/der/parse_values.h" |
| 9 | |
Tsuyoshi Horo | 4f516be | 2022-06-14 11:53:13 | [diff] [blame] | 10 | namespace net::der { |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 11 | |
Tsuyoshi Horo | 432981d5 | 2022-06-09 09:50:13 | [diff] [blame] | 12 | Parser::Parser() { |
nharper | 48a41ffa | 2016-05-27 18:41:46 | [diff] [blame] | 13 | CBS_init(&cbs_, nullptr, 0); |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 14 | } |
eroman | bd8fa8e | 2015-05-07 21:39:12 | [diff] [blame] | 15 | |
Tsuyoshi Horo | 432981d5 | 2022-06-09 09:50:13 | [diff] [blame] | 16 | Parser::Parser(const Input& input) { |
nharper | 48a41ffa | 2016-05-27 18:41:46 | [diff] [blame] | 17 | CBS_init(&cbs_, input.UnsafeData(), input.Length()); |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 18 | } |
| 19 | |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 20 | bool Parser::PeekTagAndValue(Tag* tag, Input* out) { |
nharper | 48a41ffa | 2016-05-27 18:41:46 | [diff] [blame] | 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) || |
David Benjamin | 836f838 | 2017-12-15 22:30:11 | [diff] [blame] | 26 | !CBS_skip(&tmp_out, header_len)) { |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 27 | return false; |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 28 | } |
nharper | 48a41ffa | 2016-05-27 18:41:46 | [diff] [blame] | 29 | advance_len_ = CBS_len(&tmp_out) + header_len; |
David Benjamin | 836f838 | 2017-12-15 22:30:11 | [diff] [blame] | 30 | *tag = tag_value; |
nharper | 48a41ffa | 2016-05-27 18:41:46 | [diff] [blame] | 31 | *out = Input(CBS_data(&tmp_out), CBS_len(&tmp_out)); |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 32 | return true; |
| 33 | } |
| 34 | |
| 35 | bool Parser::Advance() { |
nharper | 48a41ffa | 2016-05-27 18:41:46 | [diff] [blame] | 36 | if (advance_len_ == 0) |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 37 | return false; |
nharper | 48a41ffa | 2016-05-27 18:41:46 | [diff] [blame] | 38 | bool ret = !!CBS_skip(&cbs_, advance_len_); |
| 39 | advance_len_ = 0; |
| 40 | return ret; |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 41 | } |
| 42 | |
| 43 | bool Parser::HasMore() { |
nharper | 48a41ffa | 2016-05-27 18:41:46 | [diff] [blame] | 44 | return CBS_len(&cbs_) > 0; |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 45 | } |
| 46 | |
| 47 | bool Parser::ReadRawTLV(Input* out) { |
nharper | 48a41ffa | 2016-05-27 18:41:46 | [diff] [blame] | 48 | CBS tmp_out; |
| 49 | if (!CBS_get_any_asn1_element(&cbs_, &tmp_out, nullptr, nullptr)) |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 50 | return false; |
nharper | 48a41ffa | 2016-05-27 18:41:46 | [diff] [blame] | 51 | *out = Input(CBS_data(&tmp_out), CBS_len(&tmp_out)); |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 52 | return true; |
| 53 | } |
| 54 | |
| 55 | bool Parser::ReadTagAndValue(Tag* tag, Input* out) { |
| 56 | if (!PeekTagAndValue(tag, out)) |
| 57 | return false; |
| 58 | CHECK(Advance()); |
| 59 | return true; |
| 60 | } |
| 61 | |
Anton Bikineev | 068d291 | 2021-05-15 20:43:52 | [diff] [blame] | 62 | bool Parser::ReadOptionalTag(Tag tag, absl::optional<Input>* out) { |
David Benjamin | c64293e7 | 2017-11-22 03:03:40 | [diff] [blame] | 63 | if (!HasMore()) { |
Anton Bikineev | 068d291 | 2021-05-15 20:43:52 | [diff] [blame] | 64 | *out = absl::nullopt; |
David Benjamin | c64293e7 | 2017-11-22 03:03:40 | [diff] [blame] | 65 | return true; |
| 66 | } |
| 67 | Tag actual_tag; |
| 68 | Input value; |
| 69 | if (!PeekTagAndValue(&actual_tag, &value)) { |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 70 | return false; |
David Benjamin | c64293e7 | 2017-11-22 03:03:40 | [diff] [blame] | 71 | } |
| 72 | if (actual_tag == tag) { |
| 73 | CHECK(Advance()); |
David Benjamin | c64293e7 | 2017-11-22 03:03:40 | [diff] [blame] | 74 | *out = value; |
| 75 | } else { |
| 76 | advance_len_ = 0; |
Anton Bikineev | 068d291 | 2021-05-15 20:43:52 | [diff] [blame] | 77 | *out = absl::nullopt; |
David Benjamin | c64293e7 | 2017-11-22 03:03:40 | [diff] [blame] | 78 | } |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 79 | return true; |
| 80 | } |
| 81 | |
Matt Mueller | 7304edd | 2019-06-06 22:57:36 | [diff] [blame] | 82 | bool Parser::ReadOptionalTag(Tag tag, Input* out, bool* present) { |
Anton Bikineev | 068d291 | 2021-05-15 20:43:52 | [diff] [blame] | 83 | absl::optional<Input> tmp_out; |
Matt Mueller | 7304edd | 2019-06-06 22:57:36 | [diff] [blame] | 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 | |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 91 | bool Parser::SkipOptionalTag(Tag tag, bool* present) { |
| 92 | Input out; |
| 93 | return ReadOptionalTag(tag, &out, present); |
| 94 | } |
| 95 | |
| 96 | bool Parser::ReadTag(Tag tag, Input* out) { |
David Benjamin | c64293e7 | 2017-11-22 03:03:40 | [diff] [blame] | 97 | Tag actual_tag; |
| 98 | Input value; |
| 99 | if (!PeekTagAndValue(&actual_tag, &value) || actual_tag != tag) { |
nharper | 48a41ffa | 2016-05-27 18:41:46 | [diff] [blame] | 100 | return false; |
David Benjamin | c64293e7 | 2017-11-22 03:03:40 | [diff] [blame] | 101 | } |
| 102 | CHECK(Advance()); |
| 103 | *out = value; |
nharper | 48a41ffa | 2016-05-27 18:41:46 | [diff] [blame] | 104 | return true; |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 105 | } |
| 106 | |
| 107 | bool Parser::SkipTag(Tag tag) { |
| 108 | Input out; |
| 109 | return ReadTag(tag, &out); |
| 110 | } |
| 111 | |
| 112 | // Type-specific variants of ReadTag |
| 113 | |
| 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 | |
| 124 | bool Parser::ReadSequence(Parser* out) { |
| 125 | return ReadConstructed(kSequence, out); |
| 126 | } |
| 127 | |
svaldez | be48178 | 2016-03-24 17:16:32 | [diff] [blame] | 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 | |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 135 | bool Parser::ReadUint64(uint64_t* out) { |
eroman | 67dc5e7 | 2015-07-01 19:31:54 | [diff] [blame] | 136 | Input encoded_int; |
| 137 | if (!ReadTag(kInteger, &encoded_int)) |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 138 | return false; |
eroman | 67dc5e7 | 2015-07-01 19:31:54 | [diff] [blame] | 139 | return ParseUint64(encoded_int, out); |
nharper | 00e51a36 | 2015-04-22 23:13:50 | [diff] [blame] | 140 | } |
| 141 | |
Hubert Chao | ef83357 | 2022-04-21 20:58:39 | [diff] [blame] | 142 | absl::optional<BitString> Parser::ReadBitString() { |
eroman | 5915fe2e | 2015-07-27 23:05:50 | [diff] [blame] | 143 | Input value; |
| 144 | if (!ReadTag(kBitString, &value)) |
Hubert Chao | ef83357 | 2022-04-21 20:58:39 | [diff] [blame] | 145 | return absl::nullopt; |
| 146 | return ParseBitString(value); |
eroman | 5915fe2e | 2015-07-27 23:05:50 | [diff] [blame] | 147 | } |
| 148 | |
svaldez | be48178 | 2016-03-24 17:16:32 | [diff] [blame] | 149 | bool Parser::ReadGeneralizedTime(GeneralizedTime* out) { |
| 150 | Input value; |
| 151 | if (!ReadTag(kGeneralizedTime, &value)) |
| 152 | return false; |
| 153 | return ParseGeneralizedTime(value, out); |
| 154 | } |
| 155 | |
Tsuyoshi Horo | 4f516be | 2022-06-14 11:53:13 | [diff] [blame] | 156 | } // namespace net::der |