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

#include <base/logging.h>
#include <brillo/secure_blob.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 "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"

using brillo::SecureBlob;
using std::hex;
using std::map;
using std::set;
using std::string;
using std::vector;

namespace chaps {

static const int kDefaultAuthDataBytes = 20;
static const int kMaxCipherBlockBytes = 16;
static const int kMaxRSAOutputBytes = 2048;
static const int kMaxDigestOutputBytes = EVP_MAX_MD_SIZE;
static const int kMinRSAKeyBits = 512;
static const int kMaxRSAKeyBitsHW = 2048;  // Max supported by the TPM.
static const int kMaxRSAKeyBitsSW = kMaxRSAOutputBytes * 8;

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,
                                                        NULL,
                                                        NULL));
  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,
                              NULL,
                              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 = NULL;
  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 = NULL;
  if (!GetObject(object_handle, &object))
    return CKR_OBJECT_HANDLE_INVALID;
  CHECK(object);
  ObjectPool* pool = object->IsTokenObject() ? token_object_pool_
      : session_object_pool_.get();
  if (!pool->Delete(object))
    return CKR_GENERAL_ERROR;
  return CKR_OK;
}

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

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

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

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()) {
    if (!token_object_pool_->Find(search_template.get(), &objects))
      return CKR_GENERAL_ERROR;
  }
  if (!search_template->IsAttributePresent(CKA_TOKEN) ||
      !search_template->IsTokenObject()) {
    if (!session_object_pool_->Find(search_template.get(), &objects))
      return 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 (!IsValidMechanism(operation, mechanism)) {
    LOG(ERROR) << "Mechanism not supported: 0x" << hex << mechanism;
    return CKR_MECHANISM_INVALID;
  }
  if (operation != kDigest) {
    // Make sure the key is valid for the mechanism.
    CHECK(key);
    if (!IsValidKeyType(operation,
                        mechanism,
                        key->GetObjectClass(),
                        key->GetAttributeInt(CKA_KEY_TYPE, -1))) {
      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)) {
      int key_size = key->GetAttributeString(CKA_MODULUS).length() * 8;
      if (key_size < kMinRSAKeyBits || key_size > kMaxRSAKeyBitsSW) {
        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 {
    // It is valid for GetOpenSSLDigest to return NULL (e.g. CKM_RSA_PKCS).
    const EVP_MD* digest = GetOpenSSLDigest(mechanism);
    if (IsHMAC(mechanism)) {
      string key_material = key->GetAttributeString(CKA_VALUE);
      HMAC_CTX_init(&context->hmac_context_);
      HMAC_Init_ex(&context->hmac_context_,
                   key_material.data(),
                   key_material.length(),
                   digest,
                   NULL);
      context->is_hmac_ = true;
    } else if (digest) {
      EVP_DigestInit(&context->digest_context_, digest);
      context->is_digest_ = true;
    }
    if (IsRSA(mechanism))
      context->key_ = key;
    context->is_valid_ = true;
  }
  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_,
                     data_in.data(),
                     data_in.length());
  } else if (context->is_hmac_) {
    HMAC_Update(&context->hmac_context_,
                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(&context->digest_context_, 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_, buffer, &out_length);
      HMAC_CTX_cleanup(&context->hmac_context_);
      context->data_ = string(reinterpret_cast<char*>(buffer), out_length);
    }
    // Some RSA mechanisms use a digest so it's important to finish the digest
    // before finishing the RSA 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;
      }
    }
    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 two Verify mechanisms, HMAC and RSA.
  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;
  } else {
    // The data_out contents will be the computed digest.
    return RSAVerify(context, data_out, signature);
  }
  return CKR_OK;
}

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;
      int 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;
      int 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();
  if (!pool->Insert(object.get()))
    return 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);
  if (mechanism != CKM_RSA_PKCS_KEY_PAIR_GEN) {
    LOG(ERROR) << "GenerateKeyPair: Mechanism not supported: " << hex
               << mechanism;
    return CKR_MECHANISM_INVALID;
  }
  std::unique_ptr<Object> public_object(factory_->CreateObject());
  CHECK(public_object.get());
  std::unique_ptr<Object> private_object(factory_->CreateObject());
  CHECK(private_object.get());
  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;
  // 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);
  if (!public_object->IsAttributePresent(CKA_MODULUS_BITS))
    return CKR_TEMPLATE_INCOMPLETE;
  int modulus_bits = public_object->GetAttributeInt(CKA_MODULUS_BITS, 0);
  if (modulus_bits < kMinRSAKeyBits || modulus_bits > kMaxRSAKeyBitsSW)
    return CKR_KEY_SIZE_RANGE;
  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());
  // Check if we are able to back this key with the TPM.
  if (tpm_utility_->IsTPMAvailable() &&
      private_object->IsTokenObject() &&
      modulus_bits <= kMaxRSAKeyBitsHW) {
    string auth_data = GenerateRandomSoftware(kDefaultAuthDataBytes);
    string key_blob;
    int tpm_key_handle;
    if (!tpm_utility_->GenerateKey(slot_id_,
                                   modulus_bits,
                                   public_exponent,
                                   SecureBlob(auth_data.begin(),
                                              auth_data.end()),
                                   &key_blob,
                                   &tpm_key_handle))
      return CKR_FUNCTION_FAILED;
    string modulus;
    if (!tpm_utility_->GetPublicKey(tpm_key_handle, &public_exponent, &modulus))
      return CKR_FUNCTION_FAILED;
    public_object->SetAttributeString(CKA_MODULUS, modulus);
    private_object->SetAttributeString(CKA_MODULUS, modulus);
    private_object->SetAttributeString(kAuthDataAttribute, auth_data);
    private_object->SetAttributeString(kKeyBlobAttribute, key_blob);
  } else {
    if (!GenerateKeyPairSoftware(modulus_bits,
                                 public_exponent,
                                 public_object.get(),
                                 private_object.get()))
      return CKR_FUNCTION_FAILED;
  }
  public_object->SetAttributeInt(CKA_CLASS, CKO_PUBLIC_KEY);
  public_object->SetAttributeInt(CKA_KEY_TYPE, CKK_RSA);
  private_object->SetAttributeInt(CKA_CLASS, CKO_PRIVATE_KEY);
  private_object->SetAttributeInt(CKA_KEY_TYPE, CKK_RSA);
  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);
  result = public_object->FinalizeNewObject();
  if (result != CKR_OK)
    return result;
  result = private_object->FinalizeNewObject();
  if (result != CKR_OK)
    return result;
  if (!public_pool->Insert(public_object.get()))
    return CKR_FUNCTION_FAILED;
  if (!private_pool->Insert(private_object.get())) {
    public_pool->Delete(public_object.release());
    return 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;
}

