123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- // Copyright 2015 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "net/der/parser.h"
- #include "base/check.h"
- #include "net/der/parse_values.h"
- namespace net::der {
- Parser::Parser() {
- CBS_init(&cbs_, nullptr, 0);
- }
- Parser::Parser(const Input& input) {
- CBS_init(&cbs_, input.UnsafeData(), input.Length());
- }
- bool Parser::PeekTagAndValue(Tag* tag, Input* out) {
- CBS peeker = cbs_;
- CBS tmp_out;
- size_t header_len;
- unsigned tag_value;
- if (!CBS_get_any_asn1_element(&peeker, &tmp_out, &tag_value, &header_len) ||
- !CBS_skip(&tmp_out, header_len)) {
- return false;
- }
- advance_len_ = CBS_len(&tmp_out) + header_len;
- *tag = tag_value;
- *out = Input(CBS_data(&tmp_out), CBS_len(&tmp_out));
- return true;
- }
- bool Parser::Advance() {
- if (advance_len_ == 0)
- return false;
- bool ret = !!CBS_skip(&cbs_, advance_len_);
- advance_len_ = 0;
- return ret;
- }
- bool Parser::HasMore() {
- return CBS_len(&cbs_) > 0;
- }
- bool Parser::ReadRawTLV(Input* out) {
- CBS tmp_out;
- if (!CBS_get_any_asn1_element(&cbs_, &tmp_out, nullptr, nullptr))
- return false;
- *out = Input(CBS_data(&tmp_out), CBS_len(&tmp_out));
- return true;
- }
- bool Parser::ReadTagAndValue(Tag* tag, Input* out) {
- if (!PeekTagAndValue(tag, out))
- return false;
- CHECK(Advance());
- return true;
- }
- bool Parser::ReadOptionalTag(Tag tag, absl::optional<Input>* out) {
- if (!HasMore()) {
- *out = absl::nullopt;
- return true;
- }
- Tag actual_tag;
- Input value;
- if (!PeekTagAndValue(&actual_tag, &value)) {
- return false;
- }
- if (actual_tag == tag) {
- CHECK(Advance());
- *out = value;
- } else {
- advance_len_ = 0;
- *out = absl::nullopt;
- }
- return true;
- }
- bool Parser::ReadOptionalTag(Tag tag, Input* out, bool* present) {
- absl::optional<Input> tmp_out;
- if (!ReadOptionalTag(tag, &tmp_out))
- return false;
- *present = tmp_out.has_value();
- *out = tmp_out.value_or(der::Input());
- return true;
- }
- bool Parser::SkipOptionalTag(Tag tag, bool* present) {
- Input out;
- return ReadOptionalTag(tag, &out, present);
- }
- bool Parser::ReadTag(Tag tag, Input* out) {
- Tag actual_tag;
- Input value;
- if (!PeekTagAndValue(&actual_tag, &value) || actual_tag != tag) {
- return false;
- }
- CHECK(Advance());
- *out = value;
- return true;
- }
- bool Parser::SkipTag(Tag tag) {
- Input out;
- return ReadTag(tag, &out);
- }
- // Type-specific variants of ReadTag
- bool Parser::ReadConstructed(Tag tag, Parser* out) {
- if (!IsConstructed(tag))
- return false;
- Input data;
- if (!ReadTag(tag, &data))
- return false;
- *out = Parser(data);
- return true;
- }
- bool Parser::ReadSequence(Parser* out) {
- return ReadConstructed(kSequence, out);
- }
- bool Parser::ReadUint8(uint8_t* out) {
- Input encoded_int;
- if (!ReadTag(kInteger, &encoded_int))
- return false;
- return ParseUint8(encoded_int, out);
- }
- bool Parser::ReadUint64(uint64_t* out) {
- Input encoded_int;
- if (!ReadTag(kInteger, &encoded_int))
- return false;
- return ParseUint64(encoded_int, out);
- }
- absl::optional<BitString> Parser::ReadBitString() {
- Input value;
- if (!ReadTag(kBitString, &value))
- return absl::nullopt;
- return ParseBitString(value);
- }
- bool Parser::ReadGeneralizedTime(GeneralizedTime* out) {
- Input value;
- if (!ReadTag(kGeneralizedTime, &value))
- return false;
- return ParseGeneralizedTime(value, out);
- }
- } // namespace net::der
|