bool generate_verity_tree(const std::string& data_filename,
                          const std::string& verity_filename,
                          HashTreeBuilder* builder,
                          const std::vector<unsigned char>& salt_content,
                          size_t block_size, bool sparse, bool verbose) {
  android::base::unique_fd data_fd(open(data_filename.c_str(), O_RDONLY));
  if (data_fd == -1) {
    PLOG(ERROR) << "failed to open " << data_filename;
    return false;
  }

  struct sparse_file* file;
  if (sparse) {
    file = sparse_file_import(data_fd, false, false);
  } else {
    file = sparse_file_import_auto(data_fd, false, verbose);
  }

  if (!file) {
    LOG(ERROR) << "failed to read file " << data_filename;
    return false;
  }

  int64_t len = sparse_file_len(file, false, false);
  if (len % block_size != 0) {
    LOG(ERROR) << "file size " << len << " is not a multiple of " << block_size
               << " byte";
    return false;
  }

  // Initialize the builder to compute the hash tree.
  if (!builder->Initialize(len, salt_content)) {
    LOG(ERROR) << "Failed to initialize HashTreeBuilder";
    return false;
  }

  auto hash_callback = [](void* priv, const void* data, size_t len) {
    auto sparse_hasher = static_cast<HashTreeBuilder*>(priv);
    return sparse_hasher->Update(static_cast<const unsigned char*>(data), len)
               ? 0
               : 1;
  };
  sparse_file_callback(file, false, false, hash_callback, builder);
  sparse_file_destroy(file);

  if (!builder->BuildHashTree()) {
    return false;
  }

  return builder->WriteHashTreeToFile(verity_filename);
}
Exemplo n.º 2
0
static void ProcessFirmwareEvent(const Uevent& uevent) {
    int booting = IsBooting();

    LOG(INFO) << "firmware: loading '" << uevent.firmware << "' for '" << uevent.path << "'";

    std::string root = "/sys" + uevent.path;
    std::string loading = root + "/loading";
    std::string data = root + "/data";

    unique_fd loading_fd(open(loading.c_str(), O_WRONLY | O_CLOEXEC));
    if (loading_fd == -1) {
        PLOG(ERROR) << "couldn't open firmware loading fd for " << uevent.firmware;
        return;
    }

    unique_fd data_fd(open(data.c_str(), O_WRONLY | O_CLOEXEC));
    if (data_fd == -1) {
        PLOG(ERROR) << "couldn't open firmware data fd for " << uevent.firmware;
        return;
    }

    static const char* firmware_dirs[] = {"/etc/firmware/", "/vendor/firmware/",
                                          "/firmware/image/"};

try_loading_again:
    for (size_t i = 0; i < arraysize(firmware_dirs); i++) {
        std::string file = firmware_dirs[i] + uevent.firmware;
        unique_fd fw_fd(open(file.c_str(), O_RDONLY | O_CLOEXEC));
        struct stat sb;
        if (fw_fd != -1 && fstat(fw_fd, &sb) != -1) {
            LoadFirmware(uevent, root, fw_fd, sb.st_size, loading_fd, data_fd);
            return;
        }
    }

    if (booting) {
        // If we're not fully booted, we may be missing
        // filesystems needed for firmware, wait and retry.
        std::this_thread::sleep_for(100ms);
        booting = IsBooting();
        goto try_loading_again;
    }

    LOG(ERROR) << "firmware: could not find firmware for " << uevent.firmware;

    // Write "-1" as our response to the kernel's firmware request, since we have nothing for it.
    write(loading_fd, "-1", 2);
}