void SessionImpl::WaitForPrivateObjects() {
  std::unique_ptr<Object> all_private(factory_->CreateObject());
  CHECK(all_private.get());
  all_private->SetAttributeBool(CKA_PRIVATE, true);
  vector<const Object*> found;
  token_object_pool_->Find(all_private.get(), &found);
}

bool SessionImpl::IsValidKeyType(OperationType operation,
                                 CK_MECHANISM_TYPE mechanism,
                                 CK_OBJECT_CLASS object_class,
                                 CK_KEY_TYPE key_type) {
  CK_KEY_TYPE expected_key_type = 0;
  CK_OBJECT_CLASS expected_class = 0;
  CK_OBJECT_CLASS asymmetric_class = CKO_PUBLIC_KEY;
  if (operation == kSign || operation == kDecrypt)
    asymmetric_class = CKO_PRIVATE_KEY;
  switch (mechanism) {
    case CKM_DES_ECB:
    case CKM_DES_CBC:
    case CKM_DES_CBC_PAD:
      expected_key_type = CKK_DES;
      expected_class = CKO_SECRET_KEY;
      break;
    case CKM_DES3_ECB:
    case CKM_DES3_CBC:
    case CKM_DES3_CBC_PAD:
      expected_key_type = CKK_DES3;
      expected_class = CKO_SECRET_KEY;
      break;
    case CKM_AES_ECB:
    case CKM_AES_CBC:
    case CKM_AES_CBC_PAD:
      expected_key_type = CKK_AES;
      expected_class = CKO_SECRET_KEY;
      break;
    case CKM_RSA_PKCS:
    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:
      expected_key_type = CKK_RSA;
      expected_class = asymmetric_class;
      break;
    case CKM_MD5_HMAC:
    case CKM_SHA_1_HMAC:
    case CKM_SHA256_HMAC:
    case CKM_SHA384_HMAC:
    case CKM_SHA512_HMAC:
      expected_key_type = CKK_GENERIC_SECRET;
      expected_class = CKO_SECRET_KEY;
      break;
    default:
      return false;
  }
  return (key_type == expected_key_type &&
          object_class == expected_class);
}

