// Copyright 2017 The Cobalt 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/stl_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 DER SPKI "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};

// The SHA256 hash of the DER SPKI "ecdsa_2017_public" Crx3 test key.
constexpr uint8_t kPublisherTestKeyHash[] = {
    0x6c, 0x46, 0x41, 0x3b, 0x00, 0xd0, 0xfa, 0x0e, 0x72, 0xc8, 0xd2,
    0x5f, 0x64, 0xf3, 0xa6, 0x17, 0x03, 0x0d, 0xde, 0x21, 0x61, 0xbe,
    0xb7, 0x95, 0x91, 0x95, 0x83, 0x68, 0x12, 0xe9, 0x78, 0x1e};

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;
}
#if defined(IN_MEMORY_UPDATES)
int ReadAndHashBufferFromString(uint8_t* buffer,
                                int length,
                                std::string::const_iterator* it,
                                crypto::SecureHash* hash) {
  static_assert(sizeof(char) == sizeof(uint8_t), "Unsupported char size.");
  memcpy(buffer, &(**it), length);
  hash->Update(buffer, length);

  // TODO(b/158043520): consider wrapping the CRX string in a type that keeps
  // track of how much of the string has already been copied so that the string
  // can be "read" like a file, without direct management of the iterator.
  std::advance(*it, length);

  return length;
}
#endif

// 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];
}
#if defined(IN_MEMORY_UPDATES)
// Returns the read uint32.
uint32_t ReadAndHashLittleEndianUInt32FromString(
    std::string::const_iterator* it,
    crypto::SecureHash* hash) {
  uint8_t buffer[4] = {};
  ReadAndHashBufferFromString(buffer, sizeof(buffer), it, hash);
  return buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
}
#endif

// 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, base::size(buffer), file, hash)) >
         0) {
    for (auto& verifier : verifiers)
      verifier->VerifyUpdate(base::make_span(buffer, len));
  }
  for (auto& verifier : verifiers) {
    if (!verifier->VerifyFinal())
      return false;
  }
  return len == 0;
}
#if defined(IN_MEMORY_UPDATES)
// Reads to the end of the string, updating the hash and all verifiers.
bool ReadHashAndVerifyArchiveFromString(const std::string& crx_str,
                                        std::string::const_iterator* it,
                                        crypto::SecureHash* hash,
                                        const VerifierCollection& verifiers) {
  int remaining_bytes = crx_str.end() - *it;

  uint8_t buffer[1 << 12] = {};
  while (remaining_bytes > 0) {
    size_t len = remaining_bytes >= base::size(buffer) ? base::size(buffer)
                                                       : remaining_bytes;

    ReadAndHashBufferFromString(buffer, len, it, hash);
    remaining_bytes -= len;

    for (auto& verifier : verifiers) {
      verifier->VerifyUpdate(base::make_span(buffer, len));
    }
  }

  for (auto& verifier : verifiers) {
    if (!verifier->VerifyFinal())
      return false;
  }
  return true;
}
#endif

