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

#include "cryptohome/crypto/scrypt.h"

#include <limits>
#include <utility>
#include <vector>

#include <malloc.h>
#include <openssl/err.h>
#include <openssl/kdf.h>
#include <openssl/sha.h>
#include <unistd.h>

#include <base/check.h>
#include <base/check_op.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/notreached.h>
#include <base/numerics/safe_conversions.h>
#include <base/stl_util.h>
#include <brillo/secure_blob.h>
#include <crypto/libcrypto-compat.h>
#include <crypto/scoped_openssl_types.h>

#include "cryptohome/crypto/aes.h"
#include "cryptohome/crypto/secure_blob_util.h"
#include "cryptohome/libscrypt_compat.h"
#include "cryptohome/platform.h"

using brillo::SecureBlob;

namespace cryptohome {

namespace {

// Global override-able for testing.
ScryptParameters gScryptParams = kDefaultScryptParams;

}  // namespace

// The current number of hash rounds we use.  Large enough to be a measurable
// amount of time, but not add too much overhead to login (around 10ms).
const unsigned int kDefaultPasswordRounds = 1337;

// The number of hash rounds we originally used when converting a password to a
// key.  This is used when converting older cryptohome vault keysets.
const unsigned int kDefaultLegacyPasswordRounds = 1;

// The maximum number of times to try decryption with the TPM.
constexpr int kTpmDecryptMaxRetries = 2;

// The size in bytes of password blob to be generated by Scrypt. Should be the
// same size as the modulus of cryptohome key, since we need to be able to
// decrypt it.
constexpr unsigned int kDefaultPassBlobSize = 256;

// Scrypt creates a header in the cipher text that we need to account for in
// buffer sizing. This accounts for both the header and the HMAC.
constexpr unsigned int kScryptMetadataSize = 128;

// An upper bound on the amount of memory that we allow Scrypt to use when
// performing key strengthening (32MB).  A large size is okay since we only use
// Scrypt during the login process, before the user is logged in.  This memory
// is managed (and freed) by the scrypt library.
const unsigned int kScryptMaxMem = 32 * 1024 * 1024;

// An upper bound on the amount of time we allow Scrypt to use when performing
// key strenthening (1/3s) for encryption.
constexpr double kScryptMaxEncryptTime = 0.333;

// These are the params to use for production code.
constexpr ScryptParameters kDefaultScryptParams;

// scrypt, with the default params, is too slow for unit testing so here are
// some fast parameters only for test code.
constexpr ScryptParameters kTestScryptParams = {1024, 8, 1};

bool DeriveSecretsScrypt(const brillo::SecureBlob& passkey,
                         const brillo::SecureBlob& salt,
                         std::vector<brillo::SecureBlob*> gen_secrets) {
  if (gen_secrets.empty()) {
    LOG(ERROR) << "No secrets requested from scrypt derivation.";
    return false;
  }
  size_t total_len = 0;
  for (auto& secret : gen_secrets) {
    if (secret->empty()) {
      LOG(ERROR) << "Empty secret requested from scrypt derivation.";
      return false;
    }
    total_len += secret->size();
  }

  SecureBlob generated(total_len);
  if (!Scrypt(passkey, salt, kDefaultScryptParams.n_factor,
              kDefaultScryptParams.r_factor, kDefaultScryptParams.p_factor,
              &generated)) {
    LOG(ERROR) << "Failed to derive scrypt keys from passkey.";
    return false;
  }

  uint8_t* data = generated.data();
  for (auto& value : gen_secrets) {
    value->assign(data, data + value->size());
    data += value->size();
  }

  return true;
}

bool Scrypt(const brillo::SecureBlob& input,
            const brillo::SecureBlob& salt,
            int work_factor,
            int block_size,
            int parallel_factor,
            brillo::SecureBlob* result) {
  crypto::ScopedEVP_PKEY_CTX pctx(EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, NULL));
  if (EVP_PKEY_derive_init(pctx.get()) <= 0)
    return false;
  if (EVP_PKEY_CTX_set1_pbe_pass(pctx.get(), input.data(), input.size()) <= 0)
    return false;
  if (EVP_PKEY_CTX_set1_scrypt_salt(pctx.get(), salt.data(), salt.size()) <= 0)
    return false;
  if (EVP_PKEY_CTX_set_scrypt_N(pctx.get(), work_factor) <= 0)
    return false;
  if (EVP_PKEY_CTX_set_scrypt_r(pctx.get(), block_size) <= 0)
    return false;
  if (EVP_PKEY_CTX_set_scrypt_p(pctx.get(), parallel_factor) <= 0)
    return false;

