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