// Copyright 2018 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 "oobe_config/usb_utils.h"

#include <string>
#include <vector>

#include <base/files/file_util.h>
#include <base/strings/string_util.h>
#include <brillo/process.h>
#include <openssl/evp.h>
#include <openssl/pem.h>

using base::FilePath;
using crypto::ScopedEVP_PKEY;
using std::string;
using std::vector;

namespace oobe_config {

const char kStatefulDir[] = "/mnt/stateful_partition/";
const char kUnencryptedOobeConfigDir[] = "unencrypted/oobe_auto_config/";
const char kConfigFile[] = "config.json";
const char kDomainFile[] = "enrollment_domain";
const char kKeyFile[] = "validation_key.pub";
const char kDevDiskById[] = "/dev/disk/by-id/";
const char kUsbDevicePathSigFile[] = "usb_device_path.sig";
const char kStoreDir[] = "/var/lib/oobe_config_restore/";
const char kOobeConfigRestoreUser[] = "oobe_config_restore";

bool Sign(const FilePath& priv_key,
          const string& src_content,
          const FilePath& dst) {
  if (src_content.empty()) {
    LOG(ERROR) << "Input content string cannot be empty!";
    return false;
  }
  // Reading the private key.
  base::ScopedFILE pkf(base::OpenFile(priv_key, "r"));
  if (!pkf) {
    PLOG(ERROR) << "Failed to open the private key file " << priv_key.value();
    return false;
  }
  crypto::ScopedEVP_PKEY private_key(
      PEM_read_PrivateKey(pkf.get(), nullptr, nullptr, nullptr));
  if (!private_key) {
    PLOG(ERROR) << "Failed to read the PEM private key file "
                << priv_key.value();
    return false;
  }

  // Creating the context.
  crypto::ScopedEVP_MD_CTX mdctx(EVP_MD_CTX_create());
  if (!mdctx) {
    LOG(ERROR) << "Failed to create a EVP_MD context.";
    return false;
  }

  // Signing the |src_content|.
  size_t signature_len = 0;
  if (EVP_DigestSignInit(mdctx.get(), nullptr, EVP_sha256(), nullptr,
                         private_key.get()) != 1 ||
      EVP_DigestSignUpdate(mdctx.get(), src_content.c_str(),
                           src_content.length()) != 1 ||
      EVP_DigestSignFinal(mdctx.get(), nullptr, &signature_len) != 1) {
    LOG(ERROR) << "Failed to sign the content.";
  }
  // Now we know the size of the signature, let's get it.
  crypto::ScopedOpenSSLBytes signature(reinterpret_cast<unsigned char*>(
      OPENSSL_malloc(sizeof(unsigned char) * signature_len)));
  if (!signature) {
    PLOG(ERROR) << "Failed to malloc " << signature_len
                << " bytes for the signature.";
    return false;
  }
  if (EVP_DigestSignFinal(mdctx.get(), signature.get(), &signature_len) != 1) {
    LOG(ERROR) << "Getting the signature failed; however, technically this"
               << " should not happen!";
    return false;
  }
  if (!base::WriteFile(dst, reinterpret_cast<char*>(signature.get()),
                       signature_len)) {
    PLOG(ERROR) << "Failed to write the signature to file " << dst.value();
    return false;
  }

  return true;
}

bool Sign(const FilePath& priv_key, const FilePath& src, const FilePath& dst) {
  // Reading the source file.
  string src_content;
  if (!base::ReadFileToString(src, &src_content)) {
    PLOG(ERROR) << "Failed to read the source file " << src.value();
    return false;
  }

  return Sign(priv_key, src_content, dst);
}

bool ReadPublicKey(const FilePath& pub_key_file, ScopedEVP_PKEY* pub_key) {
  base::ScopedFILE pkf(base::OpenFile(pub_key_file, "r"));
  if (!pkf) {
    PLOG(ERROR) << "Failed to open the public key file "
                << pub_key_file.value();
    return false;
  }
  pub_key->reset(PEM_read_PUBKEY(pkf.get(), nullptr, nullptr, nullptr));
  if (!(*pub_key)) {
    LOG(ERROR) << "Failed to read the PEM public key file "
               << pub_key_file.value();
    return false;
  }
  return true;
}

bool VerifySignature(const string& message,
                     const string& signature,
                     const ScopedEVP_PKEY& pub_key) {
  crypto::ScopedEVP_MD_CTX mdctx(EVP_MD_CTX_create());
  if (!mdctx) {
    LOG(ERROR) << "Failed to create a EVP_MD context.";
    return false;
  }
  if (EVP_DigestVerifyInit(mdctx.get(), nullptr, EVP_sha256(), nullptr,
                           pub_key.get()) != 1 ||
      EVP_DigestVerifyUpdate(mdctx.get(), message.c_str(), message.length()) !=
          1 ||
      EVP_DigestVerifyFinal(
          mdctx.get(), reinterpret_cast<const unsigned char*>(signature.data()),
          signature.size()) != 1) {
    LOG(ERROR) << "Failed to verify the signature.";
    return false;
  }
  return true;
}

}  // namespace oobe_config
