xref: /optee_os/ta/pkcs11/src/processing.c (revision 9e91a619a03fd01c1744986a56843f4da105a060)
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 
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 
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;
49*9e91a619SVesa Jääskeläinen 	case PKCS11_CMD_DIGEST_UPDATE:
50*9e91a619SVesa Jääskeläinen 	case PKCS11_CMD_DIGEST_KEY:
51*9e91a619SVesa Jääskeläinen 	case PKCS11_CMD_DIGEST_ONESHOT:
52*9e91a619SVesa Jääskeläinen 	case PKCS11_CMD_DIGEST_FINAL:
53*9e91a619SVesa 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 
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 
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 
102512cbf1dSJens Wiklander void release_active_processing(struct pkcs11_session *session)
103512cbf1dSJens Wiklander {
104512cbf1dSJens Wiklander 	if (!session->processing)
105512cbf1dSJens Wiklander 		return;
106512cbf1dSJens Wiklander 
107512cbf1dSJens Wiklander 	if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
108512cbf1dSJens Wiklander 		TEE_FreeOperation(session->processing->tee_op_handle);
109512cbf1dSJens Wiklander 		session->processing->tee_op_handle = TEE_HANDLE_NULL;
110512cbf1dSJens Wiklander 	}
111512cbf1dSJens Wiklander 
1122158ea6cSRuchika Gupta 	TEE_Free(session->processing->extra_ctx);
1132158ea6cSRuchika Gupta 
114512cbf1dSJens Wiklander 	TEE_Free(session->processing);
115512cbf1dSJens Wiklander 	session->processing = NULL;
116512cbf1dSJens Wiklander }
117512cbf1dSJens Wiklander 
118512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj)
119512cbf1dSJens Wiklander {
120512cbf1dSJens Wiklander 	uint32_t a_size = 0;
121512cbf1dSJens Wiklander 	struct obj_attrs *attrs = obj->attributes;
122512cbf1dSJens Wiklander 
123512cbf1dSJens Wiklander 	switch (get_key_type(attrs)) {
124512cbf1dSJens Wiklander 	case PKCS11_CKK_AES:
125689f4e5bSRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
126689f4e5bSRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
127689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
128689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
129689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA256_HMAC:
130689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
131689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
132512cbf1dSJens Wiklander 		if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
133512cbf1dSJens Wiklander 			return 0;
134512cbf1dSJens Wiklander 
135512cbf1dSJens Wiklander 		return a_size * 8;
136512cbf1dSJens Wiklander 	default:
137512cbf1dSJens Wiklander 		TEE_Panic(0);
138512cbf1dSJens Wiklander 		return 0;
139512cbf1dSJens Wiklander 	}
140512cbf1dSJens Wiklander }
141512cbf1dSJens Wiklander 
142fa247a2aSRuchika Gupta static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
143fa247a2aSRuchika Gupta {
144fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
145fa247a2aSRuchika Gupta 	void *data = NULL;
146fa247a2aSRuchika Gupta 	uint32_t data_size = 0;
147fa247a2aSRuchika Gupta 	uint32_t value_len = 0;
148fa247a2aSRuchika Gupta 	void *value = NULL;
149fa247a2aSRuchika Gupta 
150fa247a2aSRuchika Gupta 	if (!*head)
151fa247a2aSRuchika Gupta 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
152fa247a2aSRuchika Gupta 
153fa247a2aSRuchika Gupta 	rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size);
154fa247a2aSRuchika Gupta 	if (rc || data_size != sizeof(uint32_t)) {
155fa247a2aSRuchika Gupta 		DMSG("%s", rc ? "No attribute value_len found" :
156fa247a2aSRuchika Gupta 		     "Invalid size for attribute VALUE_LEN");
157fa247a2aSRuchika Gupta 
158fa247a2aSRuchika Gupta 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
159fa247a2aSRuchika Gupta 	}
160fa247a2aSRuchika Gupta 	TEE_MemMove(&value_len, data, data_size);
161fa247a2aSRuchika Gupta 
162fa247a2aSRuchika Gupta 	/* Remove the default empty value attribute if found */
163fa247a2aSRuchika Gupta 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
164fa247a2aSRuchika Gupta 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
165fa247a2aSRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
166fa247a2aSRuchika Gupta 
167fa247a2aSRuchika Gupta 	value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
168fa247a2aSRuchika Gupta 	if (!value)
169fa247a2aSRuchika Gupta 		return PKCS11_CKR_DEVICE_MEMORY;
170fa247a2aSRuchika Gupta 
171fa247a2aSRuchika Gupta 	TEE_GenerateRandom(value, value_len);
172fa247a2aSRuchika Gupta 
173fa247a2aSRuchika Gupta 	rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
174fa247a2aSRuchika Gupta 
175fa247a2aSRuchika Gupta 	TEE_Free(value);
176fa247a2aSRuchika Gupta 
177fa247a2aSRuchika Gupta 	return rc;
178fa247a2aSRuchika Gupta }
179fa247a2aSRuchika Gupta 
180fa247a2aSRuchika Gupta enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
181fa247a2aSRuchika Gupta 				     uint32_t ptypes, TEE_Param *params)
182fa247a2aSRuchika Gupta {
183fa247a2aSRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
184fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE,
185fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
186fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE);
187fa247a2aSRuchika Gupta 	TEE_Param *ctrl = params;
188fa247a2aSRuchika Gupta 	TEE_Param *out = params + 2;
189fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
190fa247a2aSRuchika Gupta 	struct serialargs ctrlargs = { };
191fa247a2aSRuchika Gupta 	struct pkcs11_session *session = NULL;
192fa247a2aSRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
193fa247a2aSRuchika Gupta 	struct obj_attrs *head = NULL;
194fa247a2aSRuchika Gupta 	struct pkcs11_object_head *template = NULL;
195fa247a2aSRuchika Gupta 	size_t template_size = 0;
196fa247a2aSRuchika Gupta 	uint32_t obj_handle = 0;
197fa247a2aSRuchika Gupta 
198fa247a2aSRuchika Gupta 	if (!client || ptypes != exp_pt ||
199fa247a2aSRuchika Gupta 	    out->memref.size != sizeof(obj_handle))
200fa247a2aSRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
201fa247a2aSRuchika Gupta 
202fa247a2aSRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
203fa247a2aSRuchika Gupta 
204fa247a2aSRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
205fa247a2aSRuchika Gupta 	if (rc)
206fa247a2aSRuchika Gupta 		return rc;
207fa247a2aSRuchika Gupta 
208fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
209fa247a2aSRuchika Gupta 	if (rc)
210fa247a2aSRuchika Gupta 		goto out;
211fa247a2aSRuchika Gupta 
212fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
213fa247a2aSRuchika Gupta 	if (rc)
214fa247a2aSRuchika Gupta 		goto out;
215fa247a2aSRuchika Gupta 
216fa247a2aSRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
217fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
218fa247a2aSRuchika Gupta 		goto out;
219fa247a2aSRuchika Gupta 	}
220fa247a2aSRuchika Gupta 
221fa247a2aSRuchika Gupta 	rc = get_ready_session(session);
222fa247a2aSRuchika Gupta 	if (rc)
223fa247a2aSRuchika Gupta 		goto out;
224fa247a2aSRuchika Gupta 
225fa247a2aSRuchika Gupta 	template_size = sizeof(*template) + template->attrs_size;
226fa247a2aSRuchika Gupta 
227fa247a2aSRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
228fa247a2aSRuchika Gupta 						PKCS11_FUNCTION_GENERATE,
229fa247a2aSRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
230fa247a2aSRuchika Gupta 	if (rc) {
231fa247a2aSRuchika Gupta 		DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
232fa247a2aSRuchika Gupta 		goto out;
233fa247a2aSRuchika Gupta 	}
234fa247a2aSRuchika Gupta 
235fa247a2aSRuchika Gupta 	/*
236fa247a2aSRuchika Gupta 	 * Prepare a clean initial state for the requested object attributes.
237fa247a2aSRuchika Gupta 	 * Free temporary template once done.
238fa247a2aSRuchika Gupta 	 */
239fa247a2aSRuchika Gupta 	rc = create_attributes_from_template(&head, template, template_size,
240fa247a2aSRuchika Gupta 					     NULL, PKCS11_FUNCTION_GENERATE,
2414cfce748SRuchika Gupta 					     proc_params->id,
2424cfce748SRuchika Gupta 					     PKCS11_CKO_UNDEFINED_ID);
243fa247a2aSRuchika Gupta 	if (rc)
244fa247a2aSRuchika Gupta 		goto out;
245fa247a2aSRuchika Gupta 
246fa247a2aSRuchika Gupta 	TEE_Free(template);
247fa247a2aSRuchika Gupta 	template = NULL;
248fa247a2aSRuchika Gupta 
249fa247a2aSRuchika Gupta 	rc = check_created_attrs(head, NULL);
250fa247a2aSRuchika Gupta 	if (rc)
251fa247a2aSRuchika Gupta 		goto out;
252fa247a2aSRuchika Gupta 
253fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_processing(proc_params->id, head);
254fa247a2aSRuchika Gupta 	if (rc)
255fa247a2aSRuchika Gupta 		goto out;
256fa247a2aSRuchika Gupta 
257fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_token(session, head);
258fa247a2aSRuchika Gupta 	if (rc)
259fa247a2aSRuchika Gupta 		goto out;
260fa247a2aSRuchika Gupta 
261fa247a2aSRuchika Gupta 	/*
262fa247a2aSRuchika Gupta 	 * Execute target processing and add value as attribute
263fa247a2aSRuchika Gupta 	 * PKCS11_CKA_VALUE. Symm key generation: depends on target
264fa247a2aSRuchika Gupta 	 * processing to be used.
265fa247a2aSRuchika Gupta 	 */
266fa247a2aSRuchika Gupta 	switch (proc_params->id) {
267fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
268fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
269fa247a2aSRuchika Gupta 		/* Generate random of size specified by attribute VALUE_LEN */
270fa247a2aSRuchika Gupta 		rc = generate_random_key_value(&head);
271fa247a2aSRuchika Gupta 		if (rc)
272fa247a2aSRuchika Gupta 			goto out;
273fa247a2aSRuchika Gupta 		break;
274fa247a2aSRuchika Gupta 
275fa247a2aSRuchika Gupta 	default:
276fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
277fa247a2aSRuchika Gupta 		goto out;
278fa247a2aSRuchika Gupta 	}
279fa247a2aSRuchika Gupta 
280fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
281fa247a2aSRuchika Gupta 	proc_params = NULL;
282fa247a2aSRuchika Gupta 
283fa247a2aSRuchika Gupta 	/*
284fa247a2aSRuchika Gupta 	 * Object is ready, register it and return a handle.
285fa247a2aSRuchika Gupta 	 */
286fa247a2aSRuchika Gupta 	rc = create_object(session, head, &obj_handle);
287fa247a2aSRuchika Gupta 	if (rc)
288fa247a2aSRuchika Gupta 		goto out;
289fa247a2aSRuchika Gupta 
290fa247a2aSRuchika Gupta 	/*
291fa247a2aSRuchika Gupta 	 * Now obj_handle (through the related struct pkcs11_object instance)
292fa247a2aSRuchika Gupta 	 * owns the serialized buffer that holds the object attributes.
293fa247a2aSRuchika Gupta 	 * We reset head to NULL as it is no more the buffer owner and would
294fa247a2aSRuchika Gupta 	 * be freed at function out.
295fa247a2aSRuchika Gupta 	 */
296fa247a2aSRuchika Gupta 	head = NULL;
297fa247a2aSRuchika Gupta 
298fa247a2aSRuchika Gupta 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
299fa247a2aSRuchika Gupta 	out->memref.size = sizeof(obj_handle);
300fa247a2aSRuchika Gupta 
301fa247a2aSRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
302fa247a2aSRuchika Gupta 	     session->handle, obj_handle);
303fa247a2aSRuchika Gupta 
304fa247a2aSRuchika Gupta out:
305fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
306fa247a2aSRuchika Gupta 	TEE_Free(template);
307fa247a2aSRuchika Gupta 	TEE_Free(head);
308fa247a2aSRuchika Gupta 
309fa247a2aSRuchika Gupta 	return rc;
310fa247a2aSRuchika Gupta }
311fa247a2aSRuchika Gupta 
312512cbf1dSJens Wiklander /*
313512cbf1dSJens Wiklander  * entry_processing_init - Generic entry for initializing a processing
314512cbf1dSJens Wiklander  *
315512cbf1dSJens Wiklander  * @client = client reference
316512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
317512cbf1dSJens Wiklander  * @params = Invocation parameters reference
318512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
319512cbf1dSJens Wiklander  */
320512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
321512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
322512cbf1dSJens Wiklander 				     enum processing_func function)
323512cbf1dSJens Wiklander {
324512cbf1dSJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
325512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
326512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
327512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE);
328512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
329512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
330512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
331512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
332512cbf1dSJens Wiklander 	struct pkcs11_attribute_head *proc_params = NULL;
333512cbf1dSJens Wiklander 	uint32_t key_handle = 0;
334512cbf1dSJens Wiklander 	struct pkcs11_object *obj = NULL;
335512cbf1dSJens Wiklander 
336512cbf1dSJens Wiklander 	if (!client || ptypes != exp_pt)
337512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
338512cbf1dSJens Wiklander 
339512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
340512cbf1dSJens Wiklander 
341512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
342512cbf1dSJens Wiklander 	if (rc)
343512cbf1dSJens Wiklander 		return rc;
344512cbf1dSJens Wiklander 
345*9e91a619SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_DIGEST) {
346512cbf1dSJens Wiklander 		rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
347512cbf1dSJens Wiklander 		if (rc)
348512cbf1dSJens Wiklander 			return rc;
349*9e91a619SVesa Jääskeläinen 	}
350512cbf1dSJens Wiklander 
351512cbf1dSJens Wiklander 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
352512cbf1dSJens Wiklander 	if (rc)
353512cbf1dSJens Wiklander 		return rc;
354512cbf1dSJens Wiklander 
355512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs)) {
356512cbf1dSJens Wiklander 		rc = PKCS11_CKR_ARGUMENTS_BAD;
357512cbf1dSJens Wiklander 		goto out;
358512cbf1dSJens Wiklander 	}
359512cbf1dSJens Wiklander 
360512cbf1dSJens Wiklander 	rc = get_ready_session(session);
361512cbf1dSJens Wiklander 	if (rc)
362512cbf1dSJens Wiklander 		goto out;
363512cbf1dSJens Wiklander 
364*9e91a619SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_DIGEST) {
365512cbf1dSJens Wiklander 		obj = pkcs11_handle2object(key_handle, session);
366512cbf1dSJens Wiklander 		if (!obj) {
367512cbf1dSJens Wiklander 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
368512cbf1dSJens Wiklander 			goto out;
369512cbf1dSJens Wiklander 		}
370*9e91a619SVesa Jääskeläinen 	}
371512cbf1dSJens Wiklander 
372512cbf1dSJens Wiklander 	rc = set_processing_state(session, function, obj, NULL);
373512cbf1dSJens Wiklander 	if (rc)
374512cbf1dSJens Wiklander 		goto out;
375512cbf1dSJens Wiklander 
376512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, proc_params->id,
377512cbf1dSJens Wiklander 						function,
378512cbf1dSJens Wiklander 						PKCS11_FUNC_STEP_INIT);
379512cbf1dSJens Wiklander 	if (rc)
380512cbf1dSJens Wiklander 		goto out;
381512cbf1dSJens Wiklander 
382*9e91a619SVesa Jääskeläinen 	if (obj) {
383*9e91a619SVesa Jääskeläinen 		rc = check_parent_attrs_against_processing(proc_params->id,
384*9e91a619SVesa Jääskeläinen 							   function,
385512cbf1dSJens Wiklander 							   obj->attributes);
386512cbf1dSJens Wiklander 		if (rc)
387512cbf1dSJens Wiklander 			goto out;
388512cbf1dSJens Wiklander 
389*9e91a619SVesa Jääskeläinen 		rc = check_access_attrs_against_token(session,
390*9e91a619SVesa Jääskeläinen 						      obj->attributes);
391512cbf1dSJens Wiklander 		if (rc)
392512cbf1dSJens Wiklander 			goto out;
393*9e91a619SVesa Jääskeläinen 	}
394512cbf1dSJens Wiklander 
395512cbf1dSJens Wiklander 	if (processing_is_tee_symm(proc_params->id))
396512cbf1dSJens Wiklander 		rc = init_symm_operation(session, function, proc_params, obj);
397*9e91a619SVesa Jääskeläinen 	else if (processing_is_tee_digest(proc_params->id))
398*9e91a619SVesa Jääskeläinen 		rc = init_digest_operation(session, proc_params);
399512cbf1dSJens Wiklander 	else
400512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
401512cbf1dSJens Wiklander 
402512cbf1dSJens Wiklander 	if (rc == PKCS11_CKR_OK) {
403512cbf1dSJens Wiklander 		session->processing->mecha_type = proc_params->id;
404512cbf1dSJens Wiklander 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
405512cbf1dSJens Wiklander 		     session->handle, id2str_proc(proc_params->id),
406512cbf1dSJens Wiklander 		     id2str_function(function));
407512cbf1dSJens Wiklander 	}
408512cbf1dSJens Wiklander 
409512cbf1dSJens Wiklander out:
410512cbf1dSJens Wiklander 	if (rc && session)
411512cbf1dSJens Wiklander 		release_active_processing(session);
412512cbf1dSJens Wiklander 
413512cbf1dSJens Wiklander 	TEE_Free(proc_params);
414512cbf1dSJens Wiklander 
415512cbf1dSJens Wiklander 	return rc;
416512cbf1dSJens Wiklander }
417512cbf1dSJens Wiklander 
418512cbf1dSJens Wiklander /*
419512cbf1dSJens Wiklander  * entry_processing_step - Generic entry on active processing
420512cbf1dSJens Wiklander  *
421512cbf1dSJens Wiklander  * @client = client reference
422512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
423512cbf1dSJens Wiklander  * @params = Invocation parameters reference
424512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
425512cbf1dSJens Wiklander  * @step - update, oneshot, final
426512cbf1dSJens Wiklander  */
427512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
428512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
429512cbf1dSJens Wiklander 				     enum processing_func function,
430512cbf1dSJens Wiklander 				     enum processing_step step)
431512cbf1dSJens Wiklander {
432512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
433512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
434512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
435512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
436512cbf1dSJens Wiklander 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
437*9e91a619SVesa Jääskeläinen 	uint32_t key_handle = 0;
438*9e91a619SVesa Jääskeläinen 	struct pkcs11_object *obj = NULL;
439512cbf1dSJens Wiklander 
440512cbf1dSJens Wiklander 	if (!client ||
441512cbf1dSJens Wiklander 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
442512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
443512cbf1dSJens Wiklander 
444512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
445512cbf1dSJens Wiklander 
446512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
447512cbf1dSJens Wiklander 	if (rc)
448512cbf1dSJens Wiklander 		return rc;
449512cbf1dSJens Wiklander 
450*9e91a619SVesa Jääskeläinen 	if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
451*9e91a619SVesa Jääskeläinen 		assert(function == PKCS11_FUNCTION_DIGEST);
452*9e91a619SVesa Jääskeläinen 
453*9e91a619SVesa Jääskeläinen 		rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
454*9e91a619SVesa Jääskeläinen 		if (rc)
455*9e91a619SVesa Jääskeläinen 			return rc;
456*9e91a619SVesa Jääskeläinen 	}
457*9e91a619SVesa Jääskeläinen 
458512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs))
459512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
460512cbf1dSJens Wiklander 
461512cbf1dSJens Wiklander 	rc = get_active_session(session, function);
462512cbf1dSJens Wiklander 	if (rc)
463512cbf1dSJens Wiklander 		return rc;
464512cbf1dSJens Wiklander 
465*9e91a619SVesa Jääskeläinen 	if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
466*9e91a619SVesa Jääskeläinen 		assert(function == PKCS11_FUNCTION_DIGEST);
467*9e91a619SVesa Jääskeläinen 
468*9e91a619SVesa Jääskeläinen 		obj = pkcs11_handle2object(key_handle, session);
469*9e91a619SVesa Jääskeläinen 		if (!obj) {
470*9e91a619SVesa Jääskeläinen 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
471*9e91a619SVesa Jääskeläinen 			goto out;
472*9e91a619SVesa Jääskeläinen 		}
473*9e91a619SVesa Jääskeläinen 
474*9e91a619SVesa Jääskeläinen 		rc = check_access_attrs_against_token(session,
475*9e91a619SVesa Jääskeläinen 						      obj->attributes);
476*9e91a619SVesa Jääskeläinen 		if (rc) {
477*9e91a619SVesa Jääskeläinen 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
478*9e91a619SVesa Jääskeläinen 			goto out;
479*9e91a619SVesa Jääskeläinen 		}
480*9e91a619SVesa Jääskeläinen 	}
481*9e91a619SVesa Jääskeläinen 
482512cbf1dSJens Wiklander 	mecha_type = session->processing->mecha_type;
483512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, mecha_type,
484512cbf1dSJens Wiklander 						function, step);
485512cbf1dSJens Wiklander 	if (rc)
486512cbf1dSJens Wiklander 		goto out;
487512cbf1dSJens Wiklander 
488512cbf1dSJens Wiklander 	if (processing_is_tee_symm(mecha_type))
489512cbf1dSJens Wiklander 		rc = step_symm_operation(session, function, step,
490512cbf1dSJens Wiklander 					 ptypes, params);
491*9e91a619SVesa Jääskeläinen 	else if (processing_is_tee_digest(mecha_type))
492*9e91a619SVesa Jääskeläinen 		rc = step_digest_operation(session, step, obj, ptypes, params);
493512cbf1dSJens Wiklander 	else
494512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
495512cbf1dSJens Wiklander 
496*9e91a619SVesa Jääskeläinen 	if (rc == PKCS11_CKR_OK && (step == PKCS11_FUNC_STEP_UPDATE ||
497*9e91a619SVesa Jääskeläinen 				    step == PKCS11_FUNC_STEP_UPDATE_KEY)) {
498512cbf1dSJens Wiklander 		session->processing->updated = true;
499512cbf1dSJens Wiklander 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
500512cbf1dSJens Wiklander 		     session->handle, id2str_proc(mecha_type),
501512cbf1dSJens Wiklander 		     id2str_function(function));
502512cbf1dSJens Wiklander 	}
503512cbf1dSJens Wiklander 
504512cbf1dSJens Wiklander out:
505512cbf1dSJens Wiklander 	switch (step) {
506512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_UPDATE:
507*9e91a619SVesa Jääskeläinen 	case PKCS11_FUNC_STEP_UPDATE_KEY:
508512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
509512cbf1dSJens Wiklander 			release_active_processing(session);
510512cbf1dSJens Wiklander 		break;
511512cbf1dSJens Wiklander 	default:
512512cbf1dSJens Wiklander 		/* ONESHOT and FINAL terminates processing on success */
513512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
514512cbf1dSJens Wiklander 			release_active_processing(session);
515512cbf1dSJens Wiklander 		break;
516512cbf1dSJens Wiklander 	}
517512cbf1dSJens Wiklander 
518512cbf1dSJens Wiklander 	return rc;
519512cbf1dSJens Wiklander }
52048799892SRuchika Gupta 
5214dad6642SRuchika Gupta enum pkcs11_rc entry_processing_key(struct pkcs11_client *client,
5224dad6642SRuchika Gupta 				    uint32_t ptypes, TEE_Param *params,
5234dad6642SRuchika Gupta 				    enum processing_func function)
52448799892SRuchika Gupta {
52548799892SRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
52648799892SRuchika Gupta 						TEE_PARAM_TYPE_NONE,
52748799892SRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
52848799892SRuchika Gupta 						TEE_PARAM_TYPE_NONE);
52948799892SRuchika Gupta 	TEE_Param *ctrl = params;
53048799892SRuchika Gupta 	TEE_Param *out = params + 2;
53148799892SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
53248799892SRuchika Gupta 	struct serialargs ctrlargs = { };
53348799892SRuchika Gupta 	struct pkcs11_session *session = NULL;
53448799892SRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
53548799892SRuchika Gupta 	struct pkcs11_object_head *template = NULL;
53648799892SRuchika Gupta 	uint32_t parent_handle = 0;
53748799892SRuchika Gupta 	uint32_t obj_handle = 0;
53848799892SRuchika Gupta 	struct pkcs11_object *parent = NULL;
53948799892SRuchika Gupta 	struct obj_attrs *head = NULL;
54048799892SRuchika Gupta 	size_t template_size = 0;
5418c499324SRuchika Gupta 	void *out_buf = NULL;
5428c499324SRuchika Gupta 	uint32_t out_size = 0;
54348799892SRuchika Gupta 
54448799892SRuchika Gupta 	if (!client || ptypes != exp_pt ||
54548799892SRuchika Gupta 	    out->memref.size != sizeof(obj_handle))
54648799892SRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
54748799892SRuchika Gupta 
54848799892SRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
54948799892SRuchika Gupta 
55048799892SRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
55148799892SRuchika Gupta 	if (rc)
55248799892SRuchika Gupta 		return rc;
55348799892SRuchika Gupta 
55448799892SRuchika Gupta 	rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t));
55548799892SRuchika Gupta 	if (rc)
55648799892SRuchika Gupta 		return rc;
55748799892SRuchika Gupta 
55848799892SRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
55948799892SRuchika Gupta 	if (rc)
56048799892SRuchika Gupta 		goto out_free;
56148799892SRuchika Gupta 
56248799892SRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
56348799892SRuchika Gupta 	if (rc)
56448799892SRuchika Gupta 		goto out_free;
56548799892SRuchika Gupta 
56648799892SRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
56748799892SRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
56848799892SRuchika Gupta 		goto out_free;
56948799892SRuchika Gupta 	}
57048799892SRuchika Gupta 
57148799892SRuchika Gupta 	/* Return error if processing already active */
57248799892SRuchika Gupta 	rc = get_ready_session(session);
57348799892SRuchika Gupta 	if (rc)
57448799892SRuchika Gupta 		goto out_free;
57548799892SRuchika Gupta 
57648799892SRuchika Gupta 	/* Check parent handle */
57748799892SRuchika Gupta 	parent = pkcs11_handle2object(parent_handle, session);
57848799892SRuchika Gupta 	if (!parent) {
57948799892SRuchika Gupta 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
58048799892SRuchika Gupta 		goto out_free;
58148799892SRuchika Gupta 	}
58248799892SRuchika Gupta 
58348799892SRuchika Gupta 	/* Check if mechanism can be used for derivation function */
58448799892SRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
58548799892SRuchika Gupta 						function,
58648799892SRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
58748799892SRuchika Gupta 	if (rc)
58848799892SRuchika Gupta 		goto out_free;
58948799892SRuchika Gupta 
59048799892SRuchika Gupta 	/* Set the processing state to active */
59148799892SRuchika Gupta 	rc = set_processing_state(session, function, parent, NULL);
59248799892SRuchika Gupta 	if (rc)
59348799892SRuchika Gupta 		goto out_free;
59448799892SRuchika Gupta 
59548799892SRuchika Gupta 	/*
59648799892SRuchika Gupta 	 * Check if base/parent key has CKA_DERIVE set and its key type is
59748799892SRuchika Gupta 	 * compatible with the mechanism passed
59848799892SRuchika Gupta 	 */
59948799892SRuchika Gupta 	rc = check_parent_attrs_against_processing(proc_params->id, function,
60048799892SRuchika Gupta 						   parent->attributes);
601d05ab5feSRuchika Gupta 	if (rc) {
602d05ab5feSRuchika Gupta 		/*
603d05ab5feSRuchika Gupta 		 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
604d05ab5feSRuchika Gupta 		 * specified with C_Derive/Unwrap() in the specification. So
605d05ab5feSRuchika Gupta 		 * return the next most appropriate error.
606d05ab5feSRuchika Gupta 		 */
607d05ab5feSRuchika Gupta 		if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED)
608d05ab5feSRuchika Gupta 			rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT;
60948799892SRuchika Gupta 		goto out;
610d05ab5feSRuchika Gupta 	}
61148799892SRuchika Gupta 
61248799892SRuchika Gupta 	/* Check access of base/parent key */
61348799892SRuchika Gupta 	rc = check_access_attrs_against_token(session, parent->attributes);
61448799892SRuchika Gupta 	if (rc)
61548799892SRuchika Gupta 		goto out;
61648799892SRuchika Gupta 
61748799892SRuchika Gupta 	template_size = sizeof(*template) + template->attrs_size;
61848799892SRuchika Gupta 	/*
61948799892SRuchika Gupta 	 * Prepare a clean initial state for the requested object attributes
62048799892SRuchika Gupta 	 * using base/parent key attributes. Free temporary template once done.
62148799892SRuchika Gupta 	 */
62248799892SRuchika Gupta 	rc = create_attributes_from_template(&head, template, template_size,
62348799892SRuchika Gupta 					     parent->attributes,
62448799892SRuchika Gupta 					     function,
62548799892SRuchika Gupta 					     proc_params->id,
62648799892SRuchika Gupta 					     PKCS11_CKO_UNDEFINED_ID);
62748799892SRuchika Gupta 	if (rc)
62848799892SRuchika Gupta 		goto out;
62948799892SRuchika Gupta 
63048799892SRuchika Gupta 	TEE_Free(template);
63148799892SRuchika Gupta 	template = NULL;
63248799892SRuchika Gupta 
63348799892SRuchika Gupta 	/* check_created_attrs() is called later once key size is known */
63448799892SRuchika Gupta 
63548799892SRuchika Gupta 	rc = check_created_attrs_against_processing(proc_params->id, head);
63648799892SRuchika Gupta 	if (rc)
63748799892SRuchika Gupta 		goto out;
63848799892SRuchika Gupta 
63948799892SRuchika Gupta 	rc = check_created_attrs_against_token(session, head);
64048799892SRuchika Gupta 	if (rc)
64148799892SRuchika Gupta 		goto out;
64248799892SRuchika Gupta 
6438c499324SRuchika Gupta 	if (processing_is_tee_symm(proc_params->id)) {
64448799892SRuchika Gupta 		/*
64548799892SRuchika Gupta 		 * These derivation mechanism require encryption to be
64648799892SRuchika Gupta 		 * performed on the data passed in proc_params by parent
64748799892SRuchika Gupta 		 * key. Hence pass function as PKCS11_FUNCTION_ENCRYPT
64848799892SRuchika Gupta 		 * to init_symm_operation()
64948799892SRuchika Gupta 		 */
65048799892SRuchika Gupta 		rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT,
65148799892SRuchika Gupta 					 proc_params, parent);
65248799892SRuchika Gupta 		if (rc)
65348799892SRuchika Gupta 			goto out;
65448799892SRuchika Gupta 
6558c499324SRuchika Gupta 		session->processing->mecha_type = proc_params->id;
6568c499324SRuchika Gupta 
6578c499324SRuchika Gupta 		rc = derive_key_by_symm_enc(session, &out_buf, &out_size);
65848799892SRuchika Gupta 		if (rc)
65948799892SRuchika Gupta 			goto out;
6608c499324SRuchika Gupta 	} else {
66148799892SRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
66248799892SRuchika Gupta 		goto out;
66348799892SRuchika Gupta 	}
66448799892SRuchika Gupta 
6658c499324SRuchika Gupta 	rc = set_key_data(&head, out_buf, out_size);
6668c499324SRuchika Gupta 	if (rc)
6678c499324SRuchika Gupta 		goto out;
6688c499324SRuchika Gupta 
6698c499324SRuchika Gupta 	TEE_Free(out_buf);
6708c499324SRuchika Gupta 	out_buf = NULL;
6718c499324SRuchika Gupta 
67248799892SRuchika Gupta 	TEE_Free(proc_params);
67348799892SRuchika Gupta 	proc_params = NULL;
67448799892SRuchika Gupta 
67548799892SRuchika Gupta 	/*
67648799892SRuchika Gupta 	 * Object is ready, register it and return a handle.
67748799892SRuchika Gupta 	 */
67848799892SRuchika Gupta 	rc = create_object(session, head, &obj_handle);
67948799892SRuchika Gupta 	if (rc)
68048799892SRuchika Gupta 		goto out;
68148799892SRuchika Gupta 
68248799892SRuchika Gupta 	/*
68348799892SRuchika Gupta 	 * Now obj_handle (through the related struct pkcs11_object instance)
68448799892SRuchika Gupta 	 * owns the serialized buffer that holds the object attributes.
68548799892SRuchika Gupta 	 * We reset head to NULL as it is no more the buffer owner and would
68648799892SRuchika Gupta 	 * be freed at function out.
68748799892SRuchika Gupta 	 */
68848799892SRuchika Gupta 	head = NULL;
68948799892SRuchika Gupta 
69048799892SRuchika Gupta 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
69148799892SRuchika Gupta 	out->memref.size = sizeof(obj_handle);
69248799892SRuchika Gupta 
69348799892SRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32,
69448799892SRuchika Gupta 	     session->handle, obj_handle);
69548799892SRuchika Gupta 
69648799892SRuchika Gupta out:
69748799892SRuchika Gupta 	release_active_processing(session);
69848799892SRuchika Gupta out_free:
69948799892SRuchika Gupta 	TEE_Free(proc_params);
70048799892SRuchika Gupta 	TEE_Free(template);
70148799892SRuchika Gupta 	TEE_Free(head);
7028c499324SRuchika Gupta 	TEE_Free(out_buf);
70348799892SRuchika Gupta 
70448799892SRuchika Gupta 	return rc;
70548799892SRuchika Gupta }
706eb6141b6SVesa Jääskeläinen 
707eb6141b6SVesa Jääskeläinen enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client,
708eb6141b6SVesa Jääskeläinen 					       uint32_t ptypes,
709eb6141b6SVesa Jääskeläinen 					       TEE_Param *params)
710eb6141b6SVesa Jääskeläinen {
711eb6141b6SVesa Jääskeläinen 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
712eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE,
713eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE,
714eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE);
715eb6141b6SVesa Jääskeläinen 	TEE_Param *ctrl = params;
716eb6141b6SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
717eb6141b6SVesa Jääskeläinen 	struct serialargs ctrlargs = { };
718eb6141b6SVesa Jääskeläinen 	struct pkcs11_session *session = NULL;
719eb6141b6SVesa Jääskeläinen 	enum processing_func function = PKCS11_FUNCTION_UNKNOWN;
720eb6141b6SVesa Jääskeläinen 	uint32_t cmd = 0;
721eb6141b6SVesa Jääskeläinen 
722eb6141b6SVesa Jääskeläinen 	if (!client || ptypes != exp_pt)
723eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
724eb6141b6SVesa Jääskeläinen 
725eb6141b6SVesa Jääskeläinen 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
726eb6141b6SVesa Jääskeläinen 
727eb6141b6SVesa Jääskeläinen 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
728eb6141b6SVesa Jääskeläinen 	if (rc)
729eb6141b6SVesa Jääskeläinen 		return rc;
730eb6141b6SVesa Jääskeläinen 
731eb6141b6SVesa Jääskeläinen 	rc = serialargs_get_u32(&ctrlargs, &cmd);
732eb6141b6SVesa Jääskeläinen 
733eb6141b6SVesa Jääskeläinen 	if (serialargs_remaining_bytes(&ctrlargs))
734eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
735eb6141b6SVesa Jääskeläinen 
736eb6141b6SVesa Jääskeläinen 	function = func_for_cmd(cmd);
737eb6141b6SVesa Jääskeläinen 	if (function == PKCS11_FUNCTION_UNKNOWN)
738eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
739eb6141b6SVesa Jääskeläinen 
740eb6141b6SVesa Jääskeläinen 	rc = get_active_session(session, function);
741eb6141b6SVesa Jääskeläinen 	if (rc)
742eb6141b6SVesa Jääskeläinen 		return rc;
743eb6141b6SVesa Jääskeläinen 
744eb6141b6SVesa Jääskeläinen 	release_active_processing(session);
745eb6141b6SVesa Jääskeläinen 
746eb6141b6SVesa Jääskeläinen 	DMSG("PKCS11 session %"PRIu32": release processing", session->handle);
747eb6141b6SVesa Jääskeläinen 
748eb6141b6SVesa Jääskeläinen 	return PKCS11_CKR_OK;
749eb6141b6SVesa Jääskeläinen }
750