// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/net/nss_service.h"

#include <memory>
#include <utility>

#include "base/callback_list.h"
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
#include "base/task/single_thread_task_runner.h"
#include "chrome/browser/ash/login/startup_utils.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chromeos/ash/components/dbus/dbus_thread_manager.h"
#include "chromeos/ash/components/dbus/userdataauth/cryptohome_pkcs11_client.h"
#include "chromeos/ash/components/settings/cros_settings_names.h"
#include "chromeos/ash/components/tpm/tpm_token_info_getter.h"
#include "chromeos/components/kiosk/kiosk_utils.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/nss_util.h"
#include "crypto/nss_util_internal.h"
#include "net/cert/nss_cert_database_chromeos.h"

using content::BrowserThread;

namespace {

// The following four functions are responsible for initializing NSS for each
// profile on ChromeOS, which has a separate NSS database and TPM slot
// per-profile.
//
// Initialization basically follows these steps:
// 1) Get some info from user_manager::UserManager about the User for this
// profile.
// 2) Tell nss_util to initialize the software slot for this profile.
// 3) Wait for the TPM module to be loaded by nss_util if it isn't already.
// 4) Ask CryptohomePkcs11Client which TPM slot id corresponds to this profile.
// 5) Tell nss_util to use that slot id on the TPM module.
//
// Some of these steps must happen on the UI thread, others must happen on the
// IO thread:
//               UI thread                              IO Thread
//
//  NssService::NssService
//                   |
//  ProfileHelper::Get()->GetUserByProfile()
//                   \---------------------------------------v
//                                                 StartNSSInitOnIOThread
//                                                           |
//                                          crypto::InitializeNSSForChromeOSUser
//                                                           |
//                                                crypto::IsTPMTokenEnabled
//                                                           |
//                                          StartTPMSlotInitializationOnIOThread
//                   v---------------------------------------/
//     GetTPMInfoForUserOnUIThread
//                   |
//   ash::TPMTokenInfoGetter::Start
//                   |
//     DidGetTPMInfoForUserOnUIThread
//                   \---------------------------------------v
//                                          crypto::InitializeTPMForChromeOSUser

void DidGetTPMInfoForUserOnUIThread(
    std::unique_ptr<ash::TPMTokenInfoGetter> getter,
    const std::string& username_hash,
    std::optional<user_data_auth::TpmTokenInfo> token_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (token_info.has_value() && token_info->slot() != -1) {
    DVLOG(1) << "Got TPM slot for " << username_hash << ": "
             << token_info->slot();
    content::GetIOThreadTaskRunner({})->PostTask(
        FROM_HERE, base::BindOnce(&crypto::InitializeTPMForChromeOSUser,
                                  username_hash, token_info->slot()));
  } else {
    NOTREACHED() << "TPMTokenInfoGetter reported invalid token.";
  }
}

void GetTPMInfoForUserOnUIThread(const AccountId& account_id,
                                 const std::string& username_hash) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DVLOG(1) << "Getting TPM info from cryptohome for "
           << " " << account_id.Serialize() << " " << username_hash;
  std::unique_ptr<ash::TPMTokenInfoGetter> scoped_token_info_getter =
      ash::TPMTokenInfoGetter::CreateForUserToken(
          account_id, ash::CryptohomePkcs11Client::Get(),
          base::SingleThreadTaskRunner::GetCurrentDefault());
  ash::TPMTokenInfoGetter* token_info_getter = scoped_token_info_getter.get();

  // Bind |token_info_getter| to the callback to ensure it does not go away
  // before TPM token info is fetched.
  token_info_getter->Start(base::BindOnce(&DidGetTPMInfoForUserOnUIThread,
                                          std::move(scoped_token_info_getter),
                                          username_hash));
}

void StartTPMSlotInitializationOnIOThread(const AccountId& account_id,
                                          const std::string& username_hash,
                                          bool is_tpm_token_enabled) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (!is_tpm_token_enabled) {
    crypto::InitializePrivateSoftwareSlotForChromeOSUser(username_hash);
    return;
  }

  content::GetUIThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(&GetTPMInfoForUserOnUIThread, account_id, username_hash));
}

void StartNSSInitOnIOThread(const AccountId& account_id,
                            const std::string& username_hash,
                            const base::FilePath& path,
                            bool is_kiosk) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DVLOG(1) << "Starting NSS init for " << account_id.Serialize()
           << "  hash:" << username_hash;

  // Make sure NSS is initialized for the user.
  if (is_kiosk) {
    // Kiosk sessions don't have the UI that could result in interactions with
    // the public slot. Kiosk users are also not owner users and can't have
    // the owner key in the public slot. So the public slot is not used in
    // Kiosk sessions and can be replaced by the internal slot. This is done
    // mainly because Chrome sometimes fails to load the public slot and has
    // to crash because of that.
    crypto::InitializeNSSForChromeOSUserWithSlot(
        username_hash, crypto::ScopedPK11Slot(PK11_GetInternalKeySlot()));
  } else {
    crypto::InitializeNSSForChromeOSUser(username_hash, path);
  }

  // Check if it's OK to initialize TPM for the user before continuing. This
  // may not be the case if the TPM slot initialization was previously
  // requested for the same user.
  if (!crypto::ShouldInitializeTPMForChromeOSUser(username_hash))
    return;

  crypto::WillInitializeTPMForChromeOSUser(username_hash);
  crypto::IsTPMTokenEnabled(base::BindOnce(
      &StartTPMSlotInitializationOnIOThread, account_id, username_hash));
}

}  // namespace

