| // Copyright (c) 2011 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_redirect.h" |
| |
| #include <dlfcn.h> |
| #include <errno.h> |
| |
| #include <base/logging.h> |
| #include <base/memory/scoped_ptr.h> |
| #include <chromeos/secure_blob.h> |
| |
| #include "chaps/attributes.h" |
| #include "chaps/chaps.h" |
| #include "chaps/chaps_utility.h" |
| #include "chaps/platform_globals.h" |
| |
| using std::string; |
| using std::vector; |
| using chromeos::SecureBlob; |
| |
| typedef CK_RV (*GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR); |
| |
| namespace chaps { |
| |
| ChapsServiceRedirect::ChapsServiceRedirect(const char* library_path) |
| : library_path_(library_path), |
| library_(NULL), |
| functions_(NULL), |
| is_initialized_(false) {} |
| |
| ChapsServiceRedirect::~ChapsServiceRedirect() { |
| TearDown(); |
| } |
| |
| bool ChapsServiceRedirect::Init() { |
| library_ = dlopen(library_path_.c_str(), RTLD_NOW | RTLD_LOCAL); |
| if (!library_) { |
| LOG(ERROR) << "Failed to load " << library_path_ << " - " << dlerror(); |
| return false; |
| } |
| GetFunctionList get_func_list = |
| reinterpret_cast<GetFunctionList>(dlsym(library_, "C_GetFunctionList")); |
| if (!get_func_list) { |
| LOG(ERROR) << "Failed to find C_GetFunctionList - " << dlerror(); |
| TearDown(); |
| return false; |
| } |
| if (get_func_list(&functions_) != CKR_OK) { |
| LOG(ERROR) << "C_GetFunctionList failed."; |
| TearDown(); |
| return false; |
| } |
| CHECK(functions_) << "Library successfully returned NULL function list."; |
| return true; |
| } |
| |
| bool ChapsServiceRedirect::Init2() { |
| CHECK(functions_); |
| if (is_initialized_) |
| return true; |
| if (!SetProcessUserAndGroup(kServiceRedirectProcessUser, |
| kServiceRedirectProcessGroup, |
| false)) |
| return false; |
| CK_RV result = functions_->C_Initialize(NULL); |
| if (result != CKR_OK && result != CKR_CRYPTOKI_ALREADY_INITIALIZED) { |
| LOG(ERROR) << "C_Initialize : " << CK_RVToString(result); |
| return false; |
| } |
| LOG(INFO) << library_path_ << " initialized."; |
| is_initialized_ = true; |
| return true; |
| } |
| |
| void ChapsServiceRedirect::TearDown() { |
| if (functions_) { |
| functions_->C_Finalize(NULL); |
| functions_ = NULL; |
| } |
| if (library_) { |
| dlclose(library_); |
| library_ = NULL; |
| } |
| } |
| |
| uint32_t ChapsServiceRedirect::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); |
| if (!Init2()) { |
| // If we can't initialize the target library, we will successfully report |
| // zero slots. |
| return CKR_OK; |
| } |
| CK_ULONG count = 0; |
| // First, call with NULL to retrieve the slot count. |
| CK_RV result = functions_->C_GetSlotList(token_present, NULL, &count); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| scoped_ptr<CK_SLOT_ID[]> slot_array(new CK_SLOT_ID[count]); |
| CHECK(slot_array.get()) << "GetSlotList out of memory."; |
| // Now, query the actual list. |
| result = functions_->C_GetSlotList(token_present, slot_array.get(), &count); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| for (CK_ULONG i = 0; i < count; ++i) { |
| slot_list->push_back(static_cast<uint64_t>(slot_array[i])); |
| } |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::GetSlotInfo(const SecureBlob& isolate_credential, |
| uint64_t slot_id, |
| vector<uint8_t>* slot_description, |
| vector<uint8_t>* manufacturer_id, |
| uint64_t* flags, |
| uint8_t* hardware_version_major, |
| uint8_t* hardware_version_minor, |
| uint8_t* firmware_version_major, |
| uint8_t* firmware_version_minor) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| if (!slot_description || !manufacturer_id || !flags || |
| !hardware_version_major || !hardware_version_minor || |
| !firmware_version_major || !firmware_version_minor) { |
| LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD); |
| } |
| CK_SLOT_INFO slot_info; |
| CK_RV result = functions_->C_GetSlotInfo(slot_id, &slot_info); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *slot_description = |
| ConvertByteBufferToVector(slot_info.slotDescription, |
| arraysize(slot_info.slotDescription)); |
| *manufacturer_id = |
| ConvertByteBufferToVector(slot_info.manufacturerID, |
| arraysize(slot_info.manufacturerID)); |
| *flags = static_cast<uint64_t>(slot_info.flags); |
| *hardware_version_major = slot_info.hardwareVersion.major; |
| *hardware_version_minor = slot_info.hardwareVersion.minor; |
| *firmware_version_major = slot_info.firmwareVersion.major; |
| *firmware_version_minor = slot_info.firmwareVersion.minor; |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::GetTokenInfo( |
| const SecureBlob& isolate_credential, |
| uint64_t slot_id, |
| vector<uint8_t>* label, |
| vector<uint8_t>* manufacturer_id, |
| vector<uint8_t>* model, |
| vector<uint8_t>* serial_number, |
| uint64_t* flags, |
| uint64_t* max_session_count, |
| uint64_t* session_count, |
| uint64_t* max_session_count_rw, |
| uint64_t* session_count_rw, |
| uint64_t* max_pin_len, |
| uint64_t* min_pin_len, |
| uint64_t* total_public_memory, |
| uint64_t* free_public_memory, |
| uint64_t* total_private_memory, |
| uint64_t* free_private_memory, |
| uint8_t* hardware_version_major, |
| uint8_t* hardware_version_minor, |
| uint8_t* firmware_version_major, |
| uint8_t* firmware_version_minor) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| if (!label || !manufacturer_id || !model || !serial_number || !flags || |
| !max_session_count || !session_count || !max_session_count_rw || |
| !session_count_rw || !max_pin_len || !min_pin_len || |
| !total_public_memory || !free_public_memory || !total_private_memory || |
| !total_public_memory || |
| !hardware_version_major || !hardware_version_minor || |
| !firmware_version_major || !firmware_version_minor) { |
| LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD); |
| } |
| CK_TOKEN_INFO token_info; |
| CK_RV result = functions_->C_GetTokenInfo(slot_id, &token_info); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *label = |
| ConvertByteBufferToVector(token_info.label, arraysize(token_info.label)); |
| *manufacturer_id = |
| ConvertByteBufferToVector(token_info.manufacturerID, |
| arraysize(token_info.manufacturerID)); |
| *model = ConvertByteBufferToVector(token_info.model, |
| arraysize(token_info.model)); |
| *serial_number = |
| ConvertByteBufferToVector(token_info.serialNumber, |
| arraysize(token_info.serialNumber)); |
| *flags = token_info.flags; |
| *max_session_count = token_info.ulMaxSessionCount; |
| *session_count = token_info.ulSessionCount; |
| *max_session_count_rw = token_info.ulMaxRwSessionCount; |
| *session_count_rw = token_info.ulRwSessionCount; |
| *max_pin_len = token_info.ulMaxPinLen; |
| *min_pin_len = token_info.ulMinPinLen; |
| *total_public_memory = token_info.ulTotalPublicMemory; |
| *free_public_memory = token_info.ulFreePublicMemory; |
| *total_private_memory = token_info.ulTotalPrivateMemory; |
| *free_private_memory = token_info.ulFreePrivateMemory; |
| *hardware_version_major = token_info.hardwareVersion.major; |
| *hardware_version_minor = token_info.hardwareVersion.minor; |
| *firmware_version_major = token_info.firmwareVersion.major; |
| *firmware_version_minor = token_info.firmwareVersion.minor; |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::GetMechanismList( |
| const SecureBlob& isolate_credential, |
| uint64_t slot_id, |
| vector<uint64_t>* mechanism_list) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!mechanism_list || mechanism_list->size() > 0, |
| CKR_ARGUMENTS_BAD); |
| CK_ULONG count = 0; |
| // First, call with NULL to retrieve the mechanism count. |
| CK_RV result = functions_->C_GetMechanismList(slot_id, NULL, &count); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| scoped_ptr<CK_MECHANISM_TYPE[]> mech_array(new CK_MECHANISM_TYPE[count]); |
| LOG_CK_RV_AND_RETURN_IF(!mech_array.get(), CKR_HOST_MEMORY); |
| // Now, query the actual list. |
| result = functions_->C_GetMechanismList(slot_id, mech_array.get(), &count); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| for (CK_ULONG i = 0; i < count; ++i) { |
| mechanism_list->push_back(static_cast<uint64_t>(mech_array[i])); |
| } |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::GetMechanismInfo( |
| const SecureBlob& isolate_credential, |
| uint64_t slot_id, |
| uint64_t mechanism_type, |
| uint64_t* min_key_size, |
| uint64_t* max_key_size, |
| uint64_t* flags) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| if (!min_key_size || !max_key_size || !flags) |
| LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD); |
| CK_MECHANISM_INFO mech_info; |
| CK_RV result = functions_->C_GetMechanismInfo(slot_id, |
| mechanism_type, |
| &mech_info); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *min_key_size = static_cast<uint64_t>(mech_info.ulMinKeySize); |
| *max_key_size = static_cast<uint64_t>(mech_info.ulMaxKeySize); |
| *flags = static_cast<uint64_t>(mech_info.flags); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::InitToken(const SecureBlob& isolate_credential, |
| uint64_t slot_id, |
| const string* so_pin, |
| const vector<uint8_t>& label) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(label.size() != chaps::kTokenLabelSize, |
| CKR_ARGUMENTS_BAD); |
| CK_UTF8CHAR_PTR pin_buffer = |
| so_pin ? ConvertStringToCharBuffer(so_pin->data()) : NULL; |
| CK_ULONG pin_length = so_pin ? static_cast<CK_ULONG>(so_pin->length()) : 0; |
| CK_UTF8CHAR label_buffer[chaps::kTokenLabelSize]; |
| memcpy(label_buffer, &label.front(), chaps::kTokenLabelSize); |
| CK_RV result = functions_->C_InitToken(slot_id, |
| pin_buffer, |
| pin_length, |
| label_buffer); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::InitPIN(const SecureBlob& isolate_credential, |
| uint64_t session_id, const string* pin) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_UTF8CHAR_PTR pin_buffer = |
| pin ? ConvertStringToCharBuffer(pin->data()) : NULL; |
| CK_ULONG pin_length = pin ? static_cast<CK_ULONG>(pin->length()) : 0; |
| CK_RV result = functions_->C_InitPIN(session_id, pin_buffer, pin_length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::SetPIN(const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| const string* old_pin, |
| const string* new_pin) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_UTF8CHAR_PTR old_pin_buffer = |
| old_pin ? ConvertStringToCharBuffer(old_pin->data()) : NULL; |
| CK_ULONG old_pin_length = |
| old_pin ? static_cast<CK_ULONG>(old_pin->length()) : 0; |
| CK_UTF8CHAR_PTR new_pin_buffer = |
| new_pin ? ConvertStringToCharBuffer(new_pin->data()) : NULL; |
| CK_ULONG new_pin_length = |
| new_pin ? static_cast<CK_ULONG>(new_pin->length()) : 0; |
| CK_RV result = functions_->C_SetPIN(session_id, |
| old_pin_buffer, old_pin_length, |
| new_pin_buffer, new_pin_length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::OpenSession(const SecureBlob& isolate_credential, |
| uint64_t slot_id, uint64_t flags, |
| uint64_t* session_id) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!session_id, CKR_ARGUMENTS_BAD); |
| CK_SESSION_HANDLE handle; |
| uint32_t result = functions_->C_OpenSession(slot_id, flags, NULL, NULL, |
| &handle); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *session_id = handle; |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::CloseSession( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| uint32_t result = functions_->C_CloseSession(session_id); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::CloseAllSessions( |
| const SecureBlob& isolate_credential, |
| uint64_t slot_id) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| uint32_t result = functions_->C_CloseAllSessions(slot_id); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::GetSessionInfo( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| uint64_t* slot_id, |
| uint64_t* state, |
| uint64_t* flags, |
| uint64_t* device_error) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| if (!slot_id || !state || !flags || !device_error) |
| LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD); |
| CK_SESSION_INFO info; |
| uint32_t result = functions_->C_GetSessionInfo(session_id, &info); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *slot_id = static_cast<uint64_t>(info.slotID); |
| *state = static_cast<uint64_t>(info.state); |
| *flags = static_cast<uint64_t>(info.flags); |
| *device_error = static_cast<uint64_t>(info.ulDeviceError); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::GetOperationState( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| vector<uint8_t>* operation_state) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!operation_state, CKR_ARGUMENTS_BAD); |
| CK_ULONG size = 0; |
| // First, call with NULL to retrieve the state size. |
| CK_RV result = functions_->C_GetOperationState(session_id, NULL, &size); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| scoped_ptr<CK_BYTE[]> buffer(new CK_BYTE[size]); |
| LOG_CK_RV_AND_RETURN_IF(!buffer.get(), CKR_HOST_MEMORY); |
| // Now, get the actual state data. |
| result = functions_->C_GetOperationState(session_id, buffer.get(), &size); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *operation_state = ConvertByteBufferToVector(buffer.get(), size); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| uint32_t result = functions_->C_SetOperationState( |
| session_id, |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&operation_state.front())), |
| static_cast<CK_ULONG>(operation_state.size()), |
| static_cast<CK_OBJECT_HANDLE>(encryption_key_handle), |
| static_cast<CK_OBJECT_HANDLE>(authentication_key_handle)); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::Login(const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| uint64_t user_type, |
| const string* pin) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_UTF8CHAR_PTR pin_buffer = |
| pin ? ConvertStringToCharBuffer(pin->data()) : NULL; |
| CK_ULONG pin_length = pin ? static_cast<CK_ULONG>(pin->length()) : 0; |
| uint32_t result = functions_->C_Login(session_id, |
| user_type, |
| pin_buffer, |
| pin_length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::Logout(const SecureBlob& isolate_credential, |
| uint64_t session_id) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| uint32_t result = functions_->C_Logout(session_id); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!new_object_handle, CKR_ARGUMENTS_BAD); |
| Attributes tmp; |
| if (!tmp.Parse(attributes)) |
| LOG_CK_RV_AND_RETURN(CKR_TEMPLATE_INCONSISTENT); |
| uint32_t result = functions_->C_CreateObject( |
| session_id, |
| tmp.attributes(), |
| tmp.num_attributes(), |
| PreservedUint64_t(new_object_handle)); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!new_object_handle, CKR_ARGUMENTS_BAD); |
| Attributes tmp; |
| if (!tmp.Parse(attributes)) |
| LOG_CK_RV_AND_RETURN(CKR_TEMPLATE_INCONSISTENT); |
| uint32_t result = functions_->C_CopyObject( |
| session_id, |
| object_handle, |
| tmp.attributes(), |
| tmp.num_attributes(), |
| PreservedUint64_t(new_object_handle)); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::DestroyObject( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| uint64_t object_handle) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| uint32_t result = functions_->C_DestroyObject(session_id, object_handle); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::GetObjectSize( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| uint64_t object_handle, |
| uint64_t* object_size) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!object_size, CKR_ARGUMENTS_BAD); |
| uint32_t result = functions_->C_GetObjectSize(session_id, |
| object_handle, |
| PreservedUint64_t(object_size)); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!attributes_out, CKR_ARGUMENTS_BAD); |
| Attributes tmp; |
| if (!tmp.Parse(attributes_in)) |
| LOG_CK_RV_AND_RETURN(CKR_TEMPLATE_INCONSISTENT); |
| uint32_t result = functions_->C_GetAttributeValue(session_id, |
| object_handle, |
| tmp.attributes(), |
| tmp.num_attributes()); |
| if (result != CKR_OK) |
| LOG_CK_RV(result); |
| if (!tmp.Serialize(attributes_out)) |
| LOG_CK_RV_AND_RETURN(CKR_TEMPLATE_INCONSISTENT); |
| return result; |
| } |
| |
| uint32_t ChapsServiceRedirect::SetAttributeValue( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| uint64_t object_handle, |
| const vector<uint8_t>& attributes) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| Attributes tmp; |
| LOG_CK_RV_AND_RETURN_IF(!tmp.Parse(attributes), CKR_TEMPLATE_INCONSISTENT); |
| uint32_t result = functions_->C_SetAttributeValue(session_id, |
| object_handle, |
| tmp.attributes(), |
| tmp.num_attributes()); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::FindObjectsInit( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| const vector<uint8_t>& attributes) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| Attributes tmp; |
| LOG_CK_RV_AND_RETURN_IF(!tmp.Parse(attributes), CKR_TEMPLATE_INCONSISTENT); |
| uint32_t result = functions_->C_FindObjectsInit(session_id, |
| tmp.attributes(), |
| tmp.num_attributes()); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::FindObjects(const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| uint64_t max_object_count, |
| vector<uint64_t>* object_list) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| if (!object_list || object_list->size() > 0) |
| LOG_CK_RV_AND_RETURN(CKR_ARGUMENTS_BAD); |
| scoped_ptr<CK_OBJECT_HANDLE[]> object_handles( |
| new CK_OBJECT_HANDLE[max_object_count]); |
| CHECK(object_handles.get()); |
| CK_ULONG object_count = 0; |
| uint32_t result = functions_->C_FindObjects(session_id, |
| object_handles.get(), |
| max_object_count, |
| &object_count); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| for (CK_ULONG i = 0; i < object_count; i++) { |
| object_list->push_back(static_cast<uint64_t>(object_handles[i])); |
| } |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::FindObjectsFinal( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| uint32_t result = functions_->C_FindObjectsFinal(session_id); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::EncryptInit( |
| 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_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_MECHANISM mechanism; |
| mechanism.mechanism = static_cast<CK_MECHANISM_TYPE>(mechanism_type); |
| mechanism.pParameter = const_cast<uint8_t*>(&mechanism_parameter.front()); |
| mechanism.ulParameterLen = mechanism_parameter.size(); |
| uint32_t result = functions_->C_EncryptInit( |
| session_id, |
| &mechanism, |
| static_cast<CK_OBJECT_HANDLE>(key_handle)); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data_in.front())); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_Encrypt(session_id, |
| in_bytes, |
| data_in.size(), |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *data_out = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data_in.front())); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_EncryptUpdate(session_id, |
| in_bytes, |
| data_in.size(), |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *data_out = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_EncryptFinal(session_id, |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *data_out = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| void ChapsServiceRedirect::EncryptCancel( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id) { |
| LOG(ERROR) << "Unexpected cancel operation"; |
| } |
| |
| uint32_t ChapsServiceRedirect::DecryptInit( |
| 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_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_MECHANISM mechanism; |
| mechanism.mechanism = static_cast<CK_MECHANISM_TYPE>(mechanism_type); |
| mechanism.pParameter = const_cast<uint8_t*>(&mechanism_parameter.front()); |
| mechanism.ulParameterLen = mechanism_parameter.size(); |
| uint32_t result = functions_->C_DecryptInit( |
| session_id, |
| &mechanism, |
| static_cast<CK_OBJECT_HANDLE>(key_handle)); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data_in.front())); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_Decrypt(session_id, |
| in_bytes, |
| data_in.size(), |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| if (out_bytes.get()) |
| *data_out = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data_in.front())); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_DecryptUpdate(session_id, |
| in_bytes, |
| data_in.size(), |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *data_out = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_DecryptFinal(session_id, |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *data_out = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| void ChapsServiceRedirect::DecryptCancel( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id) { |
| LOG(ERROR) << "Unexpected cancel operation"; |
| } |
| |
| uint32_t ChapsServiceRedirect::DigestInit( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| uint64_t mechanism_type, |
| const vector<uint8_t>& mechanism_parameter) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_MECHANISM mechanism; |
| mechanism.mechanism = static_cast<CK_MECHANISM_TYPE>(mechanism_type); |
| mechanism.pParameter = const_cast<uint8_t*>(&mechanism_parameter.front()); |
| mechanism.ulParameterLen = mechanism_parameter.size(); |
| uint32_t result = functions_->C_DigestInit(session_id, &mechanism); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !digest, CKR_ARGUMENTS_BAD); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data_in.front())); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_Digest(session_id, |
| in_bytes, |
| data_in.size(), |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *digest = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::DigestUpdate( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| const vector<uint8_t>& data_in) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data_in.front())); |
| uint32_t result = functions_->C_DigestUpdate(session_id, |
| in_bytes, |
| data_in.size()); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::DigestKey(const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| uint64_t key_handle) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| uint32_t result = functions_->C_DigestKey(session_id, key_handle); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !digest, CKR_ARGUMENTS_BAD); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_DigestFinal(session_id, |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *digest = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| void ChapsServiceRedirect::DigestCancel( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id) { |
| LOG(ERROR) << "Unexpected cancel operation"; |
| } |
| |
| uint32_t ChapsServiceRedirect::SignInit( |
| 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_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_MECHANISM mechanism; |
| mechanism.mechanism = static_cast<CK_MECHANISM_TYPE>(mechanism_type); |
| mechanism.pParameter = const_cast<uint8_t*>(&mechanism_parameter.front()); |
| mechanism.ulParameterLen = mechanism_parameter.size(); |
| uint32_t result = functions_->C_SignInit(session_id, &mechanism, key_handle); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !signature, CKR_ARGUMENTS_BAD); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data.front())); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_Sign(session_id, |
| in_bytes, |
| data.size(), |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *signature = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::SignUpdate(const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| const vector<uint8_t>& data_part) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data_part.front())); |
| uint32_t result = functions_->C_SignUpdate(session_id, |
| in_bytes, |
| data_part.size()); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !signature, CKR_ARGUMENTS_BAD); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_SignFinal(session_id, |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *signature = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| void ChapsServiceRedirect::SignCancel( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id) { |
| LOG(ERROR) << "Unexpected cancel operation"; |
| } |
| |
| uint32_t ChapsServiceRedirect::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_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_MECHANISM mechanism; |
| mechanism.mechanism = static_cast<CK_MECHANISM_TYPE>(mechanism_type); |
| mechanism.pParameter = const_cast<uint8_t*>(&mechanism_parameter.front()); |
| mechanism.ulParameterLen = mechanism_parameter.size(); |
| uint32_t result = functions_->C_SignRecoverInit(session_id, |
| &mechanism, |
| key_handle); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !signature, CKR_ARGUMENTS_BAD); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data.front())); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_SignRecover(session_id, |
| in_bytes, |
| data.size(), |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *signature = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::VerifyInit( |
| 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_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_MECHANISM mechanism; |
| mechanism.mechanism = static_cast<CK_MECHANISM_TYPE>(mechanism_type); |
| mechanism.pParameter = const_cast<uint8_t*>(&mechanism_parameter.front()); |
| mechanism.ulParameterLen = mechanism_parameter.size(); |
| uint32_t result = functions_->C_VerifyInit(session_id, |
| &mechanism, |
| key_handle); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::Verify(const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| const vector<uint8_t>& data, |
| const vector<uint8_t>& signature) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_BYTE_PTR data_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data.front())); |
| CK_BYTE_PTR sig_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&signature.front())); |
| uint32_t result = functions_->C_Verify(session_id, |
| data_bytes, |
| data.size(), |
| sig_bytes, |
| signature.size()); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::VerifyUpdate( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| const vector<uint8_t>& data_part) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data_part.front())); |
| uint32_t result = functions_->C_VerifyUpdate(session_id, |
| in_bytes, |
| data_part.size()); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::VerifyFinal(const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| const vector<uint8_t>& signature) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&signature.front())); |
| uint32_t result = functions_->C_VerifyFinal(session_id, |
| in_bytes, |
| signature.size()); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| void ChapsServiceRedirect::VerifyCancel( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id) { |
| LOG(ERROR) << "Unexpected cancel operation"; |
| } |
| |
| uint32_t ChapsServiceRedirect::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_IF(!Init2(), CKR_GENERAL_ERROR); |
| CK_MECHANISM mechanism; |
| mechanism.mechanism = static_cast<CK_MECHANISM_TYPE>(mechanism_type); |
| mechanism.pParameter = const_cast<uint8_t*>(&mechanism_parameter.front()); |
| mechanism.ulParameterLen = mechanism_parameter.size(); |
| uint32_t result = functions_->C_VerifyRecoverInit(session_id, |
| &mechanism, |
| key_handle); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data, CKR_ARGUMENTS_BAD); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&signature.front())); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_VerifyRecover(session_id, |
| in_bytes, |
| signature.size(), |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *data = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data_in.front())); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_DigestEncryptUpdate(session_id, |
| in_bytes, |
| data_in.size(), |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *data_out = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data_in.front())); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_DecryptDigestUpdate(session_id, |
| in_bytes, |
| data_in.size(), |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *data_out = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data_in.front())); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_SignEncryptUpdate(session_id, |
| in_bytes, |
| data_in.size(), |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *data_out = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !data_out, CKR_ARGUMENTS_BAD); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&data_in.front())); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_DecryptVerifyUpdate(session_id, |
| in_bytes, |
| data_in.size(), |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *data_out = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!key_handle, CKR_ARGUMENTS_BAD); |
| CK_MECHANISM mechanism; |
| mechanism.mechanism = static_cast<CK_MECHANISM_TYPE>(mechanism_type); |
| mechanism.pParameter = const_cast<uint8_t*>(&mechanism_parameter.front()); |
| mechanism.ulParameterLen = mechanism_parameter.size(); |
| Attributes parsed_attributes; |
| if (!parsed_attributes.Parse(attributes)) |
| LOG_CK_RV_AND_RETURN(CKR_TEMPLATE_INCONSISTENT); |
| uint32_t result = functions_->C_GenerateKey( |
| session_id, |
| &mechanism, |
| parsed_attributes.attributes(), |
| parsed_attributes.num_attributes(), |
| PreservedUint64_t(key_handle)); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!public_key_handle || !private_key_handle, |
| CKR_ARGUMENTS_BAD); |
| CK_MECHANISM mechanism; |
| mechanism.mechanism = static_cast<CK_MECHANISM_TYPE>(mechanism_type); |
| mechanism.pParameter = const_cast<uint8_t*>(&mechanism_parameter.front()); |
| mechanism.ulParameterLen = mechanism_parameter.size(); |
| Attributes public_parsed_attributes; |
| if (!public_parsed_attributes.Parse(public_attributes)) |
| LOG_CK_RV_AND_RETURN(CKR_TEMPLATE_INCONSISTENT); |
| Attributes private_parsed_attributes; |
| if (!private_parsed_attributes.Parse(private_attributes)) |
| LOG_CK_RV_AND_RETURN(CKR_TEMPLATE_INCONSISTENT); |
| uint32_t result = functions_->C_GenerateKeyPair( |
| session_id, |
| &mechanism, |
| public_parsed_attributes.attributes(), |
| public_parsed_attributes.num_attributes(), |
| private_parsed_attributes.attributes(), |
| private_parsed_attributes.num_attributes(), |
| PreservedUint64_t(public_key_handle), |
| PreservedUint64_t(private_key_handle)); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!actual_out_length || !wrapped_key, |
| CKR_ARGUMENTS_BAD); |
| CK_MECHANISM mechanism; |
| mechanism.mechanism = static_cast<CK_MECHANISM_TYPE>(mechanism_type); |
| mechanism.pParameter = const_cast<uint8_t*>(&mechanism_parameter.front()); |
| mechanism.ulParameterLen = mechanism_parameter.size(); |
| scoped_ptr<CK_BYTE[]> out_bytes; |
| if (max_out_length) { |
| out_bytes.reset(new CK_BYTE[max_out_length]); |
| CHECK(out_bytes.get()); |
| } |
| CK_ULONG length = max_out_length; |
| uint32_t result = functions_->C_WrapKey(session_id, |
| &mechanism, |
| wrapping_key_handle, |
| key_handle, |
| out_bytes.get(), |
| &length); |
| // Provide the length before checking the result. This handles cases like |
| // CKR_BUFFER_TOO_SMALL. |
| *actual_out_length = static_cast<uint64_t>(length); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *wrapped_key = ConvertByteBufferToVector(out_bytes.get(), length); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!key_handle, CKR_ARGUMENTS_BAD); |
| CK_MECHANISM mechanism; |
| mechanism.mechanism = static_cast<CK_MECHANISM_TYPE>(mechanism_type); |
| mechanism.pParameter = const_cast<uint8_t*>(&mechanism_parameter.front()); |
| mechanism.ulParameterLen = mechanism_parameter.size(); |
| Attributes parsed_attributes; |
| if (!parsed_attributes.Parse(attributes)) |
| LOG_CK_RV_AND_RETURN(CKR_TEMPLATE_INCONSISTENT); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&wrapped_key.front())); |
| uint32_t result = functions_->C_UnwrapKey(session_id, |
| &mechanism, |
| wrapping_key_handle, |
| in_bytes, |
| wrapped_key.size(), |
| parsed_attributes.attributes(), |
| parsed_attributes.num_attributes(), |
| PreservedUint64_t(key_handle)); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::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_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!key_handle, CKR_ARGUMENTS_BAD); |
| CK_MECHANISM mechanism; |
| mechanism.mechanism = static_cast<CK_MECHANISM_TYPE>(mechanism_type); |
| mechanism.pParameter = const_cast<uint8_t*>(&mechanism_parameter.front()); |
| mechanism.ulParameterLen = mechanism_parameter.size(); |
| Attributes parsed_attributes; |
| if (!parsed_attributes.Parse(attributes)) |
| LOG_CK_RV_AND_RETURN(CKR_TEMPLATE_INCONSISTENT); |
| uint32_t result = functions_->C_DeriveKey(session_id, |
| &mechanism, |
| base_key_handle, |
| parsed_attributes.attributes(), |
| parsed_attributes.num_attributes(), |
| PreservedUint64_t(key_handle)); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::SeedRandom(const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| const vector<uint8_t>& seed) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(seed.size() == 0, CKR_ARGUMENTS_BAD); |
| CK_BYTE_PTR in_bytes = |
| static_cast<CK_BYTE_PTR>(const_cast<uint8_t*>(&seed.front())); |
| uint32_t result = functions_->C_SeedRandom(session_id, in_bytes, seed.size()); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| return CKR_OK; |
| } |
| |
| uint32_t ChapsServiceRedirect::GenerateRandom( |
| const SecureBlob& isolate_credential, |
| uint64_t session_id, |
| uint64_t num_bytes, |
| vector<uint8_t>* random_data) { |
| LOG_CK_RV_AND_RETURN_IF(!Init2(), CKR_GENERAL_ERROR); |
| LOG_CK_RV_AND_RETURN_IF(!random_data || num_bytes == 0, CKR_ARGUMENTS_BAD); |
| scoped_ptr<CK_BYTE[]> out_bytes(new CK_BYTE[num_bytes]); |
| CHECK(out_bytes.get()); |
| uint32_t result = functions_->C_GenerateRandom(session_id, |
| out_bytes.get(), |
| num_bytes); |
| LOG_CK_RV_AND_RETURN_IF_ERR(result); |
| *random_data = ConvertByteBufferToVector(out_bytes.get(), num_bytes); |
| return CKR_OK; |
| } |
| |
| } // namespace chaps |