xref: /optee_os/ta/pkcs11/src/processing.c (revision d05ab5fe8dc8eedf222aa28adca31e49d0585ab8)
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 	/* Remove the default empty value attribute if found */
134 	rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
135 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
136 		return PKCS11_CKR_GENERAL_ERROR;
137 
138 	value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
139 	if (!value)
140 		return PKCS11_CKR_DEVICE_MEMORY;
141 
142 	TEE_GenerateRandom(value, value_len);
143 
144 	rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
145 
146 	TEE_Free(value);
147 
148 	return rc;
149 }
150 
151 enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
152 				     uint32_t ptypes, TEE_Param *params)
153 {
154 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
155 						TEE_PARAM_TYPE_NONE,
156 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
157 						TEE_PARAM_TYPE_NONE);
158 	TEE_Param *ctrl = params;
159 	TEE_Param *out = params + 2;
160 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
161 	struct serialargs ctrlargs = { };
162 	struct pkcs11_session *session = NULL;
163 	struct pkcs11_attribute_head *proc_params = NULL;
164 	struct obj_attrs *head = NULL;
165 	struct pkcs11_object_head *template = NULL;
166 	size_t template_size = 0;
167 	uint32_t obj_handle = 0;
168 
169 	if (!client || ptypes != exp_pt ||
170 	    out->memref.size != sizeof(obj_handle))
171 		return PKCS11_CKR_ARGUMENTS_BAD;
172 
173 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
174 
175 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
176 	if (rc)
177 		return rc;
178 
179 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
180 	if (rc)
181 		goto out;
182 
183 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
184 	if (rc)
185 		goto out;
186 
187 	if (serialargs_remaining_bytes(&ctrlargs)) {
188 		rc = PKCS11_CKR_ARGUMENTS_BAD;
189 		goto out;
190 	}
191 
192 	rc = get_ready_session(session);
193 	if (rc)
194 		goto out;
195 
196 	template_size = sizeof(*template) + template->attrs_size;
197 
198 	rc = check_mechanism_against_processing(session, proc_params->id,
199 						PKCS11_FUNCTION_GENERATE,
200 						PKCS11_FUNC_STEP_INIT);
201 	if (rc) {
202 		DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
203 		goto out;
204 	}
205 
206 	/*
207 	 * Prepare a clean initial state for the requested object attributes.
208 	 * Free temporary template once done.
209 	 */
210 	rc = create_attributes_from_template(&head, template, template_size,
211 					     NULL, PKCS11_FUNCTION_GENERATE,
212 					     proc_params->id,
213 					     PKCS11_CKO_UNDEFINED_ID);
214 	if (rc)
215 		goto out;
216 
217 	TEE_Free(template);
218 	template = NULL;
219 
220 	rc = check_created_attrs(head, NULL);
221 	if (rc)
222 		goto out;
223 
224 	rc = check_created_attrs_against_processing(proc_params->id, head);
225 	if (rc)
226 		goto out;
227 
228 	rc = check_created_attrs_against_token(session, head);
229 	if (rc)
230 		goto out;
231 
232 	/*
233 	 * Execute target processing and add value as attribute
234 	 * PKCS11_CKA_VALUE. Symm key generation: depends on target
235 	 * processing to be used.
236 	 */
237 	switch (proc_params->id) {
238 	case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
239 	case PKCS11_CKM_AES_KEY_GEN:
240 		/* Generate random of size specified by attribute VALUE_LEN */
241 		rc = generate_random_key_value(&head);
242 		if (rc)
243 			goto out;
244 		break;
245 
246 	default:
247 		rc = PKCS11_CKR_MECHANISM_INVALID;
248 		goto out;
249 	}
250 
251 	TEE_Free(proc_params);
252 	proc_params = NULL;
253 
254 	/*
255 	 * Object is ready, register it and return a handle.
256 	 */
257 	rc = create_object(session, head, &obj_handle);
258 	if (rc)
259 		goto out;
260 
261 	/*
262 	 * Now obj_handle (through the related struct pkcs11_object instance)
263 	 * owns the serialized buffer that holds the object attributes.
264 	 * We reset head to NULL as it is no more the buffer owner and would
265 	 * be freed at function out.
266 	 */
267 	head = NULL;
268 
269 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
270 	out->memref.size = sizeof(obj_handle);
271 
272 	DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
273 	     session->handle, obj_handle);
274 
275 out:
276 	TEE_Free(proc_params);
277 	TEE_Free(template);
278 	TEE_Free(head);
279 
280 	return rc;
281 }
282 
283 /*
284  * entry_processing_init - Generic entry for initializing a processing
285  *
286  * @client = client reference
287  * @ptype = Invocation parameter types
288  * @params = Invocation parameters reference
289  * @function - encrypt, decrypt, sign, verify, digest, ...
290  */
291 enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
292 				     uint32_t ptypes, TEE_Param *params,
293 				     enum processing_func function)
294 {
295 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
296 						TEE_PARAM_TYPE_NONE,
297 						TEE_PARAM_TYPE_NONE,
298 						TEE_PARAM_TYPE_NONE);
299 	TEE_Param *ctrl = params;
300 	enum pkcs11_rc rc = PKCS11_CKR_OK;
301 	struct serialargs ctrlargs = { };
302 	struct pkcs11_session *session = NULL;
303 	struct pkcs11_attribute_head *proc_params = NULL;
304 	uint32_t key_handle = 0;
305 	struct pkcs11_object *obj = NULL;
306 
307 	if (!client || ptypes != exp_pt)
308 		return PKCS11_CKR_ARGUMENTS_BAD;
309 
310 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
311 
312 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
313 	if (rc)
314 		return rc;
315 
316 	rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
317 	if (rc)
318 		return rc;
319 
320 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
321 	if (rc)
322 		return rc;
323 
324 	if (serialargs_remaining_bytes(&ctrlargs)) {
325 		rc = PKCS11_CKR_ARGUMENTS_BAD;
326 		goto out;
327 	}
328 
329 	rc = get_ready_session(session);
330 	if (rc)
331 		goto out;
332 
333 	obj = pkcs11_handle2object(key_handle, session);
334 	if (!obj) {
335 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
336 		goto out;
337 	}
338 
339 	rc = set_processing_state(session, function, obj, NULL);
340 	if (rc)
341 		goto out;
342 
343 	rc = check_mechanism_against_processing(session, proc_params->id,
344 						function,
345 						PKCS11_FUNC_STEP_INIT);
346 	if (rc)
347 		goto out;
348 
349 	rc = check_parent_attrs_against_processing(proc_params->id, function,
350 						   obj->attributes);
351 	if (rc)
352 		goto out;
353 
354 	rc = check_access_attrs_against_token(session, obj->attributes);
355 	if (rc)
356 		goto out;
357 
358 	if (processing_is_tee_symm(proc_params->id))
359 		rc = init_symm_operation(session, function, proc_params, obj);
360 	else
361 		rc = PKCS11_CKR_MECHANISM_INVALID;
362 
363 	if (rc == PKCS11_CKR_OK) {
364 		session->processing->mecha_type = proc_params->id;
365 		DMSG("PKCS11 session %"PRIu32": init processing %s %s",
366 		     session->handle, id2str_proc(proc_params->id),
367 		     id2str_function(function));
368 	}
369 
370 out:
371 	if (rc && session)
372 		release_active_processing(session);
373 
374 	TEE_Free(proc_params);
375 
376 	return rc;
377 }
378 
379 /*
380  * entry_processing_step - Generic entry on active processing
381  *
382  * @client = client reference
383  * @ptype = Invocation parameter types
384  * @params = Invocation parameters reference
385  * @function - encrypt, decrypt, sign, verify, digest, ...
386  * @step - update, oneshot, final
387  */
388 enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
389 				     uint32_t ptypes, TEE_Param *params,
390 				     enum processing_func function,
391 				     enum processing_step step)
392 {
393 	TEE_Param *ctrl = params;
394 	enum pkcs11_rc rc = PKCS11_CKR_OK;
395 	struct serialargs ctrlargs = { };
396 	struct pkcs11_session *session = NULL;
397 	enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
398 
399 	if (!client ||
400 	    TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
401 		return PKCS11_CKR_ARGUMENTS_BAD;
402 
403 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
404 
405 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
406 	if (rc)
407 		return rc;
408 
409 	if (serialargs_remaining_bytes(&ctrlargs))
410 		return PKCS11_CKR_ARGUMENTS_BAD;
411 
412 	rc = get_active_session(session, function);
413 	if (rc)
414 		return rc;
415 
416 	mecha_type = session->processing->mecha_type;
417 	rc = check_mechanism_against_processing(session, mecha_type,
418 						function, step);
419 	if (rc)
420 		goto out;
421 
422 	if (processing_is_tee_symm(mecha_type))
423 		rc = step_symm_operation(session, function, step,
424 					 ptypes, params);
425 	else
426 		rc = PKCS11_CKR_MECHANISM_INVALID;
427 
428 	if (rc == PKCS11_CKR_OK && step == PKCS11_FUNC_STEP_UPDATE) {
429 		session->processing->updated = true;
430 		DMSG("PKCS11 session%"PRIu32": processing %s %s",
431 		     session->handle, id2str_proc(mecha_type),
432 		     id2str_function(function));
433 	}
434 
435 out:
436 	switch (step) {
437 	case PKCS11_FUNC_STEP_UPDATE:
438 		if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
439 			release_active_processing(session);
440 		break;
441 	default:
442 		/* ONESHOT and FINAL terminates processing on success */
443 		if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
444 			release_active_processing(session);
445 		break;
446 	}
447 
448 	return rc;
449 }
450 
451 enum pkcs11_rc entry_processing_key(struct pkcs11_client *client,
452 				    uint32_t ptypes, TEE_Param *params,
453 				    enum processing_func function)
454 {
455 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
456 						TEE_PARAM_TYPE_NONE,
457 						TEE_PARAM_TYPE_MEMREF_OUTPUT,
458 						TEE_PARAM_TYPE_NONE);
459 	TEE_Param *ctrl = params;
460 	TEE_Param *out = params + 2;
461 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
462 	struct serialargs ctrlargs = { };
463 	struct pkcs11_session *session = NULL;
464 	struct pkcs11_attribute_head *proc_params = NULL;
465 	struct pkcs11_object_head *template = NULL;
466 	uint32_t parent_handle = 0;
467 	uint32_t obj_handle = 0;
468 	struct pkcs11_object *parent = NULL;
469 	struct obj_attrs *head = NULL;
470 	size_t template_size = 0;
471 	void *out_buf = NULL;
472 	uint32_t out_size = 0;
473 
474 	if (!client || ptypes != exp_pt ||
475 	    out->memref.size != sizeof(obj_handle))
476 		return PKCS11_CKR_ARGUMENTS_BAD;
477 
478 	serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
479 
480 	rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
481 	if (rc)
482 		return rc;
483 
484 	rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t));
485 	if (rc)
486 		return rc;
487 
488 	rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
489 	if (rc)
490 		goto out_free;
491 
492 	rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
493 	if (rc)
494 		goto out_free;
495 
496 	if (serialargs_remaining_bytes(&ctrlargs)) {
497 		rc = PKCS11_CKR_ARGUMENTS_BAD;
498 		goto out_free;
499 	}
500 
501 	/* Return error if processing already active */
502 	rc = get_ready_session(session);
503 	if (rc)
504 		goto out_free;
505 
506 	/* Check parent handle */
507 	parent = pkcs11_handle2object(parent_handle, session);
508 	if (!parent) {
509 		rc = PKCS11_CKR_KEY_HANDLE_INVALID;
510 		goto out_free;
511 	}
512 
513 	/* Check if mechanism can be used for derivation function */
514 	rc = check_mechanism_against_processing(session, proc_params->id,
515 						function,
516 						PKCS11_FUNC_STEP_INIT);
517 	if (rc)
518 		goto out_free;
519 
520 	/* Set the processing state to active */
521 	rc = set_processing_state(session, function, parent, NULL);
522 	if (rc)
523 		goto out_free;
524 
525 	/*
526 	 * Check if base/parent key has CKA_DERIVE set and its key type is
527 	 * compatible with the mechanism passed
528 	 */
529 	rc = check_parent_attrs_against_processing(proc_params->id, function,
530 						   parent->attributes);
531 	if (rc) {
532 		/*
533 		 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
534 		 * specified with C_Derive/Unwrap() in the specification. So
535 		 * return the next most appropriate error.
536 		 */
537 		if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED)
538 			rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT;
539 		goto out;
540 	}
541 
542 	/* Check access of base/parent key */
543 	rc = check_access_attrs_against_token(session, parent->attributes);
544 	if (rc)
545 		goto out;
546 
547 	template_size = sizeof(*template) + template->attrs_size;
548 	/*
549 	 * Prepare a clean initial state for the requested object attributes
550 	 * using base/parent key attributes. Free temporary template once done.
551 	 */
552 	rc = create_attributes_from_template(&head, template, template_size,
553 					     parent->attributes,
554 					     function,
555 					     proc_params->id,
556 					     PKCS11_CKO_UNDEFINED_ID);
557 	if (rc)
558 		goto out;
559 
560 	TEE_Free(template);
561 	template = NULL;
562 
563 	/* check_created_attrs() is called later once key size is known */
564 
565 	rc = check_created_attrs_against_processing(proc_params->id, head);
566 	if (rc)
567 		goto out;
568 
569 	rc = check_created_attrs_against_token(session, head);
570 	if (rc)
571 		goto out;
572 
573 	if (processing_is_tee_symm(proc_params->id)) {
574 		/*
575 		 * These derivation mechanism require encryption to be
576 		 * performed on the data passed in proc_params by parent
577 		 * key. Hence pass function as PKCS11_FUNCTION_ENCRYPT
578 		 * to init_symm_operation()
579 		 */
580 		rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT,
581 					 proc_params, parent);
582 		if (rc)
583 			goto out;
584 
585 		session->processing->mecha_type = proc_params->id;
586 
587 		rc = derive_key_by_symm_enc(session, &out_buf, &out_size);
588 		if (rc)
589 			goto out;
590 	} else {
591 		rc = PKCS11_CKR_MECHANISM_INVALID;
592 		goto out;
593 	}
594 
595 	rc = set_key_data(&head, out_buf, out_size);
596 	if (rc)
597 		goto out;
598 
599 	TEE_Free(out_buf);
600 	out_buf = NULL;
601 
602 	TEE_Free(proc_params);
603 	proc_params = NULL;
604 
605 	/*
606 	 * Object is ready, register it and return a handle.
607 	 */
608 	rc = create_object(session, head, &obj_handle);
609 	if (rc)
610 		goto out;
611 
612 	/*
613 	 * Now obj_handle (through the related struct pkcs11_object instance)
614 	 * owns the serialized buffer that holds the object attributes.
615 	 * We reset head to NULL as it is no more the buffer owner and would
616 	 * be freed at function out.
617 	 */
618 	head = NULL;
619 
620 	TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
621 	out->memref.size = sizeof(obj_handle);
622 
623 	DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32,
624 	     session->handle, obj_handle);
625 
626 out:
627 	release_active_processing(session);
628 out_free:
629 	TEE_Free(proc_params);
630 	TEE_Free(template);
631 	TEE_Free(head);
632 	TEE_Free(out_buf);
633 
634 	return rc;
635 }
636