// Creates and manages a NSSCertDatabaseChromeOS. Created on the UI thread, but
// all other calls are made on the IO thread.
class NssService::NSSCertDatabaseChromeOSManager {
 public:
  using GetNSSCertDatabaseCallback =
      base::OnceCallback<void(net::NSSCertDatabase*)>;

  NSSCertDatabaseChromeOSManager(std::string username_hash,
                                 bool enable_system_slot)
      : username_hash_(std::move(username_hash)),
        enable_system_slot_(enable_system_slot) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
  }

  NSSCertDatabaseChromeOSManager(const NSSCertDatabaseChromeOSManager&) =
      delete;
  NSSCertDatabaseChromeOSManager& operator=(
      const NSSCertDatabaseChromeOSManager&) = delete;

  ~NSSCertDatabaseChromeOSManager() { DCHECK_CURRENTLY_ON(BrowserThread::IO); }

  net::NSSCertDatabase* GetNSSCertDatabase(
      GetNSSCertDatabaseCallback callback) {
    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

    if (nss_cert_database_) {
      return nss_cert_database_.get();
    }

    ready_callback_list_.AddUnsafe(std::move(callback));

    if (!database_creation_started_) {
      database_creation_started_ = true;
      content::GetIOThreadTaskRunner({})->PostTask(
          FROM_HERE,
          base::BindOnce(&NSSCertDatabaseChromeOSManager::StartDatabaseCreation,
                         weak_ptr_factory_.GetWeakPtr()));
    }

    return nullptr;
  }

 private:
  void StartDatabaseCreation() {
    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

    crypto::ScopedPK11Slot private_slot(crypto::GetPrivateSlotForChromeOSUser(
        username_hash_,
        base::BindOnce(&NSSCertDatabaseChromeOSManager::DidGetPrivateSlot,
                       weak_ptr_factory_.GetWeakPtr())));
    if (private_slot)
      DidGetPrivateSlot(std::move(private_slot));
  }

  void DidGetPrivateSlot(crypto::ScopedPK11Slot private_slot) {
    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

    if (!enable_system_slot_) {
      CreateDatabase(std::move(private_slot),
                     /*system_slot=*/crypto::ScopedPK11Slot());
      return;
    }

    crypto::GetSystemNSSKeySlot(base::BindOnce(
        &NSSCertDatabaseChromeOSManager::CreateDatabase,
        weak_ptr_factory_.GetWeakPtr(), std::move(private_slot)));
  }

  void CreateDatabase(crypto::ScopedPK11Slot private_slot,
                      crypto::ScopedPK11Slot system_slot) {
    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

    auto public_slot = crypto::GetPublicSlotForChromeOSUser(username_hash_);

    if (!public_slot) {
      // The public slot can be null in tests. Consider using FakeNssService if
      // a specific NSS behavior is required in tests.
      // Sometimes the slot also fails to load. This will prevent importing new
      // client certificates into it and the owner key won't be found, but
      // overall this is not a critical error and should resolve itself after a
      // reboot. The existing certificates should keep working. Other slots are
      // unaffected and certificates for the public slot are currently
      // dual-written into the private slot as well.
      // Initialize the slot with the read-only internal NSS slot to prevent
      // ChromeOS from crashing on the CHECK in the NSSCertDatabase constructor.
      public_slot = crypto::ScopedPK11Slot(PK11_GetInternalKeySlot());
    }

    nss_cert_database_ = std::make_unique<net::NSSCertDatabaseChromeOS>(
        std::move(public_slot), std::move(private_slot));

    if (system_slot)
      nss_cert_database_->SetSystemSlot(std::move(system_slot));

    ready_callback_list_.Notify(nss_cert_database_.get());
  }

  const std::string username_hash_;
  bool enable_system_slot_ = false;
  bool database_creation_started_ = false;

  std::unique_ptr<net::NSSCertDatabaseChromeOS> nss_cert_database_;
  base::OnceCallbackList<GetNSSCertDatabaseCallback::RunType>
      ready_callback_list_;

  base::WeakPtrFactory<NSSCertDatabaseChromeOSManager> weak_ptr_factory_{this};
};

NssService::NssService(content::BrowserContext* context) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(context);

  Profile* profile = Profile::FromBrowserContext(context);
  const user_manager::User* user =
      ash::ProfileHelper::Get()->GetUserByProfile(profile);
  // No need to initialize NSS for users with empty username hash:
  // Getters for a user's NSS slots always return a null slot if the user's
  // username hash is empty, even when the NSS is not initialized for the
  // user.
  std::string username_hash;
  bool enable_system_slot = false;
  if (user && !user->username_hash().empty()) {
    username_hash = user->username_hash();
    DCHECK(!username_hash.empty());
    content::GetIOThreadTaskRunner({})->PostTask(
        FROM_HERE, base::BindOnce(&StartNSSInitOnIOThread, user->GetAccountId(),
                                  username_hash, profile->GetPath(),
                                  chromeos::IsKioskSession()));

    enable_system_slot = user->IsAffiliated();
  }

  DCHECK(!(username_hash.empty() && enable_system_slot));

  nss_cert_database_manager_ = std::make_unique<NSSCertDatabaseChromeOSManager>(
      std::move(username_hash), enable_system_slot);
}

NssService::~NssService() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  content::GetIOThreadTaskRunner({})->DeleteSoon(
      FROM_HERE, std::move(nss_cert_database_manager_));
}

NssCertDatabaseGetter NssService::CreateNSSCertDatabaseGetterForIOThread() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return base::BindOnce(&NSSCertDatabaseChromeOSManager::GetNSSCertDatabase,
                        base::Unretained(nss_cert_database_manager_.get()));
}
