1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2018-2020, Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <pkcs11_ta.h> 8 #include <string.h> 9 #include <string_ext.h> 10 #include <tee_internal_api_extensions.h> 11 #include <util.h> 12 13 #include "pkcs11_token.h" 14 #include "pkcs11_helpers.h" 15 16 #define PERSISTENT_OBJECT_ID_LEN 32 17 18 /* 19 * Token persistent objects 20 * 21 * The persistent objects are each identified by a UUID. 22 * The persistent object database stores the list of the UUIDs registered. For 23 * each it is expected that a file of ID "UUID" is stored in the TA secure 24 * storage. 25 */ 26 static TEE_Result get_db_file_name(struct ck_token *token, 27 char *name, size_t size) 28 { 29 int n = snprintf(name, size, "token.db.%u", get_token_id(token)); 30 31 if (n < 0 || (size_t)n >= size) 32 return TEE_ERROR_SECURITY; 33 else 34 return TEE_SUCCESS; 35 } 36 37 static TEE_Result open_db_file(struct ck_token *token, 38 TEE_ObjectHandle *out_hdl) 39 { 40 char file[PERSISTENT_OBJECT_ID_LEN] = { }; 41 TEE_Result res = TEE_ERROR_GENERIC; 42 43 res = get_db_file_name(token, file, sizeof(file)); 44 if (res) 45 return res; 46 47 return TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, file, sizeof(file), 48 TEE_DATA_FLAG_ACCESS_READ | 49 TEE_DATA_FLAG_ACCESS_WRITE, 50 out_hdl); 51 } 52 53 void update_persistent_db(struct ck_token *token) 54 { 55 TEE_Result res = TEE_ERROR_GENERIC; 56 TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; 57 58 res = open_db_file(token, &db_hdl); 59 if (res) { 60 EMSG("Failed to open token persistent db: %#"PRIx32, res); 61 TEE_Panic(0); 62 } 63 res = TEE_WriteObjectData(db_hdl, token->db_main, 64 sizeof(*token->db_main)); 65 if (res) { 66 EMSG("Failed to write to token persistent db: %#"PRIx32, res); 67 TEE_Panic(0); 68 } 69 70 TEE_CloseObject(db_hdl); 71 } 72 73 static enum pkcs11_rc do_hash(uint32_t user, const uint8_t *pin, 74 size_t pin_size, uint32_t salt, 75 uint8_t hash[TEE_MAX_HASH_SIZE]) 76 { 77 TEE_Result res = TEE_SUCCESS; 78 TEE_OperationHandle oh = TEE_HANDLE_NULL; 79 uint32_t sz = TEE_MAX_HASH_SIZE; 80 81 res = TEE_AllocateOperation(&oh, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0); 82 if (res) 83 return tee2pkcs_error(res); 84 85 TEE_DigestUpdate(oh, &user, sizeof(user)); 86 TEE_DigestUpdate(oh, &salt, sizeof(salt)); 87 res = TEE_DigestDoFinal(oh, pin, pin_size, hash, &sz); 88 TEE_FreeOperation(oh); 89 90 if (res) 91 return PKCS11_CKR_GENERAL_ERROR; 92 93 memset(hash + sz, 0, TEE_MAX_HASH_SIZE - sz); 94 return PKCS11_CKR_OK; 95 } 96 97 enum pkcs11_rc hash_pin(enum pkcs11_user_type user, const uint8_t *pin, 98 size_t pin_size, uint32_t *salt, 99 uint8_t hash[TEE_MAX_HASH_SIZE]) 100 { 101 enum pkcs11_rc rc = PKCS11_CKR_OK; 102 uint32_t s = 0; 103 104 TEE_GenerateRandom(&s, sizeof(s)); 105 if (!s) 106 s++; 107 108 rc = do_hash(user, pin, pin_size, s, hash); 109 if (!rc) 110 *salt = s; 111 return rc; 112 } 113 114 enum pkcs11_rc verify_pin(enum pkcs11_user_type user, const uint8_t *pin, 115 size_t pin_size, uint32_t salt, 116 const uint8_t hash[TEE_MAX_HASH_SIZE]) 117 { 118 uint8_t tmp_hash[TEE_MAX_HASH_SIZE] = { 0 }; 119 enum pkcs11_rc rc = PKCS11_CKR_OK; 120 121 rc = do_hash(user, pin, pin_size, salt, tmp_hash); 122 if (rc) 123 return rc; 124 125 if (buf_compare_ct(tmp_hash, hash, TEE_MAX_HASH_SIZE)) 126 rc = PKCS11_CKR_PIN_INCORRECT; 127 128 return rc; 129 } 130 131 #if defined(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) 132 enum pkcs11_rc setup_so_identity_auth_from_client(struct ck_token *token) 133 { 134 TEE_Identity identity = { }; 135 TEE_Result res = TEE_SUCCESS; 136 137 res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, 138 "gpd.client.identity", &identity); 139 if (res != TEE_SUCCESS) { 140 EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res); 141 return PKCS11_CKR_PIN_INVALID; 142 } 143 144 TEE_MemMove(&token->db_main->so_identity, &identity, sizeof(identity)); 145 token->db_main->flags |= PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH; 146 147 token->db_main->so_pin_salt = 0; 148 149 return PKCS11_CKR_OK; 150 } 151 152 enum pkcs11_rc setup_identity_auth_from_pin(struct ck_token *token, 153 enum pkcs11_user_type user_type, 154 const uint8_t *pin, 155 size_t pin_size) 156 { 157 TEE_Identity identity = { }; 158 TEE_Result res = TEE_SUCCESS; 159 uint32_t flags_clear = 0; 160 uint32_t flags_set = 0; 161 char *acl_string = NULL; 162 char *uuid_str = NULL; 163 164 assert(token->db_main->flags & 165 PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH); 166 167 if (!pin) { 168 /* Use client identity */ 169 res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, 170 "gpd.client.identity", 171 &identity); 172 if (res != TEE_SUCCESS) { 173 EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, 174 res); 175 return PKCS11_CKR_PIN_INVALID; 176 } 177 } else { 178 /* Parse PIN ACL string: <login type>:<client id> */ 179 acl_string = TEE_Malloc(pin_size + 1, TEE_MALLOC_FILL_ZERO); 180 if (!acl_string) 181 return PKCS11_CKR_DEVICE_MEMORY; 182 TEE_MemMove(acl_string, pin, pin_size); 183 184 uuid_str = strstr(acl_string, ":"); 185 if (uuid_str) 186 uuid_str++; 187 if (strcmp(PKCS11_AUTH_TEE_IDENTITY_PUBLIC, acl_string) == 0) { 188 identity.login = TEE_LOGIN_PUBLIC; 189 } else if (strstr(acl_string, PKCS11_AUTH_TEE_IDENTITY_USER) == 190 acl_string) { 191 identity.login = TEE_LOGIN_USER; 192 } else if (strstr(acl_string, PKCS11_AUTH_TEE_IDENTITY_GROUP) == 193 acl_string) { 194 identity.login = TEE_LOGIN_GROUP; 195 } else { 196 EMSG("Invalid PIN ACL string - login"); 197 TEE_Free(acl_string); 198 return PKCS11_CKR_PIN_INVALID; 199 } 200 201 if (identity.login != TEE_LOGIN_PUBLIC) { 202 if (!uuid_str) { 203 EMSG("Invalid PIN ACL string - colon"); 204 TEE_Free(acl_string); 205 return PKCS11_CKR_PIN_INVALID; 206 } 207 208 res = tee_uuid_from_str(&identity.uuid, uuid_str); 209 if (res) { 210 EMSG("Invalid PIN ACL string - client id"); 211 TEE_Free(acl_string); 212 return PKCS11_CKR_PIN_INVALID; 213 } 214 } 215 216 TEE_Free(acl_string); 217 } 218 219 switch (user_type) { 220 case PKCS11_CKU_SO: 221 token->db_main->so_pin_count = 0; 222 token->db_main->so_pin_salt = 0; 223 flags_clear = PKCS11_CKFT_SO_PIN_COUNT_LOW | 224 PKCS11_CKFT_SO_PIN_FINAL_TRY | 225 PKCS11_CKFT_SO_PIN_LOCKED | 226 PKCS11_CKFT_SO_PIN_TO_BE_CHANGED; 227 228 TEE_MemMove(&token->db_main->so_identity, &identity, 229 sizeof(identity)); 230 break; 231 case PKCS11_CKU_USER: 232 token->db_main->user_pin_count = 0; 233 token->db_main->user_pin_salt = 0; 234 flags_clear = PKCS11_CKFT_USER_PIN_COUNT_LOW | 235 PKCS11_CKFT_USER_PIN_FINAL_TRY | 236 PKCS11_CKFT_USER_PIN_LOCKED | 237 PKCS11_CKFT_USER_PIN_TO_BE_CHANGED; 238 flags_set = PKCS11_CKFT_USER_PIN_INITIALIZED; 239 240 TEE_MemMove(&token->db_main->user_identity, &identity, 241 sizeof(identity)); 242 break; 243 default: 244 return PKCS11_CKR_FUNCTION_FAILED; 245 } 246 247 token->db_main->flags &= ~flags_clear; 248 token->db_main->flags |= flags_set; 249 250 return PKCS11_CKR_OK; 251 } 252 253 enum pkcs11_rc verify_identity_auth(struct ck_token *token, 254 enum pkcs11_user_type user_type) 255 { 256 TEE_Identity identity = { }; 257 TEE_Result res = TEE_SUCCESS; 258 259 assert(token->db_main->flags & 260 PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH); 261 262 res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, 263 "gpd.client.identity", &identity); 264 if (res != TEE_SUCCESS) { 265 EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res); 266 return PKCS11_CKR_PIN_INVALID; 267 } 268 269 if (user_type == PKCS11_CKU_SO) { 270 if (TEE_MemCompare(&token->db_main->so_identity, &identity, 271 sizeof(identity))) 272 return PKCS11_CKR_PIN_INCORRECT; 273 } else if (user_type == PKCS11_CKU_USER) { 274 if (TEE_MemCompare(&token->db_main->user_identity, &identity, 275 sizeof(identity))) 276 return PKCS11_CKR_PIN_INCORRECT; 277 } else { 278 return PKCS11_CKR_PIN_INCORRECT; 279 } 280 281 return PKCS11_CKR_OK; 282 } 283 #endif /* CFG_PKCS11_TA_AUTH_TEE_IDENTITY */ 284 285 /* 286 * Release resources relate to persistent database 287 */ 288 void close_persistent_db(struct ck_token *token __unused) 289 { 290 } 291 292 static int get_persistent_obj_idx(struct ck_token *token, TEE_UUID *uuid) 293 { 294 size_t i = 0; 295 296 if (!uuid) 297 return -1; 298 299 for (i = 0; i < token->db_objs->count; i++) 300 if (!TEE_MemCompare(token->db_objs->uuids + i, 301 uuid, sizeof(TEE_UUID))) 302 return i; 303 304 return -1; 305 } 306 307 /* UUID for persistent object */ 308 enum pkcs11_rc create_object_uuid(struct ck_token *token, 309 struct pkcs11_object *obj) 310 { 311 assert(!obj->uuid); 312 313 obj->uuid = TEE_Malloc(sizeof(TEE_UUID), 314 TEE_USER_MEM_HINT_NO_FILL_ZERO); 315 if (!obj->uuid) 316 return PKCS11_CKR_DEVICE_MEMORY; 317 318 do { 319 TEE_GenerateRandom(obj->uuid, sizeof(TEE_UUID)); 320 } while (get_persistent_obj_idx(token, obj->uuid) >= 0); 321 322 return PKCS11_CKR_OK; 323 } 324 325 void destroy_object_uuid(struct ck_token *token __maybe_unused, 326 struct pkcs11_object *obj) 327 { 328 assert(get_persistent_obj_idx(token, obj->uuid) < 0); 329 330 TEE_Free(obj->uuid); 331 obj->uuid = NULL; 332 } 333 334 enum pkcs11_rc get_persistent_objects_list(struct ck_token *token, 335 TEE_UUID *array, size_t *size) 336 { 337 size_t out_size = *size; 338 339 *size = token->db_objs->count * sizeof(TEE_UUID); 340 341 if (out_size < *size) 342 return PKCS11_CKR_BUFFER_TOO_SMALL; 343 344 if (array) 345 TEE_MemMove(array, token->db_objs->uuids, *size); 346 347 return PKCS11_CKR_OK; 348 } 349 350 enum pkcs11_rc unregister_persistent_object(struct ck_token *token, 351 TEE_UUID *uuid) 352 { 353 TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; 354 struct token_persistent_objs *ptr = NULL; 355 TEE_Result res = TEE_ERROR_GENERIC; 356 int count = 0; 357 int idx = 0; 358 359 if (!uuid) 360 return PKCS11_CKR_OK; 361 362 idx = get_persistent_obj_idx(token, uuid); 363 if (idx < 0) { 364 DMSG("Cannot unregister an invalid persistent object"); 365 return PKCS11_RV_NOT_FOUND; 366 } 367 368 ptr = TEE_Malloc(sizeof(struct token_persistent_objs) + 369 ((token->db_objs->count - 1) * sizeof(TEE_UUID)), 370 TEE_USER_MEM_HINT_NO_FILL_ZERO); 371 if (!ptr) 372 return PKCS11_CKR_DEVICE_MEMORY; 373 374 res = open_db_file(token, &db_hdl); 375 if (res) 376 goto out; 377 378 res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main), 379 TEE_DATA_SEEK_SET); 380 if (res) { 381 DMSG("Failed to read database"); 382 goto out; 383 } 384 385 TEE_MemMove(ptr, token->db_objs, 386 sizeof(struct token_persistent_objs) + 387 idx * sizeof(TEE_UUID)); 388 389 ptr->count--; 390 count = ptr->count - idx; 391 392 TEE_MemMove(&ptr->uuids[idx], 393 &token->db_objs->uuids[idx + 1], 394 count * sizeof(TEE_UUID)); 395 396 res = TEE_WriteObjectData(db_hdl, ptr, 397 sizeof(struct token_persistent_objs) + 398 ptr->count * sizeof(TEE_UUID)); 399 if (res) 400 DMSG("Failed to update database"); 401 TEE_Free(token->db_objs); 402 token->db_objs = ptr; 403 ptr = NULL; 404 405 out: 406 TEE_CloseObject(db_hdl); 407 TEE_Free(ptr); 408 409 return tee2pkcs_error(res); 410 } 411 412 enum pkcs11_rc register_persistent_object(struct ck_token *token, 413 TEE_UUID *uuid) 414 { 415 TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; 416 TEE_Result res = TEE_ERROR_GENERIC; 417 void *ptr = NULL; 418 size_t size = 0; 419 int count = 0; 420 421 if (get_persistent_obj_idx(token, uuid) >= 0) 422 TEE_Panic(0); 423 424 count = token->db_objs->count; 425 ptr = TEE_Realloc(token->db_objs, 426 sizeof(struct token_persistent_objs) + 427 ((count + 1) * sizeof(TEE_UUID))); 428 if (!ptr) 429 return PKCS11_CKR_DEVICE_MEMORY; 430 431 token->db_objs = ptr; 432 TEE_MemMove(token->db_objs->uuids + count, uuid, sizeof(TEE_UUID)); 433 434 size = sizeof(struct token_persistent_main) + 435 sizeof(struct token_persistent_objs) + 436 count * sizeof(TEE_UUID); 437 438 res = open_db_file(token, &db_hdl); 439 if (res) 440 goto out; 441 442 res = TEE_TruncateObjectData(db_hdl, size + sizeof(TEE_UUID)); 443 if (res) 444 goto out; 445 446 res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main), 447 TEE_DATA_SEEK_SET); 448 if (res) 449 goto out; 450 451 token->db_objs->count++; 452 453 res = TEE_WriteObjectData(db_hdl, token->db_objs, 454 sizeof(struct token_persistent_objs) + 455 token->db_objs->count * sizeof(TEE_UUID)); 456 if (res) 457 token->db_objs->count--; 458 459 out: 460 TEE_CloseObject(db_hdl); 461 462 return tee2pkcs_error(res); 463 } 464 465 enum pkcs11_rc load_persistent_object_attributes(struct pkcs11_object *obj) 466 { 467 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 468 TEE_Result res = TEE_ERROR_GENERIC; 469 TEE_ObjectHandle hdl = obj->attribs_hdl; 470 TEE_ObjectInfo info = { }; 471 struct obj_attrs *attr = NULL; 472 uint32_t read_bytes = 0; 473 474 if (obj->attributes) 475 return PKCS11_CKR_OK; 476 477 if (hdl == TEE_HANDLE_NULL) { 478 res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, 479 obj->uuid, sizeof(*obj->uuid), 480 TEE_DATA_FLAG_ACCESS_READ, &hdl); 481 if (res) { 482 EMSG("OpenPersistent failed %#"PRIx32, res); 483 return tee2pkcs_error(res); 484 } 485 } 486 487 TEE_MemFill(&info, 0, sizeof(info)); 488 res = TEE_GetObjectInfo1(hdl, &info); 489 if (res) { 490 EMSG("GetObjectInfo failed %#"PRIx32, res); 491 rc = tee2pkcs_error(res); 492 goto out; 493 } 494 495 attr = TEE_Malloc(info.dataSize, TEE_MALLOC_FILL_ZERO); 496 if (!attr) { 497 rc = PKCS11_CKR_DEVICE_MEMORY; 498 goto out; 499 } 500 501 res = TEE_ReadObjectData(hdl, attr, info.dataSize, &read_bytes); 502 if (!res) { 503 res = TEE_SeekObjectData(hdl, 0, TEE_DATA_SEEK_SET); 504 if (res) 505 EMSG("Seek to 0 failed %#"PRIx32, res); 506 } 507 508 if (res) { 509 rc = tee2pkcs_error(res); 510 EMSG("Read %"PRIu32" bytes, failed %#"PRIx32, 511 read_bytes, res); 512 goto out; 513 } 514 if (read_bytes != info.dataSize) { 515 EMSG("Read %"PRIu32" bytes, expected %"PRIu32, 516 read_bytes, info.dataSize); 517 rc = PKCS11_CKR_GENERAL_ERROR; 518 goto out; 519 } 520 521 obj->attributes = attr; 522 attr = NULL; 523 524 rc = PKCS11_CKR_OK; 525 526 out: 527 TEE_Free(attr); 528 /* Close object only if it was open from this function */ 529 if (obj->attribs_hdl == TEE_HANDLE_NULL) 530 TEE_CloseObject(hdl); 531 532 return rc; 533 } 534 535 void release_persistent_object_attributes(struct pkcs11_object *obj) 536 { 537 TEE_Free(obj->attributes); 538 obj->attributes = NULL; 539 } 540 541 /* 542 * Return the token instance, either initialized from reset or initialized 543 * from the token persistent state if found. 544 */ 545 struct ck_token *init_persistent_db(unsigned int token_id) 546 { 547 struct ck_token *token = get_token(token_id); 548 TEE_Result res = TEE_ERROR_GENERIC; 549 TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; 550 /* Copy persistent database: main db and object db */ 551 struct token_persistent_main *db_main = NULL; 552 struct token_persistent_objs *db_objs = NULL; 553 void *ptr = NULL; 554 555 if (!token) 556 return NULL; 557 558 LIST_INIT(&token->object_list); 559 560 db_main = TEE_Malloc(sizeof(*db_main), TEE_MALLOC_FILL_ZERO); 561 db_objs = TEE_Malloc(sizeof(*db_objs), TEE_MALLOC_FILL_ZERO); 562 if (!db_main || !db_objs) 563 goto error; 564 565 res = open_db_file(token, &db_hdl); 566 567 if (res == TEE_SUCCESS) { 568 uint32_t size = 0; 569 size_t idx = 0; 570 571 IMSG("PKCS11 token %u: load db", token_id); 572 573 size = sizeof(*db_main); 574 res = TEE_ReadObjectData(db_hdl, db_main, size, &size); 575 if (res || size != sizeof(*db_main)) 576 TEE_Panic(0); 577 578 size = sizeof(*db_objs); 579 res = TEE_ReadObjectData(db_hdl, db_objs, size, &size); 580 if (res || size != sizeof(*db_objs)) 581 TEE_Panic(0); 582 583 if (db_objs->count > 0) { 584 size += db_objs->count * sizeof(TEE_UUID); 585 ptr = TEE_Realloc(db_objs, size); 586 if (!ptr) 587 goto error; 588 589 db_objs = ptr; 590 size -= sizeof(*db_objs); 591 res = TEE_ReadObjectData(db_hdl, db_objs->uuids, size, 592 &size); 593 if (res || size != (db_objs->count * sizeof(TEE_UUID))) 594 TEE_Panic(0); 595 } 596 597 for (idx = 0; idx < db_objs->count; idx++) { 598 /* Create an empty object instance */ 599 struct pkcs11_object *obj = NULL; 600 TEE_UUID *uuid = NULL; 601 602 uuid = TEE_Malloc(sizeof(TEE_UUID), 603 TEE_USER_MEM_HINT_NO_FILL_ZERO); 604 if (!uuid) 605 goto error; 606 607 TEE_MemMove(uuid, &db_objs->uuids[idx], sizeof(*uuid)); 608 609 obj = create_token_object(NULL, uuid); 610 if (!obj) 611 TEE_Panic(0); 612 613 LIST_INSERT_HEAD(&token->object_list, obj, link); 614 } 615 616 } else if (res == TEE_ERROR_ITEM_NOT_FOUND) { 617 char file[PERSISTENT_OBJECT_ID_LEN] = { }; 618 619 IMSG("PKCS11 token %u: init db", token_id); 620 621 TEE_MemFill(db_main, 0, sizeof(*db_main)); 622 TEE_MemFill(db_main->label, '*', sizeof(db_main->label)); 623 624 db_main->flags = PKCS11_CKFT_SO_PIN_TO_BE_CHANGED | 625 PKCS11_CKFT_USER_PIN_TO_BE_CHANGED | 626 PKCS11_CKFT_RNG | 627 PKCS11_CKFT_DUAL_CRYPTO_OPERATIONS | 628 PKCS11_CKFT_LOGIN_REQUIRED; 629 630 res = get_db_file_name(token, file, sizeof(file)); 631 if (res) 632 TEE_Panic(0); 633 634 /* 635 * Object stores persistent state + persistent object 636 * references. 637 */ 638 res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, 639 file, sizeof(file), 640 TEE_DATA_FLAG_ACCESS_READ | 641 TEE_DATA_FLAG_ACCESS_WRITE, 642 TEE_HANDLE_NULL, 643 db_main, sizeof(*db_main), 644 &db_hdl); 645 if (res) { 646 EMSG("Failed to create db: %#"PRIx32, res); 647 goto error; 648 } 649 650 res = TEE_TruncateObjectData(db_hdl, sizeof(*db_main) + 651 sizeof(*db_objs)); 652 if (res) 653 TEE_Panic(0); 654 655 res = TEE_SeekObjectData(db_hdl, sizeof(*db_main), 656 TEE_DATA_SEEK_SET); 657 if (res) 658 TEE_Panic(0); 659 660 db_objs->count = 0; 661 res = TEE_WriteObjectData(db_hdl, db_objs, sizeof(*db_objs)); 662 if (res) 663 TEE_Panic(0); 664 665 } else { 666 goto error; 667 } 668 669 token->db_main = db_main; 670 token->db_objs = db_objs; 671 TEE_CloseObject(db_hdl); 672 673 return token; 674 675 error: 676 TEE_Free(db_main); 677 TEE_Free(db_objs); 678 if (db_hdl != TEE_HANDLE_NULL) 679 TEE_CloseObject(db_hdl); 680 681 return NULL; 682 } 683