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
get_ready_session(struct pkcs11_session * session)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
func_for_cmd(enum pkcs11_ta_cmd cmd)30 static enum processing_func func_for_cmd(enum pkcs11_ta_cmd cmd)
31 {
32 switch (cmd) {
33 case PKCS11_CMD_ENCRYPT_UPDATE:
34 case PKCS11_CMD_ENCRYPT_ONESHOT:
35 case PKCS11_CMD_ENCRYPT_FINAL:
36 return PKCS11_FUNCTION_ENCRYPT;
37 case PKCS11_CMD_DECRYPT_UPDATE:
38 case PKCS11_CMD_DECRYPT_ONESHOT:
39 case PKCS11_CMD_DECRYPT_FINAL:
40 return PKCS11_FUNCTION_DECRYPT;
41 case PKCS11_CMD_SIGN_ONESHOT:
42 case PKCS11_CMD_SIGN_UPDATE:
43 case PKCS11_CMD_SIGN_FINAL:
44 return PKCS11_FUNCTION_SIGN;
45 case PKCS11_CMD_VERIFY_ONESHOT:
46 case PKCS11_CMD_VERIFY_UPDATE:
47 case PKCS11_CMD_VERIFY_FINAL:
48 return PKCS11_FUNCTION_VERIFY;
49 case PKCS11_CMD_DIGEST_UPDATE:
50 case PKCS11_CMD_DIGEST_KEY:
51 case PKCS11_CMD_DIGEST_ONESHOT:
52 case PKCS11_CMD_DIGEST_FINAL:
53 return PKCS11_FUNCTION_DIGEST;
54 default:
55 return PKCS11_FUNCTION_UNKNOWN;
56 }
57 }
58
func_matches_state(enum processing_func function,enum pkcs11_proc_state state)59 static bool func_matches_state(enum processing_func function,
60 enum pkcs11_proc_state state)
61 {
62 switch (function) {
63 case PKCS11_FUNCTION_ENCRYPT:
64 return state == PKCS11_SESSION_ENCRYPTING ||
65 state == PKCS11_SESSION_DIGESTING_ENCRYPTING ||
66 state == PKCS11_SESSION_SIGNING_ENCRYPTING;
67 case PKCS11_FUNCTION_DECRYPT:
68 return state == PKCS11_SESSION_DECRYPTING ||
69 state == PKCS11_SESSION_DECRYPTING_DIGESTING ||
70 state == PKCS11_SESSION_DECRYPTING_VERIFYING;
71 case PKCS11_FUNCTION_DIGEST:
72 return state == PKCS11_SESSION_DIGESTING ||
73 state == PKCS11_SESSION_DIGESTING_ENCRYPTING;
74 case PKCS11_FUNCTION_SIGN:
75 return state == PKCS11_SESSION_SIGNING ||
76 state == PKCS11_SESSION_SIGNING_ENCRYPTING;
77 case PKCS11_FUNCTION_VERIFY:
78 return state == PKCS11_SESSION_VERIFYING ||
79 state == PKCS11_SESSION_DECRYPTING_VERIFYING;
80 case PKCS11_FUNCTION_SIGN_RECOVER:
81 return state == PKCS11_SESSION_SIGNING_RECOVER;
82 case PKCS11_FUNCTION_VERIFY_RECOVER:
83 return state == PKCS11_SESSION_SIGNING_RECOVER;
84 default:
85 TEE_Panic(function);
86 return false;
87 }
88 }
89
get_active_session(struct pkcs11_session * session,enum processing_func function)90 static enum pkcs11_rc get_active_session(struct pkcs11_session *session,
91 enum processing_func function)
92 {
93 enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED;
94
95 if (session->processing &&
96 func_matches_state(function, session->processing->state))
97 rc = PKCS11_CKR_OK;
98
99 return rc;
100 }
101
release_active_processing(struct pkcs11_session * session)102 void release_active_processing(struct pkcs11_session *session)
103 {
104 if (!session->processing)
105 return;
106
107 if (session->processing->tee_hash_op_handle != TEE_HANDLE_NULL) {
108 TEE_FreeOperation(session->processing->tee_hash_op_handle);
109 session->processing->tee_hash_op_handle = TEE_HANDLE_NULL;
110 session->processing->tee_hash_algo = 0;
111 }
112
113 if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
114 TEE_FreeOperation(session->processing->tee_op_handle);
115 session->processing->tee_op_handle = TEE_HANDLE_NULL;
116 }
117
118 TEE_Free(session->processing->extra_ctx);
119
120 TEE_Free(session->processing);
121 session->processing = NULL;
122 }
123
get_object_key_bit_size(struct pkcs11_object * obj)124 size_t get_object_key_bit_size(struct pkcs11_object *obj)
125 {
126 void *a_ptr = NULL;
127 uint32_t a_size = 0;
128 struct obj_attrs *attrs = obj->attributes;
129
130 switch (get_key_type(attrs)) {
131 case PKCS11_CKK_AES:
132 case PKCS11_CKK_GENERIC_SECRET:
133 case PKCS11_CKK_MD5_HMAC:
134 case PKCS11_CKK_SHA_1_HMAC:
135 case PKCS11_CKK_SHA224_HMAC:
136 case PKCS11_CKK_SHA256_HMAC:
137 case PKCS11_CKK_SHA384_HMAC:
138 case PKCS11_CKK_SHA512_HMAC:
139 if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size))
140 return 0;
141
142 return a_size * 8;
143 case PKCS11_CKK_RSA:
144 if (get_attribute_ptr(attrs, PKCS11_CKA_MODULUS, NULL, &a_size))
145 return 0;
146
147 return a_size * 8;
148 case PKCS11_CKK_EC:
149 if (get_attribute_ptr(attrs, PKCS11_CKA_EC_PARAMS,
150 &a_ptr, &a_size) || !a_ptr)
151 return 0;
152
153 return ec_params2tee_keysize(a_ptr, a_size);
154 default:
155 TEE_Panic(0);
156 return 0;
157 }
158 }
159
generate_random_key_value(struct obj_attrs ** head)160 static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
161 {
162 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
163 void *data = NULL;
164 uint32_t data_size = 0;
165 uint32_t value_len = 0;
166 void *value = NULL;
167
168 if (!*head)
169 return PKCS11_CKR_TEMPLATE_INCONSISTENT;
170
171 rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size);
172 if (rc || data_size != sizeof(uint32_t)) {
173 DMSG("%s", rc ? "No attribute value_len found" :
174 "Invalid size for attribute VALUE_LEN");
175
176 return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
177 }
178 TEE_MemMove(&value_len, data, data_size);
179
180 /* Remove the default empty value attribute if found */
181 rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
182 if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
183 return PKCS11_CKR_GENERAL_ERROR;
184
185 value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
186 if (!value)
187 return PKCS11_CKR_DEVICE_MEMORY;
188
189 TEE_GenerateRandom(value, value_len);
190
191 rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
192
193 TEE_Free(value);
194
195 return rc;
196 }
197
entry_generate_secret(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)198 enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
199 uint32_t ptypes, TEE_Param *params)
200 {
201 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
202 TEE_PARAM_TYPE_NONE,
203 TEE_PARAM_TYPE_MEMREF_OUTPUT,
204 TEE_PARAM_TYPE_NONE);
205 TEE_Param *ctrl = params;
206 TEE_Param *out = params + 2;
207 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
208 struct serialargs ctrlargs = { };
209 struct pkcs11_session *session = NULL;
210 struct pkcs11_attribute_head *proc_params = NULL;
211 struct obj_attrs *head = NULL;
212 struct pkcs11_object_head *template = NULL;
213 size_t template_size = 0;
214 uint32_t obj_handle = 0;
215
216 if (!client || ptypes != exp_pt ||
217 out->memref.size != sizeof(obj_handle))
218 return PKCS11_CKR_ARGUMENTS_BAD;
219
220 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
221
222 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
223 if (rc)
224 return rc;
225
226 rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
227 if (rc)
228 goto out;
229
230 rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
231 if (rc)
232 goto out;
233
234 if (serialargs_remaining_bytes(&ctrlargs)) {
235 rc = PKCS11_CKR_ARGUMENTS_BAD;
236 goto out;
237 }
238
239 rc = get_ready_session(session);
240 if (rc)
241 goto out;
242
243 template_size = sizeof(*template) + template->attrs_size;
244
245 rc = check_mechanism_against_processing(session, proc_params->id,
246 PKCS11_FUNCTION_GENERATE,
247 PKCS11_FUNC_STEP_INIT);
248 if (rc) {
249 DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
250 goto out;
251 }
252
253 /*
254 * Prepare a clean initial state for the requested object attributes.
255 * Free temporary template once done.
256 */
257 rc = create_attributes_from_template(&head, template, template_size,
258 NULL, PKCS11_FUNCTION_GENERATE,
259 proc_params->id,
260 PKCS11_CKO_UNDEFINED_ID);
261 if (rc)
262 goto out;
263
264 TEE_Free(template);
265 template = NULL;
266
267 rc = check_created_attrs(head, NULL);
268 if (rc)
269 goto out;
270
271 rc = check_created_attrs_against_processing(proc_params->id, head);
272 if (rc)
273 goto out;
274
275 rc = check_created_attrs_against_token(session, head);
276 if (rc)
277 goto out;
278
279 /*
280 * Execute target processing and add value as attribute
281 * PKCS11_CKA_VALUE. Symm key generation: depends on target
282 * processing to be used.
283 */
284 switch (proc_params->id) {
285 case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
286 case PKCS11_CKM_AES_KEY_GEN:
287 /* Generate random of size specified by attribute VALUE_LEN */
288 rc = generate_random_key_value(&head);
289 if (rc)
290 goto out;
291 break;
292
293 default:
294 rc = PKCS11_CKR_MECHANISM_INVALID;
295 goto out;
296 }
297
298 TEE_Free(proc_params);
299 proc_params = NULL;
300
301 /*
302 * Object is ready, register it and return a handle.
303 */
304 rc = create_object(session, head, &obj_handle);
305 if (rc)
306 goto out;
307
308 /*
309 * Now obj_handle (through the related struct pkcs11_object instance)
310 * owns the serialized buffer that holds the object attributes.
311 * We reset head to NULL as it is no more the buffer owner and would
312 * be freed at function out.
313 */
314 head = NULL;
315
316 TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
317 out->memref.size = sizeof(obj_handle);
318
319 DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
320 session->handle, obj_handle);
321
322 out:
323 TEE_Free(proc_params);
324 TEE_Free(template);
325 TEE_Free(head);
326
327 return rc;
328 }
329
alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj,uint32_t attribute,void ** data,size_t * size)330 enum pkcs11_rc alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj,
331 uint32_t attribute,
332 void **data, size_t *size)
333 {
334 TEE_Result res = TEE_ERROR_GENERIC;
335 void *ptr = NULL;
336 uint32_t sz = 0;
337
338 res = TEE_GetObjectBufferAttribute(tee_obj, attribute, NULL, &sz);
339 if (res != TEE_ERROR_SHORT_BUFFER)
340 return PKCS11_CKR_FUNCTION_FAILED;
341
342 ptr = TEE_Malloc(sz, TEE_USER_MEM_HINT_NO_FILL_ZERO);
343 if (!ptr)
344 return PKCS11_CKR_DEVICE_MEMORY;
345
346 res = TEE_GetObjectBufferAttribute(tee_obj, attribute, ptr, &sz);
347 if (res) {
348 TEE_Free(ptr);
349 } else {
350 *data = ptr;
351 *size = sz;
352 }
353
354 return tee2pkcs_error(res);
355 }
356
tee2pkcs_add_attribute(struct obj_attrs ** head,uint32_t pkcs11_id,TEE_ObjectHandle tee_obj,uint32_t tee_id)357 enum pkcs11_rc tee2pkcs_add_attribute(struct obj_attrs **head,
358 uint32_t pkcs11_id,
359 TEE_ObjectHandle tee_obj,
360 uint32_t tee_id)
361 {
362 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
363 void *a_ptr = NULL;
364 size_t a_size = 0;
365
366 rc = alloc_get_tee_attribute_data(tee_obj, tee_id, &a_ptr, &a_size);
367 if (rc)
368 goto out;
369
370 rc = add_attribute(head, pkcs11_id, a_ptr, a_size);
371
372 TEE_Free(a_ptr);
373
374 out:
375 if (rc)
376 EMSG("Failed TEE attribute %#"PRIx32" for %#"PRIx32"/%s",
377 tee_id, pkcs11_id, id2str_attr(pkcs11_id));
378 return rc;
379 }
380
entry_generate_key_pair(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)381 enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client,
382 uint32_t ptypes, TEE_Param *params)
383 {
384 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
385 TEE_PARAM_TYPE_NONE,
386 TEE_PARAM_TYPE_MEMREF_OUTPUT,
387 TEE_PARAM_TYPE_NONE);
388 TEE_Param *ctrl = params;
389 TEE_Param *out = params + 2;
390 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
391 struct serialargs ctrlargs = { };
392 struct pkcs11_session *session = NULL;
393 struct pkcs11_attribute_head *proc_params = NULL;
394 struct obj_attrs *pub_head = NULL;
395 struct obj_attrs *priv_head = NULL;
396 struct pkcs11_object_head *pub_template = NULL;
397 struct pkcs11_object_head *priv_template = NULL;
398 struct pkcs11_object *object = NULL;
399 size_t pub_template_size = 0;
400 size_t priv_template_size = 0;
401 uint32_t pubkey_handle = 0;
402 uint32_t privkey_handle = 0;
403 uint32_t *hdl_ptr = NULL;
404 size_t out_ref_size = sizeof(pubkey_handle) + sizeof(privkey_handle);
405
406 if (!client || ptypes != exp_pt || out->memref.size != out_ref_size)
407 return PKCS11_CKR_ARGUMENTS_BAD;
408
409 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
410
411 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
412 if (rc)
413 return rc;
414
415 rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
416 if (rc)
417 goto out;
418
419 rc = serialargs_alloc_get_attributes(&ctrlargs, &pub_template);
420 if (rc)
421 goto out;
422
423 rc = serialargs_alloc_get_attributes(&ctrlargs, &priv_template);
424 if (rc)
425 goto out;
426
427 if (serialargs_remaining_bytes(&ctrlargs)) {
428 rc = PKCS11_CKR_ARGUMENTS_BAD;
429 goto out;
430 }
431
432 rc = get_ready_session(session);
433 if (rc)
434 goto out;
435
436 rc = check_mechanism_against_processing(session, proc_params->id,
437 PKCS11_FUNCTION_GENERATE_PAIR,
438 PKCS11_FUNC_STEP_INIT);
439 if (rc)
440 goto out;
441
442 pub_template_size = sizeof(*pub_template) + pub_template->attrs_size;
443
444 rc = create_attributes_from_template(&pub_head, pub_template,
445 pub_template_size, NULL,
446 PKCS11_FUNCTION_GENERATE_PAIR,
447 proc_params->id,
448 PKCS11_CKO_PUBLIC_KEY);
449 if (rc)
450 goto out;
451
452 TEE_Free(pub_template);
453 pub_template = NULL;
454
455 priv_template_size = sizeof(*priv_template) +
456 priv_template->attrs_size;
457
458 rc = create_attributes_from_template(&priv_head, priv_template,
459 priv_template_size, NULL,
460 PKCS11_FUNCTION_GENERATE_PAIR,
461 proc_params->id,
462 PKCS11_CKO_PRIVATE_KEY);
463 if (rc)
464 goto out;
465
466 TEE_Free(priv_template);
467 priv_template = NULL;
468
469 /* Generate CKA_ID for keys if not specified by the templates */
470 rc = add_missing_attribute_id(&pub_head, &priv_head);
471 if (rc)
472 goto out;
473
474 /* Check created object against processing and token state */
475 rc = check_created_attrs(pub_head, priv_head);
476 if (rc)
477 goto out;
478
479 rc = check_created_attrs_against_processing(proc_params->id, pub_head);
480 if (rc)
481 goto out;
482
483 rc = check_created_attrs_against_processing(proc_params->id,
484 priv_head);
485 if (rc)
486 goto out;
487
488 rc = check_created_attrs_against_token(session, pub_head);
489 if (rc)
490 goto out;
491
492 rc = check_access_attrs_against_token(session, pub_head);
493 if (rc)
494 goto out;
495
496 rc = check_created_attrs_against_token(session, priv_head);
497 if (rc)
498 goto out;
499
500 rc = check_access_attrs_against_token(session, priv_head);
501 if (rc)
502 goto out;
503
504 /* Generate key pair */
505 switch (proc_params->id) {
506 case PKCS11_CKM_EC_KEY_PAIR_GEN:
507 rc = generate_ec_keys(proc_params, &pub_head, &priv_head);
508 break;
509 case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
510 rc = generate_rsa_keys(proc_params, &pub_head, &priv_head);
511 break;
512 default:
513 rc = PKCS11_CKR_MECHANISM_INVALID;
514 break;
515 }
516 if (rc)
517 goto out;
518
519 TEE_Free(proc_params);
520 proc_params = NULL;
521
522 /*
523 * Object is ready, register it and return a handle.
524 */
525 rc = create_object(session, pub_head, &pubkey_handle);
526 if (rc)
527 goto out;
528
529 /*
530 * Now obj_handle (through the related struct pkcs11_object instance)
531 * owns the serialized buffer that holds the object attributes.
532 * We reset local pub_head to NULL to mark that ownership has been
533 * transferred.
534 */
535 pub_head = NULL;
536
537 rc = create_object(session, priv_head, &privkey_handle);
538 if (rc)
539 goto out;
540
541 /* Ownership has been transferred so mark it with NULL */
542 priv_head = NULL;
543
544 hdl_ptr = (uint32_t *)out->memref.buffer;
545
546 TEE_MemMove(hdl_ptr, &pubkey_handle, sizeof(pubkey_handle));
547 TEE_MemMove(hdl_ptr + 1, &privkey_handle, sizeof(privkey_handle));
548
549 pubkey_handle = 0;
550 privkey_handle = 0;
551
552 DMSG("PKCS11 session %"PRIu32": create key pair %#"PRIx32"/%#"PRIx32,
553 session->handle, privkey_handle, pubkey_handle);
554
555 out:
556 if (pubkey_handle) {
557 object = pkcs11_handle2object(pubkey_handle, session);
558 if (!object)
559 TEE_Panic(0);
560 destroy_object(session, object, false);
561 }
562 TEE_Free(priv_head);
563 TEE_Free(pub_head);
564 TEE_Free(priv_template);
565 TEE_Free(pub_template);
566 TEE_Free(proc_params);
567
568 return rc;
569 }
570
571 /*
572 * entry_processing_init - Generic entry for initializing a processing
573 *
574 * @client = client reference
575 * @ptype = Invocation parameter types
576 * @params = Invocation parameters reference
577 * @function - encrypt, decrypt, sign, verify, digest, ...
578 */
entry_processing_init(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params,enum processing_func function)579 enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
580 uint32_t ptypes, TEE_Param *params,
581 enum processing_func function)
582 {
583 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
584 TEE_PARAM_TYPE_NONE,
585 TEE_PARAM_TYPE_NONE,
586 TEE_PARAM_TYPE_NONE);
587 TEE_Param *ctrl = params;
588 enum pkcs11_rc rc = PKCS11_CKR_OK;
589 struct serialargs ctrlargs = { };
590 struct pkcs11_session *session = NULL;
591 struct pkcs11_attribute_head *proc_params = NULL;
592 uint32_t key_handle = 0;
593 struct pkcs11_object *obj = NULL;
594
595 if (!client || ptypes != exp_pt)
596 return PKCS11_CKR_ARGUMENTS_BAD;
597
598 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
599
600 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
601 if (rc)
602 return rc;
603
604 if (function != PKCS11_FUNCTION_DIGEST) {
605 rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
606 if (rc)
607 return rc;
608 }
609
610 rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
611 if (rc)
612 return rc;
613
614 if (serialargs_remaining_bytes(&ctrlargs)) {
615 rc = PKCS11_CKR_ARGUMENTS_BAD;
616 goto out_free;
617 }
618
619 rc = get_ready_session(session);
620 if (rc)
621 goto out_free;
622
623 if (function != PKCS11_FUNCTION_DIGEST) {
624 obj = pkcs11_handle2object(key_handle, session);
625 if (!obj) {
626 rc = PKCS11_CKR_KEY_HANDLE_INVALID;
627 goto out_free;
628 }
629 }
630
631 rc = set_processing_state(session, function, obj, NULL);
632 if (rc)
633 goto out;
634
635 rc = check_mechanism_against_processing(session, proc_params->id,
636 function,
637 PKCS11_FUNC_STEP_INIT);
638 if (rc)
639 goto out;
640
641 if (obj) {
642 rc = check_parent_attrs_against_processing(proc_params->id,
643 function,
644 obj->attributes);
645 if (rc)
646 goto out;
647
648 rc = check_access_attrs_against_token(session,
649 obj->attributes);
650 if (rc)
651 goto out;
652 }
653
654 if (processing_is_tee_symm(proc_params->id))
655 rc = init_symm_operation(session, function, proc_params, obj);
656 else if (processing_is_tee_asymm(proc_params->id))
657 rc = init_asymm_operation(session, function, proc_params, obj);
658 else if (processing_is_tee_digest(proc_params->id))
659 rc = init_digest_operation(session, proc_params);
660 else
661 rc = PKCS11_CKR_MECHANISM_INVALID;
662
663 if (rc == PKCS11_CKR_OK) {
664 session->processing->mecha_type = proc_params->id;
665 DMSG("PKCS11 session %"PRIu32": init processing %s %s",
666 session->handle, id2str_proc(proc_params->id),
667 id2str_function(function));
668 }
669
670 out:
671 if (rc)
672 release_active_processing(session);
673 out_free:
674 TEE_Free(proc_params);
675
676 return rc;
677 }
678
679 /*
680 * entry_processing_step - Generic entry on active processing
681 *
682 * @client = client reference
683 * @ptype = Invocation parameter types
684 * @params = Invocation parameters reference
685 * @function - encrypt, decrypt, sign, verify, digest, ...
686 * @step - update, oneshot, final
687 */
entry_processing_step(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params,enum processing_func function,enum processing_step step)688 enum pkcs11_rc entry_processing_step(struct pkcs11_client *client,
689 uint32_t ptypes, TEE_Param *params,
690 enum processing_func function,
691 enum processing_step step)
692 {
693 TEE_Param *ctrl = params;
694 enum pkcs11_rc rc = PKCS11_CKR_OK;
695 struct serialargs ctrlargs = { };
696 struct pkcs11_session *session = NULL;
697 enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID;
698 uint32_t key_handle = 0;
699 struct pkcs11_object *obj = NULL;
700
701 if (!client ||
702 TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT)
703 return PKCS11_CKR_ARGUMENTS_BAD;
704
705 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
706
707 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
708 if (rc)
709 return rc;
710
711 if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
712 assert(function == PKCS11_FUNCTION_DIGEST);
713
714 rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
715 if (rc)
716 return rc;
717 }
718
719 if (serialargs_remaining_bytes(&ctrlargs))
720 return PKCS11_CKR_ARGUMENTS_BAD;
721
722 rc = get_active_session(session, function);
723 if (rc)
724 return rc;
725
726 if (step == PKCS11_FUNC_STEP_UPDATE_KEY) {
727 assert(function == PKCS11_FUNCTION_DIGEST);
728
729 obj = pkcs11_handle2object(key_handle, session);
730 if (!obj) {
731 rc = PKCS11_CKR_KEY_HANDLE_INVALID;
732 goto out;
733 }
734
735 rc = check_access_attrs_against_token(session,
736 obj->attributes);
737 if (rc) {
738 rc = PKCS11_CKR_KEY_HANDLE_INVALID;
739 goto out;
740 }
741 }
742
743 mecha_type = session->processing->mecha_type;
744 rc = check_mechanism_against_processing(session, mecha_type,
745 function, step);
746 if (rc)
747 goto out;
748
749 if (processing_is_tee_symm(mecha_type))
750 rc = step_symm_operation(session, function, step,
751 ptypes, params);
752 else if (processing_is_tee_asymm(mecha_type))
753 rc = step_asymm_operation(session, function, step,
754 ptypes, params);
755 else if (processing_is_tee_digest(mecha_type))
756 rc = step_digest_operation(session, step, obj, ptypes, params);
757 else
758 rc = PKCS11_CKR_MECHANISM_INVALID;
759
760 if (rc == PKCS11_CKR_OK && (step == PKCS11_FUNC_STEP_UPDATE ||
761 step == PKCS11_FUNC_STEP_UPDATE_KEY)) {
762 session->processing->step = PKCS11_FUNC_STEP_UPDATE;
763 DMSG("PKCS11 session%"PRIu32": processing %s %s",
764 session->handle, id2str_proc(mecha_type),
765 id2str_function(function));
766 }
767
768 if (rc == PKCS11_CKR_BUFFER_TOO_SMALL &&
769 step == PKCS11_FUNC_STEP_ONESHOT)
770 session->processing->step = PKCS11_FUNC_STEP_ONESHOT;
771
772 if (rc == PKCS11_CKR_BUFFER_TOO_SMALL && step == PKCS11_FUNC_STEP_FINAL)
773 session->processing->step = PKCS11_FUNC_STEP_FINAL;
774
775 out:
776 switch (step) {
777 case PKCS11_FUNC_STEP_UPDATE:
778 case PKCS11_FUNC_STEP_UPDATE_KEY:
779 if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
780 release_active_processing(session);
781 break;
782 default:
783 /* ONESHOT and FINAL terminates processing on success */
784 if (rc != PKCS11_CKR_BUFFER_TOO_SMALL)
785 release_active_processing(session);
786 break;
787 }
788
789 return rc;
790 }
791
entry_processing_key(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params,enum processing_func function)792 enum pkcs11_rc entry_processing_key(struct pkcs11_client *client,
793 uint32_t ptypes, TEE_Param *params,
794 enum processing_func function)
795 {
796 TEE_Param *ctrl = params;
797 TEE_Param *out = params + 2;
798 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
799 struct serialargs ctrlargs = { };
800 struct pkcs11_session *session = NULL;
801 struct pkcs11_attribute_head *proc_params = NULL;
802 struct pkcs11_object_head *template = NULL;
803 uint32_t parent_handle = 0;
804 uint32_t obj_handle = 0;
805 struct pkcs11_object *parent = NULL;
806 struct obj_attrs *head = NULL;
807 size_t template_size = 0;
808 void *in_buf = NULL;
809 uint32_t in_size = 0;
810 void *out_buf = NULL;
811 uint32_t out_size = 0;
812 enum processing_func operation = PKCS11_FUNCTION_UNKNOWN;
813
814 if (!client ||
815 TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT ||
816 TEE_PARAM_TYPE_GET(ptypes, 2) != TEE_PARAM_TYPE_MEMREF_OUTPUT ||
817 out->memref.size != sizeof(obj_handle) ||
818 TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
819 return PKCS11_CKR_ARGUMENTS_BAD;
820
821 switch (function) {
822 case PKCS11_FUNCTION_UNWRAP:
823 if (TEE_PARAM_TYPE_GET(ptypes, 1) !=
824 TEE_PARAM_TYPE_MEMREF_INPUT)
825 return PKCS11_CKR_ARGUMENTS_BAD;
826
827 in_buf = params[1].memref.buffer;
828 in_size = params[1].memref.size;
829 if (in_size && !in_buf)
830 return PKCS11_CKR_ARGUMENTS_BAD;
831
832 /*
833 * Some unwrap mechanisms require encryption to be
834 * performed on the data passed in proc_params by parent
835 * key. Hence set operation as PKCS11_FUNCTION_DECRYPT
836 * to be used with init_symm_operation()
837 */
838 operation = PKCS11_FUNCTION_DECRYPT;
839 break;
840 case PKCS11_FUNCTION_DERIVE:
841 if (TEE_PARAM_TYPE_GET(ptypes, 1) != TEE_PARAM_TYPE_NONE)
842 return PKCS11_CKR_ARGUMENTS_BAD;
843
844 /*
845 * Some derivation mechanism require encryption to be
846 * performed on the data passed in proc_params by parent
847 * key. Hence set operation as PKCS11_FUNCTION_ENCRYPT
848 * to be used with init_symm_operation()
849 */
850 operation = PKCS11_FUNCTION_ENCRYPT;
851 break;
852 default:
853 return PKCS11_CKR_ARGUMENTS_BAD;
854 }
855
856 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
857
858 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
859 if (rc)
860 return rc;
861
862 rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t));
863 if (rc)
864 return rc;
865
866 rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
867 if (rc)
868 return rc;
869
870 rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
871 if (rc)
872 goto out_free;
873
874 if (serialargs_remaining_bytes(&ctrlargs)) {
875 rc = PKCS11_CKR_ARGUMENTS_BAD;
876 goto out_free;
877 }
878
879 /* Return error if processing already active */
880 rc = get_ready_session(session);
881 if (rc)
882 goto out_free;
883
884 /* Check parent handle */
885 parent = pkcs11_handle2object(parent_handle, session);
886 if (!parent) {
887 rc = PKCS11_CKR_KEY_HANDLE_INVALID;
888 goto out_free;
889 }
890
891 /* Check if mechanism can be used for derivation function */
892 rc = check_mechanism_against_processing(session, proc_params->id,
893 function,
894 PKCS11_FUNC_STEP_INIT);
895 if (rc)
896 goto out_free;
897
898 /* Set the processing state to active */
899 rc = set_processing_state(session, function, parent, NULL);
900 if (rc)
901 goto out_free;
902
903 /*
904 * Check if base/parent key has CKA_DERIVE set and its key type is
905 * compatible with the mechanism passed
906 */
907 rc = check_parent_attrs_against_processing(proc_params->id, function,
908 parent->attributes);
909 if (rc) {
910 /*
911 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
912 * specified with C_Derive/Unwrap() in the specification. So
913 * return the next most appropriate error.
914 */
915 if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) {
916 if (function == PKCS11_FUNCTION_UNWRAP)
917 rc =
918 PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
919 else
920 rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT;
921 }
922 goto out;
923 }
924
925 /* Check access of base/parent key */
926 rc = check_access_attrs_against_token(session, parent->attributes);
927 if (rc)
928 goto out;
929
930 template_size = sizeof(*template) + template->attrs_size;
931 /*
932 * Prepare a clean initial state for the requested object attributes
933 * using base/parent key attributes. Free temporary template once done.
934 */
935 rc = create_attributes_from_template(&head, template, template_size,
936 parent->attributes,
937 function,
938 proc_params->id,
939 PKCS11_CKO_UNDEFINED_ID);
940 if (rc)
941 goto out;
942
943 TEE_Free(template);
944 template = NULL;
945
946 /* check_created_attrs() is called later once key size is known */
947
948 rc = check_created_attrs_against_processing(proc_params->id, head);
949 if (rc)
950 goto out;
951
952 rc = check_created_attrs_against_token(session, head);
953 if (rc)
954 goto out;
955
956 rc = check_access_attrs_against_token(session, head);
957 if (rc)
958 goto out;
959
960 if (processing_is_tee_symm(proc_params->id)) {
961 rc = init_symm_operation(session, operation, proc_params,
962 parent);
963 if (rc)
964 goto out;
965
966 session->processing->mecha_type = proc_params->id;
967
968 switch (function) {
969 case PKCS11_FUNCTION_DERIVE:
970 rc = derive_key_by_symm_enc(session, &out_buf,
971 &out_size);
972 break;
973 case PKCS11_FUNCTION_UNWRAP:
974 rc = unwrap_key_by_symm(session, in_buf, in_size,
975 &out_buf, &out_size);
976 break;
977 default:
978 TEE_Panic(function);
979 }
980 if (rc)
981 goto out;
982 } else {
983 rc = PKCS11_CKR_MECHANISM_INVALID;
984 goto out;
985 }
986
987 rc = set_key_data(&head, out_buf, out_size);
988 if (rc)
989 goto out;
990
991 TEE_Free(out_buf);
992 out_buf = NULL;
993
994 TEE_Free(proc_params);
995 proc_params = NULL;
996
997 /*
998 * Object is ready, register it and return a handle.
999 */
1000 rc = create_object(session, head, &obj_handle);
1001 if (rc)
1002 goto out;
1003
1004 /*
1005 * Now obj_handle (through the related struct pkcs11_object instance)
1006 * owns the serialized buffer that holds the object attributes.
1007 * We reset head to NULL as it is no more the buffer owner and would
1008 * be freed at function out.
1009 */
1010 head = NULL;
1011
1012 TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
1013 out->memref.size = sizeof(obj_handle);
1014
1015 DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32,
1016 session->handle, obj_handle);
1017
1018 out:
1019 release_active_processing(session);
1020 out_free:
1021 TEE_Free(proc_params);
1022 TEE_Free(template);
1023 TEE_Free(head);
1024 TEE_Free(out_buf);
1025
1026 return rc;
1027 }
1028
entry_release_active_processing(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)1029 enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client,
1030 uint32_t ptypes,
1031 TEE_Param *params)
1032 {
1033 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1034 TEE_PARAM_TYPE_NONE,
1035 TEE_PARAM_TYPE_NONE,
1036 TEE_PARAM_TYPE_NONE);
1037 TEE_Param *ctrl = params;
1038 enum pkcs11_rc rc = PKCS11_CKR_OK;
1039 struct serialargs ctrlargs = { };
1040 struct pkcs11_session *session = NULL;
1041 enum processing_func function = PKCS11_FUNCTION_UNKNOWN;
1042 uint32_t cmd = 0;
1043
1044 if (!client || ptypes != exp_pt)
1045 return PKCS11_CKR_ARGUMENTS_BAD;
1046
1047 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1048
1049 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1050 if (rc)
1051 return rc;
1052
1053 rc = serialargs_get_u32(&ctrlargs, &cmd);
1054
1055 if (serialargs_remaining_bytes(&ctrlargs))
1056 return PKCS11_CKR_ARGUMENTS_BAD;
1057
1058 function = func_for_cmd(cmd);
1059 if (function == PKCS11_FUNCTION_UNKNOWN)
1060 return PKCS11_CKR_ARGUMENTS_BAD;
1061
1062 rc = get_active_session(session, function);
1063 if (rc)
1064 return rc;
1065
1066 release_active_processing(session);
1067
1068 DMSG("PKCS11 session %"PRIu32": release processing", session->handle);
1069
1070 return PKCS11_CKR_OK;
1071 }
1072
entry_wrap_key(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)1073 enum pkcs11_rc entry_wrap_key(struct pkcs11_client *client,
1074 uint32_t ptypes, TEE_Param *params)
1075 {
1076 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1077 TEE_PARAM_TYPE_NONE,
1078 TEE_PARAM_TYPE_MEMREF_OUTPUT,
1079 TEE_PARAM_TYPE_NONE);
1080 TEE_Param *ctrl = params;
1081 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
1082 struct serialargs ctrlargs = { };
1083 struct pkcs11_session *session = NULL;
1084 struct pkcs11_attribute_head *proc_params = NULL;
1085 struct pkcs11_object *wrapping_key = NULL;
1086 struct pkcs11_object *key = NULL;
1087 void *req_attrs = NULL;
1088 uint32_t wrapping_key_handle = 0;
1089 uint32_t key_handle = 0;
1090 uint32_t size = 0;
1091 void *key_data = NULL;
1092 uint32_t key_sz = 0;
1093 void *out_buf = params[2].memref.buffer;
1094 uint32_t out_size = params[2].memref.size;
1095 const enum processing_func function = PKCS11_FUNCTION_WRAP;
1096
1097 if (!client || ptypes != exp_pt ||
1098 (out_size && !out_buf))
1099 return PKCS11_CKR_ARGUMENTS_BAD;
1100
1101 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1102
1103 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1104 if (rc)
1105 return rc;
1106
1107 rc = serialargs_get(&ctrlargs, &wrapping_key_handle, sizeof(uint32_t));
1108 if (rc)
1109 return rc;
1110
1111 rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t));
1112 if (rc)
1113 return rc;
1114
1115 rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
1116 if (rc)
1117 return rc;
1118
1119 if (serialargs_remaining_bytes(&ctrlargs)) {
1120 rc = PKCS11_CKR_ARGUMENTS_BAD;
1121 goto out_free;
1122 }
1123
1124 rc = get_ready_session(session);
1125 if (rc)
1126 goto out_free;
1127
1128 wrapping_key = pkcs11_handle2object(wrapping_key_handle, session);
1129 if (!wrapping_key) {
1130 rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID;
1131 goto out_free;
1132 }
1133
1134 key = pkcs11_handle2object(key_handle, session);
1135 if (!key) {
1136 rc = PKCS11_CKR_KEY_HANDLE_INVALID;
1137 goto out_free;
1138 }
1139
1140 /*
1141 * The wrapping key and key to be wrapped shouldn't be same.
1142 * PKCS#11 spec doesn't explicitly state that but logically this isn't
1143 * a use case and also acts as an attack vector, so explicitly
1144 * disallow this.
1145 */
1146 if (key == wrapping_key) {
1147 rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID;
1148 goto out_free;
1149 }
1150
1151 rc = set_processing_state(session, function, wrapping_key, NULL);
1152 if (rc)
1153 goto out_free;
1154
1155 /* Check if mechanism can be used for wrapping function */
1156 rc = check_mechanism_against_processing(session, proc_params->id,
1157 function,
1158 PKCS11_FUNC_STEP_INIT);
1159 if (rc)
1160 goto out;
1161
1162 /*
1163 * Check if wrapping key has CKA_WRAP set and its key type is
1164 * compatible with the mechanism passed
1165 */
1166 rc = check_parent_attrs_against_processing(proc_params->id, function,
1167 wrapping_key->attributes);
1168 if (rc) {
1169 /*
1170 * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors
1171 * specified with C_Wrap() in the specification. So
1172 * return the next most appropriate error.
1173 */
1174 if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED)
1175 rc = PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
1176
1177 goto out;
1178 }
1179
1180 /* Check access of wrapping key */
1181 rc = check_access_attrs_against_token(session,
1182 wrapping_key->attributes);
1183 if (rc)
1184 goto out;
1185
1186 switch (get_class(key->attributes)) {
1187 case PKCS11_CKO_SECRET_KEY:
1188 break;
1189 /* Key type not supported as yet */
1190 case PKCS11_CKO_PRIVATE_KEY:
1191 default:
1192 rc = PKCS11_CKR_KEY_NOT_WRAPPABLE;
1193 goto out;
1194 }
1195
1196 /* Check if key to be wrapped is extractable */
1197 if (!get_bool(key->attributes, PKCS11_CKA_EXTRACTABLE)) {
1198 DMSG("Extractable property is false");
1199 rc = PKCS11_CKR_KEY_UNEXTRACTABLE;
1200 goto out;
1201 }
1202
1203 if (get_bool(key->attributes, PKCS11_CKA_WRAP_WITH_TRUSTED) &&
1204 !get_bool(wrapping_key->attributes, PKCS11_CKA_TRUSTED)) {
1205 DMSG("Wrap with trusted not satisfied");
1206 rc = PKCS11_CKR_KEY_NOT_WRAPPABLE;
1207 goto out;
1208 }
1209
1210 rc = check_access_attrs_against_token(session, key->attributes);
1211 if (rc)
1212 goto out;
1213
1214 rc = get_attribute_ptr(wrapping_key->attributes,
1215 PKCS11_CKA_WRAP_TEMPLATE, &req_attrs, &size);
1216 if (rc == PKCS11_CKR_OK && size != 0) {
1217 if (!attributes_match_reference(key->attributes, req_attrs)) {
1218 rc = PKCS11_CKR_KEY_HANDLE_INVALID;
1219 goto out;
1220 }
1221 }
1222
1223 rc = get_key_data_to_wrap(key->attributes, &key_data, &key_sz);
1224 if (rc)
1225 goto out;
1226
1227 if (processing_is_tee_symm(proc_params->id)) {
1228 rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT,
1229 proc_params, wrapping_key);
1230 if (rc)
1231 goto out;
1232
1233 session->processing->mecha_type = proc_params->id;
1234
1235 rc = wrap_data_by_symm_enc(session, key_data, key_sz, out_buf,
1236 &out_size);
1237 } else {
1238 rc = PKCS11_CKR_MECHANISM_INVALID;
1239 }
1240
1241 if (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)
1242 params[2].memref.size = out_size;
1243
1244 out:
1245 release_active_processing(session);
1246 out_free:
1247 TEE_Free(proc_params);
1248 return rc;
1249 }
1250