// Copyright (c) 2011 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 "login_manager/nss_util.h"

#include <stdint.h>
#include <stdlib.h>

#include <memory>
#include <string>
#include <utility>

#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/memory/ptr_util.h>
#include <base/notreached.h>
#include <base/strings/stringprintf.h>
#include <crypto/nss_util.h>
#include <crypto/nss_util_internal.h>
#include <crypto/rsa_private_key.h>
#include <crypto/scoped_nss_types.h>
#include <crypto/signature_creator.h>
#include <crypto/signature_verifier.h>
#include <brillo/scoped_mount_namespace.h>
#include <keyhi.h>
#include <pk11pub.h>
#include <prerror.h>
#include <secmod.h>
#include <secmodt.h>

using brillo::ScopedMountNamespace;

using crypto::RSAPrivateKey;
using crypto::ScopedPK11Slot;
using crypto::ScopedSECItem;
using crypto::ScopedSECKEYPrivateKey;
using crypto::ScopedSECKEYPublicKey;

namespace {
// This should match the same constant in Chrome tree:
// chromeos/dbus/constants/dbus_paths.cc
const char kOwnerKeyFile[] = "/var/lib/devicesettings/owner.key";

// TODO(hidehiko): Move this to scoped_nss_types.h.
struct CERTSubjectPublicKeyInfoDeleter {
  void operator()(CERTSubjectPublicKeyInfo* ptr) const {
    SECKEY_DestroySubjectPublicKeyInfo(ptr);
  }
};
using ScopedCERTSubjectPublicKeyInfo =
    std::unique_ptr<CERTSubjectPublicKeyInfo, CERTSubjectPublicKeyInfoDeleter>;

}  // namespace

namespace login_manager {
///////////////////////////////////////////////////////////////////////////
// NssUtil

NssUtil::NssUtil() = default;

NssUtil::~NssUtil() = default;

///////////////////////////////////////////////////////////////////////////
// NssUtilImpl

class NssUtilImpl : public NssUtil {
 public:
  NssUtilImpl();
  NssUtilImpl(const NssUtilImpl&) = delete;
  NssUtilImpl& operator=(const NssUtilImpl&) = delete;

  ~NssUtilImpl() override;

  ScopedPK11SlotDescriptor OpenUserDB(
      const base::FilePath& user_homedir,
      const OptionalFilePath& ns_mnt_path) override;

  std::unique_ptr<RSAPrivateKey> GetPrivateKeyForUser(
      const std::vector<uint8_t>& public_key_der,
      PK11SlotDescriptor* user_slot) override;

  std::unique_ptr<RSAPrivateKey> GenerateKeyPairForUser(
      PK11SlotDescriptor* user_slot) override;

  base::FilePath GetOwnerKeyFilePath() override;

  base::FilePath GetNssdbSubpath() override;

  bool CheckPublicKeyBlob(const std::vector<uint8_t>& blob) override;

  bool Verify(const std::vector<uint8_t>& signature,
              const std::vector<uint8_t>& data,
              const std::vector<uint8_t>& public_key) override;

  bool Sign(const std::vector<uint8_t>& data,
            RSAPrivateKey* key,
            std::vector<uint8_t>* out_signature) override;

 private:
  static const uint16_t kKeySizeInBits;
  static const char kNssdbSubpath[];
};

// Defined here, instead of up above, because we need NssUtilImpl.
// static
std::unique_ptr<NssUtil> NssUtil::Create() {
  return std::make_unique<NssUtilImpl>();
}

// We're generating and using 2048-bit RSA keys.
// static
const uint16_t NssUtilImpl::kKeySizeInBits = 2048;
// static
const char NssUtilImpl::kNssdbSubpath[] = ".pki/nssdb";

NssUtilImpl::NssUtilImpl() {
  if (setenv("NSS_SDB_USE_CACHE", "no", 1) == -1)
    PLOG(WARNING) << "Can't set NSS_SDB_USE_CACHE=no in the environment!";
  crypto::EnsureNSSInit();
}

NssUtilImpl::~NssUtilImpl() = default;

ScopedPK11SlotDescriptor NssUtilImpl::OpenUserDB(
    const base::FilePath& user_homedir, const OptionalFilePath& ns_mnt_path) {
  // TODO(cmasone): If we ever try to keep the session_manager alive across
  // user sessions, we'll need to close these persistent DBs.
  base::FilePath db_path(user_homedir.AppendASCII(kNssdbSubpath));
  const std::string modspec =
      base::StringPrintf("configDir='sql:%s' tokenDescription='%s'",
                         db_path.value().c_str(), user_homedir.value().c_str());

  // If necessary, enter the mount namespace where the user mounts exist.
  std::unique_ptr<ScopedMountNamespace> ns_mnt;
  if (ns_mnt_path) {
    ns_mnt = ScopedMountNamespace::CreateFromPath(ns_mnt_path.value());
  }

  ScopedPK11SlotDescriptor res = std::make_unique<PK11SlotDescriptor>();
  res->ns_mnt_path = ns_mnt_path;

  ScopedPK11Slot db_slot(SECMOD_OpenUserDB(modspec.c_str()));
  if (!db_slot.get()) {
    LOG(ERROR) << "Error opening persistent database (" << modspec
               << "): " << PR_GetError();
    res->slot = ScopedPK11Slot();
    return res;
  }

  if (PK11_NeedUserInit(db_slot.get()))
    PK11_InitPin(db_slot.get(), nullptr, nullptr);

  // If we opened successfully, we will have a non-default private key slot.
  if (PK11_IsInternalKeySlot(db_slot.get())) {
    res->slot = ScopedPK11Slot();
    return res;
  }

  res->slot = std::move(db_slot);
  return res;
}

std::unique_ptr<RSAPrivateKey> NssUtilImpl::GetPrivateKeyForUser(
    const std::vector<uint8_t>& public_key_der, PK11SlotDescriptor* desc) {
  if (public_key_der.size() == 0) {
    LOG(ERROR) << "Not checking key because size is 0";
    return nullptr;
  }

  // First, decode and save the public key.
  SECItem key_der;
  key_der.type = siBuffer;
  key_der.data = const_cast<unsigned char*>(&public_key_der[0]);
  key_der.len = public_key_der.size();

  ScopedCERTSubjectPublicKeyInfo spki(
      SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der));
  if (!spki) {
    NOTREACHED();
    return nullptr;
  }