bool SessionImpl::IsValidMechanism(OperationType operation,
                                   CK_MECHANISM_TYPE mechanism) {
  if (operation == kEncrypt || operation == kDecrypt) {
    switch (mechanism) {
      case CKM_DES_ECB:
      case CKM_DES_CBC:
      case CKM_DES_CBC_PAD:
      case CKM_DES3_ECB:
      case CKM_DES3_CBC:
      case CKM_DES3_CBC_PAD:
      case CKM_AES_ECB:
      case CKM_AES_CBC:
      case CKM_AES_CBC_PAD:
      case CKM_RSA_PKCS:
        return true;
    }
  } else if (operation == kSign || operation == kVerify) {
    switch (mechanism) {
      case CKM_RSA_PKCS:
      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:
      case CKM_MD5_HMAC:
      case CKM_SHA_1_HMAC:
      case CKM_SHA256_HMAC:
      case CKM_SHA384_HMAC:
      case CKM_SHA512_HMAC:
        return true;
    }
  } else {
    switch (mechanism) {
      case CKM_MD5:
      case CKM_SHA_1:
      case CKM_SHA256:
      case CKM_SHA384:
      case CKM_SHA512:
        return true;
    }
  }
  return false;
}

CK_RV SessionImpl::CipherInit(bool is_encrypt,
                              CK_MECHANISM_TYPE mechanism,
                              const string& mechanism_parameter,
                              const Object* key) {
  OperationType operation = is_encrypt ? kEncrypt : kDecrypt;
  EVP_CIPHER_CTX* context =
      &operation_context_[operation].cipher_context_;
  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;
  }
  if (!EVP_CipherInit(context,
                      cipher_type,
                      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, IsPaddingEnabled(mechanism));
  operation_context_[operation].is_valid_ = true;
  operation_context_[operation].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_,
        ConvertStringToByteBuffer(context->data_.c_str()),
        &out_length,
        ConvertStringToByteBuffer(data_in.c_str()),
        in_length)) {
      EVP_CIPHER_CTX_cleanup(&context->cipher_context_);
      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(
        &context->cipher_context_,
        ConvertStringToByteBuffer(context->data_.c_str()),
        &out_length)) {
      LOG(ERROR) << "EVP_CipherFinal failed: " << GetOpenSSLError();
      EVP_CIPHER_CTX_cleanup(&context->cipher_context_);
      return CKR_FUNCTION_FAILED;
    }
    EVP_CIPHER_CTX_cleanup(&context->cipher_context_);
    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;
  if (!copy_from_object) {
    result = object->FinalizeNewObject();
    if (result != CKR_OK)
      return result;
  }
  ObjectPool* pool = token_object_pool_;
  if (object->IsTokenObject()) {
    result = WrapPrivateKey(object.get());
    if (result != CKR_OK)
      return result;
  } else {
    pool = session_object_pool_.get();
  }
  if (!pool->Insert(object.get()))
    return 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;
}

bool SessionImpl::GenerateKeyPairSoftware(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;
  BIGNUM* e = ConvertToBIGNUM(public_exponent);
  RSA* key = RSA_generate_key(modulus_bits, BN_get_word(e), NULL, NULL);
  CHECK(key);
  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);
  RSA_free(key);
  BN_free(e);
  return true;
}

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

string SessionImpl::GetDERDigestInfo(CK_MECHANISM_TYPE mechanism) {
  // These strings are the DER encodings of the DigestInfo values for the
  // supported digest algorithms.  See PKCS #1 v2.1: 9.2.
  static const string kMD5DigestInfo(
      "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04"
      "\x10",
      18);
  static const string kSHA1DigestInfo(
      "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14",
      15);
  static const string kSHA256DigestInfo(
      "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04"
      "\x20",
      19);
  static const string kSHA384DigestInfo(
      "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04"
      "\x30",
      19);
  static const string kSHA512DigestInfo(
      "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04"
      "\x40",
      19);
  const EVP_MD* md = GetOpenSSLDigest(mechanism);
  if (md == EVP_md5()) {
    return kMD5DigestInfo;
  } else if (md == EVP_sha1()) {
    return kSHA1DigestInfo;
  } else if (md == EVP_sha256()) {
    return kSHA256DigestInfo;
  } else if (md == EVP_sha384()) {
    return kSHA384DigestInfo;
  } else if (md == EVP_sha512()) {
    return kSHA512DigestInfo;
  }
  // This is valid in some cases (e.g. CKM_RSA_PKCS).
  return string();
}

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::IsHMAC(CK_MECHANISM_TYPE mechanism) {
  switch (mechanism) {
    case CKM_MD5_HMAC:
    case CKM_SHA_1_HMAC:
    case CKM_SHA256_HMAC:
    case CKM_SHA384_HMAC:
    case CKM_SHA512_HMAC:
      return true;
  }
  return false;
}

