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

#include <limits>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include <base/logging.h>
#include <brillo/secure_blob.h>
#include <crypto/libcrypto-compat.h>
#include <crypto/scoped_openssl_types.h>
#include <openssl/bio.h>
#include <openssl/des.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/ec.h>

#include "chaps/chaps.h"
#include "chaps/chaps_factory.h"
#include "chaps/chaps_utility.h"
#include "chaps/object.h"
#include "chaps/object_pool.h"
#include "chaps/tpm_utility.h"
#include "pkcs11/cryptoki.h"

#define CKK_INVALID_KEY_TYPE (CKK_VENDOR_DEFINED + 0)

using brillo::SecureBlob;
using ScopedASN1_OCTET_STRING =
    crypto::ScopedOpenSSL<ASN1_OCTET_STRING, ASN1_OCTET_STRING_free>;
using std::hex;
using std::map;
using std::set;
using std::string;
using std::vector;

namespace chaps {

namespace {

using chaps::OperationType::kDecrypt;
using chaps::OperationType::kDigest;
using chaps::OperationType::kEncrypt;
using chaps::OperationType::kSign;
using chaps::OperationType::kVerify;

const int kDefaultAuthDataBytes = 20;
const int kMaxCipherBlockBytes = 16;
const int kMaxRSAOutputBytes = 2048;
const int kMaxDigestOutputBytes = EVP_MAX_MD_SIZE;
const int kMinRSAKeyBits = 512;
const int kMaxRSAKeyBits = kMaxRSAOutputBytes * 8;

CK_RV ResultToRV(chaps::ObjectPool::Result result, CK_RV fail_rv) {
  switch (result) {
    case chaps::ObjectPool::Result::Success:
      return CKR_OK;
    case chaps::ObjectPool::Result::Failure:
      return fail_rv;
    case chaps::ObjectPool::Result::WaitForPrivateObjects:
      return CKR_WOULD_BLOCK_FOR_PRIVATE_OBJECTS;
  }
}

bool IsSuccess(chaps::ObjectPool::Result result) {
  return result == chaps::ObjectPool::Result::Success;
}

class MechanismInfo {
 public:
  explicit MechanismInfo(CK_MECHANISM_TYPE mechanism);
  bool IsSupported() const;
  bool IsOperationValid(chaps::OperationType op) const;
  bool IsForKeyType(CK_KEY_TYPE keytype) const;

 private:
  struct MechanismInfoData {
    bool is_supported;
    set<chaps::OperationType> operation;
    CK_KEY_TYPE key_type;
  };

  static MechanismInfoData GetSupportedMechanismInfo(
      CK_MECHANISM_TYPE mechanism);

  MechanismInfoData data_;
};

MechanismInfo::MechanismInfo(CK_MECHANISM_TYPE mechanism)
    : data_(GetSupportedMechanismInfo(mechanism)) {}

bool MechanismInfo::IsSupported() const {
  return data_.is_supported;
}

bool MechanismInfo::IsOperationValid(chaps::OperationType op) const {
  return IsSupported() && data_.operation.count(op) > 0;
}

bool MechanismInfo::IsForKeyType(CK_KEY_TYPE keytype) const {
  return IsSupported() && data_.key_type == keytype;
}

MechanismInfo::MechanismInfoData MechanismInfo::GetSupportedMechanismInfo(
    CK_MECHANISM_TYPE mechanism) {
  switch (mechanism) {
    // DES
    case CKM_DES_ECB:
    case CKM_DES_CBC:
    case CKM_DES_CBC_PAD:
      return {true, {kEncrypt, kDecrypt}, CKK_DES};

    // DES3
    case CKM_DES3_ECB:
    case CKM_DES3_CBC:
    case CKM_DES3_CBC_PAD:
      return {true, {kEncrypt, kDecrypt}, CKK_DES3};

    // AES
    case CKM_AES_ECB:
    case CKM_AES_CBC:
    case CKM_AES_CBC_PAD:
      return {true, {kEncrypt, kDecrypt}, CKK_AES};

    // RSA PKCS v1.5
    case CKM_RSA_PKCS:
      return {true, {kEncrypt, kDecrypt, kSign, kVerify}, CKK_RSA};
    case CKM_MD5_RSA_PKCS:
    case CKM_SHA1_RSA_PKCS:
    case CKM_SHA256_RSA_PKCS:
    case CKM_SHA384_RSA_PKCS:
    case CKM_SHA512_RSA_PKCS:
      return {true, {kSign, kVerify}, CKK_RSA};

    // RSA RSS
    case CKM_RSA_PKCS_PSS:
    case CKM_SHA1_RSA_PKCS_PSS:
    case CKM_SHA256_RSA_PKCS_PSS:
    case CKM_SHA384_RSA_PKCS_PSS:
    case CKM_SHA512_RSA_PKCS_PSS:
    case CKM_SHA224_RSA_PKCS_PSS:
      return {true, {kSign, kVerify}, CKK_RSA};

    // ECC
    case CKM_ECDSA:
    case CKM_ECDSA_SHA1:
      return {true, {kSign, kVerify}, CKK_EC};

    // HMAC
    case CKM_MD5_HMAC:
    case CKM_SHA_1_HMAC:
    case CKM_SHA256_HMAC:
    case CKM_SHA384_HMAC:
    case CKM_SHA512_HMAC:
      return {true, {kSign, kVerify}, CKK_GENERIC_SECRET};

    // Digest
    case CKM_MD5:
    case CKM_SHA_1:
    case CKM_SHA256:
    case CKM_SHA384:
    case CKM_SHA512:
      return {true, {kDigest}, CKK_INVALID_KEY_TYPE};

    default:
      return {false, {}, CKK_INVALID_KEY_TYPE};
  }
}

bool IsHMAC(CK_MECHANISM_TYPE mechanism) {
  return MechanismInfo(mechanism).IsForKeyType(CKK_GENERIC_SECRET);
}

// Returns true if the given block cipher (AES/DES) mechanism uses padding.
bool IsPaddingEnabled(CK_MECHANISM_TYPE mechanism) {
  switch (mechanism) {
    case CKM_DES_CBC_PAD:
    case CKM_DES3_CBC_PAD:
    case CKM_AES_CBC_PAD:
      return true;

    default:
      return false;
  }
}

bool IsRSA(CK_MECHANISM_TYPE mechanism) {
  return MechanismInfo(mechanism).IsForKeyType(CKK_RSA);
}

bool IsECC(CK_MECHANISM_TYPE mechanism) {
  return MechanismInfo(mechanism).IsForKeyType(CKK_EC);
}

bool IsMechanismValidForOperation(chaps::OperationType operation,
                                  CK_MECHANISM_TYPE mechanism) {
  return MechanismInfo(mechanism).IsOperationValid(operation);
}

CK_OBJECT_CLASS GetExpectedObjectClass(chaps::OperationType operation,
                                       CK_KEY_TYPE key_type) {
  bool use_private_key = operation == kSign || operation == kDecrypt;
  switch (key_type) {
    case CKK_DES:
    case CKK_DES3:
    case CKK_AES:
      return CKO_SECRET_KEY;
    case CKK_RSA:
    case CKK_EC:
      return use_private_key ? CKO_PRIVATE_KEY : CKO_PUBLIC_KEY;
    case CKK_GENERIC_SECRET:
      return CKO_SECRET_KEY;

    default:
      // Never used
      NOTREACHED();
      return -1;
  }
}

// Check |object_class| and |key_type| is valid for |mechanism| and |operation|
bool IsValidKeyType(chaps::OperationType operation,
                    CK_MECHANISM_TYPE mechanism,
                    CK_OBJECT_CLASS object_class,
                    CK_KEY_TYPE key_type) {
  return MechanismInfo(mechanism).IsForKeyType(key_type) &&
         object_class == GetExpectedObjectClass(operation, key_type);
}

const EVP_CIPHER* GetOpenSSLCipher(CK_MECHANISM_TYPE mechanism,
                                   size_t key_size) {
  switch (mechanism) {
    case CKM_DES_ECB:
      return EVP_des_ecb();
    case CKM_DES_CBC:
    case CKM_DES_CBC_PAD:
      return EVP_des_cbc();
    case CKM_DES3_ECB:
      return EVP_des_ede3();
    case CKM_DES3_CBC:
    case CKM_DES3_CBC_PAD:
      return EVP_des_ede3_cbc();
    case CKM_AES_ECB:
      switch (key_size) {
        case 16:
          return EVP_aes_128_ecb();
        case 24:
          return EVP_aes_192_ecb();
        default:
          return EVP_aes_256_ecb();
      }
      break;
    case CKM_AES_CBC:
    case CKM_AES_CBC_PAD:
      switch (key_size) {
        case 16:
          return EVP_aes_128_cbc();
        case 24:
          return EVP_aes_192_cbc();
        default:
          return EVP_aes_256_cbc();
      }
      break;
  }
  return nullptr;
}

string GetDERDigestInfo(CK_MECHANISM_TYPE mechanism) {
  return GetDigestAlgorithmEncoding(chaps::GetDigestAlgorithm(mechanism));
}

// TODO(menghuan): Move Create*KeyFromObject to the member function of object.
crypto::ScopedEC_KEY CreateECCPublicKeyFromObject(const Object* key_object) {
  // Start parsing EC_PARAMS
  string ec_params = key_object->GetAttributeString(CKA_EC_PARAMS);
  crypto::ScopedEC_KEY key = chaps::CreateECCKeyFromEC_PARAMS(ec_params);
  if (key == nullptr)
    return nullptr;

  // Start parsing EC_POINT
  // DER decode EC_POINT to OCT_STRING
  string pub_data = key_object->GetAttributeString(CKA_EC_POINT);
  const unsigned char* buf = chaps::ConvertStringToByteBuffer(pub_data.data());
  ScopedASN1_OCTET_STRING os(
      d2i_ASN1_OCTET_STRING(nullptr, &buf, pub_data.size()));
  if (os == nullptr)
    return nullptr;

  // Convert OCT_STRING to *EC_KEY
  buf = os->data;
  EC_KEY* key_ptr = key.get();
  key_ptr = o2i_ECPublicKey(&key_ptr, &buf, os->length);
  if (key_ptr == nullptr)
    return nullptr;
  CHECK_EQ(key_ptr, key.get());

  if (!EC_KEY_check_key(key.get())) {
    LOG(ERROR) << __func__
               << ": Bad key created from object. OpenSSL key check fail.";
    return nullptr;
  }

  return key;
}

crypto::ScopedEC_KEY CreateECCPrivateKeyFromObject(const Object* key_object) {
  // Parse EC_PARAMS
  string ec_params = key_object->GetAttributeString(CKA_EC_PARAMS);
  crypto::ScopedEC_KEY key = chaps::CreateECCKeyFromEC_PARAMS(ec_params);
  if (key == nullptr)
    return nullptr;

  crypto::ScopedBIGNUM d(BN_new());
  if (!d) {
    LOG(ERROR) << "Failed to allocate BIGNUM.";
    return nullptr;
  }

  if (!chaps::ConvertToBIGNUM(key_object->GetAttributeString(CKA_VALUE),
                              d.get())) {
    LOG(ERROR) << "Failed to convert CKA_VALUE to BIGNUM.";
    return nullptr;
  }

  if (!EC_KEY_set_private_key(key.get(), d.get()))
    return nullptr;

  // OpenSSL will not set public key field. Need to manually compute.
  const EC_GROUP* group = EC_KEY_get0_group(key.get());
  if (group == nullptr)
    return nullptr;

  crypto::ScopedEC_POINT pub_key(EC_POINT_new(group));
  EC_POINT_mul(group, pub_key.get(), d.get(), nullptr, nullptr, nullptr);
  if (!EC_KEY_set_public_key(key.get(), pub_key.get()))
    return nullptr;

  if (!EC_KEY_check_key(key.get())) {
    LOG(ERROR) << __func__
               << ": Bad key created from object. OpenSSL key check fail.";
    return nullptr;
  }

  return key;
}

crypto::ScopedRSA CreateRSAKeyFromObject(const chaps::Object* key_object) {
  crypto::ScopedRSA rsa(RSA_new());
  if (!rsa) {
    LOG(ERROR) << "Failed to allocate RSA or BIGNUM for key.";
    return nullptr;
  }
  if (key_object->GetObjectClass() == CKO_PUBLIC_KEY) {
    crypto::ScopedBIGNUM rsa_n(BN_new()), rsa_e(BN_new());
    if (!rsa_n || !rsa_e) {
      LOG(ERROR) << "Failed to allocate RSA or BIGNUM for key.";
      return nullptr;
    }
    string n = key_object->GetAttributeString(CKA_MODULUS);
    string e = key_object->GetAttributeString(CKA_PUBLIC_EXPONENT);
    if (!chaps::ConvertToBIGNUM(n, rsa_n.get()) ||
        !chaps::ConvertToBIGNUM(e, rsa_e.get())) {
      LOG(ERROR) << "Failed to convert modulus or exponent for key.";
      return nullptr;
    }
    if (!RSA_set0_key(rsa.get(), rsa_n.release(), rsa_e.release(), nullptr)) {
      LOG(ERROR) << "Failed to set modulus or exponent for RSA.";
      return nullptr;
    }
  } else {  // key_object->GetObjectClass() == CKO_PRIVATE_KEY
    crypto::ScopedBIGNUM rsa_n(BN_new()), rsa_e(BN_new()), rsa_d(BN_new()),
        rsa_p(BN_new()), rsa_q(BN_new()), rsa_dmp1(BN_new()),
        rsa_dmq1(BN_new()), rsa_iqmp(BN_new());
    if (!rsa_n || !rsa_e || !rsa_d || !rsa_p || !rsa_q || !rsa_dmp1 ||
        !rsa_dmq1 || !rsa_iqmp) {
      LOG(ERROR) << "Failed to allocate BIGNUM for private key.";
      return nullptr;
    }
    string n = key_object->GetAttributeString(CKA_MODULUS);
    string e = key_object->GetAttributeString(CKA_PUBLIC_EXPONENT);
    string d = key_object->GetAttributeString(CKA_PRIVATE_EXPONENT);
    string p = key_object->GetAttributeString(CKA_PRIME_1);
    string q = key_object->GetAttributeString(CKA_PRIME_2);
    string dmp1 = key_object->GetAttributeString(CKA_EXPONENT_1);
    string dmq1 = key_object->GetAttributeString(CKA_EXPONENT_2);
    string iqmp = key_object->GetAttributeString(CKA_COEFFICIENT);
    if (!chaps::ConvertToBIGNUM(n, rsa_n.get()) ||
        !chaps::ConvertToBIGNUM(e, rsa_e.get()) ||
        !chaps::ConvertToBIGNUM(d, rsa_d.get()) ||
        !chaps::ConvertToBIGNUM(p, rsa_p.get()) ||
        !chaps::ConvertToBIGNUM(q, rsa_q.get()) ||
        !chaps::ConvertToBIGNUM(dmp1, rsa_dmp1.get()) ||
        !chaps::ConvertToBIGNUM(dmq1, rsa_dmq1.get()) ||
        !chaps::ConvertToBIGNUM(iqmp, rsa_iqmp.get())) {
      LOG(ERROR) << "Failed to convert parameters for private key.";
      return nullptr;
    }
    if (!RSA_set0_key(rsa.get(), rsa_n.release(), rsa_e.release(),
                      rsa_d.release()) ||
        !RSA_set0_factors(rsa.get(), rsa_p.release(), rsa_q.release()) ||
        !RSA_set0_crt_params(rsa.get(), rsa_dmp1.release(), rsa_dmq1.release(),
                             rsa_iqmp.release())) {
      LOG(ERROR) << "Failed to set parameters for private key RSA.";
      return nullptr;
    }
  }
  return rsa;
}

// TODO(crbug/916023): Move OpenSSL utility to cross daemon library.
// Return the length (in bytes) of group order of the EC key |key| or 0 on error
// which is aligned with OpenSSL design.
size_t GetGroupOrderLengthFromEcKey(const crypto::ScopedEC_KEY& key) {
  crypto::ScopedBIGNUM order(BN_new());
  if (!order) {
    LOG(ERROR) << "Failed to allocate BIGNUM for EC key order.";
    return 0;
  }

  const EC_GROUP* group = EC_KEY_get0_group(key.get());
  if (group == nullptr)
    return 0;

  if (!EC_GROUP_get_order(group, order.get(), nullptr))
    return 0;

  return BN_num_bytes(order.get());
}

// RSA Sign/Verify Helper
class RSASignerVerifier {
 public:
  // Just a default destructor, nothing more, nothing less.
  // Note: It's here because this is a base class, and we want to avoid having
  // non-virtual destructor in base class.
  virtual ~RSASignerVerifier() = default;

