// 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::kThreshold));
  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::kKeyIds));
  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::kKeyId));
    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::kSig));
    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::kKeyval));
    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",
               static_cast<unsigned>(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::kSerializedRootMetadata));
  PW_TRY(trusted.status());

  // Retrieves the serialized new root metadata bytes.
  protobuf::Bytes serialized = new_root.AsBytes(static_cast<uint32_t>(
      SignedRootMetadata::Fields::kSerializedRootMetadata));
  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::kKeys));
  PW_TRY(key_mapping.status());

  // Gets the signatures of the new root.
  protobuf::RepeatedMessages signatures = new_root.AsRepeatedMessages(
      static_cast<uint32_t>(SignedRootMetadata::Fields::kSignatures));
  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::kRootSignatureRequirement));
  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::kVersion));
  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::kTargetPayloads));
  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::kFileName));

    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::kLength));
    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::kTargetPayloads));
  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::kRootMetadata));
  } 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::kRootMetadata));

  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::kSerializedRootMetadata));
  PW_TRY(trusted_root_content.status());
  Result<uint32_t> trusted_root_version = GetMetadataVersion(
      trusted_root_content,
      static_cast<uint32_t>(RootMetadata::Fields::kCommonMetadata));
  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::kSerializedRootMetadata));
  PW_TRY(new_root_content.status());
  Result<uint32_t> new_root_version = GetMetadataVersion(
      new_root_content,
      static_cast<uint32_t>(RootMetadata::Fields::kCommonMetadata));
  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",
                 static_cast<unsigned>(trusted_root_version.value()),
                 static_cast<unsigned>(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::kTargetsMetadata));
  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::kSerializedTargetsMetadata));

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

  // Retrieve the trusted root metadata message.
  protobuf::Message trusted_root =
      trusted_root_.AsMessage(static_cast<uint32_t>(
          SignedRootMetadata::Fields::kSerializedRootMetadata));
  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::kKeys));
  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::kTargetsSignatureRequirement));
  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::kCommonMetadata));
  PW_TRY(new_version.status());
  if (current_version.value() > new_version.value()) {
    PW_LOG_ERROR("Blocking Targets metadata rollback from %u to %u",
                 static_cast<unsigned>(current_version.value()),
                 static_cast<unsigned>(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::kFileName));
    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::kLength));
    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::kHashes));
    for (protobuf::Message hash : hashes) {
      protobuf::Uint32 hash_function =
          hash.AsUint32(static_cast<uint32_t>(Hash::Fields::kFunction));
      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::kHash));
        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::kTargetPayloads));
  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,
    [[maybe_unused]] protobuf::Uint64 expected_length,
    [[maybe_unused]] 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::kLength));
  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::kHashes));
  for (protobuf::Message hash : hashes) {
    protobuf::Uint32 hash_function =
        hash.AsUint32(static_cast<uint32_t>(Hash::Fields::kFunction));
    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::kHash));
      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.data());
  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
