// Copyright (c) 2012 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.

// Contains the implementation of class Crypto

#include "cryptohome/crypto.h"

#include <sys/types.h>

#include <crypto/sha2.h>
#include <limits>
#include <map>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <unistd.h>
#include <utility>

#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <brillo/secure_blob.h>
extern "C" {
#include <scrypt/scryptenc.h>
}

#include "cryptohome/attestation.pb.h"
#include "cryptohome/challenge_credential_auth_block.h"
#include "cryptohome/cryptohome_common.h"
#include "cryptohome/cryptohome_metrics.h"
#include "cryptohome/cryptolib.h"
#include "cryptohome/double_wrapped_compat_auth_block.h"
#include "cryptohome/key_objects.h"
#include "cryptohome/le_credential_manager_impl.h"
#include "cryptohome/libscrypt_compat.h"
#include "cryptohome/libscrypt_compat_auth_block.h"
#include "cryptohome/pin_weaver_auth_block.h"
#include "cryptohome/platform.h"
#include "cryptohome/tpm_auth_block.h"
#include "cryptohome/tpm_init.h"
#include "cryptohome/vault_keyset.h"

using base::FilePath;
using brillo::SecureBlob;

namespace cryptohome {

namespace {

// Location where we store the Low Entropy (LE) credential manager related
// state.
const char kSignInHashTreeDir[] = "/home/.shadow/low_entropy_creds";

// Maximum size of the salt file.
const int64_t kSystemSaltMaxSize = (1 << 20);  // 1 MB

// File permissions of salt file (modulo umask).
const mode_t kSaltFilePermissions = 0644;

// This generates the reset secret for PinWeaver credentials. Doing it per
// secret is confusing and difficult to maintain. It's necessary so that
// different credentials can all maintain  the same reset secret (i.e. the
// password resets the PIN), without storing said secret in the clear. In the
// USS key hierarchy, only one reset secret will exist.
bool GenerateResetSecret(const VaultKeyset& vault_keyset,
                         brillo::SecureBlob* reset_secret,
                         brillo::SecureBlob* reset_salt) {
  DCHECK(reset_secret);
  DCHECK(reset_salt);

  // For new users, a reset seed is stored in the VaultKeyset, which is derived
  // into the reset secret.
  if (!vault_keyset.reset_seed().empty()) {
    SecureBlob local_reset_seed(vault_keyset.reset_seed().begin(),
                                vault_keyset.reset_seed().end());
    *reset_salt = CryptoLib::CreateSecureRandomBlob(kAesBlockSize);
    *reset_secret = CryptoLib::HmacSha256(*reset_salt, local_reset_seed);
    return true;
  }

  // When a user credential is being migrated (such as the password), the reset
  // secret needs to remain the same to unlock the PIN. In this case, the reset
  // secret is passed through the vault keyset.
  if (!vault_keyset.reset_secret().empty()) {
    reset_secret->assign(vault_keyset.reset_secret().begin(),
                         vault_keyset.reset_secret().end());
    return true;
  }
  LOG(ERROR) << "The VaultKeyset doesn't have a reset seed, so we can't"
                " set up an LE credential.";
  return false;
}

void DecryptAuthorizationData(const SerializedVaultKeyset& serialized,
                              VaultKeyset* keyset,
                              const SecureBlob& vkk_key,
                              const SecureBlob& vkk_iv) {
  // Use the same key to unwrap the wrapped authorization data.
  if (serialized.key_data().authorization_data_size() > 0) {
    KeyData* key_data = keyset->mutable_serialized()->mutable_key_data();
    for (int auth_data_i = 0; auth_data_i < key_data->authorization_data_size();
         ++auth_data_i) {
      KeyAuthorizationData* auth_data =
          key_data->mutable_authorization_data(auth_data_i);
      for (int secret_i = 0; secret_i < auth_data->secrets_size(); ++secret_i) {
        KeyAuthorizationSecret* secret = auth_data->mutable_secrets(secret_i);
        if (!secret->wrapped() || !secret->has_symmetric_key())
          continue;
        SecureBlob encrypted_auth_key(secret->symmetric_key());
        SecureBlob clear_key;
        // Is it reasonable to use this key here as well?
        if (!CryptoLib::AesDecryptDeprecated(encrypted_auth_key, vkk_key,
                                             vkk_iv, &clear_key)) {
          LOG(ERROR) << "Failed to unwrap a symmetric authorization key:"
                     << " (" << auth_data_i << "," << secret_i << ")";
          // This does not force a failure to use the keyset.
          continue;
        }
        secret->set_symmetric_key(clear_key.to_string());
        secret->set_wrapped(false);
      }
    }
  }
}

bool UnwrapVKKVaultKeyset(const SerializedVaultKeyset& serialized,
                          const KeyBlobs& vkk_data,
                          VaultKeyset* keyset,
                          CryptoError* error) {
  const SecureBlob& vkk_key = vkk_data.vkk_key.value();
  const SecureBlob& vkk_iv = vkk_data.vkk_iv.value();
  const SecureBlob& chaps_iv = vkk_data.chaps_iv.value();
  const SecureBlob& auth_data_iv = vkk_data.authorization_data_iv.value();

  // Decrypt the keyset protobuf.
  SecureBlob local_encrypted_keyset(serialized.wrapped_keyset().begin(),
                                    serialized.wrapped_keyset().end());
  SecureBlob plain_text;

  if (!CryptoLib::AesDecryptDeprecated(local_encrypted_keyset, vkk_key, vkk_iv,
                                       &plain_text)) {
    LOG(ERROR) << "AES decryption failed for vault keyset.";
    PopulateError(error, CryptoError::CE_OTHER_CRYPTO);
    return false;
  }
  if (!keyset->FromKeysBlob(plain_text)) {
    LOG(ERROR) << "Failed to decode the keys blob.";
    PopulateError(error, CryptoError::CE_OTHER_CRYPTO);
    return false;
  }

  // Decrypt the chaps key.
  if (serialized.has_wrapped_chaps_key()) {
    SecureBlob local_wrapped_chaps_key(serialized.wrapped_chaps_key());
    SecureBlob unwrapped_chaps_key;

    if (!CryptoLib::AesDecryptDeprecated(local_wrapped_chaps_key, vkk_key,
                                         chaps_iv, &unwrapped_chaps_key)) {
      LOG(ERROR) << "AES decryption failed for chaps key.";
      PopulateError(error, CryptoError::CE_OTHER_CRYPTO);
      return false;
    }

    keyset->set_chaps_key(unwrapped_chaps_key);
  }

  // Decrypt the reset seed.
  if (vkk_data.wrapped_reset_seed != base::nullopt &&
      !vkk_data.wrapped_reset_seed.value().empty()) {
    SecureBlob unwrapped_reset_seed;
    SecureBlob local_wrapped_reset_seed =
        SecureBlob(serialized.wrapped_reset_seed());
    SecureBlob local_reset_iv = SecureBlob(serialized.reset_iv());

    if (!CryptoLib::AesDecryptDeprecated(local_wrapped_reset_seed, vkk_key,
                                         local_reset_iv,
                                         &unwrapped_reset_seed)) {
      LOG(ERROR) << "AES decryption failed for reset seed.";
      PopulateError(error, CryptoError::CE_OTHER_CRYPTO);
      return false;
    }

    keyset->set_reset_seed(unwrapped_reset_seed);
  }

  // TODO(kerrnel): Audit if authorization data is used anywhere.
  DecryptAuthorizationData(serialized, keyset, vkk_key, auth_data_iv);

  return true;
}

bool UnwrapScryptVaultKeyset(const SerializedVaultKeyset& serialized,
                             const KeyBlobs& vkk_data,
                             VaultKeyset* keyset,
                             CryptoError* error) {
  SecureBlob blob = SecureBlob(serialized.wrapped_keyset());
  SecureBlob decrypted(blob.size());
  if (!LibScryptCompat::Decrypt(blob, vkk_data.scrypt_key.value(),
                                &decrypted)) {
    return false;
  }

  if (serialized.has_wrapped_chaps_key()) {
    SecureBlob chaps_key;
    SecureBlob wrapped_chaps_key = SecureBlob(serialized.wrapped_chaps_key());
    chaps_key.resize(wrapped_chaps_key.size());
    if (!LibScryptCompat::Decrypt(
            wrapped_chaps_key, vkk_data.chaps_scrypt_key.value(), &chaps_key)) {
      return false;
    }
    keyset->set_chaps_key(chaps_key);
  }

  if (serialized.has_wrapped_reset_seed()) {
    SecureBlob reset_seed;
    SecureBlob wrapped_reset_seed = SecureBlob(serialized.wrapped_reset_seed());
    reset_seed.resize(wrapped_reset_seed.size());
    if (!LibScryptCompat::Decrypt(
            wrapped_reset_seed, vkk_data.scrypt_wrapped_reset_seed_key.value(),
            &reset_seed)) {
      return false;
    }
    keyset->set_reset_seed(reset_seed);
  }

  // There is a SHA hash included at the end of the decrypted blob. However,
  // scrypt already appends a MAC, so if the payload is corrupted we will fail
  // on the first call to DecryptScryptBlob.
  // TODO(crbug.com/984782): get rid of this entirely.
  if (decrypted.size() < SHA_DIGEST_LENGTH) {
    LOG(ERROR) << "Message length underflow: " << decrypted.size() << " bytes?";
    return false;
  }
  decrypted.resize(decrypted.size() - SHA_DIGEST_LENGTH);
  keyset->FromKeysBlob(decrypted);
  return true;
}

}  // namespace

// File name of the system salt file.
const char kSystemSaltFile[] = "salt";

Crypto::Crypto(Platform* platform)
    : use_tpm_(false),
      tpm_(NULL),
      platform_(platform),
      tpm_init_(NULL),
      disable_logging_for_tests_(false) {}

Crypto::~Crypto() {
}

bool Crypto::Init(TpmInit* tpm_init) {
  if (use_tpm_) {
    CHECK(tpm_init) << "Crypto wanted to use TPM but was not provided a TPM";
    if (tpm_ == NULL) {
      tpm_ = tpm_init->get_tpm();
    }
    tpm_init_ = tpm_init;
    tpm_init_->SetupTpm(true);
    if (tpm_->GetLECredentialBackend() &&
        tpm_->GetLECredentialBackend()->IsSupported()) {
      le_manager_ = std::make_unique<LECredentialManagerImpl>(
          tpm_->GetLECredentialBackend(), base::FilePath(kSignInHashTreeDir));
    }
  }
  return true;
}

CryptoError Crypto::EnsureTpm(bool reload_key) const {
  CryptoError result = CryptoError::CE_NONE;
  if (tpm_ && tpm_init_) {
    if (reload_key || !tpm_init_->HasCryptohomeKey()) {
      tpm_init_->SetupTpm(true);
    }
  }
  return result;
}

bool Crypto::PasskeyToTokenAuthData(const brillo::SecureBlob& passkey,
                                    const FilePath& salt_file,
                                    SecureBlob* auth_data) const {
  // Use the scrypt algorithm to derive auth data from the passkey.
  const size_t kAuthDataSizeBytes = 32;
  // The following scrypt parameters are based on Colin Percival's interactive
  // login example in http://www.tarsnap.com/scrypt/scrypt-slides.pdf and
  // adjusted for ~100ms performance on slower models. The performance is
  // dependant on CPU and memory performance.
  const uint64_t kScryptParameterN = (1 << 11);
  const uint32_t kScryptParameterR = 8;
  const uint32_t kScryptParameterP = 1;
  const unsigned int kSaltLength = 32;
  SecureBlob salt;
  if (!GetOrCreateSalt(salt_file, kSaltLength, false, &salt)) {
    LOG(ERROR) << "Failed to get authorization data salt.";
    return false;
  }

  SecureBlob local_auth_data;
  local_auth_data.resize(kAuthDataSizeBytes);
  if (0 != CryptoLib::Scrypt(passkey, salt, kScryptParameterN,
                             kScryptParameterR, kScryptParameterP,
                             &local_auth_data)) {
    LOG(ERROR) << "Scrypt key derivation failed.";
    return false;
  }

  auth_data->swap(local_auth_data);
  return true;
}

bool Crypto::GetOrCreateSalt(const FilePath& path,
                             size_t length,
                             bool force,
                             SecureBlob* salt) const {
  int64_t file_len = 0;
  if (platform_->FileExists(path)) {
    if (!platform_->GetFileSize(path, &file_len)) {
      LOG(ERROR) << "Can't get file len for " << path.value();
      return false;
    }
  }
  SecureBlob local_salt;
  if (force || file_len == 0 || file_len > kSystemSaltMaxSize) {
    LOG(ERROR) << "Creating new salt at " << path.value()
               << " (" << force << ", " << file_len << ")";
    // If this salt doesn't exist, automatically create it.
    local_salt = CryptoLib::CreateSecureRandomBlob(length);
    if (!platform_->WriteSecureBlobToFileAtomicDurable(
            path, local_salt, kSaltFilePermissions)) {
      LOG(ERROR) << "Could not write user salt";
      return false;
    }
  } else {
    local_salt.resize(file_len);
    if (!platform_->ReadFileToSecureBlob(path, &local_salt)) {
      LOG(ERROR) << "Could not read salt file of length " << file_len;
      return false;
    }
  }
  salt->swap(local_salt);
  return true;
}

void Crypto::PasswordToPasskey(const char* password,
                               const brillo::SecureBlob& salt,
                               SecureBlob* passkey) {
  CHECK(password);

  std::string ascii_salt = CryptoLib::SecureBlobToHex(salt);
  // Convert a raw password to a password hash
  SHA256_CTX sha_context;
  SecureBlob md_value(SHA256_DIGEST_LENGTH);

  SHA256_Init(&sha_context);
  SHA256_Update(&sha_context, ascii_salt.data(), ascii_salt.length());
  SHA256_Update(&sha_context, password, strlen(password));
  SHA256_Final(md_value.data(), &sha_context);

  md_value.resize(SHA256_DIGEST_LENGTH / 2);
  SecureBlob local_passkey(SHA256_DIGEST_LENGTH);
  CryptoLib::SecureBlobToHexToBuffer(md_value,
                                     local_passkey.data(),
                                     local_passkey.size());
  passkey->swap(local_passkey);
}

bool Crypto::UnwrapVaultKeyset(const SerializedVaultKeyset& serialized,
                               const KeyBlobs& vkk_data,
                               VaultKeyset* keyset,
                               CryptoError* error) const {
  bool has_vkk_key = vkk_data.vkk_key != base::nullopt &&
                     vkk_data.vkk_iv != base::nullopt &&
                     vkk_data.chaps_iv != base::nullopt &&
                     vkk_data.authorization_data_iv != base::nullopt;
  bool has_scrypt_key = vkk_data.scrypt_key != base::nullopt;

  if (has_vkk_key && !has_scrypt_key) {
    return UnwrapVKKVaultKeyset(serialized, vkk_data, keyset, error);
  } else if (has_scrypt_key && !has_vkk_key) {
    return UnwrapScryptVaultKeyset(serialized, vkk_data, keyset, error);
  } else {
    DLOG(FATAL) << "An invalid key combination exists";
    return false;
  }
}

bool Crypto::DecryptScrypt(const SerializedVaultKeyset& serialized,
                           const SecureBlob& key,
                           CryptoError* error,
                           VaultKeyset* keyset) const {
  SecureBlob blob = SecureBlob(serialized.wrapped_keyset());
  SecureBlob decrypted(blob.size());
  if (!CryptoLib::DecryptScryptBlob(blob, key, &decrypted, error)) {
    LOG(ERROR) << "Wrapped keyset Scrypt decrypt failed.";
    return false;
  }

  bool chaps_key_present = serialized.has_wrapped_chaps_key();
  if (chaps_key_present) {
    SecureBlob chaps_key;
    SecureBlob wrapped_chaps_key = SecureBlob(serialized.wrapped_chaps_key());
    chaps_key.resize(wrapped_chaps_key.size());
    // Perform a Scrypt operation on wrapped chaps key.
    if (!CryptoLib::DecryptScryptBlob(wrapped_chaps_key, key, &chaps_key,
                                      error)) {
      LOG(ERROR) << "Chaps key scrypt decrypt failed.";
      return false;
    }
    keyset->set_chaps_key(chaps_key);
  }

  if (serialized.has_wrapped_reset_seed()) {
    SecureBlob reset_seed;
    SecureBlob wrapped_reset_seed = SecureBlob(serialized.wrapped_reset_seed());
    reset_seed.resize(wrapped_reset_seed.size());
    // Perform a Scrypt operation on wrapped reset seed.
    if (!CryptoLib::DecryptScryptBlob(wrapped_reset_seed, key, &reset_seed,
                                      error)) {
      LOG(ERROR) << "Reset seed scrypt decrypt failed.";
      return false;
    }
    keyset->set_reset_seed(reset_seed);
  }

  // There is a SHA hash included at the end of the decrypted blob. However,
  // scrypt already appends a MAC, so if the payload is corrupted we will fail
  // on the first call to DecryptScryptBlob.
  // TODO(crbug.com/984782): get rid of this entirely.
  if (decrypted.size() < SHA_DIGEST_LENGTH) {
    LOG(ERROR) << "Message length underflow: " << decrypted.size() << " bytes?";
    return false;
  }
  decrypted.resize(decrypted.size() - SHA_DIGEST_LENGTH);
  keyset->FromKeysBlob(decrypted);
  return true;
}

bool Crypto::NeedsPcrBinding(const uint64_t& label) const {
  DCHECK(le_manager_)
      << "le_manage_ doesn't exist when calling NeedsPcrBinding()";
  return le_manager_->NeedsPcrBinding(label);
}

bool Crypto::DecryptVaultKeyset(const SerializedVaultKeyset& serialized,
                                const SecureBlob& vault_key,
                                bool locked_to_single_user,
                                unsigned int* crypt_flags, CryptoError* error,
                                VaultKeyset* vault_keyset) const {
  if (crypt_flags)
    *crypt_flags = serialized.flags();
  PopulateError(error, CryptoError::CE_NONE);

  unsigned int flags = serialized.flags();

  if (flags & SerializedVaultKeyset::LE_CREDENTIAL) {
    PinWeaverAuthBlock pin_weaver_auth(le_manager_.get(), tpm_init_);

    AuthInput auth_input = { vault_key };
    AuthBlockState auth_state = { serialized };
    KeyBlobs vkk_data;
    if (!pin_weaver_auth.Derive(auth_input, auth_state, &vkk_data, error)) {
      return false;
    }

    // This is possible to be empty if an old version of CR50 is running.
    if (vkk_data.reset_secret.has_value() &&
        !vkk_data.reset_secret.value().empty()) {
      vault_keyset->set_reset_secret(vkk_data.reset_secret.value());
    }

    return UnwrapVaultKeyset(serialized, vkk_data, vault_keyset, error);
  }

  if (flags & SerializedVaultKeyset::SIGNATURE_CHALLENGE_PROTECTED) {
    AuthInput user_input = {vault_key};
    AuthBlockState auth_state = {serialized};
    KeyBlobs vkk_data;
    ChallengeCredentialAuthBlock auth_block;
    if (!auth_block.Derive(user_input, auth_state, &vkk_data, error)) {
      return false;
    }
    return UnwrapVaultKeyset(serialized, vkk_data, vault_keyset, error);
  }

  if (flags & SerializedVaultKeyset::SCRYPT_WRAPPED &&
      flags & SerializedVaultKeyset::TPM_WRAPPED) {
    LOG(ERROR) << "Keyset wrapped with both TPM and Scrypt?";
    ReportCryptohomeError(cryptohome::kBothTpmAndScryptWrappedKeyset);

    AuthInput auth_input = {vault_key};
    AuthBlockState auth_state = {serialized};
    KeyBlobs vkk_data;
    DoubleWrappedCompatAuthBlock auth_block(tpm_, tpm_init_);
    if (!auth_block.Derive(auth_input, auth_state, &vkk_data, error)) {
      return false;
    }
    return UnwrapVaultKeyset(serialized, vkk_data, vault_keyset, error);
  }

  if (flags & SerializedVaultKeyset::TPM_WRAPPED) {
    KeyBlobs vkk_data;
    AuthInput auth_input;
    auth_input.user_input = vault_key;
    auth_input.locked_to_single_user = locked_to_single_user;

    AuthBlockState auth_state = { serialized };
    TpmAuthBlock tpm_auth(tpm_, tpm_init_);
    if (!tpm_auth.Derive(auth_input, auth_state, &vkk_data, error)) {
      return false;
    }

    return UnwrapVaultKeyset(serialized, vkk_data, vault_keyset, error);
  }

  if (flags & SerializedVaultKeyset::SCRYPT_WRAPPED) {
    KeyBlobs vkk_data;
    AuthInput auth_input;
    auth_input.user_input = vault_key;
    auth_input.locked_to_single_user = locked_to_single_user;

    AuthBlockState auth_state = { serialized };
    LibScryptCompatAuthBlock auth_block;
    if (!auth_block.Derive(auth_input, auth_state, &vkk_data, error)) {
      return false;
    }

    return UnwrapVaultKeyset(serialized, vkk_data, vault_keyset, error);
  }

  LOG(ERROR) << "Keyset wrapped with unknown method.";
  return false;
}

bool Crypto::GenerateEncryptedRawKeyset(const VaultKeyset& vault_keyset,
                                        const SecureBlob& vkk_key,
                                        const SecureBlob& fek_iv,
                                        const SecureBlob& chaps_iv,
                                        SecureBlob* cipher_text,
                                        SecureBlob* wrapped_chaps_key) const {
  SecureBlob blob;
  if (!vault_keyset.ToKeysBlob(&blob)) {
    LOG(ERROR) << "Failure serializing keyset to buffer";
    return false;
  }

  SecureBlob chaps_key = vault_keyset.chaps_key();
  if (!CryptoLib::AesEncryptDeprecated(blob, vkk_key, fek_iv, cipher_text) ||
      !CryptoLib::AesEncryptDeprecated(chaps_key, vkk_key, chaps_iv,
                                       wrapped_chaps_key)) {
    LOG(ERROR) << "AES encryption failed.";
    return false;
  }

  return true;
}

bool Crypto::GenerateAndWrapKeys(const VaultKeyset& vault_keyset,
                                 const SecureBlob& key,
                                 const SecureBlob& salt,
                                 const KeyBlobs& blobs,
                                 bool store_reset_seed,
                                 SerializedVaultKeyset* serialized) const {
  if (blobs.vkk_key == base::nullopt ||
      blobs.vkk_iv == base::nullopt ||
      blobs.chaps_iv == base::nullopt) {
    DLOG(FATAL) << "Fields missing from KeyBlobs.";
    return false;
  }

  SecureBlob cipher_text;
  SecureBlob wrapped_chaps_key;
  if (!GenerateEncryptedRawKeyset(vault_keyset, blobs.vkk_key.value(),
                                  blobs.vkk_iv.value(), blobs.chaps_iv.value(),
                                  &cipher_text, &wrapped_chaps_key)) {
    return false;
  }

  if (vault_keyset.chaps_key().size() == CRYPTOHOME_CHAPS_KEY_LENGTH) {
    serialized->set_wrapped_chaps_key(wrapped_chaps_key.data(),
                                      wrapped_chaps_key.size());
  } else {
    serialized->clear_wrapped_chaps_key();
  }
  serialized->set_wrapped_keyset(cipher_text.data(), cipher_text.size());

  // If a reset seed is present, encrypt and store it, else clear the field.
  if (store_reset_seed && vault_keyset.reset_seed().size() != 0) {
    const auto reset_iv =
        CryptoLib::CreateSecureRandomBlob(kAesBlockSize);
    SecureBlob wrapped_reset_seed;
    if (!CryptoLib::AesEncryptDeprecated(vault_keyset.reset_seed(),
                                         blobs.vkk_key.value(), reset_iv,
                                         &wrapped_reset_seed)) {
      LOG(ERROR) << "AES encryption of Reset seed failed.";
      return false;
    }
    serialized->set_wrapped_reset_seed(wrapped_reset_seed.data(),
                                       wrapped_reset_seed.size());
    serialized->set_reset_iv(reset_iv.data(), reset_iv.size());
  } else {
    serialized->clear_wrapped_reset_seed();
    serialized->clear_reset_iv();
  }

  return true;
}

bool Crypto::EncryptTPM(const VaultKeyset& vault_keyset,
                        const SecureBlob& key,
                        const SecureBlob& salt,
                        const std::string& obfuscated_username,
                        KeyBlobs* out_blobs,
                        SerializedVaultKeyset* serialized) const {
  if (!use_tpm_)
    return false;
  EnsureTpm(false);
  if (!is_cryptohome_key_loaded())
    return false;

  const auto vkk_key = CryptoLib::CreateSecureRandomBlob(kDefaultAesKeySize);
  SecureBlob pass_blob(kDefaultPassBlobSize);
  SecureBlob vkk_iv(kAesBlockSize);
  if (!CryptoLib::DeriveSecretsScrypt(key, salt, {&pass_blob, &vkk_iv}))
    return false;

  SecureBlob tpm_key;
  SecureBlob extended_tpm_key;
  std::map<uint32_t, std::string> default_pcr_map =
      tpm_->GetPcrMap(obfuscated_username, false /* use_extended_pcr */);
  std::map<uint32_t, std::string> extended_pcr_map =
      tpm_->GetPcrMap(obfuscated_username, true /* use_extended_pcr */);

  // Encrypt the VKK using the TPM and the user's passkey. The output is two
  // encrypted blobs, sealed to PCR in |tpm_key| and |extended_tpm_key|,
  // which are stored in the serialized vault keyset.
  if (tpm_->SealToPcrWithAuthorization(tpm_init_->GetCryptohomeKey(), vkk_key,
                                       pass_blob, default_pcr_map,
                                       &tpm_key) != Tpm::kTpmRetryNone) {
    LOG(ERROR) << "Failed to wrap vkk with creds.";
    return false;
  }
  if (tpm_->SealToPcrWithAuthorization(
          tpm_init_->GetCryptohomeKey(), vkk_key, pass_blob, extended_pcr_map,
          &extended_tpm_key) != Tpm::kTpmRetryNone) {
    LOG(ERROR) << "Failed to wrap vkk with creds for extended PCR.";
    return false;
  }

  // Allow this to fail.  It is not absolutely necessary; it allows us to
  // detect a TPM clear.  If this fails due to a transient issue, then on next
  // successful login, the vault keyset will be re-saved anyway.
  SecureBlob pub_key_hash;
  if (tpm_->GetPublicKeyHash(tpm_init_->GetCryptohomeKey(), &pub_key_hash) ==
      Tpm::kTpmRetryNone)
    serialized->set_tpm_public_key_hash(pub_key_hash.data(),
                                        pub_key_hash.size());

  unsigned int flags = serialized->flags();
  serialized->set_flags((flags & ~SerializedVaultKeyset::SCRYPT_WRAPPED) |
                        SerializedVaultKeyset::TPM_WRAPPED |
                        SerializedVaultKeyset::SCRYPT_DERIVED |
                        SerializedVaultKeyset::PCR_BOUND);
  serialized->set_tpm_key(tpm_key.data(), tpm_key.size());
  serialized->set_extended_tpm_key(extended_tpm_key.data(),
                                   extended_tpm_key.size());

  // Pass back the vkk_key and vkk_iv so the generic secret wrapping can use it.
  out_blobs->vkk_key = vkk_key;
  out_blobs->vkk_iv = vkk_iv;
  out_blobs->chaps_iv = vkk_iv;
  out_blobs->auth_iv = vkk_iv;

  return true;
}

bool Crypto::EncryptTPMNotBoundToPcr(const VaultKeyset& vault_keyset,
                                     const SecureBlob& key,
                                     const SecureBlob& salt,
                                     KeyBlobs* out_blobs,
                                     SerializedVaultKeyset* serialized) const {
  if (!use_tpm_)
    return false;
  EnsureTpm(false);
  if (!is_cryptohome_key_loaded())
    return false;
  const auto local_blob = CryptoLib::CreateSecureRandomBlob(kDefaultAesKeySize);
  SecureBlob tpm_key;
  SecureBlob aes_skey(kDefaultAesKeySize);
  SecureBlob kdf_skey(kDefaultAesKeySize);
  SecureBlob vkk_iv(kAesBlockSize);

  if (!CryptoLib::DeriveSecretsScrypt(key, salt,
                                      {&aes_skey, &kdf_skey, &vkk_iv})) {
    return false;
  }
  // Encrypt the VKK using the TPM and the user's passkey.  The output is an
  // encrypted blob in tpm_key, which is stored in the serialized vault
  // keyset.
  if (tpm_->EncryptBlob(tpm_init_->GetCryptohomeKey(),
                        local_blob,
                        aes_skey,
                        &tpm_key) != Tpm::kTpmRetryNone) {
    LOG(ERROR) << "Failed to wrap vkk with creds.";
    return false;
  }

  // Allow this to fail.  It is not absolutely necessary; it allows us to
  // detect a TPM clear.  If this fails due to a transient issue, then on next
  // successful login, the vault keyset will be re-saved anyway.
  SecureBlob pub_key_hash;
  if (tpm_->GetPublicKeyHash(tpm_init_->GetCryptohomeKey(),
                             &pub_key_hash) == Tpm::kTpmRetryNone)
    serialized->set_tpm_public_key_hash(pub_key_hash.data(),
                                        pub_key_hash.size());

  unsigned int flags = serialized->flags();
  serialized->set_flags((flags & ~SerializedVaultKeyset::SCRYPT_WRAPPED
                               & ~SerializedVaultKeyset::PCR_BOUND)
                        | SerializedVaultKeyset::TPM_WRAPPED
                        | SerializedVaultKeyset::SCRYPT_DERIVED);
  serialized->set_tpm_key(tpm_key.data(), tpm_key.size());

  SecureBlob vkk_key = CryptoLib::HmacSha256(kdf_skey, local_blob);

  // Pass back the vkk_key and vkk_iv so the generic secret wrapping can use it.
  out_blobs->vkk_key = vkk_key;
  out_blobs->vkk_iv = vkk_iv;
  out_blobs->chaps_iv = vkk_iv;
  out_blobs->auth_iv = vkk_iv;

  return true;
}

bool Crypto::EncryptScrypt(const VaultKeyset& vault_keyset,
                           const SecureBlob& key,
                           SerializedVaultKeyset* serialized) const {
  SecureBlob blob;
  if (vault_keyset.IsLECredential()) {
    LOG(ERROR) << "Low entropy credentials cannot be scrypt-wrapped.";
    return false;
  }
  if (!vault_keyset.ToKeysBlob(&blob)) {
    LOG(ERROR) << "Failure serializing keyset to buffer";
    return false;
  }
  // Append the SHA1 hash of the keyset blob. This is done solely for
  // backwards-compatibility purposes, since scrypt already creates a
  // MAC for the encrypted blob. It is ignored in DecryptScrypt since
  // it is redundant.
  SecureBlob hash = CryptoLib::Sha1(blob);
  SecureBlob local_blob = SecureBlob::Combine(blob, hash);
  SecureBlob cipher_text;

  if (!CryptoLib::EncryptScryptBlob(local_blob, key, &cipher_text)) {
    LOG(ERROR) << "Scrypt encrypt of keyset blob failed.";
    return false;
  }

  SecureBlob wrapped_chaps_key;
  if (!CryptoLib::EncryptScryptBlob(vault_keyset.chaps_key(), key,
                                    &wrapped_chaps_key)) {
    LOG(ERROR) << "Scrypt encrypt of chaps key failed.";
    return false;
  }
  unsigned int flags = serialized->flags();
  serialized->set_flags((flags & ~SerializedVaultKeyset::TPM_WRAPPED)
                        | SerializedVaultKeyset::SCRYPT_WRAPPED);
  serialized->set_wrapped_keyset(cipher_text.data(), cipher_text.size());
  if (vault_keyset.chaps_key().size() == CRYPTOHOME_CHAPS_KEY_LENGTH) {
    serialized->set_wrapped_chaps_key(wrapped_chaps_key.data(),
                                      wrapped_chaps_key.size());
  } else {
    serialized->clear_wrapped_chaps_key();
  }

  // If there is a reset seed, encrypt and store it.
  if (vault_keyset.reset_seed().size() != 0) {
    SecureBlob wrapped_reset_seed;
    if (!CryptoLib::EncryptScryptBlob(vault_keyset.reset_seed(), key,
                                      &wrapped_reset_seed)) {
      LOG(ERROR) << "Scrypt encrypt of reset seed failed.";
      return false;
    }
    serialized->set_wrapped_reset_seed(wrapped_reset_seed.data(),
                                       wrapped_reset_seed.size());
  } else {
    serialized->clear_wrapped_reset_seed();
  }

  return true;
}

bool Crypto::EncryptChallengeCredential(
    const VaultKeyset& vault_keyset,
    const SecureBlob& key,
    const std::string& obfuscated_username,
    SerializedVaultKeyset* serialized) const {
  serialized->set_flags(serialized->flags() |
                        SerializedVaultKeyset::SIGNATURE_CHALLENGE_PROTECTED);
  if (!EncryptScrypt(vault_keyset, key, serialized))
    return false;
  DCHECK(!(serialized->flags() & SerializedVaultKeyset::TPM_WRAPPED));
  DCHECK(serialized->flags() & SerializedVaultKeyset::SCRYPT_WRAPPED);
  DCHECK(serialized->flags() &
         SerializedVaultKeyset::SIGNATURE_CHALLENGE_PROTECTED);
  return true;
}

bool Crypto::EncryptAuthorizationData(SerializedVaultKeyset* serialized,
                                      const SecureBlob& vkk_key,
                                      const SecureBlob& vkk_iv) const {
  // Handle AuthorizationData secrets if provided.
  if (serialized->key_data().authorization_data_size() > 0) {
    KeyData* key_data = serialized->mutable_key_data();
    for (int auth_data_i = 0; auth_data_i < key_data->authorization_data_size();
         ++auth_data_i) {
      KeyAuthorizationData* auth_data =
          key_data->mutable_authorization_data(auth_data_i);
      for (int secret_i = 0; secret_i < auth_data->secrets_size(); ++secret_i) {
        KeyAuthorizationSecret* secret = auth_data->mutable_secrets(secret_i);
        // Secrets that are externally provided should not be wrapped when
        // this is called.  However, calling Encrypt() again should be
        // idempotent.  External callers should be filtered at the API layer.
        if (secret->wrapped() || !secret->has_symmetric_key())
          continue;
        SecureBlob clear_auth_key(secret->symmetric_key());
        SecureBlob encrypted_auth_key;

        if (!CryptoLib::AesEncryptDeprecated(clear_auth_key, vkk_key, vkk_iv,
                                             &encrypted_auth_key)) {
          LOG(ERROR) << "Failed to wrap a symmetric authorization key:"
                     << " (" << auth_data_i << "," << secret_i << ")";
          // This forces a failure.
          return false;
        }
        secret->set_symmetric_key(encrypted_auth_key.to_string());
        secret->set_wrapped(true);
      }
    }
  }

  return true;
}

bool Crypto::EncryptVaultKeyset(const VaultKeyset& vault_keyset,
                                const SecureBlob& vault_key,
                                const SecureBlob& vault_key_salt,
                                const std::string& obfuscated_username,
                                SerializedVaultKeyset* serialized) const {
  if (vault_keyset.IsLECredential()) {
    SecureBlob reset_secret;
    SecureBlob reset_salt;
    if (!GenerateResetSecret(vault_keyset, &reset_secret, &reset_salt)) {
      return false;
    }

    serialized->set_reset_salt(reset_salt.data(), reset_salt.size());

    KeyBlobs blobs;
    PinWeaverAuthBlock pin_weaver_auth(le_manager_.get(), tpm_init_);

    AuthInput user_input = {vault_key, /*is_pcr_extended=*/base::nullopt,
                            vault_key_salt, obfuscated_username, reset_secret};
    AuthBlockState auth_state = {SerializedVaultKeyset()};
    KeyBlobs vkk_data;
    CryptoError error;

    // TODO(kerrnel): When switching to a factory method, report the error
    // object.
    if (!pin_weaver_auth.Create(user_input, &auth_state, &vkk_data, &error)) {
      LOG(ERROR) << "Failed to create pinweaver credential: " << error;
      return false;
    }

    serialized->set_le_fek_iv(auth_state.vault_keyset.value().le_fek_iv());
    serialized->set_le_chaps_iv(auth_state.vault_keyset.value().le_chaps_iv());
    serialized->set_flags(auth_state.vault_keyset.value().flags());
    serialized->set_le_label(auth_state.vault_keyset.value().le_label());
    serialized->mutable_key_data()->mutable_policy()->set_auth_locked(false);

    if (!GenerateAndWrapKeys(vault_keyset, vault_key, vault_key_salt, vkk_data,
                             /*store_reset_seed=*/false, serialized)) {
      LOG(ERROR) << "Failed to generate unwrapped keys";
      return false;
    }

    if (!EncryptAuthorizationData(serialized, vkk_data.vkk_key.value(),
                                  vkk_data.auth_iv.value())) {
      return false;
    }
  } else if (vault_keyset.IsSignatureChallengeProtected()) {
    if (!EncryptChallengeCredential(vault_keyset, vault_key,
                                    obfuscated_username, serialized)) {
      // TODO(crbug.com/842791): add ReportCryptohomeError
      return false;
    }
  } else {
    bool encrypt_tpm_success = false;
    KeyBlobs blobs;
    if (CanUnsealWithUserAuth()) {
      encrypt_tpm_success = EncryptTPM(vault_keyset, vault_key, vault_key_salt,
                                       obfuscated_username, &blobs, serialized);
    } else {
      encrypt_tpm_success = EncryptTPMNotBoundToPcr(
          vault_keyset, vault_key, vault_key_salt, &blobs, serialized);
    }
    if (!encrypt_tpm_success) {
      LOG_IF(ERROR, !disable_logging_for_tests_) << "Encrypt using TPM failed";
      if (use_tpm_ && tpm_ && tpm_->IsOwned()) {
        ReportCryptohomeError(kEncryptWithTpmFailed);
      }
      if (!EncryptScrypt(vault_keyset, vault_key, serialized)) {
        return false;
      }
    } else {
      if (!GenerateAndWrapKeys(vault_keyset, vault_key, vault_key_salt, blobs,
                               /*store_reset_seed=*/true, serialized)) {
        LOG(ERROR) << "Failed to generate unwrapped keys";
        return false;
      }

      if (!EncryptAuthorizationData(serialized, blobs.vkk_key.value(),
                                    blobs.auth_iv.value())) {
        return false;
      }
    }
  }

  serialized->set_salt(vault_key_salt.data(), vault_key_salt.size());
  return true;
}

bool Crypto::EncryptWithTpm(const SecureBlob& data,
                            std::string* encrypted_data) const {
  SecureBlob aes_key;
  SecureBlob sealed_key;
  if (!CreateSealedKey(&aes_key, &sealed_key))
    return false;
  return EncryptData(data, aes_key, sealed_key, encrypted_data);
}

bool Crypto::DecryptWithTpm(const std::string& encrypted_data,
                            SecureBlob* data) const {
  SecureBlob aes_key;
  SecureBlob sealed_key;
  if (!UnsealKey(encrypted_data, &aes_key, &sealed_key)) {
    return false;
  }
  return DecryptData(encrypted_data, aes_key, data);
}

bool Crypto::CreateSealedKey(SecureBlob* aes_key,
                             SecureBlob* sealed_key) const {
  if (!use_tpm_)
    return false;
  if (!tpm_->GetRandomDataSecureBlob(kDefaultAesKeySize, aes_key)) {
    LOG(ERROR) << "GetRandomDataSecureBlob failed.";
    return false;
  }
  if (!tpm_->SealToPCR0(*aes_key, sealed_key)) {
    LOG(ERROR) << "Failed to seal cipher key.";
    return false;
  }
  return true;
}

bool Crypto::EncryptData(const SecureBlob& data,
                         const SecureBlob& aes_key,
                         const SecureBlob& sealed_key,
                         std::string* encrypted_data) const {
  if (!use_tpm_)
    return false;
  SecureBlob iv;
  if (!tpm_->GetRandomDataSecureBlob(kAesBlockSize, &iv)) {
    LOG(ERROR) << "GetRandomDataSecureBlob failed.";
    return false;
  }
  SecureBlob encrypted_data_blob;
  if (!CryptoLib::AesEncryptSpecifyBlockMode(data, 0, data.size(), aes_key, iv,
                                             CryptoLib::kPaddingStandard,
                                             CryptoLib::kCbc,
                                             &encrypted_data_blob)) {
    LOG(ERROR) << "Failed to encrypt serial data.";
    return false;
  }
  EncryptedData encrypted_pb;
  encrypted_pb.set_wrapped_key(sealed_key.data(), sealed_key.size());
  encrypted_pb.set_iv(iv.data(), iv.size());
  encrypted_pb.set_encrypted_data(encrypted_data_blob.data(),
                                  encrypted_data_blob.size());
  encrypted_pb.set_mac(CryptoLib::ComputeEncryptedDataHMAC(encrypted_pb,
                                                           aes_key));
  if (!encrypted_pb.SerializeToString(encrypted_data)) {
    LOG(ERROR) << "Could not serialize data to string.";
    return false;
  }
  return true;
}

bool Crypto::UnsealKey(const std::string& encrypted_data,
                       SecureBlob* aes_key,
                       SecureBlob* sealed_key) const {
  if (!use_tpm_)
    return false;
  EncryptedData encrypted_pb;
  if (!encrypted_pb.ParseFromString(encrypted_data)) {
    LOG(ERROR) << "Could not decrypt data as it was not an EncryptedData "
               << "protobuf";
    return false;
  }
  SecureBlob tmp(encrypted_pb.wrapped_key().begin(),
                 encrypted_pb.wrapped_key().end());
  sealed_key->swap(tmp);
  if (!tpm_->Unseal(*sealed_key, aes_key)) {
    LOG(ERROR) << "Cannot unseal aes key.";
    return false;
  }
  return true;
}

bool Crypto::DecryptData(const std::string& encrypted_data,
                         const brillo::SecureBlob& aes_key,
                         brillo::SecureBlob* data) const {
  EncryptedData encrypted_pb;
  if (!encrypted_pb.ParseFromString(encrypted_data)) {
    LOG(ERROR) << "Could not decrypt data as it was not an EncryptedData "
               << "protobuf";
    return false;
  }
  std::string mac = CryptoLib::ComputeEncryptedDataHMAC(encrypted_pb, aes_key);
  if (mac.length() != encrypted_pb.mac().length()) {
    LOG(ERROR) << "Corrupted data in encrypted pb.";
    return false;
  }
  if (0 != brillo::SecureMemcmp(mac.data(), encrypted_pb.mac().data(),
                                  mac.length())) {
    LOG(ERROR) << "Corrupted data in encrypted pb.";
    return false;
  }
  SecureBlob iv(encrypted_pb.iv().begin(), encrypted_pb.iv().end());
  SecureBlob encrypted_data_blob(encrypted_pb.encrypted_data().begin(),
                                 encrypted_pb.encrypted_data().end());
  if (!CryptoLib::AesDecryptSpecifyBlockMode(encrypted_data_blob,
                                             0,
                                             encrypted_data_blob.size(),
                                             aes_key,
                                             iv,
                                             CryptoLib::kPaddingStandard,
                                             CryptoLib::kCbc,
                                             data)) {
    LOG(ERROR) << "Failed to decrypt encrypted data.";
    return false;
  }
  return true;
}

bool Crypto::ResetLECredential(const SerializedVaultKeyset& serialized_reset,
                               CryptoError* error,
                               const VaultKeyset& vk) const {
  if (!use_tpm_ || !tpm_)
    return false;

  // Bail immediately if we don't have a valid LECredentialManager.
  if (!le_manager_) {
    LOG(ERROR) << "Attempting to Reset LECredential on a platform that doesn't "
                  "support LECredential";
    PopulateError(error, CryptoError::CE_LE_NOT_SUPPORTED);
    return false;
  }

  CHECK(serialized_reset.flags() & SerializedVaultKeyset::LE_CREDENTIAL);
  SecureBlob local_reset_seed(vk.reset_seed().begin(), vk.reset_seed().end());
  SecureBlob reset_salt(serialized_reset.reset_salt().begin(),
                        serialized_reset.reset_salt().end());
  if (local_reset_seed.empty() || reset_salt.empty()) {
    LOG(ERROR) << "Reset seed/salt is empty, can't reset LE credential.";
    PopulateError(error, CryptoError::CE_OTHER_FATAL);
    return false;
  }

  SecureBlob reset_secret = CryptoLib::HmacSha256(reset_salt, local_reset_seed);
  int ret =
      le_manager_->ResetCredential(serialized_reset.le_label(), reset_secret);
  if (ret != LE_CRED_SUCCESS) {
    PopulateError(error, ret == LE_CRED_ERROR_INVALID_RESET_SECRET
                             ? CryptoError::CE_LE_INVALID_SECRET
                             : CryptoError::CE_OTHER_FATAL);
    return false;
  }
  return true;
}

int Crypto::GetWrongAuthAttempts(
    const SerializedVaultKeyset& le_serialized) const {
  DCHECK(le_manager_)
      << "le_manage_ doesn't exist when calling GetWrongAuthAttempts()";
  return le_manager_->GetWrongAuthAttempts(le_serialized.le_label());
}

bool Crypto::RemoveLECredential(uint64_t label) const {
  if (!use_tpm_ || !tpm_) {
    LOG(WARNING) << "No TPM instance for RemoveLECredential.";
    return false;
  }

  // Bail immediately if we don't have a valid LECredentialManager.
  if (!le_manager_) {
    LOG(ERROR) << "No LECredentialManager instance for RemoveLECredential.";
    return false;
  }

  return le_manager_->RemoveCredential(label) == LE_CRED_SUCCESS;
}

bool Crypto::is_cryptohome_key_loaded() const {
  if (tpm_ == NULL || tpm_init_ == NULL) {
    return false;
  }
  return tpm_init_->HasCryptohomeKey();
}

bool Crypto::CanUnsealWithUserAuth() const {
  if (!tpm_)
    return false;
  if (tpm_->GetVersion() != Tpm::TPM_1_2)
    return true;
  if (!tpm_->DelegateCanResetDACounter())
    return false;
  base::Optional<bool> is_pcr_bound = tpm_->IsDelegateBoundToPcr();
  if (is_pcr_bound.has_value() && !is_pcr_bound.value())
    return true;

#if USE_DOUBLE_EXTEND_PCR_ISSUE
  return false;
#else
  return true;
#endif
}

}  // namespace cryptohome