  size_t outlen = result->size();
  int rc = EVP_PKEY_derive(pctx.get(), result->data(), &outlen);

  return rc > 0 && outlen == result->size();
}

bool DeprecatedEncryptScryptBlob(const brillo::SecureBlob& blob,
                                 const brillo::SecureBlob& key_source,
                                 brillo::SecureBlob* wrapped_blob) {
  wrapped_blob->resize(blob.size() + kScryptMetadataSize);

  brillo::SecureBlob salt = CreateSecureRandomBlob(kLibScryptSaltSize);
  brillo::SecureBlob derived_key(kLibScryptDerivedKeySize, '0');
  if (!Scrypt(key_source, salt, gScryptParams.n_factor, gScryptParams.r_factor,
              gScryptParams.p_factor, &derived_key) != 0) {
    LOG(ERROR) << "Failed to derive key with scrypt.";
    return false;
  }

  if (!LibScryptCompat::Encrypt(derived_key, salt, blob, gScryptParams,
                                wrapped_blob)) {
    LOG(ERROR) << "Failed to generate encrypted data.";
    return false;
  }

  return true;
}

bool DeprecatedDecryptScryptBlob(const brillo::SecureBlob& wrapped_blob,
                                 const brillo::SecureBlob& key,
                                 brillo::SecureBlob* blob,
                                 CryptoError* error) {
  DCHECK(blob->size() >= wrapped_blob.size());

  ScryptParameters params;
  brillo::SecureBlob salt;
  if (!LibScryptCompat::ParseHeader(wrapped_blob, &params, &salt)) {
    LOG(ERROR) << "Failed to parse header.";
    PopulateError(error, CryptoError::CE_SCRYPT_CRYPTO);
    return false;
  }

  // Generate the derived key.
  brillo::SecureBlob derived_key(kLibScryptDerivedKeySize, 0);
  if (!Scrypt(key, salt, params.n_factor, params.r_factor, params.p_factor,
              &derived_key)) {
    LOG(ERROR) << "scrypt failed";
    return false;
  }

  if (!LibScryptCompat::Decrypt(wrapped_blob, derived_key, blob)) {
    LOG(ERROR) << "Failed to decrypt output.";
    PopulateError(error, CryptoError::CE_SCRYPT_CRYPTO);
    return false;
  }

  // Check if the plaintext is the right length.
  if ((wrapped_blob.size() < kScryptMetadataSize) ||
      (blob->size() != (wrapped_blob.size() - kScryptMetadataSize))) {
    LOG(ERROR) << "Blob Scrypt decryption output was the wrong length";
    PopulateError(error, CryptoError::CE_SCRYPT_CRYPTO);
    return false;
  }
  return true;
}

void AssertProductionScryptParams() {
  // Always perform the check just in case.
  CHECK_EQ(kDefaultScryptParams.n_factor, gScryptParams.n_factor);
  CHECK_EQ(kDefaultScryptParams.r_factor, gScryptParams.r_factor);
  CHECK_EQ(kDefaultScryptParams.p_factor, gScryptParams.p_factor);
}

void SetScryptTestingParams() {
  gScryptParams = kTestScryptParams;
}

}  // namespace cryptohome
