// 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/cryptolib.h"

#include <limits>
#include <vector>

#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <unistd.h>

#include <base/files/file_util.h>
#include <base/logging.h>
#include <brillo/secure_blob.h>
#include <crypto/scoped_openssl_types.h>
extern "C" {
#include <scrypt/crypto_scrypt.h>
#include <scrypt/scryptenc.h>
}

#include "cryptohome/platform.h"

using brillo::SecureBlob;

namespace cryptohome {

// The well-known exponent used when generating RSA keys.  Cryptohome only
// generates one RSA key, which is the system-wide cryptohome key.  This is the
// common public exponent.
const unsigned int kWellKnownExponent = 65537;

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

// AES block size in bytes.
const unsigned int  kAesBlockSize = 16;

void CryptoLib::GetSecureRandom(unsigned char* buf, size_t length) {
  // OpenSSL takes a signed integer.  On the off chance that the user requests
  // something too large, truncate it.
  if (length > static_cast<size_t>(std::numeric_limits<int>::max())) {
    length = std::numeric_limits<int>::max();
  }
  RAND_bytes(buf, length);
}

bool CryptoLib::CreateRsaKey(size_t key_bits,
                             SecureBlob* n,
                          SecureBlob* p) {
  crypto::ScopedRSA rsa(RSA_generate_key(key_bits,
                                         kWellKnownExponent,
                                         NULL,
                                         NULL));
  if (rsa.get() == NULL) {
    LOG(ERROR) << "RSA key generation failed.";
    return false;
  }

  SecureBlob local_n(BN_num_bytes(rsa.get()->n));
  if (BN_bn2bin(rsa.get()->n, local_n.data()) <= 0) {
    LOG(ERROR) << "Unable to get modulus from RSA key.";
    return false;
  }

  SecureBlob local_p(BN_num_bytes(rsa.get()->p));
  if (BN_bn2bin(rsa.get()->p, local_p.data()) <= 0) {
    LOG(ERROR) << "Unable to get private key from RSA key.";
    return false;
  }

  n->swap(local_n);
  p->swap(local_p);
  return true;
}

SecureBlob CryptoLib::Sha1(const brillo::Blob& data) {
  SHA_CTX sha_context;
  unsigned char md_value[SHA_DIGEST_LENGTH];
  SecureBlob hash;

  SHA1_Init(&sha_context);
  SHA1_Update(&sha_context, data.data(), data.size());
  SHA1_Final(md_value, &sha_context);
  hash.resize(sizeof(md_value));
  memcpy(hash.data(), md_value, sizeof(md_value));
  // Zero the stack to match expectations set by SecureBlob.
  brillo::SecureMemset(md_value, 0, sizeof(md_value));
  return hash;
}

SecureBlob CryptoLib::Sha256(const brillo::Blob& data) {
  SHA256_CTX sha_context;
  unsigned char md_value[SHA256_DIGEST_LENGTH];
  SecureBlob hash;

  SHA256_Init(&sha_context);
  SHA256_Update(&sha_context, data.data(), data.size());
  SHA256_Final(md_value, &sha_context);
  hash.resize(sizeof(md_value));
  memcpy(hash.data(), md_value, sizeof(md_value));
  // Zero the stack to match expectations set by SecureBlob.
  brillo::SecureMemset(md_value, 0, sizeof(md_value));
  return hash;
}

brillo::SecureBlob CryptoLib::HmacSha512(const brillo::SecureBlob& key,
                                           const brillo::Blob& data) {
  const int kSha512OutputSize = 64;
  unsigned char mac[kSha512OutputSize];
  HMAC(EVP_sha512(),
       key.data(), key.size(),
       data.data(), data.size(),
       mac, NULL);
  return brillo::SecureBlob(std::begin(mac), std::end(mac));
}

brillo::SecureBlob CryptoLib::HmacSha256(const brillo::SecureBlob& key,
                                           const brillo::Blob& data) {
  const int kSha256OutputSize = 32;
  unsigned char mac[kSha256OutputSize];
  HMAC(EVP_sha256(),
       key.data(), key.size(),
       data.data(), data.size(),
       mac, NULL);
  return brillo::SecureBlob(std::begin(mac), std::end(mac));
}

size_t CryptoLib::GetAesBlockSize() {
  return EVP_CIPHER_block_size(EVP_aes_256_cbc());
}

bool CryptoLib::PasskeyToAesKey(const brillo::Blob& passkey,
                                const brillo::Blob& salt, unsigned int rounds,
                                SecureBlob* key, SecureBlob* iv) {
  if (salt.size() != PKCS5_SALT_LEN) {
    LOG(ERROR) << "Bad salt size.";
    return false;
  }

  const EVP_CIPHER* cipher = EVP_aes_256_cbc();
  SecureBlob aes_key(EVP_CIPHER_key_length(cipher));
  SecureBlob local_iv(EVP_CIPHER_iv_length(cipher));

  // Convert the passkey to a key
  if (!EVP_BytesToKey(cipher,
                      EVP_sha1(),
                      salt.data(),
                      passkey.data(),
                      passkey.size(),
                      rounds,
                      aes_key.data(),
                      local_iv.data())) {
    LOG(ERROR) << "Failure converting bytes to key";
    return false;
  }

  key->swap(aes_key);
  if (iv) {
    iv->swap(local_iv);
  }

  return true;
}

bool CryptoLib::AesEncrypt(const brillo::Blob& plaintext,
                           const SecureBlob& key,
                           const SecureBlob& iv,
                           SecureBlob* ciphertext) {
  return AesEncryptSpecifyBlockMode(plaintext, 0, plaintext.size(), key, iv,
                                    kPaddingCryptohomeDefault, kCbc,
                                    ciphertext);
}

bool CryptoLib::AesDecrypt(const brillo::Blob& ciphertext,
                           const SecureBlob& key,
                           const SecureBlob& iv,
                           SecureBlob* plaintext) {
  return AesDecryptSpecifyBlockMode(ciphertext, 0, ciphertext.size(), key, iv,
                                    kPaddingCryptohomeDefault, kCbc, plaintext);
}

// This is the reverse operation of AesEncryptSpecifyBlockMode above.  See that
// method for a description of how padding and block_mode affect the crypto
// operations.  This method automatically removes and verifies the padding, so
// plain_text (on success) will contain the original data.
//
// Note that a call to AesDecryptSpecifyBlockMode needs to have the same padding
// and block_mode as the corresponding encrypt call.  Changing the block mode
// will drastically alter the decryption.  And an incorrect PaddingScheme will
// result in the padding verification failing, for which the method call fails,
// even if the key and initialization vector were correct.
bool CryptoLib::AesDecryptSpecifyBlockMode(const brillo::Blob& encrypted,
                                           unsigned int start,
                                           unsigned int count,
                                           const SecureBlob& key,
                                           const SecureBlob& iv,
                                           PaddingScheme padding,
                                           BlockMode block_mode,
                                           SecureBlob* plain_text) {
  if ((start > encrypted.size()) ||
      ((start + count) > encrypted.size()) ||
      ((start + count) < start)) {
    return false;
  }
  SecureBlob local_plain_text(count);

  if (local_plain_text.size() >
      static_cast<unsigned int>(std::numeric_limits<int>::max())) {
    // EVP_DecryptUpdate takes a signed int
    return false;
  }
  int final_size = 0;
  int decrypt_size = local_plain_text.size();

  const EVP_CIPHER* cipher;
  switch (block_mode) {
    case kCbc:
      cipher = EVP_aes_256_cbc();
      break;
    case kEcb:
      cipher = EVP_aes_256_ecb();
      break;
    default:
      LOG(ERROR) << "Invalid block mode specified: " << block_mode;
      return false;
  }
  if (key.size() != static_cast<unsigned int>(EVP_CIPHER_key_length(cipher))) {
    LOG(ERROR) << "Invalid key length of " << key.size()
               << ", expected " << EVP_CIPHER_key_length(cipher);
    return false;
  }
  // ECB ignores the IV, so only check the IV length if we are using a different
  // block mode.
  if ((block_mode != kEcb) &&
      (iv.size() != static_cast<unsigned int>(EVP_CIPHER_iv_length(cipher)))) {
    LOG(ERROR) << "Invalid iv length of " << iv.size()
               << ", expected " << EVP_CIPHER_iv_length(cipher);
    return false;
  }

  EVP_CIPHER_CTX decryption_context;
  EVP_CIPHER_CTX_init(&decryption_context);
  EVP_DecryptInit_ex(&decryption_context, cipher, NULL, key.data(), iv.data());
  if (padding == kPaddingNone) {
    EVP_CIPHER_CTX_set_padding(&decryption_context, 0);
  }

  // Make sure we're not pointing into an empty buffer or past the end.
  const unsigned char *encrypted_buf = NULL;
  if (start < encrypted.size())
    encrypted_buf = &encrypted[start];

  if (!EVP_DecryptUpdate(&decryption_context, local_plain_text.data(),
                         &decrypt_size, encrypted_buf, count)) {
    LOG(ERROR) << "DecryptUpdate failed";
    EVP_CIPHER_CTX_cleanup(&decryption_context);
    return false;
  }

  // In the case of local_plain_text being full, we must avoid trying to
  // point past the end of the buffer when calling EVP_DecryptFinal_ex().
  unsigned char *final_buf = NULL;
  if (static_cast<unsigned int>(decrypt_size) < local_plain_text.size())
    final_buf = &local_plain_text[decrypt_size];

  if (!EVP_DecryptFinal_ex(&decryption_context, final_buf, &final_size)) {
    unsigned long err = ERR_get_error(); // NOLINT openssl types
    ERR_load_ERR_strings();
    ERR_load_crypto_strings();

    LOG(ERROR) << "DecryptFinal Error: " << err
               << ": " << ERR_lib_error_string(err)
               << ", " << ERR_func_error_string(err)
               << ", " << ERR_reason_error_string(err);

    EVP_CIPHER_CTX_cleanup(&decryption_context);
    return false;
  }
  final_size += decrypt_size;

  if (padding == kPaddingCryptohomeDefault) {
    if (final_size < SHA_DIGEST_LENGTH) {
      LOG(ERROR) << "Plain text was too small.";
      EVP_CIPHER_CTX_cleanup(&decryption_context);
      return false;
    }

    final_size -= SHA_DIGEST_LENGTH;

    SHA_CTX sha_context;
    unsigned char md_value[SHA_DIGEST_LENGTH];

    SHA1_Init(&sha_context);
    SHA1_Update(&sha_context, local_plain_text.data(), final_size);
    SHA1_Final(md_value, &sha_context);

    const unsigned char* md_ptr = local_plain_text.data();
    md_ptr += final_size;
    if (brillo::SecureMemcmp(md_ptr, md_value, SHA_DIGEST_LENGTH)) {
      LOG(ERROR) << "Digest verification failed.";
      EVP_CIPHER_CTX_cleanup(&decryption_context);
      return false;
    }
  }

  local_plain_text.resize(final_size);
  plain_text->swap(local_plain_text);
  EVP_CIPHER_CTX_cleanup(&decryption_context);
  return true;
}

// AesEncryptSpecifyBlockMode encrypts the bytes in plain_text using AES,
// placing the output into encrypted.  Aside from range constraints (start and
// count) and the key and initialization vector, this method has two parameters
// that control how the ciphertext is generated and are useful in encrypting
// specific types of data in cryptohome.
//
// First, padding specifies whether and how the plaintext is padded before
// encryption.  The three options, described in the PaddingScheme enumeration
// are used as such:
//   - kPaddingNone is used to mix the user's passkey (derived from the
//     password) into the encrypted blob storing the vault keyset when the TPM
//     is used.  This is described in more detail in the README file.  There is
//     no padding in this case, and the size of plain_text needs to be a
//     multiple of the AES block size (16 bytes).
//   - kPaddingStandard uses standard PKCS padding, which is the default for
//     OpenSSL.
//   - kPaddingCryptohomeDefault appends a SHA1 hash of the plaintext in
//     plain_text before passing it to OpenSSL, which still uses PKCS padding
//     so that we do not have to re-implement block-multiple padding ourselves.
//     This padding scheme allows us to strongly verify the plaintext on
//     decryption, which is essential when, for example, test decrypting a nonce
//     to test whether a password was correct (we do this in user_session.cc).
//
// The block mode switches between ECB and CBC.  Generally, CBC is used for most
// AES crypto that we perform, since it is a better mode for us for data that is
// larger than the block size.  We use ECB only when mixing the user passkey
// into the TPM-encrypted blob, since we only encrypt a single block of that
// data.
bool CryptoLib::AesEncryptSpecifyBlockMode(const brillo::Blob& plain_text,
                                           unsigned int start,
                                           unsigned int count,
                                           const SecureBlob& key,
                                           const SecureBlob& iv,
                                           PaddingScheme padding,
                                           BlockMode block_mode,
                                           SecureBlob* encrypted) {
  // Verify that the range is within the data passed
  if ((start > plain_text.size()) ||
      ((start + count) > plain_text.size()) ||
      ((start + count) < start)) {
    return false;
  }
  if (count > static_cast<unsigned int>(std::numeric_limits<int>::max())) {
    // EVP_EncryptUpdate takes a signed int
    return false;
  }

  // First set the output size based on the padding scheme.  No padding means
  // that the input needs to be a multiple of the block size, and the output
  // size is equal to the input size.  Standard padding means we should allocate
  // up to a full block additional for the PKCS padding.  Cryptohome default
  // means we should allocate a full block additional for the PKCS padding and
  // enough for a SHA1 hash.
  unsigned int block_size = GetAesBlockSize();
  unsigned int needed_size = count;
  switch (padding) {
    case kPaddingCryptohomeDefault:
      // The AES block size and SHA digest length are not enough for this to
      // overflow, as needed_size is initialized to count, which must be <=
      // INT_MAX, but needed_size is itself an unsigned.  The block size and
      // digest length are fixed by the algorithm.
      needed_size += block_size + SHA_DIGEST_LENGTH;
      break;
    case kPaddingStandard:
      needed_size += block_size;
      break;
    case kPaddingNone:
      if (count % block_size) {
        LOG(ERROR) << "Data size (" << count << ") was not a multiple "
                   << "of the block size (" << block_size << ")";
        return false;
      }
      break;
    default:
      LOG(ERROR) << "Invalid padding specified";
      return false;
      break;
  }
  SecureBlob cipher_text(needed_size);

  // Set the block mode
  const EVP_CIPHER* cipher;
  switch (block_mode) {
    case kCbc:
      cipher = EVP_aes_256_cbc();
      break;
    case kEcb:
      cipher = EVP_aes_256_ecb();
      break;
    default:
      LOG(ERROR) << "Invalid block mode specified";
      return false;
  }
  if (key.size() != static_cast<unsigned int>(EVP_CIPHER_key_length(cipher))) {
    LOG(ERROR) << "Invalid key length of " << key.size()
               << ", expected " << EVP_CIPHER_key_length(cipher);
    return false;
  }

  // ECB ignores the IV, so only check the IV length if we are using a different
  // block mode.
  if ((block_mode != kEcb) &&
      (iv.size() != static_cast<unsigned int>(EVP_CIPHER_iv_length(cipher)))) {
    LOG(ERROR) << "Invalid iv length of " << iv.size()
               << ", expected " << EVP_CIPHER_iv_length(cipher);
    return false;
  }

  // Initialize the OpenSSL crypto context
  EVP_CIPHER_CTX encryption_context;
  EVP_CIPHER_CTX_init(&encryption_context);
  EVP_EncryptInit_ex(&encryption_context, cipher, NULL, key.data(), iv.data());
  if (padding == kPaddingNone) {
    EVP_CIPHER_CTX_set_padding(&encryption_context, 0);
  }

  // First, encrypt the plain_text data
  unsigned int current_size = 0;
  int encrypt_size = 0;

  // Make sure we're not pointing into an empty buffer or past the end.
  const unsigned char *plain_buf = NULL;
  if (start < plain_text.size())
    plain_buf = &plain_text[start];

  if (!EVP_EncryptUpdate(&encryption_context, &cipher_text[current_size],
                         &encrypt_size, plain_buf, count)) {
    LOG(ERROR) << "EncryptUpdate failed";
    EVP_CIPHER_CTX_cleanup(&encryption_context);
    return false;
  }
  current_size += encrypt_size;
  encrypt_size = 0;

  // Next, if the padding uses the cryptohome default scheme, encrypt a SHA1
  // hash of the preceding plain_text into the output data
  if (padding == kPaddingCryptohomeDefault) {
    SHA_CTX sha_context;
    unsigned char md_value[SHA_DIGEST_LENGTH];

    SHA1_Init(&sha_context);
    SHA1_Update(&sha_context, &plain_text[start], count);
    SHA1_Final(md_value, &sha_context);
    if (!EVP_EncryptUpdate(&encryption_context, &cipher_text[current_size],
                           &encrypt_size, md_value, sizeof(md_value))) {
      LOG(ERROR) << "EncryptUpdate failed";
      EVP_CIPHER_CTX_cleanup(&encryption_context);
      return false;
    }
    current_size += encrypt_size;
    encrypt_size = 0;
  }

  // In the case of cipher_text being full, we must avoid trying to
  // point past the end of the buffer when calling EVP_EncryptFinal_ex().
  unsigned char *final_buf = NULL;
  if (static_cast<unsigned int>(current_size) < cipher_text.size())
    final_buf = &cipher_text[current_size];

  // Finally, finish the encryption
  if (!EVP_EncryptFinal_ex(&encryption_context, final_buf, &encrypt_size)) {
    LOG(ERROR) << "EncryptFinal failed";
    EVP_CIPHER_CTX_cleanup(&encryption_context);
    return false;
  }
  current_size += encrypt_size;
  cipher_text.resize(current_size);

  encrypted->swap(cipher_text);
  EVP_CIPHER_CTX_cleanup(&encryption_context);
  return true;
}

// Obscure (and Unobscure) RSA messages.
// Let k be a key derived from the user passphrase. On disk, we store
// m = ObscureRSAMessage(RSA-on-TPM(random-data), k). The reason for this
// function is the existence of an ambiguity in the TPM spec: the format of data
// returned by Tspi_Data_Bind is unspecified, so it's _possible_ (although does
// not happen in practice) that RSA-on-TPM(random-data) could start with some
// kind of ASN.1 header or whatever (some known data). If this was true, and we
// encrypted all of RSA-on-TPM(random-data), then one could test values of k by
// decrypting RSA-on-TPM(random-data) and looking for the known header, which
// would allow brute-forcing the user passphrase without talking to the TPM.
//
// Therefore, we instead encrypt _one block_ of RSA-on-TPM(random-data) with AES
// in ECB mode; we pick the last AES block, in the hope that that block will be
// part of the RSA message. TODO(ellyjones): why? if the TPM could add a header,
// it could also add a footer, and we'd be just as sunk.
//
// If we do encrypt part of the RSA message, the entirety of
// RSA-on-TPM(random-data) should be impossible to decrypt, without encrypting
// any known plaintext. This approach also requires brute-force attempts on k to
// go through the TPM, since there's no way to test a potential decryption
// without doing UnRSA-on-TPM() to see if the message is valid now.
bool CryptoLib::ObscureRSAMessage(const SecureBlob& plaintext,
                                  const SecureBlob& key,
                                  SecureBlob* ciphertext) {
  unsigned int aes_block_size = GetAesBlockSize();
  if (plaintext.size() < aes_block_size * 2) {
    LOG(ERROR) << "Plaintext is too small.";
    return false;
  }
  unsigned int offset = plaintext.size() - aes_block_size;

  SecureBlob obscured_chunk;
  if (!AesEncryptSpecifyBlockMode(plaintext, offset, aes_block_size, key,
                                  SecureBlob(0), kPaddingNone, kEcb,
                                  &obscured_chunk)) {
    LOG(ERROR) << "AES encryption failed.";
    return false;
  }
  ciphertext->resize(plaintext.size());
  char *data = reinterpret_cast<char*>(ciphertext->data());
  memcpy(data, plaintext.data(), plaintext.size());
  memcpy(data + offset, obscured_chunk.data(), obscured_chunk.size());
  return true;
}

bool CryptoLib::UnobscureRSAMessage(const SecureBlob& ciphertext,
                                    const SecureBlob& key,
                                    SecureBlob* plaintext) {
  unsigned int aes_block_size = GetAesBlockSize();
  if (ciphertext.size() < aes_block_size * 2) {
    LOG(ERROR) << "Ciphertext is is too small.";
    return false;
  }
  unsigned int offset = ciphertext.size() - aes_block_size;

  SecureBlob unobscured_chunk;
  if (!AesDecryptSpecifyBlockMode(ciphertext, offset, aes_block_size, key,
                                  SecureBlob(0), kPaddingNone, kEcb,
                                  &unobscured_chunk)) {
    LOG(ERROR) << "AES decryption failed.";
    return false;
  }
  plaintext->resize(ciphertext.size());
  char *data = reinterpret_cast<char*>(plaintext->data());
  memcpy(data, ciphertext.data(), ciphertext.size());
  memcpy(data + offset, unobscured_chunk.data(),
         unobscured_chunk.size());
  return true;
}

std::string CryptoLib::BlobToHex(const brillo::Blob& blob) {
  std::string buffer(blob.size() * 2, '\x00');
  BlobToHexToBuffer(blob, &buffer[0], buffer.size());
  return buffer;
}

void CryptoLib::BlobToHexToBuffer(const brillo::Blob& blob,
                                  void* buffer,
                                  size_t buffer_length) {
  static const char table[] = "0123456789abcdef";
  char* char_buffer = reinterpret_cast<char*>(buffer);
  char* char_buffer_end = char_buffer + buffer_length;
  for (uint8_t byte : blob) {
    if (char_buffer == char_buffer_end)
      break;
    *char_buffer++ = table[(byte >> 4) & 0x0f];
    if (char_buffer == char_buffer_end)
      break;
    *char_buffer++ = table[byte & 0x0f];
  }
  if (char_buffer != char_buffer_end)
    *char_buffer = '\x00';
}

std::string CryptoLib::ComputeEncryptedDataHMAC(
    const EncryptedData& encrypted_data, const SecureBlob& hmac_key) {
  SecureBlob blob1(encrypted_data.iv().begin(), encrypted_data.iv().end());
  SecureBlob blob2(encrypted_data.encrypted_data().begin(),
                   encrypted_data.encrypted_data().end());
  SecureBlob result = SecureBlob::Combine(blob1, blob2);
  SecureBlob hmac = HmacSha512(hmac_key, result);
  return hmac.to_string();
}

}  // namespace cryptohome
