// 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/component.h"

#include <fcntl.h>

#include <algorithm>
#include <string>
#include <utility>
#include <vector>

#include <base/files/file.h>
#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/json/json_string_value_serializer.h>
#include <base/logging.h>
#include <base/numerics/safe_conversions.h>
#include <base/posix/eintr_wrapper.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <crypto/secure_hash.h>
#include <crypto/sha2.h>
#include <crypto/signature_verifier.h>

#include "imageloader/helper_process_proxy.h"

namespace imageloader {

namespace {

// The name of the imageloader manifest file.
constexpr char kManifestName[] = "imageloader.json";
// The name of the fingerprint file.
constexpr char kFingerprintName[] = "manifest.fingerprint";
// The manifest signature.
constexpr char kManifestSignatureNamePattern[] = "imageloader.sig.[1-2]";
// The name of the image file (squashfs).
constexpr char kImageFileNameSquashFS[] = "image.squash";
// The name of the image file (ext4).
constexpr char kImageFileNameExt4[] = "image.ext4";
// The name of the table file.
constexpr char kTableFileName[] = "table";

base::FilePath GetManifestPath(const base::FilePath& component_dir) {
  return component_dir.Append(kManifestName);
}

bool GetSignaturePath(const base::FilePath& component_dir,
                      base::FilePath* signature_path,
                      size_t* key_number) {
  DCHECK(signature_path);
  DCHECK(key_number);

  base::FileEnumerator files(component_dir, false,
                             base::FileEnumerator::FileType::FILES,
                             kManifestSignatureNamePattern);
  for (base::FilePath path = files.Next(); !path.empty(); path = files.Next()) {
    // Extract the key number.
    std::string key_ext = path.FinalExtension();
    if (key_ext.empty())
      continue;

    size_t ext_number;
    if (!base::StringToSizeT(key_ext.substr(1), &ext_number))
      continue;

    *signature_path = path;
    *key_number = ext_number;
    return true;
  }
  return false;
}

base::FilePath GetSignaturePathForKey(const base::FilePath& component_dir,
                                      size_t key_number) {
  std::string signature_name(kManifestSignatureNamePattern);
  signature_name =
      signature_name.substr(0, signature_name.find_last_of('.') + 1);
  return component_dir.Append(signature_name +
                              base::NumberToString(key_number));
}

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

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

base::FilePath GetImagePath(const base::FilePath& component_dir,
                            FileSystem fs_type) {
  if (fs_type == FileSystem::kExt4) {
    return component_dir.Append(kImageFileNameExt4);
  } else if (fs_type == FileSystem::kSquashFS) {
    return component_dir.Append(kImageFileNameSquashFS);
  } else {
    NOTREACHED();
    return base::FilePath();
  }
}

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 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;
}

}  // namespace

Component::Component(const base::FilePath& component_dir, int key_number)
    : component_dir_(component_dir), key_number_(key_number) {}

std::unique_ptr<Component> Component::Create(
    const base::FilePath& component_dir, const Keys& public_keys) {
  base::FilePath signature_path;
  size_t key_number;
  if (!GetSignaturePath(component_dir, &signature_path, &key_number)) {
    LOG(ERROR) << "Could not find manifest signature";
    return nullptr;
  }
  if (key_number < 1 || key_number > public_keys.size()) {
    LOG(ERROR) << "Invalid key number";
    return nullptr;
  }

  std::unique_ptr<Component> component(
      new Component(component_dir, key_number));
  if (!component->LoadManifest(public_keys[key_number - 1]))
    return nullptr;
  return component;
}

const Manifest& Component::manifest() {
  return manifest_;
}

