// 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 "cose/sig_structure.h"

#include <cstdint>
#include <string>
#include <utility>
#include <vector>

#include "absl/log/absl_log.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "cbor/cbor.h"
#include "cbor/parse.h"
#include "cppbor/cppbor.h"
#include "crypto/algorithms.h"

namespace credentio {
namespace {
// 'alg' in https://datatracker.ietf.org/doc/html/rfc8152#section-3.1
constexpr int kSigningAlgorithmKey = 1;
// See
// https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_obtaining_the_time_stamp
// for more details.
constexpr absl::string_view kTimestampV2HeaderKey = "sigTst2";
// DEPRECATED. DO NOT GENERATE. Contents of 'sigTst' CBOR map.
constexpr absl::string_view kTimestampV1HeaderKey = "sigTst";
// See
// https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_create_a_temporary_claim_and_signature
// for more details about padding.
constexpr absl::string_view kPadHeaderKey = "pad";
// See
// https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_going_back_and_filling_in
// about using `pad2`.
constexpr absl::string_view kPad2HeaderKey = "pad2";
// https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#x509_certificates
constexpr int kCertificateChainKey = 33;
constexpr absl::string_view kCertificateChainDeprecatedKey = "x5chain";
constexpr absl::string_view kOcspValsKey = "ocspVals";
constexpr absl::string_view kRvalsKey = "rVals";

// https://www.iana.org/assignments/cose/cose.xhtml#algorithms
absl::StatusOr<int64_t> GetAlgorithm(SigningAlgorithm e) {
  switch (e) {
    case SigningAlgorithm::kEs256:
      return -7;
    case SigningAlgorithm::kEdDsa:
      return -8;
    case SigningAlgorithm::kEs384:
      return -35;
    case SigningAlgorithm::kEs512:
      return -36;
    case SigningAlgorithm::kPs256:
      return -37;
    case SigningAlgorithm::kPs384:
      return -38;
    case SigningAlgorithm::kPs512:
      return -39;
  }
  return absl::InvalidArgumentError("Unsupported algorithm");
}

absl::StatusOr<SigningAlgorithm> GetSigningAlgorithm(cbor::MapView headers) {
  auto alg = headers.GetInt64(kSigningAlgorithmKey);
  if (!alg.ok()) {
    return absl::Status(
        alg.status().code(),
        absl::StrCat("no COSE algorithm specified in protected headers: ",
                     alg.status().message()));
  }
  // https://www.iana.org/assignments/cose/cose.xhtml#algorithms
  ABSL_DVLOG(1) << ".cose_alg = " << *alg << ",";
  switch (*alg) {
    case -7:
      return SigningAlgorithm::kEs256;
    case -35:
      return SigningAlgorithm::kEs384;
    case -36:
      return SigningAlgorithm::kEs512;
    case -37:
      return SigningAlgorithm::kPs256;
    case -38:
      return SigningAlgorithm::kPs384;
    case -39:
      return SigningAlgorithm::kPs512;
    case -8:
      return SigningAlgorithm::kEdDsa;
  }
  return absl::InvalidArgumentError(
      absl::StrCat("unsupported COSE algorithm: ", *alg));
}

absl::StatusOr<std::vector<std::string>> GetCertificateChain(
    cbor::MapView headers) {
  // Check if there is a single certificate in the chain. In this case, label 33
  // of the header map (or "x5chain" key) is a bstr.
  // Claim generators should only use 33 (integer) key but the validators should
  // both accept 33 and "x5chain" keys. If both 33 (integer) and "x5chain"
  // (string) keys are present, the label 33 should be used.
  auto certificate_chain = headers.GetByteString(kCertificateChainKey);
  if (!certificate_chain.ok()) {
    certificate_chain = headers.GetByteString(kCertificateChainDeprecatedKey);
  }
  if (certificate_chain.ok()) {
    return std::vector<std::string>({std::string(*certificate_chain)});
  }
  // Check if there is a list of certificates in the chain. In this case, label
  // 33 of the header map (or "x5chain" key) is an array of bstrs.
  auto certificate_chain_array = headers.GetArray(kCertificateChainKey);
  if (!certificate_chain_array.ok()) {
    certificate_chain_array = headers.GetArray(kCertificateChainDeprecatedKey);
  }
  if (certificate_chain_array.ok()) {
    std::vector<std::string> certificate_chain;
    for (int i = 0; i < certificate_chain_array->size(); ++i) {
      auto certificate_chain_element =
          certificate_chain_array->GetByteString(i);
      if (!certificate_chain_element.ok()) {
        return absl::InvalidArgumentError(
            absl::StrCat("Failed to parse the certificate chain element: ",
                         certificate_chain_element.status()));
      }
      ABSL_DVLOG(1) << ".certs_b64[" << i << "] = R\"("
                    << absl::Base64Escape(*certificate_chain_element) << ")\",";
      certificate_chain.push_back(std::string(*certificate_chain_element));
    }
    return certificate_chain;
  }
  return std::vector<std::string>();
}

std::vector<std::string> DecodeOcspResponses(cbor::MapView map) {
  auto rvals = map.GetOptionalMap(kRvalsKey);
  if (!rvals.has_value()) {
    return {};
  }
  auto ocsp_responses = rvals->GetArray(kOcspValsKey);
  if (!ocsp_responses.ok()) {
    return {};
  }
  std::vector<std::string> v;
  v.reserve(ocsp_responses->size());
  for (int i = 0; i < ocsp_responses->size(); ++i) {
    auto ocsp_response = ocsp_responses->GetByteString(i);
    if (ocsp_response.ok()) {
      v.push_back(std::string(*ocsp_response));
    }
  }
  return v;
}

}  // namespace

absl::StatusOr<std::string> EncodeProtectedHeader(
    const ProtectedHeader& protected_header) {
  cppbor::Map m;
  ABSL_ASSIGN_OR_RETURN(auto alg, GetAlgorithm(protected_header.alg));
  m.add(cppbor::Uint(kSigningAlgorithmKey), cppbor::Nint(alg));
  if (protected_header.certificate_chain.size() == 1) {
    m.add(cppbor::Uint(kCertificateChainKey),
          cppbor::Bstr(protected_header.certificate_chain[0]));
  } else {
    cppbor::Array chain;
    for (const auto& cert : protected_header.certificate_chain) {
      chain.add(cppbor::Bstr(cert));
    }
    m.add(cppbor::Uint(kCertificateChainKey), std::move(chain));
  }
  return m.toString();
}

absl::StatusOr<ProtectedHeader> DecodeProtectedHeader(absl::string_view cbor) {
  ProtectedHeader protected_header;
  ABSL_ASSIGN_OR_RETURN(auto res, cbor::Parse(cbor));
  ABSL_ASSIGN_OR_RETURN(auto map, res->AsMap());
  ABSL_ASSIGN_OR_RETURN(auto alg, GetSigningAlgorithm(map));
  protected_header.alg = alg;

  ABSL_ASSIGN_OR_RETURN(auto certificate_chain, GetCertificateChain(map));
  protected_header.certificate_chain = std::move(certificate_chain);
  return protected_header;
}

void EncodeTstToken(const TstToken& tst_token, cppbor::Map& m) {
  m.add(cppbor::Tstr("val"), cppbor::Bstr(tst_token.val));
}

absl::StatusOr<TstToken> DecodeTstToken(cbor::MapView map) {
  ABSL_ASSIGN_OR_RETURN(auto val, map.GetByteString("val"));
  return TstToken{.val = std::string(val)};
}

void EncodeTstContainer(const TstContainer& tst_container, cppbor::Map& m) {
  cppbor::Array tstTokens;
  for (const auto& tstToken : tst_container.tst_tokens) {
    cppbor::Map tstTokenMap;
    EncodeTstToken(tstToken, tstTokenMap);
    tstTokens.add(std::move(tstTokenMap));
  }
  m.add(cppbor::Tstr("tstTokens"), std::move(tstTokens));
}

absl::StatusOr<TstContainer> DecodeTstContainer(cbor::MapView map) {
  ABSL_ASSIGN_OR_RETURN(auto tst_tokens, map.GetArray("tstTokens"));
  TstContainer tst_container;
  for (int i = 0; i < tst_tokens.size(); ++i) {
    ABSL_ASSIGN_OR_RETURN(auto tst_token, tst_tokens.GetMap(i));
    ABSL_ASSIGN_OR_RETURN(auto tst_token_decoded, DecodeTstToken(tst_token));
    tst_container.tst_tokens.push_back(std::move(tst_token_decoded));
  }
  return tst_container;
}

void EncodeUnprotectedHeader(const UnprotectedHeader& unprotected_header,
                             cppbor::Map& m) {
  if (unprotected_header.sig_tst2.has_value()) {
    cppbor::Map tstContainer;
    EncodeTstContainer(*unprotected_header.sig_tst2, tstContainer);
    m.add(cppbor::Tstr(kTimestampV2HeaderKey), std::move(tstContainer));
  }
  if (!unprotected_header.ocsp_responses.empty()) {
    cppbor::Array ocsp_responses;
    for (const auto& ocsp_response : unprotected_header.ocsp_responses) {
      ocsp_responses.add(cppbor::Bstr(ocsp_response));
    }
    cppbor::Map rvals;
    rvals.add(cppbor::Tstr(kOcspValsKey), std::move(ocsp_responses));
    m.add(cppbor::Tstr(kRvalsKey), std::move(rvals));
  }
  if (unprotected_header.pad.has_value()) {
    m.add(cppbor::Tstr(kPadHeaderKey), cppbor::Bstr(*unprotected_header.pad));
  }
  if (unprotected_header.pad2.has_value()) {
    m.add(cppbor::Tstr(kPad2HeaderKey), cppbor::Bstr(*unprotected_header.pad2));
  }
}

absl::StatusOr<UnprotectedHeader> DecodeUnprotectedHeader(cbor::MapView map) {
  UnprotectedHeader unprotected_header;
  auto sig_tst2 = map.GetOptionalMap(kTimestampV2HeaderKey);
  if (sig_tst2.has_value()) {
    ABSL_ASSIGN_OR_RETURN(unprotected_header.sig_tst2,
                          DecodeTstContainer(*sig_tst2));
  }
  auto sig_tst = map.GetOptionalMap(kTimestampV1HeaderKey);
  if (sig_tst.has_value()) {
    ABSL_ASSIGN_OR_RETURN(unprotected_header.sig_tst,
                          DecodeTstContainer(*sig_tst));
  }
  unprotected_header.ocsp_responses = DecodeOcspResponses(map);
  auto pad = map.GetOptionalByteString(kPadHeaderKey);
  if (pad.has_value()) {
    unprotected_header.pad = std::string(*pad);
  }
  auto pad2 = map.GetOptionalByteString(kPad2HeaderKey);
  if (pad2.has_value()) {
    unprotected_header.pad2 = std::string(*pad2);
  }
  auto certificate_chain = GetCertificateChain(map);
  if (certificate_chain.ok()) {
    unprotected_header.certificate_chain = *std::move(certificate_chain);
  }
  return unprotected_header;
}

std::string EncodeSig1Structure(const Sig1Structure& sig_structure) {
  cppbor::Array s;
  s.add(cppbor::Tstr(sig_structure.context));
  s.add(cppbor::Bstr(sig_structure.body_protected));
  s.add(cppbor::Bstr(sig_structure.external_aad));
  s.add(cppbor::Bstr(sig_structure.payload));
  return s.toString();
}

std::string EncodeCoseSign1TaggedStructure(const CoseSign1TaggedStructure& s) {
  cppbor::Array array;
  // Add protected_header.
  array.add(cppbor::Bstr(s.protected_header));
  // Add unprotected_header.
  cppbor::Map unprotected_header_map;
  EncodeUnprotectedHeader(s.unprotected_header, unprotected_header_map);
  array.add(std::move(unprotected_header_map));
  // Add payload.
  if (s.payload.has_value()) {
    array.add(cppbor::Bstr(*s.payload));
  } else {
    array.add(cppbor::Null());
  }
  // Add signature.
  array.add(cppbor::Bstr(s.signature));
  // tag 18 see https://datatracker.ietf.org/doc/html/rfc8152#section-4.2
  cppbor::SemanticTag tagged_cbor(18, std::move(array));
  return tagged_cbor.toString();
}

absl::StatusOr<CoseSign1TaggedStructure> DecodeCoseSign1TaggedStructure(
    absl::string_view cbor) {
  // COSE_Sign1 structure is a CBOR array of size 4.
  // CDDL schema for the case of a single signer is:
  //
  // COSE_Sign1 = [
  //     protected: bstr,
  //     unprotected: map,
  //     payload: bstr / nil,
  //     signature: bstr
  // ]
  //
  // See https://datatracker.ietf.org/doc/html/rfc9052 for more
  // details.
  ABSL_ASSIGN_OR_RETURN(auto res, cbor::Parse(cbor));
  ABSL_ASSIGN_OR_RETURN(auto array, res->AsArray());
  CoseSign1TaggedStructure s;
  ABSL_ASSIGN_OR_RETURN(s.protected_header, array.GetByteString(0));
  ABSL_ASSIGN_OR_RETURN(auto unprotect_header_cbor, array.GetMap(1));
  ABSL_ASSIGN_OR_RETURN(s.unprotected_header,
                        DecodeUnprotectedHeader(unprotect_header_cbor));
  ABSL_ASSIGN_OR_RETURN(auto is_payload_null, array.IsNull(2));
  if (!is_payload_null) {
    ABSL_ASSIGN_OR_RETURN(auto payload, array.GetByteString(2));
    s.payload.emplace(payload);
  }

  // In COSE standard, there can also be an array of signatures instead of a
  // single signature, if there are multiple signers. However, in C2PA we will
  // always have a single signer.
  ABSL_ASSIGN_OR_RETURN(auto signature, array.GetByteString(3));
  s.signature = std::string(signature);
  return s;
}

std::string CoseSign1TaggedStructure::signature_bstr() const {
  return cppbor::Bstr(signature).toString();
}

}  // namespace credentio
