1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2017-2020, Linaro Limited
4 */
5
6 #include <assert.h>
7 #include <inttypes.h>
8 #include <string_ext.h>
9 #include <tee_internal_api.h>
10 #include <tee_internal_api_extensions.h>
11
12 #include "attributes.h"
13 #include "handle.h"
14 #include "object.h"
15 #include "pkcs11_attributes.h"
16 #include "pkcs11_helpers.h"
17 #include "pkcs11_token.h"
18 #include "sanitize_object.h"
19 #include "serializer.h"
20
21 /*
22 * Temporary list used to register allocated struct pkcs11_object instances
23 * so that destroy_object() can unconditionally remove the object from its
24 * list, being from an object destruction request or because object creation
25 * failed before being completed. Objects are moved to their target list at
26 * creation completion.
27 */
28 LIST_HEAD(temp_obj_list, pkcs11_object) temporary_object_list =
29 LIST_HEAD_INITIALIZER(temp_obj_list);
30
31 static struct ck_token *get_session_token(void *session);
32
pkcs11_handle2object(uint32_t handle,struct pkcs11_session * session)33 struct pkcs11_object *pkcs11_handle2object(uint32_t handle,
34 struct pkcs11_session *session)
35 {
36 struct pkcs11_object *object = NULL;
37
38 object = handle_lookup(get_object_handle_db(session), handle);
39 if (!object)
40 return NULL;
41
42 /*
43 * If object is session only then no extra checks are needed as session
44 * objects has flat access control space
45 */
46 if (!object->token)
47 return object;
48
49 /*
50 * Only allow access to token object if session is associated with
51 * the token
52 */
53 if (object->token != get_session_token(session))
54 return NULL;
55
56 return object;
57 }
58
pkcs11_object2handle(struct pkcs11_object * obj,struct pkcs11_session * session)59 uint32_t pkcs11_object2handle(struct pkcs11_object *obj,
60 struct pkcs11_session *session)
61 {
62 return handle_lookup_handle(get_object_handle_db(session), obj);
63 }
64
65 /* Currently handle pkcs11 sessions and tokens */
66
get_session_objects(void * session)67 static struct object_list *get_session_objects(void *session)
68 {
69 /* Currently supporting only pkcs11 session */
70 struct pkcs11_session *ck_session = session;
71
72 return pkcs11_get_session_objects(ck_session);
73 }
74
get_session_token(void * session)75 static struct ck_token *get_session_token(void *session)
76 {
77 struct pkcs11_session *ck_session = session;
78
79 return pkcs11_session2token(ck_session);
80 }
81
82 /* Release resources of a non-persistent object */
cleanup_volatile_obj_ref(struct pkcs11_object * obj)83 static void cleanup_volatile_obj_ref(struct pkcs11_object *obj)
84 {
85 if (!obj)
86 return;
87
88 LIST_REMOVE(obj, link);
89
90 if (obj->key_handle != TEE_HANDLE_NULL)
91 TEE_FreeTransientObject(obj->key_handle);
92
93 if (obj->attribs_hdl != TEE_HANDLE_NULL)
94 TEE_CloseObject(obj->attribs_hdl);
95
96 TEE_Free(obj->attributes);
97 TEE_Free(obj->uuid);
98 TEE_Free(obj);
99 }
100
101 /* Release resources of a persistent object including volatile resources */
cleanup_persistent_object(struct pkcs11_object * obj,struct ck_token * token)102 void cleanup_persistent_object(struct pkcs11_object *obj,
103 struct ck_token *token)
104 {
105 TEE_Result res = TEE_SUCCESS;
106
107 if (!obj)
108 return;
109
110 /* Open handle with write properties to destroy the object */
111 if (obj->attribs_hdl != TEE_HANDLE_NULL)
112 TEE_CloseObject(obj->attribs_hdl);
113
114 res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
115 obj->uuid, sizeof(TEE_UUID),
116 TEE_DATA_FLAG_ACCESS_WRITE_META,
117 &obj->attribs_hdl);
118 if (!res)
119 TEE_CloseAndDeletePersistentObject1(obj->attribs_hdl);
120
121 obj->attribs_hdl = TEE_HANDLE_NULL;
122 destroy_object_uuid(token, obj);
123
124 cleanup_volatile_obj_ref(obj);
125 }
126
127 /*
128 * destroy_object - destroy an PKCS11 TA object
129 *
130 * @session - session requesting object destruction
131 * @obj - reference to the PKCS11 TA object
132 * @session_only - true if only session object shall be destroyed
133 */
destroy_object(struct pkcs11_session * session,struct pkcs11_object * obj,bool session_only)134 void destroy_object(struct pkcs11_session *session, struct pkcs11_object *obj,
135 bool session_only)
136 {
137 #ifdef DEBUG
138 trace_attributes("[destroy]", obj->attributes);
139 if (obj->uuid)
140 MSG_RAW("[destroy] obj uuid %pUl", (void *)obj->uuid);
141 #endif
142
143 if (session_only) {
144 /* Destroy object due to session closure */
145 handle_put(get_object_handle_db(session),
146 pkcs11_object2handle(obj, session));
147 cleanup_volatile_obj_ref(obj);
148
149 return;
150 }
151
152 /* Destroy target object (persistent or not) */
153 if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
154 assert(obj->uuid);
155 /* Try twice otherwise panic! */
156 if (unregister_persistent_object(session->token, obj->uuid) &&
157 unregister_persistent_object(session->token, obj->uuid))
158 TEE_Panic(0);
159
160 handle_put(get_object_handle_db(session),
161 pkcs11_object2handle(obj, session));
162 cleanup_persistent_object(obj, session->token);
163
164 token_invalidate_object_handles(obj);
165 } else {
166 handle_put(get_object_handle_db(session),
167 pkcs11_object2handle(obj, session));
168 cleanup_volatile_obj_ref(obj);
169 }
170 }
171
create_obj_instance(struct obj_attrs * head,struct ck_token * token)172 static struct pkcs11_object *create_obj_instance(struct obj_attrs *head,
173 struct ck_token *token)
174 {
175 struct pkcs11_object *obj = NULL;
176
177 obj = TEE_Malloc(sizeof(struct pkcs11_object), TEE_MALLOC_FILL_ZERO);
178 if (!obj)
179 return NULL;
180
181 obj->key_handle = TEE_HANDLE_NULL;
182 obj->attribs_hdl = TEE_HANDLE_NULL;
183 obj->attributes = head;
184 obj->token = token;
185
186 return obj;
187 }
188
create_token_object(struct obj_attrs * head,TEE_UUID * uuid,struct ck_token * token)189 struct pkcs11_object *create_token_object(struct obj_attrs *head,
190 TEE_UUID *uuid,
191 struct ck_token *token)
192 {
193 struct pkcs11_object *obj = create_obj_instance(head, token);
194
195 if (obj)
196 obj->uuid = uuid;
197
198 return obj;
199 }
200
201 /*
202 * create_object - create an PKCS11 TA object from its attributes and value
203 *
204 * @sess - session requesting object creation
205 * @head - reference to serialized attributes
206 * @out_handle - generated handle for the created object
207 */
create_object(void * sess,struct obj_attrs * head,uint32_t * out_handle)208 enum pkcs11_rc create_object(void *sess, struct obj_attrs *head,
209 uint32_t *out_handle)
210 {
211 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
212 struct pkcs11_object *obj = NULL;
213 struct pkcs11_session *session = (struct pkcs11_session *)sess;
214 uint32_t obj_handle = 0;
215
216 #ifdef DEBUG
217 trace_attributes("[create]", head);
218 #endif
219
220 /*
221 * We do not check the key attributes. At this point, key attributes
222 * are expected consistent and reliable.
223 */
224
225 obj = create_obj_instance(head, NULL);
226 if (!obj)
227 return PKCS11_CKR_DEVICE_MEMORY;
228
229 LIST_INSERT_HEAD(&temporary_object_list, obj, link);
230
231 /* Create a handle for the object in the session database */
232 obj_handle = handle_get(get_object_handle_db(session), obj);
233 if (!obj_handle) {
234 rc = PKCS11_CKR_DEVICE_MEMORY;
235 goto err;
236 }
237
238 if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
239 TEE_Result res = TEE_SUCCESS;
240
241 /*
242 * Get an ID for the persistent object
243 * Create the file
244 * Register the object in the persistent database
245 * (move the full sequence to persisent_db.c?)
246 */
247 size_t size = sizeof(struct obj_attrs) +
248 obj->attributes->attrs_size;
249 uint32_t tee_obj_flags = TEE_DATA_FLAG_ACCESS_READ |
250 TEE_DATA_FLAG_ACCESS_WRITE |
251 TEE_DATA_FLAG_ACCESS_WRITE_META;
252
253 rc = create_object_uuid(get_session_token(session), obj);
254 if (rc)
255 goto err;
256
257 res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
258 obj->uuid, sizeof(TEE_UUID),
259 tee_obj_flags,
260 TEE_HANDLE_NULL,
261 obj->attributes, size,
262 &obj->attribs_hdl);
263 if (res) {
264 rc = tee2pkcs_error(res);
265 goto err;
266 }
267
268 rc = register_persistent_object(get_session_token(session),
269 obj->uuid);
270 if (rc)
271 goto err;
272
273 TEE_CloseObject(obj->attribs_hdl);
274 obj->attribs_hdl = TEE_HANDLE_NULL;
275
276 /* Move object from temporary list to target token list */
277 LIST_REMOVE(obj, link);
278 LIST_INSERT_HEAD(&session->token->object_list, obj, link);
279 } else {
280 /* Move object from temporary list to target session list */
281 LIST_REMOVE(obj, link);
282 LIST_INSERT_HEAD(get_session_objects(session), obj, link);
283 }
284
285 *out_handle = obj_handle;
286
287 return PKCS11_CKR_OK;
288 err:
289 /* make sure that supplied "head" isn't freed */
290 obj->attributes = NULL;
291 handle_put(get_object_handle_db(session), obj_handle);
292 if (get_bool(head, PKCS11_CKA_TOKEN))
293 cleanup_persistent_object(obj, session->token);
294 else
295 cleanup_volatile_obj_ref(obj);
296
297 return rc;
298 }
299
entry_create_object(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)300 enum pkcs11_rc entry_create_object(struct pkcs11_client *client,
301 uint32_t ptypes, TEE_Param *params)
302 {
303 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
304 TEE_PARAM_TYPE_NONE,
305 TEE_PARAM_TYPE_MEMREF_OUTPUT,
306 TEE_PARAM_TYPE_NONE);
307 enum pkcs11_rc rc = PKCS11_CKR_OK;
308 TEE_Param *ctrl = params;
309 TEE_Param *out = params + 2;
310 struct serialargs ctrlargs = { };
311 struct pkcs11_session *session = NULL;
312 struct obj_attrs *head = NULL;
313 struct pkcs11_object_head *template = NULL;
314 size_t template_size = 0;
315 uint32_t obj_handle = 0;
316
317 /*
318 * Collect the arguments of the request
319 */
320
321 if (!client || ptypes != exp_pt ||
322 out->memref.size != sizeof(obj_handle))
323 return PKCS11_CKR_ARGUMENTS_BAD;
324
325 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
326
327 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
328 if (rc)
329 return rc;
330
331 rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
332 if (rc)
333 return rc;
334
335 if (serialargs_remaining_bytes(&ctrlargs)) {
336 rc = PKCS11_CKR_ARGUMENTS_BAD;
337 goto out;
338 }
339
340 template_size = sizeof(*template) + template->attrs_size;
341
342 /*
343 * Prepare a clean initial state for the requested object attributes.
344 * Free temporary template once done.
345 */
346 rc = create_attributes_from_template(&head, template, template_size,
347 NULL, PKCS11_FUNCTION_IMPORT,
348 PKCS11_PROCESSING_IMPORT,
349 PKCS11_CKO_UNDEFINED_ID);
350 TEE_Free(template);
351 template = NULL;
352 if (rc)
353 goto out;
354
355 /* Set key check value attribute */
356 rc = set_check_value_attr(&head);
357 if (rc)
358 goto out;
359
360 /*
361 * Check target object attributes match target processing
362 * Check target object attributes match token state
363 */
364 rc = check_created_attrs_against_processing(PKCS11_PROCESSING_IMPORT,
365 head);
366 if (rc)
367 goto out;
368
369 rc = check_created_attrs_against_token(session, head);
370 if (rc)
371 goto out;
372
373 rc = check_access_attrs_against_token(session, head);
374 if (rc)
375 goto out;
376
377 /*
378 * At this stage the object is almost created: all its attributes are
379 * referenced in @head, including the key value and are assumed
380 * reliable. Now need to register it and get a handle for it.
381 */
382 rc = create_object(session, head, &obj_handle);
383 if (rc)
384 goto out;
385
386 /*
387 * Now obj_handle (through the related struct pkcs11_object
388 * instance) owns the serialized buffer that holds the object
389 * attributes. We clear reference in head to NULL as the serializer
390 * object is now referred from obj_handle. This allows smooth pass
391 * through free at function exit.
392 */
393 head = NULL;
394
395 TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
396 out->memref.size = sizeof(obj_handle);
397
398 DMSG("PKCS11 session %"PRIu32": import object %#"PRIx32,
399 session->handle, obj_handle);
400
401 out:
402 TEE_Free(template);
403 TEE_Free(head);
404
405 return rc;
406 }
407
entry_destroy_object(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)408 enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client,
409 uint32_t ptypes, TEE_Param *params)
410 {
411 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
412 TEE_PARAM_TYPE_NONE,
413 TEE_PARAM_TYPE_NONE,
414 TEE_PARAM_TYPE_NONE);
415 enum pkcs11_rc rc = PKCS11_CKR_OK;
416 TEE_Param *ctrl = params;
417 struct serialargs ctrlargs = { };
418 uint32_t object_handle = 0;
419 struct pkcs11_session *session = NULL;
420 struct pkcs11_object *object = NULL;
421
422 if (!client || ptypes != exp_pt)
423 return PKCS11_CKR_ARGUMENTS_BAD;
424
425 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
426
427 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
428 if (rc)
429 return rc;
430
431 rc = serialargs_get_u32(&ctrlargs, &object_handle);
432 if (rc)
433 return rc;
434
435 if (serialargs_remaining_bytes(&ctrlargs))
436 return PKCS11_CKR_ARGUMENTS_BAD;
437
438 object = pkcs11_handle2object(object_handle, session);
439 if (!object)
440 return PKCS11_CKR_OBJECT_HANDLE_INVALID;
441
442 /* Only session objects can be destroyed during a read-only session */
443 if (get_bool(object->attributes, PKCS11_CKA_TOKEN) &&
444 !pkcs11_session_is_read_write(session)) {
445 DMSG("Can't destroy persistent object");
446 return PKCS11_CKR_SESSION_READ_ONLY;
447 }
448
449 /*
450 * Only public objects can be destroyed unless normal user is logged in
451 */
452 rc = check_access_attrs_against_token(session, object->attributes);
453 if (rc)
454 return PKCS11_CKR_USER_NOT_LOGGED_IN;
455
456 /* Objects with PKCS11_CKA_DESTROYABLE as false aren't destroyable */
457 if (!get_bool(object->attributes, PKCS11_CKA_DESTROYABLE))
458 return PKCS11_CKR_ACTION_PROHIBITED;
459
460 destroy_object(session, object, false);
461
462 DMSG("PKCS11 session %"PRIu32": destroy object %#"PRIx32,
463 session->handle, object_handle);
464
465 return rc;
466 }
467
release_find_obj_context(struct pkcs11_find_objects * find_ctx)468 static void release_find_obj_context(struct pkcs11_find_objects *find_ctx)
469 {
470 if (!find_ctx)
471 return;
472
473 TEE_Free(find_ctx->attributes);
474 TEE_Free(find_ctx->handles);
475 TEE_Free(find_ctx);
476 }
477
find_ctx_add(struct pkcs11_find_objects * find_ctx,uint32_t handle)478 static enum pkcs11_rc find_ctx_add(struct pkcs11_find_objects *find_ctx,
479 uint32_t handle)
480 {
481 uint32_t *hdls = TEE_Realloc(find_ctx->handles,
482 (find_ctx->count + 1) * sizeof(*hdls));
483
484 if (!hdls)
485 return PKCS11_CKR_DEVICE_MEMORY;
486
487 find_ctx->handles = hdls;
488
489 *(find_ctx->handles + find_ctx->count) = handle;
490 find_ctx->count++;
491
492 return PKCS11_CKR_OK;
493 }
494
entry_find_objects_init(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)495 enum pkcs11_rc entry_find_objects_init(struct pkcs11_client *client,
496 uint32_t ptypes, TEE_Param *params)
497 {
498 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
499 TEE_PARAM_TYPE_NONE,
500 TEE_PARAM_TYPE_NONE,
501 TEE_PARAM_TYPE_NONE);
502 TEE_Param *ctrl = params;
503 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
504 struct serialargs ctrlargs = { };
505 struct pkcs11_session *session = NULL;
506 struct pkcs11_session *sess = NULL;
507 struct pkcs11_object_head *template = NULL;
508 struct obj_attrs *req_attrs = NULL;
509 struct pkcs11_object *obj = NULL;
510 struct pkcs11_find_objects *find_ctx = NULL;
511 struct handle_db *object_db = NULL;
512
513 if (!client || ptypes != exp_pt)
514 return PKCS11_CKR_ARGUMENTS_BAD;
515
516 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
517
518 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
519 if (rc)
520 return rc;
521
522 rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
523 if (rc)
524 return rc;
525
526 if (serialargs_remaining_bytes(&ctrlargs)) {
527 rc = PKCS11_CKR_ARGUMENTS_BAD;
528 goto out;
529 }
530
531 /* Search objects only if no operation is on-going */
532 if (session_is_active(session)) {
533 rc = PKCS11_CKR_OPERATION_ACTIVE;
534 goto out;
535 }
536
537 if (session->find_ctx) {
538 EMSG("Active object search already in progress");
539 rc = PKCS11_CKR_FUNCTION_FAILED;
540 goto out;
541 }
542
543 rc = sanitize_client_object(&req_attrs, template,
544 sizeof(*template) + template->attrs_size,
545 PKCS11_UNDEFINED_ID, PKCS11_UNDEFINED_ID);
546 if (rc)
547 goto out;
548
549 /* Must zero init the structure */
550 find_ctx = TEE_Malloc(sizeof(*find_ctx), TEE_MALLOC_FILL_ZERO);
551 if (!find_ctx) {
552 rc = PKCS11_CKR_DEVICE_MEMORY;
553 goto out;
554 }
555
556 TEE_Free(template);
557 template = NULL;
558
559 switch (get_class(req_attrs)) {
560 case PKCS11_CKO_UNDEFINED_ID:
561 /* Unspecified class searches among data objects */
562 case PKCS11_CKO_SECRET_KEY:
563 case PKCS11_CKO_PUBLIC_KEY:
564 case PKCS11_CKO_PRIVATE_KEY:
565 case PKCS11_CKO_DATA:
566 case PKCS11_CKO_CERTIFICATE:
567 break;
568 default:
569 EMSG("Find object of class %s (%"PRIu32") is not supported",
570 id2str_class(get_class(req_attrs)),
571 get_class(req_attrs));
572 rc = PKCS11_CKR_ARGUMENTS_BAD;
573 goto out;
574 }
575
576 /*
577 * Scan all objects (sessions and persistent ones) and set a list of
578 * candidates that match caller attributes.
579 */
580
581 /* Scan all session objects first */
582 TAILQ_FOREACH(sess, get_session_list(session), link) {
583 LIST_FOREACH(obj, &sess->object_list, link) {
584 /*
585 * Skip all token objects as they could be from
586 * different token which the session does not have
587 * access
588 */
589 if (obj->token)
590 continue;
591
592 if (!attributes_match_reference(obj->attributes,
593 req_attrs))
594 continue;
595
596 rc = find_ctx_add(find_ctx,
597 pkcs11_object2handle(obj, session));
598 if (rc)
599 goto out;
600 }
601 }
602
603 object_db = get_object_handle_db(session);
604
605 /* Scan token objects */
606 LIST_FOREACH(obj, &session->token->object_list, link) {
607 uint32_t handle = 0;
608 bool new_load = false;
609
610 if (!obj->attributes) {
611 rc = load_persistent_object_attributes(obj);
612 if (rc) {
613 rc = PKCS11_CKR_GENERAL_ERROR;
614 goto out;
615 }
616
617 new_load = true;
618 }
619
620 if (!obj->attributes ||
621 check_access_attrs_against_token(session,
622 obj->attributes) ||
623 !attributes_match_reference(obj->attributes, req_attrs)) {
624 if (new_load)
625 release_persistent_object_attributes(obj);
626
627 continue;
628 }
629
630 /* Resolve object handle for object */
631 handle = pkcs11_object2handle(obj, session);
632 if (!handle) {
633 handle = handle_get(object_db, obj);
634 if (!handle) {
635 rc = PKCS11_CKR_DEVICE_MEMORY;
636 goto out;
637 }
638 }
639
640 rc = find_ctx_add(find_ctx, handle);
641 if (rc)
642 goto out;
643 }
644
645 find_ctx->attributes = req_attrs;
646 req_attrs = NULL;
647 session->find_ctx = find_ctx;
648 find_ctx = NULL;
649 rc = PKCS11_CKR_OK;
650
651 out:
652 TEE_Free(req_attrs);
653 TEE_Free(template);
654 release_find_obj_context(find_ctx);
655
656 return rc;
657 }
658
entry_find_objects(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)659 enum pkcs11_rc entry_find_objects(struct pkcs11_client *client,
660 uint32_t ptypes, TEE_Param *params)
661 {
662 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
663 TEE_PARAM_TYPE_NONE,
664 TEE_PARAM_TYPE_MEMREF_OUTPUT,
665 TEE_PARAM_TYPE_NONE);
666 TEE_Param *ctrl = params;
667 TEE_Param *out = params + 2;
668 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
669 struct serialargs ctrlargs = { };
670 struct pkcs11_session *session = NULL;
671 struct pkcs11_find_objects *ctx = NULL;
672 uint8_t *out_handles = NULL;
673 size_t out_count = 0;
674 size_t count = 0;
675
676 if (!client || ptypes != exp_pt)
677 return PKCS11_CKR_ARGUMENTS_BAD;
678
679 out_count = out->memref.size / sizeof(uint32_t);
680 out_handles = out->memref.buffer;
681
682 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
683
684 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
685 if (rc)
686 return rc;
687
688 if (serialargs_remaining_bytes(&ctrlargs))
689 return PKCS11_CKR_ARGUMENTS_BAD;
690
691 ctx = session->find_ctx;
692
693 if (!ctx)
694 return PKCS11_CKR_OPERATION_NOT_INITIALIZED;
695
696 for (count = 0; ctx->next < ctx->count && count < out_count;
697 ctx->next++, count++)
698 TEE_MemMove(out_handles + count * sizeof(uint32_t),
699 ctx->handles + ctx->next, sizeof(uint32_t));
700
701 /* Update output buffer according the number of handles provided */
702 out->memref.size = count * sizeof(uint32_t);
703
704 DMSG("PKCS11 session %"PRIu32": finding objects", session->handle);
705
706 return PKCS11_CKR_OK;
707 }
708
release_session_find_obj_context(struct pkcs11_session * session)709 void release_session_find_obj_context(struct pkcs11_session *session)
710 {
711 release_find_obj_context(session->find_ctx);
712 session->find_ctx = NULL;
713 }
714
entry_find_objects_final(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)715 enum pkcs11_rc entry_find_objects_final(struct pkcs11_client *client,
716 uint32_t ptypes, TEE_Param *params)
717 {
718 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
719 TEE_PARAM_TYPE_NONE,
720 TEE_PARAM_TYPE_NONE,
721 TEE_PARAM_TYPE_NONE);
722 TEE_Param *ctrl = params;
723 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
724 struct serialargs ctrlargs = { };
725 struct pkcs11_session *session = NULL;
726
727 if (!client || ptypes != exp_pt)
728 return PKCS11_CKR_ARGUMENTS_BAD;
729
730 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
731
732 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
733 if (rc)
734 return rc;
735
736 if (serialargs_remaining_bytes(&ctrlargs))
737 return PKCS11_CKR_ARGUMENTS_BAD;
738
739 if (!session->find_ctx)
740 return PKCS11_CKR_OPERATION_NOT_INITIALIZED;
741
742 release_session_find_obj_context(session);
743
744 return PKCS11_CKR_OK;
745 }
746
entry_get_attribute_value(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)747 enum pkcs11_rc entry_get_attribute_value(struct pkcs11_client *client,
748 uint32_t ptypes, TEE_Param *params)
749 {
750 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
751 TEE_PARAM_TYPE_NONE,
752 TEE_PARAM_TYPE_MEMREF_OUTPUT,
753 TEE_PARAM_TYPE_NONE);
754 TEE_Param *ctrl = params;
755 TEE_Param *out = params + 2;
756 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
757 struct serialargs ctrlargs = { };
758 struct pkcs11_session *session = NULL;
759 struct pkcs11_object_head *template = NULL;
760 struct pkcs11_object *obj = NULL;
761 uint32_t object_handle = 0;
762 char *cur = NULL;
763 size_t len = 0;
764 char *end = NULL;
765 bool attr_sensitive = 0;
766 bool attr_type_invalid = 0;
767 bool buffer_too_small = 0;
768
769 if (!client || ptypes != exp_pt)
770 return PKCS11_CKR_ARGUMENTS_BAD;
771
772 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
773
774 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
775 if (rc)
776 return rc;
777
778 rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
779 if (rc)
780 return rc;
781
782 rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
783 if (rc)
784 return rc;
785
786 if (serialargs_remaining_bytes(&ctrlargs)) {
787 rc = PKCS11_CKR_ARGUMENTS_BAD;
788 goto out;
789 }
790
791 obj = pkcs11_handle2object(object_handle, session);
792 if (!obj) {
793 rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
794 goto out;
795 }
796
797 rc = check_access_attrs_against_token(session, obj->attributes);
798 if (rc) {
799 rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
800 goto out;
801 }
802
803 /*
804 * We will update the template with relevant data, without resizing it.
805 * Upon completion, it will be copied to client output buffer.
806 */
807 if (out->memref.size < sizeof(*template) + template->attrs_size) {
808 rc = PKCS11_CKR_ARGUMENTS_BAD;
809 goto out;
810 }
811
812 /* Iterate over attributes and set their values */
813 /*
814 * 1. If the specified attribute (i.e., the attribute specified by the
815 * type field) for the object cannot be revealed because the object is
816 * sensitive or unextractable, then the ulValueLen field in that triple
817 * is modified to hold the value PKCS11_CK_UNAVAILABLE_INFORMATION.
818 *
819 * 2. Otherwise, if the specified value for the object is invalid (the
820 * object does not possess such an attribute), then the ulValueLen field
821 * in that triple is modified to hold the value
822 * PKCS11_CK_UNAVAILABLE_INFORMATION.
823 *
824 * 3. Otherwise, if the pValue field has the value NULL_PTR, then the
825 * ulValueLen field is modified to hold the exact length of the
826 * specified attribute for the object.
827 *
828 * 4. Otherwise, if the length specified in ulValueLen is large enough
829 * to hold the value of the specified attribute for the object, then
830 * that attribute is copied into the buffer located at pValue, and the
831 * ulValueLen field is modified to hold the exact length of the
832 * attribute.
833 *
834 * 5. Otherwise, the ulValueLen field is modified to hold the value
835 * PKCS11_CK_UNAVAILABLE_INFORMATION.
836 */
837 cur = (char *)template + sizeof(struct pkcs11_object_head);
838 end = cur + template->attrs_size;
839
840 for (; cur < end; cur += len) {
841 struct pkcs11_attribute_head *cli_ref = (void *)cur;
842 struct pkcs11_attribute_head cli_head = { };
843 uintptr_t cli_end = 0;
844 void *data_ptr = NULL;
845
846 if ((char *)(cli_ref + 1) > end) {
847 rc = PKCS11_CKR_ARGUMENTS_BAD;
848 goto out;
849 }
850
851 /* Make copy of header so that is aligned properly. */
852 TEE_MemMove(&cli_head, cli_ref, sizeof(cli_head));
853
854 if (ADD_OVERFLOW(sizeof(*cli_ref), cli_head.size, &len) ||
855 ADD_OVERFLOW((uintptr_t)cur, len, &cli_end) ||
856 (char *)cli_end > end) {
857 rc = PKCS11_CKR_ARGUMENTS_BAD;
858 goto out;
859 }
860
861 /* Treat hidden attributes as missing attributes */
862 if (attribute_is_hidden(&cli_head)) {
863 cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION;
864 TEE_MemMove(&cli_ref->size, &cli_head.size,
865 sizeof(cli_head.size));
866 attr_type_invalid = 1;
867 continue;
868 }
869
870 /* We don't support getting value of indirect templates */
871 if (pkcs11_attr_has_indirect_attributes(cli_head.id)) {
872 attr_type_invalid = 1;
873 continue;
874 }
875
876 /* Check 1. */
877 if (!attribute_is_exportable(&cli_head, obj)) {
878 cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION;
879 TEE_MemMove(&cli_ref->size, &cli_head.size,
880 sizeof(cli_head.size));
881 attr_sensitive = 1;
882 continue;
883 }
884
885 /* Get real data pointer from template data */
886 data_ptr = cli_head.size ? cli_ref->data : NULL;
887
888 /*
889 * We assume that if size is 0, pValue was NULL, so we return
890 * the size of the required buffer for it (3., 4.)
891 */
892 rc = get_attribute(obj->attributes, cli_head.id, data_ptr,
893 &cli_head.size);
894 /* Check 2. */
895 switch (rc) {
896 case PKCS11_CKR_OK:
897 break;
898 case PKCS11_RV_NOT_FOUND:
899 cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION;
900 attr_type_invalid = 1;
901 break;
902 case PKCS11_CKR_BUFFER_TOO_SMALL:
903 if (data_ptr) {
904 cli_head.size =
905 PKCS11_CK_UNAVAILABLE_INFORMATION;
906 buffer_too_small = 1;
907 }
908 break;
909 default:
910 rc = PKCS11_CKR_GENERAL_ERROR;
911 goto out;
912 }
913
914 TEE_MemMove(&cli_ref->size, &cli_head.size,
915 sizeof(cli_head.size));
916 }
917
918 /*
919 * If case 1 applies to any of the requested attributes, then the call
920 * should return the value CKR_ATTRIBUTE_SENSITIVE. If case 2 applies to
921 * any of the requested attributes, then the call should return the
922 * value CKR_ATTRIBUTE_TYPE_INVALID. If case 5 applies to any of the
923 * requested attributes, then the call should return the value
924 * CKR_BUFFER_TOO_SMALL. As usual, if more than one of these error codes
925 * is applicable, Cryptoki may return any of them. Only if none of them
926 * applies to any of the requested attributes will CKR_OK be returned.
927 */
928
929 rc = PKCS11_CKR_OK;
930 if (attr_sensitive)
931 rc = PKCS11_CKR_ATTRIBUTE_SENSITIVE;
932 if (attr_type_invalid)
933 rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
934 if (buffer_too_small)
935 rc = PKCS11_CKR_BUFFER_TOO_SMALL;
936
937 /* Move updated template to out buffer */
938 out->memref.size = sizeof(*template) + template->attrs_size;
939 TEE_MemMove(out->memref.buffer, template, out->memref.size);
940
941 DMSG("PKCS11 session %"PRIu32": get attributes %#"PRIx32,
942 session->handle, object_handle);
943
944 out:
945 TEE_Free(template);
946
947 return rc;
948 }
949
entry_get_object_size(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)950 enum pkcs11_rc entry_get_object_size(struct pkcs11_client *client,
951 uint32_t ptypes, TEE_Param *params)
952 {
953 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
954 TEE_PARAM_TYPE_NONE,
955 TEE_PARAM_TYPE_MEMREF_OUTPUT,
956 TEE_PARAM_TYPE_NONE);
957 TEE_Param *ctrl = params;
958 TEE_Param *out = params + 2;
959 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
960 struct serialargs ctrlargs = { };
961 struct pkcs11_session *session = NULL;
962 uint32_t object_handle = 0;
963 struct pkcs11_object *obj = NULL;
964 uint32_t obj_size = 0;
965
966 if (!client || ptypes != exp_pt)
967 return PKCS11_CKR_ARGUMENTS_BAD;
968
969 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
970
971 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
972 if (rc)
973 return rc;
974
975 rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
976 if (rc)
977 return rc;
978
979 if (serialargs_remaining_bytes(&ctrlargs))
980 return PKCS11_CKR_ARGUMENTS_BAD;
981
982 obj = pkcs11_handle2object(object_handle, session);
983 if (!obj)
984 return PKCS11_CKR_OBJECT_HANDLE_INVALID;
985
986 rc = check_access_attrs_against_token(session, obj->attributes);
987 if (rc)
988 return PKCS11_CKR_OBJECT_HANDLE_INVALID;
989
990 if (out->memref.size != sizeof(uint32_t))
991 return PKCS11_CKR_ARGUMENTS_BAD;
992
993 obj_size = ((struct obj_attrs *)obj->attributes)->attrs_size +
994 sizeof(struct obj_attrs);
995 TEE_MemMove(out->memref.buffer, &obj_size, sizeof(obj_size));
996
997 return PKCS11_CKR_OK;
998 }
999
entry_set_attribute_value(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)1000 enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client,
1001 uint32_t ptypes, TEE_Param *params)
1002 {
1003 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1004 TEE_PARAM_TYPE_NONE,
1005 TEE_PARAM_TYPE_NONE,
1006 TEE_PARAM_TYPE_NONE);
1007 TEE_Param *ctrl = params;
1008 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
1009 struct serialargs ctrlargs = { };
1010 struct pkcs11_session *session = NULL;
1011 struct pkcs11_object_head *template = NULL;
1012 size_t template_size = 0;
1013 struct pkcs11_object *obj = NULL;
1014 struct obj_attrs *head = NULL;
1015 struct obj_attrs *head_new = NULL;
1016 struct obj_attrs *head_old = NULL;
1017 uint32_t object_handle = 0;
1018 enum processing_func function = PKCS11_FUNCTION_MODIFY;
1019
1020 if (!client || ptypes != exp_pt)
1021 return PKCS11_CKR_ARGUMENTS_BAD;
1022
1023 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1024
1025 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1026 if (rc)
1027 return rc;
1028
1029 rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
1030 if (rc)
1031 return rc;
1032
1033 rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
1034 if (rc)
1035 return rc;
1036
1037 if (serialargs_remaining_bytes(&ctrlargs)) {
1038 rc = PKCS11_CKR_ARGUMENTS_BAD;
1039 goto out;
1040 }
1041
1042 obj = pkcs11_handle2object(object_handle, session);
1043 if (!obj) {
1044 rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
1045 goto out;
1046 }
1047
1048 /* Only session objects can be modified during a read-only session */
1049 if (object_is_token(obj->attributes) &&
1050 !pkcs11_session_is_read_write(session)) {
1051 DMSG("Can't modify persistent object in a RO session");
1052 rc = PKCS11_CKR_SESSION_READ_ONLY;
1053 goto out;
1054 }
1055
1056 /*
1057 * Only public objects can be modified unless normal user is logged in
1058 */
1059 rc = check_access_attrs_against_token(session, obj->attributes);
1060 if (rc) {
1061 rc = PKCS11_CKR_USER_NOT_LOGGED_IN;
1062 goto out;
1063 }
1064
1065 /* Objects with PKCS11_CKA_MODIFIABLE as false aren't modifiable */
1066 if (!object_is_modifiable(obj->attributes)) {
1067 rc = PKCS11_CKR_ACTION_PROHIBITED;
1068 goto out;
1069 }
1070
1071 template_size = sizeof(*template) + template->attrs_size;
1072
1073 /*
1074 * Prepare a clean initial state (@head) for the template. Helps in
1075 * removing any duplicates or inconsistent values from the
1076 * template.
1077 */
1078 rc = create_attributes_from_template(&head, template, template_size,
1079 NULL, function,
1080 PKCS11_CKM_UNDEFINED_ID,
1081 PKCS11_CKO_UNDEFINED_ID);
1082 if (rc)
1083 goto out;
1084
1085 /* Check the attributes in @head to see if they are modifiable */
1086 rc = check_attrs_against_modification(session, head, obj, function);
1087 if (rc)
1088 goto out;
1089
1090 /* Create new object attributes to modify */
1091 template_size = sizeof(*obj->attributes) + obj->attributes->attrs_size;
1092 head_new = TEE_Malloc(template_size, TEE_MALLOC_FILL_ZERO);
1093 if (!head_new) {
1094 rc = PKCS11_CKR_DEVICE_MEMORY;
1095 goto out;
1096 }
1097
1098 TEE_MemMove(head_new, obj->attributes, template_size);
1099
1100 /*
1101 * All checks complete. The attributes in @head have been checked and
1102 * can now be used to set/modify the object attributes.
1103 */
1104 rc = modify_attributes_list(&head_new, head);
1105 if (rc)
1106 goto out;
1107
1108 /* Set key check value attribute */
1109 rc = set_check_value_attr(&head_new);
1110 if (rc)
1111 goto out;
1112
1113 /* Update the object */
1114 head_old = obj->attributes;
1115 obj->attributes = head_new;
1116 head_new = NULL;
1117
1118 if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
1119 rc = update_persistent_object_attributes(obj);
1120 if (rc) {
1121 TEE_Free(obj->attributes);
1122 obj->attributes = head_old;
1123 goto out;
1124 }
1125 }
1126
1127 TEE_Free(head_old);
1128
1129 DMSG("PKCS11 session %"PRIu32": set attributes %#"PRIx32,
1130 session->handle, object_handle);
1131
1132 out:
1133 TEE_Free(head);
1134 TEE_Free(head_new);
1135 TEE_Free(template);
1136 return rc;
1137 }
1138
entry_copy_object(struct pkcs11_client * client,uint32_t ptypes,TEE_Param * params)1139 enum pkcs11_rc entry_copy_object(struct pkcs11_client *client, uint32_t ptypes,
1140 TEE_Param *params)
1141 {
1142 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
1143 TEE_PARAM_TYPE_NONE,
1144 TEE_PARAM_TYPE_MEMREF_OUTPUT,
1145 TEE_PARAM_TYPE_NONE);
1146 TEE_Param *ctrl = params;
1147 TEE_Param *out = params + 2;
1148 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
1149 struct serialargs ctrlargs = { };
1150 struct pkcs11_session *session = NULL;
1151 struct pkcs11_object_head *template = NULL;
1152 struct obj_attrs *head = NULL;
1153 struct obj_attrs *head_new = NULL;
1154 size_t template_size = 0;
1155 struct pkcs11_object *obj = NULL;
1156 uint32_t object_handle = 0;
1157 uint32_t obj_handle = 0;
1158 enum processing_func function = PKCS11_FUNCTION_COPY;
1159 enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID;
1160
1161 if (!client || ptypes != exp_pt ||
1162 out->memref.size != sizeof(obj_handle))
1163 return PKCS11_CKR_ARGUMENTS_BAD;
1164
1165 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
1166
1167 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
1168 if (rc)
1169 return rc;
1170
1171 rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
1172 if (rc)
1173 return rc;
1174
1175 rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
1176 if (rc)
1177 return rc;
1178
1179 if (serialargs_remaining_bytes(&ctrlargs)) {
1180 rc = PKCS11_CKR_ARGUMENTS_BAD;
1181 goto out;
1182 }
1183
1184 obj = pkcs11_handle2object(object_handle, session);
1185 if (!obj) {
1186 rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
1187 goto out;
1188 }
1189
1190 /* Only session objects can be modified during a read-only session */
1191 if (object_is_token(obj->attributes) &&
1192 !pkcs11_session_is_read_write(session)) {
1193 DMSG("Can't modify persistent object in a RO session");
1194 rc = PKCS11_CKR_SESSION_READ_ONLY;
1195 goto out;
1196 }
1197
1198 /*
1199 * Only public objects can be modified unless normal user is logged in
1200 */
1201 rc = check_access_attrs_against_token(session, obj->attributes);
1202 if (rc) {
1203 rc = PKCS11_CKR_USER_NOT_LOGGED_IN;
1204 goto out;
1205 }
1206
1207 /* Objects with PKCS11_CKA_COPYABLE as false can't be copied */
1208 if (!object_is_copyable(obj->attributes)) {
1209 rc = PKCS11_CKR_ACTION_PROHIBITED;
1210 goto out;
1211 }
1212
1213 template_size = sizeof(*template) + template->attrs_size;
1214
1215 /*
1216 * Prepare a clean initial state (@head) for the template. Helps in
1217 * removing any duplicates or inconsistent values from the
1218 * template.
1219 */
1220 rc = create_attributes_from_template(&head, template, template_size,
1221 NULL, function,
1222 PKCS11_CKM_UNDEFINED_ID,
1223 PKCS11_CKO_UNDEFINED_ID);
1224 if (rc)
1225 goto out;
1226
1227 /* Check the attributes in @head to see if they are modifiable */
1228 rc = check_attrs_against_modification(session, head, obj, function);
1229 if (rc)
1230 goto out;
1231
1232 class = get_class(obj->attributes);
1233
1234 if (class == PKCS11_CKO_SECRET_KEY ||
1235 class == PKCS11_CKO_PRIVATE_KEY) {
1236 /*
1237 * If CKA_EXTRACTABLE attribute in passed template (@head) is
1238 * modified to CKA_FALSE, CKA_NEVER_EXTRACTABLE should also
1239 * change to CKA_FALSE in copied obj. So, add it to the
1240 * passed template.
1241 */
1242 uint8_t bbool = 0;
1243 uint32_t size = sizeof(bbool);
1244
1245 rc = get_attribute(head, PKCS11_CKA_EXTRACTABLE, &bbool, &size);
1246 if (!rc && !bbool) {
1247 rc = add_attribute(&head, PKCS11_CKA_NEVER_EXTRACTABLE,
1248 &bbool, sizeof(uint8_t));
1249 if (rc)
1250 goto out;
1251 }
1252 rc = PKCS11_CKR_OK;
1253 }
1254
1255 /*
1256 * All checks have passed. Create a copy of the serialized buffer which
1257 * holds the object attributes in @head_new for the new object
1258 */
1259 template_size = sizeof(*obj->attributes) + obj->attributes->attrs_size;
1260 head_new = TEE_Malloc(template_size, TEE_MALLOC_FILL_ZERO);
1261 if (!head_new) {
1262 rc = PKCS11_CKR_DEVICE_MEMORY;
1263 goto out;
1264 }
1265
1266 TEE_MemMove(head_new, obj->attributes, template_size);
1267
1268 /*
1269 * Modify the copied attribute @head_new based on the template @head
1270 * given by the callee
1271 */
1272 rc = modify_attributes_list(&head_new, head);
1273 if (rc)
1274 goto out;
1275
1276 /* Set key check value attribute */
1277 rc = set_check_value_attr(&head_new);
1278 if (rc)
1279 goto out;
1280
1281 /*
1282 * At this stage the object is almost created: all its attributes are
1283 * referenced in @head_new, including the key value and are assumed
1284 * reliable. Now need to register it and get a handle for it.
1285 */
1286 rc = create_object(session, head_new, &obj_handle);
1287 if (rc)
1288 goto out;
1289
1290 /*
1291 * Now obj_handle (through the related struct pkcs11_object
1292 * instance) owns the serialized buffer that holds the object
1293 * attributes. We clear reference in head to NULL as the serializer
1294 * object is now referred from obj_handle. This allows smooth pass
1295 * through free at function exit.
1296 */
1297 head_new = NULL;
1298
1299 TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
1300 out->memref.size = sizeof(obj_handle);
1301
1302 DMSG("PKCS11 session %"PRIu32": copy object %#"PRIx32,
1303 session->handle, obj_handle);
1304
1305 out:
1306 TEE_Free(head_new);
1307 TEE_Free(head);
1308 TEE_Free(template);
1309 return rc;
1310 }
1311