  // Sign |context->data_| with |rsa|.
  virtual bool Sign(crypto::ScopedRSA rsa,
                    SessionImpl::OperationContext* context) = 0;

  // Verify |signature| of |digest| against |rsa|.
  virtual CK_RV Verify(crypto::ScopedRSA rsa,
                       SessionImpl::OperationContext* context,
                       const string& digest,
                       const string& signature) = 0;

  static std::unique_ptr<RSASignerVerifier> GetForMechanism(
      CK_MECHANISM_TYPE mechanism);
};

// Sign/Verify helper for PKCS#1 v1.5
class RSASignerVerifierImplPKCS115 : public RSASignerVerifier {
 public:
  virtual ~RSASignerVerifierImplPKCS115() = default;

  bool Sign(crypto::ScopedRSA rsa,
            SessionImpl::OperationContext* context) final {
    if (RSA_size(rsa.get()) > kMaxRSAOutputBytes) {
      LOG(ERROR) << __func__ << ": RSA Key size is too large for PKCS#1 v1.5.";
      return false;
    }
    uint8_t buffer[kMaxRSAOutputBytes];
    // Emulate RSASSA by performing raw RSA (decrypting) with RSA_PKCS1_PADDING
    string input = GetDERDigestInfo(context->mechanism_) + context->data_;
    int length = RSA_private_encrypt(
        input.length(), ConvertStringToByteBuffer(input.data()), buffer,
        rsa.get(), RSA_PKCS1_PADDING);  // Adds PKCS #1 type 1 padding.
    if (length == -1) {
      LOG(ERROR) << __func__ << ": RSA_private_encrypt failed for PKCS#1 v1.5: "
                 << GetOpenSSLError();
      return false;
    }
    // Set the signature in context->data_.
    context->data_ = string(reinterpret_cast<char*>(buffer), length);
    return true;
  };

  CK_RV Verify(crypto::ScopedRSA rsa,
               SessionImpl::OperationContext* context,
               const string& digest,
               const string& signature) final {
    if (RSA_size(rsa.get()) > kMaxRSAOutputBytes) {
      LOG(ERROR) << __func__ << ": RSA Key size is too large for PKCS#1 v1.5.";
      return CKR_KEY_SIZE_RANGE;
    }
    uint8_t buffer[kMaxRSAOutputBytes];

    int length = RSA_public_decrypt(
        signature.length(), ConvertStringToByteBuffer(signature.data()), buffer,
        rsa.get(), RSA_PKCS1_PADDING);  // Strips PKCS #1 type 1 padding.
    if (length == -1) {
      LOG(ERROR) << __func__ << ": RSA_public_decrypt failed for PKCS#1 v1.5: "
                 << GetOpenSSLError();
      return CKR_SIGNATURE_INVALID;
    }
    string signed_data = GetDERDigestInfo(context->mechanism_) + digest;
    if (static_cast<size_t>(length) != signed_data.length() ||
        0 != brillo::SecureMemcmp(buffer, signed_data.data(), length)) {
      return CKR_SIGNATURE_INVALID;
    }
    return CKR_OK;
  };
};

// Sign/Verify helper for RSA PSS
class RSASignerVerifierImplPSS : public RSASignerVerifier {
 public:
  virtual ~RSASignerVerifierImplPSS() = default;

