blob: 26bcbf7baa6cd8ae505563f5c50beb11aedaaedf [file] [log] [blame]
// 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/chaps_service.h"
#include <base/logging.h>
#include "chaps/attributes.h"
#include "chaps/chaps.h"
#include "chaps/chaps_utility.h"
#include "chaps/object.h"
#include "chaps/proto_conversion.h"
#include "chaps/session.h"
#include "chaps/slot_manager.h"
using std::string;
using std::vector;
using brillo::SecureBlob;
namespace chaps {
ChapsServiceImpl::ChapsServiceImpl(SlotManager* slot_manager)
: slot_manager_(slot_manager) {
CHECK(slot_manager);
}
uint32_t ChapsServiceImpl::GetSlotList(const SecureBlob& isolate_credential,
bool token_present,
vector<uint64_t>* slot_list) {
if (!slot_list || slot_list->size() > 0)
LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
int num_slots = slot_manager_->GetSlotCount();
for (int i = 0; i < num_slots; ++i) {
if (slot_manager_->IsTokenAccessible(isolate_credential, i) &&
(!token_present ||
slot_manager_->IsTokenPresent(isolate_credential, i)))
slot_list->push_back(i);
}
return CKR_OK;
}
uint32_t ChapsServiceImpl::GetSlotInfo(const SecureBlob& isolate_credential,
uint64_t slot_id,
SlotInfo* slot_info) {
LOG_CK_RV_AND_RETURN_IF(!slot_info, CKR_ARGUMENTS_BAD);
if (static_cast<int>(slot_id) >= slot_manager_->GetSlotCount() ||
!slot_manager_->IsTokenAccessible(isolate_credential, slot_id))
LOG_CK_RV_AND_RETURN(CKR_SLOT_ID_INVALID);
CK_SLOT_INFO ck_slot_info;
slot_manager_->GetSlotInfo(isolate_credential, slot_id, &ck_slot_info);
*slot_info = SlotInfoToProto(&ck_slot_info);
return CKR_OK;
}
uint32_t ChapsServiceImpl::GetTokenInfo(const SecureBlob& isolate_credential,
uint64_t slot_id,
TokenInfo* token_info) {
LOG_CK_RV_AND_RETURN_IF(!token_info, CKR_ARGUMENTS_BAD);
if (static_cast<int>(slot_id) >= slot_manager_->GetSlotCount() ||
!slot_manager_->IsTokenAccessible(isolate_credential, slot_id))
LOG_CK_RV_AND_RETURN(CKR_SLOT_ID_INVALID);
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->IsTokenPresent(isolate_credential,
slot_id),
CKR_TOKEN_NOT_PRESENT);
CK_TOKEN_INFO ck_token_info;
slot_manager_->GetTokenInfo(isolate_credential, slot_id, &ck_token_info);
*token_info = TokenInfoToProto(&ck_token_info);
return CKR_OK;
}
uint32_t ChapsServiceImpl::GetMechanismList(
const SecureBlob& isolate_credential,
uint64_t slot_id,
vector<uint64_t>* mechanism_list) {
LOG_CK_RV_AND_RETURN_IF(!mechanism_list || mechanism_list->size() > 0,
CKR_ARGUMENTS_BAD);
if (static_cast<int>(slot_id) >= slot_manager_->GetSlotCount() ||
!slot_manager_->IsTokenAccessible(isolate_credential, slot_id))
LOG_CK_RV_AND_RETURN(CKR_SLOT_ID_INVALID);
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->IsTokenPresent(isolate_credential,
slot_id),
CKR_TOKEN_NOT_PRESENT);
const MechanismMap* mechanism_info =
slot_manager_->GetMechanismInfo(isolate_credential, slot_id);
CHECK(mechanism_info);
for (MechanismMapIterator it = mechanism_info->begin();
it != mechanism_info->end();
++it) {
mechanism_list->push_back(it->first);
}
return CKR_OK;
}
uint32_t ChapsServiceImpl::GetMechanismInfo(
const SecureBlob& isolate_credential,
uint64_t slot_id,
uint64_t mechanism_type,
MechanismInfo* mechanism_info) {
LOG_CK_RV_AND_RETURN_IF(!mechanism_info, CKR_ARGUMENTS_BAD);
if (static_cast<int>(slot_id) >= slot_manager_->GetSlotCount() ||
!slot_manager_->IsTokenAccessible(isolate_credential, slot_id))
LOG_CK_RV_AND_RETURN(CKR_SLOT_ID_INVALID);
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->IsTokenPresent(isolate_credential,
slot_id),
CKR_TOKEN_NOT_PRESENT);
const MechanismMap* mechanism_map =
slot_manager_->GetMechanismInfo(isolate_credential, slot_id);
CHECK(mechanism_info);
MechanismMapIterator it = mechanism_map->find(mechanism_type);
LOG_CK_RV_AND_RETURN_IF(it == mechanism_map->end(), CKR_MECHANISM_INVALID);
*mechanism_info = MechanismInfoToProto(&it->second);
return CKR_OK;
}
uint32_t ChapsServiceImpl::InitToken(const SecureBlob& isolate_credential,
uint64_t slot_id,
const string* so_pin,
const vector<uint8_t>& label) {
LOG_CK_RV_AND_RETURN_IF(label.size() != chaps::kTokenLabelSize,
CKR_ARGUMENTS_BAD);
if (static_cast<int>(slot_id) >= slot_manager_->GetSlotCount() ||
!slot_manager_->IsTokenAccessible(isolate_credential, slot_id))
LOG_CK_RV_AND_RETURN(CKR_SLOT_ID_INVALID);
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->IsTokenPresent(isolate_credential,
slot_id),
CKR_TOKEN_NOT_PRESENT);
// We have no notion of a security officer role and no notion of initializing
// a token via this interface. CKR_FUNCTION_NOT_SUPPORTED could be an option
// here but reporting an incorrect pin is more likely to be handled gracefully
// by the caller.
LOG_CK_RV_AND_RETURN(CKR_PIN_INCORRECT);
}
uint32_t ChapsServiceImpl::InitPIN(const SecureBlob& isolate_credential,
uint64_t session_id, const string* pin) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
// Authentication is not handled via this interface. Since this function can
// only be called in the "R/W SO Functions" state and we don't support this
// state, CKR_USER_NOT_LOGGED_IN is the appropriate response.
LOG_CK_RV_AND_RETURN(CKR_USER_NOT_LOGGED_IN);
}
uint32_t ChapsServiceImpl::SetPIN(const SecureBlob& isolate_credential,
uint64_t session_id,
const string* old_pin,
const string* new_pin) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
// Authentication is not handled via this interface. We do not support
// changing a pin or password of any kind.
LOG_CK_RV_AND_RETURN(CKR_PIN_INVALID);
}
uint32_t ChapsServiceImpl::OpenSession(const SecureBlob& isolate_credential,
uint64_t slot_id,
uint64_t flags,
uint64_t* session_id) {
LOG_CK_RV_AND_RETURN_IF(!session_id, CKR_ARGUMENTS_BAD);
if (static_cast<int>(slot_id) >= slot_manager_->GetSlotCount() ||
!slot_manager_->IsTokenAccessible(isolate_credential, slot_id))
LOG_CK_RV_AND_RETURN(CKR_SLOT_ID_INVALID);
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->IsTokenPresent(isolate_credential,
slot_id),
CKR_TOKEN_NOT_PRESENT);
LOG_CK_RV_AND_RETURN_IF(0 == (flags & CKF_SERIAL_SESSION),
CKR_SESSION_PARALLEL_NOT_SUPPORTED);
*session_id = slot_manager_->OpenSession(isolate_credential, slot_id,
(flags & CKF_RW_SESSION) == 0);
return CKR_OK;
}
uint32_t ChapsServiceImpl::CloseSession(const SecureBlob& isolate_credential,
uint64_t session_id) {
if (!slot_manager_->CloseSession(isolate_credential, session_id))
LOG_CK_RV_AND_RETURN(CKR_SESSION_HANDLE_INVALID);
return CKR_OK;
}
uint32_t ChapsServiceImpl::CloseAllSessions(
const SecureBlob& isolate_credential,
uint64_t slot_id) {
if (static_cast<int>(slot_id) >= slot_manager_->GetSlotCount() ||
!slot_manager_->IsTokenAccessible(isolate_credential, slot_id))
LOG_CK_RV_AND_RETURN(CKR_SLOT_ID_INVALID);
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->IsTokenPresent(isolate_credential,
slot_id),
CKR_TOKEN_NOT_PRESENT);
slot_manager_->CloseAllSessions(isolate_credential, slot_id);
return CKR_OK;
}
uint32_t ChapsServiceImpl::GetSessionInfo(const SecureBlob& isolate_credential,
uint64_t session_id,
SessionInfo* session_info) {
LOG_CK_RV_AND_RETURN_IF(!session_info, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
session_info->set_slot_id(static_cast<uint64_t>(session->GetSlot()));
session_info->set_state(static_cast<uint64_t>(session->GetState()));
uint64_t flags;
flags = CKF_SERIAL_SESSION;
if (!session->IsReadOnly())
flags |= CKF_RW_SESSION;
session_info->set_flags(flags);
session_info->set_device_error(0);
return CKR_OK;
}
uint32_t ChapsServiceImpl::GetOperationState(
const SecureBlob& isolate_credential,
uint64_t session_id,
vector<uint8_t>* operation_state) {
LOG_CK_RV_AND_RETURN_IF(!operation_state, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
LOG_CK_RV_AND_RETURN_IF(!session->IsOperationActive(kEncrypt) &&
!session->IsOperationActive(kDecrypt) &&
!session->IsOperationActive(kDigest) &&
!session->IsOperationActive(kSign) &&
!session->IsOperationActive(kVerify),
CKR_OPERATION_NOT_INITIALIZED);
// There is an active operation but we'll still refuse to give out state.
LOG_CK_RV_AND_RETURN(CKR_STATE_UNSAVEABLE);
}
uint32_t ChapsServiceImpl::SetOperationState(
const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& operation_state,
uint64_t encryption_key_handle,
uint64_t authentication_key_handle) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
// We don't give out operation state so there's no way this is valid.
LOG_CK_RV_AND_RETURN(CKR_SAVED_STATE_INVALID);
}
uint32_t ChapsServiceImpl::Login(const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t user_type,
const string* pin) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
// We have no notion of a security officer role.
LOG_CK_RV_AND_RETURN_IF(user_type == CKU_SO, CKR_PIN_INCORRECT);
LOG_CK_RV_AND_RETURN_IF(user_type != CKU_USER &&
user_type != CKU_CONTEXT_SPECIFIC,
CKR_USER_TYPE_INVALID);
// For backwards compatibility we'll accept the hard-coded pin previously used
// with openCryptoki. We'll also accept a protected authentication path
// operation (i.e. a null pin).
const string legacy_pin("111111");
LOG_CK_RV_AND_RETURN_IF(pin && *pin != legacy_pin, CKR_PIN_INCORRECT);
// After successful C_Login, applications will expect private objects to be
// available for queries. Don't block waiting for them to become available,
// return the appropriate error immediately instead.
LOG_CK_RV_AND_RETURN_IF(!session->IsPrivateLoaded(),
CKR_WOULD_BLOCK_FOR_PRIVATE_OBJECTS);
// We could use CKR_USER_ALREADY_LOGGED_IN but that will cause some
// applications to close all sessions and start from scratch which is
// unnecessary.
return CKR_OK;
}
uint32_t ChapsServiceImpl::Logout(const SecureBlob& isolate_credential,
uint64_t session_id) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
return CKR_OK;
}
uint32_t ChapsServiceImpl::CreateObject(const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& attributes,
uint64_t* new_object_handle) {
LOG_CK_RV_AND_RETURN_IF(!new_object_handle, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
Attributes parsed_attributes;
LOG_CK_RV_AND_RETURN_IF(!parsed_attributes.Parse(attributes),
CKR_TEMPLATE_INCONSISTENT);
return session->CreateObject(
parsed_attributes.attributes(),
parsed_attributes.num_attributes(),
PreservedValue<uint64_t, int>(new_object_handle));
}
uint32_t ChapsServiceImpl::CopyObject(const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t object_handle,
const vector<uint8_t>& attributes,
uint64_t* new_object_handle) {
LOG_CK_RV_AND_RETURN_IF(!new_object_handle, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
Attributes parsed_attributes;
LOG_CK_RV_AND_RETURN_IF(!parsed_attributes.Parse(attributes),
CKR_TEMPLATE_INCONSISTENT);
return session->CopyObject(parsed_attributes.attributes(),
parsed_attributes.num_attributes(),
object_handle,
PreservedValue<uint64_t, int>(new_object_handle));
}
uint32_t ChapsServiceImpl::DestroyObject(const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t object_handle) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
return session->DestroyObject(object_handle);
}
uint32_t ChapsServiceImpl::GetObjectSize(const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t object_handle,
uint64_t* object_size) {
LOG_CK_RV_AND_RETURN_IF(!object_size, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
const Object* object = NULL;
LOG_CK_RV_AND_RETURN_IF(!session->GetObject(object_handle, &object),
CKR_OBJECT_HANDLE_INVALID);
CHECK(object);
*object_size = object->GetSize();
return CKR_OK;
}
uint32_t ChapsServiceImpl::GetAttributeValue(
const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t object_handle,
const vector<uint8_t>& attributes_in,
vector<uint8_t>* attributes_out) {
LOG_CK_RV_AND_RETURN_IF(!attributes_out, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
const Object* object = NULL;
LOG_CK_RV_AND_RETURN_IF(!session->GetObject(object_handle, &object),
CKR_OBJECT_HANDLE_INVALID);
CHECK(object);
Attributes tmp;
LOG_CK_RV_AND_RETURN_IF(!tmp.Parse(attributes_in), CKR_TEMPLATE_INCONSISTENT);
CK_RV result = object->GetAttributes(tmp.attributes(), tmp.num_attributes());
if (result == CKR_OK ||
result == CKR_ATTRIBUTE_SENSITIVE ||
result == CKR_ATTRIBUTE_TYPE_INVALID ||
result == CKR_BUFFER_TOO_SMALL) {
LOG_CK_RV_AND_RETURN_IF(!tmp.Serialize(attributes_out),
CKR_FUNCTION_FAILED);
}
return result;
}
uint32_t ChapsServiceImpl::SetAttributeValue(
const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t object_handle,
const vector<uint8_t>& attributes) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
Object* object = NULL;
LOG_CK_RV_AND_RETURN_IF(!session->GetModifiableObject(object_handle, &object),
CKR_OBJECT_HANDLE_INVALID);
CHECK(object);
Attributes tmp;
LOG_CK_RV_AND_RETURN_IF(!tmp.Parse(attributes), CKR_TEMPLATE_INCONSISTENT);
CK_RV result = object->SetAttributes(tmp.attributes(), tmp.num_attributes());
LOG_CK_RV_AND_RETURN_IF_ERR(result);
result = session->FlushModifiableObject(object);
LOG_CK_RV_AND_RETURN_IF_ERR(result);
return CKR_OK;
}
uint32_t ChapsServiceImpl::FindObjectsInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& attributes) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
Attributes tmp;
LOG_CK_RV_AND_RETURN_IF(!tmp.Parse(attributes), CKR_TEMPLATE_INCONSISTENT);
return session->FindObjectsInit(tmp.attributes(), tmp.num_attributes());
}
uint32_t ChapsServiceImpl::FindObjects(const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t max_object_count,
vector<uint64_t>* object_list) {
if (!object_list || object_list->size() > 0)
LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
vector<int> tmp;
CK_RV result = session->FindObjects(max_object_count, &tmp);
if (result == CKR_OK) {
for (size_t i = 0; i < tmp.size(); ++i) {
object_list->push_back(static_cast<uint64_t>(tmp[i]));
}
}
return result;
}
uint32_t ChapsServiceImpl::FindObjectsFinal(
const SecureBlob& isolate_credential,
uint64_t session_id) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
return session->FindObjectsFinal();
}
uint32_t ChapsServiceImpl::EncryptInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
const vector<uint8_t>& mechanism_parameter,
uint64_t key_handle) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
const Object* key = NULL;
LOG_CK_RV_AND_RETURN_IF(!session->GetObject(key_handle, &key),
CKR_KEY_HANDLE_INVALID);
CHECK(key);
return session->OperationInit(kEncrypt,
mechanism_type,
ConvertByteVectorToString(mechanism_parameter),
key);
}
uint32_t ChapsServiceImpl::Encrypt(const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data_in,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* data_out) {
LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
*actual_out_length = max_out_length;
return session->OperationSinglePart(
kEncrypt,
ConvertByteVectorToString(data_in),
PreservedValue<uint64_t, int>(actual_out_length),
PreservedByteVector(data_out));
}
uint32_t ChapsServiceImpl::EncryptUpdate(
const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data_in,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* data_out) {
LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
*actual_out_length = max_out_length;
return session->OperationUpdate(
kEncrypt,
ConvertByteVectorToString(data_in),
PreservedValue<uint64_t, int>(actual_out_length),
PreservedByteVector(data_out));
}
uint32_t ChapsServiceImpl::EncryptFinal(const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* data_out) {
LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
*actual_out_length = max_out_length;
return session->OperationFinal(
kEncrypt,
PreservedValue<uint64_t, int>(actual_out_length),
PreservedByteVector(data_out));
}
void ChapsServiceImpl::EncryptCancel(const SecureBlob& isolate_credential,
uint64_t session_id) {
Session* session = NULL;
if (!slot_manager_->GetSession(isolate_credential,
session_id,
&session))
return;
CHECK(session);
session->OperationCancel(kEncrypt);
}
uint32_t ChapsServiceImpl::DecryptInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
const vector<uint8_t>& mechanism_parameter,
uint64_t key_handle) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
const Object* key = NULL;
LOG_CK_RV_AND_RETURN_IF(!session->GetObject(key_handle, &key),
CKR_KEY_HANDLE_INVALID);
CHECK(key);
return session->OperationInit(kDecrypt,
mechanism_type,
ConvertByteVectorToString(mechanism_parameter),
key);
}
uint32_t ChapsServiceImpl::Decrypt(const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data_in,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* data_out) {
LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
*actual_out_length = max_out_length;
return session->OperationSinglePart(
kDecrypt,
ConvertByteVectorToString(data_in),
PreservedValue<uint64_t, int>(actual_out_length),
PreservedByteVector(data_out));
}
uint32_t ChapsServiceImpl::DecryptUpdate(
const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data_in,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* data_out) {
LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
*actual_out_length = max_out_length;
return session->OperationUpdate(
kDecrypt,
ConvertByteVectorToString(data_in),
PreservedValue<uint64_t, int>(actual_out_length),
PreservedByteVector(data_out));
}
uint32_t ChapsServiceImpl::DecryptFinal(const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* data_out) {
LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
*actual_out_length = max_out_length;
return session->OperationFinal(
kDecrypt,
PreservedValue<uint64_t, int>(actual_out_length),
PreservedByteVector(data_out));
}
void ChapsServiceImpl::DecryptCancel(const SecureBlob& isolate_credential,
uint64_t session_id) {
Session* session = NULL;
if (!slot_manager_->GetSession(isolate_credential,
session_id,
&session))
return;
CHECK(session);
session->OperationCancel(kDecrypt);
}
uint32_t ChapsServiceImpl::DigestInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
const vector<uint8_t>& mechanism_parameter) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
return session->OperationInit(kDigest,
mechanism_type,
ConvertByteVectorToString(mechanism_parameter),
NULL);
}
uint32_t ChapsServiceImpl::Digest(const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data_in,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* digest) {
LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !digest, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
*actual_out_length = max_out_length;
return session->OperationSinglePart(
kDigest,
ConvertByteVectorToString(data_in),
PreservedValue<uint64_t, int>(actual_out_length),
PreservedByteVector(digest));
}
uint32_t ChapsServiceImpl::DigestUpdate(const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data_in) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
return session->OperationUpdate(kDigest,
ConvertByteVectorToString(data_in),
NULL,
NULL);
}
uint32_t ChapsServiceImpl::DigestKey(const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t key_handle) {
// We don't give out key digests.
LOG_CK_RV_AND_RETURN(CKR_KEY_INDIGESTIBLE);
}
uint32_t ChapsServiceImpl::DigestFinal(const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* digest) {
LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !digest, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
*actual_out_length = max_out_length;
return session->OperationFinal(
kDigest,
PreservedValue<uint64_t, int>(actual_out_length),
PreservedByteVector(digest));
}
void ChapsServiceImpl::DigestCancel(const SecureBlob& isolate_credential,
uint64_t session_id) {
Session* session = NULL;
if (!slot_manager_->GetSession(isolate_credential,
session_id,
&session))
return;
CHECK(session);
session->OperationCancel(kDigest);
}
uint32_t ChapsServiceImpl::SignInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
const vector<uint8_t>& mechanism_parameter,
uint64_t key_handle) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
const Object* key = NULL;
LOG_CK_RV_AND_RETURN_IF(!session->GetObject(key_handle, &key),
CKR_KEY_HANDLE_INVALID);
CHECK(key);
return session->OperationInit(kSign,
mechanism_type,
ConvertByteVectorToString(mechanism_parameter),
key);
}
uint32_t ChapsServiceImpl::Sign(const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* signature) {
LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !signature, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
*actual_out_length = max_out_length;
return session->OperationSinglePart(
kSign,
ConvertByteVectorToString(data),
PreservedValue<uint64_t, int>(actual_out_length),
PreservedByteVector(signature));
}
uint32_t ChapsServiceImpl::SignUpdate(const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data_part) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
return session->OperationUpdate(kSign,
ConvertByteVectorToString(data_part),
NULL,
NULL);
}
uint32_t ChapsServiceImpl::SignFinal(const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* signature) {
LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !signature, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
*actual_out_length = max_out_length;
return session->OperationFinal(
kSign,
PreservedValue<uint64_t, int>(actual_out_length),
PreservedByteVector(signature));
}
void ChapsServiceImpl::SignCancel(const SecureBlob& isolate_credential,
uint64_t session_id) {
Session* session = NULL;
if (!slot_manager_->GetSession(isolate_credential,
session_id,
&session))
return;
CHECK(session);
session->OperationCancel(kSign);
}
uint32_t ChapsServiceImpl::SignRecoverInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
const vector<uint8_t>& mechanism_parameter,
uint64_t key_handle) {
LOG_CK_RV_AND_RETURN(CKR_FUNCTION_NOT_SUPPORTED);
}
uint32_t ChapsServiceImpl::SignRecover(const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* signature) {
LOG_CK_RV_AND_RETURN(CKR_FUNCTION_NOT_SUPPORTED);
}
uint32_t ChapsServiceImpl::VerifyInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
const vector<uint8_t>& mechanism_parameter,
uint64_t key_handle) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
const Object* key = NULL;
LOG_CK_RV_AND_RETURN_IF(!session->GetObject(key_handle, &key),
CKR_KEY_HANDLE_INVALID);
CHECK(key);
return session->OperationInit(kVerify,
mechanism_type,
ConvertByteVectorToString(mechanism_parameter),
key);
}
uint32_t ChapsServiceImpl::Verify(const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data,
const vector<uint8_t>& signature) {
CK_RV result = VerifyUpdate(isolate_credential, session_id, data);
if (result == CKR_OK)
result = VerifyFinal(isolate_credential, session_id, signature);
return result;
}
uint32_t ChapsServiceImpl::VerifyUpdate(const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data_part) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
return session->OperationUpdate(kVerify,
ConvertByteVectorToString(data_part),
NULL,
NULL);
}
uint32_t ChapsServiceImpl::VerifyFinal(const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& signature) {
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
return session->VerifyFinal(ConvertByteVectorToString(signature));
}
void ChapsServiceImpl::VerifyCancel(const SecureBlob& isolate_credential,
uint64_t session_id) {
Session* session = NULL;
if (!slot_manager_->GetSession(isolate_credential,
session_id,
&session))
return;
CHECK(session);
session->OperationCancel(kVerify);
}
uint32_t ChapsServiceImpl::VerifyRecoverInit(
const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
const vector<uint8_t>& mechanism_parameter,
uint64_t key_handle) {
LOG_CK_RV_AND_RETURN(CKR_FUNCTION_NOT_SUPPORTED);
}
uint32_t ChapsServiceImpl::VerifyRecover(const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& signature,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* data) {
LOG_CK_RV_AND_RETURN(CKR_FUNCTION_NOT_SUPPORTED);
}
uint32_t ChapsServiceImpl::DigestEncryptUpdate(
const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data_in,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* data_out) {
LOG_CK_RV_AND_RETURN(CKR_FUNCTION_NOT_SUPPORTED);
}
uint32_t ChapsServiceImpl::DecryptDigestUpdate(
const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data_in,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* data_out) {
LOG_CK_RV_AND_RETURN(CKR_FUNCTION_NOT_SUPPORTED);
}
uint32_t ChapsServiceImpl::SignEncryptUpdate(
const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data_in,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* data_out) {
LOG_CK_RV_AND_RETURN(CKR_FUNCTION_NOT_SUPPORTED);
}
uint32_t ChapsServiceImpl::DecryptVerifyUpdate(
const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& data_in,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* data_out) {
LOG_CK_RV_AND_RETURN(CKR_FUNCTION_NOT_SUPPORTED);
}
uint32_t ChapsServiceImpl::GenerateKey(
const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
const vector<uint8_t>& mechanism_parameter,
const vector<uint8_t>& attributes,
uint64_t* key_handle) {
LOG_CK_RV_AND_RETURN_IF(!key_handle, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
Attributes tmp;
LOG_CK_RV_AND_RETURN_IF(!tmp.Parse(attributes), CKR_TEMPLATE_INCONSISTENT);
return session->GenerateKey(mechanism_type,
ConvertByteVectorToString(mechanism_parameter),
tmp.attributes(),
tmp.num_attributes(),
PreservedValue<uint64_t, int>(key_handle));
}
uint32_t ChapsServiceImpl::GenerateKeyPair(
const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
const vector<uint8_t>& mechanism_parameter,
const vector<uint8_t>& public_attributes,
const vector<uint8_t>& private_attributes,
uint64_t* public_key_handle,
uint64_t* private_key_handle) {
LOG_CK_RV_AND_RETURN_IF(!public_key_handle || !private_key_handle,
CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
Attributes tmp_public;
LOG_CK_RV_AND_RETURN_IF(!tmp_public.Parse(public_attributes),
CKR_TEMPLATE_INCONSISTENT);
Attributes tmp_private;
LOG_CK_RV_AND_RETURN_IF(!tmp_private.Parse(private_attributes),
CKR_TEMPLATE_INCONSISTENT);
return session->GenerateKeyPair(
mechanism_type,
ConvertByteVectorToString(mechanism_parameter),
tmp_public.attributes(),
tmp_public.num_attributes(),
tmp_private.attributes(),
tmp_private.num_attributes(),
PreservedValue<uint64_t, int>(public_key_handle),
PreservedValue<uint64_t, int>(private_key_handle));
}
uint32_t ChapsServiceImpl::WrapKey(
const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
const vector<uint8_t>& mechanism_parameter,
uint64_t wrapping_key_handle,
uint64_t key_handle,
uint64_t max_out_length,
uint64_t* actual_out_length,
vector<uint8_t>* wrapped_key) {
LOG_CK_RV_AND_RETURN(CKR_FUNCTION_NOT_SUPPORTED);
}
uint32_t ChapsServiceImpl::UnwrapKey(
const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
const vector<uint8_t>& mechanism_parameter,
uint64_t wrapping_key_handle,
const vector<uint8_t>& wrapped_key,
const vector<uint8_t>& attributes,
uint64_t* key_handle) {
LOG_CK_RV_AND_RETURN(CKR_FUNCTION_NOT_SUPPORTED);
}
uint32_t ChapsServiceImpl::DeriveKey(
const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t mechanism_type,
const vector<uint8_t>& mechanism_parameter,
uint64_t base_key_handle,
const vector<uint8_t>& attributes,
uint64_t* key_handle) {
LOG_CK_RV_AND_RETURN(CKR_FUNCTION_NOT_SUPPORTED);
}
uint32_t ChapsServiceImpl::SeedRandom(const SecureBlob& isolate_credential,
uint64_t session_id,
const vector<uint8_t>& seed) {
LOG_CK_RV_AND_RETURN_IF(seed.size() == 0, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
session->SeedRandom(ConvertByteVectorToString(seed));
return CKR_OK;
}
uint32_t ChapsServiceImpl::GenerateRandom(const SecureBlob& isolate_credential,
uint64_t session_id,
uint64_t num_bytes,
vector<uint8_t>* random_data) {
LOG_CK_RV_AND_RETURN_IF(!random_data || num_bytes == 0, CKR_ARGUMENTS_BAD);
Session* session = NULL;
LOG_CK_RV_AND_RETURN_IF(!slot_manager_->GetSession(isolate_credential,
session_id,
&session),
CKR_SESSION_HANDLE_INVALID);
CHECK(session);
session->GenerateRandom(num_bytes, PreservedByteVector(random_data));
return CKR_OK;
}
} // namespace chaps