1512cbf1dSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2512cbf1dSJens Wiklander /*
3512cbf1dSJens Wiklander * Copyright (c) 2017-2020, Linaro Limited
4512cbf1dSJens Wiklander */
5512cbf1dSJens Wiklander
6512cbf1dSJens Wiklander #include <assert.h>
7512cbf1dSJens Wiklander #include <pkcs11_ta.h>
8512cbf1dSJens Wiklander #include <string.h>
9512cbf1dSJens Wiklander #include <tee_api_defines.h>
10512cbf1dSJens Wiklander #include <tee_internal_api.h>
11512cbf1dSJens Wiklander #include <tee_internal_api_extensions.h>
12512cbf1dSJens Wiklander #include <util.h>
13512cbf1dSJens Wiklander
14512cbf1dSJens Wiklander #include "attributes.h"
15512cbf1dSJens Wiklander #include "object.h"
16512cbf1dSJens Wiklander #include "pkcs11_attributes.h"
17512cbf1dSJens Wiklander #include "pkcs11_helpers.h"
18512cbf1dSJens Wiklander #include "pkcs11_token.h"
19512cbf1dSJens Wiklander #include "processing.h"
20512cbf1dSJens Wiklander #include "serializer.h"
21512cbf1dSJens Wiklander
get_ready_session(struct pkcs11_session * session)22512cbf1dSJens Wiklander static enum pkcs11_rc get_ready_session(struct pkcs11_session *session)
23512cbf1dSJens Wiklander {
24512cbf1dSJens Wiklander if (session_is_active(session))
25512cbf1dSJens Wiklander return PKCS11_CKR_OPERATION_ACTIVE;
26512cbf1dSJens Wiklander
27512cbf1dSJens Wiklander return PKCS11_CKR_OK;
28512cbf1dSJens Wiklander }
29512cbf1dSJens Wiklander
func_for_cmd(enum pkcs11_ta_cmd cmd)30eb6141b6SVesa Jääskeläinen static enum processing_func func_for_cmd(enum pkcs11_ta_cmd cmd)
31eb6141b6SVesa Jääskeläinen {
32eb6141b6SVesa Jääskeläinen switch (cmd) {
33eb6141b6SVesa Jääskeläinen case PKCS11_CMD_ENCRYPT_UPDATE:
34eb6141b6SVesa Jääskeläinen case PKCS11_CMD_ENCRYPT_ONESHOT:
35eb6141b6SVesa Jääskeläinen case PKCS11_CMD_ENCRYPT_FINAL:
36eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_ENCRYPT;
37eb6141b6SVesa Jääskeläinen case PKCS11_CMD_DECRYPT_UPDATE:
38eb6141b6SVesa Jääskeläinen case PKCS11_CMD_DECRYPT_ONESHOT:
39eb6141b6SVesa Jääskeläinen case PKCS11_CMD_DECRYPT_FINAL:
40eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_DECRYPT;
41eb6141b6SVesa Jääskeläinen case PKCS11_CMD_SIGN_ONESHOT:
42eb6141b6SVesa Jääskeläinen case PKCS11_CMD_SIGN_UPDATE:
43eb6141b6SVesa Jääskeläinen case PKCS11_CMD_SIGN_FINAL:
44eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_SIGN;
45eb6141b6SVesa Jääskeläinen case PKCS11_CMD_VERIFY_ONESHOT:
46eb6141b6SVesa Jääskeläinen case PKCS11_CMD_VERIFY_UPDATE:
47eb6141b6SVesa Jääskeläinen case PKCS11_CMD_VERIFY_FINAL:
48eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_VERIFY;
499e91a619SVesa Jääskeläinen case PKCS11_CMD_DIGEST_UPDATE:
509e91a619SVesa Jääskeläinen case PKCS11_CMD_DIGEST_KEY:
519e91a619SVesa Jääskeläinen case PKCS11_CMD_DIGEST_ONESHOT:
529e91a619SVesa Jääskeläinen case PKCS11_CMD_DIGEST_FINAL:
539e91a619SVesa Jääskeläinen return PKCS11_FUNCTION_DIGEST;
54eb6141b6SVesa Jääskeläinen default:
55eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_UNKNOWN;
56eb6141b6SVesa Jääskeläinen }
57eb6141b6SVesa Jääskeläinen }
58eb6141b6SVesa Jääskeläinen
func_matches_state(enum processing_func function,enum pkcs11_proc_state state)59512cbf1dSJens Wiklander static bool func_matches_state(enum processing_func function,
60512cbf1dSJens Wiklander enum pkcs11_proc_state state)
61512cbf1dSJens Wiklander {
62512cbf1dSJens Wiklander switch (function) {
63512cbf1dSJens Wiklander case PKCS11_FUNCTION_ENCRYPT:
64512cbf1dSJens Wiklander return state == PKCS11_SESSION_ENCRYPTING ||
65512cbf1dSJens Wiklander state == PKCS11_SESSION_DIGESTING_ENCRYPTING ||
66512cbf1dSJens Wiklander state == PKCS11_SESSION_SIGNING_ENCRYPTING;
67512cbf1dSJens Wiklander case PKCS11_FUNCTION_DECRYPT:
68512cbf1dSJens Wiklander return state == PKCS11_SESSION_DECRYPTING ||
69512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_DIGESTING ||
70512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_VERIFYING;
71512cbf1dSJens Wiklander case PKCS11_FUNCTION_DIGEST:
72512cbf1dSJens Wiklander return state == PKCS11_SESSION_DIGESTING ||
73512cbf1dSJens Wiklander state == PKCS11_SESSION_DIGESTING_ENCRYPTING;
74512cbf1dSJens Wiklander case PKCS11_FUNCTION_SIGN:
75512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING ||
76512cbf1dSJens Wiklander state == PKCS11_SESSION_SIGNING_ENCRYPTING;
77512cbf1dSJens Wiklander case PKCS11_FUNCTION_VERIFY:
78512cbf1dSJens Wiklander return state == PKCS11_SESSION_VERIFYING ||
79512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_VERIFYING;
80512cbf1dSJens Wiklander case PKCS11_FUNCTION_SIGN_RECOVER:
81512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING_RECOVER;
82512cbf1dSJens Wiklander case PKCS11_FUNCTION_VERIFY_RECOVER:
83512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING_RECOVER;
84512cbf1dSJens Wiklander default:
85512cbf1dSJens Wiklander TEE_Panic(function);
86512cbf1dSJens Wiklander return false;
87512cbf1dSJens Wiklander }
88512cbf1dSJens Wiklander }
89512cbf1dSJens Wiklander
get_active_session(struct pkcs11_session * session,enum processing_func function)90512cbf1dSJens Wiklander static enum pkcs11_rc get_active_session(struct pkcs11_session *session,
91512cbf1dSJens Wiklander enum processing_func function)
92512cbf1dSJens Wiklander {
93512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED;
94512cbf1dSJens Wiklander
95512cbf1dSJens Wiklander if (session->processing &&
96512cbf1dSJens Wiklander func_matches_state(function, session->processing->state))
97512cbf1dSJens Wiklander rc = PKCS11_CKR_OK;
98512cbf1dSJens Wiklander
99512cbf1dSJens Wiklander return rc;
100512cbf1dSJens Wiklander }
101512cbf1dSJens Wiklander
release_active_processing(struct pkcs11_session * session)102512cbf1dSJens Wiklander void release_active_processing(struct pkcs11_session *session)
103512cbf1dSJens Wiklander {
104512cbf1dSJens Wiklander if (!session->processing)
105512cbf1dSJens Wiklander return;
106512cbf1dSJens Wiklander
107*63778faaSEtienne Carriere switch (session->processing->mecha_type) {
108*63778faaSEtienne Carriere case PKCS11_CKM_AES_GCM:
109*63778faaSEtienne Carriere tee_release_gcm_operation(session);
110*63778faaSEtienne Carriere break;
111*63778faaSEtienne Carriere default:
112*63778faaSEtienne Carriere break;
113*63778faaSEtienne Carriere }
114*63778faaSEtienne Carriere
115512cbf1dSJens Wiklander if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
116512cbf1dSJens Wiklander TEE_FreeOperation(session->processing->tee_op_handle);
117512cbf1dSJens Wiklander session->processing->tee_op_handle = TEE_HANDLE_NULL;
118512cbf1dSJens Wiklander }
119512cbf1dSJens Wiklander
120*63778faaSEtienne Carriere if (session->processing->tee_op_handle2 != TEE_HANDLE_NULL) {
121*63778faaSEtienne Carriere TEE_FreeOperation(session->processing->tee_op_handle2);
122*63778faaSEtienne Carriere session->processing->tee_op_handle2 = TEE_HANDLE_NULL;
123*63778faaSEtienne Carriere }
124*63778faaSEtienne Carriere
1252158ea6cSRuchika Gupta TEE_Free(session->processing->extra_ctx);
1262158ea6cSRuchika Gupta
127512cbf1dSJens Wiklander TEE_Free(session->processing);
128512cbf1dSJens Wiklander session->processing = NULL;
129512cbf1dSJens Wiklander }
130512cbf1dSJens Wiklander
get_object_key_bit_size(struct pkcs11_object * obj)131512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj)
132512cbf1dSJens Wiklander {
133fb279d8bSVesa Jääskeläinen void *a_ptr = NULL;
134512cbf1dSJens Wiklander uint32_t a_size = 0;
135512cbf1dSJens Wiklander struct obj_attrs *attrs = obj->attributes;
136512cbf1dSJens Wiklander
137512cbf1dSJens Wiklander switch (get_key_type(attrs)) {
138512cbf1dSJens Wiklander case PKCS11_CKK_AES:
139689f4e5bSRuchika Gupta case PKCS11_CKK_GENERIC_SECRET:
140689f4e5bSRuchika Gupta case PKCS11_CKK_MD5_HMAC:
141689f4e5bSRuchika Gupta case PKCS11_CKK_SHA_1_HMAC:
142689f4e5bSRuchika Gupta case PKCS11_CKK_SHA224_HMAC:
143689f4e5bSRuchika Gupta case PKCS11_CKK_SHA256_HMAC:
144689f4e5bSRuchika Gupta case PKCS11_CKK_SHA384_HMAC:
145689f4e5bSRuchika Gupta case PKCS11_CKK_SHA512_HMAC:
146512cbf1dSJens Wiklander if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
147512cbf1dSJens Wiklander return 0;
148512cbf1dSJens Wiklander
149512cbf1dSJens Wiklander return a_size * 8;
1500442c956SVesa Jääskeläinen case PKCS11_CKK_RSA:
1510442c956SVesa Jääskeläinen if (get_attribute_ptr(attrs, PKCS11_CKA_MODULUS, NULL, &a_size))
1520442c956SVesa Jääskeläinen return 0;
1530442c956SVesa Jääskeläinen
1540442c956SVesa Jääskeläinen return a_size * 8;
155fb279d8bSVesa Jääskeläinen case PKCS11_CKK_EC:
156fb279d8bSVesa Jääskeläinen if (get_attribute_ptr(attrs, PKCS11_CKA_EC_PARAMS,
157fb279d8bSVesa Jääskeläinen &a_ptr, &a_size) || !a_ptr)
158fb279d8bSVesa Jääskeläinen return 0;
159fb279d8bSVesa Jääskeläinen
160fb279d8bSVesa Jääskeläinen return ec_params2tee_keysize(a_ptr, a_size);
161ecd7f426SValerii Chubar case PKCS11_CKK_EC_EDWARDS:
162ecd7f426SValerii Chubar if (get_attribute_ptr(attrs, PKCS11_CKA_EC_POINT, NULL,
163ecd7f426SValerii Chubar &a_size))
164ecd7f426SValerii Chubar return 0;
165ecd7f426SValerii Chubar
166ecd7f426SValerii Chubar return a_size * 8;
167512cbf1dSJens Wiklander default:
168512cbf1dSJens Wiklander TEE_Panic(0);
169512cbf1dSJens Wiklander return 0;
170512cbf1dSJens Wiklander }
171512cbf1dSJens Wiklander }
172512cbf1dSJens Wiklander
generate_random_key_value(struct obj_attrs ** head)173fa247a2aSRuchika Gupta static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
174fa247a2aSRuchika Gupta {
175fa247a2aSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
176fa247a2aSRuchika Gupta uint32_t data_size = 0;
177fa247a2aSRuchika Gupta uint32_t value_len = 0;
178fa247a2aSRuchika Gupta void *value = NULL;
179bcac2127SMarouene Boubakri void *data = NULL;
180fa247a2aSRuchika Gupta
181fa247a2aSRuchika Gupta if (!*head)
182fa247a2aSRuchika Gupta return PKCS11_CKR_TEMPLATE_INCONSISTENT;
183fa247a2aSRuchika Gupta
184fa247a2aSRuchika Gupta rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size);
185fa247a2aSRuchika Gupta if (rc || data_size != sizeof(uint32_t)) {
186fa247a2aSRuchika Gupta DMSG("%s", rc ? "No attribute value_len found" :
187fa247a2aSRuchika Gupta "Invalid size for attribute VALUE_LEN");
188fa247a2aSRuchika Gupta
189fa247a2aSRuchika Gupta return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
190fa247a2aSRuchika Gupta }
191fa247a2aSRuchika Gupta TEE_MemMove(&value_len, data, data_size);
192fa247a2aSRuchika Gupta
193fa247a2aSRuchika Gupta /* Remove the default empty value attribute if found */
194fa247a2aSRuchika Gupta rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
195fa247a2aSRuchika Gupta if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
196fa247a2aSRuchika Gupta return PKCS11_CKR_GENERAL_ERROR;
197fa247a2aSRuchika Gupta
198fa247a2aSRuchika Gupta value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
199fa247a2aSRuchika Gupta if (!value)
200fa247a2aSRuchika Gupta return PKCS11_CKR_DEVICE_MEMORY;
201fa247a2aSRuchika Gupta
202fa247a2aSRuchika Gupta TEE_GenerateRandom(value, value_len);
203fa247a2aSRuchika Gupta
204fa247a2aSRuchika Gupta rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
205fa247a2aSRuchika Gupta
206bcac2127SMarouene Boubakri if (rc == PKCS11_CKR_OK)
207bcac2127SMarouene Boubakri rc = set_check_value_attr(head);
208bcac2127SMarouene Boubakri
209fa247a2aSRuchika Gupta TEE_Free(value);
210fa247a2aSRuchika Gupta
211fa247a2aSRuchika Gupta return rc;
212fa247a2aSRuchika Gupta }
213fa247a2aSRuchika Gupta
entry_generate_secret(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)214fa247a2aSRuchika Gupta enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
215fa247a2aSRuchika Gupta uint32_t ptypes, TEE_Param *params)
216fa247a2aSRuchika Gupta {
217fa247a2aSRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
218fa247a2aSRuchika Gupta TEE_PARAM_TYPE_NONE,
219fa247a2aSRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT,
220fa247a2aSRuchika Gupta TEE_PARAM_TYPE_NONE);
221fa247a2aSRuchika Gupta TEE_Param *ctrl = params;
222fa247a2aSRuchika Gupta TEE_Param *out = params + 2;
223fa247a2aSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
224fa247a2aSRuchika Gupta struct serialargs ctrlargs = { };
225fa247a2aSRuchika Gupta struct pkcs11_session *session = NULL;
226fa247a2aSRuchika Gupta struct pkcs11_attribute_head *proc_params = NULL;
227fa247a2aSRuchika Gupta struct obj_attrs *head = NULL;
228fa247a2aSRuchika Gupta struct pkcs11_object_head *template = NULL;
229fa247a2aSRuchika Gupta size_t template_size = 0;
230fa247a2aSRuchika Gupta uint32_t obj_handle = 0;
231fa247a2aSRuchika Gupta
232fa247a2aSRuchika Gupta if (!client || ptypes != exp_pt ||
233fa247a2aSRuchika Gupta out->memref.size != sizeof(obj_handle))
234fa247a2aSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
235fa247a2aSRuchika Gupta
236fa247a2aSRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
237fa247a2aSRuchika Gupta
238fa247a2aSRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
239fa247a2aSRuchika Gupta if (rc)
240fa247a2aSRuchika Gupta return rc;
241fa247a2aSRuchika Gupta
242fa247a2aSRuchika Gupta rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
243fa247a2aSRuchika Gupta if (rc)
244fa247a2aSRuchika Gupta goto out;
245fa247a2aSRuchika Gupta
246fa247a2aSRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
247fa247a2aSRuchika Gupta if (rc)
248fa247a2aSRuchika Gupta goto out;
249fa247a2aSRuchika Gupta
250fa247a2aSRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) {
251fa247a2aSRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD;
252fa247a2aSRuchika Gupta goto out;
253fa247a2aSRuchika Gupta }
254fa247a2aSRuchika Gupta
255fa247a2aSRuchika Gupta rc = get_ready_session(session);
256fa247a2aSRuchika Gupta if (rc)
257fa247a2aSRuchika Gupta goto out;
258fa247a2aSRuchika Gupta
259fa247a2aSRuchika Gupta template_size = sizeof(*template) + template->attrs_size;
260fa247a2aSRuchika Gupta
261fa247a2aSRuchika Gupta rc = check_mechanism_against_processing(session, proc_params->id,
262fa247a2aSRuchika Gupta PKCS11_FUNCTION_GENERATE,
263fa247a2aSRuchika Gupta PKCS11_FUNC_STEP_INIT);
264fa247a2aSRuchika Gupta if (rc) {
265fa247a2aSRuchika Gupta DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
266fa247a2aSRuchika Gupta goto out;
267fa247a2aSRuchika Gupta }
268fa247a2aSRuchika Gupta
269fa247a2aSRuchika Gupta /*
270fa247a2aSRuchika Gupta * Prepare a clean initial state for the requested object attributes.
271fa247a2aSRuchika Gupta * Free temporary template once done.
272fa247a2aSRuchika Gupta */
273fa247a2aSRuchika Gupta rc = create_attributes_from_template(&head, template, template_size,
274fa247a2aSRuchika Gupta NULL, PKCS11_FUNCTION_GENERATE,
2754cfce748SRuchika Gupta proc_params->id,
2764cfce748SRuchika Gupta PKCS11_CKO_UNDEFINED_ID);
277fa247a2aSRuchika Gupta if (rc)
278fa247a2aSRuchika Gupta goto out;
279fa247a2aSRuchika Gupta
280fa247a2aSRuchika Gupta TEE_Free(template);
281fa247a2aSRuchika Gupta template = NULL;
282fa247a2aSRuchika Gupta
283fa247a2aSRuchika Gupta rc = check_created_attrs(head, NULL);
284fa247a2aSRuchika Gupta if (rc)
285fa247a2aSRuchika Gupta goto out;
286fa247a2aSRuchika Gupta
287fa247a2aSRuchika Gupta rc = check_created_attrs_against_processing(proc_params->id, head);
288fa247a2aSRuchika Gupta if (rc)
289fa247a2aSRuchika Gupta goto out;
290fa247a2aSRuchika Gupta
291fa247a2aSRuchika Gupta rc = check_created_attrs_against_token(session, head);
292fa247a2aSRuchika Gupta if (rc)
293fa247a2aSRuchika Gupta goto out;
294fa247a2aSRuchika Gupta
295fa247a2aSRuchika Gupta /*
296fa247a2aSRuchika Gupta * Execute target processing and add value as attribute
297fa247a2aSRuchika Gupta * PKCS11_CKA_VALUE. Symm key generation: depends on target
298fa247a2aSRuchika Gupta * processing to be used.
299fa247a2aSRuchika Gupta */
300fa247a2aSRuchika Gupta switch (proc_params->id) {
301fa247a2aSRuchika Gupta case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
302fa247a2aSRuchika Gupta case PKCS11_CKM_AES_KEY_GEN:
303fa247a2aSRuchika Gupta /* Generate random of size specified by attribute VALUE_LEN */
304fa247a2aSRuchika Gupta rc = generate_random_key_value(&head);
305fa247a2aSRuchika Gupta if (rc)
306fa247a2aSRuchika Gupta goto out;
307fa247a2aSRuchika Gupta break;
308fa247a2aSRuchika Gupta
309fa247a2aSRuchika Gupta default:
310fa247a2aSRuchika Gupta rc = PKCS11_CKR_MECHANISM_INVALID;
311fa247a2aSRuchika Gupta goto out;
312fa247a2aSRuchika Gupta }
313fa247a2aSRuchika Gupta
314fa247a2aSRuchika Gupta TEE_Free(proc_params);
315fa247a2aSRuchika Gupta proc_params = NULL;
316fa247a2aSRuchika Gupta
317fa247a2aSRuchika Gupta /*
318fa247a2aSRuchika Gupta * Object is ready, register it and return a handle.
319fa247a2aSRuchika Gupta */
320fa247a2aSRuchika Gupta rc = create_object(session, head, &obj_handle);
321fa247a2aSRuchika Gupta if (rc)
322fa247a2aSRuchika Gupta goto out;
323fa247a2aSRuchika Gupta
324fa247a2aSRuchika Gupta /*
325fa247a2aSRuchika Gupta * Now obj_handle (through the related struct pkcs11_object instance)
326fa247a2aSRuchika Gupta * owns the serialized buffer that holds the object attributes.
327fa247a2aSRuchika Gupta * We reset head to NULL as it is no more the buffer owner and would
328fa247a2aSRuchika Gupta * be freed at function out.
329fa247a2aSRuchika Gupta */
330fa247a2aSRuchika Gupta head = NULL;
331fa247a2aSRuchika Gupta
332fa247a2aSRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
333fa247a2aSRuchika Gupta out->memref.size = sizeof(obj_handle);
334fa247a2aSRuchika Gupta
335fa247a2aSRuchika Gupta DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
336fa247a2aSRuchika Gupta session->handle, obj_handle);
337fa247a2aSRuchika Gupta
338fa247a2aSRuchika Gupta out:
339fa247a2aSRuchika Gupta TEE_Free(proc_params);
340fa247a2aSRuchika Gupta TEE_Free(template);
341fa247a2aSRuchika Gupta TEE_Free(head);
342fa247a2aSRuchika Gupta
343fa247a2aSRuchika Gupta return rc;
344fa247a2aSRuchika Gupta }
345fa247a2aSRuchika Gupta
alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj,uint32_t attribute,void ** data,size_t * size)346013934d8SVesa Jääskeläinen enum pkcs11_rc alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj,
347013934d8SVesa Jääskeläinen uint32_t attribute,
348013934d8SVesa Jääskeläinen void **data, size_t *size)
349013934d8SVesa Jääskeläinen {
350013934d8SVesa Jääskeläinen TEE_Result res = TEE_ERROR_GENERIC;
351013934d8SVesa Jääskeläinen void *ptr = NULL;
352c7f1b4f7SJens Wiklander size_t sz = 0;
353013934d8SVesa Jääskeläinen
354013934d8SVesa Jääskeläinen res = TEE_GetObjectBufferAttribute(tee_obj, attribute, NULL, &sz);
355013934d8SVesa Jääskeläinen if (res != TEE_ERROR_SHORT_BUFFER)
356013934d8SVesa Jääskeläinen return PKCS11_CKR_FUNCTION_FAILED;
357013934d8SVesa Jääskeläinen
358013934d8SVesa Jääskeläinen ptr = TEE_Malloc(sz, TEE_USER_MEM_HINT_NO_FILL_ZERO);
359013934d8SVesa Jääskeläinen if (!ptr)
360013934d8SVesa Jääskeläinen return PKCS11_CKR_DEVICE_MEMORY;
361013934d8SVesa Jääskeläinen
362013934d8SVesa Jääskeläinen res = TEE_GetObjectBufferAttribute(tee_obj, attribute, ptr, &sz);
363013934d8SVesa Jääskeläinen if (res) {
364013934d8SVesa Jääskeläinen TEE_Free(ptr);
365013934d8SVesa Jääskeläinen } else {
366013934d8SVesa Jääskeläinen *data = ptr;
367013934d8SVesa Jääskeläinen *size = sz;
368013934d8SVesa Jääskeläinen }
369013934d8SVesa Jääskeläinen
370013934d8SVesa Jääskeläinen return tee2pkcs_error(res);
371013934d8SVesa Jääskeläinen }
372013934d8SVesa Jääskeläinen
tee2pkcs_add_attribute(struct obj_attrs ** head,uint32_t pkcs11_id,TEE_ObjectHandle tee_obj,uint32_t tee_id)373013934d8SVesa Jääskeläinen enum pkcs11_rc tee2pkcs_add_attribute(struct obj_attrs **head,
374013934d8SVesa Jääskeläinen uint32_t pkcs11_id,
375013934d8SVesa Jääskeläinen TEE_ObjectHandle tee_obj,
376013934d8SVesa Jääskeläinen uint32_t tee_id)
377013934d8SVesa Jääskeläinen {
378013934d8SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
379013934d8SVesa Jääskeläinen void *a_ptr = NULL;
380013934d8SVesa Jääskeläinen size_t a_size = 0;
381013934d8SVesa Jääskeläinen
382013934d8SVesa Jääskeläinen rc = alloc_get_tee_attribute_data(tee_obj, tee_id, &a_ptr, &a_size);
383013934d8SVesa Jääskeläinen if (rc)
384013934d8SVesa Jääskeläinen goto out;
385013934d8SVesa Jääskeläinen
386013934d8SVesa Jääskeläinen rc = add_attribute(head, pkcs11_id, a_ptr, a_size);
387013934d8SVesa Jääskeläinen
388013934d8SVesa Jääskeläinen TEE_Free(a_ptr);
389013934d8SVesa Jääskeläinen
390013934d8SVesa Jääskeläinen out:
391013934d8SVesa Jääskeläinen if (rc)
392013934d8SVesa Jääskeläinen EMSG("Failed TEE attribute %#"PRIx32" for %#"PRIx32"/%s",
393013934d8SVesa Jääskeläinen tee_id, pkcs11_id, id2str_attr(pkcs11_id));
394013934d8SVesa Jääskeläinen return rc;
395013934d8SVesa Jääskeläinen }
396013934d8SVesa Jääskeläinen
entry_generate_key_pair(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)397013934d8SVesa Jääskeläinen enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client,
398013934d8SVesa Jääskeläinen uint32_t ptypes, TEE_Param *params)
399013934d8SVesa Jääskeläinen {
400013934d8SVesa Jääskeläinen const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
401013934d8SVesa Jääskeläinen TEE_PARAM_TYPE_NONE,
402013934d8SVesa Jääskeläinen TEE_PARAM_TYPE_MEMREF_OUTPUT,
403013934d8SVesa Jääskeläinen TEE_PARAM_TYPE_NONE);
404013934d8SVesa Jääskeläinen TEE_Param *ctrl = params;
405013934d8SVesa Jääskeläinen TEE_Param *out = params + 2;
406013934d8SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
407013934d8SVesa Jääskeläinen struct serialargs ctrlargs = { };
408013934d8SVesa Jääskeläinen struct pkcs11_session *session = NULL;
409013934d8SVesa Jääskeläinen struct pkcs11_attribute_head *proc_params = NULL;
410013934d8SVesa Jääskeläinen struct obj_attrs *pub_head = NULL;
411013934d8SVesa Jääskeläinen struct obj_attrs *priv_head = NULL;
412013934d8SVesa Jääskeläinen struct pkcs11_object_head *pub_template = NULL;
413013934d8SVesa Jääskeläinen struct pkcs11_object_head *priv_template = NULL;
414013934d8SVesa Jääskeläinen struct pkcs11_object *object = NULL;
415013934d8SVesa Jääskeläinen size_t pub_template_size = 0;
416013934d8SVesa Jääskeläinen size_t priv_template_size = 0;
417013934d8SVesa Jääskeläinen uint32_t pubkey_handle = 0;
418013934d8SVesa Jääskeläinen uint32_t privkey_handle = 0;
419013934d8SVesa Jääskeläinen uint32_t *hdl_ptr = NULL;
420013934d8SVesa Jääskeläinen size_t out_ref_size = sizeof(pubkey_handle) + sizeof(privkey_handle);
421013934d8SVesa Jääskeläinen
422013934d8SVesa Jääskeläinen if (!client || ptypes != exp_pt || out->memref.size != out_ref_size)
423013934d8SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
424013934d8SVesa Jääskeläinen
425013934d8SVesa Jääskeläinen serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
426013934d8SVesa Jääskeläinen
427013934d8SVesa Jääskeläinen rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
428013934d8SVesa Jääskeläinen if (rc)
429013934d8SVesa Jääskeläinen return rc;
430013934d8SVesa Jääskeläinen
431013934d8SVesa Jääskeläinen rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
432013934d8SVesa Jääskeläinen if (rc)
433013934d8SVesa Jääskeläinen goto out;
434013934d8SVesa Jääskeläinen
435013934d8SVesa Jääskeläinen rc = serialargs_alloc_get_attributes(&ctrlargs, &pub_template);
436013934d8SVesa Jääskeläinen if (rc)
437013934d8SVesa Jääskeläinen goto out;
438013934d8SVesa Jääskeläinen
439013934d8SVesa Jääskeläinen rc = serialargs_alloc_get_attributes(&ctrlargs, &priv_template);
440013934d8SVesa Jääskeläinen if (rc)
441013934d8SVesa Jääskeläinen goto out;
442013934d8SVesa Jääskeläinen
443013934d8SVesa Jääskeläinen if (serialargs_remaining_bytes(&ctrlargs)) {
444013934d8SVesa Jääskeläinen rc = PKCS11_CKR_ARGUMENTS_BAD;
445013934d8SVesa Jääskeläinen goto out;
446013934d8SVesa Jääskeläinen }
447013934d8SVesa Jääskeläinen
448013934d8SVesa Jääskeläinen rc = get_ready_session(session);
449013934d8SVesa Jääskeläinen if (rc)
450013934d8SVesa Jääskeläinen goto out;
451013934d8SVesa Jääskeläinen
452013934d8SVesa Jääskeläinen rc = check_mechanism_against_processing(session, proc_params->id,
453013934d8SVesa Jääskeläinen PKCS11_FUNCTION_GENERATE_PAIR,
454013934d8SVesa Jääskeläinen PKCS11_FUNC_STEP_INIT);
455013934d8SVesa Jääskeläinen if (rc)
456013934d8SVesa Jääskeläinen goto out;
457013934d8SVesa Jääskeläinen
458013934d8SVesa Jääskeläinen pub_template_size = sizeof(*pub_template) + pub_template->attrs_size;
459013934d8SVesa Jääskeläinen
460013934d8SVesa Jääskeläinen rc = create_attributes_from_template(&pub_head, pub_template,
461013934d8SVesa Jääskeläinen pub_template_size, NULL,
462013934d8SVesa Jääskeläinen PKCS11_FUNCTION_GENERATE_PAIR,
463013934d8SVesa Jääskeläinen proc_params->id,
464013934d8SVesa Jääskeläinen PKCS11_CKO_PUBLIC_KEY);
465013934d8SVesa Jääskeläinen if (rc)
466013934d8SVesa Jääskeläinen goto out;
467013934d8SVesa Jääskeläinen
468013934d8SVesa Jääskeläinen TEE_Free(pub_template);
469013934d8SVesa Jääskeläinen pub_template = NULL;
470013934d8SVesa Jääskeläinen
471013934d8SVesa Jääskeläinen priv_template_size = sizeof(*priv_template) +
472013934d8SVesa Jääskeläinen priv_template->attrs_size;
473013934d8SVesa Jääskeläinen
474013934d8SVesa Jääskeläinen rc = create_attributes_from_template(&priv_head, priv_template,
475013934d8SVesa Jääskeläinen priv_template_size, NULL,
476013934d8SVesa Jääskeläinen PKCS11_FUNCTION_GENERATE_PAIR,
477013934d8SVesa Jääskeläinen proc_params->id,
478013934d8SVesa Jääskeläinen PKCS11_CKO_PRIVATE_KEY);
479013934d8SVesa Jääskeläinen if (rc)
480013934d8SVesa Jääskeläinen goto out;
481013934d8SVesa Jääskeläinen
482013934d8SVesa Jääskeläinen TEE_Free(priv_template);
483013934d8SVesa Jääskeläinen priv_template = NULL;
484013934d8SVesa Jääskeläinen
485013934d8SVesa Jääskeläinen /* Generate CKA_ID for keys if not specified by the templates */
486013934d8SVesa Jääskeläinen rc = add_missing_attribute_id(&pub_head, &priv_head);
487013934d8SVesa Jääskeläinen if (rc)
488013934d8SVesa Jääskeläinen goto out;
489013934d8SVesa Jääskeläinen
490013934d8SVesa Jääskeläinen /* Check created object against processing and token state */
491013934d8SVesa Jääskeläinen rc = check_created_attrs(pub_head, priv_head);
492013934d8SVesa Jääskeläinen if (rc)
493013934d8SVesa Jääskeläinen goto out;
494013934d8SVesa Jääskeläinen
495013934d8SVesa Jääskeläinen rc = check_created_attrs_against_processing(proc_params->id, pub_head);
496013934d8SVesa Jääskeläinen if (rc)
497013934d8SVesa Jääskeläinen goto out;
498013934d8SVesa Jääskeläinen
499013934d8SVesa Jääskeläinen rc = check_created_attrs_against_processing(proc_params->id,
500013934d8SVesa Jääskeläinen priv_head);
501013934d8SVesa Jääskeläinen if (rc)
502013934d8SVesa Jääskeläinen goto out;
503013934d8SVesa Jääskeläinen
504013934d8SVesa Jääskeläinen rc = check_created_attrs_against_token(session, pub_head);
505013934d8SVesa Jääskeläinen if (rc)
506013934d8SVesa Jääskeläinen goto out;
507013934d8SVesa Jääskeläinen
508013934d8SVesa Jääskeläinen rc = check_access_attrs_against_token(session, pub_head);
509013934d8SVesa Jääskeläinen if (rc)
510013934d8SVesa Jääskeläinen goto out;
511013934d8SVesa Jääskeläinen
512013934d8SVesa Jääskeläinen rc = check_created_attrs_against_token(session, priv_head);
513013934d8SVesa Jääskeläinen if (rc)
514013934d8SVesa Jääskeläinen goto out;
515013934d8SVesa Jääskeläinen
516013934d8SVesa Jääskeläinen rc = check_access_attrs_against_token(session, priv_head);
517013934d8SVesa Jääskeläinen if (rc)
518013934d8SVesa Jääskeläinen goto out;
519013934d8SVesa Jääskeläinen
520013934d8SVesa Jääskeläinen /* Generate key pair */
521013934d8SVesa Jääskeläinen switch (proc_params->id) {
52203e07432SValerii Chubar case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN:
52303e07432SValerii Chubar rc = generate_eddsa_keys(proc_params, &pub_head, &priv_head);
52403e07432SValerii Chubar break;
52502b16804SVesa Jääskeläinen case PKCS11_CKM_EC_KEY_PAIR_GEN:
52602b16804SVesa Jääskeläinen rc = generate_ec_keys(proc_params, &pub_head, &priv_head);
52702b16804SVesa Jääskeläinen break;
52886922832SVesa Jääskeläinen case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
52986922832SVesa Jääskeläinen rc = generate_rsa_keys(proc_params, &pub_head, &priv_head);
53086922832SVesa Jääskeläinen break;
531013934d8SVesa Jääskeläinen default:
532013934d8SVesa Jääskeläinen rc = PKCS11_CKR_MECHANISM_INVALID;
533013934d8SVesa Jääskeläinen break;
534013934d8SVesa Jääskeläinen }
535013934d8SVesa Jääskeläinen if (rc)
536013934d8SVesa Jääskeläinen goto out;
537013934d8SVesa Jääskeläinen
538013934d8SVesa Jääskeläinen TEE_Free(proc_params);
539013934d8SVesa Jääskeläinen proc_params = NULL;
540013934d8SVesa Jääskeläinen
541013934d8SVesa Jääskeläinen /*
542013934d8SVesa Jääskeläinen * Object is ready, register it and return a handle.
543013934d8SVesa Jääskeläinen */
544013934d8SVesa Jääskeläinen rc = create_object(session, pub_head, &pubkey_handle);
545013934d8SVesa Jääskeläinen if (rc)
546013934d8SVesa Jääskeläinen goto out;
547013934d8SVesa Jääskeläinen
548013934d8SVesa Jääskeläinen /*
549013934d8SVesa Jääskeläinen * Now obj_handle (through the related struct pkcs11_object instance)
550013934d8SVesa Jääskeläinen * owns the serialized buffer that holds the object attributes.
551013934d8SVesa Jääskeläinen * We reset local pub_head to NULL to mark that ownership has been
552013934d8SVesa Jääskeläinen * transferred.
553013934d8SVesa Jääskeläinen */
554013934d8SVesa Jääskeläinen pub_head = NULL;
555013934d8SVesa Jääskeläinen
556013934d8SVesa Jääskeläinen rc = create_object(session, priv_head, &privkey_handle);
557013934d8SVesa Jääskeläinen if (rc)
558013934d8SVesa Jääskeläinen goto out;
559013934d8SVesa Jääskeläinen
560013934d8SVesa Jääskeläinen /* Ownership has been transferred so mark it with NULL */
561013934d8SVesa Jääskeläinen priv_head = NULL;
562013934d8SVesa Jääskeläinen
563013934d8SVesa Jääskeläinen hdl_ptr = (uint32_t *)out->memref.buffer;
564013934d8SVesa Jääskeläinen
565013934d8SVesa Jääskeläinen TEE_MemMove(hdl_ptr, &pubkey_handle, sizeof(pubkey_handle));
566013934d8SVesa Jääskeläinen TEE_MemMove(hdl_ptr + 1, &privkey_handle, sizeof(privkey_handle));
567013934d8SVesa Jääskeläinen
568013934d8SVesa Jääskeläinen DMSG("PKCS11 session %"PRIu32": create key pair %#"PRIx32"/%#"PRIx32,
569013934d8SVesa Jääskeläinen session->handle, privkey_handle, pubkey_handle);
570013934d8SVesa Jääskeläinen
5712f7f001aSSergiy Kibrik pubkey_handle = 0;
5722f7f001aSSergiy Kibrik privkey_handle = 0;
573013934d8SVesa Jääskeläinen out:
574013934d8SVesa Jääskeläinen if (pubkey_handle) {
575013934d8SVesa Jääskeläinen object = pkcs11_handle2object(pubkey_handle, session);
576013934d8SVesa Jääskeläinen if (!object)
577013934d8SVesa Jääskeläinen TEE_Panic(0);
578013934d8SVesa Jääskeläinen destroy_object(session, object, false);
579013934d8SVesa Jääskeläinen }
580013934d8SVesa Jääskeläinen TEE_Free(priv_head);
581013934d8SVesa Jääskeläinen TEE_Free(pub_head);
582013934d8SVesa Jääskeläinen TEE_Free(priv_template);
583013934d8SVesa Jääskeläinen TEE_Free(pub_template);
584013934d8SVesa Jääskeläinen TEE_Free(proc_params);
585013934d8SVesa Jääskeläinen
586013934d8SVesa Jääskeläinen return rc;
587013934d8SVesa Jääskeläinen }
588013934d8SVesa Jääskeläinen
589512cbf1dSJens Wiklander /*
590512cbf1dSJens Wiklander * entry_processing_init - Generic entry for initializing a processing
591512cbf1dSJens Wiklander *
592512cbf1dSJens Wiklander * @client = client reference
593512cbf1dSJens Wiklander * @ptype = Invocation parameter types
594512cbf1dSJens Wiklander * @params = Invocation parameters reference
595512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ...
596512cbf1dSJens Wiklander */
entry_processing_init(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params,enum processing_func function)597512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
598512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params,
599512cbf1dSJens Wiklander enum processing_func function)
600512cbf1dSJens Wiklander {
601512cbf1dSJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
602512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE,
603512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE,
604512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE);
605512cbf1dSJens Wiklander TEE_Param *ctrl = params;
606512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
607512cbf1dSJens Wiklander struct serialargs ctrlargs = { };
608512cbf1dSJens Wiklander struct pkcs11_session *session = NULL;
609512cbf1dSJens Wiklander struct pkcs11_attribute_head *proc_params = NULL;
610512cbf1dSJens Wiklander uint32_t key_handle = 0;
611512cbf1dSJens Wiklander struct pkcs11_object *obj = NULL;
612512cbf1dSJens Wiklander
613512cbf1dSJens Wiklander if (!client || ptypes != exp_pt)
614512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
615512cbf1dSJens Wiklander
616512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
617512cbf1dSJens Wiklander
618512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
619512cbf1dSJens Wiklander if (rc)
620512cbf1dSJens Wiklander return rc;
621512cbf1dSJens Wiklander
6229e91a619SVesa Jääskeläinen if (function != PKCS11_FUNCTION_DIGEST) {
623512cbf1dSJens Wiklander rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
624512cbf1dSJens Wiklander if (rc)
625512cbf1dSJens Wiklander return rc;
6269e91a619SVesa Jääskeläinen }
627512cbf1dSJens Wiklander
628512cbf1dSJens Wiklander rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
629512cbf1dSJens Wiklander if (rc)
630512cbf1dSJens Wiklander return rc;
631512cbf1dSJens Wiklander
632512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) {
633512cbf1dSJens Wiklander rc = PKCS11_CKR_ARGUMENTS_BAD;
6348abbc8f7SVesa Jääskeläinen goto out_free;
635512cbf1dSJens Wiklander }
636512cbf1dSJens Wiklander
637512cbf1dSJens Wiklander rc = get_ready_session(session);
638512cbf1dSJens Wiklander if (rc)
6398abbc8f7SVesa Jääskeläinen goto out_free;
640512cbf1dSJens Wiklander
6419e91a619SVesa Jääskeläinen if (function != PKCS11_FUNCTION_DIGEST) {
642512cbf1dSJens Wiklander obj = pkcs11_handle2object(key_handle, session);
643512cbf1dSJens Wiklander if (!obj) {
644512cbf1dSJens Wiklander rc = PKCS11_CKR_KEY_HANDLE_INVALID;
6458abbc8f7SVesa Jääskeläinen goto out_free;
646512cbf1dSJens Wiklander }
6479e91a619SVesa Jääskeläinen }
648512cbf1dSJens Wiklander
649512cbf1dSJens Wiklander rc = set_processing_state(session, function, obj, NULL);
650512cbf1dSJens Wiklander if (rc)
651512cbf1dSJens Wiklander goto out;
652512cbf1dSJens Wiklander
653512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, proc_params->id,
654512cbf1dSJens Wiklander function,
655512cbf1dSJens Wiklander PKCS11_FUNC_STEP_INIT);
656512cbf1dSJens Wiklander if (rc)
657512cbf1dSJens Wiklander goto out;
658512cbf1dSJens Wiklander
6599e91a619SVesa Jääskeläinen if (obj) {
6609e91a619SVesa Jääskeläinen rc = check_parent_attrs_against_processing(proc_params->id,
6619e91a619SVesa Jääskeläinen function,
662512cbf1dSJens Wiklander obj->attributes);
663512cbf1dSJens Wiklander if (rc)
664512cbf1dSJens Wiklander goto out;
665512cbf1dSJens Wiklander
6669e91a619SVesa Jääskeläinen rc = check_access_attrs_against_token(session,
6679e91a619SVesa Jääskeläinen obj->attributes);
668512cbf1dSJens Wiklander if (rc)
669512cbf1dSJens Wiklander goto out;
6709e91a619SVesa Jääskeläinen }
671512cbf1dSJens Wiklander
672512cbf1dSJens Wiklander if (processing_is_tee_symm(proc_params->id))
673512cbf1dSJens Wiklander rc = init_symm_operation(session, function, proc_params, obj);
674fb279d8bSVesa Jääskeläinen else if (processing_is_tee_asymm(proc_params->id))
675fb279d8bSVesa Jääskeläinen rc = init_asymm_operation(session, function, proc_params, obj);
6769e91a619SVesa Jääskeläinen else if (processing_is_tee_digest(proc_params->id))
6779e91a619SVesa Jääskeläinen rc = init_digest_operation(session, proc_params);
678512cbf1dSJens Wiklander else
679512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID;
680512cbf1dSJens Wiklander
681512cbf1dSJens Wiklander if (rc == PKCS11_CKR_OK) {
682512cbf1dSJens Wiklander DMSG("PKCS11 session %"PRIu32": init processing %s %s",
683512cbf1dSJens Wiklander session->handle, id2str_proc(proc_params->id),
684512cbf1dSJens Wiklander id2str_function(function));
685512cbf1dSJens Wiklander }
686512cbf1dSJens Wiklander
687512cbf1dSJens Wiklander out:
6888abbc8f7SVesa Jääskeläinen if (rc)
689512cbf1dSJens Wiklander release_active_processing(session);
6908abbc8f7SVesa Jääskeläinen out_free:
691512cbf1dSJens Wiklander TEE_Free(proc_params);
692512cbf1dSJens Wiklander
693512cbf1dSJens Wiklander return rc;
694512cbf1dSJens Wiklander }
695512cbf1dSJens Wiklander
696512cbf1dSJens Wiklander /*
697512cbf1dSJens Wiklander * entry_processing_step - Generic entry on active processing
698512cbf1dSJens Wiklander *
699512cbf1dSJens Wiklander * @client = client reference
700512cbf1dSJens Wiklander * @ptype = Invocation parameter types
701512cbf1dSJens Wiklander * @params = Invocation parameters reference
702512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ...
703512cbf1dSJens Wiklander * @step - update, oneshot, final
704512cbf1dSJens Wiklander */
entry_processing_step(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params,enum processing_func function,enum processing_step step)705512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
706512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params,
707512cbf1dSJens Wiklander enum processing_func function,
708512cbf1dSJens Wiklander enum processing_step step)
709512cbf1dSJens Wiklander {
710512cbf1dSJens Wiklander TEE_Param *ctrl = params;
711512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
712512cbf1dSJens Wiklander struct serialargs ctrlargs = { };
713512cbf1dSJens Wiklander struct pkcs11_session *session = NULL;
714512cbf1dSJens Wiklander enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
7159e91a619SVesa Jääskeläinen uint32_t key_handle = 0;
7169e91a619SVesa Jääskeläinen struct pkcs11_object *obj = NULL;
717512cbf1dSJens Wiklander
718512cbf1dSJens Wiklander if (!client ||
719512cbf1dSJens Wiklander TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
720512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
721512cbf1dSJens Wiklander
722512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
723512cbf1dSJens Wiklander
724512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
725512cbf1dSJens Wiklander if (rc)
726512cbf1dSJens Wiklander return rc;
727512cbf1dSJens Wiklander
7289e91a619SVesa Jääskeläinen if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
7299e91a619SVesa Jääskeläinen assert(function == PKCS11_FUNCTION_DIGEST);
7309e91a619SVesa Jääskeläinen
7319e91a619SVesa Jääskeläinen rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
7329e91a619SVesa Jääskeläinen if (rc)
7339e91a619SVesa Jääskeläinen return rc;
7349e91a619SVesa Jääskeläinen }
7359e91a619SVesa Jääskeläinen
736512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs))
737512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD;
738512cbf1dSJens Wiklander
739512cbf1dSJens Wiklander rc = get_active_session(session, function);
740512cbf1dSJens Wiklander if (rc)
741512cbf1dSJens Wiklander return rc;
742512cbf1dSJens Wiklander
7439e91a619SVesa Jääskeläinen if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
7449e91a619SVesa Jääskeläinen assert(function == PKCS11_FUNCTION_DIGEST);
7459e91a619SVesa Jääskeläinen
7469e91a619SVesa Jääskeläinen obj = pkcs11_handle2object(key_handle, session);
7479e91a619SVesa Jääskeläinen if (!obj) {
7489e91a619SVesa Jääskeläinen rc = PKCS11_CKR_KEY_HANDLE_INVALID;
7499e91a619SVesa Jääskeläinen goto out;
7509e91a619SVesa Jääskeläinen }
7519e91a619SVesa Jääskeläinen
7529e91a619SVesa Jääskeläinen rc = check_access_attrs_against_token(session,
7539e91a619SVesa Jääskeläinen obj->attributes);
7549e91a619SVesa Jääskeläinen if (rc) {
7559e91a619SVesa Jääskeläinen rc = PKCS11_CKR_KEY_HANDLE_INVALID;
7569e91a619SVesa Jääskeläinen goto out;
7579e91a619SVesa Jääskeläinen }
7589e91a619SVesa Jääskeläinen }
7599e91a619SVesa Jääskeläinen
760512cbf1dSJens Wiklander mecha_type = session->processing->mecha_type;
761512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, mecha_type,
762512cbf1dSJens Wiklander function, step);
763512cbf1dSJens Wiklander if (rc)
764512cbf1dSJens Wiklander goto out;
765512cbf1dSJens Wiklander
766512cbf1dSJens Wiklander if (processing_is_tee_symm(mecha_type))
767512cbf1dSJens Wiklander rc = step_symm_operation(session, function, step,
768512cbf1dSJens Wiklander ptypes, params);
769fb279d8bSVesa Jääskeläinen else if (processing_is_tee_asymm(mecha_type))
770fb279d8bSVesa Jääskeläinen rc = step_asymm_operation(session, function, step,
771fb279d8bSVesa Jääskeläinen ptypes, params);
7729e91a619SVesa Jääskeläinen else if (processing_is_tee_digest(mecha_type))
7739e91a619SVesa Jääskeläinen rc = step_digest_operation(session, step, obj, ptypes, params);
774512cbf1dSJens Wiklander else
775512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID;
776512cbf1dSJens Wiklander
7779e91a619SVesa Jääskeläinen if (rc == PKCS11_CKR_OK && (step == PKCS11_FUNC_STEP_UPDATE ||
7789e91a619SVesa Jääskeläinen step == PKCS11_FUNC_STEP_UPDATE_KEY)) {
7792364aa69SRuchika Gupta session->processing->step = PKCS11_FUNC_STEP_UPDATE;
780512cbf1dSJens Wiklander DMSG("PKCS11 session%"PRIu32": processing %s %s",
781512cbf1dSJens Wiklander session->handle, id2str_proc(mecha_type),
782512cbf1dSJens Wiklander id2str_function(function));
783512cbf1dSJens Wiklander }
784512cbf1dSJens Wiklander
7852364aa69SRuchika Gupta if (rc == PKCS11_CKR_BUFFER_TOO_SMALL &&
7862364aa69SRuchika Gupta step == PKCS11_FUNC_STEP_ONESHOT)
7872364aa69SRuchika Gupta session->processing->step = PKCS11_FUNC_STEP_ONESHOT;
7882364aa69SRuchika Gupta
7892364aa69SRuchika Gupta if (rc == PKCS11_CKR_BUFFER_TOO_SMALL && step == PKCS11_FUNC_STEP_FINAL)
7902364aa69SRuchika Gupta session->processing->step = PKCS11_FUNC_STEP_FINAL;
7912364aa69SRuchika Gupta
792512cbf1dSJens Wiklander out:
793512cbf1dSJens Wiklander switch (step) {
794512cbf1dSJens Wiklander case PKCS11_FUNC_STEP_UPDATE:
7959e91a619SVesa Jääskeläinen case PKCS11_FUNC_STEP_UPDATE_KEY:
796512cbf1dSJens Wiklander if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
797512cbf1dSJens Wiklander release_active_processing(session);
798512cbf1dSJens Wiklander break;
799512cbf1dSJens Wiklander default:
800512cbf1dSJens Wiklander /* ONESHOT and FINAL terminates processing on success */
801512cbf1dSJens Wiklander if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
802512cbf1dSJens Wiklander release_active_processing(session);
803512cbf1dSJens Wiklander break;
804512cbf1dSJens Wiklander }
805512cbf1dSJens Wiklander
806512cbf1dSJens Wiklander return rc;
807512cbf1dSJens Wiklander }
80848799892SRuchika Gupta
entry_processing_key(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params,enum processing_func function)8094dad6642SRuchika Gupta enum pkcs11_rc entry_processing_key(struct pkcs11_client *client,
8104dad6642SRuchika Gupta uint32_t ptypes, TEE_Param *params,
8114dad6642SRuchika Gupta enum processing_func function)
81248799892SRuchika Gupta {
81348799892SRuchika Gupta TEE_Param *ctrl = params;
81448799892SRuchika Gupta TEE_Param *out = params + 2;
81548799892SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
81648799892SRuchika Gupta struct serialargs ctrlargs = { };
81748799892SRuchika Gupta struct pkcs11_session *session = NULL;
81848799892SRuchika Gupta struct pkcs11_attribute_head *proc_params = NULL;
81948799892SRuchika Gupta struct pkcs11_object_head *template = NULL;
82048799892SRuchika Gupta uint32_t parent_handle = 0;
82148799892SRuchika Gupta uint32_t obj_handle = 0;
82248799892SRuchika Gupta struct pkcs11_object *parent = NULL;
82348799892SRuchika Gupta struct obj_attrs *head = NULL;
82448799892SRuchika Gupta size_t template_size = 0;
8253668310bSRuchika Gupta void *in_buf = NULL;
8263668310bSRuchika Gupta uint32_t in_size = 0;
8278c499324SRuchika Gupta void *out_buf = NULL;
8288c499324SRuchika Gupta uint32_t out_size = 0;
8293668310bSRuchika Gupta enum processing_func operation = PKCS11_FUNCTION_UNKNOWN;
83048799892SRuchika Gupta
8313668310bSRuchika Gupta if (!client ||
8323668310bSRuchika Gupta TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT ||
8333668310bSRuchika Gupta TEE_PARAM_TYPE_GET(ptypes, 2) != TEE_PARAM_TYPE_MEMREF_OUTPUT ||
8343668310bSRuchika Gupta out->memref.size != sizeof(obj_handle) ||
8353668310bSRuchika Gupta TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
83648799892SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
83748799892SRuchika Gupta
8383668310bSRuchika Gupta switch (function) {
8393668310bSRuchika Gupta case PKCS11_FUNCTION_UNWRAP:
8403668310bSRuchika Gupta if (TEE_PARAM_TYPE_GET(ptypes, 1) !=
8413668310bSRuchika Gupta TEE_PARAM_TYPE_MEMREF_INPUT)
8423668310bSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
8433668310bSRuchika Gupta
8443668310bSRuchika Gupta in_buf = params[1].memref.buffer;
8453668310bSRuchika Gupta in_size = params[1].memref.size;
8463668310bSRuchika Gupta if (in_size && !in_buf)
8473668310bSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
8483668310bSRuchika Gupta
8493668310bSRuchika Gupta /*
8503668310bSRuchika Gupta * Some unwrap mechanisms require encryption to be
8513668310bSRuchika Gupta * performed on the data passed in proc_params by parent
8523668310bSRuchika Gupta * key. Hence set operation as PKCS11_FUNCTION_DECRYPT
8533668310bSRuchika Gupta * to be used with init_symm_operation()
8543668310bSRuchika Gupta */
8553668310bSRuchika Gupta operation = PKCS11_FUNCTION_DECRYPT;
8563668310bSRuchika Gupta break;
8573668310bSRuchika Gupta case PKCS11_FUNCTION_DERIVE:
8583668310bSRuchika Gupta if (TEE_PARAM_TYPE_GET(ptypes, 1) != TEE_PARAM_TYPE_NONE)
8593668310bSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
8603668310bSRuchika Gupta
8613668310bSRuchika Gupta /*
8623668310bSRuchika Gupta * Some derivation mechanism require encryption to be
8633668310bSRuchika Gupta * performed on the data passed in proc_params by parent
8643668310bSRuchika Gupta * key. Hence set operation as PKCS11_FUNCTION_ENCRYPT
8653668310bSRuchika Gupta * to be used with init_symm_operation()
8663668310bSRuchika Gupta */
8673668310bSRuchika Gupta operation = PKCS11_FUNCTION_ENCRYPT;
8683668310bSRuchika Gupta break;
8693668310bSRuchika Gupta default:
8703668310bSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
8713668310bSRuchika Gupta }
8723668310bSRuchika Gupta
87348799892SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
87448799892SRuchika Gupta
87548799892SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
87648799892SRuchika Gupta if (rc)
87748799892SRuchika Gupta return rc;
87848799892SRuchika Gupta
87948799892SRuchika Gupta rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t));
88048799892SRuchika Gupta if (rc)
88148799892SRuchika Gupta return rc;
88248799892SRuchika Gupta
88348799892SRuchika Gupta rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
88448799892SRuchika Gupta if (rc)
8855f80f270SRuchika Gupta return rc;
88648799892SRuchika Gupta
88748799892SRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
88848799892SRuchika Gupta if (rc)
88948799892SRuchika Gupta goto out_free;
89048799892SRuchika Gupta
89148799892SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) {
89248799892SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD;
89348799892SRuchika Gupta goto out_free;
89448799892SRuchika Gupta }
89548799892SRuchika Gupta
89648799892SRuchika Gupta /* Return error if processing already active */
89748799892SRuchika Gupta rc = get_ready_session(session);
89848799892SRuchika Gupta if (rc)
89948799892SRuchika Gupta goto out_free;
90048799892SRuchika Gupta
90148799892SRuchika Gupta /* Check parent handle */
90248799892SRuchika Gupta parent = pkcs11_handle2object(parent_handle, session);
90348799892SRuchika Gupta if (!parent) {
90448799892SRuchika Gupta rc = PKCS11_CKR_KEY_HANDLE_INVALID;
90548799892SRuchika Gupta goto out_free;
90648799892SRuchika Gupta }
90748799892SRuchika Gupta
90848799892SRuchika Gupta /* Check if mechanism can be used for derivation function */
90948799892SRuchika Gupta rc = check_mechanism_against_processing(session, proc_params->id,
91048799892SRuchika Gupta function,
91148799892SRuchika Gupta PKCS11_FUNC_STEP_INIT);
91248799892SRuchika Gupta if (rc)
91348799892SRuchika Gupta goto out_free;
91448799892SRuchika Gupta
91548799892SRuchika Gupta /* Set the processing state to active */
91648799892SRuchika Gupta rc = set_processing_state(session, function, parent, NULL);
91748799892SRuchika Gupta if (rc)
91848799892SRuchika Gupta goto out_free;
91948799892SRuchika Gupta
92048799892SRuchika Gupta /*
92148799892SRuchika Gupta * Check if base/parent key has CKA_DERIVE set and its key type is
92248799892SRuchika Gupta * compatible with the mechanism passed
92348799892SRuchika Gupta */
92448799892SRuchika Gupta rc = check_parent_attrs_against_processing(proc_params->id, function,
92548799892SRuchika Gupta parent->attributes);
926d05ab5feSRuchika Gupta if (rc) {
927d05ab5feSRuchika Gupta /*
928d05ab5feSRuchika Gupta * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
929d05ab5feSRuchika Gupta * specified with C_Derive/Unwrap() in the specification. So
930d05ab5feSRuchika Gupta * return the next most appropriate error.
931d05ab5feSRuchika Gupta */
9323668310bSRuchika Gupta if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) {
9333668310bSRuchika Gupta if (function == PKCS11_FUNCTION_UNWRAP)
9343668310bSRuchika Gupta rc =
9353668310bSRuchika Gupta PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
9363668310bSRuchika Gupta else
937d05ab5feSRuchika Gupta rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT;
9383668310bSRuchika Gupta }
93948799892SRuchika Gupta goto out;
940d05ab5feSRuchika Gupta }
94148799892SRuchika Gupta
94248799892SRuchika Gupta /* Check access of base/parent key */
94348799892SRuchika Gupta rc = check_access_attrs_against_token(session, parent->attributes);
94448799892SRuchika Gupta if (rc)
94548799892SRuchika Gupta goto out;
94648799892SRuchika Gupta
94748799892SRuchika Gupta template_size = sizeof(*template) + template->attrs_size;
94848799892SRuchika Gupta /*
94948799892SRuchika Gupta * Prepare a clean initial state for the requested object attributes
95048799892SRuchika Gupta * using base/parent key attributes. Free temporary template once done.
95148799892SRuchika Gupta */
95248799892SRuchika Gupta rc = create_attributes_from_template(&head, template, template_size,
95348799892SRuchika Gupta parent->attributes,
95448799892SRuchika Gupta function,
95548799892SRuchika Gupta proc_params->id,
95648799892SRuchika Gupta PKCS11_CKO_UNDEFINED_ID);
95748799892SRuchika Gupta if (rc)
95848799892SRuchika Gupta goto out;
95948799892SRuchika Gupta
96048799892SRuchika Gupta TEE_Free(template);
96148799892SRuchika Gupta template = NULL;
96248799892SRuchika Gupta
96348799892SRuchika Gupta /* check_created_attrs() is called later once key size is known */
96448799892SRuchika Gupta
96548799892SRuchika Gupta rc = check_created_attrs_against_processing(proc_params->id, head);
96648799892SRuchika Gupta if (rc)
96748799892SRuchika Gupta goto out;
96848799892SRuchika Gupta
96948799892SRuchika Gupta rc = check_created_attrs_against_token(session, head);
97048799892SRuchika Gupta if (rc)
97148799892SRuchika Gupta goto out;
97248799892SRuchika Gupta
973f5c0739cSRuchika Gupta rc = check_access_attrs_against_token(session, head);
974f5c0739cSRuchika Gupta if (rc)
975f5c0739cSRuchika Gupta goto out;
976f5c0739cSRuchika Gupta
9778c499324SRuchika Gupta if (processing_is_tee_symm(proc_params->id)) {
9783668310bSRuchika Gupta rc = init_symm_operation(session, operation, proc_params,
9793668310bSRuchika Gupta parent);
98048799892SRuchika Gupta if (rc)
98148799892SRuchika Gupta goto out;
98248799892SRuchika Gupta
9833668310bSRuchika Gupta switch (function) {
9843668310bSRuchika Gupta case PKCS11_FUNCTION_DERIVE:
9853668310bSRuchika Gupta rc = derive_key_by_symm_enc(session, &out_buf,
9863668310bSRuchika Gupta &out_size);
9873668310bSRuchika Gupta break;
9883668310bSRuchika Gupta case PKCS11_FUNCTION_UNWRAP:
9893668310bSRuchika Gupta rc = unwrap_key_by_symm(session, in_buf, in_size,
9903668310bSRuchika Gupta &out_buf, &out_size);
9913668310bSRuchika Gupta break;
9923668310bSRuchika Gupta default:
9933668310bSRuchika Gupta TEE_Panic(function);
9943668310bSRuchika Gupta }
99548799892SRuchika Gupta if (rc)
99648799892SRuchika Gupta goto out;
997cc062b46SJorge Ramirez-Ortiz
998cc062b46SJorge Ramirez-Ortiz } else if (processing_is_tee_asymm(proc_params->id)) {
99945d40bdaSValerii Chubar switch (function) {
100045d40bdaSValerii Chubar case PKCS11_FUNCTION_DERIVE:
100145d40bdaSValerii Chubar rc = init_asymm_operation(session, function,
100245d40bdaSValerii Chubar proc_params, parent);
1003cc062b46SJorge Ramirez-Ortiz if (rc)
1004cc062b46SJorge Ramirez-Ortiz goto out;
1005cc062b46SJorge Ramirez-Ortiz
1006cc062b46SJorge Ramirez-Ortiz rc = do_asymm_derivation(session, proc_params, &head);
100745d40bdaSValerii Chubar if (!rc)
100845d40bdaSValerii Chubar goto done;
100945d40bdaSValerii Chubar break;
101045d40bdaSValerii Chubar case PKCS11_FUNCTION_UNWRAP:
101145d40bdaSValerii Chubar rc = init_asymm_operation(session, operation,
101245d40bdaSValerii Chubar proc_params, parent);
1013cc062b46SJorge Ramirez-Ortiz if (rc)
1014cc062b46SJorge Ramirez-Ortiz goto out;
1015cc062b46SJorge Ramirez-Ortiz
101645d40bdaSValerii Chubar rc = unwrap_key_by_asymm(session, in_buf, in_size,
101745d40bdaSValerii Chubar &out_buf, &out_size);
101845d40bdaSValerii Chubar break;
101945d40bdaSValerii Chubar default:
102045d40bdaSValerii Chubar TEE_Panic(function);
102145d40bdaSValerii Chubar }
102245d40bdaSValerii Chubar
102345d40bdaSValerii Chubar if (rc)
102445d40bdaSValerii Chubar goto out;
10258c499324SRuchika Gupta } else {
102648799892SRuchika Gupta rc = PKCS11_CKR_MECHANISM_INVALID;
102748799892SRuchika Gupta goto out;
102848799892SRuchika Gupta }
102948799892SRuchika Gupta
10308c499324SRuchika Gupta rc = set_key_data(&head, out_buf, out_size);
10318c499324SRuchika Gupta if (rc)
10328c499324SRuchika Gupta goto out;
10338c499324SRuchika Gupta
1034cc062b46SJorge Ramirez-Ortiz done:
10358c499324SRuchika Gupta TEE_Free(out_buf);
10368c499324SRuchika Gupta out_buf = NULL;
10378c499324SRuchika Gupta
103848799892SRuchika Gupta TEE_Free(proc_params);
103948799892SRuchika Gupta proc_params = NULL;
104048799892SRuchika Gupta
104148799892SRuchika Gupta /*
104248799892SRuchika Gupta * Object is ready, register it and return a handle.
104348799892SRuchika Gupta */
104448799892SRuchika Gupta rc = create_object(session, head, &obj_handle);
104548799892SRuchika Gupta if (rc)
104648799892SRuchika Gupta goto out;
104748799892SRuchika Gupta
104848799892SRuchika Gupta /*
104948799892SRuchika Gupta * Now obj_handle (through the related struct pkcs11_object instance)
105048799892SRuchika Gupta * owns the serialized buffer that holds the object attributes.
105148799892SRuchika Gupta * We reset head to NULL as it is no more the buffer owner and would
105248799892SRuchika Gupta * be freed at function out.
105348799892SRuchika Gupta */
105448799892SRuchika Gupta head = NULL;
105548799892SRuchika Gupta
105648799892SRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
105748799892SRuchika Gupta out->memref.size = sizeof(obj_handle);
105848799892SRuchika Gupta
105948799892SRuchika Gupta DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32,
106048799892SRuchika Gupta session->handle, obj_handle);
106148799892SRuchika Gupta
106248799892SRuchika Gupta out:
106348799892SRuchika Gupta release_active_processing(session);
106448799892SRuchika Gupta out_free:
106548799892SRuchika Gupta TEE_Free(proc_params);
106648799892SRuchika Gupta TEE_Free(template);
106748799892SRuchika Gupta TEE_Free(head);
10688c499324SRuchika Gupta TEE_Free(out_buf);
106948799892SRuchika Gupta
107048799892SRuchika Gupta return rc;
107148799892SRuchika Gupta }
1072eb6141b6SVesa Jääskeläinen
entry_release_active_processing(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)1073eb6141b6SVesa Jääskeläinen enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client,
1074eb6141b6SVesa Jääskeläinen uint32_t ptypes,
1075eb6141b6SVesa Jääskeläinen TEE_Param *params)
1076eb6141b6SVesa Jääskeläinen {
1077eb6141b6SVesa Jääskeläinen const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1078eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE,
1079eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE,
1080eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE);
1081eb6141b6SVesa Jääskeläinen TEE_Param *ctrl = params;
1082eb6141b6SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_OK;
1083eb6141b6SVesa Jääskeläinen struct serialargs ctrlargs = { };
1084eb6141b6SVesa Jääskeläinen struct pkcs11_session *session = NULL;
1085eb6141b6SVesa Jääskeläinen enum processing_func function = PKCS11_FUNCTION_UNKNOWN;
1086eb6141b6SVesa Jääskeläinen uint32_t cmd = 0;
1087eb6141b6SVesa Jääskeläinen
1088eb6141b6SVesa Jääskeläinen if (!client || ptypes != exp_pt)
1089eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
1090eb6141b6SVesa Jääskeläinen
1091eb6141b6SVesa Jääskeläinen serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1092eb6141b6SVesa Jääskeläinen
1093eb6141b6SVesa Jääskeläinen rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1094eb6141b6SVesa Jääskeläinen if (rc)
1095eb6141b6SVesa Jääskeläinen return rc;
1096eb6141b6SVesa Jääskeläinen
1097eb6141b6SVesa Jääskeläinen rc = serialargs_get_u32(&ctrlargs, &cmd);
1098eb6141b6SVesa Jääskeläinen
1099eb6141b6SVesa Jääskeläinen if (serialargs_remaining_bytes(&ctrlargs))
1100eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
1101eb6141b6SVesa Jääskeläinen
1102eb6141b6SVesa Jääskeläinen function = func_for_cmd(cmd);
1103eb6141b6SVesa Jääskeläinen if (function == PKCS11_FUNCTION_UNKNOWN)
1104eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD;
1105eb6141b6SVesa Jääskeläinen
1106eb6141b6SVesa Jääskeläinen rc = get_active_session(session, function);
1107eb6141b6SVesa Jääskeläinen if (rc)
1108eb6141b6SVesa Jääskeläinen return rc;
1109eb6141b6SVesa Jääskeläinen
1110eb6141b6SVesa Jääskeläinen release_active_processing(session);
1111eb6141b6SVesa Jääskeläinen
1112eb6141b6SVesa Jääskeläinen DMSG("PKCS11 session %"PRIu32": release processing", session->handle);
1113eb6141b6SVesa Jääskeläinen
1114eb6141b6SVesa Jääskeläinen return PKCS11_CKR_OK;
1115eb6141b6SVesa Jääskeläinen }
11165f80f270SRuchika Gupta
entry_wrap_key(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)11175f80f270SRuchika Gupta enum pkcs11_rc entry_wrap_key(struct pkcs11_client *client,
11185f80f270SRuchika Gupta uint32_t ptypes, TEE_Param *params)
11195f80f270SRuchika Gupta {
11205f80f270SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
11215f80f270SRuchika Gupta TEE_PARAM_TYPE_NONE,
11225f80f270SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT,
11235f80f270SRuchika Gupta TEE_PARAM_TYPE_NONE);
11245f80f270SRuchika Gupta TEE_Param *ctrl = params;
11255f80f270SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
11265f80f270SRuchika Gupta struct serialargs ctrlargs = { };
11275f80f270SRuchika Gupta struct pkcs11_session *session = NULL;
11285f80f270SRuchika Gupta struct pkcs11_attribute_head *proc_params = NULL;
11295f80f270SRuchika Gupta struct pkcs11_object *wrapping_key = NULL;
11305f80f270SRuchika Gupta struct pkcs11_object *key = NULL;
11315f80f270SRuchika Gupta void *req_attrs = NULL;
11325f80f270SRuchika Gupta uint32_t wrapping_key_handle = 0;
11335f80f270SRuchika Gupta uint32_t key_handle = 0;
11345f80f270SRuchika Gupta uint32_t size = 0;
11355f80f270SRuchika Gupta void *key_data = NULL;
11365f80f270SRuchika Gupta uint32_t key_sz = 0;
11375f80f270SRuchika Gupta void *out_buf = params[2].memref.buffer;
11385f80f270SRuchika Gupta uint32_t out_size = params[2].memref.size;
11395f80f270SRuchika Gupta const enum processing_func function = PKCS11_FUNCTION_WRAP;
11405f80f270SRuchika Gupta
11415f80f270SRuchika Gupta if (!client || ptypes != exp_pt ||
11425f80f270SRuchika Gupta (out_size && !out_buf))
11435f80f270SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD;
11445f80f270SRuchika Gupta
11455f80f270SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
11465f80f270SRuchika Gupta
11475f80f270SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
11485f80f270SRuchika Gupta if (rc)
11495f80f270SRuchika Gupta return rc;
11505f80f270SRuchika Gupta
11515f80f270SRuchika Gupta rc = serialargs_get(&ctrlargs, &wrapping_key_handle, sizeof(uint32_t));
11525f80f270SRuchika Gupta if (rc)
11535f80f270SRuchika Gupta return rc;
11545f80f270SRuchika Gupta
11555f80f270SRuchika Gupta rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
11565f80f270SRuchika Gupta if (rc)
11575f80f270SRuchika Gupta return rc;
11585f80f270SRuchika Gupta
11595f80f270SRuchika Gupta rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
11605f80f270SRuchika Gupta if (rc)
11615f80f270SRuchika Gupta return rc;
11625f80f270SRuchika Gupta
11635f80f270SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) {
11645f80f270SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD;
11655f80f270SRuchika Gupta goto out_free;
11665f80f270SRuchika Gupta }
11675f80f270SRuchika Gupta
11685f80f270SRuchika Gupta rc = get_ready_session(session);
11695f80f270SRuchika Gupta if (rc)
11705f80f270SRuchika Gupta goto out_free;
11715f80f270SRuchika Gupta
11725f80f270SRuchika Gupta wrapping_key = pkcs11_handle2object(wrapping_key_handle, session);
11735f80f270SRuchika Gupta if (!wrapping_key) {
11745f80f270SRuchika Gupta rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID;
11755f80f270SRuchika Gupta goto out_free;
11765f80f270SRuchika Gupta }
11775f80f270SRuchika Gupta
11785f80f270SRuchika Gupta key = pkcs11_handle2object(key_handle, session);
11795f80f270SRuchika Gupta if (!key) {
11805f80f270SRuchika Gupta rc = PKCS11_CKR_KEY_HANDLE_INVALID;
11815f80f270SRuchika Gupta goto out_free;
11825f80f270SRuchika Gupta }
11835f80f270SRuchika Gupta
11845f80f270SRuchika Gupta /*
11855f80f270SRuchika Gupta * The wrapping key and key to be wrapped shouldn't be same.
11865f80f270SRuchika Gupta * PKCS#11 spec doesn't explicitly state that but logically this isn't
11875f80f270SRuchika Gupta * a use case and also acts as an attack vector, so explicitly
11885f80f270SRuchika Gupta * disallow this.
11895f80f270SRuchika Gupta */
11905f80f270SRuchika Gupta if (key == wrapping_key) {
11915f80f270SRuchika Gupta rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID;
11925f80f270SRuchika Gupta goto out_free;
11935f80f270SRuchika Gupta }
11945f80f270SRuchika Gupta
11955f80f270SRuchika Gupta rc = set_processing_state(session, function, wrapping_key, NULL);
11965f80f270SRuchika Gupta if (rc)
11975f80f270SRuchika Gupta goto out_free;
11985f80f270SRuchika Gupta
11995f80f270SRuchika Gupta /* Check if mechanism can be used for wrapping function */
12005f80f270SRuchika Gupta rc = check_mechanism_against_processing(session, proc_params->id,
12015f80f270SRuchika Gupta function,
12025f80f270SRuchika Gupta PKCS11_FUNC_STEP_INIT);
12035f80f270SRuchika Gupta if (rc)
12045f80f270SRuchika Gupta goto out;
12055f80f270SRuchika Gupta
12065f80f270SRuchika Gupta /*
12075f80f270SRuchika Gupta * Check if wrapping key has CKA_WRAP set and its key type is
12085f80f270SRuchika Gupta * compatible with the mechanism passed
12095f80f270SRuchika Gupta */
12105f80f270SRuchika Gupta rc = check_parent_attrs_against_processing(proc_params->id, function,
12115f80f270SRuchika Gupta wrapping_key->attributes);
12125f80f270SRuchika Gupta if (rc) {
12135f80f270SRuchika Gupta /*
12145f80f270SRuchika Gupta * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
12155f80f270SRuchika Gupta * specified with C_Wrap() in the specification. So
12165f80f270SRuchika Gupta * return the next most appropriate error.
12175f80f270SRuchika Gupta */
12185f80f270SRuchika Gupta if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED)
12195f80f270SRuchika Gupta rc = PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
12205f80f270SRuchika Gupta
12215f80f270SRuchika Gupta goto out;
12225f80f270SRuchika Gupta }
12235f80f270SRuchika Gupta
12245f80f270SRuchika Gupta /* Check access of wrapping key */
12255f80f270SRuchika Gupta rc = check_access_attrs_against_token(session,
12265f80f270SRuchika Gupta wrapping_key->attributes);
12275f80f270SRuchika Gupta if (rc)
12285f80f270SRuchika Gupta goto out;
12295f80f270SRuchika Gupta
12305f80f270SRuchika Gupta switch (get_class(key->attributes)) {
12315f80f270SRuchika Gupta case PKCS11_CKO_SECRET_KEY:
12325f80f270SRuchika Gupta case PKCS11_CKO_PRIVATE_KEY:
123345d40bdaSValerii Chubar break;
12345f80f270SRuchika Gupta default:
12355f80f270SRuchika Gupta rc = PKCS11_CKR_KEY_NOT_WRAPPABLE;
12365f80f270SRuchika Gupta goto out;
12375f80f270SRuchika Gupta }
12385f80f270SRuchika Gupta
12395f80f270SRuchika Gupta /* Check if key to be wrapped is extractable */
12405f80f270SRuchika Gupta if (!get_bool(key->attributes, PKCS11_CKA_EXTRACTABLE)) {
12415f80f270SRuchika Gupta DMSG("Extractable property is false");
12425f80f270SRuchika Gupta rc = PKCS11_CKR_KEY_UNEXTRACTABLE;
12435f80f270SRuchika Gupta goto out;
12445f80f270SRuchika Gupta }
12455f80f270SRuchika Gupta
12465f80f270SRuchika Gupta if (get_bool(key->attributes, PKCS11_CKA_WRAP_WITH_TRUSTED) &&
12475f80f270SRuchika Gupta !get_bool(wrapping_key->attributes, PKCS11_CKA_TRUSTED)) {
12485f80f270SRuchika Gupta DMSG("Wrap with trusted not satisfied");
12495f80f270SRuchika Gupta rc = PKCS11_CKR_KEY_NOT_WRAPPABLE;
12505f80f270SRuchika Gupta goto out;
12515f80f270SRuchika Gupta }
12525f80f270SRuchika Gupta
12535f80f270SRuchika Gupta rc = check_access_attrs_against_token(session, key->attributes);
12545f80f270SRuchika Gupta if (rc)
12555f80f270SRuchika Gupta goto out;
12565f80f270SRuchika Gupta
12575f80f270SRuchika Gupta rc = get_attribute_ptr(wrapping_key->attributes,
12585f80f270SRuchika Gupta PKCS11_CKA_WRAP_TEMPLATE, &req_attrs, &size);
12595f80f270SRuchika Gupta if (rc == PKCS11_CKR_OK && size != 0) {
12605f80f270SRuchika Gupta if (!attributes_match_reference(key->attributes, req_attrs)) {
12615f80f270SRuchika Gupta rc = PKCS11_CKR_KEY_HANDLE_INVALID;
12625f80f270SRuchika Gupta goto out;
12635f80f270SRuchika Gupta }
12645f80f270SRuchika Gupta }
12655f80f270SRuchika Gupta
1266a9aa45d8SValerii Chubar rc = alloc_key_data_to_wrap(key->attributes, &key_data, &key_sz);
12675f80f270SRuchika Gupta if (rc)
12685f80f270SRuchika Gupta goto out;
12695f80f270SRuchika Gupta
12705f80f270SRuchika Gupta if (processing_is_tee_symm(proc_params->id)) {
12715f80f270SRuchika Gupta rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT,
12725f80f270SRuchika Gupta proc_params, wrapping_key);
12735f80f270SRuchika Gupta if (rc)
12745f80f270SRuchika Gupta goto out;
12755f80f270SRuchika Gupta
12765f80f270SRuchika Gupta rc = wrap_data_by_symm_enc(session, key_data, key_sz, out_buf,
12775f80f270SRuchika Gupta &out_size);
12785f80f270SRuchika Gupta } else {
127945d40bdaSValerii Chubar rc = init_asymm_operation(session, PKCS11_FUNCTION_ENCRYPT,
128045d40bdaSValerii Chubar proc_params, wrapping_key);
128145d40bdaSValerii Chubar if (rc)
128245d40bdaSValerii Chubar goto out;
128345d40bdaSValerii Chubar
128445d40bdaSValerii Chubar rc = wrap_data_by_asymm_enc(session, key_data, key_sz, out_buf,
128545d40bdaSValerii Chubar &out_size);
12865f80f270SRuchika Gupta }
12875f80f270SRuchika Gupta
12885f80f270SRuchika Gupta if (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)
12895f80f270SRuchika Gupta params[2].memref.size = out_size;
12905f80f270SRuchika Gupta
12915f80f270SRuchika Gupta out:
12925f80f270SRuchika Gupta release_active_processing(session);
12935f80f270SRuchika Gupta out_free:
1294a9aa45d8SValerii Chubar TEE_Free(key_data);
12955f80f270SRuchika Gupta TEE_Free(proc_params);
12965f80f270SRuchika Gupta return rc;
12975f80f270SRuchika Gupta }
1298