Bob Beck | bc97b7a | 2023-04-18 08:35:15 -0600 | [diff] [blame^] | 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 "fillins/check.h" |
| 8 | #include "parse_values.h" |
| 9 | |
| 10 | namespace bssl::der { |
| 11 | |
| 12 | Parser::Parser() { |
| 13 | CBS_init(&cbs_, nullptr, 0); |
| 14 | } |
| 15 | |
| 16 | Parser::Parser(const Input& input) { |
| 17 | CBS_init(&cbs_, input.UnsafeData(), input.Length()); |
| 18 | } |
| 19 | |
| 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 | |
| 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 | |
| 43 | bool Parser::HasMore() { |
| 44 | return CBS_len(&cbs_) > 0; |
| 45 | } |
| 46 | |
| 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 | |
| 55 | bool Parser::ReadTagAndValue(Tag* tag, Input* out) { |
| 56 | if (!PeekTagAndValue(tag, out)) |
| 57 | return false; |
| 58 | CHECK(Advance()); |
| 59 | return true; |
| 60 | } |
| 61 | |
| 62 | bool Parser::ReadOptionalTag(Tag tag, std::optional<Input>* out) { |
| 63 | if (!HasMore()) { |
| 64 | *out = std::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 = std::nullopt; |
| 78 | } |
| 79 | return true; |
| 80 | } |
| 81 | |
| 82 | bool Parser::ReadOptionalTag(Tag tag, Input* out, bool* present) { |
| 83 | std::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 | |
| 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) { |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 142 | std::optional<BitString> Parser::ReadBitString() { |
| 143 | Input value; |
| 144 | if (!ReadTag(kBitString, &value)) |
| 145 | return std::nullopt; |
| 146 | return ParseBitString(value); |
| 147 | } |
| 148 | |
| 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 bssl::der |