xref: /optee_os/ta/pkcs11/src/processing.c (revision fa247a2a296e38934a5835558abd4ec5f1209a94)
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 
113*fa247a2aSRuchika Gupta static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
114*fa247a2aSRuchika Gupta {
115*fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
116*fa247a2aSRuchika Gupta 	void *data = NULL;
117*fa247a2aSRuchika Gupta 	uint32_t data_size = 0;
118*fa247a2aSRuchika Gupta 	uint32_t value_len = 0;
119*fa247a2aSRuchika Gupta 	void *value = NULL;
120*fa247a2aSRuchika Gupta 
121*fa247a2aSRuchika Gupta 	if (!*head)
122*fa247a2aSRuchika Gupta 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
123*fa247a2aSRuchika Gupta 
124*fa247a2aSRuchika Gupta 	rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size);
125*fa247a2aSRuchika Gupta 	if (rc || data_size != sizeof(uint32_t)) {
126*fa247a2aSRuchika Gupta 		DMSG("%s", rc ? "No attribute value_len found" :
127*fa247a2aSRuchika Gupta 		     "Invalid size for attribute VALUE_LEN");
128*fa247a2aSRuchika Gupta 
129*fa247a2aSRuchika Gupta 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
130*fa247a2aSRuchika Gupta 	}
131*fa247a2aSRuchika Gupta 	TEE_MemMove(&value_len, data, data_size);
132*fa247a2aSRuchika Gupta 
133*fa247a2aSRuchika Gupta 	if (get_key_type(*head) == PKCS11_CKK_GENERIC_SECRET)
134*fa247a2aSRuchika Gupta 		value_len = (value_len + 7) / 8;
135*fa247a2aSRuchika Gupta 
136*fa247a2aSRuchika Gupta 	/* Remove the default empty value attribute if found */
137*fa247a2aSRuchika Gupta 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
138*fa247a2aSRuchika Gupta 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
139*fa247a2aSRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
140*fa247a2aSRuchika Gupta 
141*fa247a2aSRuchika Gupta 	value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
142*fa247a2aSRuchika Gupta 	if (!value)
143*fa247a2aSRuchika Gupta 		return PKCS11_CKR_DEVICE_MEMORY;
144*fa247a2aSRuchika Gupta 
145*fa247a2aSRuchika Gupta 	TEE_GenerateRandom(value, value_len);
146*fa247a2aSRuchika Gupta 
147*fa247a2aSRuchika Gupta 	rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
148*fa247a2aSRuchika Gupta 
149*fa247a2aSRuchika Gupta 	TEE_Free(value);
150*fa247a2aSRuchika Gupta 
151*fa247a2aSRuchika Gupta 	return rc;
152*fa247a2aSRuchika Gupta }
153*fa247a2aSRuchika Gupta 
154*fa247a2aSRuchika Gupta enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
155*fa247a2aSRuchika Gupta 				     uint32_t ptypes, TEE_Param *params)
156*fa247a2aSRuchika Gupta {
157*fa247a2aSRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
158*fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE,
159*fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
160*fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE);
161*fa247a2aSRuchika Gupta 	TEE_Param *ctrl = params;
162*fa247a2aSRuchika Gupta 	TEE_Param *out = params + 2;
163*fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
164*fa247a2aSRuchika Gupta 	struct serialargs ctrlargs = { };
165*fa247a2aSRuchika Gupta 	struct pkcs11_session *session = NULL;
166*fa247a2aSRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
167*fa247a2aSRuchika Gupta 	struct obj_attrs *head = NULL;
168*fa247a2aSRuchika Gupta 	struct pkcs11_object_head *template = NULL;
169*fa247a2aSRuchika Gupta 	size_t template_size = 0;
170*fa247a2aSRuchika Gupta 	uint32_t obj_handle = 0;
171*fa247a2aSRuchika Gupta 
172*fa247a2aSRuchika Gupta 	if (!client || ptypes != exp_pt ||
173*fa247a2aSRuchika Gupta 	    out->memref.size != sizeof(obj_handle))
174*fa247a2aSRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
175*fa247a2aSRuchika Gupta 
176*fa247a2aSRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
177*fa247a2aSRuchika Gupta 
178*fa247a2aSRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
179*fa247a2aSRuchika Gupta 	if (rc)
180*fa247a2aSRuchika Gupta 		return rc;
181*fa247a2aSRuchika Gupta 
182*fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
183*fa247a2aSRuchika Gupta 	if (rc)
184*fa247a2aSRuchika Gupta 		goto out;
185*fa247a2aSRuchika Gupta 
186*fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
187*fa247a2aSRuchika Gupta 	if (rc)
188*fa247a2aSRuchika Gupta 		goto out;
189*fa247a2aSRuchika Gupta 
190*fa247a2aSRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
191*fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
192*fa247a2aSRuchika Gupta 		goto out;
193*fa247a2aSRuchika Gupta 	}
194*fa247a2aSRuchika Gupta 
195*fa247a2aSRuchika Gupta 	rc = get_ready_session(session);
196*fa247a2aSRuchika Gupta 	if (rc)
197*fa247a2aSRuchika Gupta 		goto out;
198*fa247a2aSRuchika Gupta 
199*fa247a2aSRuchika Gupta 	template_size = sizeof(*template) + template->attrs_size;
200*fa247a2aSRuchika Gupta 
201*fa247a2aSRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
202*fa247a2aSRuchika Gupta 						PKCS11_FUNCTION_GENERATE,
203*fa247a2aSRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
204*fa247a2aSRuchika Gupta 	if (rc) {
205*fa247a2aSRuchika Gupta 		DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
206*fa247a2aSRuchika Gupta 		goto out;
207*fa247a2aSRuchika Gupta 	}
208*fa247a2aSRuchika Gupta 
209*fa247a2aSRuchika Gupta 	/*
210*fa247a2aSRuchika Gupta 	 * Prepare a clean initial state for the requested object attributes.
211*fa247a2aSRuchika Gupta 	 * Free temporary template once done.
212*fa247a2aSRuchika Gupta 	 */
213*fa247a2aSRuchika Gupta 	rc = create_attributes_from_template(&head, template, template_size,
214*fa247a2aSRuchika Gupta 					     NULL, PKCS11_FUNCTION_GENERATE,
215*fa247a2aSRuchika Gupta 					     proc_params->id);
216*fa247a2aSRuchika Gupta 	if (rc)
217*fa247a2aSRuchika Gupta 		goto out;
218*fa247a2aSRuchika Gupta 
219*fa247a2aSRuchika Gupta 	TEE_Free(template);
220*fa247a2aSRuchika Gupta 	template = NULL;
221*fa247a2aSRuchika Gupta 
222*fa247a2aSRuchika Gupta 	rc = check_created_attrs(head, NULL);
223*fa247a2aSRuchika Gupta 	if (rc)
224*fa247a2aSRuchika Gupta 		goto out;
225*fa247a2aSRuchika Gupta 
226*fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_processing(proc_params->id, head);
227*fa247a2aSRuchika Gupta 	if (rc)
228*fa247a2aSRuchika Gupta 		goto out;
229*fa247a2aSRuchika Gupta 
230*fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_token(session, head);
231*fa247a2aSRuchika Gupta 	if (rc)
232*fa247a2aSRuchika Gupta 		goto out;
233*fa247a2aSRuchika Gupta 
234*fa247a2aSRuchika Gupta 	/*
235*fa247a2aSRuchika Gupta 	 * Execute target processing and add value as attribute
236*fa247a2aSRuchika Gupta 	 * PKCS11_CKA_VALUE. Symm key generation: depends on target
237*fa247a2aSRuchika Gupta 	 * processing to be used.
238*fa247a2aSRuchika Gupta 	 */
239*fa247a2aSRuchika Gupta 	switch (proc_params->id) {
240*fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
241*fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
242*fa247a2aSRuchika Gupta 		/* Generate random of size specified by attribute VALUE_LEN */
243*fa247a2aSRuchika Gupta 		rc = generate_random_key_value(&head);
244*fa247a2aSRuchika Gupta 		if (rc)
245*fa247a2aSRuchika Gupta 			goto out;
246*fa247a2aSRuchika Gupta 		break;
247*fa247a2aSRuchika Gupta 
248*fa247a2aSRuchika Gupta 	default:
249*fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
250*fa247a2aSRuchika Gupta 		goto out;
251*fa247a2aSRuchika Gupta 	}
252*fa247a2aSRuchika Gupta 
253*fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
254*fa247a2aSRuchika Gupta 	proc_params = NULL;
255*fa247a2aSRuchika Gupta 
256*fa247a2aSRuchika Gupta 	/*
257*fa247a2aSRuchika Gupta 	 * Object is ready, register it and return a handle.
258*fa247a2aSRuchika Gupta 	 */
259*fa247a2aSRuchika Gupta 	rc = create_object(session, head, &obj_handle);
260*fa247a2aSRuchika Gupta 	if (rc)
261*fa247a2aSRuchika Gupta 		goto out;
262*fa247a2aSRuchika Gupta 
263*fa247a2aSRuchika Gupta 	/*
264*fa247a2aSRuchika Gupta 	 * Now obj_handle (through the related struct pkcs11_object instance)
265*fa247a2aSRuchika Gupta 	 * owns the serialized buffer that holds the object attributes.
266*fa247a2aSRuchika Gupta 	 * We reset head to NULL as it is no more the buffer owner and would
267*fa247a2aSRuchika Gupta 	 * be freed at function out.
268*fa247a2aSRuchika Gupta 	 */
269*fa247a2aSRuchika Gupta 	head = NULL;
270*fa247a2aSRuchika Gupta 
271*fa247a2aSRuchika Gupta 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
272*fa247a2aSRuchika Gupta 	out->memref.size = sizeof(obj_handle);
273*fa247a2aSRuchika Gupta 
274*fa247a2aSRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
275*fa247a2aSRuchika Gupta 	     session->handle, obj_handle);
276*fa247a2aSRuchika Gupta 
277*fa247a2aSRuchika Gupta out:
278*fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
279*fa247a2aSRuchika Gupta 	TEE_Free(template);
280*fa247a2aSRuchika Gupta 	TEE_Free(head);
281*fa247a2aSRuchika Gupta 
282*fa247a2aSRuchika Gupta 	return rc;
283*fa247a2aSRuchika Gupta }
284*fa247a2aSRuchika Gupta 
285512cbf1dSJens Wiklander /*
286512cbf1dSJens Wiklander  * entry_processing_init - Generic entry for initializing a processing
287512cbf1dSJens Wiklander  *
288512cbf1dSJens Wiklander  * @client = client reference
289512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
290512cbf1dSJens Wiklander  * @params = Invocation parameters reference
291512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
292512cbf1dSJens Wiklander  */
293512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
294512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
295512cbf1dSJens Wiklander 				     enum processing_func function)
296512cbf1dSJens Wiklander {
297512cbf1dSJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
298512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
299512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
300512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE);
301512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
302512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
303512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
304512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
305512cbf1dSJens Wiklander 	struct pkcs11_attribute_head *proc_params = NULL;
306512cbf1dSJens Wiklander 	uint32_t key_handle = 0;
307512cbf1dSJens Wiklander 	struct pkcs11_object *obj = NULL;
308512cbf1dSJens Wiklander 
309512cbf1dSJens Wiklander 	if (!client || ptypes != exp_pt)
310512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
311512cbf1dSJens Wiklander 
312512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
313512cbf1dSJens Wiklander 
314512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
315512cbf1dSJens Wiklander 	if (rc)
316512cbf1dSJens Wiklander 		return rc;
317512cbf1dSJens Wiklander 
318512cbf1dSJens Wiklander 	rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
319512cbf1dSJens Wiklander 	if (rc)
320512cbf1dSJens Wiklander 		return rc;
321512cbf1dSJens Wiklander 
322512cbf1dSJens Wiklander 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
323512cbf1dSJens Wiklander 	if (rc)
324512cbf1dSJens Wiklander 		return rc;
325512cbf1dSJens Wiklander 
326512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs)) {
327512cbf1dSJens Wiklander 		rc = PKCS11_CKR_ARGUMENTS_BAD;
328512cbf1dSJens Wiklander 		goto out;
329512cbf1dSJens Wiklander 	}
330512cbf1dSJens Wiklander 
331512cbf1dSJens Wiklander 	rc = get_ready_session(session);
332512cbf1dSJens Wiklander 	if (rc)
333512cbf1dSJens Wiklander 		goto out;
334512cbf1dSJens Wiklander 
335512cbf1dSJens Wiklander 	obj = pkcs11_handle2object(key_handle, session);
336512cbf1dSJens Wiklander 	if (!obj) {
337512cbf1dSJens Wiklander 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
338512cbf1dSJens Wiklander 		goto out;
339512cbf1dSJens Wiklander 	}
340512cbf1dSJens Wiklander 
341512cbf1dSJens Wiklander 	rc = set_processing_state(session, function, obj, NULL);
342512cbf1dSJens Wiklander 	if (rc)
343512cbf1dSJens Wiklander 		goto out;
344512cbf1dSJens Wiklander 
345512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, proc_params->id,
346512cbf1dSJens Wiklander 						function,
347512cbf1dSJens Wiklander 						PKCS11_FUNC_STEP_INIT);
348512cbf1dSJens Wiklander 	if (rc)
349512cbf1dSJens Wiklander 		goto out;
350512cbf1dSJens Wiklander 
351512cbf1dSJens Wiklander 	rc = check_parent_attrs_against_processing(proc_params->id, function,
352512cbf1dSJens Wiklander 						   obj->attributes);
353512cbf1dSJens Wiklander 	if (rc)
354512cbf1dSJens Wiklander 		goto out;
355512cbf1dSJens Wiklander 
356512cbf1dSJens Wiklander 	rc = check_access_attrs_against_token(session, obj->attributes);
357512cbf1dSJens Wiklander 	if (rc)
358512cbf1dSJens Wiklander 		goto out;
359512cbf1dSJens Wiklander 
360512cbf1dSJens Wiklander 	if (processing_is_tee_symm(proc_params->id))
361512cbf1dSJens Wiklander 		rc = init_symm_operation(session, function, proc_params, obj);
362512cbf1dSJens Wiklander 	else
363512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
364512cbf1dSJens Wiklander 
365512cbf1dSJens Wiklander 	if (rc == PKCS11_CKR_OK) {
366512cbf1dSJens Wiklander 		session->processing->mecha_type = proc_params->id;
367512cbf1dSJens Wiklander 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
368512cbf1dSJens Wiklander 		     session->handle, id2str_proc(proc_params->id),
369512cbf1dSJens Wiklander 		     id2str_function(function));
370512cbf1dSJens Wiklander 	}
371512cbf1dSJens Wiklander 
372512cbf1dSJens Wiklander out:
373512cbf1dSJens Wiklander 	if (rc && session)
374512cbf1dSJens Wiklander 		release_active_processing(session);
375512cbf1dSJens Wiklander 
376512cbf1dSJens Wiklander 	TEE_Free(proc_params);
377512cbf1dSJens Wiklander 
378512cbf1dSJens Wiklander 	return rc;
379512cbf1dSJens Wiklander }
380512cbf1dSJens Wiklander 
381512cbf1dSJens Wiklander /*
382512cbf1dSJens Wiklander  * entry_processing_step - Generic entry on active processing
383512cbf1dSJens Wiklander  *
384512cbf1dSJens Wiklander  * @client = client reference
385512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
386512cbf1dSJens Wiklander  * @params = Invocation parameters reference
387512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
388512cbf1dSJens Wiklander  * @step - update, oneshot, final
389512cbf1dSJens Wiklander  */
390512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
391512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
392512cbf1dSJens Wiklander 				     enum processing_func function,
393512cbf1dSJens Wiklander 				     enum processing_step step)
394512cbf1dSJens Wiklander {
395512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
396512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
397512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
398512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
399512cbf1dSJens Wiklander 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
400512cbf1dSJens Wiklander 
401512cbf1dSJens Wiklander 	if (!client ||
402512cbf1dSJens Wiklander 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
403512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
404512cbf1dSJens Wiklander 
405512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
406512cbf1dSJens Wiklander 
407512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
408512cbf1dSJens Wiklander 	if (rc)
409512cbf1dSJens Wiklander 		return rc;
410512cbf1dSJens Wiklander 
411512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs))
412512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
413512cbf1dSJens Wiklander 
414512cbf1dSJens Wiklander 	rc = get_active_session(session, function);
415512cbf1dSJens Wiklander 	if (rc)
416512cbf1dSJens Wiklander 		return rc;
417512cbf1dSJens Wiklander 
418512cbf1dSJens Wiklander 	mecha_type = session->processing->mecha_type;
419512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, mecha_type,
420512cbf1dSJens Wiklander 						function, step);
421512cbf1dSJens Wiklander 	if (rc)
422512cbf1dSJens Wiklander 		goto out;
423512cbf1dSJens Wiklander 
424512cbf1dSJens Wiklander 	if (processing_is_tee_symm(mecha_type))
425512cbf1dSJens Wiklander 		rc = step_symm_operation(session, function, step,
426512cbf1dSJens Wiklander 					 ptypes, params);
427512cbf1dSJens Wiklander 	else
428512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
429512cbf1dSJens Wiklander 
430689f4e5bSRuchika Gupta 	if (rc == PKCS11_CKR_OK && step == PKCS11_FUNC_STEP_UPDATE) {
431512cbf1dSJens Wiklander 		session->processing->updated = true;
432512cbf1dSJens Wiklander 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
433512cbf1dSJens Wiklander 		     session->handle, id2str_proc(mecha_type),
434512cbf1dSJens Wiklander 		     id2str_function(function));
435512cbf1dSJens Wiklander 	}
436512cbf1dSJens Wiklander 
437512cbf1dSJens Wiklander out:
438512cbf1dSJens Wiklander 	switch (step) {
439512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_UPDATE:
440512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
441512cbf1dSJens Wiklander 			release_active_processing(session);
442512cbf1dSJens Wiklander 		break;
443512cbf1dSJens Wiklander 	default:
444512cbf1dSJens Wiklander 		/* ONESHOT and FINAL terminates processing on success */
445512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
446512cbf1dSJens Wiklander 			release_active_processing(session);
447512cbf1dSJens Wiklander 		break;
448512cbf1dSJens Wiklander 	}
449512cbf1dSJens Wiklander 
450512cbf1dSJens Wiklander 	return rc;
451512cbf1dSJens Wiklander }
452