// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2018, Linaro Limited */ #include #include #include #include #include #include #include "pkcs11_processing.h" #include "invoke_ta.h" #include "serializer.h" #include "serialize_ck.h" CK_RV ck_create_object(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR handle) { CK_RV rv = CKR_GENERAL_ERROR; struct serializer obj = { 0 }; size_t ctrl_size = 0; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; uint32_t session_handle = session; uint32_t key_handle = 0; char *buf = NULL; size_t out_size = 0; if (!handle || !attribs || !count) return CKR_ARGUMENTS_BAD; rv = serialize_ck_attributes(&obj, attribs, count); if (rv) goto out; /* Shm io0: (i/o) [session-handle][serialized-attributes] / [status] */ ctrl_size = sizeof(session_handle) + obj.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto out; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, obj.buffer, obj.size); /* Shm io2: (out) [object handle] */ out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto out; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_CREATE_OBJECT, ctrl, out_shm, &out_size); if (rv != CKR_OK || out_size != out_shm->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto out; } memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); *handle = key_handle; out: release_serial_object(&obj); ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; size_t ctrl_size = 0; char *buf = NULL; uint32_t session_handle = session; uint32_t obj_id = obj; /* Shm io0: (i/o) ctrl = [session-handle][object-handle] / [status] */ ctrl_size = sizeof(session_handle) + sizeof(obj_id); ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &obj_id, sizeof(obj_id)); rv = ckteec_invoke_ctrl(PKCS11_CMD_DESTROY_OBJECT, ctrl); ckteec_free_shm(ctrl); return rv; } CK_RV ck_encdecrypt_init(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key, int decrypt) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; struct serializer obj = { 0 }; uint32_t session_handle = session; uint32_t key_handle = key; size_t ctrl_size = 0; char *buf = NULL; if (!mechanism) return CKR_ARGUMENTS_BAD; rv = serialize_ck_mecha_params(&obj, mechanism); if (rv) return rv; /* * Shm io0: (in/out) ctrl * (in) [session-handle][key-handle][serialized-mechanism-blob] * (out) [status] */ ctrl_size = sizeof(session_handle) + sizeof(key_handle) + obj.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &key_handle, sizeof(key_handle)); buf += sizeof(key_handle); memcpy(buf, obj.buffer, obj.size); rv = ckteec_invoke_ctrl(decrypt ? PKCS11_CMD_DECRYPT_INIT : PKCS11_CMD_ENCRYPT_INIT, ctrl); bail: ckteec_free_shm(ctrl); release_serial_object(&obj); return rv; } CK_RV ck_encdecrypt_update(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int decrypt) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *in_shm = NULL; TEEC_SharedMemory *out_shm = NULL; uint32_t session_handle = session; size_t out_size = 0; if (!out_len || (in_len && !in)) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* 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 bail; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io1: input data buffer if any */ if (in_len) { in_shm = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); if (!in_shm) { rv = CKR_HOST_MEMORY; goto bail; } } /* Shm io2: output data buffer */ if (out && out_len && *out_len) { out_shm = ckteec_register_shm(out, *out_len, CKTEEC_SHM_OUT); } else { /* Query output data size */ out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); } if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } /* Invoke */ rv = ckteec_invoke_ta(decrypt ? PKCS11_CMD_DECRYPT_UPDATE : PKCS11_CMD_ENCRYPT_UPDATE, ctrl, in_shm, out_shm, &out_size, NULL, NULL); if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) *out_len = out_size; if (rv == CKR_BUFFER_TOO_SMALL && out_size && !out) rv = CKR_OK; goto bail_invoked; bail: ck_release_active_processing(session, decrypt ? PKCS11_CMD_DECRYPT_UPDATE : PKCS11_CMD_ENCRYPT_UPDATE); bail_invoked: ckteec_free_shm(out_shm); ckteec_free_shm(in_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_encdecrypt_oneshot(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int decrypt) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *in_shm = NULL; TEEC_SharedMemory *out_shm = NULL; uint32_t session_handle = session; size_t out_size = 0; if (!out_len || (in_len && !in)) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* 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 bail; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io1: input data buffer */ in_shm = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); if (!in_shm) { rv = CKR_HOST_MEMORY; goto bail; } /* Shm io2: output data buffer */ if (out && out_len && *out_len) { out_shm = ckteec_register_shm(out, *out_len, CKTEEC_SHM_OUT); } else { /* Query output data size */ out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); } if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ta(decrypt ? PKCS11_CMD_DECRYPT_ONESHOT : PKCS11_CMD_ENCRYPT_ONESHOT, ctrl, in_shm, out_shm, &out_size, NULL, NULL); if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) *out_len = out_size; if (rv == CKR_BUFFER_TOO_SMALL && out_size && !out) rv = CKR_OK; goto bail_invoked; bail: ck_release_active_processing(session, decrypt ? PKCS11_CMD_DECRYPT_ONESHOT : PKCS11_CMD_ENCRYPT_ONESHOT); bail_invoked: ckteec_free_shm(out_shm); ckteec_free_shm(in_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_encdecrypt_final(CK_SESSION_HANDLE session, CK_BYTE_PTR out, CK_ULONG_PTR out_len, int decrypt) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; uint32_t session_handle = session; size_t out_size = 0; if (!out_len) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* 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 bail; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io2: output buffer reference */ if (out && out_len && *out_len) { out_shm = ckteec_register_shm(out, *out_len, CKTEEC_SHM_OUT); } else { /* Query output data size */ out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); } if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(decrypt ? PKCS11_CMD_DECRYPT_FINAL : PKCS11_CMD_ENCRYPT_FINAL, ctrl, out_shm, &out_size); if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) *out_len = out_size; if (rv == CKR_BUFFER_TOO_SMALL && out_size && !out) rv = CKR_OK; goto bail_invoked; bail: ck_release_active_processing(session, decrypt ? PKCS11_CMD_DECRYPT_FINAL : PKCS11_CMD_ENCRYPT_FINAL); bail_invoked: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_digest_init(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; struct serializer obj = { 0 }; uint32_t session_handle = session; size_t ctrl_size = 0; uint8_t *buf = NULL; if (!mechanism) return CKR_ARGUMENTS_BAD; rv = serialize_ck_mecha_params(&obj, mechanism); if (rv) return rv; /* * Shm io0: (in/out) ctrl * (in) [session-handle][serialized-mechanism-blob] * (out) [status] */ ctrl_size = sizeof(session_handle) + obj.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, obj.buffer, obj.size); rv = ckteec_invoke_ctrl(PKCS11_CMD_DIGEST_INIT, ctrl); bail: ckteec_free_shm(ctrl); release_serial_object(&obj); return rv; } CK_RV ck_digest_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t session_handle = session; uint32_t key_handle = key; size_t ctrl_size = 0; uint8_t *buf = NULL; /* * Shm io0: (in/out) ctrl * (in) [session-handle][key-handle] * (out) [status] */ ctrl_size = sizeof(session_handle) + sizeof(key_handle); ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &key_handle, sizeof(key_handle)); rv = ckteec_invoke_ctrl(PKCS11_CMD_DIGEST_KEY, ctrl); ckteec_free_shm(ctrl); return rv; } CK_RV ck_digest_update(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *io1 = NULL; uint32_t session_handle = session; uint8_t *buf = NULL; if (!in && in_len) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* * 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 bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); /* Shm io1: input payload */ if (in_len && in) { io1 = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); if (!io1) { rv = CKR_HOST_MEMORY; goto bail; } } rv = ckteec_invoke_ctrl_in(PKCS11_CMD_DIGEST_UPDATE, ctrl, io1); goto bail_invoked; bail: ck_release_active_processing(session, PKCS11_CMD_DIGEST_UPDATE); bail_invoked: ckteec_free_shm(io1); ckteec_free_shm(ctrl); return rv; } CK_RV ck_digest_oneshot(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR digest_ref, CK_ULONG_PTR digest_len) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *io1 = NULL; TEEC_SharedMemory *io2 = NULL; uint32_t session_handle = session; size_t out_size = 0; uint8_t *buf = NULL; if ((!in && in_len) || !digest_len) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* * 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 bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); /* Shm io1: input payload */ if (in_len && in) { io1 = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); if (!io1) { rv = CKR_HOST_MEMORY; goto bail; } } /* Shm io2: output digest or null sized shm */ if (digest_ref) { io2 = ckteec_register_shm(digest_ref, *digest_len, CKTEEC_SHM_OUT); } else { /* Query size if output signature */ io2 = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); } if (!io2) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ta(PKCS11_CMD_DIGEST_ONESHOT, ctrl, io1, io2, &out_size, NULL, NULL); if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) *digest_len = out_size; if (rv == CKR_BUFFER_TOO_SMALL && out_size && !digest_ref) rv = CKR_OK; goto bail_invoked; bail: ck_release_active_processing(session, PKCS11_CMD_DIGEST_ONESHOT); bail_invoked: ckteec_free_shm(io1); ckteec_free_shm(io2); ckteec_free_shm(ctrl); return rv; } CK_RV ck_digest_final(CK_SESSION_HANDLE session, CK_BYTE_PTR digest_ref, CK_ULONG_PTR digest_len) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *io2 = NULL; uint32_t session_handle = session; size_t io2_size = 0; uint8_t *buf = NULL; /* * - If digest_ref == NULL AND digest_len == NULL -> need to call TA to * terminate session. * - If digest_len == NULL -> need to call to TA to terminate session. * - If digest_ref == NULL BUT digest_len != NULL just operate normally * to get size of the required buffer */ if (!digest_len) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* * 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 bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); /* Shm io2: output digest or null sized shm */ if (digest_ref) io2 = ckteec_register_shm(digest_ref, *digest_len, CKTEEC_SHM_OUT); else io2 = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); if (!io2) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ta(PKCS11_CMD_DIGEST_FINAL, ctrl, NULL, io2, &io2_size, NULL, NULL); if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) *digest_len = io2_size; if (rv == CKR_BUFFER_TOO_SMALL && io2_size && !digest_ref) rv = CKR_OK; goto bail_invoked; bail: ck_release_active_processing(session, PKCS11_CMD_DIGEST_FINAL); bail_invoked: ckteec_free_shm(io2); ckteec_free_shm(ctrl); return rv; } CK_RV ck_signverify_init(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE key, int sign) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; struct serializer obj = { 0 }; uint32_t session_handle = session; uint32_t key_handle = key; size_t ctrl_size = 0; char *buf = NULL; if (!mechanism) return CKR_ARGUMENTS_BAD; rv = serialize_ck_mecha_params(&obj, mechanism); if (rv) return rv; /* * Shm io0: (in/out) ctrl * (in) [session-handle][key-handle][serialized-mechanism-blob] * (out) [status] */ ctrl_size = sizeof(session_handle) + sizeof(key_handle) + obj.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &key_handle, sizeof(key_handle)); buf += sizeof(key_handle); memcpy(buf, obj.buffer, obj.size); rv = ckteec_invoke_ctrl(sign ? PKCS11_CMD_SIGN_INIT : PKCS11_CMD_VERIFY_INIT, ctrl); bail: ckteec_free_shm(ctrl); release_serial_object(&obj); return rv; } CK_RV ck_signverify_update(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, int sign) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *in_shm = NULL; uint32_t session_handle = session; if (!in && in_len) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* 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 bail; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io1: input data */ in_shm = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); if (!in_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_in(sign ? PKCS11_CMD_SIGN_UPDATE : PKCS11_CMD_VERIFY_UPDATE, ctrl, in_shm); goto bail_invoked; bail: ck_release_active_processing(session, sign ? PKCS11_CMD_SIGN_UPDATE : PKCS11_CMD_VERIFY_UPDATE); bail_invoked: ckteec_free_shm(in_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_signverify_oneshot(CK_SESSION_HANDLE session, CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR sign_ref, CK_ULONG_PTR sign_len, int sign) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *io1 = NULL; TEEC_SharedMemory *io2 = NULL; uint32_t session_handle = session; size_t out_size = 0; if ((in_len && !in) || (!sign && sign_len && *sign_len && !sign_ref) || (sign && !sign_len)) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* 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 bail; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io1: input payload */ if (in_len) { io1 = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); if (!io1) { rv = CKR_HOST_MEMORY; goto bail; } } /* * Shm io2: input signature (if verifying) or null sized shm * or * Shm io2: output signature (if signing) or null sized shm */ if (sign_ref && sign_len && *sign_len) { io2 = ckteec_register_shm(sign_ref, *sign_len, sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN); } else { /* Query size if output signature */ io2 = ckteec_alloc_shm(0, sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN); } if (!io2) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ta(sign ? PKCS11_CMD_SIGN_ONESHOT : PKCS11_CMD_VERIFY_ONESHOT, ctrl, io1, io2, &out_size, NULL, NULL); if (sign && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) *sign_len = out_size; if (rv == CKR_BUFFER_TOO_SMALL && out_size && !sign_ref) rv = CKR_OK; goto bail_invoked; bail: ck_release_active_processing(session, sign ? PKCS11_CMD_SIGN_ONESHOT : PKCS11_CMD_VERIFY_ONESHOT); bail_invoked: ckteec_free_shm(io1); ckteec_free_shm(io2); ckteec_free_shm(ctrl); return rv; } CK_RV ck_signverify_final(CK_SESSION_HANDLE session, CK_BYTE_PTR sign_ref, CK_ULONG_PTR sign_len, int sign) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *io = NULL; uint32_t session_handle = session; size_t io_size = 0; if ((!sign && sign_len && *sign_len && !sign_ref) || (sign && !sign_len)) { rv = CKR_ARGUMENTS_BAD; goto bail; } /* 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 bail; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* * Shm io1: input signature (if verifying) or null sized shm * or * Shm io1: output signature (if signing) or null sized shm */ if (sign_ref && sign_len && *sign_len) io = ckteec_register_shm(sign_ref, *sign_len, sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN); else io = ckteec_alloc_shm(0, sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN); if (!io) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ta(sign ? PKCS11_CMD_SIGN_FINAL : PKCS11_CMD_VERIFY_FINAL, ctrl, NULL, io, &io_size, NULL, NULL); if (sign && sign_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) *sign_len = io_size; if (rv == CKR_BUFFER_TOO_SMALL && io_size && !sign_ref) rv = CKR_OK; goto bail_invoked; bail: ck_release_active_processing(session, sign ? PKCS11_CMD_SIGN_FINAL : PKCS11_CMD_VERIFY_FINAL); bail_invoked: ckteec_free_shm(io); ckteec_free_shm(ctrl); return rv; } CK_RV ck_generate_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR handle) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; struct serializer smecha = { 0 }; struct serializer sattr = { 0 }; uint32_t session_handle = session; size_t ctrl_size = 0; uint32_t key_handle = 0; char *buf = NULL; size_t out_size = 0; if (!handle || !mechanism || (count && !attribs)) return CKR_ARGUMENTS_BAD; rv = serialize_ck_mecha_params(&smecha, mechanism); if (rv) return rv; rv = serialize_ck_attributes(&sattr, attribs, count); if (rv) goto bail; /* * Shm io0: (in/out) ctrl * (in) [session-handle][serialized-mecha][serialized-attributes] * (out) [status] */ ctrl_size = sizeof(session_handle) + smecha.size + sattr.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, smecha.buffer, smecha.size); buf += smecha.size; memcpy(buf, sattr.buffer, sattr.size); /* Shm io2: (out) [object handle] */ out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GENERATE_KEY, ctrl, out_shm, &out_size); if (rv != CKR_OK || out_size != out_shm->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto bail; } memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); *handle = key_handle; bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); release_serial_object(&sattr); release_serial_object(&smecha); return rv; } CK_RV ck_find_objects_init(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR attribs, CK_ULONG count) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t session_handle = session; struct serializer obj = { 0 }; size_t ctrl_size = 0; char *buf = NULL; if (count && !attribs) return CKR_ARGUMENTS_BAD; rv = serialize_ck_attributes(&obj, attribs, count); if (rv) return rv; /* Shm io0: (in/out) ctrl * (in) [session-handle][headed-serialized-attributes] * (out) [status] */ ctrl_size = sizeof(session_handle) + obj.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, obj.buffer, obj.size); rv = ckteec_invoke_ctrl(PKCS11_CMD_FIND_OBJECTS_INIT, ctrl); bail: ckteec_free_shm(ctrl); release_serial_object(&obj); return rv; } CK_RV ck_find_objects(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE_PTR obj, CK_ULONG max_count, CK_ULONG_PTR count) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; uint32_t session_handle = session; uint32_t *handles = NULL; size_t handles_size = max_count * sizeof(uint32_t); CK_ULONG n = 0; CK_ULONG last = 0; size_t out_size = 0; if (!count || (max_count && !obj)) 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 bail; } memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); /* Shm io2: (out) [object handle list] */ out_shm = ckteec_alloc_shm(handles_size, CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_FIND_OBJECTS, ctrl, out_shm, &out_size); if (rv || out_size > out_shm->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto bail; } handles = out_shm->buffer; last = out_size / sizeof(uint32_t); *count = last; for (n = 0; n < last; n++) obj[n] = handles[n]; bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_find_objects_final(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) return CKR_HOST_MEMORY; memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); rv = ckteec_invoke_ctrl(PKCS11_CMD_FIND_OBJECTS_FINAL, ctrl); ckteec_free_shm(ctrl); return rv; } CK_RV ck_get_object_size(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, CK_ULONG_PTR p_size) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; size_t ctrl_size = 0; uint32_t session_handle = session; uint32_t obj_handle = obj; char *buf = NULL; size_t out_size = 0; uint32_t u32_sz = 0; if (!p_size) return CKR_ARGUMENTS_BAD; /* Shm io0: (in/out) [session][obj-handle] / [status] */ ctrl_size = sizeof(session_handle) + sizeof(obj_handle); ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &obj_handle, sizeof(obj_handle)); /* Shm io2: (out) [object size] */ out_shm = ckteec_alloc_shm(sizeof(uint32_t), CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GET_OBJECT_SIZE, ctrl, out_shm, &out_size); if (rv) goto bail; if (out_shm->size != sizeof(uint32_t)) { rv = CKR_DEVICE_ERROR; goto bail; } memcpy(&u32_sz, out_shm->buffer, out_shm->size); *p_size = u32_sz; bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); return rv; } CK_RV ck_get_attribute_value(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR attribs, CK_ULONG count) { CK_RV rv = CKR_GENERAL_ERROR; CK_RV rv2 = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; struct serializer sattr = { 0 }; size_t ctrl_size = 0; uint32_t session_handle = session; uint32_t obj_handle = obj; char *buf = NULL; size_t out_size = 0; if (count && !attribs) return CKR_ARGUMENTS_BAD; rv = serialize_ck_attributes(&sattr, attribs, count); if (rv) goto bail; /* Shm io0: (in/out) [session][obj-handle][attributes] / [status] */ ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + sattr.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &obj_handle, sizeof(obj_handle)); buf += sizeof(obj_handle); memcpy(buf, sattr.buffer, sattr.size); /* Shm io2: (out) [attributes] */ out_shm = ckteec_alloc_shm(sattr.size, CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GET_ATTRIBUTE_VALUE, ctrl, out_shm, &out_size); if (rv == CKR_OK || rv == CKR_ATTRIBUTE_SENSITIVE || rv == CKR_ATTRIBUTE_TYPE_INVALID || rv == CKR_BUFFER_TOO_SMALL) { rv2 = deserialize_ck_attributes(out_shm->buffer, attribs, count); if (rv2) rv = CKR_GENERAL_ERROR; } bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); release_serial_object(&sattr); return rv; } CK_RV ck_set_attribute_value(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR attribs, CK_ULONG count) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; struct serializer sattr = { 0 }; size_t ctrl_size = 0; uint32_t session_handle = session; uint32_t obj_handle = obj; char *buf = NULL; if (count && !attribs) return CKR_ARGUMENTS_BAD; rv = serialize_ck_attributes(&sattr, attribs, count); if (rv) goto bail; /* Shm io0: (in/out) [session][obj-handle][attributes] / [status] */ ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + sattr.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &obj_handle, sizeof(obj_handle)); buf += sizeof(obj_handle); memcpy(buf, sattr.buffer, sattr.size); rv = ckteec_invoke_ctrl(PKCS11_CMD_SET_ATTRIBUTE_VALUE, ctrl); bail: ckteec_free_shm(ctrl); release_serial_object(&sattr); return rv; } CK_RV ck_copy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR handle) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; struct serializer sattr = { 0 }; size_t ctrl_size = 0; uint32_t session_handle = session; uint32_t obj_handle = obj; uint32_t key_handle = 0; char *buf = NULL; size_t out_size = 0; if (!handle || (count && !attribs)) return CKR_ARGUMENTS_BAD; rv = serialize_ck_attributes(&sattr, attribs, count); if (rv) goto bail; /* Shm io0: (in/out) [session][obj-handle][attributes] / [status] */ ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + sattr.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &obj_handle, sizeof(obj_handle)); buf += sizeof(obj_handle); memcpy(buf, sattr.buffer, sattr.size); /* Shm io2: (out) [object handle] */ out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_COPY_OBJECT, ctrl, out_shm, &out_size); if (rv != CKR_OK || out_size != out_shm->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto bail; } memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); *handle = key_handle; bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); release_serial_object(&sattr); return rv; } CK_RV ck_derive_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE parent_key, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR handle) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; struct serializer smecha = { 0 }; struct serializer sattr = { 0 }; uint32_t session_handle = session; uint32_t obj_handle = parent_key; size_t ctrl_size = 0; uint32_t key_handle = 0; char *buf = NULL; size_t out_size = 0; if (!handle || !mechanism || (count && !attribs)) return CKR_ARGUMENTS_BAD; rv = serialize_ck_mecha_params(&smecha, mechanism); if (rv) return rv; rv = serialize_ck_attributes(&sattr, attribs, count); if (rv) goto bail; /* * Shm io0: (in/out) ctrl * (in) [session-handle][obj-handle][serialized-mecha][serialized-attributes] * (out) [status] */ ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + smecha.size + sattr.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &obj_handle, sizeof(obj_handle)); buf += sizeof(obj_handle); memcpy(buf, smecha.buffer, smecha.size); buf += smecha.size; memcpy(buf, sattr.buffer, sattr.size); /* Shm io2: (out) [object handle] */ out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_DERIVE_KEY, ctrl, out_shm, &out_size); if (rv != CKR_OK || out_size != out_shm->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto bail; } memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); *handle = key_handle; bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); release_serial_object(&sattr); release_serial_object(&smecha); return rv; } CK_RV ck_release_active_processing(CK_SESSION_HANDLE session, enum pkcs11_ta_cmd command) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; uint32_t session_handle = session; uint32_t cmd = command; size_t ctrl_size = 0; char *buf = NULL; /* Shm io0: (in/out) ctrl = [session-handle][command] / [status] */ ctrl_size = sizeof(session_handle) + sizeof(cmd); ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) return CKR_HOST_MEMORY; buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &cmd, sizeof(cmd)); rv = ckteec_invoke_ctrl(PKCS11_CMD_RELEASE_ACTIVE_PROCESSING, ctrl); ckteec_free_shm(ctrl); return rv; } CK_RV ck_generate_key_pair(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_ATTRIBUTE_PTR pub_attribs, CK_ULONG pub_count, CK_ATTRIBUTE_PTR priv_attribs, CK_ULONG priv_count, CK_OBJECT_HANDLE_PTR pub_key, CK_OBJECT_HANDLE_PTR priv_key) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; struct serializer smecha = { 0 }; struct serializer pub_sattr = { 0 }; struct serializer priv_sattr = { 0 }; uint32_t session_handle = session; size_t ctrl_size = 0; uint32_t *key_handle = NULL; size_t key_handle_size = 2 * sizeof(*key_handle); char *buf = NULL; size_t out_size = 0; if (!(mechanism && pub_attribs && priv_attribs && pub_key && priv_key)) return CKR_ARGUMENTS_BAD; rv = serialize_ck_mecha_params(&smecha, mechanism); if (rv) return rv; rv = serialize_ck_attributes(&pub_sattr, pub_attribs, pub_count); if (rv) goto bail; rv = serialize_ck_attributes(&priv_sattr, priv_attribs, priv_count); if (rv) goto bail; /* * Shm io0: (in/out) ctrl * (in) [session-handle][serialized-mecha][serialized-pub_attribs] * [serialized-priv_attribs] * (out) [status] */ ctrl_size = sizeof(session_handle) + smecha.size + pub_sattr.size + priv_sattr.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, smecha.buffer, smecha.size); buf += smecha.size; memcpy(buf, pub_sattr.buffer, pub_sattr.size); buf += pub_sattr.size; memcpy(buf, priv_sattr.buffer, priv_sattr.size); /* * Shm io2: (out) public key object handle][private key object handle] */ out_shm = ckteec_alloc_shm(key_handle_size, CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GENERATE_KEY_PAIR, ctrl, out_shm, &out_size); if (rv != CKR_OK || out_size != out_shm->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto bail; } key_handle = out_shm->buffer; *pub_key = key_handle[0]; *priv_key = key_handle[1]; bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); release_serial_object(&priv_sattr); release_serial_object(&pub_sattr); release_serial_object(&smecha); return rv; } CK_RV ck_wrap_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *out_shm = NULL; struct serializer smecha = { 0 }; uint32_t session_handle = session; uint32_t wrp_key_handle = wrapping_key; uint32_t key_handle = key; size_t ctrl_size = 0; size_t out_size = 0; char *buf = NULL; if (!mechanism || !wrapped_key_len) return CKR_ARGUMENTS_BAD; rv = serialize_ck_mecha_params(&smecha, mechanism); if (rv) return rv; /* * Shm io0: (in/out) ctrl * (in) [session-handle][wrapping-key-handle][key-handle] * [serialized-mecha] * (out) [status] */ ctrl_size = sizeof(session_handle) + sizeof(wrp_key_handle) + sizeof(key_handle) + smecha.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &wrp_key_handle, sizeof(wrp_key_handle)); buf += sizeof(wrp_key_handle); memcpy(buf, &key_handle, sizeof(key_handle)); buf += sizeof(key_handle); memcpy(buf, smecha.buffer, smecha.size); /* Shm io2: output buffer reference - wrapped key */ if (wrapped_key && *wrapped_key_len) out_shm = ckteec_register_shm(wrapped_key, *wrapped_key_len, CKTEEC_SHM_OUT); else /* Query output data size */ out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ctrl_out(PKCS11_CMD_WRAP_KEY, ctrl, out_shm, &out_size); if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) *wrapped_key_len = out_size; if (rv == CKR_BUFFER_TOO_SMALL && out_size && !wrapped_key) rv = CKR_OK; bail: ckteec_free_shm(out_shm); ckteec_free_shm(ctrl); release_serial_object(&smecha); return rv; } CK_RV ck_unwrap_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key, CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR attribs, CK_ULONG count, CK_OBJECT_HANDLE_PTR handle) { CK_RV rv = CKR_GENERAL_ERROR; TEEC_SharedMemory *ctrl = NULL; TEEC_SharedMemory *in_shm = NULL; TEEC_SharedMemory *out_shm = NULL; struct serializer smecha = { 0 }; struct serializer sattr = { 0 }; uint32_t session_handle = session; uint32_t unwrapping_key_handle = unwrapping_key; size_t ctrl_size = 0; uint32_t key_handle = 0; char *buf = NULL; size_t out_size = 0; if (!handle || !mechanism || (count && !attribs) || (wrapped_key_len && !wrapped_key)) return CKR_ARGUMENTS_BAD; if (!unwrapping_key) return CKR_UNWRAPPING_KEY_HANDLE_INVALID; rv = serialize_ck_mecha_params(&smecha, mechanism); if (rv) return rv; rv = serialize_ck_attributes(&sattr, attribs, count); if (rv) goto bail; /* * Shm io0: (in/out) ctrl * (in) [session-handle][unwrapping-key-handle][serialized-mecha] * [serialized-attributes] * (out) [status] */ ctrl_size = sizeof(session_handle) + sizeof(unwrapping_key_handle) + smecha.size + sattr.size; ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); if (!ctrl) { rv = CKR_HOST_MEMORY; goto bail; } buf = ctrl->buffer; memcpy(buf, &session_handle, sizeof(session_handle)); buf += sizeof(session_handle); memcpy(buf, &unwrapping_key_handle, sizeof(unwrapping_key_handle)); buf += sizeof(unwrapping_key_handle); memcpy(buf, smecha.buffer, smecha.size); buf += smecha.size; memcpy(buf, sattr.buffer, sattr.size); /* Shm io1: input - wrapped key buffer */ in_shm = ckteec_register_shm(wrapped_key, wrapped_key_len, CKTEEC_SHM_IN); if (!in_shm) { rv = CKR_HOST_MEMORY; goto bail; } /* Shm io2: (out) [object handle] */ out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); if (!out_shm) { rv = CKR_HOST_MEMORY; goto bail; } rv = ckteec_invoke_ta(PKCS11_CMD_UNWRAP_KEY, ctrl, in_shm, out_shm, &out_size, NULL, NULL); if (rv != CKR_OK || out_size != out_shm->size) { if (rv == CKR_OK) rv = CKR_DEVICE_ERROR; goto bail; } memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); *handle = key_handle; bail: ckteec_free_shm(out_shm); ckteec_free_shm(in_shm); ckteec_free_shm(ctrl); release_serial_object(&sattr); release_serial_object(&smecha); return rv; }