// Copyright 2017 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 "components/crx_file/crx_verifier.h"

#include <cstring>
#include <iterator>
#include <memory>
#include <set>
#include <utility>

#include "base/base64.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "components/crx_file/crx3.pb.h"
#include "components/crx_file/crx_file.h"
#include "components/crx_file/id_util.h"
#include "crypto/secure_hash.h"
#include "crypto/secure_util.h"
#include "crypto/sha2.h"
#include "crypto/signature_verifier.h"

namespace crx_file {

namespace {

// The maximum size the Crx2 parser will tolerate for a public key.
constexpr uint32_t kMaxPublicKeySize = 1 << 16;

// The maximum size the Crx2 parser will tolerate for a signature.
constexpr uint32_t kMaxSignatureSize = 1 << 16;

// The maximum size the Crx3 parser will tolerate for a header.
constexpr uint32_t kMaxHeaderSize = 1 << 18;

// The SHA256 hash of the "ecdsa_2017_public" Crx3 key.
constexpr uint8_t kPublisherKeyHash[] = {
    0x61, 0xf7, 0xf2, 0xa6, 0xbf, 0xcf, 0x74, 0xcd, 0x0b, 0xc1, 0xfe,
    0x24, 0x97, 0xcc, 0x9b, 0x04, 0x25, 0x4c, 0x65, 0x8f, 0x79, 0xf2,
    0x14, 0x53, 0x92, 0x86, 0x7e, 0xa8, 0x36, 0x63, 0x67, 0xcf};

using VerifierCollection =
    std::vector<std::unique_ptr<crypto::SignatureVerifier>>;
using RepeatedProof = google::protobuf::RepeatedPtrField<AsymmetricKeyProof>;

int ReadAndHashBuffer(uint8_t* buffer,
                      int length,
                      base::File* file,
                      crypto::SecureHash* hash) {
  static_assert(sizeof(char) == sizeof(uint8_t), "Unsupported char size.");
  int read = file->ReadAtCurrentPos(reinterpret_cast<char*>(buffer), length);
  if (read > 0)
    hash->Update(buffer, read);
  return read;
}

// Returns UINT32_MAX in the case of an unexpected EOF or read error, else
// returns the read uint32.
uint32_t ReadAndHashLittleEndianUInt32(base::File* file,
                                       crypto::SecureHash* hash) {
  uint8_t buffer[4] = {};
  if (ReadAndHashBuffer(buffer, 4, file, hash) != 4)
    return UINT32_MAX;
  return buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
}

// Read to the end of the file, updating the hash and all verifiers.
bool ReadHashAndVerifyArchive(base::File* file,
                              crypto::SecureHash* hash,
                              const VerifierCollection& verifiers) {
  uint8_t buffer[1 << 12] = {};
  size_t len = 0;
  while ((len = ReadAndHashBuffer(buffer, arraysize(buffer), file, hash)) > 0) {
    for (auto& verifier : verifiers)
      verifier->VerifyUpdate(buffer, len);
  }
  for (auto& verifier : verifiers) {
    if (!verifier->VerifyFinal())
      return false;
  }
  return len == 0;
}

// The remaining contents of a Crx3 file are [header-size][header][archive].
// [header] is an encoded protocol buffer and contains both a signed and
// unsigned section. The unsigned section contains a set of key/signature pairs,
// and the signed section is the encoding of another protocol buffer. All
// signatures cover [prefix][signed-header-size][signed-header][archive].
VerifierResult VerifyCrx3(
    base::File* file,
    crypto::SecureHash* hash,
    const std::vector<std::vector<uint8_t>>& required_key_hashes,
    std::string* public_key,
    std::string* crx_id,
    bool require_publisher_key) {
  // Parse [header-size] and [header].
  const uint32_t header_size = ReadAndHashLittleEndianUInt32(file, hash);
  if (header_size > kMaxHeaderSize)
    return VerifierResult::ERROR_HEADER_INVALID;
  std::vector<uint8_t> header_bytes(header_size);
  // Assuming kMaxHeaderSize can fit in an int, the following cast is safe.
  if (ReadAndHashBuffer(header_bytes.data(), header_size, file, hash) !=
      static_cast<int>(header_size))
    return VerifierResult::ERROR_HEADER_INVALID;
  CrxFileHeader header;
  if (!header.ParseFromArray(header_bytes.data(), header_size))
    return VerifierResult::ERROR_HEADER_INVALID;

  // Parse [signed-header].
  const std::string& signed_header_data_str = header.signed_header_data();
  SignedData signed_header_data;
  if (!signed_header_data.ParseFromString(signed_header_data_str))
    return VerifierResult::ERROR_HEADER_INVALID;
  const std::string& crx_id_encoded = signed_header_data.crx_id();
  const std::string declared_crx_id = id_util::GenerateIdFromHex(
      base::HexEncode(crx_id_encoded.data(), crx_id_encoded.size()));

  // Create a little-endian representation of [signed-header-size].
  const int signed_header_size = signed_header_data_str.size();
  const uint8_t header_size_octets[] = {
      signed_header_size, signed_header_size >> 8, signed_header_size >> 16,
      signed_header_size >> 24};

  // Create a set of all required key hashes.
  std::set<std::vector<uint8_t>> required_key_set(required_key_hashes.begin(),
                                                  required_key_hashes.end());
  if (require_publisher_key) {
    required_key_set.emplace(std::begin(kPublisherKeyHash),
                             std::end(kPublisherKeyHash));
  }

  using ProofFetcher = const RepeatedProof& (CrxFileHeader::*)() const;
  ProofFetcher rsa = &CrxFileHeader::sha256_with_rsa;
  ProofFetcher ecdsa = &CrxFileHeader::sha256_with_ecdsa;

  std::string public_key_bytes;
  VerifierCollection verifiers;
  verifiers.reserve(header.sha256_with_rsa_size() +
                    header.sha256_with_ecdsa_size());
  const std::vector<
      std::pair<ProofFetcher, crypto::SignatureVerifier::SignatureAlgorithm>>
      proof_types = {
          std::make_pair(rsa, crypto::SignatureVerifier::RSA_PKCS1_SHA256),
          std::make_pair(ecdsa, crypto::SignatureVerifier::ECDSA_SHA256)};

  // Initialize all verifiers and update them with
  // [prefix][signed-header-size][signed-header].
  // Clear any elements of required_key_set that are encountered, and watch for
  // the developer key.
  for (const auto& proof_type : proof_types) {
    for (const auto& proof : (header.*proof_type.first)()) {
      const std::string& key = proof.public_key();
      const std::string& sig = proof.signature();
      if (id_util::GenerateId(key) == declared_crx_id)
        public_key_bytes = key;
      std::vector<uint8_t> key_hash(crypto::kSHA256Length);
      crypto::SHA256HashString(key, key_hash.data(), key_hash.size());
      required_key_set.erase(key_hash);
      auto v = base::MakeUnique<crypto::SignatureVerifier>();
      static_assert(sizeof(unsigned char) == sizeof(uint8_t),
                    "Unsupported char size.");
      if (!v->VerifyInit(
              proof_type.second, reinterpret_cast<const uint8_t*>(sig.data()),
              sig.size(), reinterpret_cast<const uint8_t*>(key.data()),
              key.size()))
        return VerifierResult::ERROR_SIGNATURE_INITIALIZATION_FAILED;
      v->VerifyUpdate(kSignatureContext, arraysize(kSignatureContext));
      v->VerifyUpdate(header_size_octets, arraysize(header_size_octets));
      v->VerifyUpdate(
          reinterpret_cast<const uint8_t*>(signed_header_data_str.data()),
          signed_header_data_str.size());
      verifiers.push_back(std::move(v));
    }
  }
  if (public_key_bytes.empty() || !required_key_set.empty())
    return VerifierResult::ERROR_REQUIRED_PROOF_MISSING;

  // Update and finalize the verifiers with [archive].
  if (!ReadHashAndVerifyArchive(file, hash, verifiers))
    return VerifierResult::ERROR_SIGNATURE_VERIFICATION_FAILED;

  base::Base64Encode(public_key_bytes, public_key);
  *crx_id = declared_crx_id;
  return VerifierResult::OK_FULL;
}

VerifierResult VerifyCrx2(
    base::File* file,
    crypto::SecureHash* hash,
    const std::vector<std::vector<uint8_t>>& required_key_hashes,
    std::string* public_key,
    std::string* crx_id) {
  const uint32_t key_size = ReadAndHashLittleEndianUInt32(file, hash);
  if (key_size > kMaxPublicKeySize)
    return VerifierResult::ERROR_HEADER_INVALID;
  const uint32_t sig_size = ReadAndHashLittleEndianUInt32(file, hash);
  if (sig_size > kMaxSignatureSize)
    return VerifierResult::ERROR_HEADER_INVALID;
  std::vector<uint8_t> key(key_size);
  if (ReadAndHashBuffer(key.data(), key_size, file, hash) !=
      static_cast<int>(key_size))
    return VerifierResult::ERROR_HEADER_INVALID;
  for (const auto& expected_hash : required_key_hashes) {
    // In practice we expect zero or one key_hashes_ for Crx2 files.
    std::vector<uint8_t> hash(crypto::kSHA256Length);
    std::unique_ptr<crypto::SecureHash> sha256 =
        crypto::SecureHash::Create(crypto::SecureHash::SHA256);
    sha256->Update(key.data(), key.size());
    sha256->Finish(hash.data(), hash.size());
    if (hash != expected_hash)
      return VerifierResult::ERROR_REQUIRED_PROOF_MISSING;
  }

  std::vector<uint8_t> sig(sig_size);
  if (ReadAndHashBuffer(sig.data(), sig_size, file, hash) !=
      static_cast<int>(sig_size))
    return VerifierResult::ERROR_HEADER_INVALID;
  std::vector<std::unique_ptr<crypto::SignatureVerifier>> verifiers;
  verifiers.push_back(base::MakeUnique<crypto::SignatureVerifier>());
  if (!verifiers[0]->VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1,
                                sig.data(), sig.size(), key.data(),
                                key.size())) {
    return VerifierResult::ERROR_SIGNATURE_INITIALIZATION_FAILED;
  }

