xref: /optee_os/ta/pkcs11/src/persistent_token.c (revision 931c8c5e79f08c60e42b47fadf59d67b1862810b)
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