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