Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8a9a4a1e authored by Tianjie Xu's avatar Tianjie Xu Committed by android-build-merger
Browse files

Merge "Implement FilePackage class" am: 698dc085

am: cd73207f

Change-Id: I622cf88e2c2f5a431e20499bb03537c0ad2f84e1
parents e6136dca cd73207f
Loading
Loading
Loading
Loading
+24 −1
Original line number Diff line number Diff line
@@ -151,6 +151,7 @@ cc_defaults {
    static_libs: [
        "librecovery_fastboot",
        "libminui",
        "libpackage",
        "libverifier",
        "libotautil",

@@ -175,7 +176,6 @@ cc_library_static {
        "fsck_unshare_blocks.cpp",
        "fuse_sdcard_provider.cpp",
        "install.cpp",
        "package.cpp",
        "recovery.cpp",
        "roots.cpp",
    ],
@@ -210,6 +210,29 @@ cc_library_static {
    ],
}

cc_library_static {
    name: "libpackage",
    recovery_available: true,

    defaults: [
        "recovery_defaults",
    ],

    srcs: [
        "package.cpp",
    ],

    shared_libs: [
        "libbase",
        "libcrypto",
        "libziparchive",
    ],

    static_libs: [
        "libotautil",
    ],
}

cc_binary {
    name: "recovery",
    recovery: true,
+111 −3
Original line number Diff line number Diff line
@@ -17,10 +17,12 @@
#include "package.h"

#include <string.h>
#include <unistd.h>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <openssl/sha.h>
#include <android-base/unique_fd.h>

#include "otautil/error_code.h"
#include "otautil/sysutil.h"
@@ -67,14 +69,38 @@ class MemoryPackage : public Package {
  ZipArchiveHandle zip_handle_;
};

// TODO(xunchang) Implement the PackageFromFd.

void Package::SetProgress(float progress) {
  if (set_progress_) {
    set_progress_(progress);
  }
}

class FilePackage : public Package {
 public:
  FilePackage(android::base::unique_fd&& fd, uint64_t file_size, const std::string& path,
              const std::function<void(float)>& set_progress);

  ~FilePackage() override;

  uint64_t GetPackageSize() const override {
    return package_size_;
  }

  bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;

  ZipArchiveHandle GetZipArchiveHandle() override;

  bool UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers, uint64_t start,
                          uint64_t length) override;

 private:
  android::base::unique_fd fd_;  // The underlying fd to the open package.
  uint64_t package_size_;
  std::string path_;  // The physical path to the package.

  ZipArchiveHandle zip_handle_;
};

std::unique_ptr<Package> Package::CreateMemoryPackage(
    const std::string& path, const std::function<void(float)>& set_progress) {
  std::unique_ptr<MemMapping> mmap = std::make_unique<MemMapping>();
@@ -86,6 +112,23 @@ std::unique_ptr<Package> Package::CreateMemoryPackage(
  return std::make_unique<MemoryPackage>(path, std::move(mmap), set_progress);
}

std::unique_ptr<Package> Package::CreateFilePackage(
    const std::string& path, const std::function<void(float)>& set_progress) {
  android::base::unique_fd fd(open(path.c_str(), O_RDONLY));
  if (fd == -1) {
    PLOG(ERROR) << "Failed to open " << path;
    return nullptr;
  }

  off64_t file_size = lseek64(fd.get(), 0, SEEK_END);
  if (file_size == -1) {
    PLOG(ERROR) << "Failed to get the package size";
    return nullptr;
  }

  return std::make_unique<FilePackage>(std::move(fd), file_size, path, set_progress);
}

std::unique_ptr<Package> Package::CreateMemoryPackage(
    std::vector<uint8_t> content, const std::function<void(float)>& set_progress) {
  return std::make_unique<MemoryPackage>(std::move(content), set_progress);
@@ -152,3 +195,68 @@ ZipArchiveHandle MemoryPackage::GetZipArchiveHandle() {

  return zip_handle_;
}

FilePackage::FilePackage(android::base::unique_fd&& fd, uint64_t file_size, const std::string& path,
                         const std::function<void(float)>& set_progress)
    : fd_(std::move(fd)), package_size_(file_size), path_(path), zip_handle_(nullptr) {
  set_progress_ = set_progress;
}

FilePackage::~FilePackage() {
  if (zip_handle_) {
    CloseArchive(zip_handle_);
  }
}

bool FilePackage::ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) {
  if (byte_count > package_size_ || offset > package_size_ - byte_count) {
    LOG(ERROR) << "Out of bound read, offset: " << offset << ", size: " << byte_count
               << ", total package_size: " << package_size_;
    return false;
  }

  if (!android::base::ReadFullyAtOffset(fd_.get(), buffer, byte_count, offset)) {
    PLOG(ERROR) << "Failed to read " << byte_count << " bytes data at offset " << offset;
    return false;
  }

  return true;
}

bool FilePackage::UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers,
                                     uint64_t start, uint64_t length) {
  if (length > package_size_ || start > package_size_ - length) {
    LOG(ERROR) << "Out of bound read, offset: " << start << ", size: " << length
               << ", total package_size: " << package_size_;
    return false;
  }

  uint64_t so_far = 0;
  while (so_far < length) {
    uint64_t read_size = std::min<uint64_t>(length - so_far, 16 * MiB);
    std::vector<uint8_t> buffer(read_size);
    if (!ReadFullyAtOffset(buffer.data(), read_size, start + so_far)) {
      return false;
    }

    for (const auto& hasher : hashers) {
      hasher(buffer.data(), read_size);
    }
    so_far += read_size;
  }

  return true;
}

ZipArchiveHandle FilePackage::GetZipArchiveHandle() {
  if (zip_handle_) {
    return zip_handle_;
  }

  if (auto err = OpenArchiveFd(fd_.get(), path_.c_str(), &zip_handle_); err != 0) {
    LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err);
    return nullptr;
  }

  return zip_handle_;
}
+7 −6
Original line number Diff line number Diff line
@@ -32,6 +32,13 @@
// interface for both packages loaded in memory and packages read from fd.
class Package : public VerifierInterface {
 public:
  static std::unique_ptr<Package> CreateMemoryPackage(
      const std::string& path, const std::function<void(float)>& set_progress);
  static std::unique_ptr<Package> CreateMemoryPackage(
      std::vector<uint8_t> content, const std::function<void(float)>& set_progress);
  static std::unique_ptr<Package> CreateFilePackage(const std::string& path,
                                                    const std::function<void(float)>& set_progress);