bool SessionImpl::IsPaddingEnabled(CK_MECHANISM_TYPE mechanism) {
  switch (mechanism) {
    case CKM_DES_CBC_PAD:
    case CKM_DES3_CBC_PAD:
    case CKM_AES_CBC_PAD:
      return true;
  }
  return false;
}

bool SessionImpl::IsRSA(CK_MECHANISM_TYPE mechanism) {
  switch (mechanism) {
    case CKM_RSA_PKCS:
    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;
  }
  return false;
}

// Both PKCS #11 and OpenSSL use big-endian binary representations of big
// integers.  To convert we can just use the OpenSSL converters.
string SessionImpl::ConvertFromBIGNUM(const BIGNUM* bignum) {
  string big_integer(BN_num_bytes(bignum), 0);
  BN_bn2bin(bignum, ConvertStringToByteBuffer(big_integer.data()));
  return big_integer;
}

BIGNUM* SessionImpl::ConvertToBIGNUM(const string& big_integer) {
  if (big_integer.empty())
    return NULL;
  BIGNUM* b = BN_bin2bn(ConvertStringToByteBuffer(big_integer.data()),
                        big_integer.length(),
                        NULL);
  CHECK(b);
  return b;
}

RSA* SessionImpl::CreateKeyFromObject(const Object* key_object) {
  RSA* rsa = RSA_new();
  CHECK(rsa);
  if (key_object->GetObjectClass() == CKO_PUBLIC_KEY) {
    string e = key_object->GetAttributeString(CKA_PUBLIC_EXPONENT);
    rsa->e = ConvertToBIGNUM(e);
    string n = key_object->GetAttributeString(CKA_MODULUS);
    rsa->n = ConvertToBIGNUM(n);
  } else {
    string n = key_object->GetAttributeString(CKA_MODULUS);
    rsa->n = ConvertToBIGNUM(n);
    string d = key_object->GetAttributeString(CKA_PRIVATE_EXPONENT);
    rsa->d = ConvertToBIGNUM(d);
    string p = key_object->GetAttributeString(CKA_PRIME_1);
    rsa->p = ConvertToBIGNUM(p);
    string q = key_object->GetAttributeString(CKA_PRIME_2);
    rsa->q = ConvertToBIGNUM(q);
    string dmp1 = key_object->GetAttributeString(CKA_EXPONENT_1);
    rsa->dmp1 = ConvertToBIGNUM(dmp1);
    string dmq1 = key_object->GetAttributeString(CKA_EXPONENT_2);
    rsa->dmq1 = ConvertToBIGNUM(dmq1);
    string iqmp = key_object->GetAttributeString(CKA_COEFFICIENT);
    rsa->iqmp = ConvertToBIGNUM(iqmp);
  }
  return rsa;
}

const EVP_CIPHER* SessionImpl::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 NULL;
}

const EVP_MD* SessionImpl::GetOpenSSLDigest(CK_MECHANISM_TYPE mechanism) {
  switch (mechanism) {
    case CKM_MD5:
    case CKM_MD5_HMAC:
    case CKM_MD5_RSA_PKCS:
      return EVP_md5();
    case CKM_SHA_1:
    case CKM_SHA_1_HMAC:
    case CKM_SHA1_RSA_PKCS:
      return EVP_sha1();
    case CKM_SHA256:
    case CKM_SHA256_HMAC:
    case CKM_SHA256_RSA_PKCS:
      return EVP_sha256();
    case CKM_SHA384:
    case CKM_SHA384_HMAC:
    case CKM_SHA384_RSA_PKCS:
      return EVP_sha384();
    case CKM_SHA512:
    case CKM_SHA512_HMAC:
    case CKM_SHA512_RSA_PKCS:
      return EVP_sha512();
  }
  return NULL;
}

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 {
    RSA* rsa = CreateKeyFromObject(context->key_);
    uint8_t buffer[kMaxRSAOutputBytes];
    CHECK(RSA_size(rsa) <= kMaxRSAOutputBytes);
    int length = RSA_private_decrypt(
        context->data_.length(),
        ConvertStringToByteBuffer(context->data_.data()),
        buffer,
        rsa,
        RSA_PKCS1_PADDING);  // Strips PKCS #1 type 2 padding.
    RSA_free(rsa);
    if (length == -1) {
      LOG(ERROR) << "RSA_private_decrypt failed: " << GetOpenSSLError();
      return false;
    }
    context->data_ = ConvertByteBufferToString(buffer, length);
  }
  return true;
}

