| // SPDX-License-Identifier: BSD-2-Clause |
| /* |
| * Copyright (c) 2017-2018, Linaro Limited |
| */ |
| |
| #include <pkcs11.h> |
| #include <pkcs11_ta.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <tee_client_api.h> |
| |
| #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 */ |
| if (in) { |
| 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; |
| } |