1c84ccd0aSEtienne Carriere // SPDX-License-Identifier: BSD-2-Clause
2c84ccd0aSEtienne Carriere /*
3c84ccd0aSEtienne Carriere * Copyright (c) 2018-2020, Linaro Limited
4c84ccd0aSEtienne Carriere */
5c84ccd0aSEtienne Carriere
6c84ccd0aSEtienne Carriere #include <assert.h>
7c84ccd0aSEtienne Carriere #include <pkcs11_ta.h>
8c84ccd0aSEtienne Carriere #include <string.h>
9c84ccd0aSEtienne Carriere #include <string_ext.h>
10c84ccd0aSEtienne Carriere #include <tee_internal_api_extensions.h>
11c84ccd0aSEtienne Carriere #include <util.h>
12c84ccd0aSEtienne Carriere
13402d884aSRuchika Gupta #include "attributes.h"
14c84ccd0aSEtienne Carriere #include "pkcs11_token.h"
15c84ccd0aSEtienne Carriere #include "pkcs11_helpers.h"
16c84ccd0aSEtienne Carriere
1760659a86SEtienne Carriere #define PERSISTENT_OBJECT_ID_LEN 32
1860659a86SEtienne Carriere
1960659a86SEtienne Carriere /*
2060659a86SEtienne Carriere * Token persistent objects
21334316feSJens Wiklander *
22334316feSJens Wiklander * The persistent objects are each identified by a UUID.
23334316feSJens Wiklander * The persistent object database stores the list of the UUIDs registered. For
24334316feSJens Wiklander * each it is expected that a file of ID "UUID" is stored in the TA secure
25334316feSJens Wiklander * storage.
2660659a86SEtienne Carriere */
get_db_file_name(struct ck_token * token,char * name,size_t size)2760659a86SEtienne Carriere static TEE_Result get_db_file_name(struct ck_token *token,
2860659a86SEtienne Carriere char *name, size_t size)
29c84ccd0aSEtienne Carriere {
3060659a86SEtienne Carriere int n = snprintf(name, size, "token.db.%u", get_token_id(token));
3160659a86SEtienne Carriere
3260659a86SEtienne Carriere if (n < 0 || (size_t)n >= size)
3360659a86SEtienne Carriere return TEE_ERROR_SECURITY;
3460659a86SEtienne Carriere else
3560659a86SEtienne Carriere return TEE_SUCCESS;
3660659a86SEtienne Carriere }
3760659a86SEtienne Carriere
open_db_file(struct ck_token * token,TEE_ObjectHandle * out_hdl)3860659a86SEtienne Carriere static TEE_Result open_db_file(struct ck_token *token,
3960659a86SEtienne Carriere TEE_ObjectHandle *out_hdl)
4060659a86SEtienne Carriere {
4160659a86SEtienne Carriere char file[PERSISTENT_OBJECT_ID_LEN] = { };
4260659a86SEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC;
4360659a86SEtienne Carriere
4460659a86SEtienne Carriere res = get_db_file_name(token, file, sizeof(file));
4560659a86SEtienne Carriere if (res)
4660659a86SEtienne Carriere return res;
4760659a86SEtienne Carriere
4860659a86SEtienne Carriere return TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, file, sizeof(file),
4960659a86SEtienne Carriere TEE_DATA_FLAG_ACCESS_READ |
5060659a86SEtienne Carriere TEE_DATA_FLAG_ACCESS_WRITE,
5160659a86SEtienne Carriere out_hdl);
5260659a86SEtienne Carriere }
5360659a86SEtienne Carriere
update_persistent_db(struct ck_token * token)54e86828f4SJens Wiklander void update_persistent_db(struct ck_token *token)
55e86828f4SJens Wiklander {
56e86828f4SJens Wiklander TEE_Result res = TEE_ERROR_GENERIC;
57e86828f4SJens Wiklander TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
58e86828f4SJens Wiklander
59e86828f4SJens Wiklander res = open_db_file(token, &db_hdl);
60e86828f4SJens Wiklander if (res) {
61e86828f4SJens Wiklander EMSG("Failed to open token persistent db: %#"PRIx32, res);
62e86828f4SJens Wiklander TEE_Panic(0);
63e86828f4SJens Wiklander }
64e86828f4SJens Wiklander res = TEE_WriteObjectData(db_hdl, token->db_main,
65e86828f4SJens Wiklander sizeof(*token->db_main));
66e86828f4SJens Wiklander if (res) {
67e86828f4SJens Wiklander EMSG("Failed to write to token persistent db: %#"PRIx32, res);
68e86828f4SJens Wiklander TEE_Panic(0);
69e86828f4SJens Wiklander }
70e86828f4SJens Wiklander
71e86828f4SJens Wiklander TEE_CloseObject(db_hdl);
72e86828f4SJens Wiklander }
73e86828f4SJens Wiklander
do_hash(uint32_t user,const uint8_t * pin,size_t pin_size,uint32_t salt,uint8_t hash[TEE_MAX_HASH_SIZE])74bef8bc68SJens Wiklander static enum pkcs11_rc do_hash(uint32_t user, const uint8_t *pin,
75bef8bc68SJens Wiklander size_t pin_size, uint32_t salt,
76bef8bc68SJens Wiklander uint8_t hash[TEE_MAX_HASH_SIZE])
77bef8bc68SJens Wiklander {
78bef8bc68SJens Wiklander TEE_Result res = TEE_SUCCESS;
79bef8bc68SJens Wiklander TEE_OperationHandle oh = TEE_HANDLE_NULL;
80c7f1b4f7SJens Wiklander size_t sz = TEE_MAX_HASH_SIZE;
81bef8bc68SJens Wiklander
82bef8bc68SJens Wiklander res = TEE_AllocateOperation(&oh, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0);
83bef8bc68SJens Wiklander if (res)
84bef8bc68SJens Wiklander return tee2pkcs_error(res);
85bef8bc68SJens Wiklander
86bef8bc68SJens Wiklander TEE_DigestUpdate(oh, &user, sizeof(user));
87bef8bc68SJens Wiklander TEE_DigestUpdate(oh, &salt, sizeof(salt));
88bef8bc68SJens Wiklander res = TEE_DigestDoFinal(oh, pin, pin_size, hash, &sz);
89bef8bc68SJens Wiklander TEE_FreeOperation(oh);
90bef8bc68SJens Wiklander
91bef8bc68SJens Wiklander if (res)
92bef8bc68SJens Wiklander return PKCS11_CKR_GENERAL_ERROR;
93bef8bc68SJens Wiklander
94bef8bc68SJens Wiklander memset(hash + sz, 0, TEE_MAX_HASH_SIZE - sz);
95bef8bc68SJens Wiklander return PKCS11_CKR_OK;
96bef8bc68SJens Wiklander }
97bef8bc68SJens Wiklander
hash_pin(enum pkcs11_user_type user,const uint8_t * pin,size_t pin_size,uint32_t * salt,uint8_t hash[TEE_MAX_HASH_SIZE])98bef8bc68SJens Wiklander enum pkcs11_rc hash_pin(enum pkcs11_user_type user, const uint8_t *pin,
99bef8bc68SJens Wiklander size_t pin_size, uint32_t *salt,
100bef8bc68SJens Wiklander uint8_t hash[TEE_MAX_HASH_SIZE])
101bef8bc68SJens Wiklander {
102bef8bc68SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
103bef8bc68SJens Wiklander uint32_t s = 0;
104bef8bc68SJens Wiklander
105bef8bc68SJens Wiklander TEE_GenerateRandom(&s, sizeof(s));
106bef8bc68SJens Wiklander if (!s)
107bef8bc68SJens Wiklander s++;
108bef8bc68SJens Wiklander
109bef8bc68SJens Wiklander rc = do_hash(user, pin, pin_size, s, hash);
110bef8bc68SJens Wiklander if (!rc)
111bef8bc68SJens Wiklander *salt = s;
112bef8bc68SJens Wiklander return rc;
113bef8bc68SJens Wiklander }
114bef8bc68SJens Wiklander
verify_pin(enum pkcs11_user_type user,const uint8_t * pin,size_t pin_size,uint32_t salt,const uint8_t hash[TEE_MAX_HASH_SIZE])115bef8bc68SJens Wiklander enum pkcs11_rc verify_pin(enum pkcs11_user_type user, const uint8_t *pin,
116bef8bc68SJens Wiklander size_t pin_size, uint32_t salt,
117bef8bc68SJens Wiklander const uint8_t hash[TEE_MAX_HASH_SIZE])
118bef8bc68SJens Wiklander {
119bef8bc68SJens Wiklander uint8_t tmp_hash[TEE_MAX_HASH_SIZE] = { 0 };
120bef8bc68SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK;
121bef8bc68SJens Wiklander
122bef8bc68SJens Wiklander rc = do_hash(user, pin, pin_size, salt, tmp_hash);
123bef8bc68SJens Wiklander if (rc)
124bef8bc68SJens Wiklander return rc;
125bef8bc68SJens Wiklander
126bef8bc68SJens Wiklander if (buf_compare_ct(tmp_hash, hash, TEE_MAX_HASH_SIZE))
127bef8bc68SJens Wiklander rc = PKCS11_CKR_PIN_INCORRECT;
128bef8bc68SJens Wiklander
129bef8bc68SJens Wiklander return rc;
130bef8bc68SJens Wiklander }
131bef8bc68SJens Wiklander
1321a27b197SVesa Jääskeläinen #if defined(CFG_PKCS11_TA_AUTH_TEE_IDENTITY)
setup_so_identity_auth_from_client(struct ck_token * token)1331a27b197SVesa Jääskeläinen enum pkcs11_rc setup_so_identity_auth_from_client(struct ck_token *token)
1341a27b197SVesa Jääskeläinen {
1351a27b197SVesa Jääskeläinen TEE_Identity identity = { };
1361a27b197SVesa Jääskeläinen TEE_Result res = TEE_SUCCESS;
1371a27b197SVesa Jääskeläinen
1381a27b197SVesa Jääskeläinen res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT,
1391a27b197SVesa Jääskeläinen "gpd.client.identity", &identity);
1401a27b197SVesa Jääskeläinen if (res != TEE_SUCCESS) {
1411a27b197SVesa Jääskeläinen EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res);
1421a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INVALID;
1431a27b197SVesa Jääskeläinen }
1441a27b197SVesa Jääskeläinen
1451a27b197SVesa Jääskeläinen TEE_MemMove(&token->db_main->so_identity, &identity, sizeof(identity));
1461a27b197SVesa Jääskeläinen token->db_main->flags |= PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH;
1471a27b197SVesa Jääskeläinen
1481a27b197SVesa Jääskeläinen token->db_main->so_pin_salt = 0;
1491a27b197SVesa Jääskeläinen
1501a27b197SVesa Jääskeläinen return PKCS11_CKR_OK;
1511a27b197SVesa Jääskeläinen }
1521a27b197SVesa Jääskeläinen
setup_identity_auth_from_pin(struct ck_token * token,enum pkcs11_user_type user_type,const uint8_t * pin,size_t pin_size)1531a27b197SVesa Jääskeläinen enum pkcs11_rc setup_identity_auth_from_pin(struct ck_token *token,
1541a27b197SVesa Jääskeläinen enum pkcs11_user_type user_type,
1551a27b197SVesa Jääskeläinen const uint8_t *pin,
1561a27b197SVesa Jääskeläinen size_t pin_size)
1571a27b197SVesa Jääskeläinen {
1581a27b197SVesa Jääskeläinen TEE_Identity identity = { };
1591a27b197SVesa Jääskeläinen TEE_Result res = TEE_SUCCESS;
1601a27b197SVesa Jääskeläinen uint32_t flags_clear = 0;
1611a27b197SVesa Jääskeläinen uint32_t flags_set = 0;
1621a27b197SVesa Jääskeläinen char *acl_string = NULL;
1631a27b197SVesa Jääskeläinen char *uuid_str = NULL;
1641a27b197SVesa Jääskeläinen
1651a27b197SVesa Jääskeläinen assert(token->db_main->flags &
1661a27b197SVesa Jääskeläinen PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH);
1671a27b197SVesa Jääskeläinen
1681a27b197SVesa Jääskeläinen if (!pin) {
1691a27b197SVesa Jääskeläinen /* Use client identity */
1701a27b197SVesa Jääskeläinen res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT,
1711a27b197SVesa Jääskeläinen "gpd.client.identity",
1721a27b197SVesa Jääskeläinen &identity);
1731a27b197SVesa Jääskeläinen if (res != TEE_SUCCESS) {
1741a27b197SVesa Jääskeläinen EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32,
1751a27b197SVesa Jääskeläinen res);
1761a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INVALID;
1771a27b197SVesa Jääskeläinen }
1781a27b197SVesa Jääskeläinen } else {
1791a27b197SVesa Jääskeläinen /* Parse PIN ACL string: <login type>:<client id> */
1801a27b197SVesa Jääskeläinen acl_string = TEE_Malloc(pin_size + 1, TEE_MALLOC_FILL_ZERO);
1811a27b197SVesa Jääskeläinen if (!acl_string)
1821a27b197SVesa Jääskeläinen return PKCS11_CKR_DEVICE_MEMORY;
1831a27b197SVesa Jääskeläinen TEE_MemMove(acl_string, pin, pin_size);
1841a27b197SVesa Jääskeläinen
1851a27b197SVesa Jääskeläinen uuid_str = strstr(acl_string, ":");
1861a27b197SVesa Jääskeläinen if (uuid_str)
1871a27b197SVesa Jääskeläinen uuid_str++;
1881a27b197SVesa Jääskeläinen if (strcmp(PKCS11_AUTH_TEE_IDENTITY_PUBLIC, acl_string) == 0) {
1891a27b197SVesa Jääskeläinen identity.login = TEE_LOGIN_PUBLIC;
1901a27b197SVesa Jääskeläinen } else if (strstr(acl_string, PKCS11_AUTH_TEE_IDENTITY_USER) ==
1911a27b197SVesa Jääskeläinen acl_string) {
1921a27b197SVesa Jääskeläinen identity.login = TEE_LOGIN_USER;
1931a27b197SVesa Jääskeläinen } else if (strstr(acl_string, PKCS11_AUTH_TEE_IDENTITY_GROUP) ==
1941a27b197SVesa Jääskeläinen acl_string) {
1951a27b197SVesa Jääskeläinen identity.login = TEE_LOGIN_GROUP;
1961a27b197SVesa Jääskeläinen } else {
1971a27b197SVesa Jääskeläinen EMSG("Invalid PIN ACL string - login");
1981a27b197SVesa Jääskeläinen TEE_Free(acl_string);
1991a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INVALID;
2001a27b197SVesa Jääskeläinen }
2011a27b197SVesa Jääskeläinen
2021a27b197SVesa Jääskeläinen if (identity.login != TEE_LOGIN_PUBLIC) {
2031a27b197SVesa Jääskeläinen if (!uuid_str) {
2041a27b197SVesa Jääskeläinen EMSG("Invalid PIN ACL string - colon");
2051a27b197SVesa Jääskeläinen TEE_Free(acl_string);
2061a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INVALID;
2071a27b197SVesa Jääskeläinen }
2081a27b197SVesa Jääskeläinen
2091a27b197SVesa Jääskeläinen res = tee_uuid_from_str(&identity.uuid, uuid_str);
2101a27b197SVesa Jääskeläinen if (res) {
2111a27b197SVesa Jääskeläinen EMSG("Invalid PIN ACL string - client id");
2121a27b197SVesa Jääskeläinen TEE_Free(acl_string);
2131a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INVALID;
2141a27b197SVesa Jääskeläinen }
2151a27b197SVesa Jääskeläinen }
2161a27b197SVesa Jääskeläinen
2171a27b197SVesa Jääskeläinen TEE_Free(acl_string);
2181a27b197SVesa Jääskeläinen }
2191a27b197SVesa Jääskeläinen
2201a27b197SVesa Jääskeläinen switch (user_type) {
2211a27b197SVesa Jääskeläinen case PKCS11_CKU_SO:
2221a27b197SVesa Jääskeläinen token->db_main->so_pin_count = 0;
2231a27b197SVesa Jääskeläinen token->db_main->so_pin_salt = 0;
2241a27b197SVesa Jääskeläinen flags_clear = PKCS11_CKFT_SO_PIN_COUNT_LOW |
2251a27b197SVesa Jääskeläinen PKCS11_CKFT_SO_PIN_FINAL_TRY |
2261a27b197SVesa Jääskeläinen PKCS11_CKFT_SO_PIN_LOCKED |
2271a27b197SVesa Jääskeläinen PKCS11_CKFT_SO_PIN_TO_BE_CHANGED;
2281a27b197SVesa Jääskeläinen
2291a27b197SVesa Jääskeläinen TEE_MemMove(&token->db_main->so_identity, &identity,
2301a27b197SVesa Jääskeläinen sizeof(identity));
2311a27b197SVesa Jääskeläinen break;
2321a27b197SVesa Jääskeläinen case PKCS11_CKU_USER:
2331a27b197SVesa Jääskeläinen token->db_main->user_pin_count = 0;
2341a27b197SVesa Jääskeläinen token->db_main->user_pin_salt = 0;
2351a27b197SVesa Jääskeläinen flags_clear = PKCS11_CKFT_USER_PIN_COUNT_LOW |
2361a27b197SVesa Jääskeläinen PKCS11_CKFT_USER_PIN_FINAL_TRY |
2371a27b197SVesa Jääskeläinen PKCS11_CKFT_USER_PIN_LOCKED |
2381a27b197SVesa Jääskeläinen PKCS11_CKFT_USER_PIN_TO_BE_CHANGED;
2391a27b197SVesa Jääskeläinen flags_set = PKCS11_CKFT_USER_PIN_INITIALIZED;
2401a27b197SVesa Jääskeläinen
2411a27b197SVesa Jääskeläinen TEE_MemMove(&token->db_main->user_identity, &identity,
2421a27b197SVesa Jääskeläinen sizeof(identity));
2431a27b197SVesa Jääskeläinen break;
2441a27b197SVesa Jääskeläinen default:
2451a27b197SVesa Jääskeläinen return PKCS11_CKR_FUNCTION_FAILED;
2461a27b197SVesa Jääskeläinen }
2471a27b197SVesa Jääskeläinen
2481a27b197SVesa Jääskeläinen token->db_main->flags &= ~flags_clear;
2491a27b197SVesa Jääskeläinen token->db_main->flags |= flags_set;
2501a27b197SVesa Jääskeläinen
2511a27b197SVesa Jääskeläinen return PKCS11_CKR_OK;
2521a27b197SVesa Jääskeläinen }
2531a27b197SVesa Jääskeläinen
verify_identity_auth(struct ck_token * token,enum pkcs11_user_type user_type)2541a27b197SVesa Jääskeläinen enum pkcs11_rc verify_identity_auth(struct ck_token *token,
2551a27b197SVesa Jääskeläinen enum pkcs11_user_type user_type)
2561a27b197SVesa Jääskeläinen {
2571a27b197SVesa Jääskeläinen TEE_Identity identity = { };
2581a27b197SVesa Jääskeläinen TEE_Result res = TEE_SUCCESS;
2591a27b197SVesa Jääskeläinen
2601a27b197SVesa Jääskeläinen assert(token->db_main->flags &
2611a27b197SVesa Jääskeläinen PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH);
2621a27b197SVesa Jääskeläinen
2631a27b197SVesa Jääskeläinen res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT,
2641a27b197SVesa Jääskeläinen "gpd.client.identity", &identity);
2651a27b197SVesa Jääskeläinen if (res != TEE_SUCCESS) {
2661a27b197SVesa Jääskeläinen EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res);
2671a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INVALID;
2681a27b197SVesa Jääskeläinen }
2691a27b197SVesa Jääskeläinen
2701a27b197SVesa Jääskeläinen if (user_type == PKCS11_CKU_SO) {
2711a27b197SVesa Jääskeläinen if (TEE_MemCompare(&token->db_main->so_identity, &identity,
2721a27b197SVesa Jääskeläinen sizeof(identity)))
2731a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INCORRECT;
2741a27b197SVesa Jääskeläinen } else if (user_type == PKCS11_CKU_USER) {
2751a27b197SVesa Jääskeläinen if (TEE_MemCompare(&token->db_main->user_identity, &identity,
2761a27b197SVesa Jääskeläinen sizeof(identity)))
2771a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INCORRECT;
2781a27b197SVesa Jääskeläinen } else {
2791a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INCORRECT;
2801a27b197SVesa Jääskeläinen }
2811a27b197SVesa Jääskeläinen
2821a27b197SVesa Jääskeläinen return PKCS11_CKR_OK;
2831a27b197SVesa Jääskeläinen }
2841a27b197SVesa Jääskeläinen #endif /* CFG_PKCS11_TA_AUTH_TEE_IDENTITY */
2851a27b197SVesa Jääskeläinen
286c84ccd0aSEtienne Carriere /*
28760659a86SEtienne Carriere * Release resources relate to persistent database
28860659a86SEtienne Carriere */
close_persistent_db(struct ck_token * token __unused)28960659a86SEtienne Carriere void close_persistent_db(struct ck_token *token __unused)
29060659a86SEtienne Carriere {
29160659a86SEtienne Carriere }
29260659a86SEtienne Carriere
get_persistent_obj_idx(struct ck_token * token,TEE_UUID * uuid)293334316feSJens Wiklander static int get_persistent_obj_idx(struct ck_token *token, TEE_UUID *uuid)
294334316feSJens Wiklander {
295334316feSJens Wiklander size_t i = 0;
296334316feSJens Wiklander
297334316feSJens Wiklander if (!uuid)
298334316feSJens Wiklander return -1;
299334316feSJens Wiklander
300334316feSJens Wiklander for (i = 0; i < token->db_objs->count; i++)
301334316feSJens Wiklander if (!TEE_MemCompare(token->db_objs->uuids + i,
302334316feSJens Wiklander uuid, sizeof(TEE_UUID)))
303334316feSJens Wiklander return i;
304334316feSJens Wiklander
305334316feSJens Wiklander return -1;
306334316feSJens Wiklander }
307334316feSJens Wiklander
308334316feSJens Wiklander /* UUID for persistent object */
create_object_uuid(struct ck_token * token,struct pkcs11_object * obj)309334316feSJens Wiklander enum pkcs11_rc create_object_uuid(struct ck_token *token,
310334316feSJens Wiklander struct pkcs11_object *obj)
311334316feSJens Wiklander {
312334316feSJens Wiklander assert(!obj->uuid);
313334316feSJens Wiklander
314334316feSJens Wiklander obj->uuid = TEE_Malloc(sizeof(TEE_UUID),
315334316feSJens Wiklander TEE_USER_MEM_HINT_NO_FILL_ZERO);
316334316feSJens Wiklander if (!obj->uuid)
317334316feSJens Wiklander return PKCS11_CKR_DEVICE_MEMORY;
318334316feSJens Wiklander
319bc555ee0SVesa Jääskeläinen obj->token = token;
320bc555ee0SVesa Jääskeläinen
321334316feSJens Wiklander do {
322334316feSJens Wiklander TEE_GenerateRandom(obj->uuid, sizeof(TEE_UUID));
323334316feSJens Wiklander } while (get_persistent_obj_idx(token, obj->uuid) >= 0);
324334316feSJens Wiklander
325334316feSJens Wiklander return PKCS11_CKR_OK;
326334316feSJens Wiklander }
327334316feSJens Wiklander
destroy_object_uuid(struct ck_token * token __maybe_unused,struct pkcs11_object * obj)328334316feSJens Wiklander void destroy_object_uuid(struct ck_token *token __maybe_unused,
329334316feSJens Wiklander struct pkcs11_object *obj)
330334316feSJens Wiklander {
331334316feSJens Wiklander assert(get_persistent_obj_idx(token, obj->uuid) < 0);
332334316feSJens Wiklander
333334316feSJens Wiklander TEE_Free(obj->uuid);
334334316feSJens Wiklander obj->uuid = NULL;
335334316feSJens Wiklander }
336334316feSJens Wiklander
get_persistent_objects_list(struct ck_token * token,TEE_UUID * array,size_t * size)337334316feSJens Wiklander enum pkcs11_rc get_persistent_objects_list(struct ck_token *token,
338334316feSJens Wiklander TEE_UUID *array, size_t *size)
339334316feSJens Wiklander {
340334316feSJens Wiklander size_t out_size = *size;
341334316feSJens Wiklander
342334316feSJens Wiklander *size = token->db_objs->count * sizeof(TEE_UUID);
343334316feSJens Wiklander
344334316feSJens Wiklander if (out_size < *size)
345334316feSJens Wiklander return PKCS11_CKR_BUFFER_TOO_SMALL;
346334316feSJens Wiklander
347334316feSJens Wiklander if (array)
348334316feSJens Wiklander TEE_MemMove(array, token->db_objs->uuids, *size);
349334316feSJens Wiklander
350334316feSJens Wiklander return PKCS11_CKR_OK;
351334316feSJens Wiklander }
352334316feSJens Wiklander
unregister_persistent_object(struct ck_token * token,TEE_UUID * uuid)353334316feSJens Wiklander enum pkcs11_rc unregister_persistent_object(struct ck_token *token,
354334316feSJens Wiklander TEE_UUID *uuid)
355334316feSJens Wiklander {
356334316feSJens Wiklander TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
357334316feSJens Wiklander struct token_persistent_objs *ptr = NULL;
358334316feSJens Wiklander TEE_Result res = TEE_ERROR_GENERIC;
359334316feSJens Wiklander int count = 0;
360334316feSJens Wiklander int idx = 0;
361334316feSJens Wiklander
362334316feSJens Wiklander if (!uuid)
363334316feSJens Wiklander return PKCS11_CKR_OK;
364334316feSJens Wiklander
365334316feSJens Wiklander idx = get_persistent_obj_idx(token, uuid);
366334316feSJens Wiklander if (idx < 0) {
367334316feSJens Wiklander DMSG("Cannot unregister an invalid persistent object");
368334316feSJens Wiklander return PKCS11_RV_NOT_FOUND;
369334316feSJens Wiklander }
370334316feSJens Wiklander
371334316feSJens Wiklander ptr = TEE_Malloc(sizeof(struct token_persistent_objs) +
372334316feSJens Wiklander ((token->db_objs->count - 1) * sizeof(TEE_UUID)),
373334316feSJens Wiklander TEE_USER_MEM_HINT_NO_FILL_ZERO);
374334316feSJens Wiklander if (!ptr)
375334316feSJens Wiklander return PKCS11_CKR_DEVICE_MEMORY;
376334316feSJens Wiklander
377334316feSJens Wiklander res = open_db_file(token, &db_hdl);
378334316feSJens Wiklander if (res)
379334316feSJens Wiklander goto out;
380334316feSJens Wiklander
381334316feSJens Wiklander res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main),
382334316feSJens Wiklander TEE_DATA_SEEK_SET);
383334316feSJens Wiklander if (res) {
384334316feSJens Wiklander DMSG("Failed to read database");
385334316feSJens Wiklander goto out;
386334316feSJens Wiklander }
387334316feSJens Wiklander
388334316feSJens Wiklander TEE_MemMove(ptr, token->db_objs,
389334316feSJens Wiklander sizeof(struct token_persistent_objs) +
390334316feSJens Wiklander idx * sizeof(TEE_UUID));
391334316feSJens Wiklander
392334316feSJens Wiklander ptr->count--;
393334316feSJens Wiklander count = ptr->count - idx;
394334316feSJens Wiklander
395334316feSJens Wiklander TEE_MemMove(&ptr->uuids[idx],
396334316feSJens Wiklander &token->db_objs->uuids[idx + 1],
397334316feSJens Wiklander count * sizeof(TEE_UUID));
398334316feSJens Wiklander
399334316feSJens Wiklander res = TEE_WriteObjectData(db_hdl, ptr,
400334316feSJens Wiklander sizeof(struct token_persistent_objs) +
401334316feSJens Wiklander ptr->count * sizeof(TEE_UUID));
402334316feSJens Wiklander if (res)
403334316feSJens Wiklander DMSG("Failed to update database");
404334316feSJens Wiklander TEE_Free(token->db_objs);
405334316feSJens Wiklander token->db_objs = ptr;
406334316feSJens Wiklander ptr = NULL;
407334316feSJens Wiklander
408334316feSJens Wiklander out:
409334316feSJens Wiklander TEE_CloseObject(db_hdl);
410334316feSJens Wiklander TEE_Free(ptr);
411334316feSJens Wiklander
412334316feSJens Wiklander return tee2pkcs_error(res);
413334316feSJens Wiklander }
414334316feSJens Wiklander
register_persistent_object(struct ck_token * token,TEE_UUID * uuid)415334316feSJens Wiklander enum pkcs11_rc register_persistent_object(struct ck_token *token,
416334316feSJens Wiklander TEE_UUID *uuid)
417334316feSJens Wiklander {
418334316feSJens Wiklander TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
419334316feSJens Wiklander TEE_Result res = TEE_ERROR_GENERIC;
420334316feSJens Wiklander void *ptr = NULL;
421334316feSJens Wiklander size_t size = 0;
422334316feSJens Wiklander int count = 0;
423334316feSJens Wiklander
424334316feSJens Wiklander if (get_persistent_obj_idx(token, uuid) >= 0)
425334316feSJens Wiklander TEE_Panic(0);
426334316feSJens Wiklander
427334316feSJens Wiklander count = token->db_objs->count;
428334316feSJens Wiklander ptr = TEE_Realloc(token->db_objs,
429334316feSJens Wiklander sizeof(struct token_persistent_objs) +
430334316feSJens Wiklander ((count + 1) * sizeof(TEE_UUID)));
431334316feSJens Wiklander if (!ptr)
432334316feSJens Wiklander return PKCS11_CKR_DEVICE_MEMORY;
433334316feSJens Wiklander
434334316feSJens Wiklander token->db_objs = ptr;
435334316feSJens Wiklander TEE_MemMove(token->db_objs->uuids + count, uuid, sizeof(TEE_UUID));
436334316feSJens Wiklander
437334316feSJens Wiklander size = sizeof(struct token_persistent_main) +
438334316feSJens Wiklander sizeof(struct token_persistent_objs) +
439334316feSJens Wiklander count * sizeof(TEE_UUID);
440334316feSJens Wiklander
441334316feSJens Wiklander res = open_db_file(token, &db_hdl);
442334316feSJens Wiklander if (res)
443334316feSJens Wiklander goto out;
444334316feSJens Wiklander
445334316feSJens Wiklander res = TEE_TruncateObjectData(db_hdl, size + sizeof(TEE_UUID));
446334316feSJens Wiklander if (res)
447334316feSJens Wiklander goto out;
448334316feSJens Wiklander
449334316feSJens Wiklander res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main),
450334316feSJens Wiklander TEE_DATA_SEEK_SET);
451334316feSJens Wiklander if (res)
452334316feSJens Wiklander goto out;
453334316feSJens Wiklander
454334316feSJens Wiklander token->db_objs->count++;
455334316feSJens Wiklander
456334316feSJens Wiklander res = TEE_WriteObjectData(db_hdl, token->db_objs,
457334316feSJens Wiklander sizeof(struct token_persistent_objs) +
458334316feSJens Wiklander token->db_objs->count * sizeof(TEE_UUID));
459334316feSJens Wiklander if (res)
460334316feSJens Wiklander token->db_objs->count--;
461334316feSJens Wiklander
462334316feSJens Wiklander out:
463334316feSJens Wiklander TEE_CloseObject(db_hdl);
464334316feSJens Wiklander
465334316feSJens Wiklander return tee2pkcs_error(res);
466334316feSJens Wiklander }
467334316feSJens Wiklander
load_persistent_object_attributes(struct pkcs11_object * obj)468fa1ac767SRobin van der Gracht enum pkcs11_rc load_persistent_object_attributes(struct pkcs11_object *obj)
469fa1ac767SRobin van der Gracht {
470fa1ac767SRobin van der Gracht enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
471fa1ac767SRobin van der Gracht TEE_Result res = TEE_ERROR_GENERIC;
472fa1ac767SRobin van der Gracht TEE_ObjectHandle hdl = obj->attribs_hdl;
473fa1ac767SRobin van der Gracht TEE_ObjectInfo info = { };
474fa1ac767SRobin van der Gracht struct obj_attrs *attr = NULL;
475c7f1b4f7SJens Wiklander size_t read_bytes = 0;
476fa1ac767SRobin van der Gracht
477fa1ac767SRobin van der Gracht if (obj->attributes)
478fa1ac767SRobin van der Gracht return PKCS11_CKR_OK;
479fa1ac767SRobin van der Gracht
480fa1ac767SRobin van der Gracht if (hdl == TEE_HANDLE_NULL) {
481fa1ac767SRobin van der Gracht res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
482fa1ac767SRobin van der Gracht obj->uuid, sizeof(*obj->uuid),
483fa1ac767SRobin van der Gracht TEE_DATA_FLAG_ACCESS_READ, &hdl);
484fa1ac767SRobin van der Gracht if (res) {
485fa1ac767SRobin van der Gracht EMSG("OpenPersistent failed %#"PRIx32, res);
486fa1ac767SRobin van der Gracht return tee2pkcs_error(res);
487fa1ac767SRobin van der Gracht }
488fa1ac767SRobin van der Gracht }
489fa1ac767SRobin van der Gracht
490fa1ac767SRobin van der Gracht TEE_MemFill(&info, 0, sizeof(info));
491fa1ac767SRobin van der Gracht res = TEE_GetObjectInfo1(hdl, &info);
492fa1ac767SRobin van der Gracht if (res) {
493fa1ac767SRobin van der Gracht EMSG("GetObjectInfo failed %#"PRIx32, res);
494fa1ac767SRobin van der Gracht rc = tee2pkcs_error(res);
495fa1ac767SRobin van der Gracht goto out;
496fa1ac767SRobin van der Gracht }
497fa1ac767SRobin van der Gracht
498fa1ac767SRobin van der Gracht attr = TEE_Malloc(info.dataSize, TEE_MALLOC_FILL_ZERO);
499fa1ac767SRobin van der Gracht if (!attr) {
500fa1ac767SRobin van der Gracht rc = PKCS11_CKR_DEVICE_MEMORY;
501fa1ac767SRobin van der Gracht goto out;
502fa1ac767SRobin van der Gracht }
503fa1ac767SRobin van der Gracht
504fa1ac767SRobin van der Gracht res = TEE_ReadObjectData(hdl, attr, info.dataSize, &read_bytes);
505fa1ac767SRobin van der Gracht if (!res) {
506fa1ac767SRobin van der Gracht res = TEE_SeekObjectData(hdl, 0, TEE_DATA_SEEK_SET);
507fa1ac767SRobin van der Gracht if (res)
508fa1ac767SRobin van der Gracht EMSG("Seek to 0 failed %#"PRIx32, res);
509fa1ac767SRobin van der Gracht }
510fa1ac767SRobin van der Gracht
511fa1ac767SRobin van der Gracht if (res) {
512fa1ac767SRobin van der Gracht rc = tee2pkcs_error(res);
513c7f1b4f7SJens Wiklander EMSG("Read %zu bytes, failed %#"PRIx32,
514fa1ac767SRobin van der Gracht read_bytes, res);
515fa1ac767SRobin van der Gracht goto out;
516fa1ac767SRobin van der Gracht }
517fa1ac767SRobin van der Gracht if (read_bytes != info.dataSize) {
518c7f1b4f7SJens Wiklander EMSG("Read %zu bytes, expected %zu",
519fa1ac767SRobin van der Gracht read_bytes, info.dataSize);
520fa1ac767SRobin van der Gracht rc = PKCS11_CKR_GENERAL_ERROR;
521fa1ac767SRobin van der Gracht goto out;
522fa1ac767SRobin van der Gracht }
523fa1ac767SRobin van der Gracht
524fa1ac767SRobin van der Gracht obj->attributes = attr;
525fa1ac767SRobin van der Gracht attr = NULL;
526fa1ac767SRobin van der Gracht
527fa1ac767SRobin van der Gracht rc = PKCS11_CKR_OK;
528fa1ac767SRobin van der Gracht
529fa1ac767SRobin van der Gracht out:
530fa1ac767SRobin van der Gracht TEE_Free(attr);
531fa1ac767SRobin van der Gracht /* Close object only if it was open from this function */
532fa1ac767SRobin van der Gracht if (obj->attribs_hdl == TEE_HANDLE_NULL)
533fa1ac767SRobin van der Gracht TEE_CloseObject(hdl);
534fa1ac767SRobin van der Gracht
535fa1ac767SRobin van der Gracht return rc;
536fa1ac767SRobin van der Gracht }
537fa1ac767SRobin van der Gracht
release_persistent_object_attributes(struct pkcs11_object * obj)538fa1ac767SRobin van der Gracht void release_persistent_object_attributes(struct pkcs11_object *obj)
539fa1ac767SRobin van der Gracht {
540fa1ac767SRobin van der Gracht TEE_Free(obj->attributes);
541fa1ac767SRobin van der Gracht obj->attributes = NULL;
542fa1ac767SRobin van der Gracht }
543fa1ac767SRobin van der Gracht
update_persistent_object_attributes(struct pkcs11_object * obj)544402d884aSRuchika Gupta enum pkcs11_rc update_persistent_object_attributes(struct pkcs11_object *obj)
545402d884aSRuchika Gupta {
546402d884aSRuchika Gupta TEE_Result res = TEE_ERROR_GENERIC;
547402d884aSRuchika Gupta TEE_ObjectHandle hdl = TEE_HANDLE_NULL;
548402d884aSRuchika Gupta uint32_t tee_obj_flags = TEE_DATA_FLAG_ACCESS_WRITE;
549402d884aSRuchika Gupta size_t size = 0;
550402d884aSRuchika Gupta
551402d884aSRuchika Gupta assert(obj && obj->attributes);
552402d884aSRuchika Gupta
553402d884aSRuchika Gupta res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
554402d884aSRuchika Gupta obj->uuid, sizeof(*obj->uuid),
555402d884aSRuchika Gupta tee_obj_flags, &hdl);
556402d884aSRuchika Gupta if (res) {
557402d884aSRuchika Gupta EMSG("OpenPersistent failed %#"PRIx32, res);
558402d884aSRuchika Gupta return tee2pkcs_error(res);
559402d884aSRuchika Gupta }
560402d884aSRuchika Gupta
561402d884aSRuchika Gupta size = sizeof(struct obj_attrs) + obj->attributes->attrs_size;
562402d884aSRuchika Gupta
563402d884aSRuchika Gupta res = TEE_WriteObjectData(hdl, obj->attributes, size);
564402d884aSRuchika Gupta if (res)
565402d884aSRuchika Gupta goto out;
566402d884aSRuchika Gupta
567402d884aSRuchika Gupta res = TEE_TruncateObjectData(hdl, size);
568402d884aSRuchika Gupta
569402d884aSRuchika Gupta out:
570402d884aSRuchika Gupta TEE_CloseObject(hdl);
571402d884aSRuchika Gupta return tee2pkcs_error(res);
572402d884aSRuchika Gupta }
573402d884aSRuchika Gupta
57460659a86SEtienne Carriere /*
575c84ccd0aSEtienne Carriere * Return the token instance, either initialized from reset or initialized
576c84ccd0aSEtienne Carriere * from the token persistent state if found.
577c84ccd0aSEtienne Carriere */
init_persistent_db(unsigned int token_id)578c84ccd0aSEtienne Carriere struct ck_token *init_persistent_db(unsigned int token_id)
579c84ccd0aSEtienne Carriere {
580c84ccd0aSEtienne Carriere struct ck_token *token = get_token(token_id);
581c84ccd0aSEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC;
582c84ccd0aSEtienne Carriere TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
58360659a86SEtienne Carriere /* Copy persistent database: main db and object db */
584c84ccd0aSEtienne Carriere struct token_persistent_main *db_main = NULL;
585334316feSJens Wiklander struct token_persistent_objs *db_objs = NULL;
586334316feSJens Wiklander void *ptr = NULL;
587*931c8c5eSWeizhao Jiang void *initial_data = NULL;
588*931c8c5eSWeizhao Jiang uint32_t initial_data_size = 0;
589c84ccd0aSEtienne Carriere
590c84ccd0aSEtienne Carriere if (!token)
591c84ccd0aSEtienne Carriere return NULL;
592c84ccd0aSEtienne Carriere
593334316feSJens Wiklander LIST_INIT(&token->object_list);
594334316feSJens Wiklander
595c84ccd0aSEtienne Carriere db_main = TEE_Malloc(sizeof(*db_main), TEE_MALLOC_FILL_ZERO);
596334316feSJens Wiklander db_objs = TEE_Malloc(sizeof(*db_objs), TEE_MALLOC_FILL_ZERO);
597334316feSJens Wiklander if (!db_main || !db_objs)
598c84ccd0aSEtienne Carriere goto error;
599c84ccd0aSEtienne Carriere
60060659a86SEtienne Carriere res = open_db_file(token, &db_hdl);
601c84ccd0aSEtienne Carriere
602c84ccd0aSEtienne Carriere if (res == TEE_SUCCESS) {
603c7f1b4f7SJens Wiklander size_t size = 0;
604334316feSJens Wiklander size_t idx = 0;
605c84ccd0aSEtienne Carriere
606c84ccd0aSEtienne Carriere IMSG("PKCS11 token %u: load db", token_id);
607c84ccd0aSEtienne Carriere
608c84ccd0aSEtienne Carriere size = sizeof(*db_main);
609c84ccd0aSEtienne Carriere res = TEE_ReadObjectData(db_hdl, db_main, size, &size);
610c84ccd0aSEtienne Carriere if (res || size != sizeof(*db_main))
611c84ccd0aSEtienne Carriere TEE_Panic(0);
612334316feSJens Wiklander
613334316feSJens Wiklander size = sizeof(*db_objs);
614334316feSJens Wiklander res = TEE_ReadObjectData(db_hdl, db_objs, size, &size);
615334316feSJens Wiklander if (res || size != sizeof(*db_objs))
616334316feSJens Wiklander TEE_Panic(0);
617334316feSJens Wiklander
618974adb9fSRobin van der Gracht if (db_objs->count > 0) {
619334316feSJens Wiklander size += db_objs->count * sizeof(TEE_UUID);
620334316feSJens Wiklander ptr = TEE_Realloc(db_objs, size);
621334316feSJens Wiklander if (!ptr)
622334316feSJens Wiklander goto error;
623334316feSJens Wiklander
624334316feSJens Wiklander db_objs = ptr;
625a3c511dfSRobin van der Gracht size -= sizeof(*db_objs);
626974adb9fSRobin van der Gracht res = TEE_ReadObjectData(db_hdl, db_objs->uuids, size,
627974adb9fSRobin van der Gracht &size);
628334316feSJens Wiklander if (res || size != (db_objs->count * sizeof(TEE_UUID)))
629334316feSJens Wiklander TEE_Panic(0);
630974adb9fSRobin van der Gracht }
631334316feSJens Wiklander
632334316feSJens Wiklander for (idx = 0; idx < db_objs->count; idx++) {
633334316feSJens Wiklander /* Create an empty object instance */
634334316feSJens Wiklander struct pkcs11_object *obj = NULL;
635334316feSJens Wiklander TEE_UUID *uuid = NULL;
636334316feSJens Wiklander
637334316feSJens Wiklander uuid = TEE_Malloc(sizeof(TEE_UUID),
638334316feSJens Wiklander TEE_USER_MEM_HINT_NO_FILL_ZERO);
639334316feSJens Wiklander if (!uuid)
640334316feSJens Wiklander goto error;
641334316feSJens Wiklander
642334316feSJens Wiklander TEE_MemMove(uuid, &db_objs->uuids[idx], sizeof(*uuid));
643334316feSJens Wiklander
644bc555ee0SVesa Jääskeläinen obj = create_token_object(NULL, uuid, token);
645334316feSJens Wiklander if (!obj)
646334316feSJens Wiklander TEE_Panic(0);
647334316feSJens Wiklander
648334316feSJens Wiklander LIST_INSERT_HEAD(&token->object_list, obj, link);
649334316feSJens Wiklander }
650334316feSJens Wiklander
651c84ccd0aSEtienne Carriere } else if (res == TEE_ERROR_ITEM_NOT_FOUND) {
65260659a86SEtienne Carriere char file[PERSISTENT_OBJECT_ID_LEN] = { };
65360659a86SEtienne Carriere
654c84ccd0aSEtienne Carriere IMSG("PKCS11 token %u: init db", token_id);
655c84ccd0aSEtienne Carriere
656c84ccd0aSEtienne Carriere TEE_MemFill(db_main, 0, sizeof(*db_main));
657c84ccd0aSEtienne Carriere TEE_MemFill(db_main->label, '*', sizeof(db_main->label));
658c84ccd0aSEtienne Carriere
659c84ccd0aSEtienne Carriere db_main->flags = PKCS11_CKFT_SO_PIN_TO_BE_CHANGED |
660c84ccd0aSEtienne Carriere PKCS11_CKFT_USER_PIN_TO_BE_CHANGED |
661c84ccd0aSEtienne Carriere PKCS11_CKFT_RNG |
662c84ccd0aSEtienne Carriere PKCS11_CKFT_LOGIN_REQUIRED;
663c84ccd0aSEtienne Carriere
66460659a86SEtienne Carriere res = get_db_file_name(token, file, sizeof(file));
66560659a86SEtienne Carriere if (res)
66660659a86SEtienne Carriere TEE_Panic(0);
66760659a86SEtienne Carriere
668334316feSJens Wiklander /*
669334316feSJens Wiklander * Object stores persistent state + persistent object
670334316feSJens Wiklander * references.
671*931c8c5eSWeizhao Jiang *
672*931c8c5eSWeizhao Jiang * Allocate the initial_data buffer to encompass the data from
673*931c8c5eSWeizhao Jiang * both db_main and db_objs. Since the initial data for the
674*931c8c5eSWeizhao Jiang * objects will be zeroed out upon creation, there’s no need
675*931c8c5eSWeizhao Jiang * to copy it from db_objs.
676334316feSJens Wiklander */
677*931c8c5eSWeizhao Jiang initial_data_size = sizeof(*db_main) + sizeof(*db_objs);
678*931c8c5eSWeizhao Jiang initial_data = TEE_Malloc(initial_data_size,
679*931c8c5eSWeizhao Jiang TEE_MALLOC_FILL_ZERO);
680*931c8c5eSWeizhao Jiang if (!initial_data) {
681*931c8c5eSWeizhao Jiang EMSG("Failed to allocate initial_data buffer");
682*931c8c5eSWeizhao Jiang goto error;
683*931c8c5eSWeizhao Jiang }
684*931c8c5eSWeizhao Jiang TEE_MemMove(initial_data, db_main, sizeof(*db_main));
685c84ccd0aSEtienne Carriere res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
68660659a86SEtienne Carriere file, sizeof(file),
687c84ccd0aSEtienne Carriere TEE_DATA_FLAG_ACCESS_READ |
688c84ccd0aSEtienne Carriere TEE_DATA_FLAG_ACCESS_WRITE,
689c84ccd0aSEtienne Carriere TEE_HANDLE_NULL,
690*931c8c5eSWeizhao Jiang initial_data,
691*931c8c5eSWeizhao Jiang initial_data_size,
692c84ccd0aSEtienne Carriere &db_hdl);
693*931c8c5eSWeizhao Jiang TEE_Free(initial_data);
694c84ccd0aSEtienne Carriere if (res) {
69559a5257eSEtienne Carriere EMSG("Failed to create db: %#"PRIx32, res);
696c84ccd0aSEtienne Carriere goto error;
697c84ccd0aSEtienne Carriere }
698334316feSJens Wiklander
699c84ccd0aSEtienne Carriere } else {
700c84ccd0aSEtienne Carriere goto error;
701c84ccd0aSEtienne Carriere }
702c84ccd0aSEtienne Carriere
703c84ccd0aSEtienne Carriere token->db_main = db_main;
704334316feSJens Wiklander token->db_objs = db_objs;
705c84ccd0aSEtienne Carriere TEE_CloseObject(db_hdl);
706c84ccd0aSEtienne Carriere
707c84ccd0aSEtienne Carriere return token;
708c84ccd0aSEtienne Carriere
709c84ccd0aSEtienne Carriere error:
710c84ccd0aSEtienne Carriere TEE_Free(db_main);
711334316feSJens Wiklander TEE_Free(db_objs);
712c84ccd0aSEtienne Carriere if (db_hdl != TEE_HANDLE_NULL)
713c84ccd0aSEtienne Carriere TEE_CloseObject(db_hdl);
714c84ccd0aSEtienne Carriere
715c84ccd0aSEtienne Carriere return NULL;
716c84ccd0aSEtienne Carriere }
717