  ScopedSECKEYPublicKey public_key(SECKEY_ExtractPublicKey(spki.get()));
  if (!public_key) {
    NOTREACHED();
    return nullptr;
  }

  // Make sure the key is an RSA key.  If not, that's an error
  if (SECKEY_GetPublicKeyType(public_key.get()) != rsaKey) {
    NOTREACHED();
    return nullptr;
  }

  ScopedSECItem ck_id(PK11_MakeIDFromPubKey(&(public_key->u.rsa.modulus)));
  if (!ck_id) {
    NOTREACHED();
    return nullptr;
  }

  // Search in just the user slot for the key with the given ID.
  // If necessary, enter the mount namespace where the user mounts exist.
  std::unique_ptr<ScopedMountNamespace> ns_mnt;
  if (desc->ns_mnt_path) {
    ns_mnt = ScopedMountNamespace::CreateFromPath(desc->ns_mnt_path.value());
  }
  ScopedSECKEYPrivateKey key(
      PK11_FindKeyByKeyID(desc->slot.get(), ck_id.get(), nullptr));
  if (!key) {
    // We didn't find the key.
    return nullptr;
  }

  return base::WrapUnique(RSAPrivateKey::CreateFromKey(key.get()));
}

std::unique_ptr<RSAPrivateKey> NssUtilImpl::GenerateKeyPairForUser(
    PK11SlotDescriptor* desc) {
  PK11RSAGenParams param;
  param.keySizeInBits = kKeySizeInBits;
  param.pe = 65537L;
  SECKEYPublicKey* public_key_ptr = nullptr;

  // If necessary, enter the mount namespace where the user mounts exist.
  std::unique_ptr<ScopedMountNamespace> ns_mnt;
  if (desc->ns_mnt_path) {
    ns_mnt = ScopedMountNamespace::CreateFromPath(desc->ns_mnt_path.value());
  }

  ScopedSECKEYPrivateKey key(PK11_GenerateKeyPair(
      desc->slot.get(), CKM_RSA_PKCS_KEY_PAIR_GEN, &param, &public_key_ptr,
      PR_TRUE /* permanent */, PR_TRUE /* sensitive */, nullptr));
  ScopedSECKEYPublicKey public_key(public_key_ptr);
  if (!key)
    return nullptr;

  return base::WrapUnique(RSAPrivateKey::CreateFromKey(key.get()));
}

base::FilePath NssUtilImpl::GetOwnerKeyFilePath() {
  return base::FilePath(kOwnerKeyFile);
}

base::FilePath NssUtilImpl::GetNssdbSubpath() {
  return base::FilePath(kNssdbSubpath);
}

bool NssUtilImpl::CheckPublicKeyBlob(const std::vector<uint8_t>& blob) {
  SECItem spki_der;
  spki_der.type = siBuffer;
  spki_der.data = const_cast<uint8_t*>(&blob[0]);
  spki_der.len = blob.size();
  ScopedCERTSubjectPublicKeyInfo spki(
      SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der));
  if (!spki)
    return false;

  ScopedSECKEYPublicKey public_key(SECKEY_ExtractPublicKey(spki.get()));
  return static_cast<bool>(public_key);
}

// This is pretty much just a blind passthrough, so I won't test it
// in the NssUtil unit tests.  I'll test it from a class that uses this API.
bool NssUtilImpl::Verify(const std::vector<uint8_t>& signature,
                         const std::vector<uint8_t>& data,
                         const std::vector<uint8_t>& public_key) {
  crypto::SignatureVerifier verifier;

  if (!verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1,
                           signature.data(), signature.size(),
                           public_key.data(), public_key.size())) {
    LOG(ERROR) << "Could not initialize verifier";
    return false;
  }

  verifier.VerifyUpdate(data.data(), data.size());
  return verifier.VerifyFinal();
}

// This is pretty much just a blind passthrough, so I won't test it
// in the NssUtil unit tests.  I'll test it from a class that uses this API.
bool NssUtilImpl::Sign(const std::vector<uint8_t>& data,
                       RSAPrivateKey* key,
                       std::vector<uint8_t>* out_signature) {
  std::unique_ptr<crypto::SignatureCreator> signer(
      crypto::SignatureCreator::Create(key, crypto::SignatureCreator::SHA1));
  if (!signer->Update(data.data(), data.size()))
    return false;
  return signer->Final(out_signature);
}

}  // namespace login_manager