  bool Sign(crypto::ScopedRSA rsa,
            SessionImpl::OperationContext* context) final {
    if (RSA_size(rsa.get()) > kMaxRSAOutputBytes) {
      LOG(ERROR) << __func__ << ": RSA Key size is too large for RSA PSS.";
      return false;
    }
    uint8_t buffer[kMaxRSAOutputBytes];
    DigestAlgorithm digest_algorithm = GetDigestAlgorithm(context->mechanism_);
    // Parse the RSA PSS Parameters.
    const CK_RSA_PKCS_PSS_PARAMS* pss_params = nullptr;
    const EVP_MD* mgf1_hash = nullptr;
    if (!ParseRSAPSSParams(context->mechanism_, context->parameter_,
                           &pss_params, &mgf1_hash, &digest_algorithm)) {
      LOG(ERROR) << __func__ << ": Failed to parse RSA PSS parameters.";
      return false;
    }

    string padded_data(RSA_size(rsa.get()), 0);
    if (RSA_padding_add_PKCS1_PSS_mgf1(
            rsa.get(),
            reinterpret_cast<unsigned char*>(base::data(padded_data)),
            reinterpret_cast<const unsigned char*>(base::data(context->data_)),
            GetOpenSSLDigest(digest_algorithm), mgf1_hash,
            pss_params->sLen) != 1) {
      LOG(ERROR) << __func__ << ": Failed to produce the PSA PSS paddings.";
      return false;
    }
    int length = RSA_private_encrypt(
        padded_data.length(), ConvertStringToByteBuffer(padded_data.data()),
        buffer, rsa.get(), RSA_NO_PADDING);
    if (length == -1) {
      LOG(ERROR) << __func__
                 << ": RSA_private_encrypt failed: " << GetOpenSSLError();
      return false;
    }
    // Set the signature in context->data_.
    context->data_ = string(reinterpret_cast<char*>(buffer), length);
    return true;
  };

