// Copyright 2016 The Chromium OS 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 "imageloader_impl.h"

#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <unistd.h>
#include </usr/include/linux/magic.h>

#include <sstream>
#include <string>
#include <utility>

#include <base/command_line.h>
#include <base/containers/adapters.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/important_file_writer.h>
#include <base/files/scoped_file.h>
#include <base/guid.h>
#include <base/json/json_string_value_serializer.h>
#include <base/logging.h>
#include <base/numerics/safe_conversions.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/version.h>
#include <brillo/flag_helper.h>
#include <crypto/secure_hash.h>
#include <crypto/sha2.h>
#include <crypto/signature_verifier.h>
#include <dbus-c++/error.h>

#include "imageloader_common.h"

namespace imageloader {

namespace {

using imageloader::kBadResult;

// The name of the fingerprint file.
constexpr char kFingerprintName[] = "manifest.fingerprint";
// The name of the imageloader manifest file.
constexpr char kManifestName[] = "imageloader.json";
// The manifest signature.
constexpr char kManifestSignatureName[] = "imageloader.sig.1";
// The current version of the manifest file.
constexpr int kCurrentManifestVersion = 1;
// The name of the version field in the manifest.
constexpr char kManifestVersionField[] = "manifest-version";
// The name of the component version field in the manifest.
constexpr char kVersionField[] = "version";
// The name of the field containing the image hash.
constexpr char kImageHashField[] = "image-sha256-hash";
// The name of the image file.
constexpr char kImageFileName[] = "image.squash";
// The name of the field containing the table hash.
constexpr char kTableHashField[] = "table-sha256-hash";
// The name of the file containing the latest component version.
constexpr char kLatestVersionFile[] = "latest-version";
// The name of the table file.
constexpr char kTableFileName[] = "table";
// The permissions that the component update directory must use.
constexpr int kComponentDirPerms = 0755;
// The permissions that files in the component should have.
constexpr int kComponentFilePerms = 0644;
// The maximum size of any file to read into memory.
constexpr size_t kMaximumFilesize = 4096 * 10;

// TODO(kerrnel): A component should be abstracted into a class that hides the
// disk structure.
// A component is a directory on disk with a hierarchy of files inside of it. It
// looks like this for an example component, "PepperFlashPlayer":
// PepperFlashPlayer/
//  - latest_version # a file containing the latest version, in this case
//                   # (22.0.0.158)
//  - 22.0.0.158/    # the folder containing the actual component.
//    - imageloader.json  # a manifest file containing the hashes of all the
//                        # files, and some other metadata.
//    - imageloader.sig.1 # a signature blob of the imageloader.json manifest.
//    - table             # contains the device mapper table (including merkle
//                        # tree root hash), of the dm-verity image.
//    - image.squash      # The squashfs disk image containing the actual
//                        # component files. The dm-verity hash tree is appended
//                        # to the end of the disk image, and the |table| tells
//                        # the kernel the offset of the tree.

// Functions to generate paths to various files in the components.
base::FilePath GetComponentPath(const base::FilePath& storage_root,
                                const std::string& component_name) {
  return storage_root.Append(component_name);
}

// |component_root_path| is the "PepperFlashPlayer" folder in the above example.
base::FilePath GetVersionFilePath(const base::FilePath& component_root_path) {
  return component_root_path.Append(kLatestVersionFile);
}

base::FilePath GetVersionedPath(const base::FilePath& component_root_path,
                                const std::string& current_version) {
  return component_root_path.Append(current_version);
}

// |component_version_path| must refer to an actual version of the component,
// such as "22.0.0.158" in the above example.
base::FilePath GetManifestPath(const base::FilePath& component_version_path) {
  return component_version_path.Append(kManifestName);
}

base::FilePath GetSignaturePath(const base::FilePath& component_version_path) {
  return component_version_path.Append(kManifestSignatureName);
}

base::FilePath GetFingerprintPath(
    const base::FilePath& component_version_path) {
  return component_version_path.Append(kFingerprintName);
}

base::FilePath GetTablePath(const base::FilePath& component_version_path) {
  return component_version_path.Append(kTableFileName);
}

base::FilePath GetImagePath(const base::FilePath& component_version_path) {
  return component_version_path.Append(kImageFileName);
}

// |mount_base_path| is the subfolder where all components are mounted.
// For example "/mnt/imageloader."
base::FilePath GetMountPoint(const base::FilePath& mount_base_path,
                             const std::string& component_name,
                             const std::string& component_version) {
  return mount_base_path.Append(component_name).Append(component_version);
}

bool AssertComponentDirPerms(const base::FilePath& path) {
  int mode;
  if (!GetPosixFilePermissions(path, &mode)) return false;
  return mode == kComponentDirPerms;
}

bool GetSHA256FromString(const std::string& hash_str,
                         std::vector<uint8_t>* bytes) {
  if (!base::HexStringToBytes(hash_str, bytes)) return false;
  return bytes->size() == crypto::kSHA256Length;
}

bool WriteFileToDisk(const base::FilePath& path, const std::string& contents) {
  base::ScopedFD fd(HANDLE_EINTR(open(path.value().c_str(),
                                      O_CREAT | O_WRONLY | O_EXCL,
                                      kComponentFilePerms)));
  if (!fd.is_valid()) {
    PLOG(ERROR) << "Error creating file for " << path.value();
    return false;
  }

  base::File file(fd.release());
  int size = base::checked_cast<int>(contents.size());
  return file.Write(0, contents.data(), contents.size()) == size;
}

bool CreateDirectoryWithMode(const base::FilePath& full_path, int mode) {
  std::vector<base::FilePath> subpaths;

  // Collect a list of all parent directories.
  base::FilePath last_path = full_path;
  subpaths.push_back(full_path);
  for (base::FilePath path = full_path.DirName();
       path.value() != last_path.value(); path = path.DirName()) {
    subpaths.push_back(path);
    last_path = path;
  }

  // Iterate through the parents and create the missing ones.
  for (const auto& subpath : base::Reversed(subpaths)) {
    if (base::DirectoryExists(subpath)) continue;
    if (mkdir(subpath.value().c_str(), mode) == 0) continue;
    // Mkdir failed, but it might have failed with EEXIST, or some other error
    // due to the the directory appearing out of thin air. This can occur if
    // two processes are trying to create the same file system tree at the same
    // time. Check to see if it exists and make sure it is a directory.
    if (!base::DirectoryExists(subpath)) {
      PLOG(ERROR) << "Failed to create directory";
      return false;
    }
  }
  return true;
}

bool GetAndVerifyTable(const base::FilePath& path,
                       const std::vector<uint8_t>& hash,
                       std::string* out_table) {
  std::string table;
  if (!base::ReadFileToStringWithMaxSize(path, &table, kMaximumFilesize)) {
    return false;
  }

  std::vector<uint8_t> table_hash(crypto::kSHA256Length);
  crypto::SHA256HashString(table, table_hash.data(), table_hash.size());
  if (table_hash != hash) {
    LOG(ERROR) << "dm-verity table file has the wrong hash.";
    return false;
  }

  out_table->assign(table);
  return true;
}

// |callback| is repeatedly called on data read from the file, can return false on
// error to terminate the read early.
bool ReadFileWithCallback(base::File* file,
                          std::function<bool(const char*, int)> callback) {
  int size = file->GetLength();
  if (size <= 0) return false;

  int rv = 0, bytes_read = 0;
  char buf[4096];
  do {
    int remaining = size - bytes_read;
    int bytes_to_read =
        std::min(remaining, base::checked_cast<int>(sizeof(buf)));

    rv = file->ReadAtCurrentPos(buf, bytes_to_read);
    if (rv <= 0) break;

    bytes_read += rv;
    if (!callback(buf, rv)) return false;
  } while (bytes_read <= size);

  return bytes_read == size;
}

bool GetAndVerifyImage(const base::FilePath& path,
                       const std::vector<uint8_t>& hash,
                       base::ScopedFD* fd) {
  base::File image(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!image.IsValid()) {
    LOG(ERROR) << "Could not open image file.";
    return false;
  }

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

  if (!ReadFileWithCallback(&image, [&sha256](const char* buf, int length) {
        sha256->Update(buf, length);
        return true;
      })) {
    LOG(ERROR) << "Failed to read image file.";
    return false;
  }

  std::vector<uint8_t> file_hash(crypto::kSHA256Length);
  sha256->Finish(file_hash.data(), file_hash.size());

  if (hash != file_hash) {
    LOG(ERROR) << "Image is corrupt or modified.";
    return false;
  }

  fd->reset(image.TakePlatformFile());
  return true;
}

bool CreateMountPointIfNeeded(const base::FilePath& mount_point,
                              bool* already_mounted) {
  *already_mounted = false;
  // Is this mount point somehow already taken?
  struct stat st;
  if (lstat(mount_point.value().c_str(), &st) == 0) {
    if (!S_ISDIR(st.st_mode)) {
      LOG(ERROR) << "Mount point exists but is not a directory.";
      return false;
    }

    base::FilePath mount_parent = mount_point.DirName();
    struct stat st2;
    if (stat(mount_parent.value().c_str(), &st2) != 0) {
      PLOG(ERROR) << "Could not stat the mount point parent";
      return false;
    }
    if (st.st_dev != st2.st_dev) {
      struct statfs st_fs;
      if (statfs(mount_point.value().c_str(), &st_fs) != 0) {
        PLOG(ERROR) << "statfs";
        return false;
      }
      if (st_fs.f_type != SQUASHFS_MAGIC || !(st_fs.f_flags & ST_NODEV) ||
          !(st_fs.f_flags & ST_NOSUID) || !(st_fs.f_flags & ST_RDONLY)) {
        LOG(ERROR) << "File system is not the expected type.";
        return false;
      }
      LOG(INFO) << "The mount point already exists: " << mount_point.value();
      *already_mounted = true;
      return true;
    }
  } else if (!CreateDirectoryWithMode(mount_point, kComponentDirPerms)) {
    LOG(ERROR) << "Failed to create mount point: " << mount_point.value();
    return false;
  }
  return true;
}

}  // namespace {}

bool ImageLoaderImpl::GetManifestForComponent(const std::string& name,
                                              Manifest* manifest) {
  base::FilePath component_path(GetComponentPath(config_.storage_dir, name));
  if (!base::PathExists(component_path)) {
    LOG(ERROR) << "No valid component [" << name << "] on disk.";
    return false;
  }
  return GetAndVerifyManifest(name, component_path, manifest, nullptr, nullptr);
}

bool ImageLoaderImpl::GetAndVerifyManifest(const std::string& component_name,
                                           const base::FilePath& component_path,
                                           Manifest* manifest,
                                           std::string* manifest_out,
                                           std::string* sig) {
  std::string version;
  base::FilePath versioned_path;
  if (component_name != "") {
    base::FilePath version_hint_path(GetVersionFilePath(component_path));
    if (!base::ReadFileToStringWithMaxSize(version_hint_path, &version,
                                           kMaximumFilesize)) {
      LOG(ERROR) << "Could not read current version of component ["
                 << component_name << "]";
      return false;
    }
    versioned_path = GetVersionedPath(component_path, version);
  } else {
    // If the component has not been moved into its versioned path yet, there is
    // no versioned path, and so the caller passes an empty |component_name|,
    // telling this function to work with the |component_path| directly.
    versioned_path = component_path;
  }

  std::string manifest_str;
  std::string manifest_sig;
  if (!base::ReadFileToStringWithMaxSize(GetManifestPath(versioned_path),
                                         &manifest_str, kMaximumFilesize)) {
    LOG(ERROR) << "Could not read manifest file.";
    return false;
  }
  if (!base::ReadFileToStringWithMaxSize(GetSignaturePath(versioned_path),
                                         &manifest_sig, kMaximumFilesize)) {
    LOG(ERROR) << "Could not read signature file.";
    return false;
  }

  if (!VerifyAndParseManifest(manifest_str, manifest_sig, manifest)) {
    LOG(ERROR) << "Could not verify and parse manifest file.";
    return false;
  }

  if (component_name != "" && manifest->version != version) {
    LOG(ERROR) << "Manifest version does not match hint file version.";
    return false;
  }

  if (manifest_out) manifest_out->assign(manifest_str);
  if (sig) sig->assign(manifest_sig);

  return true;
}

// The client inserts manifest.fingerprint into components after unpacking the
// CRX. The file is used for delta updates. Since Chrome OS doesn't rely on it
// for security of the disk image, we are fine with sanity checking the contents
// and then preserving the unsigned file.
bool ImageLoaderImpl::IsValidFingerprintFile(const std::string& contents) {
  return contents.size() <= 256 &&
         std::find_if_not(contents.begin(), contents.end(), [](char ch) {
           return base::IsAsciiAlpha(ch) || base::IsAsciiDigit(ch) || ch == '.';
         }) == contents.end();
}

bool ImageLoaderImpl::CopyFingerprintFile(const base::FilePath& src,
                                          const base::FilePath& dest) {
  base::FilePath fingerprint_path(GetFingerprintPath(src));
  if (base::PathExists(fingerprint_path)) {
    std::string fingerprint_contents;
    if (!base::ReadFileToStringWithMaxSize(
            fingerprint_path, &fingerprint_contents, kMaximumFilesize)) {
      return false;
    }

    if (!IsValidFingerprintFile(fingerprint_contents)) return false;

    if (!WriteFileToDisk(GetFingerprintPath(dest), fingerprint_contents)) {
      return false;
    }
  }
  return true;
}

bool ImageLoaderImpl::CopyAndHashFile(
    const base::FilePath& src_path, const base::FilePath& dest_path,
    const std::vector<uint8_t>& expected_hash) {
  base::File file(src_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!file.IsValid()) return false;

  base::ScopedFD dest(
      HANDLE_EINTR(open(dest_path.value().c_str(), O_CREAT | O_WRONLY | O_EXCL,
                        kComponentFilePerms)));
  if (!dest.is_valid()) return false;

  base::File out_file(dest.release());
  std::unique_ptr<crypto::SecureHash> sha256(
      crypto::SecureHash::Create(crypto::SecureHash::SHA256));

  if (!ReadFileWithCallback(
          &file, [&sha256, &out_file](const char* buf, int length) {
            sha256->Update(buf, length);
            return out_file.WriteAtCurrentPos(buf, length) == length;
          })) {
    LOG(ERROR) << "Failed to read image file.";
    return false;
  }

  std::vector<uint8_t> file_hash(crypto::kSHA256Length);
  sha256->Finish(file_hash.data(), file_hash.size());

  if (expected_hash != file_hash) {
    LOG(ERROR) << "Image is corrupt or modified.";
    return false;
  }
  return true;
}

bool ImageLoaderImpl::VerifyAndParseManifest(
    const std::string& manifest_contents, const base::StringPiece signature,
    Manifest* manifest) {
  // Verify the manifest before trusting any of its contents.
  if (!ECVerify(manifest_contents, signature)) {
    LOG(INFO) << "Manifest did not pass signature verification.";
    return false;
  }

  // Now deserialize the manifest json and read out the rest of the component.
  int error_code;
  std::string error_message;
  JSONStringValueDeserializer deserializer(manifest_contents);
  std::unique_ptr<base::Value> value =
      deserializer.Deserialize(&error_code, &error_message);

  if (!value) {
    LOG(ERROR) << "Could not deserialize the manifest file. Error "
               << error_code << ": " << error_message;
    return false;
  }

  base::DictionaryValue* manifest_dict = nullptr;
  if (!value->GetAsDictionary(&manifest_dict)) {
    LOG(ERROR) << "Could not parse manifest file as JSON.";
    return false;
  }

  // This will have to be changed if the manifest version is bumped.
  int version;
  if (!manifest_dict->GetInteger(kManifestVersionField, &version)) {
    LOG(ERROR) << "Could not parse manifest version field from manifest.";
    return false;
  }
  if (version != kCurrentManifestVersion) {
    LOG(ERROR) << "Unsupported version of the manifest.";
    return false;
  }
  manifest->manifest_version = version;

  std::string image_hash_str;
  if (!manifest_dict->GetString(kImageHashField, &image_hash_str)) {
    LOG(ERROR) << "Could not parse image hash from manifest.";
    return false;
  }

  if (!GetSHA256FromString(image_hash_str, &(manifest->image_sha256))) {
    LOG(ERROR) << "Could not convert image hash to bytes.";
    return false;
  }

  std::string table_hash_str;
  if (!manifest_dict->GetString(kTableHashField, &table_hash_str)) {
    LOG(ERROR) << "Could not parse table hash from manifest.";
    return false;
  }

  if (!GetSHA256FromString(table_hash_str, &(manifest->table_sha256))) {
    LOG(ERROR) << "Could not convert table hash to bytes.";
    return false;
  }

  if (!manifest_dict->GetString(kVersionField, &(manifest->version))) {
    LOG(ERROR) << "Could not parse component version from manifest.";
    return false;
  }

  return true;
}

bool ImageLoaderImpl::CopyComponentDirectory(
    const base::FilePath& component_path,
    const base::FilePath& destination_folder, const std::string& version) {
  if (mkdir(destination_folder.value().c_str(), kComponentDirPerms) != 0) {
    PLOG(ERROR) << "Failed to create directory " << destination_folder.value();
    return false;
  }

  std::string manifest_str;
  std::string manifest_sig;
  Manifest manifest;
  if (!GetAndVerifyManifest("", component_path, &manifest, &manifest_str,
                            &manifest_sig)) {
    return false;
  }

  if (!WriteFileToDisk(GetManifestPath(destination_folder), manifest_str) ||
      !WriteFileToDisk(GetSignaturePath(destination_folder), manifest_sig)) {
    LOG(ERROR) << "Could not write manifest and signature to disk.";
    return false;
  }

  if (manifest.version != version) {
    LOG(ERROR) << "The client provided a different component version than the "
                  "manifest.";
    return false;
  }

  base::FilePath table_src(GetTablePath(component_path));
  base::FilePath table_dest(GetTablePath(destination_folder));
  if (!CopyAndHashFile(table_src, table_dest, manifest.table_sha256)) {
    LOG(ERROR) << "Could not copy table file.";
    return false;
  }

  base::FilePath image_src(GetImagePath(component_path));
  base::FilePath image_dest(GetImagePath(destination_folder));
  if (!CopyAndHashFile(image_src, image_dest, manifest.image_sha256)) {
    LOG(ERROR) << "Could not copy image file.";
    return false;
  }

  if (!CopyFingerprintFile(component_path, destination_folder)) {
    LOG(ERROR) << "Could not copy manifest.fingerprint file.";
    return false;
  }

  return true;
}

bool ImageLoaderImpl::ECVerify(const base::StringPiece data,
                               const base::StringPiece sig) {
  crypto::SignatureVerifier verifier;

  if (!verifier.VerifyInit(crypto::SignatureVerifier::ECDSA_SHA256,
                           reinterpret_cast<const uint8_t*>(sig.data()),
                           base::checked_cast<int>(sig.size()),
                           config_.key.data(),
                           base::checked_cast<int>(config_.key.size()))) {
    return false;
  }

  verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(data.data()),
                        base::checked_cast<int>(data.size()));

