// Copyright 2021 The Pigweed Authors
//
// 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.

#define PW_LOG_MODULE_NAME "PWSU"
#define PW_LOG_LEVEL PW_LOG_LEVEL_WARN

#include "pw_software_update/update_bundle_accessor.h"

#include <cstddef>
#include <cstring>
#include <string_view>

#include "pw_crypto/ecdsa.h"
#include "pw_crypto/sha256.h"
#include "pw_log/log.h"
#include "pw_protobuf/message.h"
#include "pw_result/result.h"
#include "pw_software_update/config.h"
#include "pw_software_update/manifest_accessor.h"
#include "pw_software_update/update_bundle.pwpb.h"
#include "pw_stream/interval_reader.h"
#include "pw_stream/memory_stream.h"
#include "pw_string/string_builder.h"

namespace pw::software_update {
namespace {

Result<bool> VerifyEcdsaSignature(protobuf::Bytes public_key,
                                  ConstByteSpan digest,
                                  protobuf::Bytes signature) {
  // TODO(b/237580538): Move this logic into an variant of the API in
  // pw_crypto:ecdsa that takes readers as inputs.
  std::byte public_key_bytes[65];
  std::byte signature_bytes[64];
  stream::IntervalReader key_reader = public_key.GetBytesReader();
  stream::IntervalReader sig_reader = signature.GetBytesReader();
  PW_TRY(key_reader.Read(public_key_bytes));
  PW_TRY(sig_reader.Read(signature_bytes));
  Status status = crypto::ecdsa::VerifyP256Signature(
      public_key_bytes, digest, signature_bytes);
  if (!status.ok()) {
    return false;
  }

  return true;
}

// Convert an integer from [0, 16) to a hex char
char IntToHex(uint8_t val) {
  PW_ASSERT(val < 16);
  return val >= 10 ? (val - 10) + 'a' : val + '0';
}

void LogKeyId(ConstByteSpan key_id) {
  char key_id_str[pw::crypto::sha256::kDigestSizeBytes * 2 + 1] = {0};
  for (size_t i = 0; i < pw::crypto::sha256::kDigestSizeBytes; i++) {
    uint8_t value = std::to_integer<uint8_t>(key_id[i]);
    key_id_str[i * 2] = IntToHex((value >> 4) & 0xf);
    key_id_str[i * 2 + 1] = IntToHex(value & 0xf);
  }

  PW_LOG_DEBUG("key_id: %s", key_id_str);
}

// Verifies signatures of a TUF metadata.
Status VerifyMetadataSignatures(protobuf::Bytes message,
                                protobuf::RepeatedMessages signatures,
                                protobuf::Message signature_requirement,
                                protobuf::StringToMessageMap key_mapping) {
  // Gets the threshold -- at least `threshold` number of signatures must
  // pass verification in order to trust this metadata.
  protobuf::Uint32 threshold = signature_requirement.AsUint32(
      static_cast<uint32_t>(SignatureRequirement::Fields::THRESHOLD));
  PW_TRY(threshold.status());

  // Gets the ids of keys that are allowed for verifying the signatures.
  protobuf::RepeatedBytes allowed_key_ids =
      signature_requirement.AsRepeatedBytes(
          static_cast<uint32_t>(SignatureRequirement::Fields::KEY_IDS));
  PW_TRY(allowed_key_ids.status());

  // Verifies the signatures. Check that at least `threshold` number of
  // signatures can be verified using the allowed keys.
  size_t verified_count = 0;
  size_t total_signatures = 0;
  for (protobuf::Message signature : signatures) {
    total_signatures++;
    protobuf::Bytes key_id =
        signature.AsBytes(static_cast<uint32_t>(Signature::Fields::KEY_ID));
    PW_TRY(key_id.status());

    // Reads the key id into a buffer, so that we can check whether it is
    // listed as allowed and look up the key value later.
    std::byte key_id_buf[pw::crypto::sha256::kDigestSizeBytes];
    stream::IntervalReader key_id_reader = key_id.GetBytesReader();
    Result<ByteSpan> key_id_read_res = key_id_reader.Read(key_id_buf);
    PW_TRY(key_id_read_res.status());
    if (key_id_read_res.value().size() != sizeof(key_id_buf)) {
      return Status::Internal();
    }

    // Verify that the `key_id` is listed in `allowed_key_ids`.
    // Note that the function assumes that the key id is properly derived
    // from the key (via sha256).
    bool key_id_is_allowed = false;
    for (protobuf::Bytes trusted : allowed_key_ids) {
      Result<bool> key_id_equal = trusted.Equal(key_id_buf);
      PW_TRY(key_id_equal.status());
      if (key_id_equal.value()) {
        key_id_is_allowed = true;
        break;
      }
    }

    if (!key_id_is_allowed) {
      PW_LOG_DEBUG("Skipping a key id not listed in allowed key ids");
      LogKeyId(key_id_buf);
      continue;
    }

    // Retrieves the signature bytes.
    protobuf::Bytes sig =
        signature.AsBytes(static_cast<uint32_t>(Signature::Fields::SIG));
    PW_TRY(sig.status());

    // Extracts the key type, scheme and value information.
    std::string_view key_id_str(reinterpret_cast<const char*>(key_id_buf),
                                sizeof(key_id_buf));
    protobuf::Message key_info = key_mapping[key_id_str];
    PW_TRY(key_info.status());

    protobuf::Bytes key_val =
        key_info.AsBytes(static_cast<uint32_t>(Key::Fields::KEYVAL));
    PW_TRY(key_val.status());

    // The function assume that all keys are ECDSA keys. This is guaranteed
    // by the fact that all trusted roots have undergone content check.

    // computes the sha256 hash
    std::byte sha256_digest[32];
    stream::IntervalReader bytes_reader = message.GetBytesReader();
    PW_TRY(crypto::sha256::Hash(bytes_reader, sha256_digest));
    Result<bool> res = VerifyEcdsaSignature(key_val, sha256_digest, sig);
    PW_TRY(res.status());
    if (res.value()) {
      verified_count++;
      if (verified_count == threshold.value()) {
        return OkStatus();
      }
    }
  }

  if (total_signatures == 0) {
    // For self verification to tell apart unsigned bundles.
    return Status::NotFound();
  }

  PW_LOG_ERROR("Insufficient signatures. Requires at least %u, verified %zu",
               threshold.value(),
               verified_count);
  return Status::Unauthenticated();
}

// Verifies the signatures of a signed new root metadata against a given
// trusted root. The helper function extracts the corresponding key maping
// signature requirement, signatures from the trusted root and passes them
// to VerifyMetadataSignatures().
//
// Precondition: The trusted root metadata has undergone content validity check.
Result<bool> VerifyRootMetadataSignatures(protobuf::Message trusted_root,
                                          protobuf::Message new_root) {
  // Retrieves the trusted root metadata content message.
  protobuf::Message trusted = trusted_root.AsMessage(static_cast<uint32_t>(
      SignedRootMetadata::Fields::SERIALIZED_ROOT_METADATA));
  PW_TRY(trusted.status());

  // Retrieves the serialized new root metadata bytes.
  protobuf::Bytes serialized = new_root.AsBytes(static_cast<uint32_t>(
      SignedRootMetadata::Fields::SERIALIZED_ROOT_METADATA));
  PW_TRY(serialized.status());

  // Gets the key mapping from the trusted root metadata.
  protobuf::StringToMessageMap key_mapping = trusted.AsStringToMessageMap(
      static_cast<uint32_t>(RootMetadata::Fields::KEYS));
  PW_TRY(key_mapping.status());

  // Gets the signatures of the new root.
  protobuf::RepeatedMessages signatures = new_root.AsRepeatedMessages(
      static_cast<uint32_t>(SignedRootMetadata::Fields::SIGNATURES));
  PW_TRY(signatures.status());

  // Gets the signature requirement from the trusted root metadata.
  protobuf::Message signature_requirement = trusted.AsMessage(
      static_cast<uint32_t>(RootMetadata::Fields::ROOT_SIGNATURE_REQUIREMENT));
  PW_TRY(signature_requirement.status());

  // Verifies the signatures.
  PW_TRY(VerifyMetadataSignatures(
      serialized, signatures, signature_requirement, key_mapping));
  return true;
}

Result<uint32_t> GetMetadataVersion(protobuf::Message& metadata,
                                    uint32_t common_metatdata_field_number) {
  // message [Root|Targets]Metadata {
  //   ...
  //   CommonMetadata common_metadata = <field_number>;
  //   ...
  // }
  //
  // message CommonMetadata {
  //   ...
  //   uint32 version = <field_number>;
  //   ...
  // }
  protobuf::Message common_metadata =
      metadata.AsMessage(common_metatdata_field_number);
  PW_TRY(common_metadata.status());
  protobuf::Uint32 res = common_metadata.AsUint32(
      static_cast<uint32_t>(software_update::CommonMetadata::Fields::VERSION));
  PW_TRY(res.status());
  return res.value();
}

// Reads a protobuf::String into a buffer and returns a std::string_view.
Result<std::string_view> ReadProtoString(protobuf::String str,
                                         span<char> buffer) {
  stream::IntervalReader reader = str.GetBytesReader();
  if (reader.interval_size() > buffer.size()) {
    return Status::ResourceExhausted();
  }

  Result<ByteSpan> res = reader.Read(as_writable_bytes(buffer));
  PW_TRY(res.status());
  return std::string_view(buffer.data(), res.value().size());
}

}  // namespace

Status UpdateBundleAccessor::OpenAndVerify() {
  if (Status status = DoOpen(); !status.ok()) {
    PW_LOG_ERROR("Failed to open staged bundle");
    return status;
  }

  if (Status status = DoVerify(); !status.ok()) {
    PW_LOG_ERROR("Failed to verified staged bundle");
    Close().IgnoreError();
    return status;
  }

  return OkStatus();
}

Result<uint64_t> UpdateBundleAccessor::GetTotalPayloadSize() {
  protobuf::RepeatedMessages manifested_targets =
      GetManifest().GetTargetFiles();
  PW_TRY(manifested_targets.status());

  protobuf::StringToBytesMap bundled_payloads = bundle_.AsStringToBytesMap(
      static_cast<uint32_t>(UpdateBundle::Fields::TARGET_PAYLOADS));
  PW_TRY(bundled_payloads.status());

  uint64_t total_bytes = 0;
  std::array<std::byte, MAX_TARGET_NAME_LENGTH> name_buffer = {};
  for (protobuf::Message target : manifested_targets) {
    protobuf::String target_name =
        target.AsString(static_cast<uint32_t>(TargetFile::Fields::FILE_NAME));

    stream::IntervalReader name_reader = target_name.GetBytesReader();
    PW_TRY(name_reader.status());
    if (name_reader.interval_size() > name_buffer.size()) {
      return Status::OutOfRange();
    }

    Result<ByteSpan> read_result = name_reader.Read(name_buffer);
    PW_TRY(read_result.status());

    ConstByteSpan name_span = read_result.value();
    std::string_view name_view(reinterpret_cast<const char*>(name_span.data()),
                               name_span.size_bytes());

    if (!bundled_payloads[name_view].ok()) {
      continue;
    }
    protobuf::Uint64 target_length =
        target.AsUint64(static_cast<uint32_t>(TargetFile::Fields::LENGTH));
    PW_TRY(target_length.status());
    total_bytes += target_length.value();
  }

  return total_bytes;
}

// Get the target element corresponding to `target_file`
stream::IntervalReader UpdateBundleAccessor::GetTargetPayload(
    std::string_view target_name) {
  protobuf::Message manifest_entry = GetManifest().GetTargetFile(target_name);
  PW_TRY(manifest_entry.status());

  protobuf::StringToBytesMap payloads_map = bundle_.AsStringToBytesMap(
      static_cast<uint32_t>(UpdateBundle::Fields::TARGET_PAYLOADS));
  return payloads_map[target_name].GetBytesReader();
}

// Get the target element corresponding to `target_file`
stream::IntervalReader UpdateBundleAccessor::GetTargetPayload(
    protobuf::String target_name) {
  char name_buf[MAX_TARGET_NAME_LENGTH] = {0};
  Result<std::string_view> name_view = ReadProtoString(target_name, name_buf);
  PW_TRY(name_view.status());
  return GetTargetPayload(name_view.value());
}

Status UpdateBundleAccessor::PersistManifest() {
  ManifestAccessor manifest = GetManifest();
  // GetManifest() fails if the bundle is yet to be verified.
  PW_TRY(manifest.status());

  // Notify backend to prepare to receive a new manifest.
  PW_TRY(backend_.BeforeManifestWrite());

  Result<stream::Writer*> writer = backend_.GetManifestWriter();
  PW_TRY(writer.status());
  PW_CHECK_NOTNULL(writer.value());

  PW_TRY(manifest.Export(*writer.value()));

  // Notify backend we are done writing. Backend should finalize
  // (seal the box).
  PW_TRY(backend_.AfterManifestWrite());

  return OkStatus();
}

Status UpdateBundleAccessor::Close() {
  bundle_verified_ = false;
  return update_reader_.IsOpen() ? update_reader_.Close() : OkStatus();
}

Status UpdateBundleAccessor::DoOpen() {
  PW_TRY(update_reader_.Open());
  bundle_ = protobuf::Message(update_reader_.reader(),
                              update_reader_.reader().ConservativeReadLimit());
  if (!bundle_.ok()) {
    update_reader_.Close().IgnoreError();
    return bundle_.status();
  }
  return OkStatus();
}

Status UpdateBundleAccessor::DoVerify() {
#if PW_SOFTWARE_UPDATE_DISABLE_BUNDLE_VERIFICATION
  PW_LOG_WARN("Bundle verification is compiled out.");
  bundle_verified_ = true;
  return OkStatus();
#else   // PW_SOFTWARE_UPDATE_DISABLE_BUNDLE_VERIFICATION
  bundle_verified_ = false;

  if (self_verification_) {
    // Use root metadata in staged bundle for self-verification. This root
    // metadata is optional and used opportunistically in the rest of the
    // verification flow.
    trusted_root_ = bundle_.AsMessage(
        static_cast<uint32_t>(UpdateBundle::Fields::ROOT_METADATA));
  } else {
    // A provisioned on-device root metadata is *required* for formal
    // verification.
    if (trusted_root_ = GetOnDeviceTrustedRoot(); !trusted_root_.ok()) {
      PW_LOG_CRITICAL("Missing on-device trusted root");
      return Status::Unauthenticated();
    }
  }

  // Verify and upgrade the on-device trust to the incoming root metadata if
  // one is included.
  if (Status status = UpgradeRoot(); !status.ok()) {
    PW_LOG_ERROR("Failed to rotate root metadata");
    return status;
  }

  if (Status status = VerifyTargetsMetadata(); !status.ok()) {
    PW_LOG_ERROR("Failed to verify Targets metadata");
    return status;
  }

  if (Status status = VerifyTargetsPayloads(); !status.ok()) {
    PW_LOG_ERROR("Failed to verify all manifested payloads");
    return status;
  }

  bundle_verified_ = true;
  return OkStatus();
#endif  // PW_SOFTWARE_UPDATE_DISABLE_BUNDLE_VERIFICATION
}

protobuf::Message UpdateBundleAccessor::GetOnDeviceTrustedRoot() {
  Result<stream::SeekableReader*> res = backend_.GetRootMetadataReader();
  if (!(res.ok() && res.value())) {
    PW_LOG_ERROR("Failed to get on-device Root metadata");
    return res.status();
  }
  // Seek to the beginning so that ConservativeReadLimit() returns the correct
  // value.
  PW_TRY(res.value()->Seek(0, stream::Stream::Whence::kBeginning));
  return protobuf::Message(*res.value(), res.value()->ConservativeReadLimit());
}

ManifestAccessor UpdateBundleAccessor::GetOnDeviceManifest() {
  // Notify backend to check if an on-device manifest exists and is valid and if
  // yes, prepare a ready-to-go reader.
  PW_TRY(backend_.BeforeManifestRead());

  Result<stream::SeekableReader*> manifest_reader =
      backend_.GetManifestReader();
  PW_TRY(manifest_reader.status());
  PW_CHECK_NOTNULL(manifest_reader.value());

  // In case `backend_.BeforeManifestRead()` forgot to reset the reader.
  PW_TRY(manifest_reader.value()->Seek(0, stream::Stream::Whence::kBeginning));

  return ManifestAccessor::FromManifest(
      protobuf::Message(*manifest_reader.value(),
                        manifest_reader.value()->ConservativeReadLimit()));
}

Status UpdateBundleAccessor::UpgradeRoot() {
#if PW_SOFTWARE_UPDATE_WITH_ROOT_ROTATION
  protobuf::Message new_root = bundle_.AsMessage(
      static_cast<uint32_t>(UpdateBundle::Fields::ROOT_METADATA));

  if (!new_root.status().ok()) {
    // Don't bother upgrading if not found or invalid.
    PW_LOG_WARN("Skipping root metadata rotation: not found or invalid");
    return OkStatus();
  }

  // TODO(b/237580538): Check whether the bundle contains a root metadata that
  // is different from the on-device trusted root.

  // Verify the signatures against the trusted root metadata.
  Result<bool> verify_res =
      VerifyRootMetadataSignatures(trusted_root_, new_root);
  if (!(verify_res.status().ok() && verify_res.value())) {
    PW_LOG_ERROR("Failed to verify incoming root against the current root");
    return Status::Unauthenticated();
  }

  // TODO(b/237580538): Verifiy the content of the new root metadata, including:
  //    1) Check role magic field.
  //    2) Check signature requirement. Specifically, check that no key is
  //       reused across different roles and keys are unique in the same
  //       requirement.
  //    3) Check key mapping. Specifically, check that all keys are unique,
  //       ECDSA keys, and the key ids are exactly the SHA256 of `key type +
  //       key scheme + key value`.

  // Verify the signatures against the new root metadata.
  verify_res = VerifyRootMetadataSignatures(new_root, new_root);
  if (!(verify_res.status().ok() && verify_res.value())) {
    PW_LOG_ERROR("Fail to verify incoming root against itself");
    return Status::Unauthenticated();
  }

  // Retrieves the trusted root metadata content message.
  protobuf::Message trusted_root_content =
      trusted_root_.AsMessage(static_cast<uint32_t>(
          SignedRootMetadata::Fields::SERIALIZED_ROOT_METADATA));
  PW_TRY(trusted_root_content.status());
  Result<uint32_t> trusted_root_version = GetMetadataVersion(
      trusted_root_content,
      static_cast<uint32_t>(RootMetadata::Fields::COMMON_METADATA));
  PW_TRY(trusted_root_version.status());

  // Retrieves the serialized new root metadata message.
  protobuf::Message new_root_content = new_root.AsMessage(static_cast<uint32_t>(
      SignedRootMetadata::Fields::SERIALIZED_ROOT_METADATA));
  PW_TRY(new_root_content.status());
  Result<uint32_t> new_root_version = GetMetadataVersion(
      new_root_content,
      static_cast<uint32_t>(RootMetadata::Fields::COMMON_METADATA));
  PW_TRY(new_root_version.status());

  if (trusted_root_version.value() > new_root_version.value()) {
    PW_LOG_ERROR("Root attempts to rollback from %u to %u",
                 trusted_root_version.value(),
                 new_root_version.value());
    return Status::Unauthenticated();
  }

  if (!self_verification_) {
    // Persist the root immediately after it is successfully verified. This is
    // to make sure the trust anchor is up-to-date in storage as soon as
    // we are confident. Although targets metadata and product-specific
    // verification have not been done yet. They should be independent from and
    // not gate the upgrade of root key. This allows timely revokation of
    // compromise keys.
    stream::IntervalReader new_root_reader =
        new_root.ToBytes().GetBytesReader();
    if (Status status = backend_.SafelyPersistRootMetadata(new_root_reader);
        !status.ok()) {
      PW_LOG_ERROR("Failed to persist rotated root metadata");
      return status;
    }
  }

  // TODO(b/237580538): Implement key change detection to determine whether
  // rotation has occured or not. Delete the persisted targets metadata version
  // if any of the targets keys has been rotated.

  return OkStatus();
#else
  // Root metadata rotation opted out.
  return OkStatus();
#endif  // PW_SOFTWARE_UPDATE_WITH_ROOT_ROTATION
}

Status UpdateBundleAccessor::VerifyTargetsMetadata() {
  if (self_verification_ && !trusted_root_.status().ok()) {
    PW_LOG_WARN(
        "Self-verification won't verify Targets metadata because there is no "
        "root");
    return OkStatus();
  }

  // A valid trust anchor is required from now on.
  PW_TRY(trusted_root_.status());

  // Retrieve the signed targets metadata map.
  //
  // message UpdateBundle {
  //   ...
  //   map<string, SignedTargetsMetadata> target_metadata = <id>;
  //   ...
  // }
  protobuf::StringToMessageMap signed_targets_metadata_map =
      bundle_.AsStringToMessageMap(
          static_cast<uint32_t>(UpdateBundle::Fields::TARGETS_METADATA));
  PW_TRY(signed_targets_metadata_map.status());

  // The top-level targets metadata is identified by key name "targets" in the
  // map.
  protobuf::Message signed_top_level_targets_metadata =
      signed_targets_metadata_map[kTopLevelTargetsName];
  PW_TRY(signed_top_level_targets_metadata.status());

  // Retrieve the serialized metadata.
  //
  // message SignedTargetsMetadata {
  //   ...
  //   bytes serialized_target_metadata = <id>;
  //   ...
  // }
  protobuf::Message top_level_targets_metadata =
      signed_top_level_targets_metadata.AsMessage(static_cast<uint32_t>(
          SignedTargetsMetadata::Fields::SERIALIZED_TARGETS_METADATA));

  // Get the sigantures from the signed targets metadata.
  protobuf::RepeatedMessages signatures =
      signed_top_level_targets_metadata.AsRepeatedMessages(
          static_cast<uint32_t>(SignedTargetsMetadata::Fields::SIGNATURES));
  PW_TRY(signatures.status());

  // Retrieve the trusted root metadata message.
  protobuf::Message trusted_root =
      trusted_root_.AsMessage(static_cast<uint32_t>(
          SignedRootMetadata::Fields::SERIALIZED_ROOT_METADATA));
  PW_TRY(trusted_root.status());

  // Get the key_mapping from the trusted root metadata.
  protobuf::StringToMessageMap key_mapping = trusted_root.AsStringToMessageMap(
      static_cast<uint32_t>(RootMetadata::Fields::KEYS));
  PW_TRY(key_mapping.status());

  // Get the target metadtata signature requirement from the trusted root.
  protobuf::Message signature_requirement =
      trusted_root.AsMessage(static_cast<uint32_t>(
          RootMetadata::Fields::TARGETS_SIGNATURE_REQUIREMENT));
  PW_TRY(signature_requirement.status());

  // Verify the sigantures
  Status sig_res =
      VerifyMetadataSignatures(top_level_targets_metadata.ToBytes(),
                               signatures,
                               signature_requirement,
                               key_mapping);

  if (self_verification_ && sig_res.IsNotFound()) {
    PW_LOG_WARN("Self-verification ignoring unsigned bundle");
    return OkStatus();
  }

  if (!sig_res.ok()) {
    PW_LOG_ERROR("Targets Metadata failed signature verification");
    return Status::Unauthenticated();
  }

  if (self_verification_) {
    // Don't bother because it does not matter.
    PW_LOG_WARN("Self verification skips Targets metadata anti-rollback");
    return OkStatus();
  }

  // Anti-rollback check.
  ManifestAccessor device_manifest = GetOnDeviceManifest();
  if (device_manifest.status().IsNotFound()) {
    PW_LOG_WARN("Skipping OTA anti-rollback due to absent device manifest");
    return OkStatus();
  }

  protobuf::Uint32 current_version = device_manifest.GetVersion();
  PW_TRY(current_version.status());

  // Retrieves the version from the new metadata
  Result<uint32_t> new_version = GetMetadataVersion(
      top_level_targets_metadata,
      static_cast<uint32_t>(
          software_update::TargetsMetadata::Fields::COMMON_METADATA));
  PW_TRY(new_version.status());
  if (current_version.value() > new_version.value()) {
    PW_LOG_ERROR("Blocking Targets metadata rollback from %u to %u",
                 current_version.value(),
                 new_version.value());
    return Status::Unauthenticated();
  }

  return OkStatus();
}

Status UpdateBundleAccessor::VerifyTargetsPayloads() {
  ManifestAccessor bundle_manifest = ManifestAccessor::FromBundle(bundle_);
  PW_TRY(bundle_manifest.status());

  // Target file descriptors (pathname, length, hash, etc.) listed in the bundle
  // manifest.
  protobuf::RepeatedMessages target_files = bundle_manifest.GetTargetFiles();
  PW_TRY(target_files.status());

  // Verify length and SHA256 hash for each file listed in the manifest.
  for (protobuf::Message target_file : target_files) {
    // Extract target file name in the form of a `std::string_view`.
    protobuf::String name_proto = target_file.AsString(
        static_cast<uint32_t>(TargetFile::Fields::FILE_NAME));
    PW_TRY(name_proto.status());
    char name_buf[MAX_TARGET_NAME_LENGTH] = {0};
    Result<std::string_view> target_name =
        ReadProtoString(name_proto, name_buf);
    PW_TRY(target_name.status());

    // Get target length.
    protobuf::Uint64 target_length =
        target_file.AsUint64(static_cast<uint32_t>(TargetFile::Fields::LENGTH));
    PW_TRY(target_length.status());
    if (target_length.value() > PW_SOFTWARE_UPDATE_MAX_TARGET_PAYLOAD_SIZE) {
      PW_LOG_ERROR("Target payload too big. Maximum is %u bytes",
                   PW_SOFTWARE_UPDATE_MAX_TARGET_PAYLOAD_SIZE);
      return Status::OutOfRange();
    }

    // Get target SHA256 hash.
    protobuf::Bytes target_sha256 = Status::NotFound();
    protobuf::RepeatedMessages hashes = target_file.AsRepeatedMessages(
        static_cast<uint32_t>(TargetFile::Fields::HASHES));
    for (protobuf::Message hash : hashes) {
      protobuf::Uint32 hash_function =
          hash.AsUint32(static_cast<uint32_t>(Hash::Fields::FUNCTION));
      PW_TRY(hash_function.status());

      if (hash_function.value() ==
          static_cast<uint32_t>(HashFunction::SHA256)) {
        target_sha256 = hash.AsBytes(static_cast<uint32_t>(Hash::Fields::HASH));
        break;
      }
    }
    PW_TRY(target_sha256.status());

    if (Status status = VerifyTargetPayload(
            bundle_manifest, target_name.value(), target_length, target_sha256);
        !status.ok()) {
      PW_LOG_ERROR("Target: %s failed verification",
                   pw::MakeString(target_name.value()).c_str());
      return status;
    }
  }  // for each target file in manifest.

  return OkStatus();
}

Status UpdateBundleAccessor::VerifyTargetPayload(
    ManifestAccessor,
    std::string_view target_name,
    protobuf::Uint64 expected_length,
    protobuf::Bytes expected_sha256) {
  protobuf::StringToBytesMap payloads_map = bundle_.AsStringToBytesMap(
      static_cast<uint32_t>(UpdateBundle::Fields::TARGET_PAYLOADS));
  stream::IntervalReader payload_reader =
      payloads_map[target_name].GetBytesReader();

  Status status;

  if (payload_reader.ok()) {
    status = VerifyInBundleTargetPayload(
        expected_length, expected_sha256, payload_reader);
  } else {
    status = VerifyOutOfBundleTargetPayload(
        target_name, expected_length, expected_sha256);
  }

  // TODO(alizhang): Notify backend to do additional checks by calling
  // backend_.VerifyTargetFile(...).
  return status;
}

// TODO(alizhang): Add unit tests for all failure conditions.
Status UpdateBundleAccessor::VerifyOutOfBundleTargetPayload(
    std::string_view target_name,
    protobuf::Uint64 expected_length,
    protobuf::Bytes expected_sha256) {
#if PW_SOFTWARE_UPDATE_WITH_PERSONALIZATION
  // The target payload is "personalized out". We we can't take a measurement
  // without backend help. For now we will check against the device manifest
  // which contains a cached measurement of the last software update.
  ManifestAccessor device_manifest = GetOnDeviceManifest();
  if (!device_manifest.ok()) {
    PW_LOG_ERROR(
        "Can't verify personalized-out target because on-device manifest is "
        "not found");
    return Status::Unauthenticated();
  }

  protobuf::Message cached = device_manifest.GetTargetFile(target_name);
  if (!cached.ok()) {
    PW_LOG_ERROR(
        "Can't verify personalized-out target because it is not found from "
        "on-device manifest");
    return Status::Unauthenticated();
  }

  protobuf::Uint64 cached_length =
      cached.AsUint64(static_cast<uint32_t>(TargetFile::Fields::LENGTH));
  PW_TRY(cached_length.status());
  if (cached_length.value() != expected_length.value()) {
    PW_LOG_ERROR("Personalized-out target has bad length: %u, expected: %u",
                 static_cast<unsigned>(cached_length.value()),
                 static_cast<unsigned>(expected_length.value()));
    return Status::Unauthenticated();
  }

  protobuf::Bytes cached_sha256 = Status::NotFound();
  protobuf::RepeatedMessages hashes = cached.AsRepeatedMessages(
      static_cast<uint32_t>(TargetFile::Fields::HASHES));
  for (protobuf::Message hash : hashes) {
    protobuf::Uint32 hash_function =
        hash.AsUint32(static_cast<uint32_t>(Hash::Fields::FUNCTION));
    PW_TRY(hash_function.status());

    if (hash_function.value() == static_cast<uint32_t>(HashFunction::SHA256)) {
      cached_sha256 = hash.AsBytes(static_cast<uint32_t>(Hash::Fields::HASH));
      break;
    }
  }
  std::byte sha256[crypto::sha256::kDigestSizeBytes] = {};
  PW_TRY(cached_sha256.GetBytesReader().Read(sha256));

  Result<bool> hash_equal = expected_sha256.Equal(sha256);
  PW_TRY(hash_equal.status());
  if (!hash_equal.value()) {
    PW_LOG_ERROR("Personalized-out target has a bad hash");
    return Status::Unauthenticated();
  }

  return OkStatus();
#else
  PW_LOG_ERROR("Target file %s not found in bundle", target_name);
  return Status::Unauthenticated();
#endif  // PW_SOFTWARE_UPDATE_WITH_PERSONALIZATION
}

Status UpdateBundleAccessor::VerifyInBundleTargetPayload(
    protobuf::Uint64 expected_length,
    protobuf::Bytes expected_sha256,
    stream::IntervalReader payload_reader) {
  // If the target payload is included in the bundle, simply take a
  // measurement.
  uint64_t actual_length = payload_reader.interval_size();
  if (actual_length != expected_length.value()) {
    PW_LOG_ERROR("Wrong payload length. Expected: %u, actual: %u",
                 static_cast<unsigned>(expected_length.value()),
                 static_cast<unsigned>(actual_length));
    return Status::Unauthenticated();
  }

  std::byte actual_sha256[crypto::sha256::kDigestSizeBytes] = {};
  PW_TRY(crypto::sha256::Hash(payload_reader, actual_sha256));
  Result<bool> hash_equal = expected_sha256.Equal(actual_sha256);
  PW_TRY(hash_equal.status());
  if (!hash_equal.value()) {
    PW_LOG_ERROR("Wrong payload sha256 hash");
    return Status::Unauthenticated();
  }

  return OkStatus();
}

ManifestAccessor UpdateBundleAccessor::GetManifest() {
  if (!bundle_verified_) {
    PW_LOG_DEBUG("Bundled has not passed verification yet");
    return Status::FailedPrecondition();
  }

  return ManifestAccessor::FromBundle(bundle_);
}

}  // namespace pw::software_update