  if (!ReadHashAndVerifyArchive(file, hash, verifiers))
    return VerifierResult::ERROR_SIGNATURE_VERIFICATION_FAILED;

  const std::string public_key_bytes(key.begin(), key.end());
  base::Base64Encode(public_key_bytes, public_key);
  *crx_id = id_util::GenerateId(public_key_bytes);
  return VerifierResult::OK_FULL;
}

}  // namespace

VerifierResult Verify(
    const base::FilePath& crx_path,
    const VerifierFormat& format,
    const std::vector<std::vector<uint8_t>>& required_key_hashes,
    const std::vector<uint8_t>& required_file_hash,
    std::string* public_key,
    std::string* crx_id) {
  std::string public_key_local;
  std::string crx_id_local;
  base::File file(crx_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!file.IsValid())
    return VerifierResult::ERROR_FILE_NOT_READABLE;

  std::unique_ptr<crypto::SecureHash> file_hash =
      crypto::SecureHash::Create(crypto::SecureHash::SHA256);

  // Magic number.
  bool diff = false;
  char buffer[kCrxFileHeaderMagicSize] = {};
  if (file.ReadAtCurrentPos(buffer, kCrxFileHeaderMagicSize) !=
      kCrxFileHeaderMagicSize)
    return VerifierResult::ERROR_HEADER_INVALID;
  if (!strncmp(buffer, kCrxDiffFileHeaderMagic, kCrxFileHeaderMagicSize))
    diff = true;
  else if (strncmp(buffer, kCrxFileHeaderMagic, kCrxFileHeaderMagicSize))
    return VerifierResult::ERROR_HEADER_INVALID;
  file_hash->Update(buffer, sizeof(buffer));

  // Version number.
  const uint32_t version =
      ReadAndHashLittleEndianUInt32(&file, file_hash.get());
  VerifierResult result;
  if (format == VerifierFormat::CRX2_OR_CRX3 &&
      (version == 2 || (diff && version == 0)))
    result = VerifyCrx2(&file, file_hash.get(), required_key_hashes,
                        &public_key_local, &crx_id_local);
  else if (version == 3)
    result = VerifyCrx3(&file, file_hash.get(), required_key_hashes,
                        &public_key_local, &crx_id_local,
                        format == VerifierFormat::CRX3_WITH_PUBLISHER_PROOF);
  else
    result = VerifierResult::ERROR_HEADER_INVALID;
  if (result != VerifierResult::OK_FULL)
    return result;

  // Finalize file hash.
  uint8_t final_hash[crypto::kSHA256Length] = {};
  file_hash->Finish(final_hash, sizeof(final_hash));
  if (!required_file_hash.empty()) {
    if (required_file_hash.size() != crypto::kSHA256Length)
      return VerifierResult::ERROR_EXPECTED_HASH_INVALID;
    if (!crypto::SecureMemEqual(final_hash, required_file_hash.data(),
                                crypto::kSHA256Length))
      return VerifierResult::ERROR_FILE_HASH_FAILED;
  }

  // All is well. Set the out-params and return.
  if (public_key)
    *public_key = public_key_local;
  if (crx_id)
    *crx_id = crx_id_local;
  return diff ? VerifierResult::OK_DELTA : VerifierResult::OK_FULL;
}

}  // namespace crx_file