  return verifier.VerifyFinal();
}

bool ImageLoaderImpl::LoadComponentHelper(const std::string& name,
                                          const Manifest& manifest,
                                          const base::FilePath& mount_point) {
  // First check if the component is already mounted and avoid unnecessary work.
  bool already_mounted = false;
  if (!CreateMountPointIfNeeded(mount_point, &already_mounted)) return false;
  if (already_mounted) return true;

  base::FilePath component_path(GetComponentPath(config_.storage_dir, name));
  if (!base::PathExists(component_path)) {
    LOG(ERROR) << "No valid component [" << name << "] on disk.";
    return false;
  }
  base::FilePath versioned_path(
      GetVersionedPath(component_path, manifest.version));

  // Now read the table in and verify the hash.
  std::string table;
  if (!GetAndVerifyTable(GetTablePath(versioned_path), manifest.table_sha256,
                         &table)) {
    LOG(ERROR) << "Could not read and verify dm-verity table.";
    return false;
  }

  // Before we mount the image, check the hash as a sanity check.
  base::ScopedFD image_fd;
  base::FilePath image_path(GetImagePath(versioned_path));
  if (!GetAndVerifyImage(image_path, manifest.image_sha256, &image_fd)) {
    LOG(ERROR) << "Failed to load and verify the disk image.";
    return false;
  }

  // The mount point is not yet taken, so go ahead.
  if (!config_.verity_mounter->Mount(image_fd, mount_point, table)) {
    LOG(ERROR) << "Failed to mount image.";
    return false;
  }
  return true;
}

