xref: /optee_os/ta/pkcs11/src/processing.c (revision 013934d8921ec762a0febb6dde6e2a9854d04a99)
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 
107512cbf1dSJens Wiklander 	if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
108512cbf1dSJens Wiklander 		TEE_FreeOperation(session->processing->tee_op_handle);
109512cbf1dSJens Wiklander 		session->processing->tee_op_handle = TEE_HANDLE_NULL;
110512cbf1dSJens Wiklander 	}
111512cbf1dSJens Wiklander 
1122158ea6cSRuchika Gupta 	TEE_Free(session->processing->extra_ctx);
1132158ea6cSRuchika Gupta 
114512cbf1dSJens Wiklander 	TEE_Free(session->processing);
115512cbf1dSJens Wiklander 	session->processing = NULL;
116512cbf1dSJens Wiklander }
117512cbf1dSJens Wiklander 
118512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj)
119512cbf1dSJens Wiklander {
120512cbf1dSJens Wiklander 	uint32_t a_size = 0;
121512cbf1dSJens Wiklander 	struct obj_attrs *attrs = obj->attributes;
122512cbf1dSJens Wiklander 
123512cbf1dSJens Wiklander 	switch (get_key_type(attrs)) {
124512cbf1dSJens Wiklander 	case PKCS11_CKK_AES:
125689f4e5bSRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
126689f4e5bSRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
127689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
128689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
129689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA256_HMAC:
130689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
131689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
132512cbf1dSJens Wiklander 		if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
133512cbf1dSJens Wiklander 			return 0;
134512cbf1dSJens Wiklander 
135512cbf1dSJens Wiklander 		return a_size * 8;
136512cbf1dSJens Wiklander 	default:
137512cbf1dSJens Wiklander 		TEE_Panic(0);
138512cbf1dSJens Wiklander 		return 0;
139512cbf1dSJens Wiklander 	}
140512cbf1dSJens Wiklander }
141512cbf1dSJens Wiklander 
142fa247a2aSRuchika Gupta static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
143fa247a2aSRuchika Gupta {
144fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
145fa247a2aSRuchika Gupta 	void *data = NULL;
146fa247a2aSRuchika Gupta 	uint32_t data_size = 0;
147fa247a2aSRuchika Gupta 	uint32_t value_len = 0;
148fa247a2aSRuchika Gupta 	void *value = NULL;
149fa247a2aSRuchika Gupta 
150fa247a2aSRuchika Gupta 	if (!*head)
151fa247a2aSRuchika Gupta 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
152fa247a2aSRuchika Gupta 
153fa247a2aSRuchika Gupta 	rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size);
154fa247a2aSRuchika Gupta 	if (rc || data_size != sizeof(uint32_t)) {
155fa247a2aSRuchika Gupta 		DMSG("%s", rc ? "No attribute value_len found" :
156fa247a2aSRuchika Gupta 		     "Invalid size for attribute VALUE_LEN");
157fa247a2aSRuchika Gupta 
158fa247a2aSRuchika Gupta 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
159fa247a2aSRuchika Gupta 	}
160fa247a2aSRuchika Gupta 	TEE_MemMove(&value_len, data, data_size);
161fa247a2aSRuchika Gupta 
162fa247a2aSRuchika Gupta 	/* Remove the default empty value attribute if found */
163fa247a2aSRuchika Gupta 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
164fa247a2aSRuchika Gupta 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
165fa247a2aSRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
166fa247a2aSRuchika Gupta 
167fa247a2aSRuchika Gupta 	value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
168fa247a2aSRuchika Gupta 	if (!value)
169fa247a2aSRuchika Gupta 		return PKCS11_CKR_DEVICE_MEMORY;
170fa247a2aSRuchika Gupta 
171fa247a2aSRuchika Gupta 	TEE_GenerateRandom(value, value_len);
172fa247a2aSRuchika Gupta 
173fa247a2aSRuchika Gupta 	rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
174fa247a2aSRuchika Gupta 
175fa247a2aSRuchika Gupta 	TEE_Free(value);
176fa247a2aSRuchika Gupta 
177fa247a2aSRuchika Gupta 	return rc;
178fa247a2aSRuchika Gupta }
179fa247a2aSRuchika Gupta 
180fa247a2aSRuchika Gupta enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
181fa247a2aSRuchika Gupta 				     uint32_t ptypes, TEE_Param *params)
182fa247a2aSRuchika Gupta {
183fa247a2aSRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
184fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE,
185fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
186fa247a2aSRuchika Gupta 						TEE_PARAM_TYPE_NONE);
187fa247a2aSRuchika Gupta 	TEE_Param *ctrl = params;
188fa247a2aSRuchika Gupta 	TEE_Param *out = params + 2;
189fa247a2aSRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
190fa247a2aSRuchika Gupta 	struct serialargs ctrlargs = { };
191fa247a2aSRuchika Gupta 	struct pkcs11_session *session = NULL;
192fa247a2aSRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
193fa247a2aSRuchika Gupta 	struct obj_attrs *head = NULL;
194fa247a2aSRuchika Gupta 	struct pkcs11_object_head *template = NULL;
195fa247a2aSRuchika Gupta 	size_t template_size = 0;
196fa247a2aSRuchika Gupta 	uint32_t obj_handle = 0;
197fa247a2aSRuchika Gupta 
198fa247a2aSRuchika Gupta 	if (!client || ptypes != exp_pt ||
199fa247a2aSRuchika Gupta 	    out->memref.size != sizeof(obj_handle))
200fa247a2aSRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
201fa247a2aSRuchika Gupta 
202fa247a2aSRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
203fa247a2aSRuchika Gupta 
204fa247a2aSRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
205fa247a2aSRuchika Gupta 	if (rc)
206fa247a2aSRuchika Gupta 		return rc;
207fa247a2aSRuchika Gupta 
208fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
209fa247a2aSRuchika Gupta 	if (rc)
210fa247a2aSRuchika Gupta 		goto out;
211fa247a2aSRuchika Gupta 
212fa247a2aSRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
213fa247a2aSRuchika Gupta 	if (rc)
214fa247a2aSRuchika Gupta 		goto out;
215fa247a2aSRuchika Gupta 
216fa247a2aSRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
217fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
218fa247a2aSRuchika Gupta 		goto out;
219fa247a2aSRuchika Gupta 	}
220fa247a2aSRuchika Gupta 
221fa247a2aSRuchika Gupta 	rc = get_ready_session(session);
222fa247a2aSRuchika Gupta 	if (rc)
223fa247a2aSRuchika Gupta 		goto out;
224fa247a2aSRuchika Gupta 
225fa247a2aSRuchika Gupta 	template_size = sizeof(*template) + template->attrs_size;
226fa247a2aSRuchika Gupta 
227fa247a2aSRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
228fa247a2aSRuchika Gupta 						PKCS11_FUNCTION_GENERATE,
229fa247a2aSRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
230fa247a2aSRuchika Gupta 	if (rc) {
231fa247a2aSRuchika Gupta 		DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
232fa247a2aSRuchika Gupta 		goto out;
233fa247a2aSRuchika Gupta 	}
234fa247a2aSRuchika Gupta 
235fa247a2aSRuchika Gupta 	/*
236fa247a2aSRuchika Gupta 	 * Prepare a clean initial state for the requested object attributes.
237fa247a2aSRuchika Gupta 	 * Free temporary template once done.
238fa247a2aSRuchika Gupta 	 */
239fa247a2aSRuchika Gupta 	rc = create_attributes_from_template(&head, template, template_size,
240fa247a2aSRuchika Gupta 					     NULL, PKCS11_FUNCTION_GENERATE,
2414cfce748SRuchika Gupta 					     proc_params->id,
2424cfce748SRuchika Gupta 					     PKCS11_CKO_UNDEFINED_ID);
243fa247a2aSRuchika Gupta 	if (rc)
244fa247a2aSRuchika Gupta 		goto out;
245fa247a2aSRuchika Gupta 
246fa247a2aSRuchika Gupta 	TEE_Free(template);
247fa247a2aSRuchika Gupta 	template = NULL;
248fa247a2aSRuchika Gupta 
249fa247a2aSRuchika Gupta 	rc = check_created_attrs(head, NULL);
250fa247a2aSRuchika Gupta 	if (rc)
251fa247a2aSRuchika Gupta 		goto out;
252fa247a2aSRuchika Gupta 
253fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_processing(proc_params->id, head);
254fa247a2aSRuchika Gupta 	if (rc)
255fa247a2aSRuchika Gupta 		goto out;
256fa247a2aSRuchika Gupta 
257fa247a2aSRuchika Gupta 	rc = check_created_attrs_against_token(session, head);
258fa247a2aSRuchika Gupta 	if (rc)
259fa247a2aSRuchika Gupta 		goto out;
260fa247a2aSRuchika Gupta 
261fa247a2aSRuchika Gupta 	/*
262fa247a2aSRuchika Gupta 	 * Execute target processing and add value as attribute
263fa247a2aSRuchika Gupta 	 * PKCS11_CKA_VALUE. Symm key generation: depends on target
264fa247a2aSRuchika Gupta 	 * processing to be used.
265fa247a2aSRuchika Gupta 	 */
266fa247a2aSRuchika Gupta 	switch (proc_params->id) {
267fa247a2aSRuchika Gupta 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
268fa247a2aSRuchika Gupta 	case PKCS11_CKM_AES_KEY_GEN:
269fa247a2aSRuchika Gupta 		/* Generate random of size specified by attribute VALUE_LEN */
270fa247a2aSRuchika Gupta 		rc = generate_random_key_value(&head);
271fa247a2aSRuchika Gupta 		if (rc)
272fa247a2aSRuchika Gupta 			goto out;
273fa247a2aSRuchika Gupta 		break;
274fa247a2aSRuchika Gupta 
275fa247a2aSRuchika Gupta 	default:
276fa247a2aSRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
277fa247a2aSRuchika Gupta 		goto out;
278fa247a2aSRuchika Gupta 	}
279fa247a2aSRuchika Gupta 
280fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
281fa247a2aSRuchika Gupta 	proc_params = NULL;
282fa247a2aSRuchika Gupta 
283fa247a2aSRuchika Gupta 	/*
284fa247a2aSRuchika Gupta 	 * Object is ready, register it and return a handle.
285fa247a2aSRuchika Gupta 	 */
286fa247a2aSRuchika Gupta 	rc = create_object(session, head, &obj_handle);
287fa247a2aSRuchika Gupta 	if (rc)
288fa247a2aSRuchika Gupta 		goto out;
289fa247a2aSRuchika Gupta 
290fa247a2aSRuchika Gupta 	/*
291fa247a2aSRuchika Gupta 	 * Now obj_handle (through the related struct pkcs11_object instance)
292fa247a2aSRuchika Gupta 	 * owns the serialized buffer that holds the object attributes.
293fa247a2aSRuchika Gupta 	 * We reset head to NULL as it is no more the buffer owner and would
294fa247a2aSRuchika Gupta 	 * be freed at function out.
295fa247a2aSRuchika Gupta 	 */
296fa247a2aSRuchika Gupta 	head = NULL;
297fa247a2aSRuchika Gupta 
298fa247a2aSRuchika Gupta 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
299fa247a2aSRuchika Gupta 	out->memref.size = sizeof(obj_handle);
300fa247a2aSRuchika Gupta 
301fa247a2aSRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
302fa247a2aSRuchika Gupta 	     session->handle, obj_handle);
303fa247a2aSRuchika Gupta 
304fa247a2aSRuchika Gupta out:
305fa247a2aSRuchika Gupta 	TEE_Free(proc_params);
306fa247a2aSRuchika Gupta 	TEE_Free(template);
307fa247a2aSRuchika Gupta 	TEE_Free(head);
308fa247a2aSRuchika Gupta 
309fa247a2aSRuchika Gupta 	return rc;
310fa247a2aSRuchika Gupta }
311fa247a2aSRuchika Gupta 
312*013934d8SVesa Jääskeläinen enum pkcs11_rc alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj,
313*013934d8SVesa Jääskeläinen 					    uint32_t attribute,
314*013934d8SVesa Jääskeläinen 					    void **data, size_t *size)
315*013934d8SVesa Jääskeläinen {
316*013934d8SVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
317*013934d8SVesa Jääskeläinen 	void *ptr = NULL;
318*013934d8SVesa Jääskeläinen 	uint32_t sz = 0;
319*013934d8SVesa Jääskeläinen 
320*013934d8SVesa Jääskeläinen 	res = TEE_GetObjectBufferAttribute(tee_obj, attribute, NULL, &sz);
321*013934d8SVesa Jääskeläinen 	if (res != TEE_ERROR_SHORT_BUFFER)
322*013934d8SVesa Jääskeläinen 		return PKCS11_CKR_FUNCTION_FAILED;
323*013934d8SVesa Jääskeläinen 
324*013934d8SVesa Jääskeläinen 	ptr = TEE_Malloc(sz, TEE_USER_MEM_HINT_NO_FILL_ZERO);
325*013934d8SVesa Jääskeläinen 	if (!ptr)
326*013934d8SVesa Jääskeläinen 		return PKCS11_CKR_DEVICE_MEMORY;
327*013934d8SVesa Jääskeläinen 
328*013934d8SVesa Jääskeläinen 	res = TEE_GetObjectBufferAttribute(tee_obj, attribute, ptr, &sz);
329*013934d8SVesa Jääskeläinen 	if (res) {
330*013934d8SVesa Jääskeläinen 		TEE_Free(ptr);
331*013934d8SVesa Jääskeläinen 	} else {
332*013934d8SVesa Jääskeläinen 		*data = ptr;
333*013934d8SVesa Jääskeläinen 		*size = sz;
334*013934d8SVesa Jääskeläinen 	}
335*013934d8SVesa Jääskeläinen 
336*013934d8SVesa Jääskeläinen 	return tee2pkcs_error(res);
337*013934d8SVesa Jääskeläinen }
338*013934d8SVesa Jääskeläinen 
339*013934d8SVesa Jääskeläinen enum pkcs11_rc tee2pkcs_add_attribute(struct obj_attrs **head,
340*013934d8SVesa Jääskeläinen 				      uint32_t pkcs11_id,
341*013934d8SVesa Jääskeläinen 				      TEE_ObjectHandle tee_obj,
342*013934d8SVesa Jääskeläinen 				      uint32_t tee_id)
343*013934d8SVesa Jääskeläinen {
344*013934d8SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
345*013934d8SVesa Jääskeläinen 	void *a_ptr = NULL;
346*013934d8SVesa Jääskeläinen 	size_t a_size = 0;
347*013934d8SVesa Jääskeläinen 
348*013934d8SVesa Jääskeläinen 	rc = alloc_get_tee_attribute_data(tee_obj, tee_id, &a_ptr, &a_size);
349*013934d8SVesa Jääskeläinen 	if (rc)
350*013934d8SVesa Jääskeläinen 		goto out;
351*013934d8SVesa Jääskeläinen 
352*013934d8SVesa Jääskeläinen 	rc = add_attribute(head, pkcs11_id, a_ptr, a_size);
353*013934d8SVesa Jääskeläinen 
354*013934d8SVesa Jääskeläinen 	TEE_Free(a_ptr);
355*013934d8SVesa Jääskeläinen 
356*013934d8SVesa Jääskeläinen out:
357*013934d8SVesa Jääskeläinen 	if (rc)
358*013934d8SVesa Jääskeläinen 		EMSG("Failed TEE attribute %#"PRIx32" for %#"PRIx32"/%s",
359*013934d8SVesa Jääskeläinen 		     tee_id, pkcs11_id, id2str_attr(pkcs11_id));
360*013934d8SVesa Jääskeläinen 	return rc;
361*013934d8SVesa Jääskeläinen }
362*013934d8SVesa Jääskeläinen 
363*013934d8SVesa Jääskeläinen enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client,
364*013934d8SVesa Jääskeläinen 				       uint32_t ptypes, TEE_Param *params)
365*013934d8SVesa Jääskeläinen {
366*013934d8SVesa Jääskeläinen 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
367*013934d8SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE,
368*013934d8SVesa Jääskeläinen 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
369*013934d8SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE);
370*013934d8SVesa Jääskeläinen 	TEE_Param *ctrl = params;
371*013934d8SVesa Jääskeläinen 	TEE_Param *out = params + 2;
372*013934d8SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
373*013934d8SVesa Jääskeläinen 	struct serialargs ctrlargs = { };
374*013934d8SVesa Jääskeläinen 	struct pkcs11_session *session = NULL;
375*013934d8SVesa Jääskeläinen 	struct pkcs11_attribute_head *proc_params = NULL;
376*013934d8SVesa Jääskeläinen 	struct obj_attrs *pub_head = NULL;
377*013934d8SVesa Jääskeläinen 	struct obj_attrs *priv_head = NULL;
378*013934d8SVesa Jääskeläinen 	struct pkcs11_object_head *pub_template = NULL;
379*013934d8SVesa Jääskeläinen 	struct pkcs11_object_head *priv_template = NULL;
380*013934d8SVesa Jääskeläinen 	struct pkcs11_object *object = NULL;
381*013934d8SVesa Jääskeläinen 	size_t pub_template_size = 0;
382*013934d8SVesa Jääskeläinen 	size_t priv_template_size = 0;
383*013934d8SVesa Jääskeläinen 	uint32_t pubkey_handle = 0;
384*013934d8SVesa Jääskeläinen 	uint32_t privkey_handle = 0;
385*013934d8SVesa Jääskeläinen 	uint32_t *hdl_ptr = NULL;
386*013934d8SVesa Jääskeläinen 	size_t out_ref_size = sizeof(pubkey_handle) + sizeof(privkey_handle);
387*013934d8SVesa Jääskeläinen 
388*013934d8SVesa Jääskeläinen 	if (!client || ptypes != exp_pt || out->memref.size != out_ref_size)
389*013934d8SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
390*013934d8SVesa Jääskeläinen 
391*013934d8SVesa Jääskeläinen 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
392*013934d8SVesa Jääskeläinen 
393*013934d8SVesa Jääskeläinen 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
394*013934d8SVesa Jääskeläinen 	if (rc)
395*013934d8SVesa Jääskeläinen 		return rc;
396*013934d8SVesa Jääskeläinen 
397*013934d8SVesa Jääskeläinen 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
398*013934d8SVesa Jääskeläinen 	if (rc)
399*013934d8SVesa Jääskeläinen 		goto out;
400*013934d8SVesa Jääskeläinen 
401*013934d8SVesa Jääskeläinen 	rc = serialargs_alloc_get_attributes(&ctrlargs, &pub_template);
402*013934d8SVesa Jääskeläinen 	if (rc)
403*013934d8SVesa Jääskeläinen 		goto out;
404*013934d8SVesa Jääskeläinen 
405*013934d8SVesa Jääskeläinen 	rc = serialargs_alloc_get_attributes(&ctrlargs, &priv_template);
406*013934d8SVesa Jääskeläinen 	if (rc)
407*013934d8SVesa Jääskeläinen 		goto out;
408*013934d8SVesa Jääskeläinen 
409*013934d8SVesa Jääskeläinen 	if (serialargs_remaining_bytes(&ctrlargs)) {
410*013934d8SVesa Jääskeläinen 		rc = PKCS11_CKR_ARGUMENTS_BAD;
411*013934d8SVesa Jääskeläinen 		goto out;
412*013934d8SVesa Jääskeläinen 	}
413*013934d8SVesa Jääskeläinen 
414*013934d8SVesa Jääskeläinen 	rc = get_ready_session(session);
415*013934d8SVesa Jääskeläinen 	if (rc)
416*013934d8SVesa Jääskeläinen 		goto out;
417*013934d8SVesa Jääskeläinen 
418*013934d8SVesa Jääskeläinen 	rc = check_mechanism_against_processing(session, proc_params->id,
419*013934d8SVesa Jääskeläinen 						PKCS11_FUNCTION_GENERATE_PAIR,
420*013934d8SVesa Jääskeläinen 						PKCS11_FUNC_STEP_INIT);
421*013934d8SVesa Jääskeläinen 	if (rc)
422*013934d8SVesa Jääskeläinen 		goto out;
423*013934d8SVesa Jääskeläinen 
424*013934d8SVesa Jääskeläinen 	pub_template_size = sizeof(*pub_template) + pub_template->attrs_size;
425*013934d8SVesa Jääskeläinen 
426*013934d8SVesa Jääskeläinen 	rc = create_attributes_from_template(&pub_head, pub_template,
427*013934d8SVesa Jääskeläinen 					     pub_template_size, NULL,
428*013934d8SVesa Jääskeläinen 					     PKCS11_FUNCTION_GENERATE_PAIR,
429*013934d8SVesa Jääskeläinen 					     proc_params->id,
430*013934d8SVesa Jääskeläinen 					     PKCS11_CKO_PUBLIC_KEY);
431*013934d8SVesa Jääskeläinen 	if (rc)
432*013934d8SVesa Jääskeläinen 		goto out;
433*013934d8SVesa Jääskeläinen 
434*013934d8SVesa Jääskeläinen 	TEE_Free(pub_template);
435*013934d8SVesa Jääskeläinen 	pub_template = NULL;
436*013934d8SVesa Jääskeläinen 
437*013934d8SVesa Jääskeläinen 	priv_template_size = sizeof(*priv_template) +
438*013934d8SVesa Jääskeläinen 			     priv_template->attrs_size;
439*013934d8SVesa Jääskeläinen 
440*013934d8SVesa Jääskeläinen 	rc = create_attributes_from_template(&priv_head, priv_template,
441*013934d8SVesa Jääskeläinen 					     priv_template_size, NULL,
442*013934d8SVesa Jääskeläinen 					     PKCS11_FUNCTION_GENERATE_PAIR,
443*013934d8SVesa Jääskeläinen 					     proc_params->id,
444*013934d8SVesa Jääskeläinen 					     PKCS11_CKO_PRIVATE_KEY);
445*013934d8SVesa Jääskeläinen 	if (rc)
446*013934d8SVesa Jääskeläinen 		goto out;
447*013934d8SVesa Jääskeläinen 
448*013934d8SVesa Jääskeläinen 	TEE_Free(priv_template);
449*013934d8SVesa Jääskeläinen 	priv_template = NULL;
450*013934d8SVesa Jääskeläinen 
451*013934d8SVesa Jääskeläinen 	/* Generate CKA_ID for keys if not specified by the templates */
452*013934d8SVesa Jääskeläinen 	rc = add_missing_attribute_id(&pub_head, &priv_head);
453*013934d8SVesa Jääskeläinen 	if (rc)
454*013934d8SVesa Jääskeläinen 		goto out;
455*013934d8SVesa Jääskeläinen 
456*013934d8SVesa Jääskeläinen 	/* Check created object against processing and token state */
457*013934d8SVesa Jääskeläinen 	rc = check_created_attrs(pub_head, priv_head);
458*013934d8SVesa Jääskeläinen 	if (rc)
459*013934d8SVesa Jääskeläinen 		goto out;
460*013934d8SVesa Jääskeläinen 
461*013934d8SVesa Jääskeläinen 	rc = check_created_attrs_against_processing(proc_params->id, pub_head);
462*013934d8SVesa Jääskeläinen 	if (rc)
463*013934d8SVesa Jääskeläinen 		goto out;
464*013934d8SVesa Jääskeläinen 
465*013934d8SVesa Jääskeläinen 	rc = check_created_attrs_against_processing(proc_params->id,
466*013934d8SVesa Jääskeläinen 						    priv_head);
467*013934d8SVesa Jääskeläinen 	if (rc)
468*013934d8SVesa Jääskeläinen 		goto out;
469*013934d8SVesa Jääskeläinen 
470*013934d8SVesa Jääskeläinen 	rc = check_created_attrs_against_token(session, pub_head);
471*013934d8SVesa Jääskeläinen 	if (rc)
472*013934d8SVesa Jääskeläinen 		goto out;
473*013934d8SVesa Jääskeläinen 
474*013934d8SVesa Jääskeläinen 	rc = check_access_attrs_against_token(session, pub_head);
475*013934d8SVesa Jääskeläinen 	if (rc)
476*013934d8SVesa Jääskeläinen 		goto out;
477*013934d8SVesa Jääskeläinen 
478*013934d8SVesa Jääskeläinen 	rc = check_created_attrs_against_token(session, priv_head);
479*013934d8SVesa Jääskeläinen 	if (rc)
480*013934d8SVesa Jääskeläinen 		goto out;
481*013934d8SVesa Jääskeläinen 
482*013934d8SVesa Jääskeläinen 	rc = check_access_attrs_against_token(session, priv_head);
483*013934d8SVesa Jääskeläinen 	if (rc)
484*013934d8SVesa Jääskeläinen 		goto out;
485*013934d8SVesa Jääskeläinen 
486*013934d8SVesa Jääskeläinen 	/* Generate key pair */
487*013934d8SVesa Jääskeläinen 	switch (proc_params->id) {
488*013934d8SVesa Jääskeläinen 	default:
489*013934d8SVesa Jääskeläinen 		rc = PKCS11_CKR_MECHANISM_INVALID;
490*013934d8SVesa Jääskeläinen 		break;
491*013934d8SVesa Jääskeläinen 	}
492*013934d8SVesa Jääskeläinen 	if (rc)
493*013934d8SVesa Jääskeläinen 		goto out;
494*013934d8SVesa Jääskeläinen 
495*013934d8SVesa Jääskeläinen 	TEE_Free(proc_params);
496*013934d8SVesa Jääskeläinen 	proc_params = NULL;
497*013934d8SVesa Jääskeläinen 
498*013934d8SVesa Jääskeläinen 	/*
499*013934d8SVesa Jääskeläinen 	 * Object is ready, register it and return a handle.
500*013934d8SVesa Jääskeläinen 	 */
501*013934d8SVesa Jääskeläinen 	rc = create_object(session, pub_head, &pubkey_handle);
502*013934d8SVesa Jääskeläinen 	if (rc)
503*013934d8SVesa Jääskeläinen 		goto out;
504*013934d8SVesa Jääskeläinen 
505*013934d8SVesa Jääskeläinen 	/*
506*013934d8SVesa Jääskeläinen 	 * Now obj_handle (through the related struct pkcs11_object instance)
507*013934d8SVesa Jääskeläinen 	 * owns the serialized buffer that holds the object attributes.
508*013934d8SVesa Jääskeläinen 	 * We reset local pub_head to NULL to mark that ownership has been
509*013934d8SVesa Jääskeläinen 	 * transferred.
510*013934d8SVesa Jääskeläinen 	 */
511*013934d8SVesa Jääskeläinen 	pub_head = NULL;
512*013934d8SVesa Jääskeläinen 
513*013934d8SVesa Jääskeläinen 	rc = create_object(session, priv_head, &privkey_handle);
514*013934d8SVesa Jääskeläinen 	if (rc)
515*013934d8SVesa Jääskeläinen 		goto out;
516*013934d8SVesa Jääskeläinen 
517*013934d8SVesa Jääskeläinen 	/* Ownership has been transferred so mark it with NULL */
518*013934d8SVesa Jääskeläinen 	priv_head = NULL;
519*013934d8SVesa Jääskeläinen 
520*013934d8SVesa Jääskeläinen 	hdl_ptr = (uint32_t *)out->memref.buffer;
521*013934d8SVesa Jääskeläinen 
522*013934d8SVesa Jääskeläinen 	TEE_MemMove(hdl_ptr, &pubkey_handle, sizeof(pubkey_handle));
523*013934d8SVesa Jääskeläinen 	TEE_MemMove(hdl_ptr + 1, &privkey_handle, sizeof(privkey_handle));
524*013934d8SVesa Jääskeläinen 
525*013934d8SVesa Jääskeläinen 	pubkey_handle = 0;
526*013934d8SVesa Jääskeläinen 	privkey_handle = 0;
527*013934d8SVesa Jääskeläinen 
528*013934d8SVesa Jääskeläinen 	DMSG("PKCS11 session %"PRIu32": create key pair %#"PRIx32"/%#"PRIx32,
529*013934d8SVesa Jääskeläinen 	     session->handle, privkey_handle, pubkey_handle);
530*013934d8SVesa Jääskeläinen 
531*013934d8SVesa Jääskeläinen out:
532*013934d8SVesa Jääskeläinen 	if (pubkey_handle) {
533*013934d8SVesa Jääskeläinen 		object = pkcs11_handle2object(pubkey_handle, session);
534*013934d8SVesa Jääskeläinen 		if (!object)
535*013934d8SVesa Jääskeläinen 			TEE_Panic(0);
536*013934d8SVesa Jääskeläinen 		destroy_object(session, object, false);
537*013934d8SVesa Jääskeläinen 	}
538*013934d8SVesa Jääskeläinen 	TEE_Free(priv_head);
539*013934d8SVesa Jääskeläinen 	TEE_Free(pub_head);
540*013934d8SVesa Jääskeläinen 	TEE_Free(priv_template);
541*013934d8SVesa Jääskeläinen 	TEE_Free(pub_template);
542*013934d8SVesa Jääskeläinen 	TEE_Free(proc_params);
543*013934d8SVesa Jääskeläinen 
544*013934d8SVesa Jääskeläinen 	return rc;
545*013934d8SVesa Jääskeläinen }
546*013934d8SVesa Jääskeläinen 
547512cbf1dSJens Wiklander /*
548512cbf1dSJens Wiklander  * entry_processing_init - Generic entry for initializing a processing
549512cbf1dSJens Wiklander  *
550512cbf1dSJens Wiklander  * @client = client reference
551512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
552512cbf1dSJens Wiklander  * @params = Invocation parameters reference
553512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
554512cbf1dSJens Wiklander  */
555512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
556512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
557512cbf1dSJens Wiklander 				     enum processing_func function)
558512cbf1dSJens Wiklander {
559512cbf1dSJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
560512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
561512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
562512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE);
563512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
564512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
565512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
566512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
567512cbf1dSJens Wiklander 	struct pkcs11_attribute_head *proc_params = NULL;
568512cbf1dSJens Wiklander 	uint32_t key_handle = 0;
569512cbf1dSJens Wiklander 	struct pkcs11_object *obj = NULL;
570512cbf1dSJens Wiklander 
571512cbf1dSJens Wiklander 	if (!client || ptypes != exp_pt)
572512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
573512cbf1dSJens Wiklander 
574512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
575512cbf1dSJens Wiklander 
576512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
577512cbf1dSJens Wiklander 	if (rc)
578512cbf1dSJens Wiklander 		return rc;
579512cbf1dSJens Wiklander 
5809e91a619SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_DIGEST) {
581512cbf1dSJens Wiklander 		rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
582512cbf1dSJens Wiklander 		if (rc)
583512cbf1dSJens Wiklander 			return rc;
5849e91a619SVesa Jääskeläinen 	}
585512cbf1dSJens Wiklander 
586512cbf1dSJens Wiklander 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
587512cbf1dSJens Wiklander 	if (rc)
588512cbf1dSJens Wiklander 		return rc;
589512cbf1dSJens Wiklander 
590512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs)) {
591512cbf1dSJens Wiklander 		rc = PKCS11_CKR_ARGUMENTS_BAD;
592512cbf1dSJens Wiklander 		goto out;
593512cbf1dSJens Wiklander 	}
594512cbf1dSJens Wiklander 
595512cbf1dSJens Wiklander 	rc = get_ready_session(session);
596512cbf1dSJens Wiklander 	if (rc)
597512cbf1dSJens Wiklander 		goto out;
598512cbf1dSJens Wiklander 
5999e91a619SVesa Jääskeläinen 	if (function != PKCS11_FUNCTION_DIGEST) {
600512cbf1dSJens Wiklander 		obj = pkcs11_handle2object(key_handle, session);
601512cbf1dSJens Wiklander 		if (!obj) {
602512cbf1dSJens Wiklander 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
603512cbf1dSJens Wiklander 			goto out;
604512cbf1dSJens Wiklander 		}
6059e91a619SVesa Jääskeläinen 	}
606512cbf1dSJens Wiklander 
607512cbf1dSJens Wiklander 	rc = set_processing_state(session, function, obj, NULL);
608512cbf1dSJens Wiklander 	if (rc)
609512cbf1dSJens Wiklander 		goto out;
610512cbf1dSJens Wiklander 
611512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, proc_params->id,
612512cbf1dSJens Wiklander 						function,
613512cbf1dSJens Wiklander 						PKCS11_FUNC_STEP_INIT);
614512cbf1dSJens Wiklander 	if (rc)
615512cbf1dSJens Wiklander 		goto out;
616512cbf1dSJens Wiklander 
6179e91a619SVesa Jääskeläinen 	if (obj) {
6189e91a619SVesa Jääskeläinen 		rc = check_parent_attrs_against_processing(proc_params->id,
6199e91a619SVesa Jääskeläinen 							   function,
620512cbf1dSJens Wiklander 							   obj->attributes);
621512cbf1dSJens Wiklander 		if (rc)
622512cbf1dSJens Wiklander 			goto out;
623512cbf1dSJens Wiklander 
6249e91a619SVesa Jääskeläinen 		rc = check_access_attrs_against_token(session,
6259e91a619SVesa Jääskeläinen 						      obj->attributes);
626512cbf1dSJens Wiklander 		if (rc)
627512cbf1dSJens Wiklander 			goto out;
6289e91a619SVesa Jääskeläinen 	}
629512cbf1dSJens Wiklander 
630512cbf1dSJens Wiklander 	if (processing_is_tee_symm(proc_params->id))
631512cbf1dSJens Wiklander 		rc = init_symm_operation(session, function, proc_params, obj);
6329e91a619SVesa Jääskeläinen 	else if (processing_is_tee_digest(proc_params->id))
6339e91a619SVesa Jääskeläinen 		rc = init_digest_operation(session, proc_params);
634512cbf1dSJens Wiklander 	else
635512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
636512cbf1dSJens Wiklander 
637512cbf1dSJens Wiklander 	if (rc == PKCS11_CKR_OK) {
638512cbf1dSJens Wiklander 		session->processing->mecha_type = proc_params->id;
639512cbf1dSJens Wiklander 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
640512cbf1dSJens Wiklander 		     session->handle, id2str_proc(proc_params->id),
641512cbf1dSJens Wiklander 		     id2str_function(function));
642512cbf1dSJens Wiklander 	}
643512cbf1dSJens Wiklander 
644512cbf1dSJens Wiklander out:
645512cbf1dSJens Wiklander 	if (rc && session)
646512cbf1dSJens Wiklander 		release_active_processing(session);
647512cbf1dSJens Wiklander 
648512cbf1dSJens Wiklander 	TEE_Free(proc_params);
649512cbf1dSJens Wiklander 
650512cbf1dSJens Wiklander 	return rc;
651512cbf1dSJens Wiklander }
652512cbf1dSJens Wiklander 
653512cbf1dSJens Wiklander /*
654512cbf1dSJens Wiklander  * entry_processing_step - Generic entry on active processing
655512cbf1dSJens Wiklander  *
656512cbf1dSJens Wiklander  * @client = client reference
657512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
658512cbf1dSJens Wiklander  * @params = Invocation parameters reference
659512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
660512cbf1dSJens Wiklander  * @step - update, oneshot, final
661512cbf1dSJens Wiklander  */
662512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
663512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
664512cbf1dSJens Wiklander 				     enum processing_func function,
665512cbf1dSJens Wiklander 				     enum processing_step step)
666512cbf1dSJens Wiklander {
667512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
668512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
669512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
670512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
671512cbf1dSJens Wiklander 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
6729e91a619SVesa Jääskeläinen 	uint32_t key_handle = 0;
6739e91a619SVesa Jääskeläinen 	struct pkcs11_object *obj = NULL;
674512cbf1dSJens Wiklander 
675512cbf1dSJens Wiklander 	if (!client ||
676512cbf1dSJens Wiklander 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
677512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
678512cbf1dSJens Wiklander 
679512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
680512cbf1dSJens Wiklander 
681512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
682512cbf1dSJens Wiklander 	if (rc)
683512cbf1dSJens Wiklander 		return rc;
684512cbf1dSJens Wiklander 
6859e91a619SVesa Jääskeläinen 	if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
6869e91a619SVesa Jääskeläinen 		assert(function == PKCS11_FUNCTION_DIGEST);
6879e91a619SVesa Jääskeläinen 
6889e91a619SVesa Jääskeläinen 		rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
6899e91a619SVesa Jääskeläinen 		if (rc)
6909e91a619SVesa Jääskeläinen 			return rc;
6919e91a619SVesa Jääskeläinen 	}
6929e91a619SVesa Jääskeläinen 
693512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs))
694512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
695512cbf1dSJens Wiklander 
696512cbf1dSJens Wiklander 	rc = get_active_session(session, function);
697512cbf1dSJens Wiklander 	if (rc)
698512cbf1dSJens Wiklander 		return rc;
699512cbf1dSJens Wiklander 
7009e91a619SVesa Jääskeläinen 	if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
7019e91a619SVesa Jääskeläinen 		assert(function == PKCS11_FUNCTION_DIGEST);
7029e91a619SVesa Jääskeläinen 
7039e91a619SVesa Jääskeläinen 		obj = pkcs11_handle2object(key_handle, session);
7049e91a619SVesa Jääskeläinen 		if (!obj) {
7059e91a619SVesa Jääskeläinen 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
7069e91a619SVesa Jääskeläinen 			goto out;
7079e91a619SVesa Jääskeläinen 		}
7089e91a619SVesa Jääskeläinen 
7099e91a619SVesa Jääskeläinen 		rc = check_access_attrs_against_token(session,
7109e91a619SVesa Jääskeläinen 						      obj->attributes);
7119e91a619SVesa Jääskeläinen 		if (rc) {
7129e91a619SVesa Jääskeläinen 			rc = PKCS11_CKR_KEY_HANDLE_INVALID;
7139e91a619SVesa Jääskeläinen 			goto out;
7149e91a619SVesa Jääskeläinen 		}
7159e91a619SVesa Jääskeläinen 	}
7169e91a619SVesa Jääskeläinen 
717512cbf1dSJens Wiklander 	mecha_type = session->processing->mecha_type;
718512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, mecha_type,
719512cbf1dSJens Wiklander 						function, step);
720512cbf1dSJens Wiklander 	if (rc)
721512cbf1dSJens Wiklander 		goto out;
722512cbf1dSJens Wiklander 
723512cbf1dSJens Wiklander 	if (processing_is_tee_symm(mecha_type))
724512cbf1dSJens Wiklander 		rc = step_symm_operation(session, function, step,
725512cbf1dSJens Wiklander 					 ptypes, params);
7269e91a619SVesa Jääskeläinen 	else if (processing_is_tee_digest(mecha_type))
7279e91a619SVesa Jääskeläinen 		rc = step_digest_operation(session, step, obj, ptypes, params);
728512cbf1dSJens Wiklander 	else
729512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
730512cbf1dSJens Wiklander 
7319e91a619SVesa Jääskeläinen 	if (rc == PKCS11_CKR_OK && (step == PKCS11_FUNC_STEP_UPDATE ||
7329e91a619SVesa Jääskeläinen 				    step == PKCS11_FUNC_STEP_UPDATE_KEY)) {
733512cbf1dSJens Wiklander 		session->processing->updated = true;
734512cbf1dSJens Wiklander 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
735512cbf1dSJens Wiklander 		     session->handle, id2str_proc(mecha_type),
736512cbf1dSJens Wiklander 		     id2str_function(function));
737512cbf1dSJens Wiklander 	}
738512cbf1dSJens Wiklander 
739512cbf1dSJens Wiklander out:
740512cbf1dSJens Wiklander 	switch (step) {
741512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_UPDATE:
7429e91a619SVesa Jääskeläinen 	case PKCS11_FUNC_STEP_UPDATE_KEY:
743512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
744512cbf1dSJens Wiklander 			release_active_processing(session);
745512cbf1dSJens Wiklander 		break;
746512cbf1dSJens Wiklander 	default:
747512cbf1dSJens Wiklander 		/* ONESHOT and FINAL terminates processing on success */
748512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
749512cbf1dSJens Wiklander 			release_active_processing(session);
750512cbf1dSJens Wiklander 		break;
751512cbf1dSJens Wiklander 	}
752512cbf1dSJens Wiklander 
753512cbf1dSJens Wiklander 	return rc;
754512cbf1dSJens Wiklander }
75548799892SRuchika Gupta 
7564dad6642SRuchika Gupta enum pkcs11_rc entry_processing_key(struct pkcs11_client *client,
7574dad6642SRuchika Gupta 				    uint32_t ptypes, TEE_Param *params,
7584dad6642SRuchika Gupta 				    enum processing_func function)
75948799892SRuchika Gupta {
76048799892SRuchika Gupta 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
76148799892SRuchika Gupta 						TEE_PARAM_TYPE_NONE,
76248799892SRuchika Gupta 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
76348799892SRuchika Gupta 						TEE_PARAM_TYPE_NONE);
76448799892SRuchika Gupta 	TEE_Param *ctrl = params;
76548799892SRuchika Gupta 	TEE_Param *out = params + 2;
76648799892SRuchika Gupta 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
76748799892SRuchika Gupta 	struct serialargs ctrlargs = { };
76848799892SRuchika Gupta 	struct pkcs11_session *session = NULL;
76948799892SRuchika Gupta 	struct pkcs11_attribute_head *proc_params = NULL;
77048799892SRuchika Gupta 	struct pkcs11_object_head *template = NULL;
77148799892SRuchika Gupta 	uint32_t parent_handle = 0;
77248799892SRuchika Gupta 	uint32_t obj_handle = 0;
77348799892SRuchika Gupta 	struct pkcs11_object *parent = NULL;
77448799892SRuchika Gupta 	struct obj_attrs *head = NULL;
77548799892SRuchika Gupta 	size_t template_size = 0;
7768c499324SRuchika Gupta 	void *out_buf = NULL;
7778c499324SRuchika Gupta 	uint32_t out_size = 0;
77848799892SRuchika Gupta 
77948799892SRuchika Gupta 	if (!client || ptypes != exp_pt ||
78048799892SRuchika Gupta 	    out->memref.size != sizeof(obj_handle))
78148799892SRuchika Gupta 		return PKCS11_CKR_ARGUMENTS_BAD;
78248799892SRuchika Gupta 
78348799892SRuchika Gupta 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
78448799892SRuchika Gupta 
78548799892SRuchika Gupta 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
78648799892SRuchika Gupta 	if (rc)
78748799892SRuchika Gupta 		return rc;
78848799892SRuchika Gupta 
78948799892SRuchika Gupta 	rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t));
79048799892SRuchika Gupta 	if (rc)
79148799892SRuchika Gupta 		return rc;
79248799892SRuchika Gupta 
79348799892SRuchika Gupta 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
79448799892SRuchika Gupta 	if (rc)
79548799892SRuchika Gupta 		goto out_free;
79648799892SRuchika Gupta 
79748799892SRuchika Gupta 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
79848799892SRuchika Gupta 	if (rc)
79948799892SRuchika Gupta 		goto out_free;
80048799892SRuchika Gupta 
80148799892SRuchika Gupta 	if (serialargs_remaining_bytes(&ctrlargs)) {
80248799892SRuchika Gupta 		rc = PKCS11_CKR_ARGUMENTS_BAD;
80348799892SRuchika Gupta 		goto out_free;
80448799892SRuchika Gupta 	}
80548799892SRuchika Gupta 
80648799892SRuchika Gupta 	/* Return error if processing already active */
80748799892SRuchika Gupta 	rc = get_ready_session(session);
80848799892SRuchika Gupta 	if (rc)
80948799892SRuchika Gupta 		goto out_free;
81048799892SRuchika Gupta 
81148799892SRuchika Gupta 	/* Check parent handle */
81248799892SRuchika Gupta 	parent = pkcs11_handle2object(parent_handle, session);
81348799892SRuchika Gupta 	if (!parent) {
81448799892SRuchika Gupta 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
81548799892SRuchika Gupta 		goto out_free;
81648799892SRuchika Gupta 	}
81748799892SRuchika Gupta 
81848799892SRuchika Gupta 	/* Check if mechanism can be used for derivation function */
81948799892SRuchika Gupta 	rc = check_mechanism_against_processing(session, proc_params->id,
82048799892SRuchika Gupta 						function,
82148799892SRuchika Gupta 						PKCS11_FUNC_STEP_INIT);
82248799892SRuchika Gupta 	if (rc)
82348799892SRuchika Gupta 		goto out_free;
82448799892SRuchika Gupta 
82548799892SRuchika Gupta 	/* Set the processing state to active */
82648799892SRuchika Gupta 	rc = set_processing_state(session, function, parent, NULL);
82748799892SRuchika Gupta 	if (rc)
82848799892SRuchika Gupta 		goto out_free;
82948799892SRuchika Gupta 
83048799892SRuchika Gupta 	/*
83148799892SRuchika Gupta 	 * Check if base/parent key has CKA_DERIVE set and its key type is
83248799892SRuchika Gupta 	 * compatible with the mechanism passed
83348799892SRuchika Gupta 	 */
83448799892SRuchika Gupta 	rc = check_parent_attrs_against_processing(proc_params->id, function,
83548799892SRuchika Gupta 						   parent->attributes);
836d05ab5feSRuchika Gupta 	if (rc) {
837d05ab5feSRuchika Gupta 		/*
838d05ab5feSRuchika Gupta 		 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
839d05ab5feSRuchika Gupta 		 * specified with C_Derive/Unwrap() in the specification. So
840d05ab5feSRuchika Gupta 		 * return the next most appropriate error.
841d05ab5feSRuchika Gupta 		 */
842d05ab5feSRuchika Gupta 		if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED)
843d05ab5feSRuchika Gupta 			rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT;
84448799892SRuchika Gupta 		goto out;
845d05ab5feSRuchika Gupta 	}
84648799892SRuchika Gupta 
84748799892SRuchika Gupta 	/* Check access of base/parent key */
84848799892SRuchika Gupta 	rc = check_access_attrs_against_token(session, parent->attributes);
84948799892SRuchika Gupta 	if (rc)
85048799892SRuchika Gupta 		goto out;
85148799892SRuchika Gupta 
85248799892SRuchika Gupta 	template_size = sizeof(*template) + template->attrs_size;
85348799892SRuchika Gupta 	/*
85448799892SRuchika Gupta 	 * Prepare a clean initial state for the requested object attributes
85548799892SRuchika Gupta 	 * using base/parent key attributes. Free temporary template once done.
85648799892SRuchika Gupta 	 */
85748799892SRuchika Gupta 	rc = create_attributes_from_template(&head, template, template_size,
85848799892SRuchika Gupta 					     parent->attributes,
85948799892SRuchika Gupta 					     function,
86048799892SRuchika Gupta 					     proc_params->id,
86148799892SRuchika Gupta 					     PKCS11_CKO_UNDEFINED_ID);
86248799892SRuchika Gupta 	if (rc)
86348799892SRuchika Gupta 		goto out;
86448799892SRuchika Gupta 
86548799892SRuchika Gupta 	TEE_Free(template);
86648799892SRuchika Gupta 	template = NULL;
86748799892SRuchika Gupta 
86848799892SRuchika Gupta 	/* check_created_attrs() is called later once key size is known */
86948799892SRuchika Gupta 
87048799892SRuchika Gupta 	rc = check_created_attrs_against_processing(proc_params->id, head);
87148799892SRuchika Gupta 	if (rc)
87248799892SRuchika Gupta 		goto out;
87348799892SRuchika Gupta 
87448799892SRuchika Gupta 	rc = check_created_attrs_against_token(session, head);
87548799892SRuchika Gupta 	if (rc)
87648799892SRuchika Gupta 		goto out;
87748799892SRuchika Gupta 
8788c499324SRuchika Gupta 	if (processing_is_tee_symm(proc_params->id)) {
87948799892SRuchika Gupta 		/*
88048799892SRuchika Gupta 		 * These derivation mechanism require encryption to be
88148799892SRuchika Gupta 		 * performed on the data passed in proc_params by parent
88248799892SRuchika Gupta 		 * key. Hence pass function as PKCS11_FUNCTION_ENCRYPT
88348799892SRuchika Gupta 		 * to init_symm_operation()
88448799892SRuchika Gupta 		 */
88548799892SRuchika Gupta 		rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT,
88648799892SRuchika Gupta 					 proc_params, parent);
88748799892SRuchika Gupta 		if (rc)
88848799892SRuchika Gupta 			goto out;
88948799892SRuchika Gupta 
8908c499324SRuchika Gupta 		session->processing->mecha_type = proc_params->id;
8918c499324SRuchika Gupta 
8928c499324SRuchika Gupta 		rc = derive_key_by_symm_enc(session, &out_buf, &out_size);
89348799892SRuchika Gupta 		if (rc)
89448799892SRuchika Gupta 			goto out;
8958c499324SRuchika Gupta 	} else {
89648799892SRuchika Gupta 		rc = PKCS11_CKR_MECHANISM_INVALID;
89748799892SRuchika Gupta 		goto out;
89848799892SRuchika Gupta 	}
89948799892SRuchika Gupta 
9008c499324SRuchika Gupta 	rc = set_key_data(&head, out_buf, out_size);
9018c499324SRuchika Gupta 	if (rc)
9028c499324SRuchika Gupta 		goto out;
9038c499324SRuchika Gupta 
9048c499324SRuchika Gupta 	TEE_Free(out_buf);
9058c499324SRuchika Gupta 	out_buf = NULL;
9068c499324SRuchika Gupta 
90748799892SRuchika Gupta 	TEE_Free(proc_params);
90848799892SRuchika Gupta 	proc_params = NULL;
90948799892SRuchika Gupta 
91048799892SRuchika Gupta 	/*
91148799892SRuchika Gupta 	 * Object is ready, register it and return a handle.
91248799892SRuchika Gupta 	 */
91348799892SRuchika Gupta 	rc = create_object(session, head, &obj_handle);
91448799892SRuchika Gupta 	if (rc)
91548799892SRuchika Gupta 		goto out;
91648799892SRuchika Gupta 
91748799892SRuchika Gupta 	/*
91848799892SRuchika Gupta 	 * Now obj_handle (through the related struct pkcs11_object instance)
91948799892SRuchika Gupta 	 * owns the serialized buffer that holds the object attributes.
92048799892SRuchika Gupta 	 * We reset head to NULL as it is no more the buffer owner and would
92148799892SRuchika Gupta 	 * be freed at function out.
92248799892SRuchika Gupta 	 */
92348799892SRuchika Gupta 	head = NULL;
92448799892SRuchika Gupta 
92548799892SRuchika Gupta 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
92648799892SRuchika Gupta 	out->memref.size = sizeof(obj_handle);
92748799892SRuchika Gupta 
92848799892SRuchika Gupta 	DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32,
92948799892SRuchika Gupta 	     session->handle, obj_handle);
93048799892SRuchika Gupta 
93148799892SRuchika Gupta out:
93248799892SRuchika Gupta 	release_active_processing(session);
93348799892SRuchika Gupta out_free:
93448799892SRuchika Gupta 	TEE_Free(proc_params);
93548799892SRuchika Gupta 	TEE_Free(template);
93648799892SRuchika Gupta 	TEE_Free(head);
9378c499324SRuchika Gupta 	TEE_Free(out_buf);
93848799892SRuchika Gupta 
93948799892SRuchika Gupta 	return rc;
94048799892SRuchika Gupta }
941eb6141b6SVesa Jääskeläinen 
942eb6141b6SVesa Jääskeläinen enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client,
943eb6141b6SVesa Jääskeläinen 					       uint32_t ptypes,
944eb6141b6SVesa Jääskeläinen 					       TEE_Param *params)
945eb6141b6SVesa Jääskeläinen {
946eb6141b6SVesa Jääskeläinen 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
947eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE,
948eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE,
949eb6141b6SVesa Jääskeläinen 						TEE_PARAM_TYPE_NONE);
950eb6141b6SVesa Jääskeläinen 	TEE_Param *ctrl = params;
951eb6141b6SVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_OK;
952eb6141b6SVesa Jääskeläinen 	struct serialargs ctrlargs = { };
953eb6141b6SVesa Jääskeläinen 	struct pkcs11_session *session = NULL;
954eb6141b6SVesa Jääskeläinen 	enum processing_func function = PKCS11_FUNCTION_UNKNOWN;
955eb6141b6SVesa Jääskeläinen 	uint32_t cmd = 0;
956eb6141b6SVesa Jääskeläinen 
957eb6141b6SVesa Jääskeläinen 	if (!client || ptypes != exp_pt)
958eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
959eb6141b6SVesa Jääskeläinen 
960eb6141b6SVesa Jääskeläinen 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
961eb6141b6SVesa Jääskeläinen 
962eb6141b6SVesa Jääskeläinen 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
963eb6141b6SVesa Jääskeläinen 	if (rc)
964eb6141b6SVesa Jääskeläinen 		return rc;
965eb6141b6SVesa Jääskeläinen 
966eb6141b6SVesa Jääskeläinen 	rc = serialargs_get_u32(&ctrlargs, &cmd);
967eb6141b6SVesa Jääskeläinen 
968eb6141b6SVesa Jääskeläinen 	if (serialargs_remaining_bytes(&ctrlargs))
969eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
970eb6141b6SVesa Jääskeläinen 
971eb6141b6SVesa Jääskeläinen 	function = func_for_cmd(cmd);
972eb6141b6SVesa Jääskeläinen 	if (function == PKCS11_FUNCTION_UNKNOWN)
973eb6141b6SVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
974eb6141b6SVesa Jääskeläinen 
975eb6141b6SVesa Jääskeläinen 	rc = get_active_session(session, function);
976eb6141b6SVesa Jääskeläinen 	if (rc)
977eb6141b6SVesa Jääskeläinen 		return rc;
978eb6141b6SVesa Jääskeläinen 
979eb6141b6SVesa Jääskeläinen 	release_active_processing(session);
980eb6141b6SVesa Jääskeläinen 
981eb6141b6SVesa Jääskeläinen 	DMSG("PKCS11 session %"PRIu32": release processing", session->handle);
982eb6141b6SVesa Jääskeläinen 
983eb6141b6SVesa Jääskeläinen 	return PKCS11_CKR_OK;
984eb6141b6SVesa Jääskeläinen }
985