xref: /optee_os/ta/pkcs11/src/processing.c (revision a1d5c81f8834a9d2c6f4372cce2e59e70e709121)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2017-2020, Linaro Limited
4  */
5 
6 #include <assert.h>
7 #include <pkcs11_ta.h>
8 #include <string.h>
9 #include <tee_api_defines.h>
10 #include <tee_internal_api.h>
11 #include <tee_internal_api_extensions.h>
12 #include <util.h>
13 
14 #include "attributes.h"
15 #include "object.h"
16 #include "pkcs11_attributes.h"
17 #include "pkcs11_helpers.h"
18 #include "pkcs11_token.h"
19 #include "processing.h"
20 #include "serializer.h"
21 
22 static enum pkcs11_rc get_ready_session(struct pkcs11_session *session)
23 {
24 	if (session_is_active(session))
25 		return PKCS11_CKR_OPERATION_ACTIVE;
26 
27 	return PKCS11_CKR_OK;
28 }
29 
30 static bool func_matches_state(enum processing_func function,
31 			       enum pkcs11_proc_state state)
32 {
33 	switch (function) {
34 	case PKCS11_FUNCTION_ENCRYPT:
35 		return state == PKCS11_SESSION_ENCRYPTING ||
36 		       state == PKCS11_SESSION_DIGESTING_ENCRYPTING ||
37 		       state == PKCS11_SESSION_SIGNING_ENCRYPTING;
38 	case PKCS11_FUNCTION_DECRYPT:
39 		return state == PKCS11_SESSION_DECRYPTING ||
40 		       state == PKCS11_SESSION_DECRYPTING_DIGESTING ||
41 		       state == PKCS11_SESSION_DECRYPTING_VERIFYING;
42 	case PKCS11_FUNCTION_DIGEST:
43 		return state == PKCS11_SESSION_DIGESTING ||
44 		       state == PKCS11_SESSION_DIGESTING_ENCRYPTING;
45 	case PKCS11_FUNCTION_SIGN:
46 		return state == PKCS11_SESSION_SIGNING ||
47 		       state == PKCS11_SESSION_SIGNING_ENCRYPTING;
48 	case PKCS11_FUNCTION_VERIFY:
49 		return state == PKCS11_SESSION_VERIFYING ||
50 		       state == PKCS11_SESSION_DECRYPTING_VERIFYING;
51 	case PKCS11_FUNCTION_SIGN_RECOVER:
52 		return state == PKCS11_SESSION_SIGNING_RECOVER;
53 	case PKCS11_FUNCTION_VERIFY_RECOVER:
54 		return state == PKCS11_SESSION_SIGNING_RECOVER;
55 	default:
56 		TEE_Panic(function);
57 		return false;
58 	}
59 }
60 
61 static enum pkcs11_rc get_active_session(struct pkcs11_session *session,
62 					 enum processing_func function)
63 {
64 	enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED;
65 
66 	if (session->processing &&
67 	    func_matches_state(function, session->processing->state))
68 		rc = PKCS11_CKR_OK;
69 
70 	return rc;
71 }
72 
73 void release_active_processing(struct pkcs11_session *session)
74 {
75 	if (!session->processing)
76 		return;
77 
78 	switch (session->processing->mecha_type) {
79 	case PKCS11_CKM_AES_CTR:
80 		tee_release_ctr_operation(session->processing);
81 		break;
82 	default:
83 		break;
84 	}
85 
86 	if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
87 		TEE_FreeOperation(session->processing->tee_op_handle);
88 		session->processing->tee_op_handle = TEE_HANDLE_NULL;
89 	}
90 
91 	TEE_Free(session->processing);
92 	session->processing = NULL;
93 }
94 
95 size_t get_object_key_bit_size(struct pkcs11_object *obj)
96 {
97 	uint32_t a_size = 0;
98 	struct obj_attrs *attrs = obj->attributes;
99 
100 	switch (get_key_type(attrs)) {
101 	case PKCS11_CKK_AES:
102 		if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
103 			return 0;
104 
105 		return a_size * 8;
106 	default:
107 		TEE_Panic(0);
108 		return 0;
109 	}
110 }
111 
112 /*
113  * entry_processing_init - Generic entry for initializing a processing
114  *
115  * @client = client reference
116  * @ptype = Invocation parameter types
117  * @params = Invocation parameters reference
118  * @function - encrypt, decrypt, sign, verify, digest, ...
119  */
120 enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
121 				     uint32_t ptypes, TEE_Param *params,
122 				     enum processing_func function)
123 {
124 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
125 						TEE_PARAM_TYPE_NONE,
126 						TEE_PARAM_TYPE_NONE,
127 						TEE_PARAM_TYPE_NONE);
128 	TEE_Param *ctrl = params;
129 	enum pkcs11_rc rc = PKCS11_CKR_OK;
130 	struct serialargs ctrlargs = { };
131 	struct pkcs11_session *session = NULL;
132 	struct pkcs11_attribute_head *proc_params = NULL;
133 	uint32_t key_handle = 0;
134 	struct pkcs11_object *obj = NULL;
135 
136 	if (!client || ptypes != exp_pt)
137 		return PKCS11_CKR_ARGUMENTS_BAD;
138 
139 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
140 
141 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
142 	if (rc)
143 		return rc;
144 
145 	rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
146 	if (rc)
147 		return rc;
148 
149 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
150 	if (rc)
151 		return rc;
152 
153 	if (serialargs_remaining_bytes(&ctrlargs)) {
154 		rc = PKCS11_CKR_ARGUMENTS_BAD;
155 		goto out;
156 	}
157 
158 	rc = get_ready_session(session);
159 	if (rc)
160 		goto out;
161 
162 	obj = pkcs11_handle2object(key_handle, session);
163 	if (!obj) {
164 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
165 		goto out;
166 	}
167 
168 	rc = set_processing_state(session, function, obj, NULL);
169 	if (rc)
170 		goto out;
171 
172 	rc = check_mechanism_against_processing(session, proc_params->id,
173 						function,
174 						PKCS11_FUNC_STEP_INIT);
175 	if (rc)
176 		goto out;
177 
178 	rc = check_parent_attrs_against_processing(proc_params->id, function,
179 						   obj->attributes);
180 	if (rc)
181 		goto out;
182 
183 	rc = check_access_attrs_against_token(session, obj->attributes);
184 	if (rc)
185 		goto out;
186 
187 	if (processing_is_tee_symm(proc_params->id))
188 		rc = init_symm_operation(session, function, proc_params, obj);
189 	else
190 		rc = PKCS11_CKR_MECHANISM_INVALID;
191 
192 	if (rc == PKCS11_CKR_OK) {
193 		session->processing->mecha_type = proc_params->id;
194 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
195 		     session->handle, id2str_proc(proc_params->id),
196 		     id2str_function(function));
197 	}
198 
199 out:
200 	if (rc && session)
201 		release_active_processing(session);
202 
203 	TEE_Free(proc_params);
204 
205 	return rc;
206 }
207 
208 /*
209  * entry_processing_step - Generic entry on active processing
210  *
211  * @client = client reference
212  * @ptype = Invocation parameter types
213  * @params = Invocation parameters reference
214  * @function - encrypt, decrypt, sign, verify, digest, ...
215  * @step - update, oneshot, final
216  */
217 enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
218 				     uint32_t ptypes, TEE_Param *params,
219 				     enum processing_func function,
220 				     enum processing_step step)
221 {
222 	TEE_Param *ctrl = params;
223 	enum pkcs11_rc rc = PKCS11_CKR_OK;
224 	struct serialargs ctrlargs = { };
225 	struct pkcs11_session *session = NULL;
226 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
227 
228 	if (!client ||
229 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
230 		return PKCS11_CKR_ARGUMENTS_BAD;
231 
232 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
233 
234 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
235 	if (rc)
236 		return rc;
237 
238 	if (serialargs_remaining_bytes(&ctrlargs))
239 		return PKCS11_CKR_ARGUMENTS_BAD;
240 
241 	rc = get_active_session(session, function);
242 	if (rc)
243 		return rc;
244 
245 	mecha_type = session->processing->mecha_type;
246 	rc = check_mechanism_against_processing(session, mecha_type,
247 						function, step);
248 	if (rc)
249 		goto out;
250 
251 	if (processing_is_tee_symm(mecha_type))
252 		rc = step_symm_operation(session, function, step,
253 					 ptypes, params);
254 	else
255 		rc = PKCS11_CKR_MECHANISM_INVALID;
256 
257 	if (rc == PKCS11_CKR_OK) {
258 		session->processing->updated = true;
259 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
260 		     session->handle, id2str_proc(mecha_type),
261 		     id2str_function(function));
262 	}
263 
264 out:
265 	switch (step) {
266 	case PKCS11_FUNC_STEP_UPDATE:
267 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
268 			release_active_processing(session);
269 		break;
270 	default:
271 		/* ONESHOT and FINAL terminates processing on success */
272 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
273 			release_active_processing(session);
274 		break;
275 	}
276 
277 	return rc;
278 }
279 
280 /*
281  * entry_verify_oneshot - Run a single part verification processing
282  *
283  * @client = client reference
284  * @ptype = Invocation parameter types
285  * @params = Invocation parameters reference
286  * @function - encrypt, decrypt, sign, verify, digest, ...
287  * @step - update, oneshot, final
288  */
289 enum pkcs11_rc entry_verify_oneshot(struct pkcs11_client *client,
290 				    uint32_t ptypes, TEE_Param *params,
291 				    enum processing_func function,
292 				    enum processing_step step)
293 
294 {
295 	TEE_Param *ctrl = params;
296 	enum pkcs11_rc rc = PKCS11_CKR_OK;
297 	struct serialargs ctrlargs = { };
298 	struct pkcs11_session *session = NULL;
299 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
300 
301 	assert(function == PKCS11_FUNCTION_VERIFY);
302 	if (!client ||
303 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
304 		return PKCS11_CKR_ARGUMENTS_BAD;
305 
306 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
307 
308 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
309 	if (rc)
310 		return rc;
311 
312 	if (serialargs_remaining_bytes(&ctrlargs))
313 		return PKCS11_CKR_ARGUMENTS_BAD;
314 
315 	rc = get_active_session(session, function);
316 	if (rc)
317 		return rc;
318 
319 	mecha_type = session->processing->mecha_type;
320 	rc = check_mechanism_against_processing(session, mecha_type,
321 						function, step);
322 	if (rc)
323 		goto out;
324 
325 	if (processing_is_tee_symm(mecha_type))
326 		rc = step_symm_operation(session, function, step,
327 					 ptypes, params);
328 	else
329 		rc = PKCS11_CKR_MECHANISM_INVALID;
330 
331 	DMSG("PKCS11 session %"PRIu32": verify %s %s: %s", session->handle,
332 	     id2str_proc(mecha_type), id2str_function(function),
333 	     id2str_rc(rc));
334 
335 out:
336 	if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
337 		release_active_processing(session);
338 
339 	return rc;
340 }
341