// 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/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:
// chrome/browser/chromeos/settings/owner_key_util.cc
const char kOwnerKeyFile[] = "/var/lib/whitelist/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() 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[];

  DISALLOW_COPY_AND_ASSIGN(NssUtilImpl);
};

// 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