bool Component::Mount(HelperProcessProxy* mounter,
                      const base::FilePath& dest_dir) {
  // Read the table in and verify the hash.
  std::string table;
  if (!GetAndVerifyTable(GetTablePath(component_dir_), manifest_.table_sha256(),
                         &table)) {
    LOG(ERROR) << "Could not read and verify dm-verity table.";
    return false;
  }

  base::FilePath image_path(GetImagePath(component_dir_, manifest_.fs_type()));
  base::File image(image_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!image.IsValid()) {
    LOG(ERROR) << "Could not open image file.";
    return false;
  }
  base::ScopedFD image_fd(image.TakePlatformFile());

  return mounter->SendMountCommand(image_fd.get(), dest_dir.value(),
                                   manifest_.fs_type(), table);
}

bool Component::LoadManifest(const std::vector<uint8_t>& public_key) {
  if (!base::ReadFileToStringWithMaxSize(GetManifestPath(component_dir_),
                                         &manifest_raw_, kMaximumFilesize)) {
    LOG(ERROR) << "Could not read manifest file.";
    return false;
  }
  if (!base::ReadFileToStringWithMaxSize(
          GetSignaturePathForKey(component_dir_, key_number_), &manifest_sig_,
          kMaximumFilesize)) {
    LOG(ERROR) << "Could not read signature file.";
    return false;
  }

  crypto::SignatureVerifier verifier;

  if (!verifier.VerifyInit(
          crypto::SignatureVerifier::ECDSA_SHA256,
          reinterpret_cast<const uint8_t*>(manifest_sig_.data()),
          base::checked_cast<int>(manifest_sig_.size()), public_key.data(),
          base::checked_cast<int>(public_key.size()))) {
    LOG(ERROR) << "Failed to initialize signature verification.";
    return false;
  }

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

  if (!verifier.VerifyFinal()) {
    LOG(ERROR) << "Manifest failed signature verification.";
    return false;
  }
  return manifest_.ParseManifest(manifest_raw_);
}

bool Component::CopyTo(const base::FilePath& dest_dir) {
  if (!WriteFileToDisk(GetManifestPath(dest_dir), manifest_raw_) ||
      !WriteFileToDisk(GetSignaturePathForKey(dest_dir, key_number_),
                       manifest_sig_)) {
    LOG(ERROR) << "Could not write manifest and signature to disk.";
    return false;
  }

  base::FilePath table_src(GetTablePath(component_dir_));
  base::FilePath table_dest(GetTablePath(dest_dir));
  if (!CopyComponentFile(table_src, table_dest, manifest_.table_sha256())) {
    LOG(ERROR) << "Could not copy table file.";
    return false;
  }

  base::FilePath image_src(GetImagePath(component_dir_, manifest_.fs_type()));
  base::FilePath image_dest(GetImagePath(dest_dir, manifest_.fs_type()));
  if (!CopyComponentFile(image_src, image_dest, manifest_.image_sha256())) {
    LOG(ERROR) << "Could not copy image file.";
    return false;
  }

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

  return true;
}

bool Component::CopyComponentFile(const base::FilePath& src,
                                  const base::FilePath& dest_path,
                                  const std::vector<uint8_t>& expected_hash) {
  base::File file(src, 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));

  std::vector<uint8_t> file_hash(crypto::kSHA256Length);
  if (!ReadHashAndCopyFile(&file, &file_hash, &out_file)) {
    LOG(ERROR) << "Failed to read image file.";
    return false;
  }

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

bool Component::ReadHashAndCopyFile(base::File* file,
                                    std::vector<uint8_t>* file_hash,
                                    base::File* out_file) {
  std::unique_ptr<crypto::SecureHash> sha256(
      crypto::SecureHash::Create(crypto::SecureHash::SHA256));
  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;
    sha256->Update(buf, rv);
    if (out_file) {
      out_file->WriteAtCurrentPos(buf, rv);
    }
  } while (bytes_read <= size);

  sha256->Finish(file_hash->data(), file_hash->size());
  return bytes_read == size;
}

bool Component::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;
}

// 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 validating the contents
// and then preserving the unsigned file.
bool Component::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();
}

}  // namespace imageloader
