xref: /optee_os/ta/pkcs11/src/processing.c (revision 5f80f270b184180ead542642a54387abf8f246c3)
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;
499e91a619SVesa Jääskeläinen 	case PKCS11_CMD_DIGEST_UPDATE:
509e91a619SVesa Jääskeläinen 	case PKCS11_CMD_DIGEST_KEY:
519e91a619SVesa Jääskeläinen 	case PKCS11_CMD_DIGEST_ONESHOT:
529e91a619SVesa Jääskeläinen 	case PKCS11_CMD_DIGEST_FINAL:
539e91a619SVesa Jääskeläinen 		return PKCS11_FUNCTION_DIGEST;
54eb6141b6SVesa Jääskeläinen 	default:
55eb6141b6SVesa Jääskeläinen 		return PKCS11_FUNCTION_UNKNOWN;
56eb6141b6SVesa Jääskeläinen 	}
57eb6141b6SVesa Jääskeläinen }
58eb6141b6SVesa Jääskeläinen 
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 
107fb279d8bSVesa Jääskeläinen 	if (session->processing->tee_hash_op_handle != TEE_HANDLE_NULL) {
108fb279d8bSVesa Jääskeläinen 		TEE_FreeOperation(session->processing->tee_hash_op_handle);
109fb279d8bSVesa Jääskeläinen 		session->processing->tee_hash_op_handle = TEE_HANDLE_NULL;
110fb279d8bSVesa Jääskeläinen 		session->processing->tee_hash_algo = 0;
111fb279d8bSVesa Jääskeläinen 	}
112fb279d8bSVesa Jääskeläinen 
113512cbf1dSJens Wiklander 	if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
114512cbf1dSJens Wiklander 		TEE_FreeOperation(session->processing->tee_op_handle);
115512cbf1dSJens Wiklander 		session->processing->tee_op_handle = TEE_HANDLE_NULL;
116512cbf1dSJens Wiklander 	}
117512cbf1dSJens Wiklander 
1182158ea6cSRuchika Gupta 	TEE_Free(session->processing->extra_ctx);
1192158ea6cSRuchika Gupta 
120512cbf1dSJens Wiklander 	TEE_Free(session->processing);
121512cbf1dSJens Wiklander 	session->processing = NULL;
122512cbf1dSJens Wiklander }
123512cbf1dSJens Wiklander 
124512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj)
125512cbf1dSJens Wiklander {
126fb279d8bSVesa Jääskeläinen 	void *a_ptr = NULL;
127512cbf1dSJens Wiklander 	uint32_t a_size = 0;
128512cbf1dSJens Wiklander 	struct obj_attrs *attrs = obj->attributes;
129512cbf1dSJens Wiklander 
130512cbf1dSJens Wiklander 	switch (get_key_type(attrs)) {
131512cbf1dSJens Wiklander 	case PKCS11_CKK_AES:
132689f4e5bSRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
133689f4e5bSRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
134689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
135689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
136689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA256_HMAC:
137689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
138689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
139512cbf1dSJens Wiklander 		if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
140512cbf1dSJens Wiklander 			return 0;
141512cbf1dSJens Wiklander 
142512cbf1dSJens Wiklander 		return a_size * 8;
143fb279d8bSVesa Jääskeläinen 	case PKCS11_CKK_EC:
144fb279d8bSVesa Jääskeläinen 		if (get_attribute_ptr(attrs, PKCS11_CKA_EC_PARAMS,
145fb279d8bSVesa Jääskeläinen 				      &a_ptr, &a_size) || !a_ptr)
146fb279d8bSVesa Jääskeläinen 			return 0;
147fb279d8bSVesa Jääskeläinen 
148fb279d8bSVesa Jääskeläinen 		return ec_params2tee_keysize(a_ptr, a_size);
149512cbf1dSJens Wiklander 	default:
150512cbf1dSJens Wiklander 		TEE_Panic(0);
151512cbf1dSJens Wiklander 		return 0;
152512cbf1dSJens Wiklander 	}
153512cbf1dSJens Wiklander }
154512cbf1dSJens Wiklander 
155fa247a2aSRuchika Gupta static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
156fa247a2aSRuchika Gupta {
157fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
158fa247a2aSRuchika Gupta 	void *data = NULL;
159fa247a2aSRuchika Gupta 	uint32_t data_size = 0;
160fa247a2aSRuchika Gupta 	uint32_t value_len = 0;
161fa247a2aSRuchika Gupta 	void *value = NULL;
162fa247a2aSRuchika Gupta 
163fa247a2aSRuchika Gupta 	if (!*head)
164fa247a2aSRuchika Gupta 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
165fa247a2aSRuchika Gupta 
166fa247a2aSRuchika Gupta 	rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size);
167fa247a2aSRuchika Gupta 	if (rc || data_size != sizeof(uint32_t)) {
168fa247a2aSRuchika Gupta 		DMSG("%s", rc ? "No attribute value_len found" :
169fa247a2aSRuchika Gupta 		     "Invalid size for attribute VALUE_LEN");
170fa247a2aSRuchika Gupta 
171fa247a2aSRuchika Gupta 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
172fa247a2aSRuchika Gupta 	}
173fa247a2aSRuchika Gupta 	TEE_MemMove(&value_len, data, data_size);
174fa247a2aSRuchika Gupta 
175fa247a2aSRuchika Gupta 	/* Remove the default empty value attribute if found */
176fa247a2aSRuchika Gupta 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
177fa247a2aSRuchika Gupta 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
178fa247a2aSRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
179fa247a2aSRuchika Gupta 
180fa247a2aSRuchika Gupta 	value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
181fa247a2aSRuchika Gupta 	if (!value)
182fa247a2aSRuchika Gupta 		return PKCS11_CKR_DEVICE_MEMORY;
183fa247a2aSRuchika Gupta 
184fa247a2aSRuchika Gupta 	TEE_GenerateRandom(value, value_len);
185fa247a2aSRuchika Gupta 
186fa247a2aSRuchika Gupta 	rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
187fa247a2aSRuchika Gupta 
188fa247a2aSRuchika Gupta 	TEE_Free(value);
189fa247a2aSRuchika Gupta 
190fa247a2aSRuchika Gupta 	return rc;
191fa247a2aSRuchika Gupta }
192fa247a2aSRuchika Gupta 
193fa247a2aSRuchika Gupta enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
194fa247a2aSRuchika Gupta 				     uint32_t ptypes, TEE_Param *params)
195fa247a2aSRuchika Gupta {
196fa247a2aSRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
197fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE,
198fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
199fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE);
200fa247a2aSRuchika Gupta 	TEE_Param *ctrl = params;
201fa247a2aSRuchika Gupta 	TEE_Param *out = params + 2;
202fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
203fa247a2aSRuchika Gupta 	struct serialargs ctrlargs = { };
204fa247a2aSRuchika Gupta 	struct pkcs11_session *session = NULL;
205fa247a2aSRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
206fa247a2aSRuchika Gupta 	struct obj_attrs *head = NULL;
207fa247a2aSRuchika Gupta 	struct pkcs11_object_head *template = NULL;
208fa247a2aSRuchika Gupta 	size_t template_size = 0;
209fa247a2aSRuchika Gupta 	uint32_t obj_handle = 0;
210fa247a2aSRuchika Gupta 
211fa247a2aSRuchika Gupta 	if (!client || ptypes != exp_pt ||
212fa247a2aSRuchika Gupta 	    out->memref.size != sizeof(obj_handle))
213fa247a2aSRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
214fa247a2aSRuchika Gupta 
215fa247a2aSRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
216fa247a2aSRuchika Gupta 
217fa247a2aSRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
218fa247a2aSRuchika Gupta 	if (rc)
219fa247a2aSRuchika Gupta 		return rc;
220fa247a2aSRuchika Gupta 
221fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
222fa247a2aSRuchika Gupta 	if (rc)
223fa247a2aSRuchika Gupta 		goto out;
224fa247a2aSRuchika Gupta 
225fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
226fa247a2aSRuchika Gupta 	if (rc)
227fa247a2aSRuchika Gupta 		goto out;
228fa247a2aSRuchika Gupta 
229fa247a2aSRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
230fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
231fa247a2aSRuchika Gupta 		goto out;
232fa247a2aSRuchika Gupta 	}
233fa247a2aSRuchika Gupta 
234fa247a2aSRuchika Gupta 	rc = get_ready_session(session);
235fa247a2aSRuchika Gupta 	if (rc)
236fa247a2aSRuchika Gupta 		goto out;
237fa247a2aSRuchika Gupta 
238fa247a2aSRuchika Gupta 	template_size = sizeof(*template) + template->attrs_size;
239fa247a2aSRuchika Gupta 
240fa247a2aSRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
241fa247a2aSRuchika Gupta 						PKCS11_FUNCTION_GENERATE,
242fa247a2aSRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
243fa247a2aSRuchika Gupta 	if (rc) {
244fa247a2aSRuchika Gupta 		DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
245fa247a2aSRuchika Gupta 		goto out;
246fa247a2aSRuchika Gupta 	}
247fa247a2aSRuchika Gupta 
248fa247a2aSRuchika Gupta 	/*
249fa247a2aSRuchika Gupta 	 * Prepare a clean initial state for the requested object attributes.
250fa247a2aSRuchika Gupta 	 * Free temporary template once done.
251fa247a2aSRuchika Gupta 	 */
252fa247a2aSRuchika Gupta 	rc = create_attributes_from_template(&head, template, template_size,
253fa247a2aSRuchika Gupta 					     NULL, PKCS11_FUNCTION_GENERATE,
2544cfce748SRuchika Gupta 					     proc_params->id,
2554cfce748SRuchika Gupta 					     PKCS11_CKO_UNDEFINED_ID);
256fa247a2aSRuchika Gupta 	if (rc)
257fa247a2aSRuchika Gupta 		goto out;
258fa247a2aSRuchika Gupta 
259fa247a2aSRuchika Gupta 	TEE_Free(template);
260fa247a2aSRuchika Gupta 	template = NULL;
261fa247a2aSRuchika Gupta 
262fa247a2aSRuchika Gupta 	rc = check_created_attrs(head, NULL);
263fa247a2aSRuchika Gupta 	if (rc)
264fa247a2aSRuchika Gupta 		goto out;
265fa247a2aSRuchika Gupta 
266fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_processing(proc_params->id, head);
267fa247a2aSRuchika Gupta 	if (rc)
268fa247a2aSRuchika Gupta 		goto out;
269fa247a2aSRuchika Gupta 
270fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_token(session, head);
271fa247a2aSRuchika Gupta 	if (rc)
272fa247a2aSRuchika Gupta 		goto out;
273fa247a2aSRuchika Gupta 
274fa247a2aSRuchika Gupta 	/*
275fa247a2aSRuchika Gupta 	 * Execute target processing and add value as attribute
276fa247a2aSRuchika Gupta 	 * PKCS11_CKA_VALUE. Symm key generation: depends on target
277fa247a2aSRuchika Gupta 	 * processing to be used.
278fa247a2aSRuchika Gupta 	 */
279fa247a2aSRuchika Gupta 	switch (proc_params->id) {
280fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
281fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
282fa247a2aSRuchika Gupta 		/* Generate random of size specified by attribute VALUE_LEN */
283fa247a2aSRuchika Gupta 		rc = generate_random_key_value(&head);
284fa247a2aSRuchika Gupta 		if (rc)
285fa247a2aSRuchika Gupta 			goto out;
286fa247a2aSRuchika Gupta 		break;
287fa247a2aSRuchika Gupta 
288fa247a2aSRuchika Gupta 	default:
289fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
290fa247a2aSRuchika Gupta 		goto out;
291fa247a2aSRuchika Gupta 	}
292fa247a2aSRuchika Gupta 
293fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
294fa247a2aSRuchika Gupta 	proc_params = NULL;
295fa247a2aSRuchika Gupta 
296fa247a2aSRuchika Gupta 	/*
297fa247a2aSRuchika Gupta 	 * Object is ready, register it and return a handle.
298fa247a2aSRuchika Gupta 	 */
299fa247a2aSRuchika Gupta 	rc = create_object(session, head, &obj_handle);
300fa247a2aSRuchika Gupta 	if (rc)
301fa247a2aSRuchika Gupta 		goto out;
302fa247a2aSRuchika Gupta 
303fa247a2aSRuchika Gupta 	/*
304fa247a2aSRuchika Gupta 	 * Now obj_handle (through the related struct pkcs11_object instance)
305fa247a2aSRuchika Gupta 	 * owns the serialized buffer that holds the object attributes.
306fa247a2aSRuchika Gupta 	 * We reset head to NULL as it is no more the buffer owner and would
307fa247a2aSRuchika Gupta 	 * be freed at function out.
308fa247a2aSRuchika Gupta 	 */
309fa247a2aSRuchika Gupta 	head = NULL;
310fa247a2aSRuchika Gupta 
311fa247a2aSRuchika Gupta 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
312fa247a2aSRuchika Gupta 	out->memref.size = sizeof(obj_handle);
313fa247a2aSRuchika Gupta 
314fa247a2aSRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
315fa247a2aSRuchika Gupta 	     session->handle, obj_handle);
316fa247a2aSRuchika Gupta 
317fa247a2aSRuchika Gupta out:
318fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
319fa247a2aSRuchika Gupta 	TEE_Free(template);
320fa247a2aSRuchika Gupta 	TEE_Free(head);
321fa247a2aSRuchika Gupta 
322fa247a2aSRuchika Gupta 	return rc;
323fa247a2aSRuchika Gupta }
324fa247a2aSRuchika Gupta 
325013934d8SVesa Jääskeläinen enum pkcs11_rc alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj,
326013934d8SVesa Jääskeläinen 					    uint32_t attribute,
327013934d8SVesa Jääskeläinen 					    void **data, size_t *size)
328013934d8SVesa Jääskeläinen {
329013934d8SVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
330013934d8SVesa Jääskeläinen 	void *ptr = NULL;
331013934d8SVesa Jääskeläinen 	uint32_t sz = 0;
332013934d8SVesa Jääskeläinen 
333013934d8SVesa Jääskeläinen 	res = TEE_GetObjectBufferAttribute(tee_obj, attribute, NULL, &sz);
334013934d8SVesa Jääskeläinen 	if (res != TEE_ERROR_SHORT_BUFFER)
335013934d8SVesa Jääskeläinen 		return PKCS11_CKR_FUNCTION_FAILED;
336013934d8SVesa Jääskeläinen 
337013934d8SVesa Jääskeläinen 	ptr = TEE_Malloc(sz, TEE_USER_MEM_HINT_NO_FILL_ZERO);
338013934d8SVesa Jääskeläinen 	if (!ptr)
339013934d8SVesa Jääskeläinen 		return PKCS11_CKR_DEVICE_MEMORY;
340013934d8SVesa Jääskeläinen 
341013934d8SVesa Jääskeläinen 	res = TEE_GetObjectBufferAttribute(tee_obj, attribute, ptr, &sz);
342013934d8SVesa Jääskeläinen 	if (res) {
343013934d8SVesa Jääskeläinen 		TEE_Free(ptr);
344013934d8SVesa Jääskeläinen 	} else {
345013934d8SVesa Jääskeläinen 		*data = ptr;
346013934d8SVesa Jääskeläinen 		*size = sz;
347013934d8SVesa Jääskeläinen 	}
348013934d8SVesa Jääskeläinen 
349013934d8SVesa Jääskeläinen 	return tee2pkcs_error(res);
350013934d8SVesa Jääskeläinen }
351013934d8SVesa Jääskeläinen 
352013934d8SVesa Jääskeläinen enum pkcs11_rc tee2pkcs_add_attribute(struct obj_attrs **head,
353013934d8SVesa Jääskeläinen 				      uint32_t pkcs11_id,
354013934d8SVesa Jääskeläinen 				      TEE_ObjectHandle tee_obj,
355013934d8SVesa Jääskeläinen 				      uint32_t tee_id)
356013934d8SVesa Jääskeläinen {
357013934d8SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
358013934d8SVesa Jääskeläinen 	void *a_ptr = NULL;
359013934d8SVesa Jääskeläinen 	size_t a_size = 0;
360013934d8SVesa Jääskeläinen 
361013934d8SVesa Jääskeläinen 	rc = alloc_get_tee_attribute_data(tee_obj, tee_id, &a_ptr, &a_size);
362013934d8SVesa Jääskeläinen 	if (rc)
363013934d8SVesa Jääskeläinen 		goto out;
364013934d8SVesa Jääskeläinen 
365013934d8SVesa Jääskeläinen 	rc = add_attribute(head, pkcs11_id, a_ptr, a_size);
366013934d8SVesa Jääskeläinen 
367013934d8SVesa Jääskeläinen 	TEE_Free(a_ptr);
368013934d8SVesa Jääskeläinen 
369013934d8SVesa Jääskeläinen out:
370013934d8SVesa Jääskeläinen 	if (rc)
371013934d8SVesa Jääskeläinen 		EMSG("Failed TEE attribute %#"PRIx32" for %#"PRIx32"/%s",
372013934d8SVesa Jääskeläinen 		     tee_id, pkcs11_id, id2str_attr(pkcs11_id));
373013934d8SVesa Jääskeläinen 	return rc;
374013934d8SVesa Jääskeläinen }
375013934d8SVesa Jääskeläinen 
376013934d8SVesa Jääskeläinen enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client,
377013934d8SVesa Jääskeläinen 				       uint32_t ptypes, TEE_Param *params)
378013934d8SVesa Jääskeläinen {
379013934d8SVesa Jääskeläinen 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
380013934d8SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE,
381013934d8SVesa Jääskeläinen 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
382013934d8SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE);
383013934d8SVesa Jääskeläinen 	TEE_Param *ctrl = params;
384013934d8SVesa Jääskeläinen 	TEE_Param *out = params + 2;
385013934d8SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
386013934d8SVesa Jääskeläinen 	struct serialargs ctrlargs = { };
387013934d8SVesa Jääskeläinen 	struct pkcs11_session *session = NULL;
388013934d8SVesa Jääskeläinen 	struct pkcs11_attribute_head *proc_params = NULL;
389013934d8SVesa Jääskeläinen 	struct obj_attrs *pub_head = NULL;
390013934d8SVesa Jääskeläinen 	struct obj_attrs *priv_head = NULL;
391013934d8SVesa Jääskeläinen 	struct pkcs11_object_head *pub_template = NULL;
392013934d8SVesa Jääskeläinen 	struct pkcs11_object_head *priv_template = NULL;
393013934d8SVesa Jääskeläinen 	struct pkcs11_object *object = NULL;
394013934d8SVesa Jääskeläinen 	size_t pub_template_size = 0;
395013934d8SVesa Jääskeläinen 	size_t priv_template_size = 0;
396013934d8SVesa Jääskeläinen 	uint32_t pubkey_handle = 0;
397013934d8SVesa Jääskeläinen 	uint32_t privkey_handle = 0;
398013934d8SVesa Jääskeläinen 	uint32_t *hdl_ptr = NULL;
399013934d8SVesa Jääskeläinen 	size_t out_ref_size = sizeof(pubkey_handle) + sizeof(privkey_handle);
400013934d8SVesa Jääskeläinen 
401013934d8SVesa Jääskeläinen 	if (!client || ptypes != exp_pt || out->memref.size != out_ref_size)
402013934d8SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
403013934d8SVesa Jääskeläinen 
404013934d8SVesa Jääskeläinen 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
405013934d8SVesa Jääskeläinen 
406013934d8SVesa Jääskeläinen 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
407013934d8SVesa Jääskeläinen 	if (rc)
408013934d8SVesa Jääskeläinen 		return rc;
409013934d8SVesa Jääskeläinen 
410013934d8SVesa Jääskeläinen 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
411013934d8SVesa Jääskeläinen 	if (rc)
412013934d8SVesa Jääskeläinen 		goto out;
413013934d8SVesa Jääskeläinen 
414013934d8SVesa Jääskeläinen 	rc = serialargs_alloc_get_attributes(&ctrlargs, &pub_template);
415013934d8SVesa Jääskeläinen 	if (rc)
416013934d8SVesa Jääskeläinen 		goto out;
417013934d8SVesa Jääskeläinen 
418013934d8SVesa Jääskeläinen 	rc = serialargs_alloc_get_attributes(&ctrlargs, &priv_template);
419013934d8SVesa Jääskeläinen 	if (rc)
420013934d8SVesa Jääskeläinen 		goto out;
421013934d8SVesa Jääskeläinen 
422013934d8SVesa Jääskeläinen 	if (serialargs_remaining_bytes(&ctrlargs)) {
423013934d8SVesa Jääskeläinen 		rc = PKCS11_CKR_ARGUMENTS_BAD;
424013934d8SVesa Jääskeläinen 		goto out;
425013934d8SVesa Jääskeläinen 	}
426013934d8SVesa Jääskeläinen 
427013934d8SVesa Jääskeläinen 	rc = get_ready_session(session);
428013934d8SVesa Jääskeläinen 	if (rc)
429013934d8SVesa Jääskeläinen 		goto out;
430013934d8SVesa Jääskeläinen 
431013934d8SVesa Jääskeläinen 	rc = check_mechanism_against_processing(session, proc_params->id,
432013934d8SVesa Jääskeläinen 						PKCS11_FUNCTION_GENERATE_PAIR,
433013934d8SVesa Jääskeläinen 						PKCS11_FUNC_STEP_INIT);
434013934d8SVesa Jääskeläinen 	if (rc)
435013934d8SVesa Jääskeläinen 		goto out;
436013934d8SVesa Jääskeläinen 
437013934d8SVesa Jääskeläinen 	pub_template_size = sizeof(*pub_template) + pub_template->attrs_size;
438013934d8SVesa Jääskeläinen 
439013934d8SVesa Jääskeläinen 	rc = create_attributes_from_template(&pub_head, pub_template,
440013934d8SVesa Jääskeläinen 					     pub_template_size, NULL,
441013934d8SVesa Jääskeläinen 					     PKCS11_FUNCTION_GENERATE_PAIR,
442013934d8SVesa Jääskeläinen 					     proc_params->id,
443013934d8SVesa Jääskeläinen 					     PKCS11_CKO_PUBLIC_KEY);
444013934d8SVesa Jääskeläinen 	if (rc)
445013934d8SVesa Jääskeläinen 		goto out;
446013934d8SVesa Jääskeläinen 
447013934d8SVesa Jääskeläinen 	TEE_Free(pub_template);
448013934d8SVesa Jääskeläinen 	pub_template = NULL;
449013934d8SVesa Jääskeläinen 
450013934d8SVesa Jääskeläinen 	priv_template_size = sizeof(*priv_template) +
451013934d8SVesa Jääskeläinen 			     priv_template->attrs_size;
452013934d8SVesa Jääskeläinen 
453013934d8SVesa Jääskeläinen 	rc = create_attributes_from_template(&priv_head, priv_template,
454013934d8SVesa Jääskeläinen 					     priv_template_size, NULL,
455013934d8SVesa Jääskeläinen 					     PKCS11_FUNCTION_GENERATE_PAIR,
456013934d8SVesa Jääskeläinen 					     proc_params->id,
457013934d8SVesa Jääskeläinen 					     PKCS11_CKO_PRIVATE_KEY);
458013934d8SVesa Jääskeläinen 	if (rc)
459013934d8SVesa Jääskeläinen 		goto out;
460013934d8SVesa Jääskeläinen 
461013934d8SVesa Jääskeläinen 	TEE_Free(priv_template);
462013934d8SVesa Jääskeläinen 	priv_template = NULL;
463013934d8SVesa Jääskeläinen 
464013934d8SVesa Jääskeläinen 	/* Generate CKA_ID for keys if not specified by the templates */
465013934d8SVesa Jääskeläinen 	rc = add_missing_attribute_id(&pub_head, &priv_head);
466013934d8SVesa Jääskeläinen 	if (rc)
467013934d8SVesa Jääskeläinen 		goto out;
468013934d8SVesa Jääskeläinen 
469013934d8SVesa Jääskeläinen 	/* Check created object against processing and token state */
470013934d8SVesa Jääskeläinen 	rc = check_created_attrs(pub_head, priv_head);
471013934d8SVesa Jääskeläinen 	if (rc)
472013934d8SVesa Jääskeläinen 		goto out;
473013934d8SVesa Jääskeläinen 
474013934d8SVesa Jääskeläinen 	rc = check_created_attrs_against_processing(proc_params->id, pub_head);
475013934d8SVesa Jääskeläinen 	if (rc)
476013934d8SVesa Jääskeläinen 		goto out;
477013934d8SVesa Jääskeläinen 
478013934d8SVesa Jääskeläinen 	rc = check_created_attrs_against_processing(proc_params->id,
479013934d8SVesa Jääskeläinen 						    priv_head);
480013934d8SVesa Jääskeläinen 	if (rc)
481013934d8SVesa Jääskeläinen 		goto out;
482013934d8SVesa Jääskeläinen 
483013934d8SVesa Jääskeläinen 	rc = check_created_attrs_against_token(session, pub_head);
484013934d8SVesa Jääskeläinen 	if (rc)
485013934d8SVesa Jääskeläinen 		goto out;
486013934d8SVesa Jääskeläinen 
487013934d8SVesa Jääskeläinen 	rc = check_access_attrs_against_token(session, pub_head);
488013934d8SVesa Jääskeläinen 	if (rc)
489013934d8SVesa Jääskeläinen 		goto out;
490013934d8SVesa Jääskeläinen 
491013934d8SVesa Jääskeläinen 	rc = check_created_attrs_against_token(session, priv_head);
492013934d8SVesa Jääskeläinen 	if (rc)
493013934d8SVesa Jääskeläinen 		goto out;
494013934d8SVesa Jääskeläinen 
495013934d8SVesa Jääskeläinen 	rc = check_access_attrs_against_token(session, priv_head);
496013934d8SVesa Jääskeläinen 	if (rc)
497013934d8SVesa Jääskeläinen 		goto out;
498013934d8SVesa Jääskeläinen 
499013934d8SVesa Jääskeläinen 	/* Generate key pair */
500013934d8SVesa Jääskeläinen 	switch (proc_params->id) {
50102b16804SVesa Jääskeläinen 	case PKCS11_CKM_EC_KEY_PAIR_GEN:
50202b16804SVesa Jääskeläinen 		rc = generate_ec_keys(proc_params, &pub_head, &priv_head);
50302b16804SVesa Jääskeläinen 		break;
504013934d8SVesa Jääskeläinen 	default:
505013934d8SVesa Jääskeläinen 		rc = PKCS11_CKR_MECHANISM_INVALID;
506013934d8SVesa Jääskeläinen 		break;
507013934d8SVesa Jääskeläinen 	}
508013934d8SVesa Jääskeläinen 	if (rc)
509013934d8SVesa Jääskeläinen 		goto out;
510013934d8SVesa Jääskeläinen 
511013934d8SVesa Jääskeläinen 	TEE_Free(proc_params);
512013934d8SVesa Jääskeläinen 	proc_params = NULL;
513013934d8SVesa Jääskeläinen 
514013934d8SVesa Jääskeläinen 	/*
515013934d8SVesa Jääskeläinen 	 * Object is ready, register it and return a handle.
516013934d8SVesa Jääskeläinen 	 */
517013934d8SVesa Jääskeläinen 	rc = create_object(session, pub_head, &pubkey_handle);
518013934d8SVesa Jääskeläinen 	if (rc)
519013934d8SVesa Jääskeläinen 		goto out;
520013934d8SVesa Jääskeläinen 
521013934d8SVesa Jääskeläinen 	/*
522013934d8SVesa Jääskeläinen 	 * Now obj_handle (through the related struct pkcs11_object instance)
523013934d8SVesa Jääskeläinen 	 * owns the serialized buffer that holds the object attributes.
524013934d8SVesa Jääskeläinen 	 * We reset local pub_head to NULL to mark that ownership has been
525013934d8SVesa Jääskeläinen 	 * transferred.
526013934d8SVesa Jääskeläinen 	 */
527013934d8SVesa Jääskeläinen 	pub_head = NULL;
528013934d8SVesa Jääskeläinen 
529013934d8SVesa Jääskeläinen 	rc = create_object(session, priv_head, &privkey_handle);
530013934d8SVesa Jääskeläinen 	if (rc)
531013934d8SVesa Jääskeläinen 		goto out;
532013934d8SVesa Jääskeläinen 
533013934d8SVesa Jääskeläinen 	/* Ownership has been transferred so mark it with NULL */
534013934d8SVesa Jääskeläinen 	priv_head = NULL;
535013934d8SVesa Jääskeläinen 
536013934d8SVesa Jääskeläinen 	hdl_ptr = (uint32_t *)out->memref.buffer;
537013934d8SVesa Jääskeläinen 
538013934d8SVesa Jääskeläinen 	TEE_MemMove(hdl_ptr, &pubkey_handle, sizeof(pubkey_handle));
539013934d8SVesa Jääskeläinen 	TEE_MemMove(hdl_ptr + 1, &privkey_handle, sizeof(privkey_handle));
540013934d8SVesa Jääskeläinen 
541013934d8SVesa Jääskeläinen 	pubkey_handle = 0;
542013934d8SVesa Jääskeläinen 	privkey_handle = 0;
543013934d8SVesa Jääskeläinen 
544013934d8SVesa Jääskeläinen 	DMSG("PKCS11 session %"PRIu32": create key pair %#"PRIx32"/%#"PRIx32,
545013934d8SVesa Jääskeläinen 	     session->handle, privkey_handle, pubkey_handle);
546013934d8SVesa Jääskeläinen 
547013934d8SVesa Jääskeläinen out:
548013934d8SVesa Jääskeläinen 	if (pubkey_handle) {
549013934d8SVesa Jääskeläinen 		object = pkcs11_handle2object(pubkey_handle, session);
550013934d8SVesa Jääskeläinen 		if (!object)
551013934d8SVesa Jääskeläinen 			TEE_Panic(0);
552013934d8SVesa Jääskeläinen 		destroy_object(session, object, false);
553013934d8SVesa Jääskeläinen 	}
554013934d8SVesa Jääskeläinen 	TEE_Free(priv_head);
555013934d8SVesa Jääskeläinen 	TEE_Free(pub_head);
556013934d8SVesa Jääskeläinen 	TEE_Free(priv_template);
557013934d8SVesa Jääskeläinen 	TEE_Free(pub_template);
558013934d8SVesa Jääskeläinen 	TEE_Free(proc_params);
559013934d8SVesa Jääskeläinen 
560013934d8SVesa Jääskeläinen 	return rc;
561013934d8SVesa Jääskeläinen }
562013934d8SVesa Jääskeläinen 
563512cbf1dSJens Wiklander /*
564512cbf1dSJens Wiklander  * entry_processing_init - Generic entry for initializing a processing
565512cbf1dSJens Wiklander  *
566512cbf1dSJens Wiklander  * @client = client reference
567512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
568512cbf1dSJens Wiklander  * @params = Invocation parameters reference
569512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
570512cbf1dSJens Wiklander  */
571512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
572512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
573512cbf1dSJens Wiklander 				     enum processing_func function)
574512cbf1dSJens Wiklander {
575512cbf1dSJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
576512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
577512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
578512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE);
579512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
580512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
581512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
582512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
583512cbf1dSJens Wiklander 	struct pkcs11_attribute_head *proc_params = NULL;
584512cbf1dSJens Wiklander 	uint32_t key_handle = 0;
585512cbf1dSJens Wiklander 	struct pkcs11_object *obj = NULL;
586512cbf1dSJens Wiklander 
587512cbf1dSJens Wiklander 	if (!client || ptypes != exp_pt)
588512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
589512cbf1dSJens Wiklander 
590512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
591512cbf1dSJens Wiklander 
592512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
593512cbf1dSJens Wiklander 	if (rc)
594512cbf1dSJens Wiklander 		return rc;
595512cbf1dSJens Wiklander 
5969e91a619SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_DIGEST) {
597512cbf1dSJens Wiklander 		rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
598512cbf1dSJens Wiklander 		if (rc)
599512cbf1dSJens Wiklander 			return rc;
6009e91a619SVesa Jääskeläinen 	}
601512cbf1dSJens Wiklander 
602512cbf1dSJens Wiklander 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
603512cbf1dSJens Wiklander 	if (rc)
604512cbf1dSJens Wiklander 		return rc;
605512cbf1dSJens Wiklander 
606512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs)) {
607512cbf1dSJens Wiklander 		rc = PKCS11_CKR_ARGUMENTS_BAD;
608512cbf1dSJens Wiklander 		goto out;
609512cbf1dSJens Wiklander 	}
610512cbf1dSJens Wiklander 
611512cbf1dSJens Wiklander 	rc = get_ready_session(session);
612512cbf1dSJens Wiklander 	if (rc)
613512cbf1dSJens Wiklander 		goto out;
614512cbf1dSJens Wiklander 
6159e91a619SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_DIGEST) {
616512cbf1dSJens Wiklander 		obj = pkcs11_handle2object(key_handle, session);
617512cbf1dSJens Wiklander 		if (!obj) {
618512cbf1dSJens Wiklander 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
619512cbf1dSJens Wiklander 			goto out;
620512cbf1dSJens Wiklander 		}
6219e91a619SVesa Jääskeläinen 	}
622512cbf1dSJens Wiklander 
623512cbf1dSJens Wiklander 	rc = set_processing_state(session, function, obj, NULL);
624512cbf1dSJens Wiklander 	if (rc)
625512cbf1dSJens Wiklander 		goto out;
626512cbf1dSJens Wiklander 
627512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, proc_params->id,
628512cbf1dSJens Wiklander 						function,
629512cbf1dSJens Wiklander 						PKCS11_FUNC_STEP_INIT);
630512cbf1dSJens Wiklander 	if (rc)
631512cbf1dSJens Wiklander 		goto out;
632512cbf1dSJens Wiklander 
6339e91a619SVesa Jääskeläinen 	if (obj) {
6349e91a619SVesa Jääskeläinen 		rc = check_parent_attrs_against_processing(proc_params->id,
6359e91a619SVesa Jääskeläinen 							   function,
636512cbf1dSJens Wiklander 							   obj->attributes);
637512cbf1dSJens Wiklander 		if (rc)
638512cbf1dSJens Wiklander 			goto out;
639512cbf1dSJens Wiklander 
6409e91a619SVesa Jääskeläinen 		rc = check_access_attrs_against_token(session,
6419e91a619SVesa Jääskeläinen 						      obj->attributes);
642512cbf1dSJens Wiklander 		if (rc)
643512cbf1dSJens Wiklander 			goto out;
6449e91a619SVesa Jääskeläinen 	}
645512cbf1dSJens Wiklander 
646512cbf1dSJens Wiklander 	if (processing_is_tee_symm(proc_params->id))
647512cbf1dSJens Wiklander 		rc = init_symm_operation(session, function, proc_params, obj);
648fb279d8bSVesa Jääskeläinen 	else if (processing_is_tee_asymm(proc_params->id))
649fb279d8bSVesa Jääskeläinen 		rc = init_asymm_operation(session, function, proc_params, obj);
6509e91a619SVesa Jääskeläinen 	else if (processing_is_tee_digest(proc_params->id))
6519e91a619SVesa Jääskeläinen 		rc = init_digest_operation(session, proc_params);
652512cbf1dSJens Wiklander 	else
653512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
654512cbf1dSJens Wiklander 
655512cbf1dSJens Wiklander 	if (rc == PKCS11_CKR_OK) {
656512cbf1dSJens Wiklander 		session->processing->mecha_type = proc_params->id;
657512cbf1dSJens Wiklander 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
658512cbf1dSJens Wiklander 		     session->handle, id2str_proc(proc_params->id),
659512cbf1dSJens Wiklander 		     id2str_function(function));
660512cbf1dSJens Wiklander 	}
661512cbf1dSJens Wiklander 
662512cbf1dSJens Wiklander out:
663512cbf1dSJens Wiklander 	if (rc && session)
664512cbf1dSJens Wiklander 		release_active_processing(session);
665512cbf1dSJens Wiklander 
666512cbf1dSJens Wiklander 	TEE_Free(proc_params);
667512cbf1dSJens Wiklander 
668512cbf1dSJens Wiklander 	return rc;
669512cbf1dSJens Wiklander }
670512cbf1dSJens Wiklander 
671512cbf1dSJens Wiklander /*
672512cbf1dSJens Wiklander  * entry_processing_step - Generic entry on active processing
673512cbf1dSJens Wiklander  *
674512cbf1dSJens Wiklander  * @client = client reference
675512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
676512cbf1dSJens Wiklander  * @params = Invocation parameters reference
677512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
678512cbf1dSJens Wiklander  * @step - update, oneshot, final
679512cbf1dSJens Wiklander  */
680512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
681512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
682512cbf1dSJens Wiklander 				     enum processing_func function,
683512cbf1dSJens Wiklander 				     enum processing_step step)
684512cbf1dSJens Wiklander {
685512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
686512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
687512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
688512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
689512cbf1dSJens Wiklander 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
6909e91a619SVesa Jääskeläinen 	uint32_t key_handle = 0;
6919e91a619SVesa Jääskeläinen 	struct pkcs11_object *obj = NULL;
692512cbf1dSJens Wiklander 
693512cbf1dSJens Wiklander 	if (!client ||
694512cbf1dSJens Wiklander 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
695512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
696512cbf1dSJens Wiklander 
697512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
698512cbf1dSJens Wiklander 
699512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
700512cbf1dSJens Wiklander 	if (rc)
701512cbf1dSJens Wiklander 		return rc;
702512cbf1dSJens Wiklander 
7039e91a619SVesa Jääskeläinen 	if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
7049e91a619SVesa Jääskeläinen 		assert(function == PKCS11_FUNCTION_DIGEST);
7059e91a619SVesa Jääskeläinen 
7069e91a619SVesa Jääskeläinen 		rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
7079e91a619SVesa Jääskeläinen 		if (rc)
7089e91a619SVesa Jääskeläinen 			return rc;
7099e91a619SVesa Jääskeläinen 	}
7109e91a619SVesa Jääskeläinen 
711512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs))
712512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
713512cbf1dSJens Wiklander 
714512cbf1dSJens Wiklander 	rc = get_active_session(session, function);
715512cbf1dSJens Wiklander 	if (rc)
716512cbf1dSJens Wiklander 		return rc;
717512cbf1dSJens Wiklander 
7189e91a619SVesa Jääskeläinen 	if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
7199e91a619SVesa Jääskeläinen 		assert(function == PKCS11_FUNCTION_DIGEST);
7209e91a619SVesa Jääskeläinen 
7219e91a619SVesa Jääskeläinen 		obj = pkcs11_handle2object(key_handle, session);
7229e91a619SVesa Jääskeläinen 		if (!obj) {
7239e91a619SVesa Jääskeläinen 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
7249e91a619SVesa Jääskeläinen 			goto out;
7259e91a619SVesa Jääskeläinen 		}
7269e91a619SVesa Jääskeläinen 
7279e91a619SVesa Jääskeläinen 		rc = check_access_attrs_against_token(session,
7289e91a619SVesa Jääskeläinen 						      obj->attributes);
7299e91a619SVesa Jääskeläinen 		if (rc) {
7309e91a619SVesa Jääskeläinen 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
7319e91a619SVesa Jääskeläinen 			goto out;
7329e91a619SVesa Jääskeläinen 		}
7339e91a619SVesa Jääskeläinen 	}
7349e91a619SVesa Jääskeläinen 
735512cbf1dSJens Wiklander 	mecha_type = session->processing->mecha_type;
736512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, mecha_type,
737512cbf1dSJens Wiklander 						function, step);
738512cbf1dSJens Wiklander 	if (rc)
739512cbf1dSJens Wiklander 		goto out;
740512cbf1dSJens Wiklander 
741512cbf1dSJens Wiklander 	if (processing_is_tee_symm(mecha_type))
742512cbf1dSJens Wiklander 		rc = step_symm_operation(session, function, step,
743512cbf1dSJens Wiklander 					 ptypes, params);
744fb279d8bSVesa Jääskeläinen 	else if (processing_is_tee_asymm(mecha_type))
745fb279d8bSVesa Jääskeläinen 		rc = step_asymm_operation(session, function, step,
746fb279d8bSVesa Jääskeläinen 					  ptypes, params);
7479e91a619SVesa Jääskeläinen 	else if (processing_is_tee_digest(mecha_type))
7489e91a619SVesa Jääskeläinen 		rc = step_digest_operation(session, step, obj, ptypes, params);
749512cbf1dSJens Wiklander 	else
750512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
751512cbf1dSJens Wiklander 
7529e91a619SVesa Jääskeläinen 	if (rc == PKCS11_CKR_OK && (step == PKCS11_FUNC_STEP_UPDATE ||
7539e91a619SVesa Jääskeläinen 				    step == PKCS11_FUNC_STEP_UPDATE_KEY)) {
754512cbf1dSJens Wiklander 		session->processing->updated = true;
755512cbf1dSJens Wiklander 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
756512cbf1dSJens Wiklander 		     session->handle, id2str_proc(mecha_type),
757512cbf1dSJens Wiklander 		     id2str_function(function));
758512cbf1dSJens Wiklander 	}
759512cbf1dSJens Wiklander 
760512cbf1dSJens Wiklander out:
761512cbf1dSJens Wiklander 	switch (step) {
762512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_UPDATE:
7639e91a619SVesa Jääskeläinen 	case PKCS11_FUNC_STEP_UPDATE_KEY:
764512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
765512cbf1dSJens Wiklander 			release_active_processing(session);
766512cbf1dSJens Wiklander 		break;
767512cbf1dSJens Wiklander 	default:
768512cbf1dSJens Wiklander 		/* ONESHOT and FINAL terminates processing on success */
769512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
770512cbf1dSJens Wiklander 			release_active_processing(session);
771512cbf1dSJens Wiklander 		break;
772512cbf1dSJens Wiklander 	}
773512cbf1dSJens Wiklander 
774512cbf1dSJens Wiklander 	return rc;
775512cbf1dSJens Wiklander }
77648799892SRuchika Gupta 
7774dad6642SRuchika Gupta enum pkcs11_rc entry_processing_key(struct pkcs11_client *client,
7784dad6642SRuchika Gupta 				    uint32_t ptypes, TEE_Param *params,
7794dad6642SRuchika Gupta 				    enum processing_func function)
78048799892SRuchika Gupta {
78148799892SRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
78248799892SRuchika Gupta 						TEE_PARAM_TYPE_NONE,
78348799892SRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
78448799892SRuchika Gupta 						TEE_PARAM_TYPE_NONE);
78548799892SRuchika Gupta 	TEE_Param *ctrl = params;
78648799892SRuchika Gupta 	TEE_Param *out = params + 2;
78748799892SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
78848799892SRuchika Gupta 	struct serialargs ctrlargs = { };
78948799892SRuchika Gupta 	struct pkcs11_session *session = NULL;
79048799892SRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
79148799892SRuchika Gupta 	struct pkcs11_object_head *template = NULL;
79248799892SRuchika Gupta 	uint32_t parent_handle = 0;
79348799892SRuchika Gupta 	uint32_t obj_handle = 0;
79448799892SRuchika Gupta 	struct pkcs11_object *parent = NULL;
79548799892SRuchika Gupta 	struct obj_attrs *head = NULL;
79648799892SRuchika Gupta 	size_t template_size = 0;
7978c499324SRuchika Gupta 	void *out_buf = NULL;
7988c499324SRuchika Gupta 	uint32_t out_size = 0;
79948799892SRuchika Gupta 
80048799892SRuchika Gupta 	if (!client || ptypes != exp_pt ||
80148799892SRuchika Gupta 	    out->memref.size != sizeof(obj_handle))
80248799892SRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
80348799892SRuchika Gupta 
80448799892SRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
80548799892SRuchika Gupta 
80648799892SRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
80748799892SRuchika Gupta 	if (rc)
80848799892SRuchika Gupta 		return rc;
80948799892SRuchika Gupta 
81048799892SRuchika Gupta 	rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t));
81148799892SRuchika Gupta 	if (rc)
81248799892SRuchika Gupta 		return rc;
81348799892SRuchika Gupta 
81448799892SRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
81548799892SRuchika Gupta 	if (rc)
816*5f80f270SRuchika Gupta 		return rc;
81748799892SRuchika Gupta 
81848799892SRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
81948799892SRuchika Gupta 	if (rc)
82048799892SRuchika Gupta 		goto out_free;
82148799892SRuchika Gupta 
82248799892SRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
82348799892SRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
82448799892SRuchika Gupta 		goto out_free;
82548799892SRuchika Gupta 	}
82648799892SRuchika Gupta 
82748799892SRuchika Gupta 	/* Return error if processing already active */
82848799892SRuchika Gupta 	rc = get_ready_session(session);
82948799892SRuchika Gupta 	if (rc)
83048799892SRuchika Gupta 		goto out_free;
83148799892SRuchika Gupta 
83248799892SRuchika Gupta 	/* Check parent handle */
83348799892SRuchika Gupta 	parent = pkcs11_handle2object(parent_handle, session);
83448799892SRuchika Gupta 	if (!parent) {
83548799892SRuchika Gupta 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
83648799892SRuchika Gupta 		goto out_free;
83748799892SRuchika Gupta 	}
83848799892SRuchika Gupta 
83948799892SRuchika Gupta 	/* Check if mechanism can be used for derivation function */
84048799892SRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
84148799892SRuchika Gupta 						function,
84248799892SRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
84348799892SRuchika Gupta 	if (rc)
84448799892SRuchika Gupta 		goto out_free;
84548799892SRuchika Gupta 
84648799892SRuchika Gupta 	/* Set the processing state to active */
84748799892SRuchika Gupta 	rc = set_processing_state(session, function, parent, NULL);
84848799892SRuchika Gupta 	if (rc)
84948799892SRuchika Gupta 		goto out_free;
85048799892SRuchika Gupta 
85148799892SRuchika Gupta 	/*
85248799892SRuchika Gupta 	 * Check if base/parent key has CKA_DERIVE set and its key type is
85348799892SRuchika Gupta 	 * compatible with the mechanism passed
85448799892SRuchika Gupta 	 */
85548799892SRuchika Gupta 	rc = check_parent_attrs_against_processing(proc_params->id, function,
85648799892SRuchika Gupta 						   parent->attributes);
857d05ab5feSRuchika Gupta 	if (rc) {
858d05ab5feSRuchika Gupta 		/*
859d05ab5feSRuchika Gupta 		 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
860d05ab5feSRuchika Gupta 		 * specified with C_Derive/Unwrap() in the specification. So
861d05ab5feSRuchika Gupta 		 * return the next most appropriate error.
862d05ab5feSRuchika Gupta 		 */
863d05ab5feSRuchika Gupta 		if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED)
864d05ab5feSRuchika Gupta 			rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT;
86548799892SRuchika Gupta 		goto out;
866d05ab5feSRuchika Gupta 	}
86748799892SRuchika Gupta 
86848799892SRuchika Gupta 	/* Check access of base/parent key */
86948799892SRuchika Gupta 	rc = check_access_attrs_against_token(session, parent->attributes);
87048799892SRuchika Gupta 	if (rc)
87148799892SRuchika Gupta 		goto out;
87248799892SRuchika Gupta 
87348799892SRuchika Gupta 	template_size = sizeof(*template) + template->attrs_size;
87448799892SRuchika Gupta 	/*
87548799892SRuchika Gupta 	 * Prepare a clean initial state for the requested object attributes
87648799892SRuchika Gupta 	 * using base/parent key attributes. Free temporary template once done.
87748799892SRuchika Gupta 	 */
87848799892SRuchika Gupta 	rc = create_attributes_from_template(&head, template, template_size,
87948799892SRuchika Gupta 					     parent->attributes,
88048799892SRuchika Gupta 					     function,
88148799892SRuchika Gupta 					     proc_params->id,
88248799892SRuchika Gupta 					     PKCS11_CKO_UNDEFINED_ID);
88348799892SRuchika Gupta 	if (rc)
88448799892SRuchika Gupta 		goto out;
88548799892SRuchika Gupta 
88648799892SRuchika Gupta 	TEE_Free(template);
88748799892SRuchika Gupta 	template = NULL;
88848799892SRuchika Gupta 
88948799892SRuchika Gupta 	/* check_created_attrs() is called later once key size is known */
89048799892SRuchika Gupta 
89148799892SRuchika Gupta 	rc = check_created_attrs_against_processing(proc_params->id, head);
89248799892SRuchika Gupta 	if (rc)
89348799892SRuchika Gupta 		goto out;
89448799892SRuchika Gupta 
89548799892SRuchika Gupta 	rc = check_created_attrs_against_token(session, head);
89648799892SRuchika Gupta 	if (rc)
89748799892SRuchika Gupta 		goto out;
89848799892SRuchika Gupta 
8998c499324SRuchika Gupta 	if (processing_is_tee_symm(proc_params->id)) {
90048799892SRuchika Gupta 		/*
90148799892SRuchika Gupta 		 * These derivation mechanism require encryption to be
90248799892SRuchika Gupta 		 * performed on the data passed in proc_params by parent
90348799892SRuchika Gupta 		 * key. Hence pass function as PKCS11_FUNCTION_ENCRYPT
90448799892SRuchika Gupta 		 * to init_symm_operation()
90548799892SRuchika Gupta 		 */
90648799892SRuchika Gupta 		rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT,
90748799892SRuchika Gupta 					 proc_params, parent);
90848799892SRuchika Gupta 		if (rc)
90948799892SRuchika Gupta 			goto out;
91048799892SRuchika Gupta 
9118c499324SRuchika Gupta 		session->processing->mecha_type = proc_params->id;
9128c499324SRuchika Gupta 
9138c499324SRuchika Gupta 		rc = derive_key_by_symm_enc(session, &out_buf, &out_size);
91448799892SRuchika Gupta 		if (rc)
91548799892SRuchika Gupta 			goto out;
9168c499324SRuchika Gupta 	} else {
91748799892SRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
91848799892SRuchika Gupta 		goto out;
91948799892SRuchika Gupta 	}
92048799892SRuchika Gupta 
9218c499324SRuchika Gupta 	rc = set_key_data(&head, out_buf, out_size);
9228c499324SRuchika Gupta 	if (rc)
9238c499324SRuchika Gupta 		goto out;
9248c499324SRuchika Gupta 
9258c499324SRuchika Gupta 	TEE_Free(out_buf);
9268c499324SRuchika Gupta 	out_buf = NULL;
9278c499324SRuchika Gupta 
92848799892SRuchika Gupta 	TEE_Free(proc_params);
92948799892SRuchika Gupta 	proc_params = NULL;
93048799892SRuchika Gupta 
93148799892SRuchika Gupta 	/*
93248799892SRuchika Gupta 	 * Object is ready, register it and return a handle.
93348799892SRuchika Gupta 	 */
93448799892SRuchika Gupta 	rc = create_object(session, head, &obj_handle);
93548799892SRuchika Gupta 	if (rc)
93648799892SRuchika Gupta 		goto out;
93748799892SRuchika Gupta 
93848799892SRuchika Gupta 	/*
93948799892SRuchika Gupta 	 * Now obj_handle (through the related struct pkcs11_object instance)
94048799892SRuchika Gupta 	 * owns the serialized buffer that holds the object attributes.
94148799892SRuchika Gupta 	 * We reset head to NULL as it is no more the buffer owner and would
94248799892SRuchika Gupta 	 * be freed at function out.
94348799892SRuchika Gupta 	 */
94448799892SRuchika Gupta 	head = NULL;
94548799892SRuchika Gupta 
94648799892SRuchika Gupta 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
94748799892SRuchika Gupta 	out->memref.size = sizeof(obj_handle);
94848799892SRuchika Gupta 
94948799892SRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32,
95048799892SRuchika Gupta 	     session->handle, obj_handle);
95148799892SRuchika Gupta 
95248799892SRuchika Gupta out:
95348799892SRuchika Gupta 	release_active_processing(session);
95448799892SRuchika Gupta out_free:
95548799892SRuchika Gupta 	TEE_Free(proc_params);
95648799892SRuchika Gupta 	TEE_Free(template);
95748799892SRuchika Gupta 	TEE_Free(head);
9588c499324SRuchika Gupta 	TEE_Free(out_buf);
95948799892SRuchika Gupta 
96048799892SRuchika Gupta 	return rc;
96148799892SRuchika Gupta }
962eb6141b6SVesa Jääskeläinen 
963eb6141b6SVesa Jääskeläinen enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client,
964eb6141b6SVesa Jääskeläinen 					       uint32_t ptypes,
965eb6141b6SVesa Jääskeläinen 					       TEE_Param *params)
966eb6141b6SVesa Jääskeläinen {
967eb6141b6SVesa Jääskeläinen 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
968eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE,
969eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE,
970eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE);
971eb6141b6SVesa Jääskeläinen 	TEE_Param *ctrl = params;
972eb6141b6SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
973eb6141b6SVesa Jääskeläinen 	struct serialargs ctrlargs = { };
974eb6141b6SVesa Jääskeläinen 	struct pkcs11_session *session = NULL;
975eb6141b6SVesa Jääskeläinen 	enum processing_func function = PKCS11_FUNCTION_UNKNOWN;
976eb6141b6SVesa Jääskeläinen 	uint32_t cmd = 0;
977eb6141b6SVesa Jääskeläinen 
978eb6141b6SVesa Jääskeläinen 	if (!client || ptypes != exp_pt)
979eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
980eb6141b6SVesa Jääskeläinen 
981eb6141b6SVesa Jääskeläinen 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
982eb6141b6SVesa Jääskeläinen 
983eb6141b6SVesa Jääskeläinen 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
984eb6141b6SVesa Jääskeläinen 	if (rc)
985eb6141b6SVesa Jääskeläinen 		return rc;
986eb6141b6SVesa Jääskeläinen 
987eb6141b6SVesa Jääskeläinen 	rc = serialargs_get_u32(&ctrlargs, &cmd);
988eb6141b6SVesa Jääskeläinen 
989eb6141b6SVesa Jääskeläinen 	if (serialargs_remaining_bytes(&ctrlargs))
990eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
991eb6141b6SVesa Jääskeläinen 
992eb6141b6SVesa Jääskeläinen 	function = func_for_cmd(cmd);
993eb6141b6SVesa Jääskeläinen 	if (function == PKCS11_FUNCTION_UNKNOWN)
994eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
995eb6141b6SVesa Jääskeläinen 
996eb6141b6SVesa Jääskeläinen 	rc = get_active_session(session, function);
997eb6141b6SVesa Jääskeläinen 	if (rc)
998eb6141b6SVesa Jääskeläinen 		return rc;
999eb6141b6SVesa Jääskeläinen 
1000eb6141b6SVesa Jääskeläinen 	release_active_processing(session);
1001eb6141b6SVesa Jääskeläinen 
1002eb6141b6SVesa Jääskeläinen 	DMSG("PKCS11 session %"PRIu32": release processing", session->handle);
1003eb6141b6SVesa Jääskeläinen 
1004eb6141b6SVesa Jääskeläinen 	return PKCS11_CKR_OK;
1005eb6141b6SVesa Jääskeläinen }
1006*5f80f270SRuchika Gupta 
1007*5f80f270SRuchika Gupta enum pkcs11_rc entry_wrap_key(struct pkcs11_client *client,
1008*5f80f270SRuchika Gupta 			      uint32_t ptypes, TEE_Param *params)
1009*5f80f270SRuchika Gupta {
1010*5f80f270SRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1011*5f80f270SRuchika Gupta 						TEE_PARAM_TYPE_NONE,
1012*5f80f270SRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
1013*5f80f270SRuchika Gupta 						TEE_PARAM_TYPE_NONE);
1014*5f80f270SRuchika Gupta 	TEE_Param *ctrl = params;
1015*5f80f270SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
1016*5f80f270SRuchika Gupta 	struct serialargs ctrlargs = { };
1017*5f80f270SRuchika Gupta 	struct pkcs11_session *session = NULL;
1018*5f80f270SRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
1019*5f80f270SRuchika Gupta 	struct pkcs11_object *wrapping_key = NULL;
1020*5f80f270SRuchika Gupta 	struct pkcs11_object *key = NULL;
1021*5f80f270SRuchika Gupta 	void *req_attrs = NULL;
1022*5f80f270SRuchika Gupta 	uint32_t wrapping_key_handle = 0;
1023*5f80f270SRuchika Gupta 	uint32_t key_handle = 0;
1024*5f80f270SRuchika Gupta 	uint32_t size = 0;
1025*5f80f270SRuchika Gupta 	void *key_data = NULL;
1026*5f80f270SRuchika Gupta 	uint32_t key_sz = 0;
1027*5f80f270SRuchika Gupta 	void *out_buf = params[2].memref.buffer;
1028*5f80f270SRuchika Gupta 	uint32_t out_size = params[2].memref.size;
1029*5f80f270SRuchika Gupta 	const enum processing_func function = PKCS11_FUNCTION_WRAP;
1030*5f80f270SRuchika Gupta 
1031*5f80f270SRuchika Gupta 	if (!client || ptypes != exp_pt ||
1032*5f80f270SRuchika Gupta 	    (out_size && !out_buf))
1033*5f80f270SRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
1034*5f80f270SRuchika Gupta 
1035*5f80f270SRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1036*5f80f270SRuchika Gupta 
1037*5f80f270SRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1038*5f80f270SRuchika Gupta 	if (rc)
1039*5f80f270SRuchika Gupta 		return rc;
1040*5f80f270SRuchika Gupta 
1041*5f80f270SRuchika Gupta 	rc = serialargs_get(&ctrlargs, &wrapping_key_handle, sizeof(uint32_t));
1042*5f80f270SRuchika Gupta 	if (rc)
1043*5f80f270SRuchika Gupta 		return rc;
1044*5f80f270SRuchika Gupta 
1045*5f80f270SRuchika Gupta 	rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
1046*5f80f270SRuchika Gupta 	if (rc)
1047*5f80f270SRuchika Gupta 		return rc;
1048*5f80f270SRuchika Gupta 
1049*5f80f270SRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
1050*5f80f270SRuchika Gupta 	if (rc)
1051*5f80f270SRuchika Gupta 		return rc;
1052*5f80f270SRuchika Gupta 
1053*5f80f270SRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
1054*5f80f270SRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
1055*5f80f270SRuchika Gupta 		goto out_free;
1056*5f80f270SRuchika Gupta 	}
1057*5f80f270SRuchika Gupta 
1058*5f80f270SRuchika Gupta 	rc = get_ready_session(session);
1059*5f80f270SRuchika Gupta 	if (rc)
1060*5f80f270SRuchika Gupta 		goto out_free;
1061*5f80f270SRuchika Gupta 
1062*5f80f270SRuchika Gupta 	wrapping_key = pkcs11_handle2object(wrapping_key_handle, session);
1063*5f80f270SRuchika Gupta 	if (!wrapping_key) {
1064*5f80f270SRuchika Gupta 		rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID;
1065*5f80f270SRuchika Gupta 		goto out_free;
1066*5f80f270SRuchika Gupta 	}
1067*5f80f270SRuchika Gupta 
1068*5f80f270SRuchika Gupta 	key = pkcs11_handle2object(key_handle, session);
1069*5f80f270SRuchika Gupta 	if (!key) {
1070*5f80f270SRuchika Gupta 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
1071*5f80f270SRuchika Gupta 		goto out_free;
1072*5f80f270SRuchika Gupta 	}
1073*5f80f270SRuchika Gupta 
1074*5f80f270SRuchika Gupta 	/*
1075*5f80f270SRuchika Gupta 	 * The wrapping key and key to be wrapped shouldn't be same.
1076*5f80f270SRuchika Gupta 	 * PKCS#11 spec doesn't explicitly state that but logically this isn't
1077*5f80f270SRuchika Gupta 	 * a use case and also acts as an attack vector, so explicitly
1078*5f80f270SRuchika Gupta 	 * disallow this.
1079*5f80f270SRuchika Gupta 	 */
1080*5f80f270SRuchika Gupta 	if (key == wrapping_key) {
1081*5f80f270SRuchika Gupta 		rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID;
1082*5f80f270SRuchika Gupta 		goto out_free;
1083*5f80f270SRuchika Gupta 	}
1084*5f80f270SRuchika Gupta 
1085*5f80f270SRuchika Gupta 	rc = set_processing_state(session, function, wrapping_key, NULL);
1086*5f80f270SRuchika Gupta 	if (rc)
1087*5f80f270SRuchika Gupta 		goto out_free;
1088*5f80f270SRuchika Gupta 
1089*5f80f270SRuchika Gupta 	/* Check if mechanism can be used for wrapping function */
1090*5f80f270SRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
1091*5f80f270SRuchika Gupta 						function,
1092*5f80f270SRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
1093*5f80f270SRuchika Gupta 	if (rc)
1094*5f80f270SRuchika Gupta 		goto out;
1095*5f80f270SRuchika Gupta 
1096*5f80f270SRuchika Gupta 	/*
1097*5f80f270SRuchika Gupta 	 * Check if wrapping key has CKA_WRAP set and its key type is
1098*5f80f270SRuchika Gupta 	 * compatible with the mechanism passed
1099*5f80f270SRuchika Gupta 	 */
1100*5f80f270SRuchika Gupta 	rc = check_parent_attrs_against_processing(proc_params->id, function,
1101*5f80f270SRuchika Gupta 						   wrapping_key->attributes);
1102*5f80f270SRuchika Gupta 	if (rc) {
1103*5f80f270SRuchika Gupta 		/*
1104*5f80f270SRuchika Gupta 		 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
1105*5f80f270SRuchika Gupta 		 * specified with C_Wrap() in the specification. So
1106*5f80f270SRuchika Gupta 		 * return the next most appropriate error.
1107*5f80f270SRuchika Gupta 		 */
1108*5f80f270SRuchika Gupta 		if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED)
1109*5f80f270SRuchika Gupta 			rc = PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
1110*5f80f270SRuchika Gupta 
1111*5f80f270SRuchika Gupta 		goto out;
1112*5f80f270SRuchika Gupta 	}
1113*5f80f270SRuchika Gupta 
1114*5f80f270SRuchika Gupta 	/* Check access of wrapping key */
1115*5f80f270SRuchika Gupta 	rc = check_access_attrs_against_token(session,
1116*5f80f270SRuchika Gupta 					      wrapping_key->attributes);
1117*5f80f270SRuchika Gupta 	if (rc)
1118*5f80f270SRuchika Gupta 		goto out;
1119*5f80f270SRuchika Gupta 
1120*5f80f270SRuchika Gupta 	switch (get_class(key->attributes)) {
1121*5f80f270SRuchika Gupta 	case PKCS11_CKO_SECRET_KEY:
1122*5f80f270SRuchika Gupta 		break;
1123*5f80f270SRuchika Gupta 	/* Key type not supported as yet */
1124*5f80f270SRuchika Gupta 	case PKCS11_CKO_PRIVATE_KEY:
1125*5f80f270SRuchika Gupta 	default:
1126*5f80f270SRuchika Gupta 		rc = PKCS11_CKR_KEY_NOT_WRAPPABLE;
1127*5f80f270SRuchika Gupta 		goto out;
1128*5f80f270SRuchika Gupta 	}
1129*5f80f270SRuchika Gupta 
1130*5f80f270SRuchika Gupta 	/* Check if key to be wrapped is extractable */
1131*5f80f270SRuchika Gupta 	if (!get_bool(key->attributes, PKCS11_CKA_EXTRACTABLE)) {
1132*5f80f270SRuchika Gupta 		DMSG("Extractable property is false");
1133*5f80f270SRuchika Gupta 		rc = PKCS11_CKR_KEY_UNEXTRACTABLE;
1134*5f80f270SRuchika Gupta 		goto out;
1135*5f80f270SRuchika Gupta 	}
1136*5f80f270SRuchika Gupta 
1137*5f80f270SRuchika Gupta 	if (get_bool(key->attributes, PKCS11_CKA_WRAP_WITH_TRUSTED) &&
1138*5f80f270SRuchika Gupta 	    !get_bool(wrapping_key->attributes, PKCS11_CKA_TRUSTED)) {
1139*5f80f270SRuchika Gupta 		DMSG("Wrap with trusted not satisfied");
1140*5f80f270SRuchika Gupta 		rc = PKCS11_CKR_KEY_NOT_WRAPPABLE;
1141*5f80f270SRuchika Gupta 		goto out;
1142*5f80f270SRuchika Gupta 	}
1143*5f80f270SRuchika Gupta 
1144*5f80f270SRuchika Gupta 	rc = check_access_attrs_against_token(session, key->attributes);
1145*5f80f270SRuchika Gupta 	if (rc)
1146*5f80f270SRuchika Gupta 		goto out;
1147*5f80f270SRuchika Gupta 
1148*5f80f270SRuchika Gupta 	rc = get_attribute_ptr(wrapping_key->attributes,
1149*5f80f270SRuchika Gupta 			       PKCS11_CKA_WRAP_TEMPLATE, &req_attrs, &size);
1150*5f80f270SRuchika Gupta 	if (rc == PKCS11_CKR_OK && size != 0) {
1151*5f80f270SRuchika Gupta 		if (!attributes_match_reference(key->attributes, req_attrs)) {
1152*5f80f270SRuchika Gupta 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
1153*5f80f270SRuchika Gupta 			goto out;
1154*5f80f270SRuchika Gupta 		}
1155*5f80f270SRuchika Gupta 	}
1156*5f80f270SRuchika Gupta 
1157*5f80f270SRuchika Gupta 	rc = get_key_data_to_wrap(key->attributes, &key_data, &key_sz);
1158*5f80f270SRuchika Gupta 	if (rc)
1159*5f80f270SRuchika Gupta 		goto out;
1160*5f80f270SRuchika Gupta 
1161*5f80f270SRuchika Gupta 	if (processing_is_tee_symm(proc_params->id)) {
1162*5f80f270SRuchika Gupta 		rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT,
1163*5f80f270SRuchika Gupta 					 proc_params, wrapping_key);
1164*5f80f270SRuchika Gupta 		if (rc)
1165*5f80f270SRuchika Gupta 			goto out;
1166*5f80f270SRuchika Gupta 
1167*5f80f270SRuchika Gupta 		session->processing->mecha_type = proc_params->id;
1168*5f80f270SRuchika Gupta 
1169*5f80f270SRuchika Gupta 		rc = wrap_data_by_symm_enc(session, key_data, key_sz, out_buf,
1170*5f80f270SRuchika Gupta 					   &out_size);
1171*5f80f270SRuchika Gupta 	} else {
1172*5f80f270SRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
1173*5f80f270SRuchika Gupta 	}
1174*5f80f270SRuchika Gupta 
1175*5f80f270SRuchika Gupta 	if (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)
1176*5f80f270SRuchika Gupta 		params[2].memref.size = out_size;
1177*5f80f270SRuchika Gupta 
1178*5f80f270SRuchika Gupta out:
1179*5f80f270SRuchika Gupta 	release_active_processing(session);
1180*5f80f270SRuchika Gupta out_free:
1181*5f80f270SRuchika Gupta 	TEE_Free(proc_params);
1182*5f80f270SRuchika Gupta 	return rc;
1183*5f80f270SRuchika Gupta }
1184