// Copyright 2020 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 "cryptohome/user_session.h"

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

#include <base/logging.h>
#include <base/memory/ref_counted.h>

#include <brillo/cryptohome.h>
#include <cryptohome/scrypt_verifier.h>

#include "cryptohome/credentials.h"
#include "cryptohome/crypto/hmac.h"
#include "cryptohome/filesystem_layout.h"
#include "cryptohome/keyset_management.h"
#include "cryptohome/storage/mount.h"

using brillo::cryptohome::home::SanitizeUserName;

namespace cryptohome {

// Message to use when generating a secret for WebAuthn.
constexpr char kWebAuthnSecretHmacMessage[] = "AuthTimeWebAuthnSecret";

UserSession::UserSession() {}
UserSession::~UserSession() {}
UserSession::UserSession(HomeDirs* homedirs,
                         KeysetManagement* keyset_management,
                         const brillo::SecureBlob& salt,
                         const scoped_refptr<Mount> mount)
    : homedirs_(homedirs),
      keyset_management_(keyset_management),
      system_salt_(salt),
      mount_(mount) {}

MountError UserSession::MountVault(const Credentials& credentials,
                                   const Mount::MountArgs& mount_args) {
  const std::string obfuscated_username =
      credentials.GetObfuscatedUsername(system_salt_);
  bool created = false;

  // TODO(chromium:1140868, dlunev): once re-recreation logic is removed, this
  // can be moved to the service level.
  MountError error = MOUNT_ERROR_NONE;
  if (!homedirs_->CryptohomeExists(obfuscated_username, &error)) {
    if (error != MOUNT_ERROR_NONE) {
      LOG(ERROR) << "Failed to check cryptohome existence for : "
                 << obfuscated_username << " error = " << error;
      return error;
    }
    if (!mount_args.create_if_missing) {
      LOG(ERROR) << "Asked to mount nonexistent user";
      return MOUNT_ERROR_USER_DOES_NOT_EXIST;
    }

    if (!homedirs_->Create(credentials.username()) ||
        !keyset_management_->AddInitialKeyset(credentials)) {
      LOG(ERROR) << "Error creating cryptohome.";
      return MOUNT_ERROR_CREATE_CRYPTOHOME_FAILED;
    }
    keyset_management_->UpdateActivityTimestamp(obfuscated_username,
                                                kInitialKeysetIndex, 0);
    created = true;
  }

  // Verifies user's credentials and retrieves the user's file system encryption
  // keys.
  MountError code = MOUNT_ERROR_NONE;
  std::unique_ptr<VaultKeyset> vk =
      keyset_management_->LoadUnwrappedKeyset(credentials, &code);
  if (code != MOUNT_ERROR_NONE) {
    return code;
  }
  if (!vk) {
    return MOUNT_ERROR_FATAL;
  }
  FileSystemKeyset fs_keyset(*vk);

  if (!mount_->MountCryptohome(credentials.username(), fs_keyset, mount_args,
                               created, &code)) {
    // In the weird case where MountCryptohome returns false with ERROR_NONE
    // code report it as FATAL.
    return code == MOUNT_ERROR_NONE ? MOUNT_ERROR_FATAL : code;
  }
  SetCredentials(credentials, vk->GetLegacyIndex());
  UpdateActivityTimestamp(0);

  PrepareWebAuthnSecret(fs_keyset.Key().fek, fs_keyset.Key().fnek);

  return code;
}

MountError UserSession::MountVault(AuthSession* auth_session,
                                   const Mount::MountArgs& mount_args) {
  // Cannot proceed with mount if the AuthSession is not authenticated yet.
  if (auth_session->GetStatus() != AuthStatus::kAuthStatusAuthenticated) {
    return MOUNT_ERROR_FATAL;
  }
  const std::string obfuscated_username =
      SanitizeUserName(auth_session->username());
  // If the AuthSession is authenticated and the user did not exist when
  // AuthSession was started, then that means the user was created.
  bool created = !auth_session->user_exists();

  MountError code = MOUNT_ERROR_NONE;
  const FileSystemKeyset fs_keyset = auth_session->file_system_keyset();

  if (!mount_->MountCryptohome(auth_session->username(), fs_keyset, mount_args,
                               created, &code)) {
    // In the weird case where MountCryptohome returns false with ERROR_NONE
    // code report it as FATAL.
    return code == MOUNT_ERROR_NONE ? MOUNT_ERROR_FATAL : code;
  }
  // Set credentials for verification using AuthSession.
  SetCredentials(auth_session);
  UpdateActivityTimestamp(0);

  PrepareWebAuthnSecret(fs_keyset.Key().fek, fs_keyset.Key().fnek);

  return code;
}

MountError UserSession::MountEphemeral(const Credentials& credentials) {
  MountError code = mount_->MountEphemeralCryptohome(credentials.username());
  if (code == MOUNT_ERROR_NONE) {
    SetCredentials(credentials, -1);
  }
  return code;
}

MountError UserSession::MountGuest() {
  bool status = mount_->MountGuestCryptohome();
  return status ? MOUNT_ERROR_NONE : MOUNT_ERROR_FATAL;
}

bool UserSession::Unmount() {
  UpdateActivityTimestamp(0);
  return mount_->UnmountCryptohome();
}

bool UserSession::UpdateActivityTimestamp(int time_shift_sec) {
  if (!mount_->IsNonEphemeralMounted()) {
    return false;
  }
  return keyset_management_->UpdateActivityTimestamp(
      obfuscated_username_, key_index_, time_shift_sec);
}

base::Value UserSession::GetStatus() const {
  return mount_->GetStatus(key_index_);
}

void UserSession::PrepareWebAuthnSecret(const brillo::SecureBlob& fek,
                                        const brillo::SecureBlob& fnek) {
  // This WebAuthn secret can be rederived upon in-session user auth success
  // since they will unlock the vault keyset.
  const std::string message(kWebAuthnSecretHmacMessage);
  webauthn_secret_ = std::make_unique<brillo::SecureBlob>(
      HmacSha256(brillo::SecureBlob::Combine(fnek, fek),
                 brillo::Blob(message.cbegin(), message.cend())));
  clear_webauthn_secret_timer_.Start(
      FROM_HERE, base::TimeDelta::FromSeconds(5),
      base::BindOnce(&UserSession::ClearWebAuthnSecret,
                     base::Unretained(this)));
}

void UserSession::ClearWebAuthnSecret() {
  webauthn_secret_.reset();
}

std::unique_ptr<brillo::SecureBlob> UserSession::GetWebAuthnSecret() {
  return std::move(webauthn_secret_);
}

bool UserSession::SetCredentials(const Credentials& credentials,
                                 int key_index) {
  obfuscated_username_ = credentials.GetObfuscatedUsername(system_salt_);
  username_ = credentials.username();
  key_data_ = credentials.key_data();
  key_index_ = key_index;

  credential_verifier_.reset(new ScryptVerifier());
  return credential_verifier_->Set(credentials.passkey());
}

void UserSession::SetCredentials(AuthSession* auth_session) {
  username_ = auth_session->username();
  obfuscated_username_ = SanitizeUserName(username_);
  key_data_ = auth_session->current_key_data();
  credential_verifier_ = auth_session->TakeCredentialVerifier();
}

bool UserSession::VerifyUser(const std::string& obfuscated_username) const {
  return obfuscated_username_ == obfuscated_username;
}

bool UserSession::VerifyCredentials(const Credentials& credentials) const {
  ReportTimerStart(kSessionUnlockTimer);

  if (!credential_verifier_) {
    LOG(ERROR) << "Attempt to verify credentials with no verifier set";
    return false;
  }
  if (!VerifyUser(credentials.GetObfuscatedUsername(system_salt_))) {
    return false;
  }
  // If the incoming credentials have no label, then just
  // test the secret.  If it is labeled, then the label must
  // match.
  if (!credentials.key_data().label().empty() &&
      credentials.key_data().label() != key_data_.label()) {
    return false;
  }

  bool status = credential_verifier_->Verify(credentials.passkey());

  ReportTimerStop(kSessionUnlockTimer);

  return status;
}

}  // namespace cryptohome