// 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,
    bool accept_publisher_test_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[] = {
      static_cast<uint8_t>(signed_header_size),
      static_cast<uint8_t>(signed_header_size >> 8),
      static_cast<uint8_t>(signed_header_size >> 16),
      static_cast<uint8_t>(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());

  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)};

  std::vector<uint8_t> publisher_key(std::begin(kPublisherKeyHash),
                                     std::end(kPublisherKeyHash));
  base::Optional<std::vector<uint8_t>> publisher_test_key;
  if (accept_publisher_test_key) {
    publisher_test_key.emplace(std::begin(kPublisherTestKeyHash),
                               std::end(kPublisherTestKeyHash));
  }
  bool found_publisher_key = false;

  // 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);
      DCHECK_EQ(accept_publisher_test_key, publisher_test_key.has_value());
      found_publisher_key =
          found_publisher_key || key_hash == publisher_key ||
          (accept_publisher_test_key && key_hash == *publisher_test_key);
      auto v = std::make_unique<crypto::SignatureVerifier>();
      static_assert(sizeof(unsigned char) == sizeof(uint8_t),
                    "Unsupported char size.");
      if (!v->VerifyInit(proof_type.second,
                         base::as_bytes(base::make_span(sig)),
                         base::as_bytes(base::make_span(key))))
        return VerifierResult::ERROR_SIGNATURE_INITIALIZATION_FAILED;
      v->VerifyUpdate(kSignatureContext);
      v->VerifyUpdate(header_size_octets);
      v->VerifyUpdate(base::as_bytes(base::make_span(signed_header_data_str)));
      verifiers.push_back(std::move(v));
    }
  }
  if (public_key_bytes.empty() || !required_key_set.empty())
    return VerifierResult::ERROR_REQUIRED_PROOF_MISSING;

  if (require_publisher_key && !found_publisher_key)
    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;
}

#if defined(IN_MEMORY_UPDATES)
// TODO(b/158043520): because we want to leave the Chromium code relatively
// intact and also want to support both in-memory and legacy updates in the same
// build while we develop the feature, there is for now a lot of duplicated code
// in some of these functions. For these functions that implement longer
// algorithms that are mostly agnostic about the Crx's representation we could
// likely share code by making them generic, but it probably makes more sense to
// live with the duplication for now. Once the feature is complete and we only
// need to support in-memory updates in builds, we can have one copy of the
// function that uses preprocessor conditions to enlist the appropriate helpers.
VerifierResult VerifyCrx3FromString(
    const std::string& crx_str,
    std::string::const_iterator* it,
    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,
    bool accept_publisher_test_key) {
  // Parse [header-size] and [header].
  const uint32_t header_size =
      ReadAndHashLittleEndianUInt32FromString(it, 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 (ReadAndHashBufferFromString(header_bytes.data(), header_size, it, 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[] = {
      static_cast<uint8_t>(signed_header_size),
      static_cast<uint8_t>(signed_header_size >> 8),
      static_cast<uint8_t>(signed_header_size >> 16),
      static_cast<uint8_t>(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());

  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)};

  std::vector<uint8_t> publisher_key(std::begin(kPublisherKeyHash),
                                     std::end(kPublisherKeyHash));
  base::Optional<std::vector<uint8_t>> publisher_test_key;
  if (accept_publisher_test_key) {
    publisher_test_key.emplace(std::begin(kPublisherTestKeyHash),
                               std::end(kPublisherTestKeyHash));
  }
  bool found_publisher_key = false;

  // 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);
      DCHECK_EQ(accept_publisher_test_key, publisher_test_key.has_value());
      found_publisher_key =
          found_publisher_key || key_hash == publisher_key ||
          (accept_publisher_test_key && key_hash == *publisher_test_key);
      auto v = std::make_unique<crypto::SignatureVerifier>();
      static_assert(sizeof(unsigned char) == sizeof(uint8_t),
                    "Unsupported char size.");
      if (!v->VerifyInit(proof_type.second,
                         base::as_bytes(base::make_span(sig)),
                         base::as_bytes(base::make_span(key))))
        return VerifierResult::ERROR_SIGNATURE_INITIALIZATION_FAILED;
      v->VerifyUpdate(kSignatureContext);
      v->VerifyUpdate(header_size_octets);
      v->VerifyUpdate(base::as_bytes(base::make_span(signed_header_data_str)));
      verifiers.push_back(std::move(v));
    }
  }
  if (public_key_bytes.empty() || !required_key_set.empty())
    return VerifierResult::ERROR_REQUIRED_PROOF_MISSING;

  if (require_publisher_key && !found_publisher_key)
    return VerifierResult::ERROR_REQUIRED_PROOF_MISSING;

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

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

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(std::make_unique<crypto::SignatureVerifier>());
  if (!verifiers[0]->VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, sig,
                                key)) {
    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;
}