bool SessionImpl::RSAEncrypt(OperationContext* context) {
  RSA* rsa = CreateKeyFromObject(context->key_);
  uint8_t buffer[kMaxRSAOutputBytes];
  CHECK(RSA_size(rsa) <= kMaxRSAOutputBytes);
  int length = RSA_public_encrypt(
      context->data_.length(),
      ConvertStringToByteBuffer(context->data_.data()),
      buffer,
      rsa,
      RSA_PKCS1_PADDING);  // Adds PKCS #1 type 2 padding.
  RSA_free(rsa);
  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 data_to_sign = GetDERDigestInfo(context->mechanism_) + context->data_;
  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, data_to_sign, &signature))
      return false;
  } else {
    RSA* rsa = CreateKeyFromObject(context->key_);
    CHECK(RSA_size(rsa) <= kMaxRSAOutputBytes);
    uint8_t buffer[kMaxRSAOutputBytes];
    int length = RSA_private_encrypt(
        data_to_sign.length(),
        ConvertStringToByteBuffer(data_to_sign.data()),
        buffer,
        rsa,
        RSA_PKCS1_PADDING);  // Adds PKCS #1 type 1 padding.
    RSA_free(rsa);
    if (length == -1) {
      LOG(ERROR) << "RSA_private_encrypt failed: " << GetOpenSSLError();
      return false;
    }
    signature = string(reinterpret_cast<char*>(buffer), length);
  }
  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;
  RSA* rsa = CreateKeyFromObject(context->key_);
  CHECK(RSA_size(rsa) <= kMaxRSAOutputBytes);
  uint8_t buffer[kMaxRSAOutputBytes];
  int length = RSA_public_decrypt(
      signature.length(),
      ConvertStringToByteBuffer(signature.data()),
      buffer,
      rsa,
      RSA_PKCS1_PADDING);  // Strips PKCS #1 type 1 padding.
  RSA_free(rsa);
  if (length == -1) {
    LOG(ERROR) << "RSA_public_decrypt failed: " << 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;
}

CK_RV SessionImpl::WrapPrivateKey(Object* object) {
  if (!tpm_utility_->IsTPMAvailable() ||
      object->GetObjectClass() != CKO_PRIVATE_KEY ||
      object->IsAttributePresent(kKeyBlobAttribute)) {
    // This object does not need to be wrapped.
    return CKR_OK;
  }
  if (!object->IsAttributePresent(CKA_PUBLIC_EXPONENT) ||
      !object->IsAttributePresent(CKA_MODULUS) ||
      !(object->IsAttributePresent(CKA_PRIME_1) ||
        object->IsAttributePresent(CKA_PRIME_2)))
    return CKR_TEMPLATE_INCOMPLETE;
  string prime;
  if (object->IsAttributePresent(CKA_PRIME_1)) {
    prime = object->GetAttributeString(CKA_PRIME_1);
  } else {
    prime = object->GetAttributeString(CKA_PRIME_2);
  }
  int key_size_bits = object->GetAttributeString(CKA_MODULUS).length() * 8;
  if (key_size_bits > kMaxRSAKeyBitsHW || key_size_bits < kMinRSAKeyBits) {
    LOG(WARNING) << "WARNING: " << key_size_bits
                 << "-bit private key cannot be wrapped by the TPM.";
    // Fall back to software.
    return CKR_OK;
  }
  string auth_data = GenerateRandomSoftware(kDefaultAuthDataBytes);
  string key_blob;
  int tpm_key_handle = 0;
  if (!tpm_utility_->WrapKey(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;
}

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

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

void SessionImpl::OperationContext::Clear() {
  if (is_valid_ && !is_finished_) {
    if (is_cipher_) {
      EVP_CIPHER_CTX_cleanup(&cipher_context_);
    } else if (is_digest_) {
      EVP_MD_CTX_cleanup(&digest_context_);
    } else if (is_hmac_) {
      HMAC_CTX_cleanup(&hmac_context_);
    }
  }
  is_valid_ = false;
  is_cipher_ = false;
  is_digest_ = false;
  is_hmac_ = false;
  is_incremental_ = false;
  is_finished_ = false;
  key_ = NULL;
  data_.clear();
  parameter_.clear();
}

}  // namespace chaps