bool ImageLoaderImpl::LoadComponent(const std::string& name,
                                    const std::string& mount_point_str) {
  Manifest manifest;
  if (!GetManifestForComponent(name, &manifest)) return false;

  base::FilePath mount_point(mount_point_str);
  return LoadComponentHelper(name, manifest, mount_point);
}

std::string ImageLoaderImpl::LoadComponent(const std::string& name) {
  Manifest manifest;
  if (!GetManifestForComponent(name, &manifest)) return kBadResult;

  base::FilePath mount_point(
      GetMountPoint(config_.mount_path, name, manifest.version));
  return LoadComponentHelper(name, manifest, mount_point) ? mount_point.value()
                                                          : kBadResult;
}

bool ImageLoaderImpl::RegisterComponent(
    const std::string& name, const std::string& version,
    const std::string& component_folder_abs_path) {
  base::FilePath components_dir(config_.storage_dir);
  if (!base::PathExists(components_dir)) {
    if (mkdir(components_dir.value().c_str(), kComponentDirPerms) != 0) {
      PLOG(ERROR) << "Could not create the ImageLoader components directory.";
      return false;
    }
  }

  if (!AssertComponentDirPerms(config_.storage_dir)) return false;

  base::FilePath component_root(GetComponentPath(components_dir, name));

  std::string current_version_hint;
  base::FilePath version_hint_path(GetVersionFilePath(component_root));
  bool was_previous_version = base::PathExists(version_hint_path);
  if (was_previous_version) {
    if (!base::ReadFileToStringWithMaxSize(
            version_hint_path, &current_version_hint, kMaximumFilesize)) {
      return false;
    }

    // Check for version rollback. We trust the version from the directory name
    // because it had to be validated to ever be registered.
    base::Version current_version(current_version_hint);
    base::Version new_version(version);
    if (!current_version.IsValid() || !new_version.IsValid()) {
      return false;
    }

    if (new_version <= current_version) {
      LOG(ERROR) << "Version [" << new_version << "] is not newer than ["
                 << current_version << "] for component [" << name
                 << "] and cannot be registered.";
      return false;
    }
  }

  // Check if this specific component already exists in the filesystem.
  if (!base::PathExists(component_root)) {
    if (mkdir(component_root.value().c_str(), kComponentDirPerms) != 0) {
      PLOG(ERROR) << "Could not create component specific directory.";
      return false;
    }
  }

  // Take ownership of the component and verify it.
  base::FilePath version_path(GetVersionedPath(component_root, version));
  base::FilePath folder_path(component_folder_abs_path);

  // If |version_path| exists but was not the active version, ImageLoader
  // probably crashed previously and could not cleanup.
  if (base::PathExists(version_path)) {
    base::DeleteFile(version_path, /*recursive=*/true);
  }

  if (!CopyComponentDirectory(folder_path, version_path, version)) {
    base::DeleteFile(version_path, /*recursive=*/true);
    return false;
  }

  if (!base::ImportantFileWriter::WriteFileAtomically(version_hint_path,
                                                      version)) {
    base::DeleteFile(version_path, /*recursive=*/true);
    LOG(ERROR) << "Failed to update current version hint file.";
    return false;
  }

  // Now delete the old component version, if there was one.
  if (was_previous_version) {
    base::DeleteFile(GetVersionedPath(component_root, current_version_hint),
                     true);
  }

  return true;
}

std::string ImageLoaderImpl::GetComponentVersion(const std::string& name) {
  base::FilePath component_path(GetComponentPath(config_.storage_dir, name));
  if (!base::PathExists(component_path)) {
    LOG(ERROR) << "No valid component [" << name << "] on disk.";
    return kBadResult;
  }

  Manifest manifest;
  if (!GetAndVerifyManifest(name, component_path, &manifest, nullptr, nullptr))
    return kBadResult;

  return manifest.version;
}

}  // namespace imageloader
