xref: /optee_os/ta/pkcs11/src/processing.c (revision 4dad6642f7009ed11de0d69769f5af15a8458ba7)
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 
30512cbf1dSJens Wiklander static bool func_matches_state(enum processing_func function,
31512cbf1dSJens Wiklander 			       enum pkcs11_proc_state state)
32512cbf1dSJens Wiklander {
33512cbf1dSJens Wiklander 	switch (function) {
34512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_ENCRYPT:
35512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_ENCRYPTING ||
36512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DIGESTING_ENCRYPTING ||
37512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_SIGNING_ENCRYPTING;
38512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DECRYPT:
39512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_DECRYPTING ||
40512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_DIGESTING ||
41512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_VERIFYING;
42512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DIGEST:
43512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_DIGESTING ||
44512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DIGESTING_ENCRYPTING;
45512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN:
46512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING ||
47512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_SIGNING_ENCRYPTING;
48512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY:
49512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_VERIFYING ||
50512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_VERIFYING;
51512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN_RECOVER:
52512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING_RECOVER;
53512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY_RECOVER:
54512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING_RECOVER;
55512cbf1dSJens Wiklander 	default:
56512cbf1dSJens Wiklander 		TEE_Panic(function);
57512cbf1dSJens Wiklander 		return false;
58512cbf1dSJens Wiklander 	}
59512cbf1dSJens Wiklander }
60512cbf1dSJens Wiklander 
61512cbf1dSJens Wiklander static enum pkcs11_rc get_active_session(struct pkcs11_session *session,
62512cbf1dSJens Wiklander 					 enum processing_func function)
63512cbf1dSJens Wiklander {
64512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED;
65512cbf1dSJens Wiklander 
66512cbf1dSJens Wiklander 	if (session->processing &&
67512cbf1dSJens Wiklander 	    func_matches_state(function, session->processing->state))
68512cbf1dSJens Wiklander 		rc = PKCS11_CKR_OK;
69512cbf1dSJens Wiklander 
70512cbf1dSJens Wiklander 	return rc;
71512cbf1dSJens Wiklander }
72512cbf1dSJens Wiklander 
73512cbf1dSJens Wiklander void release_active_processing(struct pkcs11_session *session)
74512cbf1dSJens Wiklander {
75512cbf1dSJens Wiklander 	if (!session->processing)
76512cbf1dSJens Wiklander 		return;
77512cbf1dSJens Wiklander 
78512cbf1dSJens Wiklander 	if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
79512cbf1dSJens Wiklander 		TEE_FreeOperation(session->processing->tee_op_handle);
80512cbf1dSJens Wiklander 		session->processing->tee_op_handle = TEE_HANDLE_NULL;
81512cbf1dSJens Wiklander 	}
82512cbf1dSJens Wiklander 
832158ea6cSRuchika Gupta 	TEE_Free(session->processing->extra_ctx);
842158ea6cSRuchika Gupta 
85512cbf1dSJens Wiklander 	TEE_Free(session->processing);
86512cbf1dSJens Wiklander 	session->processing = NULL;
87512cbf1dSJens Wiklander }
88512cbf1dSJens Wiklander 
89512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj)
90512cbf1dSJens Wiklander {
91512cbf1dSJens Wiklander 	uint32_t a_size = 0;
92512cbf1dSJens Wiklander 	struct obj_attrs *attrs = obj->attributes;
93512cbf1dSJens Wiklander 
94512cbf1dSJens Wiklander 	switch (get_key_type(attrs)) {
95512cbf1dSJens Wiklander 	case PKCS11_CKK_AES:
96689f4e5bSRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
97689f4e5bSRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
98689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
99689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
100689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA256_HMAC:
101689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
102689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
103512cbf1dSJens Wiklander 		if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
104512cbf1dSJens Wiklander 			return 0;
105512cbf1dSJens Wiklander 
106512cbf1dSJens Wiklander 		return a_size * 8;
107512cbf1dSJens Wiklander 	default:
108512cbf1dSJens Wiklander 		TEE_Panic(0);
109512cbf1dSJens Wiklander 		return 0;
110512cbf1dSJens Wiklander 	}
111512cbf1dSJens Wiklander }
112512cbf1dSJens Wiklander 
113fa247a2aSRuchika Gupta static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
114fa247a2aSRuchika Gupta {
115fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
116fa247a2aSRuchika Gupta 	void *data = NULL;
117fa247a2aSRuchika Gupta 	uint32_t data_size = 0;
118fa247a2aSRuchika Gupta 	uint32_t value_len = 0;
119fa247a2aSRuchika Gupta 	void *value = NULL;
120fa247a2aSRuchika Gupta 
121fa247a2aSRuchika Gupta 	if (!*head)
122fa247a2aSRuchika Gupta 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
123fa247a2aSRuchika Gupta 
124fa247a2aSRuchika Gupta 	rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size);
125fa247a2aSRuchika Gupta 	if (rc || data_size != sizeof(uint32_t)) {
126fa247a2aSRuchika Gupta 		DMSG("%s", rc ? "No attribute value_len found" :
127fa247a2aSRuchika Gupta 		     "Invalid size for attribute VALUE_LEN");
128fa247a2aSRuchika Gupta 
129fa247a2aSRuchika Gupta 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
130fa247a2aSRuchika Gupta 	}
131fa247a2aSRuchika Gupta 	TEE_MemMove(&value_len, data, data_size);
132fa247a2aSRuchika Gupta 
133fa247a2aSRuchika Gupta 	/* Remove the default empty value attribute if found */
134fa247a2aSRuchika Gupta 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
135fa247a2aSRuchika Gupta 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
136fa247a2aSRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
137fa247a2aSRuchika Gupta 
138fa247a2aSRuchika Gupta 	value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
139fa247a2aSRuchika Gupta 	if (!value)
140fa247a2aSRuchika Gupta 		return PKCS11_CKR_DEVICE_MEMORY;
141fa247a2aSRuchika Gupta 
142fa247a2aSRuchika Gupta 	TEE_GenerateRandom(value, value_len);
143fa247a2aSRuchika Gupta 
144fa247a2aSRuchika Gupta 	rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
145fa247a2aSRuchika Gupta 
146fa247a2aSRuchika Gupta 	TEE_Free(value);
147fa247a2aSRuchika Gupta 
148fa247a2aSRuchika Gupta 	return rc;
149fa247a2aSRuchika Gupta }
150fa247a2aSRuchika Gupta 
151fa247a2aSRuchika Gupta enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
152fa247a2aSRuchika Gupta 				     uint32_t ptypes, TEE_Param *params)
153fa247a2aSRuchika Gupta {
154fa247a2aSRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
155fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE,
156fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
157fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE);
158fa247a2aSRuchika Gupta 	TEE_Param *ctrl = params;
159fa247a2aSRuchika Gupta 	TEE_Param *out = params + 2;
160fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
161fa247a2aSRuchika Gupta 	struct serialargs ctrlargs = { };
162fa247a2aSRuchika Gupta 	struct pkcs11_session *session = NULL;
163fa247a2aSRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
164fa247a2aSRuchika Gupta 	struct obj_attrs *head = NULL;
165fa247a2aSRuchika Gupta 	struct pkcs11_object_head *template = NULL;
166fa247a2aSRuchika Gupta 	size_t template_size = 0;
167fa247a2aSRuchika Gupta 	uint32_t obj_handle = 0;
168fa247a2aSRuchika Gupta 
169fa247a2aSRuchika Gupta 	if (!client || ptypes != exp_pt ||
170fa247a2aSRuchika Gupta 	    out->memref.size != sizeof(obj_handle))
171fa247a2aSRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
172fa247a2aSRuchika Gupta 
173fa247a2aSRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
174fa247a2aSRuchika Gupta 
175fa247a2aSRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
176fa247a2aSRuchika Gupta 	if (rc)
177fa247a2aSRuchika Gupta 		return rc;
178fa247a2aSRuchika Gupta 
179fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
180fa247a2aSRuchika Gupta 	if (rc)
181fa247a2aSRuchika Gupta 		goto out;
182fa247a2aSRuchika Gupta 
183fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
184fa247a2aSRuchika Gupta 	if (rc)
185fa247a2aSRuchika Gupta 		goto out;
186fa247a2aSRuchika Gupta 
187fa247a2aSRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
188fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
189fa247a2aSRuchika Gupta 		goto out;
190fa247a2aSRuchika Gupta 	}
191fa247a2aSRuchika Gupta 
192fa247a2aSRuchika Gupta 	rc = get_ready_session(session);
193fa247a2aSRuchika Gupta 	if (rc)
194fa247a2aSRuchika Gupta 		goto out;
195fa247a2aSRuchika Gupta 
196fa247a2aSRuchika Gupta 	template_size = sizeof(*template) + template->attrs_size;
197fa247a2aSRuchika Gupta 
198fa247a2aSRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
199fa247a2aSRuchika Gupta 						PKCS11_FUNCTION_GENERATE,
200fa247a2aSRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
201fa247a2aSRuchika Gupta 	if (rc) {
202fa247a2aSRuchika Gupta 		DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
203fa247a2aSRuchika Gupta 		goto out;
204fa247a2aSRuchika Gupta 	}
205fa247a2aSRuchika Gupta 
206fa247a2aSRuchika Gupta 	/*
207fa247a2aSRuchika Gupta 	 * Prepare a clean initial state for the requested object attributes.
208fa247a2aSRuchika Gupta 	 * Free temporary template once done.
209fa247a2aSRuchika Gupta 	 */
210fa247a2aSRuchika Gupta 	rc = create_attributes_from_template(&head, template, template_size,
211fa247a2aSRuchika Gupta 					     NULL, PKCS11_FUNCTION_GENERATE,
2124cfce748SRuchika Gupta 					     proc_params->id,
2134cfce748SRuchika Gupta 					     PKCS11_CKO_UNDEFINED_ID);
214fa247a2aSRuchika Gupta 	if (rc)
215fa247a2aSRuchika Gupta 		goto out;
216fa247a2aSRuchika Gupta 
217fa247a2aSRuchika Gupta 	TEE_Free(template);
218fa247a2aSRuchika Gupta 	template = NULL;
219fa247a2aSRuchika Gupta 
220fa247a2aSRuchika Gupta 	rc = check_created_attrs(head, NULL);
221fa247a2aSRuchika Gupta 	if (rc)
222fa247a2aSRuchika Gupta 		goto out;
223fa247a2aSRuchika Gupta 
224fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_processing(proc_params->id, head);
225fa247a2aSRuchika Gupta 	if (rc)
226fa247a2aSRuchika Gupta 		goto out;
227fa247a2aSRuchika Gupta 
228fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_token(session, head);
229fa247a2aSRuchika Gupta 	if (rc)
230fa247a2aSRuchika Gupta 		goto out;
231fa247a2aSRuchika Gupta 
232fa247a2aSRuchika Gupta 	/*
233fa247a2aSRuchika Gupta 	 * Execute target processing and add value as attribute
234fa247a2aSRuchika Gupta 	 * PKCS11_CKA_VALUE. Symm key generation: depends on target
235fa247a2aSRuchika Gupta 	 * processing to be used.
236fa247a2aSRuchika Gupta 	 */
237fa247a2aSRuchika Gupta 	switch (proc_params->id) {
238fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
239fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
240fa247a2aSRuchika Gupta 		/* Generate random of size specified by attribute VALUE_LEN */
241fa247a2aSRuchika Gupta 		rc = generate_random_key_value(&head);
242fa247a2aSRuchika Gupta 		if (rc)
243fa247a2aSRuchika Gupta 			goto out;
244fa247a2aSRuchika Gupta 		break;
245fa247a2aSRuchika Gupta 
246fa247a2aSRuchika Gupta 	default:
247fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
248fa247a2aSRuchika Gupta 		goto out;
249fa247a2aSRuchika Gupta 	}
250fa247a2aSRuchika Gupta 
251fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
252fa247a2aSRuchika Gupta 	proc_params = NULL;
253fa247a2aSRuchika Gupta 
254fa247a2aSRuchika Gupta 	/*
255fa247a2aSRuchika Gupta 	 * Object is ready, register it and return a handle.
256fa247a2aSRuchika Gupta 	 */
257fa247a2aSRuchika Gupta 	rc = create_object(session, head, &obj_handle);
258fa247a2aSRuchika Gupta 	if (rc)
259fa247a2aSRuchika Gupta 		goto out;
260fa247a2aSRuchika Gupta 
261fa247a2aSRuchika Gupta 	/*
262fa247a2aSRuchika Gupta 	 * Now obj_handle (through the related struct pkcs11_object instance)
263fa247a2aSRuchika Gupta 	 * owns the serialized buffer that holds the object attributes.
264fa247a2aSRuchika Gupta 	 * We reset head to NULL as it is no more the buffer owner and would
265fa247a2aSRuchika Gupta 	 * be freed at function out.
266fa247a2aSRuchika Gupta 	 */
267fa247a2aSRuchika Gupta 	head = NULL;
268fa247a2aSRuchika Gupta 
269fa247a2aSRuchika Gupta 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
270fa247a2aSRuchika Gupta 	out->memref.size = sizeof(obj_handle);
271fa247a2aSRuchika Gupta 
272fa247a2aSRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
273fa247a2aSRuchika Gupta 	     session->handle, obj_handle);
274fa247a2aSRuchika Gupta 
275fa247a2aSRuchika Gupta out:
276fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
277fa247a2aSRuchika Gupta 	TEE_Free(template);
278fa247a2aSRuchika Gupta 	TEE_Free(head);
279fa247a2aSRuchika Gupta 
280fa247a2aSRuchika Gupta 	return rc;
281fa247a2aSRuchika Gupta }
282fa247a2aSRuchika Gupta 
283512cbf1dSJens Wiklander /*
284512cbf1dSJens Wiklander  * entry_processing_init - Generic entry for initializing a processing
285512cbf1dSJens Wiklander  *
286512cbf1dSJens Wiklander  * @client = client reference
287512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
288512cbf1dSJens Wiklander  * @params = Invocation parameters reference
289512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
290512cbf1dSJens Wiklander  */
291512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
292512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
293512cbf1dSJens Wiklander 				     enum processing_func function)
294512cbf1dSJens Wiklander {
295512cbf1dSJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
296512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
297512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
298512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE);
299512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
300512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
301512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
302512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
303512cbf1dSJens Wiklander 	struct pkcs11_attribute_head *proc_params = NULL;
304512cbf1dSJens Wiklander 	uint32_t key_handle = 0;
305512cbf1dSJens Wiklander 	struct pkcs11_object *obj = NULL;
306512cbf1dSJens Wiklander 
307512cbf1dSJens Wiklander 	if (!client || ptypes != exp_pt)
308512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
309512cbf1dSJens Wiklander 
310512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
311512cbf1dSJens Wiklander 
312512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
313512cbf1dSJens Wiklander 	if (rc)
314512cbf1dSJens Wiklander 		return rc;
315512cbf1dSJens Wiklander 
316512cbf1dSJens Wiklander 	rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
317512cbf1dSJens Wiklander 	if (rc)
318512cbf1dSJens Wiklander 		return rc;
319512cbf1dSJens Wiklander 
320512cbf1dSJens Wiklander 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
321512cbf1dSJens Wiklander 	if (rc)
322512cbf1dSJens Wiklander 		return rc;
323512cbf1dSJens Wiklander 
324512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs)) {
325512cbf1dSJens Wiklander 		rc = PKCS11_CKR_ARGUMENTS_BAD;
326512cbf1dSJens Wiklander 		goto out;
327512cbf1dSJens Wiklander 	}
328512cbf1dSJens Wiklander 
329512cbf1dSJens Wiklander 	rc = get_ready_session(session);
330512cbf1dSJens Wiklander 	if (rc)
331512cbf1dSJens Wiklander 		goto out;
332512cbf1dSJens Wiklander 
333512cbf1dSJens Wiklander 	obj = pkcs11_handle2object(key_handle, session);
334512cbf1dSJens Wiklander 	if (!obj) {
335512cbf1dSJens Wiklander 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
336512cbf1dSJens Wiklander 		goto out;
337512cbf1dSJens Wiklander 	}
338512cbf1dSJens Wiklander 
339512cbf1dSJens Wiklander 	rc = set_processing_state(session, function, obj, NULL);
340512cbf1dSJens Wiklander 	if (rc)
341512cbf1dSJens Wiklander 		goto out;
342512cbf1dSJens Wiklander 
343512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, proc_params->id,
344512cbf1dSJens Wiklander 						function,
345512cbf1dSJens Wiklander 						PKCS11_FUNC_STEP_INIT);
346512cbf1dSJens Wiklander 	if (rc)
347512cbf1dSJens Wiklander 		goto out;
348512cbf1dSJens Wiklander 
349512cbf1dSJens Wiklander 	rc = check_parent_attrs_against_processing(proc_params->id, function,
350512cbf1dSJens Wiklander 						   obj->attributes);
351512cbf1dSJens Wiklander 	if (rc)
352512cbf1dSJens Wiklander 		goto out;
353512cbf1dSJens Wiklander 
354512cbf1dSJens Wiklander 	rc = check_access_attrs_against_token(session, obj->attributes);
355512cbf1dSJens Wiklander 	if (rc)
356512cbf1dSJens Wiklander 		goto out;
357512cbf1dSJens Wiklander 
358512cbf1dSJens Wiklander 	if (processing_is_tee_symm(proc_params->id))
359512cbf1dSJens Wiklander 		rc = init_symm_operation(session, function, proc_params, obj);
360512cbf1dSJens Wiklander 	else
361512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
362512cbf1dSJens Wiklander 
363512cbf1dSJens Wiklander 	if (rc == PKCS11_CKR_OK) {
364512cbf1dSJens Wiklander 		session->processing->mecha_type = proc_params->id;
365512cbf1dSJens Wiklander 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
366512cbf1dSJens Wiklander 		     session->handle, id2str_proc(proc_params->id),
367512cbf1dSJens Wiklander 		     id2str_function(function));
368512cbf1dSJens Wiklander 	}
369512cbf1dSJens Wiklander 
370512cbf1dSJens Wiklander out:
371512cbf1dSJens Wiklander 	if (rc && session)
372512cbf1dSJens Wiklander 		release_active_processing(session);
373512cbf1dSJens Wiklander 
374512cbf1dSJens Wiklander 	TEE_Free(proc_params);
375512cbf1dSJens Wiklander 
376512cbf1dSJens Wiklander 	return rc;
377512cbf1dSJens Wiklander }
378512cbf1dSJens Wiklander 
379512cbf1dSJens Wiklander /*
380512cbf1dSJens Wiklander  * entry_processing_step - Generic entry on active processing
381512cbf1dSJens Wiklander  *
382512cbf1dSJens Wiklander  * @client = client reference
383512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
384512cbf1dSJens Wiklander  * @params = Invocation parameters reference
385512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
386512cbf1dSJens Wiklander  * @step - update, oneshot, final
387512cbf1dSJens Wiklander  */
388512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
389512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
390512cbf1dSJens Wiklander 				     enum processing_func function,
391512cbf1dSJens Wiklander 				     enum processing_step step)
392512cbf1dSJens Wiklander {
393512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
394512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
395512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
396512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
397512cbf1dSJens Wiklander 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
398512cbf1dSJens Wiklander 
399512cbf1dSJens Wiklander 	if (!client ||
400512cbf1dSJens Wiklander 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
401512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
402512cbf1dSJens Wiklander 
403512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
404512cbf1dSJens Wiklander 
405512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
406512cbf1dSJens Wiklander 	if (rc)
407512cbf1dSJens Wiklander 		return rc;
408512cbf1dSJens Wiklander 
409512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs))
410512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
411512cbf1dSJens Wiklander 
412512cbf1dSJens Wiklander 	rc = get_active_session(session, function);
413512cbf1dSJens Wiklander 	if (rc)
414512cbf1dSJens Wiklander 		return rc;
415512cbf1dSJens Wiklander 
416512cbf1dSJens Wiklander 	mecha_type = session->processing->mecha_type;
417512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, mecha_type,
418512cbf1dSJens Wiklander 						function, step);
419512cbf1dSJens Wiklander 	if (rc)
420512cbf1dSJens Wiklander 		goto out;
421512cbf1dSJens Wiklander 
422512cbf1dSJens Wiklander 	if (processing_is_tee_symm(mecha_type))
423512cbf1dSJens Wiklander 		rc = step_symm_operation(session, function, step,
424512cbf1dSJens Wiklander 					 ptypes, params);
425512cbf1dSJens Wiklander 	else
426512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
427512cbf1dSJens Wiklander 
428689f4e5bSRuchika Gupta 	if (rc == PKCS11_CKR_OK && step == PKCS11_FUNC_STEP_UPDATE) {
429512cbf1dSJens Wiklander 		session->processing->updated = true;
430512cbf1dSJens Wiklander 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
431512cbf1dSJens Wiklander 		     session->handle, id2str_proc(mecha_type),
432512cbf1dSJens Wiklander 		     id2str_function(function));
433512cbf1dSJens Wiklander 	}
434512cbf1dSJens Wiklander 
435512cbf1dSJens Wiklander out:
436512cbf1dSJens Wiklander 	switch (step) {
437512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_UPDATE:
438512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
439512cbf1dSJens Wiklander 			release_active_processing(session);
440512cbf1dSJens Wiklander 		break;
441512cbf1dSJens Wiklander 	default:
442512cbf1dSJens Wiklander 		/* ONESHOT and FINAL terminates processing on success */
443512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
444512cbf1dSJens Wiklander 			release_active_processing(session);
445512cbf1dSJens Wiklander 		break;
446512cbf1dSJens Wiklander 	}
447512cbf1dSJens Wiklander 
448512cbf1dSJens Wiklander 	return rc;
449512cbf1dSJens Wiklander }
45048799892SRuchika Gupta 
451*4dad6642SRuchika Gupta enum pkcs11_rc entry_processing_key(struct pkcs11_client *client,
452*4dad6642SRuchika Gupta 				    uint32_t ptypes, TEE_Param *params,
453*4dad6642SRuchika Gupta 				    enum processing_func function)
45448799892SRuchika Gupta {
45548799892SRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
45648799892SRuchika Gupta 						TEE_PARAM_TYPE_NONE,
45748799892SRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
45848799892SRuchika Gupta 						TEE_PARAM_TYPE_NONE);
45948799892SRuchika Gupta 	TEE_Param *ctrl = params;
46048799892SRuchika Gupta 	TEE_Param *out = params + 2;
46148799892SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
46248799892SRuchika Gupta 	struct serialargs ctrlargs = { };
46348799892SRuchika Gupta 	struct pkcs11_session *session = NULL;
46448799892SRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
46548799892SRuchika Gupta 	struct pkcs11_object_head *template = NULL;
46648799892SRuchika Gupta 	uint32_t parent_handle = 0;
46748799892SRuchika Gupta 	uint32_t obj_handle = 0;
46848799892SRuchika Gupta 	struct pkcs11_object *parent = NULL;
46948799892SRuchika Gupta 	struct obj_attrs *head = NULL;
47048799892SRuchika Gupta 	size_t template_size = 0;
4718c499324SRuchika Gupta 	void *out_buf = NULL;
4728c499324SRuchika Gupta 	uint32_t out_size = 0;
47348799892SRuchika Gupta 
47448799892SRuchika Gupta 	if (!client || ptypes != exp_pt ||
47548799892SRuchika Gupta 	    out->memref.size != sizeof(obj_handle))
47648799892SRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
47748799892SRuchika Gupta 
47848799892SRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
47948799892SRuchika Gupta 
48048799892SRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
48148799892SRuchika Gupta 	if (rc)
48248799892SRuchika Gupta 		return rc;
48348799892SRuchika Gupta 
48448799892SRuchika Gupta 	rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t));
48548799892SRuchika Gupta 	if (rc)
48648799892SRuchika Gupta 		return rc;
48748799892SRuchika Gupta 
48848799892SRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
48948799892SRuchika Gupta 	if (rc)
49048799892SRuchika Gupta 		goto out_free;
49148799892SRuchika Gupta 
49248799892SRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
49348799892SRuchika Gupta 	if (rc)
49448799892SRuchika Gupta 		goto out_free;
49548799892SRuchika Gupta 
49648799892SRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
49748799892SRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
49848799892SRuchika Gupta 		goto out_free;
49948799892SRuchika Gupta 	}
50048799892SRuchika Gupta 
50148799892SRuchika Gupta 	/* Return error if processing already active */
50248799892SRuchika Gupta 	rc = get_ready_session(session);
50348799892SRuchika Gupta 	if (rc)
50448799892SRuchika Gupta 		goto out_free;
50548799892SRuchika Gupta 
50648799892SRuchika Gupta 	/* Check parent handle */
50748799892SRuchika Gupta 	parent = pkcs11_handle2object(parent_handle, session);
50848799892SRuchika Gupta 	if (!parent) {
50948799892SRuchika Gupta 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
51048799892SRuchika Gupta 		goto out_free;
51148799892SRuchika Gupta 	}
51248799892SRuchika Gupta 
51348799892SRuchika Gupta 	/* Check if mechanism can be used for derivation function */
51448799892SRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
51548799892SRuchika Gupta 						function,
51648799892SRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
51748799892SRuchika Gupta 	if (rc)
51848799892SRuchika Gupta 		goto out_free;
51948799892SRuchika Gupta 
52048799892SRuchika Gupta 	/* Set the processing state to active */
52148799892SRuchika Gupta 	rc = set_processing_state(session, function, parent, NULL);
52248799892SRuchika Gupta 	if (rc)
52348799892SRuchika Gupta 		goto out_free;
52448799892SRuchika Gupta 
52548799892SRuchika Gupta 	/*
52648799892SRuchika Gupta 	 * Check if base/parent key has CKA_DERIVE set and its key type is
52748799892SRuchika Gupta 	 * compatible with the mechanism passed
52848799892SRuchika Gupta 	 */
52948799892SRuchika Gupta 	rc = check_parent_attrs_against_processing(proc_params->id, function,
53048799892SRuchika Gupta 						   parent->attributes);
53148799892SRuchika Gupta 	if (rc)
53248799892SRuchika Gupta 		goto out;
53348799892SRuchika Gupta 
53448799892SRuchika Gupta 	/* Check access of base/parent key */
53548799892SRuchika Gupta 	rc = check_access_attrs_against_token(session, parent->attributes);
53648799892SRuchika Gupta 	if (rc)
53748799892SRuchika Gupta 		goto out;
53848799892SRuchika Gupta 
53948799892SRuchika Gupta 	template_size = sizeof(*template) + template->attrs_size;
54048799892SRuchika Gupta 	/*
54148799892SRuchika Gupta 	 * Prepare a clean initial state for the requested object attributes
54248799892SRuchika Gupta 	 * using base/parent key attributes. Free temporary template once done.
54348799892SRuchika Gupta 	 */
54448799892SRuchika Gupta 	rc = create_attributes_from_template(&head, template, template_size,
54548799892SRuchika Gupta 					     parent->attributes,
54648799892SRuchika Gupta 					     function,
54748799892SRuchika Gupta 					     proc_params->id,
54848799892SRuchika Gupta 					     PKCS11_CKO_UNDEFINED_ID);
54948799892SRuchika Gupta 	if (rc)
55048799892SRuchika Gupta 		goto out;
55148799892SRuchika Gupta 
55248799892SRuchika Gupta 	TEE_Free(template);
55348799892SRuchika Gupta 	template = NULL;
55448799892SRuchika Gupta 
55548799892SRuchika Gupta 	/* check_created_attrs() is called later once key size is known */
55648799892SRuchika Gupta 
55748799892SRuchika Gupta 	rc = check_created_attrs_against_processing(proc_params->id, head);
55848799892SRuchika Gupta 	if (rc)
55948799892SRuchika Gupta 		goto out;
56048799892SRuchika Gupta 
56148799892SRuchika Gupta 	rc = check_created_attrs_against_token(session, head);
56248799892SRuchika Gupta 	if (rc)
56348799892SRuchika Gupta 		goto out;
56448799892SRuchika Gupta 
5658c499324SRuchika Gupta 	if (processing_is_tee_symm(proc_params->id)) {
56648799892SRuchika Gupta 		/*
56748799892SRuchika Gupta 		 * These derivation mechanism require encryption to be
56848799892SRuchika Gupta 		 * performed on the data passed in proc_params by parent
56948799892SRuchika Gupta 		 * key. Hence pass function as PKCS11_FUNCTION_ENCRYPT
57048799892SRuchika Gupta 		 * to init_symm_operation()
57148799892SRuchika Gupta 		 */
57248799892SRuchika Gupta 		rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT,
57348799892SRuchika Gupta 					 proc_params, parent);
57448799892SRuchika Gupta 		if (rc)
57548799892SRuchika Gupta 			goto out;
57648799892SRuchika Gupta 
5778c499324SRuchika Gupta 		session->processing->mecha_type = proc_params->id;
5788c499324SRuchika Gupta 
5798c499324SRuchika Gupta 		rc = derive_key_by_symm_enc(session, &out_buf, &out_size);
58048799892SRuchika Gupta 		if (rc)
58148799892SRuchika Gupta 			goto out;
5828c499324SRuchika Gupta 	} else {
58348799892SRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
58448799892SRuchika Gupta 		goto out;
58548799892SRuchika Gupta 	}
58648799892SRuchika Gupta 
5878c499324SRuchika Gupta 	rc = set_key_data(&head, out_buf, out_size);
5888c499324SRuchika Gupta 	if (rc)
5898c499324SRuchika Gupta 		goto out;
5908c499324SRuchika Gupta 
5918c499324SRuchika Gupta 	TEE_Free(out_buf);
5928c499324SRuchika Gupta 	out_buf = NULL;
5938c499324SRuchika Gupta 
59448799892SRuchika Gupta 	TEE_Free(proc_params);
59548799892SRuchika Gupta 	proc_params = NULL;
59648799892SRuchika Gupta 
59748799892SRuchika Gupta 	/*
59848799892SRuchika Gupta 	 * Object is ready, register it and return a handle.
59948799892SRuchika Gupta 	 */
60048799892SRuchika Gupta 	rc = create_object(session, head, &obj_handle);
60148799892SRuchika Gupta 	if (rc)
60248799892SRuchika Gupta 		goto out;
60348799892SRuchika Gupta 
60448799892SRuchika Gupta 	/*
60548799892SRuchika Gupta 	 * Now obj_handle (through the related struct pkcs11_object instance)
60648799892SRuchika Gupta 	 * owns the serialized buffer that holds the object attributes.
60748799892SRuchika Gupta 	 * We reset head to NULL as it is no more the buffer owner and would
60848799892SRuchika Gupta 	 * be freed at function out.
60948799892SRuchika Gupta 	 */
61048799892SRuchika Gupta 	head = NULL;
61148799892SRuchika Gupta 
61248799892SRuchika Gupta 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
61348799892SRuchika Gupta 	out->memref.size = sizeof(obj_handle);
61448799892SRuchika Gupta 
61548799892SRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32,
61648799892SRuchika Gupta 	     session->handle, obj_handle);
61748799892SRuchika Gupta 
61848799892SRuchika Gupta out:
61948799892SRuchika Gupta 	release_active_processing(session);
62048799892SRuchika Gupta out_free:
62148799892SRuchika Gupta 	TEE_Free(proc_params);
62248799892SRuchika Gupta 	TEE_Free(template);
62348799892SRuchika Gupta 	TEE_Free(head);
6248c499324SRuchika Gupta 	TEE_Free(out_buf);
62548799892SRuchika Gupta 
62648799892SRuchika Gupta 	return rc;
62748799892SRuchika Gupta }
628