xref: /optee_os/ta/pkcs11/src/processing.c (revision 9fc2442cc66c279cb962c90c4375746fc9b28bb9)
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 	if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
79 		TEE_FreeOperation(session->processing->tee_op_handle);
80 		session->processing->tee_op_handle = TEE_HANDLE_NULL;
81 	}
82 
83 	TEE_Free(session->processing->extra_ctx);
84 
85 	TEE_Free(session->processing);
86 	session->processing = NULL;
87 }
88 
89 size_t get_object_key_bit_size(struct pkcs11_object *obj)
90 {
91 	uint32_t a_size = 0;
92 	struct obj_attrs *attrs = obj->attributes;
93 
94 	switch (get_key_type(attrs)) {
95 	case PKCS11_CKK_AES:
96 	case PKCS11_CKK_GENERIC_SECRET:
97 	case PKCS11_CKK_MD5_HMAC:
98 	case PKCS11_CKK_SHA_1_HMAC:
99 	case PKCS11_CKK_SHA224_HMAC:
100 	case PKCS11_CKK_SHA256_HMAC:
101 	case PKCS11_CKK_SHA384_HMAC:
102 	case PKCS11_CKK_SHA512_HMAC:
103 		if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
104 			return 0;
105 
106 		return a_size * 8;
107 	default:
108 		TEE_Panic(0);
109 		return 0;
110 	}
111 }
112 
113 static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
114 {
115 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
116 	void *data = NULL;
117 	uint32_t data_size = 0;
118 	uint32_t value_len = 0;
119 	void *value = NULL;
120 
121 	if (!*head)
122 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
123 
124 	rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size);
125 	if (rc || data_size != sizeof(uint32_t)) {
126 		DMSG("%s", rc ? "No attribute value_len found" :
127 		     "Invalid size for attribute VALUE_LEN");
128 
129 		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
130 	}
131 	TEE_MemMove(&value_len, data, data_size);
132 
133 	if (get_key_type(*head) == PKCS11_CKK_GENERIC_SECRET)
134 		value_len = (value_len + 7) / 8;
135 
136 	/* Remove the default empty value attribute if found */
137 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
138 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
139 		return PKCS11_CKR_GENERAL_ERROR;
140 
141 	value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
142 	if (!value)
143 		return PKCS11_CKR_DEVICE_MEMORY;
144 
145 	TEE_GenerateRandom(value, value_len);
146 
147 	rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
148 
149 	TEE_Free(value);
150 
151 	return rc;
152 }
153 
154 enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
155 				     uint32_t ptypes, TEE_Param *params)
156 {
157 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
158 						TEE_PARAM_TYPE_NONE,
159 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
160 						TEE_PARAM_TYPE_NONE);
161 	TEE_Param *ctrl = params;
162 	TEE_Param *out = params + 2;
163 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
164 	struct serialargs ctrlargs = { };
165 	struct pkcs11_session *session = NULL;
166 	struct pkcs11_attribute_head *proc_params = NULL;
167 	struct obj_attrs *head = NULL;
168 	struct pkcs11_object_head *template = NULL;
169 	size_t template_size = 0;
170 	uint32_t obj_handle = 0;
171 
172 	if (!client || ptypes != exp_pt ||
173 	    out->memref.size != sizeof(obj_handle))
174 		return PKCS11_CKR_ARGUMENTS_BAD;
175 
176 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
177 
178 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
179 	if (rc)
180 		return rc;
181 
182 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
183 	if (rc)
184 		goto out;
185 
186 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
187 	if (rc)
188 		goto out;
189 
190 	if (serialargs_remaining_bytes(&ctrlargs)) {
191 		rc = PKCS11_CKR_ARGUMENTS_BAD;
192 		goto out;
193 	}
194 
195 	rc = get_ready_session(session);
196 	if (rc)
197 		goto out;
198 
199 	template_size = sizeof(*template) + template->attrs_size;
200 
201 	rc = check_mechanism_against_processing(session, proc_params->id,
202 						PKCS11_FUNCTION_GENERATE,
203 						PKCS11_FUNC_STEP_INIT);
204 	if (rc) {
205 		DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
206 		goto out;
207 	}
208 
209 	/*
210 	 * Prepare a clean initial state for the requested object attributes.
211 	 * Free temporary template once done.
212 	 */
213 	rc = create_attributes_from_template(&head, template, template_size,
214 					     NULL, PKCS11_FUNCTION_GENERATE,
215 					     proc_params->id,
216 					     PKCS11_CKO_UNDEFINED_ID);
217 	if (rc)
218 		goto out;
219 
220 	TEE_Free(template);
221 	template = NULL;
222 
223 	rc = check_created_attrs(head, NULL);
224 	if (rc)
225 		goto out;
226 
227 	rc = check_created_attrs_against_processing(proc_params->id, head);
228 	if (rc)
229 		goto out;
230 
231 	rc = check_created_attrs_against_token(session, head);
232 	if (rc)
233 		goto out;
234 
235 	/*
236 	 * Execute target processing and add value as attribute
237 	 * PKCS11_CKA_VALUE. Symm key generation: depends on target
238 	 * processing to be used.
239 	 */
240 	switch (proc_params->id) {
241 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
242 	case PKCS11_CKM_AES_KEY_GEN:
243 		/* Generate random of size specified by attribute VALUE_LEN */
244 		rc = generate_random_key_value(&head);
245 		if (rc)
246 			goto out;
247 		break;
248 
249 	default:
250 		rc = PKCS11_CKR_MECHANISM_INVALID;
251 		goto out;
252 	}
253 
254 	TEE_Free(proc_params);
255 	proc_params = NULL;
256 
257 	/*
258 	 * Object is ready, register it and return a handle.
259 	 */
260 	rc = create_object(session, head, &obj_handle);
261 	if (rc)
262 		goto out;
263 
264 	/*
265 	 * Now obj_handle (through the related struct pkcs11_object instance)
266 	 * owns the serialized buffer that holds the object attributes.
267 	 * We reset head to NULL as it is no more the buffer owner and would
268 	 * be freed at function out.
269 	 */
270 	head = NULL;
271 
272 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
273 	out->memref.size = sizeof(obj_handle);
274 
275 	DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
276 	     session->handle, obj_handle);
277 
278 out:
279 	TEE_Free(proc_params);
280 	TEE_Free(template);
281 	TEE_Free(head);
282 
283 	return rc;
284 }
285 
286 /*
287  * entry_processing_init - Generic entry for initializing a processing
288  *
289  * @client = client reference
290  * @ptype = Invocation parameter types
291  * @params = Invocation parameters reference
292  * @function - encrypt, decrypt, sign, verify, digest, ...
293  */
294 enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
295 				     uint32_t ptypes, TEE_Param *params,
296 				     enum processing_func function)
297 {
298 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
299 						TEE_PARAM_TYPE_NONE,
300 						TEE_PARAM_TYPE_NONE,
301 						TEE_PARAM_TYPE_NONE);
302 	TEE_Param *ctrl = params;
303 	enum pkcs11_rc rc = PKCS11_CKR_OK;
304 	struct serialargs ctrlargs = { };
305 	struct pkcs11_session *session = NULL;
306 	struct pkcs11_attribute_head *proc_params = NULL;
307 	uint32_t key_handle = 0;
308 	struct pkcs11_object *obj = NULL;
309 
310 	if (!client || ptypes != exp_pt)
311 		return PKCS11_CKR_ARGUMENTS_BAD;
312 
313 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
314 
315 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
316 	if (rc)
317 		return rc;
318 
319 	rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
320 	if (rc)
321 		return rc;
322 
323 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
324 	if (rc)
325 		return rc;
326 
327 	if (serialargs_remaining_bytes(&ctrlargs)) {
328 		rc = PKCS11_CKR_ARGUMENTS_BAD;
329 		goto out;
330 	}
331 
332 	rc = get_ready_session(session);
333 	if (rc)
334 		goto out;
335 
336 	obj = pkcs11_handle2object(key_handle, session);
337 	if (!obj) {
338 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
339 		goto out;
340 	}
341 
342 	rc = set_processing_state(session, function, obj, NULL);
343 	if (rc)
344 		goto out;
345 
346 	rc = check_mechanism_against_processing(session, proc_params->id,
347 						function,
348 						PKCS11_FUNC_STEP_INIT);
349 	if (rc)
350 		goto out;
351 
352 	rc = check_parent_attrs_against_processing(proc_params->id, function,
353 						   obj->attributes);
354 	if (rc)
355 		goto out;
356 
357 	rc = check_access_attrs_against_token(session, obj->attributes);
358 	if (rc)
359 		goto out;
360 
361 	if (processing_is_tee_symm(proc_params->id))
362 		rc = init_symm_operation(session, function, proc_params, obj);
363 	else
364 		rc = PKCS11_CKR_MECHANISM_INVALID;
365 
366 	if (rc == PKCS11_CKR_OK) {
367 		session->processing->mecha_type = proc_params->id;
368 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
369 		     session->handle, id2str_proc(proc_params->id),
370 		     id2str_function(function));
371 	}
372 
373 out:
374 	if (rc && session)
375 		release_active_processing(session);
376 
377 	TEE_Free(proc_params);
378 
379 	return rc;
380 }
381 
382 /*
383  * entry_processing_step - Generic entry on active processing
384  *
385  * @client = client reference
386  * @ptype = Invocation parameter types
387  * @params = Invocation parameters reference
388  * @function - encrypt, decrypt, sign, verify, digest, ...
389  * @step - update, oneshot, final
390  */
391 enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
392 				     uint32_t ptypes, TEE_Param *params,
393 				     enum processing_func function,
394 				     enum processing_step step)
395 {
396 	TEE_Param *ctrl = params;
397 	enum pkcs11_rc rc = PKCS11_CKR_OK;
398 	struct serialargs ctrlargs = { };
399 	struct pkcs11_session *session = NULL;
400 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
401 
402 	if (!client ||
403 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
404 		return PKCS11_CKR_ARGUMENTS_BAD;
405 
406 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
407 
408 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
409 	if (rc)
410 		return rc;
411 
412 	if (serialargs_remaining_bytes(&ctrlargs))
413 		return PKCS11_CKR_ARGUMENTS_BAD;
414 
415 	rc = get_active_session(session, function);
416 	if (rc)
417 		return rc;
418 
419 	mecha_type = session->processing->mecha_type;
420 	rc = check_mechanism_against_processing(session, mecha_type,
421 						function, step);
422 	if (rc)
423 		goto out;
424 
425 	if (processing_is_tee_symm(mecha_type))
426 		rc = step_symm_operation(session, function, step,
427 					 ptypes, params);
428 	else
429 		rc = PKCS11_CKR_MECHANISM_INVALID;
430 
431 	if (rc == PKCS11_CKR_OK && step == PKCS11_FUNC_STEP_UPDATE) {
432 		session->processing->updated = true;
433 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
434 		     session->handle, id2str_proc(mecha_type),
435 		     id2str_function(function));
436 	}
437 
438 out:
439 	switch (step) {
440 	case PKCS11_FUNC_STEP_UPDATE:
441 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
442 			release_active_processing(session);
443 		break;
444 	default:
445 		/* ONESHOT and FINAL terminates processing on success */
446 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
447 			release_active_processing(session);
448 		break;
449 	}
450 
451 	return rc;
452 }
453