#if defined(IN_MEMORY_UPDATES)
VerifierResult VerifyCrx2FromString(
    const std::string& crx_str,
    std::string::const_iterator* it,
    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 = ReadAndHashLittleEndianUInt32FromString(it, hash);
  if (key_size > kMaxPublicKeySize)
    return VerifierResult::ERROR_HEADER_INVALID;
  const uint32_t sig_size = ReadAndHashLittleEndianUInt32FromString(it, hash);
  if (sig_size > kMaxSignatureSize)
    return VerifierResult::ERROR_HEADER_INVALID;
  std::vector<uint8_t> key(key_size);
  if (ReadAndHashBufferFromString(key.data(), key_size, it, 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 (ReadAndHashBufferFromString(sig.data(), sig_size, it, hash) !=
      static_cast<int>(sig_size))
    return VerifierResult::ERROR_HEADER_INVALID;
  std::vector<std::unique_ptr<crypto::SignatureVerifier>> verifiers;
  verifiers.push_back(std::make_unique<crypto::SignatureVerifier>());
  if (!verifiers[0]->VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, sig,
                                key)) {
    return VerifierResult::ERROR_SIGNATURE_INITIALIZATION_FAILED;
  }

  if (!ReadHashAndVerifyArchiveFromString(crx_str, it, 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;
}
#endif

}  // 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 (version == 2)
    LOG(WARNING) << "File '" << crx_path
                 << "' is in CRX2 format, which is deprecated and will not be "
                    "supported in M78+";
  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) {
    bool require_publisher_key =
        format == VerifierFormat::CRX3_WITH_PUBLISHER_PROOF ||
        format == VerifierFormat::CRX3_WITH_TEST_PUBLISHER_PROOF;
    result =
        VerifyCrx3(&file, file_hash.get(), required_key_hashes,
                   &public_key_local, &crx_id_local, require_publisher_key,
                   format == VerifierFormat::CRX3_WITH_TEST_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;
}

#if defined(IN_MEMORY_UPDATES)
VerifierResult Verify(
    const std::string& crx_str,
    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;

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

  // Magic number.
  bool diff = false;
  if (!strncmp(crx_str.c_str(), kCrxDiffFileHeaderMagic,
               kCrxFileHeaderMagicSize)) {
    diff = true;
  } else if (strncmp(crx_str.c_str(), kCrxFileHeaderMagic,
                     kCrxFileHeaderMagicSize)) {
    return VerifierResult::ERROR_HEADER_INVALID;
  }
  file_hash->Update(crx_str.c_str(), kCrxFileHeaderMagicSize);

  std::string::const_iterator it = crx_str.begin();
  // Advance the iterator past the magic string embedded in the header.
  std::advance(it, kCrxFileHeaderMagicSize);

  // Version number.
  const uint32_t version =
      ReadAndHashLittleEndianUInt32FromString(&it, file_hash.get());
  VerifierResult result;
  if (version == 2)
    SB_LOG(WARNING) << "The string is in CRX2 format, which is deprecated and "
                    << "will not be supported in M78+";
  if (format == VerifierFormat::CRX2_OR_CRX3 &&
      (version == 2 || (diff && version == 0))) {
    result =
        VerifyCrx2FromString(crx_str, &it, file_hash.get(), required_key_hashes,
                             &public_key_local, &crx_id_local);
  } else if (version == 3) {
    bool require_publisher_key =
        format == VerifierFormat::CRX3_WITH_PUBLISHER_PROOF ||
        format == VerifierFormat::CRX3_WITH_TEST_PUBLISHER_PROOF;
    result = VerifyCrx3FromString(
        crx_str, &it, file_hash.get(), required_key_hashes, &public_key_local,
        &crx_id_local, require_publisher_key,
        format == VerifierFormat::CRX3_WITH_TEST_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;
}
#endif

}  // namespace crx_file