  CK_RV Verify(crypto::ScopedRSA rsa,
               SessionImpl::OperationContext* context,
               const string& digest,
               const string& signature) final {
    if (RSA_size(rsa.get()) > kMaxRSAOutputBytes) {
      LOG(ERROR) << __func__ << ": RSA Key size is too large for RSA PSS.";
      return CKR_KEY_SIZE_RANGE;
    }

    DigestAlgorithm digest_algorithm = GetDigestAlgorithm(context->mechanism_);
    uint8_t buffer[kMaxRSAOutputBytes];

    // Parse the RSA PSS Parameters.
    const CK_RSA_PKCS_PSS_PARAMS* pss_params = nullptr;
    const EVP_MD* mgf1_hash = nullptr;
    if (!ParseRSAPSSParams(context->mechanism_, context->parameter_,
                           &pss_params, &mgf1_hash, &digest_algorithm)) {
      LOG(ERROR) << __func__ << ": Failed to parse RSA PSS parameters.";
      return CKR_SIGNATURE_INVALID;
    }

    int expected_size = EVP_MD_size(GetOpenSSLDigest(digest_algorithm));
    if (digest.size() != expected_size) {
      LOG(ERROR) << __func__ << ": Size mismatch with RSAPSS, expected "
                 << expected_size << ", actual " << digest.size();
      return CKR_SIGNATURE_INVALID;
    }

    int length = RSA_public_decrypt(signature.length(),
                                    ConvertStringToByteBuffer(signature.data()),
                                    buffer, rsa.get(), RSA_NO_PADDING);
    if (length == -1) {
      LOG(ERROR) << __func__
                 << ": RSA_public_decrypt failed: " << GetOpenSSLError();
      return CKR_SIGNATURE_INVALID;
    }
    if (RSA_verify_PKCS1_PSS_mgf1(
            rsa.get(), reinterpret_cast<const unsigned char*>(digest.data()),
            GetOpenSSLDigest(digest_algorithm), mgf1_hash, buffer,
            pss_params->sLen) != 1) {
      LOG(ERROR) << __func__ << ": Incorrect PSS padding.";
      return CKR_SIGNATURE_INVALID;
    }
    return CKR_OK;
  };
};

std::unique_ptr<RSASignerVerifier> RSASignerVerifier::GetForMechanism(
    CK_MECHANISM_TYPE mechanism) {
  auto scheme = GetSigningSchemeForMechanism(mechanism);
  switch (scheme) {
    case RsaPaddingScheme::RSASSA_PKCS1_V1_5:
      return std::make_unique<RSASignerVerifierImplPKCS115>();
    case RsaPaddingScheme::RSASSA_PSS:
      return std::make_unique<RSASignerVerifierImplPSS>();
    default:
      LOG(ERROR) << __func__ << ": Invalid mechanism "
                 << static_cast<int64_t>(mechanism);
      return nullptr;
  }
}

}  // namespace

SessionImpl::SessionImpl(int slot_id,
                         ObjectPool* token_object_pool,
                         TPMUtility* tpm_utility,
                         ChapsFactory* factory,
                         HandleGenerator* handle_generator,
                         bool is_read_only)
    : factory_(factory),
      find_results_valid_(false),
      is_read_only_(is_read_only),
      slot_id_(slot_id),
      token_object_pool_(token_object_pool),
      tpm_utility_(tpm_utility),
      is_legacy_loaded_(false),
      private_root_key_(0),
      public_root_key_(0) {
  CHECK(token_object_pool_);
  CHECK(tpm_utility_);
  CHECK(factory_);
  session_object_pool_.reset(
      factory_->CreateObjectPool(handle_generator, nullptr, nullptr));
  CHECK(session_object_pool_.get());
}

SessionImpl::~SessionImpl() {}

int SessionImpl::GetSlot() const {
  return slot_id_;
}

CK_STATE SessionImpl::GetState() const {
  return is_read_only_ ? CKS_RO_USER_FUNCTIONS : CKS_RW_USER_FUNCTIONS;
}

bool SessionImpl::IsReadOnly() const {
  return is_read_only_;
}

bool SessionImpl::IsOperationActive(OperationType type) const {
  CHECK(type < kNumOperationTypes);
  return operation_context_[type].is_valid_;
}

CK_RV SessionImpl::CreateObject(const CK_ATTRIBUTE_PTR attributes,
                                int num_attributes,
                                int* new_object_handle) {
  return CreateObjectInternal(attributes, num_attributes, nullptr,
                              new_object_handle);
}

CK_RV SessionImpl::CopyObject(const CK_ATTRIBUTE_PTR attributes,
                              int num_attributes,
                              int object_handle,
                              int* new_object_handle) {
  const Object* orig_object = nullptr;
  if (!GetObject(object_handle, &orig_object))
    return CKR_OBJECT_HANDLE_INVALID;
  CHECK(orig_object);
  return CreateObjectInternal(attributes, num_attributes, orig_object,
                              new_object_handle);
}

CK_RV SessionImpl::DestroyObject(int object_handle) {
  const Object* object = nullptr;
  if (!GetObject(object_handle, &object))
    return CKR_OBJECT_HANDLE_INVALID;
  CHECK(object);
  ObjectPool* pool =
      object->IsTokenObject() ? token_object_pool_ : session_object_pool_.get();
  return ResultToRV(pool->Delete(object), CKR_GENERAL_ERROR);
}

bool SessionImpl::GetObject(int object_handle, const Object** object) {
  CHECK(object);
  if (token_object_pool_->FindByHandle(object_handle, object) ==
      ObjectPool::Result::Success)
    return true;
  return session_object_pool_->FindByHandle(object_handle, object) ==
         ObjectPool::Result::Success;
}

bool SessionImpl::GetModifiableObject(int object_handle, Object** object) {
  CHECK(object);
  const Object* const_object;
  if (!GetObject(object_handle, &const_object))
    return false;
  ObjectPool* pool = const_object->IsTokenObject() ? token_object_pool_
                                                   : session_object_pool_.get();
  *object = pool->GetModifiableObject(const_object);
  return true;
}

CK_RV SessionImpl::FlushModifiableObject(Object* object) {
  CHECK(object);
  ObjectPool* pool =
      object->IsTokenObject() ? token_object_pool_ : session_object_pool_.get();
  return ResultToRV(pool->Flush(object), CKR_FUNCTION_FAILED);
}

CK_RV SessionImpl::FindObjectsInit(const CK_ATTRIBUTE_PTR attributes,
                                   int num_attributes) {
  if (find_results_valid_)
    return CKR_OPERATION_ACTIVE;
  std::unique_ptr<Object> search_template(factory_->CreateObject());
  CHECK(search_template.get());
  search_template->SetAttributes(attributes, num_attributes);
  vector<const Object*> objects;
  if (!search_template->IsAttributePresent(CKA_TOKEN) ||
      search_template->IsTokenObject()) {
    auto res = token_object_pool_->Find(search_template.get(), &objects);
    if (!IsSuccess(res))
      return ResultToRV(res, CKR_GENERAL_ERROR);
  }
  if (!search_template->IsAttributePresent(CKA_TOKEN) ||
      !search_template->IsTokenObject()) {
    auto res = session_object_pool_->Find(search_template.get(), &objects);
    if (!IsSuccess(res))
      return ResultToRV(res, CKR_GENERAL_ERROR);
  }
  find_results_.clear();
  find_results_offset_ = 0;
  find_results_valid_ = true;
  for (size_t i = 0; i < objects.size(); ++i) {
    find_results_.push_back(objects[i]->handle());
  }
  return CKR_OK;
}

CK_RV SessionImpl::FindObjects(int max_object_count,
                               vector<int>* object_handles) {
  CHECK(object_handles);
  if (!find_results_valid_)
    return CKR_OPERATION_NOT_INITIALIZED;
  size_t end_offset =
      find_results_offset_ + static_cast<size_t>(max_object_count);
  if (end_offset > find_results_.size())
    end_offset = find_results_.size();
  for (size_t i = find_results_offset_; i < end_offset; ++i) {
    object_handles->push_back(find_results_[i]);
  }
  find_results_offset_ += object_handles->size();
  return CKR_OK;
}

CK_RV SessionImpl::FindObjectsFinal() {
  if (!find_results_valid_)
    return CKR_OPERATION_NOT_INITIALIZED;
  find_results_valid_ = false;
  return CKR_OK;
}

CK_RV SessionImpl::OperationInit(OperationType operation,
                                 CK_MECHANISM_TYPE mechanism,
                                 const string& mechanism_parameter,
                                 const Object* key) {
  CHECK(operation < kNumOperationTypes);

  OperationContext* context = &operation_context_[operation];
  if (context->is_valid_) {
    LOG(ERROR) << "Operation is already active.";
    return CKR_OPERATION_ACTIVE;
  }

  context->Clear();
  context->mechanism_ = mechanism;
  context->parameter_ = mechanism_parameter;

  if (!IsMechanismValidForOperation(operation, mechanism)) {
    LOG(ERROR) << "Mechanism not supported: 0x" << hex << mechanism;
    return CKR_MECHANISM_INVALID;
  }

  if (operation == kSign || operation == kVerify || operation == kEncrypt ||
      operation == kDecrypt) {
    // Make sure the key is valid for the mechanism.
    CHECK(key);
    if (!IsValidKeyType(
            operation, mechanism, key->GetObjectClass(),
            key->GetAttributeInt(CKA_KEY_TYPE, CK_UNAVAILABLE_INFORMATION))) {
      LOG(ERROR) << "Key type mismatch.";
      return CKR_KEY_TYPE_INCONSISTENT;
    }
    if (!key->GetAttributeBool(GetRequiredKeyUsage(operation), false)) {
      LOG(ERROR) << "Key function not permitted.";
      return CKR_KEY_FUNCTION_NOT_PERMITTED;
    }
    if (IsRSA(mechanism)) {
      // Refuse to use RSA keys with unsupported sizes that may have been
      // created in an earlier version of chaps.
      int key_size = key->GetAttributeString(CKA_MODULUS).length() * 8;
      if (key_size < kMinRSAKeyBits || key_size > kMaxRSAKeyBits) {
        LOG(ERROR) << "Key size not supported: " << key_size;
        return CKR_KEY_SIZE_RANGE;
      }
    }
  }

  if (operation == kEncrypt || operation == kDecrypt) {
    if (mechanism == CKM_RSA_PKCS) {
      context->key_ = key;
      context->is_valid_ = true;
    } else {
      return CipherInit((operation == kEncrypt), mechanism, mechanism_parameter,
                        key);
    }
  } else if (operation == kSign || operation == kVerify ||
             operation == kDigest) {
    // It is valid for GetOpenSSLDigestForMechanism to return NULL (e.g.
    // CKM_RSA_PKCS).
    const EVP_MD* digest = GetOpenSSLDigestForMechanism(mechanism);
    if (IsHMAC(mechanism)) {
      string key_material = key->GetAttributeString(CKA_VALUE);
      context->hmac_context_.reset(HMAC_CTX_new());
      if (!context->hmac_context_) {
        LOG(ERROR) << "Failed to allocate HMAC context";
        return CKR_FUNCTION_FAILED;
      }
      HMAC_Init_ex(context->hmac_context_.get(), key_material.data(),
                   key_material.length(), digest, nullptr);
      context->is_hmac_ = true;
    } else if (digest) {
      context->digest_context_.reset(EVP_MD_CTX_new());
      if (!context->digest_context_) {
        LOG(ERROR) << "Failed to allocate EVP_MD context";
        return CKR_FUNCTION_FAILED;
      }
      EVP_DigestInit_ex(context->digest_context_.get(), digest, nullptr);
      context->is_digest_ = true;
    }
    if (IsRSA(mechanism) || IsECC(mechanism))
      context->key_ = key;
    context->is_valid_ = true;
  } else {
    NOTREACHED();
    return CKR_FUNCTION_FAILED;
  }
  return CKR_OK;
}

CK_RV SessionImpl::OperationUpdate(OperationType operation,
                                   const string& data_in,
                                   int* required_out_length,
                                   string* data_out) {
  CHECK(operation < kNumOperationTypes);
  OperationContext* context = &operation_context_[operation];
  if (!context->is_valid_) {
    LOG(ERROR) << "Operation is not initialized.";
    return CKR_OPERATION_NOT_INITIALIZED;
  }
  if (context->is_finished_) {
    LOG(ERROR) << "Operation is finished.";
    OperationCancel(operation);
    return CKR_OPERATION_ACTIVE;
  }
  context->is_incremental_ = true;
  return OperationUpdateInternal(operation, data_in, required_out_length,
                                 data_out);
}

CK_RV SessionImpl::OperationUpdateInternal(OperationType operation,
                                           const string& data_in,
                                           int* required_out_length,
                                           string* data_out) {
  CHECK(operation < kNumOperationTypes);
  OperationContext* context = &operation_context_[operation];
  if (context->is_cipher_) {
    CK_RV rv = CipherUpdate(context, data_in, required_out_length, data_out);
    if ((rv != CKR_OK) && (rv != CKR_BUFFER_TOO_SMALL))
      OperationCancel(operation);
    return rv;
  } else if (context->is_digest_) {
    EVP_DigestUpdate(context->digest_context_.get(), data_in.data(),
                     data_in.length());
  } else if (context->is_hmac_) {
    HMAC_Update(context->hmac_context_.get(),
                ConvertStringToByteBuffer(data_in.c_str()), data_in.length());
  } else {
    // We don't need to process now; just queue the data.
    context->data_ += data_in;
  }
  if (required_out_length)
    *required_out_length = 0;
  return CKR_OK;
}

void SessionImpl::OperationCancel(OperationType operation) {
  CHECK(operation < kNumOperationTypes);
  OperationContext* context = &operation_context_[operation];
  if (!context->is_valid_) {
    LOG(ERROR) << "Operation is not initialized.";
    return;
  }
  // Drop the context and any associated data.
  context->Clear();
}

CK_RV SessionImpl::OperationFinal(OperationType operation,
                                  int* required_out_length,
                                  string* data_out) {
  CHECK(required_out_length);
  CHECK(data_out);
  CHECK(operation < kNumOperationTypes);
  OperationContext* context = &operation_context_[operation];
  if (!context->is_valid_) {
    LOG(ERROR) << "Operation is not initialized.";
    return CKR_OPERATION_NOT_INITIALIZED;
  }
  if (!context->is_incremental_ && context->is_finished_) {
    LOG(ERROR) << "Operation is not incremental.";
    OperationCancel(operation);
    return CKR_OPERATION_ACTIVE;
  }
  context->is_incremental_ = true;
  return OperationFinalInternal(operation, required_out_length, data_out);
}

CK_RV SessionImpl::OperationFinalInternal(OperationType operation,
                                          int* required_out_length,
                                          string* data_out) {
  CHECK(operation < kNumOperationTypes);

  OperationContext* context = &operation_context_[operation];
  context->is_valid_ = false;

  // Complete the operation if it has not already been done.
  if (!context->is_finished_) {
    if (context->is_cipher_) {
      CK_RV result = CipherFinal(context);
      if (result != CKR_OK)
        return result;
    } else if (context->is_digest_) {
      unsigned char buffer[kMaxDigestOutputBytes];
      unsigned int out_length = 0;
      EVP_DigestFinal_ex(context->digest_context_.get(), buffer, &out_length);
      context->data_ = string(reinterpret_cast<char*>(buffer), out_length);
    } else if (context->is_hmac_) {
      unsigned char buffer[kMaxDigestOutputBytes];
      unsigned int out_length = 0;
      HMAC_Final(context->hmac_context_.get(), buffer, &out_length);
      context->data_ = string(reinterpret_cast<char*>(buffer), out_length);
    }

    // Some RSA/ECC mechanisms use a digest so it's important to finish the
    // digest before finishing the RSA/ECC computation.
    if (IsRSA(context->mechanism_)) {
      if (operation == kEncrypt) {
        if (!RSAEncrypt(context))
          return CKR_FUNCTION_FAILED;
      } else if (operation == kDecrypt) {
        if (!RSADecrypt(context))
          return CKR_FUNCTION_FAILED;
      } else if (operation == kSign) {
        if (!RSASign(context))
          return CKR_FUNCTION_FAILED;
      }
    } else if (IsECC(context->mechanism_)) {
      if (operation == kSign) {
        if (!ECCSign(context))
          return CKR_FUNCTION_FAILED;
      }
    }
    context->is_finished_ = true;
  }
  CK_RV result = GetOperationOutput(context, required_out_length, data_out);
  if (result == CKR_BUFFER_TOO_SMALL) {
    // We'll keep the context valid so a subsequent call can pick up the data.
    context->is_valid_ = true;
  }
  return result;
}

CK_RV SessionImpl::VerifyFinal(const string& signature) {
  OperationContext* context = &operation_context_[kVerify];
  // Call the generic OperationFinal so any digest or HMAC computation gets
  // finalized.
  int max_out_length = std::numeric_limits<int>::max();
  string data_out;
  CK_RV result = OperationFinal(kVerify, &max_out_length, &data_out);
  if (result != CKR_OK)
    return result;

  // We only support 3 Verify mechanisms, HMAC, RSA and ECC.
  if (context->is_hmac_) {
    // The data_out contents will be the computed HMAC. To verify an HMAC, it is
    // recomputed and literally compared.
    if (signature.length() != data_out.length())
      return CKR_SIGNATURE_LEN_RANGE;

    if (0 != brillo::SecureMemcmp(signature.data(), data_out.data(),
                                  signature.length()))
      return CKR_SIGNATURE_INVALID;

    return CKR_OK;
  } else if (IsRSA(context->mechanism_)) {
    // The data_out contents will be the computed digest.
    return RSAVerify(context, data_out, signature);
  } else if (IsECC(context->mechanism_)) {
    // The data_out contents will be the computed digest.
    return ECCVerify(context, data_out, signature);
  } else {
    NOTREACHED();
    return false;
  }
}

CK_RV SessionImpl::OperationSinglePart(OperationType operation,
                                       const string& data_in,
                                       int* required_out_length,
                                       string* data_out) {
  CHECK(operation < kNumOperationTypes);
  OperationContext* context = &operation_context_[operation];
  if (!context->is_valid_) {
    LOG(ERROR) << "Operation is not initialized.";
    return CKR_OPERATION_NOT_INITIALIZED;
  }
  if (context->is_incremental_) {
    LOG(ERROR) << "Operation is incremental.";
    OperationCancel(operation);
    return CKR_OPERATION_ACTIVE;
  }
  CK_RV result = CKR_OK;
  if (!context->is_finished_) {
    string update, final;
    int max = std::numeric_limits<int>::max();
    result = OperationUpdateInternal(operation, data_in, &max, &update);
    if (result != CKR_OK)
      return result;
    max = std::numeric_limits<int>::max();
    result = OperationFinalInternal(operation, &max, &final);
    if (result != CKR_OK)
      return result;
    context->data_ = update + final;
    context->is_finished_ = true;
  }
  context->is_valid_ = false;
  result = GetOperationOutput(context, required_out_length, data_out);
  if (result == CKR_BUFFER_TOO_SMALL) {
    // We'll keep the context valid so a subsequent call can pick up the data.
    context->is_valid_ = true;
  }
  return result;
}

CK_RV SessionImpl::GenerateKey(CK_MECHANISM_TYPE mechanism,
                               const string& mechanism_parameter,
                               const CK_ATTRIBUTE_PTR attributes,
                               int num_attributes,
                               int* new_key_handle) {
  CHECK(new_key_handle);
  std::unique_ptr<Object> object(factory_->CreateObject());
  CHECK(object.get());
  CK_RV result = object->SetAttributes(attributes, num_attributes);
  if (result != CKR_OK)
    return result;
  CK_KEY_TYPE key_type = 0;
  string key_material;
  switch (mechanism) {
    case CKM_DES_KEY_GEN: {
      key_type = CKK_DES;
      if (!GenerateDESKey(&key_material))
        return CKR_FUNCTION_FAILED;
      break;
    }
    case CKM_DES3_KEY_GEN: {
      key_type = CKK_DES3;
      string des[3];
      for (int i = 0; i < 3; ++i) {
        if (!GenerateDESKey(&des[i]))
          return CKR_FUNCTION_FAILED;
      }
      key_material = des[0] + des[1] + des[2];
      break;
    }
    case CKM_AES_KEY_GEN: {
      key_type = CKK_AES;
      if (!object->IsAttributePresent(CKA_VALUE_LEN))
        return CKR_TEMPLATE_INCOMPLETE;
      CK_ULONG key_length = object->GetAttributeInt(CKA_VALUE_LEN, 0);
      if (key_length != 16 && key_length != 24 && key_length != 32)
        return CKR_KEY_SIZE_RANGE;
      key_material = GenerateRandomSoftware(key_length);
      break;
    }
    case CKM_GENERIC_SECRET_KEY_GEN: {
      key_type = CKK_GENERIC_SECRET;
      if (!object->IsAttributePresent(CKA_VALUE_LEN))
        return CKR_TEMPLATE_INCOMPLETE;
      CK_ULONG key_length = object->GetAttributeInt(CKA_VALUE_LEN, 0);
      if (key_length < 1)
        return CKR_KEY_SIZE_RANGE;
      key_material = GenerateRandomSoftware(key_length);
      break;
    }
    default: {
      LOG(ERROR) << "GenerateKey: Mechanism not supported: " << hex
                 << mechanism;
      return CKR_MECHANISM_INVALID;
    }
  }
  object->SetAttributeInt(CKA_CLASS, CKO_SECRET_KEY);
  object->SetAttributeInt(CKA_KEY_TYPE, key_type);
  object->SetAttributeString(CKA_VALUE, key_material);
  object->SetAttributeBool(CKA_LOCAL, true);
  object->SetAttributeInt(CKA_KEY_GEN_MECHANISM, mechanism);
  result = object->FinalizeNewObject();
  if (result != CKR_OK)
    return result;
  ObjectPool* pool =
      object->IsTokenObject() ? token_object_pool_ : session_object_pool_.get();
  auto pool_res = pool->Insert(object.get());
  if (!IsSuccess(pool_res))
    return ResultToRV(pool_res, CKR_FUNCTION_FAILED);
  *new_key_handle = object.release()->handle();
  return CKR_OK;
}

CK_RV SessionImpl::GenerateKeyPair(CK_MECHANISM_TYPE mechanism,
                                   const string& mechanism_parameter,
                                   const CK_ATTRIBUTE_PTR public_attributes,
                                   int num_public_attributes,
                                   const CK_ATTRIBUTE_PTR private_attributes,
                                   int num_private_attributes,
                                   int* new_public_key_handle,
                                   int* new_private_key_handle) {
  CHECK(new_public_key_handle);
  CHECK(new_private_key_handle);

  // Create public/private key objects
  std::unique_ptr<Object> public_object(factory_->CreateObject());
  CHECK(public_object.get());
  std::unique_ptr<Object> private_object(factory_->CreateObject());
  CHECK(private_object.get());

  // copy attributes
  // TODO(menghuan): don't copy the attribute that doesn't support
  CK_RV result =
      public_object->SetAttributes(public_attributes, num_public_attributes);
  if (result != CKR_OK)
    return result;
  result =
      private_object->SetAttributes(private_attributes, num_private_attributes);
  if (result != CKR_OK)
    return result;

  // Get the object pool
  ObjectPool* public_pool =
      (public_object->IsTokenObject() ? token_object_pool_
                                      : session_object_pool_.get());
  ObjectPool* private_pool =
      (private_object->IsTokenObject() ? token_object_pool_
                                       : session_object_pool_.get());

  switch (mechanism) {
    case CKM_RSA_PKCS_KEY_PAIR_GEN:
      result = GenerateRSAKeyPair(public_object.get(), private_object.get());
      break;
    case CKM_EC_KEY_PAIR_GEN:
      result = GenerateECCKeyPair(public_object.get(), private_object.get());
      break;
    default:
      LOG(ERROR) << __func__ << ": Mechanism not supported: " << hex
                 << mechanism;
      return CKR_MECHANISM_INVALID;
  }
  if (result != CKR_OK) {
    return result;
  }

  // Set the general attributes for public / private key
  public_object->SetAttributeInt(CKA_CLASS, CKO_PUBLIC_KEY);
  private_object->SetAttributeInt(CKA_CLASS, CKO_PRIVATE_KEY);

  // The CKA_KEY_GEN_MECHANISM attribute identifies the key generation mechanism
  // used to generate the key material. It contains a valid value only if the
  // CKA_LOCAL attribute has the value CK_TRUE. If CKA_LOCAL has the value
  // CK_FALSE, the value of the attribute is CK_UNAVAILABLE_INFORMATION.
  public_object->SetAttributeBool(CKA_LOCAL, true);
  private_object->SetAttributeBool(CKA_LOCAL, true);
  public_object->SetAttributeInt(CKA_KEY_GEN_MECHANISM, mechanism);
  private_object->SetAttributeInt(CKA_KEY_GEN_MECHANISM, mechanism);

  // Finalize the objects
  result = public_object->FinalizeNewObject();
  if (result != CKR_OK) {
    LOG(ERROR) << __func__ << ": Fail to finalize public object.";
    return result;
  }
  result = private_object->FinalizeNewObject();
  if (result != CKR_OK) {
    LOG(ERROR) << __func__ << ": Fail to finalize private object.";
    return result;
  }
  auto pool_res = public_pool->Insert(public_object.get());
  if (!IsSuccess(pool_res)) {
    LOG(ERROR) << __func__ << ": Fail to insert public object to public pool.";
    return ResultToRV(pool_res, CKR_FUNCTION_FAILED);
  }
  pool_res = private_pool->Insert(private_object.get());
  if (!IsSuccess(pool_res)) {
    LOG(ERROR) << __func__
               << ": Fail to insert private object to private pool.";
    // Remove inserted public object.
    // The object will be destroy in Delete(), we should release uniptr.
    public_pool->Delete(public_object.release());
    return ResultToRV(pool_res, CKR_FUNCTION_FAILED);
  }
  *new_public_key_handle = public_object.release()->handle();
  *new_private_key_handle = private_object.release()->handle();
  return CKR_OK;
}

CK_RV SessionImpl::SeedRandom(const string& seed) {
  RAND_seed(seed.data(), seed.length());
  return CKR_OK;
}

CK_RV SessionImpl::GenerateRandom(int num_bytes, string* random_data) {
  *random_data = GenerateRandomSoftware(num_bytes);
  return CKR_OK;
}

bool SessionImpl::IsPrivateLoaded() {
  return token_object_pool_->IsPrivateLoaded();
}

CK_RV SessionImpl::CipherInit(bool is_encrypt,
                              CK_MECHANISM_TYPE mechanism,
                              const string& mechanism_parameter,
                              const Object* key) {
  string key_material = key->GetAttributeString(CKA_VALUE);
  const EVP_CIPHER* cipher_type =
      GetOpenSSLCipher(mechanism, key_material.size());
  if (!cipher_type) {
    LOG(ERROR) << "Mechanism not supported: 0x" << hex << mechanism;
    return CKR_MECHANISM_INVALID;
  }
  // The mechanism parameter is the IV for cipher modes which require an IV,
  // otherwise it is expected to be empty.
  if (static_cast<int>(mechanism_parameter.size()) !=
      EVP_CIPHER_iv_length(cipher_type)) {
    LOG(ERROR) << "IV length is invalid: " << mechanism_parameter.size();
    return CKR_MECHANISM_PARAM_INVALID;
  }
  if (static_cast<int>(key_material.size()) !=
      EVP_CIPHER_key_length(cipher_type)) {
    LOG(ERROR) << "Key size not supported: " << key_material.size();
    return CKR_KEY_SIZE_RANGE;
  }

  OperationType operation = is_encrypt ? kEncrypt : kDecrypt;
  OperationContext* context = &operation_context_[operation];
  context->cipher_context_.reset(EVP_CIPHER_CTX_new());
  if (!context->cipher_context_) {
    LOG(ERROR) << "Failed to allocate EVP_CIPHER context";
    return CKR_FUNCTION_FAILED;
  }

  if (!EVP_CipherInit_ex(context->cipher_context_.get(), cipher_type, nullptr,
                         ConvertStringToByteBuffer(key_material.c_str()),
                         ConvertStringToByteBuffer(mechanism_parameter.c_str()),
                         is_encrypt)) {
    LOG(ERROR) << "EVP_CipherInit failed: " << GetOpenSSLError();
    return CKR_FUNCTION_FAILED;
  }
  EVP_CIPHER_CTX_set_padding(context->cipher_context_.get(),
                             IsPaddingEnabled(mechanism));
  context->is_valid_ = true;
  context->is_cipher_ = true;
  return CKR_OK;
}

CK_RV SessionImpl::CipherUpdate(OperationContext* context,
                                const string& data_in,
                                int* required_out_length,
                                string* data_out) {
  CHECK(required_out_length);
  CHECK(data_out);
  // If we have output already waiting, we don't need to process input.
  if (context->data_.empty()) {
    int in_length = data_in.length();
    int out_length = in_length + kMaxCipherBlockBytes;
    context->data_.resize(out_length);
    if (!EVP_CipherUpdate(
            context->cipher_context_.get(),
            ConvertStringToByteBuffer(context->data_.c_str()), &out_length,
            ConvertStringToByteBuffer(data_in.c_str()), in_length)) {
      context->is_valid_ = false;
      LOG(ERROR) << "EVP_CipherUpdate failed: " << GetOpenSSLError();
      return CKR_FUNCTION_FAILED;
    }
    context->data_.resize(out_length);
  }
  return GetOperationOutput(context, required_out_length, data_out);
}

CK_RV SessionImpl::CipherFinal(OperationContext* context) {
  if (context->data_.empty()) {
    int out_length = kMaxCipherBlockBytes * 2;
    context->data_.resize(out_length);
    if (!EVP_CipherFinal_ex(context->cipher_context_.get(),
                            ConvertStringToByteBuffer(context->data_.c_str()),
                            &out_length)) {
      LOG(ERROR) << "EVP_CipherFinal failed: " << GetOpenSSLError();
      return CKR_FUNCTION_FAILED;
    }
    context->data_.resize(out_length);
  }
  return CKR_OK;
}

CK_RV SessionImpl::CreateObjectInternal(const CK_ATTRIBUTE_PTR attributes,
                                        int num_attributes,
                                        const Object* copy_from_object,
                                        int* new_object_handle) {
  CHECK(new_object_handle);
  CHECK(attributes || num_attributes == 0);
  std::unique_ptr<Object> object(factory_->CreateObject());
  CHECK(object.get());
  CK_RV result = CKR_OK;
  if (copy_from_object) {
    result = object->Copy(copy_from_object);
    if (result != CKR_OK)
      return result;
  }
  result = object->SetAttributes(attributes, num_attributes);
  if (result != CKR_OK)
    return result;

  bool is_token_object = object->IsTokenObject();
  if (is_token_object) {
    result = WrapPrivateKey(object.get());
    if (result != CKR_OK)
      return result;
  }

  // Finalize the object, whether it's new or copied.
  if (copy_from_object) {
    result = object->FinalizeCopyObject();
  } else {
    result = object->FinalizeNewObject();
  }
  if (result != CKR_OK) {
    return result;
  }

  ObjectPool* pool =
      is_token_object ? token_object_pool_ : session_object_pool_.get();
  auto pool_res = pool->Insert(object.get());
  if (!IsSuccess(pool_res))
    return ResultToRV(pool_res, CKR_GENERAL_ERROR);
  *new_object_handle = object.release()->handle();
  return CKR_OK;
}

bool SessionImpl::GenerateDESKey(string* key_material) {
  static const int kDESKeySizeBytes = 8;
  bool done = false;
  while (!done) {
    string tmp = GenerateRandomSoftware(kDESKeySizeBytes);
    DES_cblock des;
    memcpy(&des, tmp.data(), kDESKeySizeBytes);
    if (!DES_is_weak_key(&des)) {
      DES_set_odd_parity(&des);
      *key_material = string(reinterpret_cast<char*>(des), kDESKeySizeBytes);
      done = true;
    }
  }
  return true;
}

CK_RV SessionImpl::GenerateRSAKeyPair(Object* public_object,
                                      Object* private_object) {
  // CKA_PUBLIC_EXPONENT is optional. The default is 65537 (0x10001).
  string public_exponent("\x01\x00\x01", 3);
  if (public_object->IsAttributePresent(CKA_PUBLIC_EXPONENT))
    public_exponent = public_object->GetAttributeString(CKA_PUBLIC_EXPONENT);
  public_object->SetAttributeString(CKA_PUBLIC_EXPONENT, public_exponent);
  private_object->SetAttributeString(CKA_PUBLIC_EXPONENT, public_exponent);

  // CKA_MODULUS_BITS is requried
  if (!public_object->IsAttributePresent(CKA_MODULUS_BITS))
    return CKR_TEMPLATE_INCOMPLETE;
  CK_ULONG modulus_bits = public_object->GetAttributeInt(CKA_MODULUS_BITS, 0);
  if (modulus_bits < kMinRSAKeyBits || modulus_bits > kMaxRSAKeyBits)
    return CKR_KEY_SIZE_RANGE;

  // Set CKA_KEY_TYPE
  public_object->SetAttributeInt(CKA_KEY_TYPE, CKK_RSA);
  private_object->SetAttributeInt(CKA_KEY_TYPE, CKK_RSA);

  // Check if we are able to back this key with the TPM.
  if (tpm_utility_->IsTPMAvailable() && private_object->IsTokenObject() &&
      modulus_bits >= tpm_utility_->MinRSAKeyBits() &&
      modulus_bits <= tpm_utility_->MaxRSAKeyBits() &&
      !private_object->GetAttributeBool(kForceSoftwareAttribute, false)) {
    // Use TPM to generate RSA key
    if (!GenerateRSAKeyPairTPM(modulus_bits, public_exponent, public_object,
                               private_object))
      return CKR_FUNCTION_FAILED;
  } else {
    // Use software to generate RSA key
    if (!GenerateRSAKeyPairSoftware(modulus_bits, public_exponent,
                                    public_object, private_object))
      return CKR_FUNCTION_FAILED;
  }
  return CKR_OK;
}

bool SessionImpl::GenerateRSAKeyPairSoftware(int modulus_bits,
                                             const string& public_exponent,
                                             Object* public_object,
                                             Object* private_object) {
  if (public_exponent.length() > sizeof(uint32_t) || public_exponent.empty())
    return false;
  crypto::ScopedRSA key(RSA_new());
  crypto::ScopedBIGNUM e(BN_new());
  if (!key || !e) {
    LOG(ERROR) << "Failed to allocate RSA or BIGNUM for exponent.";
    return false;
  }
  if (!ConvertToBIGNUM(public_exponent, e.get())) {
    LOG(ERROR) << "Failed to convert exponent to BIGNUM.";
    return false;
  }
  if (!RSA_generate_key_ex(key.get(), modulus_bits, e.get(), nullptr)) {
    LOG(ERROR) << "Failed to generate key pair.";
    return false;
  }

  const BIGNUM* key_n;
  const BIGNUM* key_d;
  const BIGNUM* key_p;
  const BIGNUM* key_q;
  const BIGNUM* key_dmp1;
  const BIGNUM* key_dmq1;
  const BIGNUM* key_iqmp;
  RSA_get0_key(key.get(), &key_n, nullptr, &key_d);
  RSA_get0_factors(key.get(), &key_p, &key_q);
  RSA_get0_crt_params(key.get(), &key_dmp1, &key_dmq1, &key_iqmp);
  string n = ConvertFromBIGNUM(key_n);
  string d = ConvertFromBIGNUM(key_d);
  string p = ConvertFromBIGNUM(key_p);
  string q = ConvertFromBIGNUM(key_q);
  string dmp1 = ConvertFromBIGNUM(key_dmp1);
  string dmq1 = ConvertFromBIGNUM(key_dmq1);
  string iqmp = ConvertFromBIGNUM(key_iqmp);
  public_object->SetAttributeString(CKA_MODULUS, n);
  private_object->SetAttributeString(CKA_MODULUS, n);
  private_object->SetAttributeString(CKA_PRIVATE_EXPONENT, d);
  private_object->SetAttributeString(CKA_PRIME_1, p);
  private_object->SetAttributeString(CKA_PRIME_2, q);
  private_object->SetAttributeString(CKA_EXPONENT_1, dmp1);
  private_object->SetAttributeString(CKA_EXPONENT_2, dmq1);
  private_object->SetAttributeString(CKA_COEFFICIENT, iqmp);
  return true;
}

bool SessionImpl::GenerateRSAKeyPairTPM(int modulus_bits,
                                        const string& public_exponent,
                                        Object* public_object,
                                        Object* private_object) {
  string auth_data = GenerateRandomSoftware(kDefaultAuthDataBytes);
  string key_blob;
  int tpm_key_handle;
  if (!tpm_utility_->GenerateRSAKey(
          slot_id_, modulus_bits, public_exponent,
          SecureBlob(auth_data.begin(), auth_data.end()), &key_blob,
          &tpm_key_handle))
    return false;

  // Get public key information from TPM
  string modulus;
  string exponent;
  if (!tpm_utility_->GetRSAPublicKey(tpm_key_handle, &exponent, &modulus))
    return false;

  public_object->SetAttributeString(CKA_MODULUS, modulus);
  private_object->SetAttributeString(CKA_MODULUS, modulus);
  private_object->SetAttributeString(kAuthDataAttribute, auth_data);
  private_object->SetAttributeString(kKeyBlobAttribute, key_blob);
  return true;
}

CK_RV SessionImpl::GenerateECCKeyPair(Object* public_object,
                                      Object* private_object) {
  // CKA_EC_PARAMS is requried
  if (!public_object->IsAttributePresent(CKA_EC_PARAMS))
    return CKR_TEMPLATE_INCOMPLETE;

  crypto::ScopedEC_KEY key = CreateECCKeyFromEC_PARAMS(
      public_object->GetAttributeString(CKA_EC_PARAMS));
  if (key == nullptr) {
    LOG(ERROR) << __func__ << ": CKA_EC_PARAMS parse fail.";
    return CKR_DOMAIN_PARAMS_INVALID;
  }

  // Set CKA_KEY_TYPE
  public_object->SetAttributeInt(CKA_KEY_TYPE, CKK_EC);
  private_object->SetAttributeInt(CKA_KEY_TYPE, CKK_EC);

  // reset CKA_EC_PARAMS for both key
  const string ec_params = GetECParametersAsString(key.get());
  if (ec_params.empty()) {
    LOG(ERROR) << __func__ << ": Fail to dump CKA_EC_PARAMS";
    return CKR_FUNCTION_FAILED;
  }
  public_object->SetAttributeString(CKA_EC_PARAMS, ec_params);
  private_object->SetAttributeString(CKA_EC_PARAMS, ec_params);

  // Get NID from key
  const EC_GROUP* group = EC_KEY_get0_group(key.get());
  if (group == nullptr)
    return CKR_FUNCTION_FAILED;
  int curve_nid = EC_GROUP_get_curve_name(group);

  bool is_using_tpm =
      tpm_utility_->IsTPMAvailable() && private_object->IsTokenObject() &&
      tpm_utility_->IsECCurveSupported(curve_nid) &&
      !private_object->GetAttributeBool(kForceSoftwareAttribute, false);

  bool result = false;
  if (is_using_tpm) {
    result =
        GenerateECCKeyPairTPM(key, curve_nid, public_object, private_object);
  } else {
    result = GenerateECCKeyPairSoftware(key, public_object, private_object);
  }
  return result ? CKR_OK : CKR_FUNCTION_FAILED;
}

bool SessionImpl::GenerateECCKeyPairTPM(const crypto::ScopedEC_KEY& key,
                                        int curve_nid,
                                        Object* public_object,
                                        Object* private_object) {
  string auth_data = GenerateRandomSoftware(kDefaultAuthDataBytes);
  string key_blob;
  int tpm_key_handle;
  if (!tpm_utility_->GenerateECCKey(slot_id_, curve_nid, SecureBlob(auth_data),
                                    &key_blob, &tpm_key_handle)) {
    LOG(ERROR) << __func__ << ": Fail to generate ECC key in TPM.";
    return false;
  }

  // Get public key information from TPM
  string ec_point;
  if (!tpm_utility_->GetECCPublicKey(tpm_key_handle, &ec_point)) {
    LOG(ERROR) << __func__ << ": Fail to get ECC public key from TPM.";
    return false;
  }

  // Set CKA_EC_POINT for public key
  public_object->SetAttributeString(CKA_EC_POINT, ec_point);

  // Set TPM information for private key
  private_object->SetAttributeString(kAuthDataAttribute, auth_data);
  private_object->SetAttributeString(kKeyBlobAttribute, key_blob);

  return true;
}

bool SessionImpl::GenerateECCKeyPairSoftware(const crypto::ScopedEC_KEY& key,
                                             Object* public_object,
                                             Object* private_object) {
  if (!EC_KEY_generate_key(key.get())) {
    LOG(ERROR) << __func__
               << ": Software generate key fail. Perhaps it is not supported "
                  "by OpenSSL.";
    return false;
  }

  // Set CKA_EC_POINT for public key
  const string ec_point = GetECPointAsString(key.get());
  if (ec_point.empty()) {
    LOG(ERROR) << __func__ << ": Fail to dump EC_POINT.";
    return false;
  }
  public_object->SetAttributeString(CKA_EC_POINT, ec_point);

  // Set CKA_VALUE for private key
  const BIGNUM* privkey = EC_KEY_get0_private_key(key.get());
  private_object->SetAttributeString(CKA_VALUE, ConvertFromBIGNUM(privkey));
  return true;
}

string SessionImpl::GenerateRandomSoftware(int num_bytes) {
  string random(num_bytes, 0);
  RAND_bytes(ConvertStringToByteBuffer(random.data()), num_bytes);
  return random;
}

CK_RV SessionImpl::GetOperationOutput(OperationContext* context,
                                      int* required_out_length,
                                      string* data_out) {
  int out_length = context->data_.length();
  int max_length = *required_out_length;
  *required_out_length = out_length;
  if (max_length < out_length)
    return CKR_BUFFER_TOO_SMALL;
  *data_out = context->data_;
  context->data_.clear();
  return CKR_OK;
}

CK_ATTRIBUTE_TYPE SessionImpl::GetRequiredKeyUsage(OperationType operation) {
  switch (operation) {
    case kEncrypt:
      return CKA_ENCRYPT;
    case kDecrypt:
      return CKA_DECRYPT;
    case kSign:
      return CKA_SIGN;
    case kVerify:
      return CKA_VERIFY;
    default:
      break;
  }
  return 0;
}

bool SessionImpl::GetTPMKeyHandle(const Object* key, int* key_handle) {
  map<const Object*, int>::iterator it = object_tpm_handle_map_.find(key);
  if (it == object_tpm_handle_map_.end()) {
    // Only private keys are loaded into the TPM. All public key operations do
    // not use the TPM (and use OpenSSL instead).
    if (key->GetObjectClass() == CKO_PRIVATE_KEY) {
      string auth_data = key->GetAttributeString(kAuthDataAttribute);
      if (key->GetAttributeBool(kLegacyAttribute, false)) {
        // This is a legacy key and it needs to be loaded with the legacy root
        // key.
        if (!LoadLegacyRootKeys())
          return false;
        bool is_private = key->GetAttributeBool(CKA_PRIVATE, true);
        int root_key_handle = is_private ? private_root_key_ : public_root_key_;
        if (!tpm_utility_->LoadKeyWithParent(
                slot_id_, key->GetAttributeString(kKeyBlobAttribute),
                SecureBlob(auth_data.begin(), auth_data.end()), root_key_handle,
                key_handle))
          return false;
      } else {
        if (!tpm_utility_->LoadKey(
                slot_id_, key->GetAttributeString(kKeyBlobAttribute),
                SecureBlob(auth_data.begin(), auth_data.end()), key_handle))
          return false;
      }
    } else {
      LOG(ERROR) << "Invalid object class for loading into TPM.";
      return false;
    }
    object_tpm_handle_map_[key] = *key_handle;
  } else {
    *key_handle = it->second;
  }
  return true;
}

bool SessionImpl::LoadLegacyRootKeys() {
  if (is_legacy_loaded_)
    return true;

  // Load the legacy root keys. See http://trousers.sourceforge.net/pkcs11.html
  // for details on where these come from.
  string private_blob;
  if (!token_object_pool_->GetInternalBlob(kLegacyPrivateRootKey,
                                           &private_blob)) {
    LOG(ERROR) << "Failed to read legacy private root key blob.";
    return false;
  }
  if (!tpm_utility_->LoadKey(slot_id_, private_blob, SecureBlob(),
                             &private_root_key_)) {
    LOG(ERROR) << "Failed to load legacy private root key.";
    return false;
  }
  string public_blob;
  if (!token_object_pool_->GetInternalBlob(kLegacyPublicRootKey,
                                           &public_blob)) {
    LOG(ERROR) << "Failed to read legacy public root key blob.";
    return false;
  }
  if (!tpm_utility_->LoadKey(slot_id_, public_blob, SecureBlob(),
                             &public_root_key_)) {
    LOG(ERROR) << "Failed to load legacy public root key.";
    return false;
  }
  is_legacy_loaded_ = true;
  return true;
}

bool SessionImpl::RSADecrypt(OperationContext* context) {
  if (context->key_->IsTokenObject() &&
      context->key_->IsAttributePresent(kKeyBlobAttribute)) {
    int tpm_key_handle = 0;
    if (!GetTPMKeyHandle(context->key_, &tpm_key_handle))
      return false;
    string encrypted_data = context->data_;
    context->data_.clear();
    if (!tpm_utility_->Unbind(tpm_key_handle, encrypted_data, &context->data_))
      return false;
  } else {
    crypto::ScopedRSA rsa = CreateRSAKeyFromObject(context->key_);
    if (!rsa) {
      LOG(ERROR) << "Failed to create RSA key for decryption.";
      return false;
    }
    uint8_t buffer[kMaxRSAOutputBytes];
    CHECK(RSA_size(rsa.get()) <= kMaxRSAOutputBytes);
    int length = RSA_private_decrypt(
        context->data_.length(),
        ConvertStringToByteBuffer(context->data_.data()), buffer, rsa.get(),
        RSA_PKCS1_PADDING);  // Strips PKCS #1 type 2 padding.
    if (length == -1) {
      LOG(ERROR) << "RSA_private_decrypt failed: " << GetOpenSSLError();
      return false;
    }
    context->data_ = ConvertByteBufferToString(buffer, length);
  }
  return true;
}

bool SessionImpl::RSAEncrypt(OperationContext* context) {
  crypto::ScopedRSA rsa = CreateRSAKeyFromObject(context->key_);
  if (!rsa) {
    LOG(ERROR) << "Failed to create RSA key for encryption.";
    return false;
  }
  uint8_t buffer[kMaxRSAOutputBytes];
  CHECK(RSA_size(rsa.get()) <= kMaxRSAOutputBytes);
  int length = RSA_public_encrypt(
      context->data_.length(), ConvertStringToByteBuffer(context->data_.data()),
      buffer, rsa.get(),
      RSA_PKCS1_PADDING);  // Adds PKCS #1 type 2 padding.
  if (length == -1) {
    LOG(ERROR) << "RSA_public_encrypt failed: " << GetOpenSSLError();
    return false;
  }
  context->data_ = ConvertByteBufferToString(buffer, length);
  return true;
}

bool SessionImpl::RSASign(OperationContext* context) {
  string signature;
  if (context->key_->IsTokenObject() &&
      context->key_->IsAttributePresent(kKeyBlobAttribute)) {
    int tpm_key_handle = 0;
    if (!GetTPMKeyHandle(context->key_, &tpm_key_handle))
      return false;
    if (!tpm_utility_->Sign(tpm_key_handle, context->mechanism_,
                            context->parameter_, context->data_, &signature))
      return false;
  } else {
    crypto::ScopedRSA rsa = CreateRSAKeyFromObject(context->key_);
    if (!rsa) {
      LOG(ERROR) << "Failed to create RSA key for signing.";
      return false;
    }
    std::unique_ptr<RSASignerVerifier> signer =
        RSASignerVerifier::GetForMechanism(context->mechanism_);
    if (!signer)
      return false;

    return signer->Sign(std::move(rsa), context);
  }
  context->data_ = signature;
  return true;
}

CK_RV SessionImpl::RSAVerify(OperationContext* context,
                             const string& digest,
                             const string& signature) {
  if (context->key_->GetAttributeString(CKA_MODULUS).length() !=
      signature.length())
    return CKR_SIGNATURE_LEN_RANGE;
  crypto::ScopedRSA rsa = CreateRSAKeyFromObject(context->key_);
  if (!rsa) {
    LOG(ERROR) << "Failed to create RSA key for verification.";
    return CKR_KEY_HANDLE_INVALID;
  }
  std::unique_ptr<RSASignerVerifier> verifier =
      RSASignerVerifier::GetForMechanism(context->mechanism_);
  if (!verifier)
    return CKR_ARGUMENTS_BAD;

  return verifier->Verify(std::move(rsa), context, digest, signature);
}

bool SessionImpl::ECCSign(OperationContext* context) {
  string signature;
  if (context->key_->IsTokenObject() &&
      context->key_->IsAttributePresent(kKeyBlobAttribute)) {
    if (!ECCSignTPM(context->data_, context->mechanism_, context->key_,
                    &signature))
      return false;
  } else {
    if (!ECCSignSoftware(context->data_, context->key_, &signature))
      return false;
  }
  context->data_ = signature;
  return true;
}

bool SessionImpl::ECCSignTPM(const std::string& input,
                             CK_MECHANISM_TYPE signing_mechanism,
                             const Object* key_object,
                             std::string* signature) {
  if (!(signing_mechanism == CKM_ECDSA ||
        signing_mechanism == CKM_ECDSA_SHA1)) {
    LOG(ERROR)
        << "Failed to sign with ECCSignTPM because mechanism is unsupported: "
        << signing_mechanism;
    return false;
  }

  int tpm_key_handle = 0;
  if (!GetTPMKeyHandle(key_object, &tpm_key_handle))
    return false;
  // Note that ECC doesn't require any signing parameters.
  if (!tpm_utility_->Sign(tpm_key_handle, signing_mechanism, "", input,
                          signature))
    return false;
  return true;
}

bool SessionImpl::ECCSignSoftware(const std::string& input,
                                  const Object* key_object,
                                  std::string* signature) {
  crypto::ScopedEC_KEY key = CreateECCPrivateKeyFromObject(key_object);
  if (key == nullptr) {
    LOG(ERROR) << __func__ << ": Load key failed.";
    return false;
  }

  // We don't use ECDSA_sign here since the output format of PKCS#11 is
  // different from OpenSSL's.
  crypto::ScopedECDSA_SIG sig(ECDSA_do_sign(
      ConvertStringToByteBuffer(input.data()), input.size(), key.get()));
  if (sig == nullptr) {
    LOG(ERROR) << __func__ << ": ECDSA failed: " << GetOpenSSLError();
    return false;
  }

  // The resulting signature is always of length |2 * nLen|, where nLen is the
  // maximum size of the EC group. The first half of the signature is r and the
  // second half is s.
  int max_length = GetGroupOrderLengthFromEcKey(key);
  if (max_length <= 0) {
    LOG(ERROR) << __func__ << ": Get the group order fail.";
    return false;
  }
  const BIGNUM* r;
  const BIGNUM* s;
  ECDSA_SIG_get0(sig.get(), &r, &s);
  *signature =
      ConvertFromBIGNUM(r, max_length) + ConvertFromBIGNUM(s, max_length);

  return true;
}

CK_RV SessionImpl::ECCVerify(OperationContext* context,
                             const string& signed_data,
                             const string& signature) {
  // Software verify with ECC key
  crypto::ScopedEC_KEY key = CreateECCPublicKeyFromObject(context->key_);
  if (key == nullptr) {
    LOG(ERROR) << __func__ << ": Load key failed.";
    return CKR_FUNCTION_FAILED;
  }

  // Parse signature back to ECDSA_SIG
  int sign_size = signature.size();
  if (sign_size % 2 != 0) {
    return CKR_SIGNATURE_LEN_RANGE;
  }
  crypto::ScopedECDSA_SIG sig(ECDSA_SIG_new());
  crypto::ScopedBIGNUM r(BN_new()), s(BN_new());
  if (!sig || !r || !s) {
    LOG(ERROR) << "Failed to allocate ECDSA_SIG or BIGNUM.";
    return CKR_FUNCTION_FAILED;
  }
  if (!ConvertToBIGNUM(signature.substr(0, sign_size / 2), r.get()) ||
      !ConvertToBIGNUM(signature.substr(sign_size / 2), s.get())) {
    LOG(ERROR) << "Failed to convert BIGNUM for ECDSA_SIG.";
    return CKR_FUNCTION_FAILED;
  }
  if (!ECDSA_SIG_set0(sig.get(), r.release(), s.release())) {
    LOG(ERROR) << "Failed to set ECDSA_SIG parameters.";
    return CKR_FUNCTION_FAILED;
  }

  // 1 for a valid signature, 0 for an invalid signature and -1 on error.
  int result = ECDSA_do_verify(ConvertStringToByteBuffer(signed_data.data()),
                               signed_data.size(), sig.get(), key.get());
  if (result < 0) {
    LOG(ERROR) << __func__ << ": ECDSA verify failed: " << GetOpenSSLError();
    return CKR_FUNCTION_FAILED;
  }
  return result ? CKR_OK : CKR_SIGNATURE_INVALID;
}

CK_RV SessionImpl::WrapRSAPrivateKey(Object* object) {
  if (!object->IsAttributePresent(CKA_PUBLIC_EXPONENT) ||
      !object->IsAttributePresent(CKA_MODULUS) ||
      !(object->IsAttributePresent(CKA_PRIME_1) ||
        object->IsAttributePresent(CKA_PRIME_2)))
    return CKR_TEMPLATE_INCOMPLETE;

  // If TPM doesn't support, fall back to software.
  int key_size_bits = object->GetAttributeString(CKA_MODULUS).length() * 8;
  if (key_size_bits > tpm_utility_->MaxRSAKeyBits() ||
      key_size_bits < tpm_utility_->MinRSAKeyBits()) {
    LOG(WARNING) << "WARNING: " << key_size_bits
                 << "-bit private key cannot be wrapped by the TPM.";
    return CKR_OK;
  }

  // Get prime p or q
  string prime = object->IsAttributePresent(CKA_PRIME_1)
                     ? object->GetAttributeString(CKA_PRIME_1)
                     : object->GetAttributeString(CKA_PRIME_2);

  string auth_data = GenerateRandomSoftware(kDefaultAuthDataBytes);
  string key_blob;
  int tpm_key_handle = 0;
  // TODO(menghuan): Use Software key but report and have an auto-rewrapping
  // when WrapRSAKey() fail
  if (!tpm_utility_->WrapRSAKey(slot_id_,
                                object->GetAttributeString(CKA_PUBLIC_EXPONENT),
                                object->GetAttributeString(CKA_MODULUS), prime,
                                SecureBlob(auth_data.begin(), auth_data.end()),
                                &key_blob, &tpm_key_handle))
    return CKR_FUNCTION_FAILED;
  object->SetAttributeString(kAuthDataAttribute, auth_data);
  object->SetAttributeString(kKeyBlobAttribute, key_blob);
  object->RemoveAttribute(CKA_PRIVATE_EXPONENT);
  object->RemoveAttribute(CKA_PRIME_1);
  object->RemoveAttribute(CKA_PRIME_2);
  object->RemoveAttribute(CKA_EXPONENT_1);
  object->RemoveAttribute(CKA_EXPONENT_2);
  object->RemoveAttribute(CKA_COEFFICIENT);
  return CKR_OK;
}

CK_RV SessionImpl::WrapECCPrivateKey(Object* object) {
  if (!object->IsAttributePresent(CKA_EC_PARAMS) ||
      !object->IsAttributePresent(CKA_VALUE)) {
    return CKR_TEMPLATE_INCOMPLETE;
  }

  // Get OpenSSL NID
  crypto::ScopedEC_Key key = CreateECCPrivateKeyFromObject(object);
  const EC_GROUP* group = EC_KEY_get0_group(key.get());
  if (group == nullptr) {
    return CKR_FUNCTION_FAILED;
  }
  int curve_nid = EC_GROUP_get_curve_name(group);

  // If TPM doesn't support, fall back to software.
  if (!tpm_utility_->IsECCurveSupported(curve_nid)) {
    return CKR_OK;
  }

  // Get public key value
  crypto::ScopedBIGNUM x(BN_new()), y(BN_new());
  if (!x || !y) {
    LOG(ERROR) << "Failed to allocate BIGNUM.";
    return CKR_FUNCTION_FAILED;
  }
  const EC_POINT* ec_point = EC_KEY_get0_public_key(key.get());
  if (ec_point == nullptr) {
    return CKR_FUNCTION_FAILED;
  }
  if (!EC_POINT_get_affine_coordinates_GF2m(group, ec_point, x.get(), y.get(),
                                            nullptr)) {
    return CKR_FUNCTION_FAILED;
  }

  string auth_data = GenerateRandomSoftware(kDefaultAuthDataBytes);
  string key_blob;
  int tpm_key_handle = 0;
  if (!tpm_utility_->WrapECCKey(slot_id_, curve_nid, ConvertFromBIGNUM(x.get()),
                                ConvertFromBIGNUM(y.get()),
                                object->GetAttributeString(CKA_VALUE),
                                SecureBlob(auth_data.begin(), auth_data.end()),
                                &key_blob, &tpm_key_handle)) {
    return CKR_FUNCTION_FAILED;
  }
  object->SetAttributeString(kAuthDataAttribute, auth_data);
  object->SetAttributeString(kKeyBlobAttribute, key_blob);

  object->RemoveAttribute(CKA_VALUE);
  return CKR_OK;
}

CK_RV SessionImpl::WrapPrivateKey(Object* object) {
  if (!tpm_utility_->IsTPMAvailable() ||
      object->GetAttributeBool(kForceSoftwareAttribute, false) ||
      object->GetObjectClass() != CKO_PRIVATE_KEY ||
      object->IsAttributePresent(kKeyBlobAttribute)) {
    // This object does not need to be wrapped.
    return CKR_OK;
  }
  int key_type = object->GetAttributeInt(CKA_KEY_TYPE, 0);
  if (key_type == CKK_RSA) {
    return WrapRSAPrivateKey(object);
  } else if (key_type == CKK_EC) {
    return WrapECCPrivateKey(object);
  } else {
    // If TPM doesn't support, fall back to software.
    LOG(WARNING) << __func__ << ": Key type " << key_type
                 << " private key cannot be wrapped by the TPM.";
    return CKR_OK;
  }
}

SessionImpl::OperationContext::OperationContext()
    : is_valid_(false),
      is_cipher_(false),
      is_digest_(false),
      is_hmac_(false),
      is_finished_(false),
      key_(nullptr) {}

SessionImpl::OperationContext::~OperationContext() {
  Clear();
}

void SessionImpl::OperationContext::Clear() {
  cipher_context_.reset();
  digest_context_.reset();
  hmac_context_.reset();
  is_valid_ = false;
  is_cipher_ = false;
  is_digest_ = false;
  is_hmac_ = false;
  is_incremental_ = false;
  is_finished_ = false;
  key_ = nullptr;
  data_.clear();
  parameter_.clear();
}

}  // namespace chaps
