// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include "ck_helpers.h" #include "invoke_ta.h" #include "local_utils.h" #include "pkcs11_token.h" #define PKCS11_LIB_MANUFACTURER "Linaro" #define PKCS11_LIB_DESCRIPTION "OP-TEE PKCS11 Cryptoki library" /** * Converts uint32_t value to CK_ULONG with unavailable information support * * On 64 bit systems uint32_t cannot handle CK_ULONG defined * CK_UNAVAILABLE_INFORMATION. Check for this specific situation and return * correct value. * * @ta_value: Value form PKCS#11 TA * @return Valid CK_ULONG value */ static CK_ULONG maybe_unavail(uint32_t ta_value) { if (ta_value == PKCS11_CK_UNAVAILABLE_INFORMATION) return CK_UNAVAILABLE_INFORMATION; else return ta_value; } /** * ck_get_info - Get local information for C_GetInfo */ CK_RV ck_get_info(CK_INFO_PTR info) { const CK_INFO lib_info = { .cryptokiVersion = { CK_PKCS11_VERSION_MAJOR, CK_PKCS11_VERSION_MINOR, }, .manufacturerID = PKCS11_LIB_MANUFACTURER, .flags = 0, /* must be zero per the PKCS#11 2.40 */ .libraryDescription = PKCS11_LIB_DESCRIPTION, .libraryVersion = { PKCS11_TA_VERSION_MAJOR, PKCS11_TA_VERSION_MINOR }, }; int n = 0; if (!info) return CKR_ARGUMENTS_BAD; *info = lib_info; /* Pad strings with blank characters */ n = strnlen((char *)info->manufacturerID, sizeof(info->manufacturerID)); memset(&info->manufacturerID[n], ' ', sizeof(info->manufacturerID) - n); n = strnlen((char *)info->libraryDescription, sizeof(info->libraryDescription)); memset(&info->libraryDescription[n], ' ', sizeof(info->libraryDescription) - n); return CKR_OK; } /** * ck_slot_get_list - Wrap C_GetSlotList into PKCS11_CMD_SLOT_LIST */ CK_RV ck_slot_get_list(CK_BBOOL present, CK_SLOT_ID_PTR slots, CK_ULONG_PTR count) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *shm = NULL; uint32_t *slot_ids = NULL; size_t client_count = 0; size_t size = 0; size_t n = 0; /* Discard @present: all slots reported by TA are present */ (void)present; if (!count) return CKR_ARGUMENTS_BAD; /* * As per spec, if @slots is NULL, "The contents of *pulCount on * entry to C_GetSlotList has no meaning in this case (...)" */ if (slots) client_count = *count; size = client_count * sizeof(*slot_ids); shm = ckteec_alloc_shm(size, CKTEEC_SHM_OUT); if (!shm) return CKR_HOST_MEMORY; rv = ckteec_invoke_ta(PKCS11_CMD_SLOT_LIST, NULL, NULL, shm, &size, NULL, NULL); if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) *count = size / sizeof(*slot_ids); if (!slots && rv == CKR_BUFFER_TOO_SMALL) rv = CKR_OK; if (!slots || rv) goto out; slot_ids = shm->buffer; for (n = 0; n < *count; n++) slots[n] = slot_ids[n]; out: ckteec_free_shm(shm); return rv; } /** * ck_slot_get_info - Wrap C_GetSlotInfo into PKCS11_CMD_SLOT_INFO */ CK_RV ck_slot_get_info(CK_SLOT_ID slot, CK_SLOT_INFO_PTR info) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out = NULL; uint32_t slot_id = slot; struct pkcs11_slot_info *ta_info = NULL; size_t out_size = 0; if (!info) return CKR_ARGUMENTS_BAD; ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } memcpy(ctrl->buffer, &slot_id, sizeof(slot_id)); out = ckteec_alloc_shm(sizeof(*ta_info), CKTEEC_SHM_OUT); if (!out) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_SLOT_INFO, ctrl, out, &out_size); if (rv != CKR_OK || out_size != out->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto out; } ta_info = out->buffer; COMPILE_TIME_ASSERT(sizeof(info->slotDescription) == sizeof(ta_info->slot_description)); memcpy(info->slotDescription, ta_info->slot_description, sizeof(info->slotDescription)); COMPILE_TIME_ASSERT(sizeof(info->manufacturerID) == sizeof(ta_info->manufacturer_id)); memcpy(info->manufacturerID, ta_info->manufacturer_id, sizeof(info->manufacturerID)); info->flags = ta_info->flags; COMPILE_TIME_ASSERT(sizeof(info->hardwareVersion) == sizeof(ta_info->hardware_version)); memcpy(&info->hardwareVersion, ta_info->hardware_version, sizeof(info->hardwareVersion)); COMPILE_TIME_ASSERT(sizeof(info->firmwareVersion) == sizeof(ta_info->firmware_version)); memcpy(&info->firmwareVersion, ta_info->firmware_version, sizeof(info->firmwareVersion)); out: ckteec_free_shm(ctrl); ckteec_free_shm(out); return rv; } /** * ck_token_get_info - Wrap C_GetTokenInfo into PKCS11_CMD_TOKEN_INFO */ CK_RV ck_token_get_info(CK_SLOT_ID slot, CK_TOKEN_INFO_PTR info) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; uint32_t slot_id = slot; struct pkcs11_token_info *ta_info = NULL; size_t out_size = 0; if (!info) return CKR_ARGUMENTS_BAD; ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } memcpy(ctrl->buffer, &slot_id, sizeof(slot_id)); out_shm = ckteec_alloc_shm(sizeof(*ta_info), CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_TOKEN_INFO, ctrl, out_shm, &out_size); if (rv) goto out; if (out_size != out_shm->size) { rv = CKR_DEVICE_ERROR; goto out; } ta_info = out_shm->buffer; COMPILE_TIME_ASSERT(sizeof(info->label) == sizeof(ta_info->label)); memcpy(info->label, ta_info->label, sizeof(info->label)); COMPILE_TIME_ASSERT(sizeof(info->manufacturerID) == sizeof(ta_info->manufacturer_id)); memcpy(info->manufacturerID, ta_info->manufacturer_id, sizeof(info->manufacturerID)); COMPILE_TIME_ASSERT(sizeof(info->model) == sizeof(ta_info->model)); memcpy(info->model, ta_info->model, sizeof(info->model)); COMPILE_TIME_ASSERT(sizeof(info->serialNumber) == sizeof(ta_info->serial_number)); memcpy(info->serialNumber, ta_info->serial_number, sizeof(info->serialNumber)); info->flags = ta_info->flags; info->ulMaxSessionCount = maybe_unavail(ta_info->max_session_count); info->ulSessionCount = maybe_unavail(ta_info->session_count); info->ulMaxRwSessionCount = maybe_unavail(ta_info->max_rw_session_count); info->ulRwSessionCount = maybe_unavail(ta_info->rw_session_count); info->ulMaxPinLen = ta_info->max_pin_len; info->ulMinPinLen = ta_info->min_pin_len; info->ulTotalPublicMemory = maybe_unavail(ta_info->total_public_memory); info->ulFreePublicMemory = maybe_unavail(ta_info->free_public_memory); info->ulTotalPrivateMemory = maybe_unavail(ta_info->total_private_memory); info->ulFreePrivateMemory = maybe_unavail(ta_info->free_private_memory); COMPILE_TIME_ASSERT(sizeof(info->hardwareVersion) == sizeof(ta_info->hardware_version)); memcpy(&info->hardwareVersion, ta_info->hardware_version, sizeof(info->hardwareVersion)); COMPILE_TIME_ASSERT(sizeof(info->firmwareVersion) == sizeof(ta_info->firmware_version)); memcpy(&info->firmwareVersion, ta_info->firmware_version, sizeof(info->firmwareVersion)); COMPILE_TIME_ASSERT(sizeof(info->utcTime) == sizeof(ta_info->utc_time)); memcpy(&info->utcTime, ta_info->utc_time, sizeof(info->utcTime)); out: ckteec_free_shm(ctrl); ckteec_free_shm(out_shm); return rv; } /** * ck_token_mechanism_ids - Wrap C_GetMechanismList */ CK_RV ck_token_mechanism_ids(CK_SLOT_ID slot, CK_MECHANISM_TYPE_PTR mechanisms, CK_ULONG_PTR count) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out = NULL; uint32_t slot_id = slot; uint32_t *mecha_ids = NULL; size_t out_size = 0; size_t n = 0; if (!count) return CKR_ARGUMENTS_BAD; /* * As per spec, if @mechanism is NULL, "The contents of *pulCount on * entry to C_GetMechanismList has no meaning in this case (...)" */ if (mechanisms) out_size = *count * sizeof(*mecha_ids); ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } memcpy(ctrl->buffer, &slot_id, sizeof(slot_id)); out = ckteec_alloc_shm(out_size, CKTEEC_SHM_OUT); if (!out) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_MECHANISM_IDS, ctrl, out, &out_size); if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) *count = out_size / sizeof(*mecha_ids); if (!mechanisms && rv == CKR_BUFFER_TOO_SMALL) rv = CKR_OK; if (!mechanisms || rv) goto out; mecha_ids = out->buffer; for (n = 0; n < *count; n++) mechanisms[n] = mecha_ids[n]; out: ckteec_free_shm(ctrl); ckteec_free_shm(out); return rv; } /** * ck_token_mechanism_info - Wrap C_GetMechanismInfo into command MECHANISM_INFO */ CK_RV ck_token_mechanism_info(CK_SLOT_ID slot, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR info) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out = NULL; uint32_t slot_id = slot; uint32_t mecha_type = type; struct pkcs11_mechanism_info *ta_info = NULL; char *buf = NULL; size_t out_size = 0; if (!info) return CKR_ARGUMENTS_BAD; ctrl = ckteec_alloc_shm(sizeof(slot_id) + sizeof(mecha_type), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } buf = ctrl->buffer; memcpy(buf, &slot_id, sizeof(slot_id)); buf += sizeof(slot_id); memcpy(buf, &mecha_type, sizeof(mecha_type)); out = ckteec_alloc_shm(sizeof(*ta_info), CKTEEC_SHM_OUT); if (!out) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_MECHANISM_INFO, ctrl, out, &out_size); if (rv != CKR_OK || out_size != out->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto out; } ta_info = out->buffer; info->ulMinKeySize = ta_info->min_key_size; info->ulMaxKeySize = ta_info->max_key_size; info->flags = ta_info->flags; out: ckteec_free_shm(ctrl); ckteec_free_shm(out); return rv; } /** * ck_open_session - Wrap C_OpenSession into PKCS11_CMD_OPEN_{RW|RO}_SESSION * * Note: cookie and callback are not utilized by libckteec and are silently * sinked in to have better out-of-box compatibility with 3rd party libraries * and applications which provides the callback. */ CK_RV ck_open_session(CK_SLOT_ID slot, CK_FLAGS flags, CK_VOID_PTR cookie, CK_NOTIFY callback, CK_SESSION_HANDLE_PTR session) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out = NULL; uint32_t slot_id = slot; uint32_t u32_flags = flags; uint32_t handle = 0; size_t out_size = 0; uint8_t *buf; /* Ignore notify callback */ (void)cookie; (void)callback; if ((flags & ~(CKF_RW_SESSION | CKF_SERIAL_SESSION)) || !session) return CKR_ARGUMENTS_BAD; /* Shm io0: (in/out) ctrl = [slot-id][flags] / [status] */ ctrl = ckteec_alloc_shm(sizeof(slot_id) + sizeof(u32_flags), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } buf = (uint8_t *)ctrl->buffer; memcpy(buf, &slot_id, sizeof(slot_id)); buf += sizeof(slot_id); memcpy(buf, &u32_flags, sizeof(u32_flags)); /* Shm io2: (out) [session handle] */ out = ckteec_alloc_shm(sizeof(handle), CKTEEC_SHM_OUT); if (!out) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_OPEN_SESSION, ctrl, out, &out_size); if (rv != CKR_OK || out_size != out->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto out; } memcpy(&handle, out->buffer, sizeof(handle)); *session = handle; out: ckteec_free_shm(ctrl); ckteec_free_shm(out); return rv; } /** * ck_open_session - Wrap C_OpenSession into PKCS11_CMD_CLOSE_SESSION */ CK_RV ck_close_session(CK_SESSION_HANDLE session) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t session_handle = session; /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); rv = ckteec_invoke_ctrl(PKCS11_CMD_CLOSE_SESSION, ctrl); out: ckteec_free_shm(ctrl); return rv; } /** * ck_close_all_sessions - Wrap C_CloseAllSessions into TA command */ CK_RV ck_close_all_sessions(CK_SLOT_ID slot) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t slot_id = slot; /* Shm io0: (in/out) ctrl = [slot-id] / [status] */ ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } memcpy(ctrl->buffer, &slot_id, sizeof(slot_id)); rv = ckteec_invoke_ctrl(PKCS11_CMD_CLOSE_ALL_SESSIONS, ctrl); out: ckteec_free_shm(ctrl); return rv; } /** * ck_get_session_info - Wrap C_GetSessionInfo into PKCS11_CMD_SESSION_INFO */ CK_RV ck_get_session_info(CK_SESSION_HANDLE session, CK_SESSION_INFO_PTR info) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out = NULL; uint32_t session_handle = session; struct pkcs11_session_info *ta_info = NULL; size_t out_size = 0; if (!info) return CKR_ARGUMENTS_BAD; /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io2: (out) [session info] */ out = ckteec_alloc_shm(sizeof(struct pkcs11_session_info), CKTEEC_SHM_OUT); if (!out) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_SESSION_INFO, ctrl, out, &out_size); if (rv != CKR_OK || out_size != out->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto out; } ta_info = (struct pkcs11_session_info *)out->buffer; info->slotID = ta_info->slot_id; info->state = ta_info->state; info->flags = ta_info->flags; info->ulDeviceError = ta_info->device_error; out: ckteec_free_shm(ctrl); ckteec_free_shm(out); return rv; } /** * ck_init_token - Wrap C_InitToken into PKCS11_CMD_INIT_TOKEN */ CK_RV ck_init_token(CK_SLOT_ID slot, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len, CK_UTF8CHAR_PTR label) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t slot_id = slot; uint32_t pkcs11_pin_len = pin_len; size_t ctrl_size = 0; char *buf = NULL; if (!pin && pin_len) return CKR_ARGUMENTS_BAD; if (!label) return CKR_ARGUMENTS_BAD; /* Shm io0: (in/out) ctrl = [slot-id][pin_len][label][pin] / [status] */ ctrl_size = sizeof(slot_id) + sizeof(pkcs11_pin_len) + 32 * sizeof(uint8_t) + pkcs11_pin_len; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; buf = ctrl->buffer; memcpy(buf, &slot_id, sizeof(slot_id)); buf += sizeof(slot_id); memcpy(buf, &pkcs11_pin_len, sizeof(pkcs11_pin_len)); buf += sizeof(pkcs11_pin_len); memcpy(buf, label, 32 * sizeof(uint8_t)); buf += 32 * sizeof(uint8_t); memcpy(buf, pin, pkcs11_pin_len); rv = ckteec_invoke_ctrl(PKCS11_CMD_INIT_TOKEN, ctrl); ckteec_free_shm(ctrl); return rv; } /** * ck_init_pin - Wrap C_InitPIN into PKCS11_CMD_INIT_PIN */ CK_RV ck_init_pin(CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t pkcs11_session = session; uint32_t pkcs11_pin_len = pin_len; size_t ctrl_size = 0; char *buf = NULL; if (!pin && pin_len) return CKR_ARGUMENTS_BAD; /* Shm io0: (in/out) ctrl = [session][pin_len][pin] / [status] */ ctrl_size = sizeof(pkcs11_session) + sizeof(pkcs11_pin_len) + pkcs11_pin_len; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; buf = ctrl->buffer; memcpy(buf, &pkcs11_session, sizeof(pkcs11_session)); buf += sizeof(pkcs11_session); memcpy(buf, &pkcs11_pin_len, sizeof(pkcs11_pin_len)); buf += sizeof(pkcs11_pin_len); memcpy(buf, pin, pkcs11_pin_len); rv = ckteec_invoke_ctrl(PKCS11_CMD_INIT_PIN, ctrl); ckteec_free_shm(ctrl); return rv; } /** * ck_set_pin - Wrap C_SetPIN into PKCS11_CMD_SET_PIN */ CK_RV ck_set_pin(CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR old, CK_ULONG old_len, CK_UTF8CHAR_PTR new, CK_ULONG new_len) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t pkcs11_session = session; uint32_t pkcs11_old_len = old_len; uint32_t pkcs11_new_len = new_len; size_t ctrl_size = 0; char *buf; if ((!old && old_len) || (!new && new_len)) return CKR_ARGUMENTS_BAD; /* * Shm io0: (in/out) ctrl * (in) [session][old_pin_len][new_pin_len][old pin][new pin] * (out) [status] */ ctrl_size = sizeof(pkcs11_session) + sizeof(pkcs11_old_len) + sizeof(pkcs11_new_len) + pkcs11_old_len + pkcs11_new_len; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; buf = ctrl->buffer; memcpy(buf, &pkcs11_session, sizeof(pkcs11_session)); buf += sizeof(pkcs11_session); memcpy(buf, &pkcs11_old_len, sizeof(pkcs11_old_len)); buf += sizeof(pkcs11_old_len); memcpy(buf, &pkcs11_new_len, sizeof(pkcs11_new_len)); buf += sizeof(pkcs11_new_len); memcpy(buf, old, pkcs11_old_len); buf += pkcs11_old_len; memcpy(buf, new, pkcs11_new_len); rv = ckteec_invoke_ctrl(PKCS11_CMD_SET_PIN, ctrl); ckteec_free_shm(ctrl); return rv; } /** * ck_login - Wrap C_Login into PKCS11_CMD_LOGIN */ CK_RV ck_login(CK_SESSION_HANDLE session, CK_USER_TYPE user_type, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t pkcs11_session = session; uint32_t pkcs11_user = user_type; uint32_t pkcs11_pin_len = pin_len; size_t ctrl_size = 0; char *buf = NULL; if (!pin && pin_len) return CKR_ARGUMENTS_BAD; /* Shm io0: (i/o) ctrl = [session][user][pin length][pin] / [status] */ ctrl_size = sizeof(pkcs11_session) + sizeof(pkcs11_user) + sizeof(pkcs11_pin_len) + pkcs11_pin_len; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; buf = ctrl->buffer; memcpy(buf, &pkcs11_session, sizeof(pkcs11_session)); buf += sizeof(pkcs11_session); memcpy(buf, &pkcs11_user, sizeof(pkcs11_user)); buf += sizeof(pkcs11_user); memcpy(buf, &pkcs11_pin_len, sizeof(pkcs11_pin_len)); buf += sizeof(pkcs11_pin_len); memcpy(buf, pin, pkcs11_pin_len); rv = ckteec_invoke_ctrl(PKCS11_CMD_LOGIN, ctrl); ckteec_free_shm(ctrl); return rv; } /** * ck_logout - Wrap C_Logout into PKCS11_CMD_LOGOUT */ CK_RV ck_logout(CK_SESSION_HANDLE session) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t session_handle = session; /* io0 = [session-handle] */ ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); rv = ckteec_invoke_ctrl(PKCS11_CMD_LOGOUT, ctrl); ckteec_free_shm(ctrl); return rv; } CK_RV ck_seed_random(CK_SESSION_HANDLE session, CK_BYTE_PTR seed, CK_ULONG length) { CK_RV rv = CKR_GENERAL_ERROR; size_t ctrl_size = 0; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *in_shm = NULL; uint32_t session_handle = session; if (!seed && length) return CKR_ARGUMENTS_BAD; if (!seed) return CKR_OK; /* Shm io0: (i/o) [session-handle] / [status] */ ctrl_size = sizeof(session_handle); ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io1: (in) [seed data] */ in_shm = ckteec_register_shm(seed, length, CKTEEC_SHM_IN); if (!in_shm) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_in(PKCS11_CMD_SEED_RANDOM, ctrl, in_shm); out: ckteec_free_shm(in_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_generate_random(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG length) { CK_RV rv = CKR_GENERAL_ERROR; size_t ctrl_size = 0; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; uint32_t session_handle = session; size_t out_size = 0; if (!data && length) return CKR_ARGUMENTS_BAD; if (!data) return CKR_OK; /* Shm io0: (i/o) [session-handle] / [status] */ ctrl_size = sizeof(session_handle); ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io2: (out) [generated random] */ out_shm = ckteec_register_shm(data, length, CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GENERATE_RANDOM, ctrl, out_shm, &out_size); out: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); return rv; }