  virtual ~Package() = default;

  // Opens the package as a zip file and returns the ZipArchiveHandle.
@@ -40,12 +47,6 @@ class Package : public VerifierInterface {
  // Updates the progress in fraction during package verification.
  void SetProgress(float progress) override;

  static std::unique_ptr<Package> CreateMemoryPackage(
      const std::string& path, const std::function<void(float)>& set_progress);

  static std::unique_ptr<Package> CreateMemoryPackage(
      std::vector<uint8_t> content, const std::function<void(float)>& set_progress);

 protected:
  // An optional function to update the progress.
  std::function<void(float)> set_progress_;
+2 −0
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ librecovery_static_libs = [
    "librecovery",
    "librecovery_fastboot",
    "libminui",
    "libpackage",
    "libverifier",
    "libotautil",

@@ -117,6 +118,7 @@ cc_test {
    static_libs: libapplypatch_static_libs + [
        "librecovery_ui",
        "libminui",
        "libpackage",
        "libverifier",
        "libotautil",
        "libupdater",
+10 −5
Original line number Diff line number Diff line
@@ -240,8 +240,10 @@ class VerifierTest : public testing::TestWithParam<std::vector<std::string>> {
  void SetUp() override {
    std::vector<std::string> args = GetParam();
    std::string path = from_testdata_base(args[0]);
    package_ = Package::CreateMemoryPackage(path, nullptr);
    ASSERT_NE(nullptr, package_);
    memory_package_ = Package::CreateMemoryPackage(path, nullptr);
    ASSERT_NE(nullptr, memory_package_);
    file_package_ = Package::CreateFilePackage(path, nullptr);
    ASSERT_NE(nullptr, file_package_);

    for (auto it = ++args.cbegin(); it != args.cend(); ++it) {
      std::string public_key_file = from_testdata_base("testkey_" + *it + ".x509.pem");
@@ -250,7 +252,8 @@ class VerifierTest : public testing::TestWithParam<std::vector<std::string>> {
    }
  }

  std::unique_ptr<Package> package_;
  std::unique_ptr<Package> memory_package_;
  std::unique_ptr<Package> file_package_;
  std::vector<Certificate> certs_;
};

@@ -304,11 +307,13 @@ TEST(VerifierTest, BadPackage_SignatureStartOutOfBounds) {
}

TEST_P(VerifierSuccessTest, VerifySucceed) {
  ASSERT_EQ(VERIFY_SUCCESS, verify_file(package_.get(), certs_));
  ASSERT_EQ(VERIFY_SUCCESS, verify_file(memory_package_.get(), certs_));
  ASSERT_EQ(VERIFY_SUCCESS, verify_file(file_package_.get(), certs_));
}

TEST_P(VerifierFailureTest, VerifyFailure) {
  ASSERT_EQ(VERIFY_FAILURE, verify_file(package_.get(), certs_));
  ASSERT_EQ(VERIFY_FAILURE, verify_file(memory_package_.get(), certs_));
  ASSERT_EQ(VERIFY_FAILURE, verify_file(file_package_.get(), certs_));
}

INSTANTIATE_TEST_CASE_P(SingleKeySuccess, VerifierSuccessTest,
Loading