// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "crypto/default/cms/ber_parser.h"

#include <cstring>
#include <limits>
#include <string>
#include <vector>

#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "crypto/default/cms/cms_error_code.h"
#include "openssl/base.h"
#include "openssl/bytestring.h"

namespace credentio_cms {

BerParser::BerParser(const uint8_t* data, size_t length) {
  CBS cbs;
  CBS_init(&cbs, data, length);
  scopes_.push_back(Scope(cbs, false));
  start_ = data;
}

void BerParser::SetElementName(absl::string_view text) {
  scopes_.back().element_name = text;
}

bool BerParser::ok() const { return status_ == ErrorCode::OK; }

ErrorCode BerParser::status() const { return status_; }

std::string BerParser::error_message() const { return error_message_; }

// Checks that the next element has the expected tag. If the element is
// constructed the parser will read from it until CloseTag is called.
void BerParser::GetTag(unsigned expected_tag) {
  unsigned tag = 0;
  GetTagInternal(&tag, nullptr, nullptr, false /* raw */);
  CompareTag(tag, expected_tag, nullptr /* out */);
}

bool BerParser::GetOptionalTag(unsigned expected_tag) {
  if (!Peek(expected_tag)) {
    return false;
  }
  GetTag(expected_tag);
  return ok();
}

void BerParser::GetElementData(unsigned expected_tag, CBS* out) {
  if (!IsValid(out)) {
    return;
  }
  unsigned tag = 0;
  GetTagInternal(&tag, out, nullptr /* headers */, false /* raw tag */);
  CompareTag(tag, expected_tag, out);
}

bool BerParser::GetOptionalElementData(unsigned expected_tag, CBS* out) {
  if (!IsValid(out) || !Peek(expected_tag)) {
    return false;
  }
  GetElementData(expected_tag, out);
  return ok();
}

void BerParser::GetAnyElementAndSkipChildren(CBS* out) {
  if (!IsValid(out)) {
    return;
  }
  unsigned tag;
  GetTagInternal(&tag, nullptr, out, true /* raw */);
}

bool BerParser::Peek(unsigned expected_tag) const {
  if (!ok()) {
    return false;
  }
  const Scope& scope = scopes_.back();
  return CBS_peek_asn1_tag(&scope.data, expected_tag) == 1;
}

bool BerParser::IsNullOrEmpty() {
  if (!ok()) {
    return true;
  }
  Scope& scope = scopes_.back();
  if (CBS_len(&scope.data) == 0) {
    return true;
  }
  if (CBS_peek_asn1_tag(&scope.data, CBS_ASN1_NULL) == 1) {
    if (CBS_get_asn1(&scope.data, nullptr, CBS_ASN1_NULL) != 1) {
      SetError(ErrorCode::ASN1_PARSING_ERROR, "Failed to read NULL element ");
    }
    return true;
  }
  return scope.indefinite && IsEndOfContent();
}

int BerParser::GetInt() {
  if (!ok()) {
    // No-op if there was already an error.
    return 0;
  }
  Scope& scope = scopes_.back();
  uint64_t v;
  if (CBS_get_asn1_uint64(&scope.data, &v) != 1 ||
      v > std::numeric_limits<int>::max()) {
    SetError(ErrorCode::ASN1_PARSING_ERROR, "Failed to get an int ");
    return 0;
  }
  return static_cast<int>(v);
}

void BerParser::EndConstructed() {
  if (!ok()) {
    return;
  }
  if (scopes_.size() < 2) {
    // There should always be at least one element in the scope stack, this
    // would pop the last one.
    SetError(ErrorCode::ASN1_PARSING_ERROR, "Unexpected EndConstructed call ");
    return;
  }

  Scope& scope = scopes_.back();
  if (!scope.indefinite) {
    if (CBS_len(&scope.data) > 0) {
      SetError(ErrorCode::ASN1_PARSING_ERROR,
               "Found data remaining while expecting the end of the current "
               "element ");
    }
    scopes_.pop_back();
    return;
  }
  if (!IsEndOfContent() || CBS_skip(&scope.data, 2) != 1) {
    SetError(ErrorCode::ASN1_PARSING_ERROR,
             "Error while expecting the end of an indefinite length element ");
    return;
  }
  const auto end = CBS_data(&scope.data);
  scopes_.pop_back();
  const auto previous = CBS_data(&scopes_.back().data);
  if (end < previous || CBS_skip(&scopes_.back().data, end - previous) != 1) {
    SetError(
        ErrorCode::ASN1_PARSING_ERROR,
        "Failed to seek past the end of the current indefinite length tag ");
  }
}

bool BerParser::IsValid(CBS* out) {
  if (out == nullptr) {
    SetError(ErrorCode::INVALID_PARAMETER,
             "Caller error, null pointer passed to IsValid ");
    return false;
  }
  CBS_init(out, nullptr, 0);
  return status_ == ErrorCode::OK;
}

bool BerParser::IsEndOfContent() {
  Scope& scope = scopes_.back();
  return CBS_len(&scope.data) >= 2 &&
         memcmp(CBS_data(&scope.data), "\0\0", 2) == 0;
}

void BerParser::GetTagInternal(unsigned* tag, CBS* value, CBS* header_and_value,
                               bool raw_tag) {
  if (!ok()) {
    return;
  }
  Scope& scope = scopes_.back();
  size_t header_length;
  CBS out;
  int indefinite_length;
  if (CBS_get_any_ber_asn1_element(&scope.data, &out, tag, &header_length,
                                   /*out_ber_found=*/nullptr,
                                   &indefinite_length) != 1) {
    SetError(ErrorCode::ASN1_PARSING_ERROR, "Parsing error ");
    return;
  }

  if (indefinite_length && (value != nullptr || header_and_value != nullptr)) {
    SetError(
        ErrorCode::ASN1_PARSING_ERROR,
        "Indefinite length not supported when the element data is needed ");
    return;
  }

  if (header_and_value != nullptr) {
    *header_and_value = out;
  }
  if (value != nullptr) {
    *value = out;
    if (CBS_skip(value, header_length) != 1) {
      SetError(ErrorCode::ASN1_PARSING_ERROR, "Failed to skip the header ");
      return;
    }
  }

  if (raw_tag || (*tag & CBS_ASN1_CONSTRUCTED) == 0) {
    return;
  }
  // If the tag is constructed, start a new scope containing either the
  // element we just read (definite length) or all the data remaining if the
  // length is unknown.
  if (indefinite_length) {
    scopes_.push_back(Scope(scope.data, indefinite_length));
  } else {
    if (CBS_skip(&out, header_length) != 1) {
      SetError(ErrorCode::ASN1_PARSING_ERROR, "Failed to read the header ");
      return;
    }
    scopes_.push_back(Scope(out, indefinite_length));
  }
}

void BerParser::CompareTag(unsigned tag, unsigned expected_tag, CBS* out) {
  if (ok() && tag != expected_tag) {
    std::string message =
        absl::StrCat("Got tag ", tag, " instead of tag ", expected_tag);

    SetError(ErrorCode::ASN1_PARSING_ERROR, message);
    if (out != nullptr) {
      CBS_init(out, nullptr, 0);
    }
  }
}

void BerParser::SetError(ErrorCode status, absl::string_view text) {
  if (!ok()) {
    // Don't clear existing errors.
    return;
  }
  status_ = status;
  error_message_ =
      absl::StrCat(text, " at offset: ", GetCurrentOffset(), " in scope: ");
  for (const auto& scope : scopes_) {
    if (!scope.element_name.empty()) {
      absl::StrAppend(&error_message_, scope.element_name, " > ");
    }
  }
}

size_t BerParser::GetCurrentOffset() {
  if (scopes_.empty()) {
    return 0;
  }
  return CBS_data(&scopes_.back().data) - start_;
}

}  // namespace credentio_cms
