xref: /optee_os/ta/pkcs11/src/processing.c (revision 2158ea6c997a50729b2fd99d35f003d8d7877ba1)
1512cbf1dSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2512cbf1dSJens Wiklander /*
3512cbf1dSJens Wiklander  * Copyright (c) 2017-2020, Linaro Limited
4512cbf1dSJens Wiklander  */
5512cbf1dSJens Wiklander 
6512cbf1dSJens Wiklander #include <assert.h>
7512cbf1dSJens Wiklander #include <pkcs11_ta.h>
8512cbf1dSJens Wiklander #include <string.h>
9512cbf1dSJens Wiklander #include <tee_api_defines.h>
10512cbf1dSJens Wiklander #include <tee_internal_api.h>
11512cbf1dSJens Wiklander #include <tee_internal_api_extensions.h>
12512cbf1dSJens Wiklander #include <util.h>
13512cbf1dSJens Wiklander 
14512cbf1dSJens Wiklander #include "attributes.h"
15512cbf1dSJens Wiklander #include "object.h"
16512cbf1dSJens Wiklander #include "pkcs11_attributes.h"
17512cbf1dSJens Wiklander #include "pkcs11_helpers.h"
18512cbf1dSJens Wiklander #include "pkcs11_token.h"
19512cbf1dSJens Wiklander #include "processing.h"
20512cbf1dSJens Wiklander #include "serializer.h"
21512cbf1dSJens Wiklander 
22512cbf1dSJens Wiklander static enum pkcs11_rc get_ready_session(struct pkcs11_session *session)
23512cbf1dSJens Wiklander {
24512cbf1dSJens Wiklander 	if (session_is_active(session))
25512cbf1dSJens Wiklander 		return PKCS11_CKR_OPERATION_ACTIVE;
26512cbf1dSJens Wiklander 
27512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
28512cbf1dSJens Wiklander }
29512cbf1dSJens Wiklander 
30512cbf1dSJens Wiklander static bool func_matches_state(enum processing_func function,
31512cbf1dSJens Wiklander 			       enum pkcs11_proc_state state)
32512cbf1dSJens Wiklander {
33512cbf1dSJens Wiklander 	switch (function) {
34512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_ENCRYPT:
35512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_ENCRYPTING ||
36512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DIGESTING_ENCRYPTING ||
37512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_SIGNING_ENCRYPTING;
38512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DECRYPT:
39512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_DECRYPTING ||
40512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_DIGESTING ||
41512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_VERIFYING;
42512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_DIGEST:
43512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_DIGESTING ||
44512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DIGESTING_ENCRYPTING;
45512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN:
46512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING ||
47512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_SIGNING_ENCRYPTING;
48512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY:
49512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_VERIFYING ||
50512cbf1dSJens Wiklander 		       state == PKCS11_SESSION_DECRYPTING_VERIFYING;
51512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_SIGN_RECOVER:
52512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING_RECOVER;
53512cbf1dSJens Wiklander 	case PKCS11_FUNCTION_VERIFY_RECOVER:
54512cbf1dSJens Wiklander 		return state == PKCS11_SESSION_SIGNING_RECOVER;
55512cbf1dSJens Wiklander 	default:
56512cbf1dSJens Wiklander 		TEE_Panic(function);
57512cbf1dSJens Wiklander 		return false;
58512cbf1dSJens Wiklander 	}
59512cbf1dSJens Wiklander }
60512cbf1dSJens Wiklander 
61512cbf1dSJens Wiklander static enum pkcs11_rc get_active_session(struct pkcs11_session *session,
62512cbf1dSJens Wiklander 					 enum processing_func function)
63512cbf1dSJens Wiklander {
64512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED;
65512cbf1dSJens Wiklander 
66512cbf1dSJens Wiklander 	if (session->processing &&
67512cbf1dSJens Wiklander 	    func_matches_state(function, session->processing->state))
68512cbf1dSJens Wiklander 		rc = PKCS11_CKR_OK;
69512cbf1dSJens Wiklander 
70512cbf1dSJens Wiklander 	return rc;
71512cbf1dSJens Wiklander }
72512cbf1dSJens Wiklander 
73512cbf1dSJens Wiklander void release_active_processing(struct pkcs11_session *session)
74512cbf1dSJens Wiklander {
75512cbf1dSJens Wiklander 	if (!session->processing)
76512cbf1dSJens Wiklander 		return;
77512cbf1dSJens Wiklander 
78512cbf1dSJens Wiklander 	switch (session->processing->mecha_type) {
79512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
80512cbf1dSJens Wiklander 		tee_release_ctr_operation(session->processing);
81512cbf1dSJens Wiklander 		break;
82512cbf1dSJens Wiklander 	default:
83512cbf1dSJens Wiklander 		break;
84512cbf1dSJens Wiklander 	}
85512cbf1dSJens Wiklander 
86512cbf1dSJens Wiklander 	if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
87512cbf1dSJens Wiklander 		TEE_FreeOperation(session->processing->tee_op_handle);
88512cbf1dSJens Wiklander 		session->processing->tee_op_handle = TEE_HANDLE_NULL;
89512cbf1dSJens Wiklander 	}
90512cbf1dSJens Wiklander 
91*2158ea6cSRuchika Gupta 	TEE_Free(session->processing->extra_ctx);
92*2158ea6cSRuchika Gupta 
93512cbf1dSJens Wiklander 	TEE_Free(session->processing);
94512cbf1dSJens Wiklander 	session->processing = NULL;
95512cbf1dSJens Wiklander }
96512cbf1dSJens Wiklander 
97512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj)
98512cbf1dSJens Wiklander {
99512cbf1dSJens Wiklander 	uint32_t a_size = 0;
100512cbf1dSJens Wiklander 	struct obj_attrs *attrs = obj->attributes;
101512cbf1dSJens Wiklander 
102512cbf1dSJens Wiklander 	switch (get_key_type(attrs)) {
103512cbf1dSJens Wiklander 	case PKCS11_CKK_AES:
104689f4e5bSRuchika Gupta 	case PKCS11_CKK_GENERIC_SECRET:
105689f4e5bSRuchika Gupta 	case PKCS11_CKK_MD5_HMAC:
106689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA_1_HMAC:
107689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA224_HMAC:
108689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA256_HMAC:
109689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA384_HMAC:
110689f4e5bSRuchika Gupta 	case PKCS11_CKK_SHA512_HMAC:
111512cbf1dSJens Wiklander 		if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
112512cbf1dSJens Wiklander 			return 0;
113512cbf1dSJens Wiklander 
114512cbf1dSJens Wiklander 		return a_size * 8;
115512cbf1dSJens Wiklander 	default:
116512cbf1dSJens Wiklander 		TEE_Panic(0);
117512cbf1dSJens Wiklander 		return 0;
118512cbf1dSJens Wiklander 	}
119512cbf1dSJens Wiklander }
120512cbf1dSJens Wiklander 
121512cbf1dSJens Wiklander /*
122512cbf1dSJens Wiklander  * entry_processing_init - Generic entry for initializing a processing
123512cbf1dSJens Wiklander  *
124512cbf1dSJens Wiklander  * @client = client reference
125512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
126512cbf1dSJens Wiklander  * @params = Invocation parameters reference
127512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
128512cbf1dSJens Wiklander  */
129512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
130512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
131512cbf1dSJens Wiklander 				     enum processing_func function)
132512cbf1dSJens Wiklander {
133512cbf1dSJens Wiklander 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
134512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
135512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE,
136512cbf1dSJens Wiklander 						TEE_PARAM_TYPE_NONE);
137512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
138512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
139512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
140512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
141512cbf1dSJens Wiklander 	struct pkcs11_attribute_head *proc_params = NULL;
142512cbf1dSJens Wiklander 	uint32_t key_handle = 0;
143512cbf1dSJens Wiklander 	struct pkcs11_object *obj = NULL;
144512cbf1dSJens Wiklander 
145512cbf1dSJens Wiklander 	if (!client || ptypes != exp_pt)
146512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
147512cbf1dSJens Wiklander 
148512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
149512cbf1dSJens Wiklander 
150512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
151512cbf1dSJens Wiklander 	if (rc)
152512cbf1dSJens Wiklander 		return rc;
153512cbf1dSJens Wiklander 
154512cbf1dSJens Wiklander 	rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
155512cbf1dSJens Wiklander 	if (rc)
156512cbf1dSJens Wiklander 		return rc;
157512cbf1dSJens Wiklander 
158512cbf1dSJens Wiklander 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
159512cbf1dSJens Wiklander 	if (rc)
160512cbf1dSJens Wiklander 		return rc;
161512cbf1dSJens Wiklander 
162512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs)) {
163512cbf1dSJens Wiklander 		rc = PKCS11_CKR_ARGUMENTS_BAD;
164512cbf1dSJens Wiklander 		goto out;
165512cbf1dSJens Wiklander 	}
166512cbf1dSJens Wiklander 
167512cbf1dSJens Wiklander 	rc = get_ready_session(session);
168512cbf1dSJens Wiklander 	if (rc)
169512cbf1dSJens Wiklander 		goto out;
170512cbf1dSJens Wiklander 
171512cbf1dSJens Wiklander 	obj = pkcs11_handle2object(key_handle, session);
172512cbf1dSJens Wiklander 	if (!obj) {
173512cbf1dSJens Wiklander 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
174512cbf1dSJens Wiklander 		goto out;
175512cbf1dSJens Wiklander 	}
176512cbf1dSJens Wiklander 
177512cbf1dSJens Wiklander 	rc = set_processing_state(session, function, obj, NULL);
178512cbf1dSJens Wiklander 	if (rc)
179512cbf1dSJens Wiklander 		goto out;
180512cbf1dSJens Wiklander 
181512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, proc_params->id,
182512cbf1dSJens Wiklander 						function,
183512cbf1dSJens Wiklander 						PKCS11_FUNC_STEP_INIT);
184512cbf1dSJens Wiklander 	if (rc)
185512cbf1dSJens Wiklander 		goto out;
186512cbf1dSJens Wiklander 
187512cbf1dSJens Wiklander 	rc = check_parent_attrs_against_processing(proc_params->id, function,
188512cbf1dSJens Wiklander 						   obj->attributes);
189512cbf1dSJens Wiklander 	if (rc)
190512cbf1dSJens Wiklander 		goto out;
191512cbf1dSJens Wiklander 
192512cbf1dSJens Wiklander 	rc = check_access_attrs_against_token(session, obj->attributes);
193512cbf1dSJens Wiklander 	if (rc)
194512cbf1dSJens Wiklander 		goto out;
195512cbf1dSJens Wiklander 
196512cbf1dSJens Wiklander 	if (processing_is_tee_symm(proc_params->id))
197512cbf1dSJens Wiklander 		rc = init_symm_operation(session, function, proc_params, obj);
198512cbf1dSJens Wiklander 	else
199512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
200512cbf1dSJens Wiklander 
201512cbf1dSJens Wiklander 	if (rc == PKCS11_CKR_OK) {
202512cbf1dSJens Wiklander 		session->processing->mecha_type = proc_params->id;
203512cbf1dSJens Wiklander 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
204512cbf1dSJens Wiklander 		     session->handle, id2str_proc(proc_params->id),
205512cbf1dSJens Wiklander 		     id2str_function(function));
206512cbf1dSJens Wiklander 	}
207512cbf1dSJens Wiklander 
208512cbf1dSJens Wiklander out:
209512cbf1dSJens Wiklander 	if (rc && session)
210512cbf1dSJens Wiklander 		release_active_processing(session);
211512cbf1dSJens Wiklander 
212512cbf1dSJens Wiklander 	TEE_Free(proc_params);
213512cbf1dSJens Wiklander 
214512cbf1dSJens Wiklander 	return rc;
215512cbf1dSJens Wiklander }
216512cbf1dSJens Wiklander 
217512cbf1dSJens Wiklander /*
218512cbf1dSJens Wiklander  * entry_processing_step - Generic entry on active processing
219512cbf1dSJens Wiklander  *
220512cbf1dSJens Wiklander  * @client = client reference
221512cbf1dSJens Wiklander  * @ptype = Invocation parameter types
222512cbf1dSJens Wiklander  * @params = Invocation parameters reference
223512cbf1dSJens Wiklander  * @function - encrypt, decrypt, sign, verify, digest, ...
224512cbf1dSJens Wiklander  * @step - update, oneshot, final
225512cbf1dSJens Wiklander  */
226512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
227512cbf1dSJens Wiklander 				     uint32_t ptypes, TEE_Param *params,
228512cbf1dSJens Wiklander 				     enum processing_func function,
229512cbf1dSJens Wiklander 				     enum processing_step step)
230512cbf1dSJens Wiklander {
231512cbf1dSJens Wiklander 	TEE_Param *ctrl = params;
232512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
233512cbf1dSJens Wiklander 	struct serialargs ctrlargs = { };
234512cbf1dSJens Wiklander 	struct pkcs11_session *session = NULL;
235512cbf1dSJens Wiklander 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
236512cbf1dSJens Wiklander 
237512cbf1dSJens Wiklander 	if (!client ||
238512cbf1dSJens Wiklander 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
239512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
240512cbf1dSJens Wiklander 
241512cbf1dSJens Wiklander 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
242512cbf1dSJens Wiklander 
243512cbf1dSJens Wiklander 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
244512cbf1dSJens Wiklander 	if (rc)
245512cbf1dSJens Wiklander 		return rc;
246512cbf1dSJens Wiklander 
247512cbf1dSJens Wiklander 	if (serialargs_remaining_bytes(&ctrlargs))
248512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
249512cbf1dSJens Wiklander 
250512cbf1dSJens Wiklander 	rc = get_active_session(session, function);
251512cbf1dSJens Wiklander 	if (rc)
252512cbf1dSJens Wiklander 		return rc;
253512cbf1dSJens Wiklander 
254512cbf1dSJens Wiklander 	mecha_type = session->processing->mecha_type;
255512cbf1dSJens Wiklander 	rc = check_mechanism_against_processing(session, mecha_type,
256512cbf1dSJens Wiklander 						function, step);
257512cbf1dSJens Wiklander 	if (rc)
258512cbf1dSJens Wiklander 		goto out;
259512cbf1dSJens Wiklander 
260512cbf1dSJens Wiklander 	if (processing_is_tee_symm(mecha_type))
261512cbf1dSJens Wiklander 		rc = step_symm_operation(session, function, step,
262512cbf1dSJens Wiklander 					 ptypes, params);
263512cbf1dSJens Wiklander 	else
264512cbf1dSJens Wiklander 		rc = PKCS11_CKR_MECHANISM_INVALID;
265512cbf1dSJens Wiklander 
266689f4e5bSRuchika Gupta 	if (rc == PKCS11_CKR_OK && step == PKCS11_FUNC_STEP_UPDATE) {
267512cbf1dSJens Wiklander 		session->processing->updated = true;
268512cbf1dSJens Wiklander 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
269512cbf1dSJens Wiklander 		     session->handle, id2str_proc(mecha_type),
270512cbf1dSJens Wiklander 		     id2str_function(function));
271512cbf1dSJens Wiklander 	}
272512cbf1dSJens Wiklander 
273512cbf1dSJens Wiklander out:
274512cbf1dSJens Wiklander 	switch (step) {
275512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_UPDATE:
276512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
277512cbf1dSJens Wiklander 			release_active_processing(session);
278512cbf1dSJens Wiklander 		break;
279512cbf1dSJens Wiklander 	default:
280512cbf1dSJens Wiklander 		/* ONESHOT and FINAL terminates processing on success */
281512cbf1dSJens Wiklander 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
282512cbf1dSJens Wiklander 			release_active_processing(session);
283512cbf1dSJens Wiklander 		break;
284512cbf1dSJens Wiklander 	}
285512cbf1dSJens Wiklander 
286512cbf1dSJens Wiklander 	return rc;
287512cbf1dSJens Wiklander }
288