xref: /optee_os/ta/pkcs11/src/persistent_token.c (revision 59a5257e4f4786b248670bf93d42b0ffd2d5da53)
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 
13c84ccd0aSEtienne Carriere #include "pkcs11_token.h"
14c84ccd0aSEtienne Carriere #include "pkcs11_helpers.h"
15c84ccd0aSEtienne Carriere 
1660659a86SEtienne Carriere #define PERSISTENT_OBJECT_ID_LEN	32
1760659a86SEtienne Carriere 
1860659a86SEtienne Carriere /*
1960659a86SEtienne Carriere  * Token persistent objects
20334316feSJens Wiklander  *
21334316feSJens Wiklander  * The persistent objects are each identified by a UUID.
22334316feSJens Wiklander  * The persistent object database stores the list of the UUIDs registered. For
23334316feSJens Wiklander  * each it is expected that a file of ID "UUID" is stored in the TA secure
24334316feSJens Wiklander  * storage.
2560659a86SEtienne Carriere  */
2660659a86SEtienne Carriere static TEE_Result get_db_file_name(struct ck_token *token,
2760659a86SEtienne Carriere 				   char *name, size_t size)
28c84ccd0aSEtienne Carriere {
2960659a86SEtienne Carriere 	int n = snprintf(name, size, "token.db.%u", get_token_id(token));
3060659a86SEtienne Carriere 
3160659a86SEtienne Carriere 	if (n < 0 || (size_t)n >= size)
3260659a86SEtienne Carriere 		return TEE_ERROR_SECURITY;
3360659a86SEtienne Carriere 	else
3460659a86SEtienne Carriere 		return TEE_SUCCESS;
3560659a86SEtienne Carriere }
3660659a86SEtienne Carriere 
3760659a86SEtienne Carriere static TEE_Result open_db_file(struct ck_token *token,
3860659a86SEtienne Carriere 			       TEE_ObjectHandle *out_hdl)
3960659a86SEtienne Carriere {
4060659a86SEtienne Carriere 	char file[PERSISTENT_OBJECT_ID_LEN] = { };
4160659a86SEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
4260659a86SEtienne Carriere 
4360659a86SEtienne Carriere 	res = get_db_file_name(token, file, sizeof(file));
4460659a86SEtienne Carriere 	if (res)
4560659a86SEtienne Carriere 		return res;
4660659a86SEtienne Carriere 
4760659a86SEtienne Carriere 	return TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, file, sizeof(file),
4860659a86SEtienne Carriere 					TEE_DATA_FLAG_ACCESS_READ |
4960659a86SEtienne Carriere 					TEE_DATA_FLAG_ACCESS_WRITE,
5060659a86SEtienne Carriere 					out_hdl);
5160659a86SEtienne Carriere }
5260659a86SEtienne Carriere 
53e86828f4SJens Wiklander void update_persistent_db(struct ck_token *token)
54e86828f4SJens Wiklander {
55e86828f4SJens Wiklander 	TEE_Result res = TEE_ERROR_GENERIC;
56e86828f4SJens Wiklander 	TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
57e86828f4SJens Wiklander 
58e86828f4SJens Wiklander 	res = open_db_file(token, &db_hdl);
59e86828f4SJens Wiklander 	if (res) {
60e86828f4SJens Wiklander 		EMSG("Failed to open token persistent db: %#"PRIx32, res);
61e86828f4SJens Wiklander 		TEE_Panic(0);
62e86828f4SJens Wiklander 	}
63e86828f4SJens Wiklander 	res = TEE_WriteObjectData(db_hdl, token->db_main,
64e86828f4SJens Wiklander 				  sizeof(*token->db_main));
65e86828f4SJens Wiklander 	if (res) {
66e86828f4SJens Wiklander 		EMSG("Failed to write to token persistent db: %#"PRIx32, res);
67e86828f4SJens Wiklander 		TEE_Panic(0);
68e86828f4SJens Wiklander 	}
69e86828f4SJens Wiklander 
70e86828f4SJens Wiklander 	TEE_CloseObject(db_hdl);
71e86828f4SJens Wiklander }
72e86828f4SJens Wiklander 
73bef8bc68SJens Wiklander static enum pkcs11_rc do_hash(uint32_t user, const uint8_t *pin,
74bef8bc68SJens Wiklander 			      size_t pin_size, uint32_t salt,
75bef8bc68SJens Wiklander 			      uint8_t hash[TEE_MAX_HASH_SIZE])
76bef8bc68SJens Wiklander {
77bef8bc68SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
78bef8bc68SJens Wiklander 	TEE_OperationHandle oh = TEE_HANDLE_NULL;
79bef8bc68SJens Wiklander 	uint32_t sz = TEE_MAX_HASH_SIZE;
80bef8bc68SJens Wiklander 
81bef8bc68SJens Wiklander 	res = TEE_AllocateOperation(&oh, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0);
82bef8bc68SJens Wiklander 	if (res)
83bef8bc68SJens Wiklander 		return tee2pkcs_error(res);
84bef8bc68SJens Wiklander 
85bef8bc68SJens Wiklander 	TEE_DigestUpdate(oh, &user, sizeof(user));
86bef8bc68SJens Wiklander 	TEE_DigestUpdate(oh, &salt, sizeof(salt));
87bef8bc68SJens Wiklander 	res = TEE_DigestDoFinal(oh, pin, pin_size, hash, &sz);
88bef8bc68SJens Wiklander 	TEE_FreeOperation(oh);
89bef8bc68SJens Wiklander 
90bef8bc68SJens Wiklander 	if (res)
91bef8bc68SJens Wiklander 		return PKCS11_CKR_GENERAL_ERROR;
92bef8bc68SJens Wiklander 
93bef8bc68SJens Wiklander 	memset(hash + sz, 0, TEE_MAX_HASH_SIZE - sz);
94bef8bc68SJens Wiklander 	return PKCS11_CKR_OK;
95bef8bc68SJens Wiklander }
96bef8bc68SJens Wiklander 
97bef8bc68SJens Wiklander enum pkcs11_rc hash_pin(enum pkcs11_user_type user, const uint8_t *pin,
98bef8bc68SJens Wiklander 			size_t pin_size, uint32_t *salt,
99bef8bc68SJens Wiklander 			uint8_t hash[TEE_MAX_HASH_SIZE])
100bef8bc68SJens Wiklander {
101bef8bc68SJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
102bef8bc68SJens Wiklander 	uint32_t s = 0;
103bef8bc68SJens Wiklander 
104bef8bc68SJens Wiklander 	TEE_GenerateRandom(&s, sizeof(s));
105bef8bc68SJens Wiklander 	if (!s)
106bef8bc68SJens Wiklander 		s++;
107bef8bc68SJens Wiklander 
108bef8bc68SJens Wiklander 	rc = do_hash(user, pin, pin_size, s, hash);
109bef8bc68SJens Wiklander 	if (!rc)
110bef8bc68SJens Wiklander 		*salt = s;
111bef8bc68SJens Wiklander 	return rc;
112bef8bc68SJens Wiklander }
113bef8bc68SJens Wiklander 
114bef8bc68SJens Wiklander enum pkcs11_rc verify_pin(enum pkcs11_user_type user, const uint8_t *pin,
115bef8bc68SJens Wiklander 			  size_t pin_size, uint32_t salt,
116bef8bc68SJens Wiklander 			  const uint8_t hash[TEE_MAX_HASH_SIZE])
117bef8bc68SJens Wiklander {
118bef8bc68SJens Wiklander 	uint8_t tmp_hash[TEE_MAX_HASH_SIZE] = { 0 };
119bef8bc68SJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
120bef8bc68SJens Wiklander 
121bef8bc68SJens Wiklander 	rc = do_hash(user, pin, pin_size, salt, tmp_hash);
122bef8bc68SJens Wiklander 	if (rc)
123bef8bc68SJens Wiklander 		return rc;
124bef8bc68SJens Wiklander 
125bef8bc68SJens Wiklander 	if (buf_compare_ct(tmp_hash, hash, TEE_MAX_HASH_SIZE))
126bef8bc68SJens Wiklander 		rc = PKCS11_CKR_PIN_INCORRECT;
127bef8bc68SJens Wiklander 
128bef8bc68SJens Wiklander 	return rc;
129bef8bc68SJens Wiklander }
130bef8bc68SJens Wiklander 
131c84ccd0aSEtienne Carriere /*
13260659a86SEtienne Carriere  * Release resources relate to persistent database
13360659a86SEtienne Carriere  */
13460659a86SEtienne Carriere void close_persistent_db(struct ck_token *token __unused)
13560659a86SEtienne Carriere {
13660659a86SEtienne Carriere }
13760659a86SEtienne Carriere 
138334316feSJens Wiklander static int get_persistent_obj_idx(struct ck_token *token, TEE_UUID *uuid)
139334316feSJens Wiklander {
140334316feSJens Wiklander 	size_t i = 0;
141334316feSJens Wiklander 
142334316feSJens Wiklander 	if (!uuid)
143334316feSJens Wiklander 		return -1;
144334316feSJens Wiklander 
145334316feSJens Wiklander 	for (i = 0; i < token->db_objs->count; i++)
146334316feSJens Wiklander 		if (!TEE_MemCompare(token->db_objs->uuids + i,
147334316feSJens Wiklander 				    uuid, sizeof(TEE_UUID)))
148334316feSJens Wiklander 			return i;
149334316feSJens Wiklander 
150334316feSJens Wiklander 	return -1;
151334316feSJens Wiklander }
152334316feSJens Wiklander 
153334316feSJens Wiklander /* UUID for persistent object */
154334316feSJens Wiklander enum pkcs11_rc create_object_uuid(struct ck_token *token,
155334316feSJens Wiklander 				  struct pkcs11_object *obj)
156334316feSJens Wiklander {
157334316feSJens Wiklander 	assert(!obj->uuid);
158334316feSJens Wiklander 
159334316feSJens Wiklander 	obj->uuid = TEE_Malloc(sizeof(TEE_UUID),
160334316feSJens Wiklander 			       TEE_USER_MEM_HINT_NO_FILL_ZERO);
161334316feSJens Wiklander 	if (!obj->uuid)
162334316feSJens Wiklander 		return PKCS11_CKR_DEVICE_MEMORY;
163334316feSJens Wiklander 
164334316feSJens Wiklander 	do {
165334316feSJens Wiklander 		TEE_GenerateRandom(obj->uuid, sizeof(TEE_UUID));
166334316feSJens Wiklander 	} while (get_persistent_obj_idx(token, obj->uuid) >= 0);
167334316feSJens Wiklander 
168334316feSJens Wiklander 	return PKCS11_CKR_OK;
169334316feSJens Wiklander }
170334316feSJens Wiklander 
171334316feSJens Wiklander void destroy_object_uuid(struct ck_token *token __maybe_unused,
172334316feSJens Wiklander 			 struct pkcs11_object *obj)
173334316feSJens Wiklander {
174334316feSJens Wiklander 	assert(get_persistent_obj_idx(token, obj->uuid) < 0);
175334316feSJens Wiklander 
176334316feSJens Wiklander 	TEE_Free(obj->uuid);
177334316feSJens Wiklander 	obj->uuid = NULL;
178334316feSJens Wiklander }
179334316feSJens Wiklander 
180334316feSJens Wiklander enum pkcs11_rc get_persistent_objects_list(struct ck_token *token,
181334316feSJens Wiklander 					   TEE_UUID *array, size_t *size)
182334316feSJens Wiklander {
183334316feSJens Wiklander 	size_t out_size = *size;
184334316feSJens Wiklander 
185334316feSJens Wiklander 	*size = token->db_objs->count * sizeof(TEE_UUID);
186334316feSJens Wiklander 
187334316feSJens Wiklander 	if (out_size < *size)
188334316feSJens Wiklander 		return PKCS11_CKR_BUFFER_TOO_SMALL;
189334316feSJens Wiklander 
190334316feSJens Wiklander 	if (array)
191334316feSJens Wiklander 		TEE_MemMove(array, token->db_objs->uuids, *size);
192334316feSJens Wiklander 
193334316feSJens Wiklander 	return PKCS11_CKR_OK;
194334316feSJens Wiklander }
195334316feSJens Wiklander 
196334316feSJens Wiklander enum pkcs11_rc unregister_persistent_object(struct ck_token *token,
197334316feSJens Wiklander 					    TEE_UUID *uuid)
198334316feSJens Wiklander {
199334316feSJens Wiklander 	TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
200334316feSJens Wiklander 	struct token_persistent_objs *ptr = NULL;
201334316feSJens Wiklander 	TEE_Result res = TEE_ERROR_GENERIC;
202334316feSJens Wiklander 	int count = 0;
203334316feSJens Wiklander 	int idx = 0;
204334316feSJens Wiklander 
205334316feSJens Wiklander 	if (!uuid)
206334316feSJens Wiklander 		return PKCS11_CKR_OK;
207334316feSJens Wiklander 
208334316feSJens Wiklander 	idx = get_persistent_obj_idx(token, uuid);
209334316feSJens Wiklander 	if (idx < 0) {
210334316feSJens Wiklander 		DMSG("Cannot unregister an invalid persistent object");
211334316feSJens Wiklander 		return PKCS11_RV_NOT_FOUND;
212334316feSJens Wiklander 	}
213334316feSJens Wiklander 
214334316feSJens Wiklander 	ptr = TEE_Malloc(sizeof(struct token_persistent_objs) +
215334316feSJens Wiklander 			 ((token->db_objs->count - 1) * sizeof(TEE_UUID)),
216334316feSJens Wiklander 			 TEE_USER_MEM_HINT_NO_FILL_ZERO);
217334316feSJens Wiklander 	if (!ptr)
218334316feSJens Wiklander 		return PKCS11_CKR_DEVICE_MEMORY;
219334316feSJens Wiklander 
220334316feSJens Wiklander 	res = open_db_file(token, &db_hdl);
221334316feSJens Wiklander 	if (res)
222334316feSJens Wiklander 		goto out;
223334316feSJens Wiklander 
224334316feSJens Wiklander 	res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main),
225334316feSJens Wiklander 				 TEE_DATA_SEEK_SET);
226334316feSJens Wiklander 	if (res) {
227334316feSJens Wiklander 		DMSG("Failed to read database");
228334316feSJens Wiklander 		goto out;
229334316feSJens Wiklander 	}
230334316feSJens Wiklander 
231334316feSJens Wiklander 	TEE_MemMove(ptr, token->db_objs,
232334316feSJens Wiklander 		    sizeof(struct token_persistent_objs) +
233334316feSJens Wiklander 		    idx * sizeof(TEE_UUID));
234334316feSJens Wiklander 
235334316feSJens Wiklander 	ptr->count--;
236334316feSJens Wiklander 	count = ptr->count - idx;
237334316feSJens Wiklander 
238334316feSJens Wiklander 	TEE_MemMove(&ptr->uuids[idx],
239334316feSJens Wiklander 		    &token->db_objs->uuids[idx + 1],
240334316feSJens Wiklander 		    count * sizeof(TEE_UUID));
241334316feSJens Wiklander 
242334316feSJens Wiklander 	res = TEE_WriteObjectData(db_hdl, ptr,
243334316feSJens Wiklander 				  sizeof(struct token_persistent_objs) +
244334316feSJens Wiklander 				  ptr->count * sizeof(TEE_UUID));
245334316feSJens Wiklander 	if (res)
246334316feSJens Wiklander 		DMSG("Failed to update database");
247334316feSJens Wiklander 	TEE_Free(token->db_objs);
248334316feSJens Wiklander 	token->db_objs = ptr;
249334316feSJens Wiklander 	ptr = NULL;
250334316feSJens Wiklander 
251334316feSJens Wiklander out:
252334316feSJens Wiklander 	TEE_CloseObject(db_hdl);
253334316feSJens Wiklander 	TEE_Free(ptr);
254334316feSJens Wiklander 
255334316feSJens Wiklander 	return tee2pkcs_error(res);
256334316feSJens Wiklander }
257334316feSJens Wiklander 
258334316feSJens Wiklander enum pkcs11_rc register_persistent_object(struct ck_token *token,
259334316feSJens Wiklander 					  TEE_UUID *uuid)
260334316feSJens Wiklander {
261334316feSJens Wiklander 	TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
262334316feSJens Wiklander 	TEE_Result res = TEE_ERROR_GENERIC;
263334316feSJens Wiklander 	void *ptr = NULL;
264334316feSJens Wiklander 	size_t size = 0;
265334316feSJens Wiklander 	int count = 0;
266334316feSJens Wiklander 
267334316feSJens Wiklander 	if (get_persistent_obj_idx(token, uuid) >= 0)
268334316feSJens Wiklander 		TEE_Panic(0);
269334316feSJens Wiklander 
270334316feSJens Wiklander 	count = token->db_objs->count;
271334316feSJens Wiklander 	ptr = TEE_Realloc(token->db_objs,
272334316feSJens Wiklander 			  sizeof(struct token_persistent_objs) +
273334316feSJens Wiklander 			  ((count + 1) * sizeof(TEE_UUID)));
274334316feSJens Wiklander 	if (!ptr)
275334316feSJens Wiklander 		return PKCS11_CKR_DEVICE_MEMORY;
276334316feSJens Wiklander 
277334316feSJens Wiklander 	token->db_objs = ptr;
278334316feSJens Wiklander 	TEE_MemMove(token->db_objs->uuids + count, uuid, sizeof(TEE_UUID));
279334316feSJens Wiklander 
280334316feSJens Wiklander 	size = sizeof(struct token_persistent_main) +
281334316feSJens Wiklander 	       sizeof(struct token_persistent_objs) +
282334316feSJens Wiklander 	       count * sizeof(TEE_UUID);
283334316feSJens Wiklander 
284334316feSJens Wiklander 	res = open_db_file(token, &db_hdl);
285334316feSJens Wiklander 	if (res)
286334316feSJens Wiklander 		goto out;
287334316feSJens Wiklander 
288334316feSJens Wiklander 	res = TEE_TruncateObjectData(db_hdl, size + sizeof(TEE_UUID));
289334316feSJens Wiklander 	if (res)
290334316feSJens Wiklander 		goto out;
291334316feSJens Wiklander 
292334316feSJens Wiklander 	res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main),
293334316feSJens Wiklander 				 TEE_DATA_SEEK_SET);
294334316feSJens Wiklander 	if (res)
295334316feSJens Wiklander 		goto out;
296334316feSJens Wiklander 
297334316feSJens Wiklander 	token->db_objs->count++;
298334316feSJens Wiklander 
299334316feSJens Wiklander 	res = TEE_WriteObjectData(db_hdl, token->db_objs,
300334316feSJens Wiklander 				  sizeof(struct token_persistent_objs) +
301334316feSJens Wiklander 				  token->db_objs->count * sizeof(TEE_UUID));
302334316feSJens Wiklander 	if (res)
303334316feSJens Wiklander 		token->db_objs->count--;
304334316feSJens Wiklander 
305334316feSJens Wiklander out:
306334316feSJens Wiklander 	TEE_CloseObject(db_hdl);
307334316feSJens Wiklander 
308334316feSJens Wiklander 	return tee2pkcs_error(res);
309334316feSJens Wiklander }
310334316feSJens Wiklander 
31160659a86SEtienne Carriere /*
312c84ccd0aSEtienne Carriere  * Return the token instance, either initialized from reset or initialized
313c84ccd0aSEtienne Carriere  * from the token persistent state if found.
314c84ccd0aSEtienne Carriere  */
315c84ccd0aSEtienne Carriere struct ck_token *init_persistent_db(unsigned int token_id)
316c84ccd0aSEtienne Carriere {
317c84ccd0aSEtienne Carriere 	struct ck_token *token = get_token(token_id);
318c84ccd0aSEtienne Carriere 	TEE_Result res = TEE_ERROR_GENERIC;
319c84ccd0aSEtienne Carriere 	TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
32060659a86SEtienne Carriere 	/* Copy persistent database: main db and object db */
321c84ccd0aSEtienne Carriere 	struct token_persistent_main *db_main = NULL;
322334316feSJens Wiklander 	struct token_persistent_objs *db_objs = NULL;
323334316feSJens Wiklander 	void *ptr = NULL;
324c84ccd0aSEtienne Carriere 
325c84ccd0aSEtienne Carriere 	if (!token)
326c84ccd0aSEtienne Carriere 		return NULL;
327c84ccd0aSEtienne Carriere 
328334316feSJens Wiklander 	LIST_INIT(&token->object_list);
329334316feSJens Wiklander 
330c84ccd0aSEtienne Carriere 	db_main = TEE_Malloc(sizeof(*db_main), TEE_MALLOC_FILL_ZERO);
331334316feSJens Wiklander 	db_objs = TEE_Malloc(sizeof(*db_objs), TEE_MALLOC_FILL_ZERO);
332334316feSJens Wiklander 	if (!db_main || !db_objs)
333c84ccd0aSEtienne Carriere 		goto error;
334c84ccd0aSEtienne Carriere 
33560659a86SEtienne Carriere 	res = open_db_file(token, &db_hdl);
336c84ccd0aSEtienne Carriere 
337c84ccd0aSEtienne Carriere 	if (res == TEE_SUCCESS) {
338c84ccd0aSEtienne Carriere 		uint32_t size = 0;
339334316feSJens Wiklander 		size_t idx = 0;
340c84ccd0aSEtienne Carriere 
341c84ccd0aSEtienne Carriere 		IMSG("PKCS11 token %u: load db", token_id);
342c84ccd0aSEtienne Carriere 
343c84ccd0aSEtienne Carriere 		size = sizeof(*db_main);
344c84ccd0aSEtienne Carriere 		res = TEE_ReadObjectData(db_hdl, db_main, size, &size);
345c84ccd0aSEtienne Carriere 		if (res || size != sizeof(*db_main))
346c84ccd0aSEtienne Carriere 			TEE_Panic(0);
347334316feSJens Wiklander 
348334316feSJens Wiklander 		size = sizeof(*db_objs);
349334316feSJens Wiklander 		res = TEE_ReadObjectData(db_hdl, db_objs, size, &size);
350334316feSJens Wiklander 		if (res || size != sizeof(*db_objs))
351334316feSJens Wiklander 			TEE_Panic(0);
352334316feSJens Wiklander 
353334316feSJens Wiklander 		size += db_objs->count * sizeof(TEE_UUID);
354334316feSJens Wiklander 		ptr = TEE_Realloc(db_objs, size);
355334316feSJens Wiklander 		if (!ptr)
356334316feSJens Wiklander 			goto error;
357334316feSJens Wiklander 
358334316feSJens Wiklander 		db_objs = ptr;
359334316feSJens Wiklander 		size -= sizeof(struct token_persistent_objs);
360334316feSJens Wiklander 		res = TEE_ReadObjectData(db_hdl, db_objs->uuids, size, &size);
361334316feSJens Wiklander 		if (res || size != (db_objs->count * sizeof(TEE_UUID)))
362334316feSJens Wiklander 			TEE_Panic(0);
363334316feSJens Wiklander 
364334316feSJens Wiklander 		for (idx = 0; idx < db_objs->count; idx++) {
365334316feSJens Wiklander 			/* Create an empty object instance */
366334316feSJens Wiklander 			struct pkcs11_object *obj = NULL;
367334316feSJens Wiklander 			TEE_UUID *uuid = NULL;
368334316feSJens Wiklander 
369334316feSJens Wiklander 			uuid = TEE_Malloc(sizeof(TEE_UUID),
370334316feSJens Wiklander 					  TEE_USER_MEM_HINT_NO_FILL_ZERO);
371334316feSJens Wiklander 			if (!uuid)
372334316feSJens Wiklander 				goto error;
373334316feSJens Wiklander 
374334316feSJens Wiklander 			TEE_MemMove(uuid, &db_objs->uuids[idx], sizeof(*uuid));
375334316feSJens Wiklander 
376334316feSJens Wiklander 			obj = create_token_object(NULL, uuid);
377334316feSJens Wiklander 			if (!obj)
378334316feSJens Wiklander 				TEE_Panic(0);
379334316feSJens Wiklander 
380334316feSJens Wiklander 			LIST_INSERT_HEAD(&token->object_list, obj, link);
381334316feSJens Wiklander 		}
382334316feSJens Wiklander 
383c84ccd0aSEtienne Carriere 	} else if (res == TEE_ERROR_ITEM_NOT_FOUND) {
38460659a86SEtienne Carriere 		char file[PERSISTENT_OBJECT_ID_LEN] = { };
38560659a86SEtienne Carriere 
386c84ccd0aSEtienne Carriere 		IMSG("PKCS11 token %u: init db", token_id);
387c84ccd0aSEtienne Carriere 
388c84ccd0aSEtienne Carriere 		TEE_MemFill(db_main, 0, sizeof(*db_main));
389c84ccd0aSEtienne Carriere 		TEE_MemFill(db_main->label, '*', sizeof(db_main->label));
390c84ccd0aSEtienne Carriere 
391c84ccd0aSEtienne Carriere 		db_main->flags = PKCS11_CKFT_SO_PIN_TO_BE_CHANGED |
392c84ccd0aSEtienne Carriere 				 PKCS11_CKFT_USER_PIN_TO_BE_CHANGED |
393c84ccd0aSEtienne Carriere 				 PKCS11_CKFT_RNG |
394c84ccd0aSEtienne Carriere 				 PKCS11_CKFT_DUAL_CRYPTO_OPERATIONS |
395c84ccd0aSEtienne Carriere 				 PKCS11_CKFT_LOGIN_REQUIRED;
396c84ccd0aSEtienne Carriere 
39760659a86SEtienne Carriere 		res = get_db_file_name(token, file, sizeof(file));
39860659a86SEtienne Carriere 		if (res)
39960659a86SEtienne Carriere 			TEE_Panic(0);
40060659a86SEtienne Carriere 
401334316feSJens Wiklander 		/*
402334316feSJens Wiklander 		 * Object stores persistent state + persistent object
403334316feSJens Wiklander 		 * references.
404334316feSJens Wiklander 		 */
405c84ccd0aSEtienne Carriere 		res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
40660659a86SEtienne Carriere 						 file, sizeof(file),
407c84ccd0aSEtienne Carriere 						 TEE_DATA_FLAG_ACCESS_READ |
408c84ccd0aSEtienne Carriere 						 TEE_DATA_FLAG_ACCESS_WRITE,
409c84ccd0aSEtienne Carriere 						 TEE_HANDLE_NULL,
410c84ccd0aSEtienne Carriere 						 db_main, sizeof(*db_main),
411c84ccd0aSEtienne Carriere 						 &db_hdl);
412c84ccd0aSEtienne Carriere 		if (res) {
413*59a5257eSEtienne Carriere 			EMSG("Failed to create db: %#"PRIx32, res);
414c84ccd0aSEtienne Carriere 			goto error;
415c84ccd0aSEtienne Carriere 		}
416334316feSJens Wiklander 
417334316feSJens Wiklander 		res = TEE_TruncateObjectData(db_hdl, sizeof(*db_main) +
418334316feSJens Wiklander 						     sizeof(*db_objs));
419334316feSJens Wiklander 		if (res)
420334316feSJens Wiklander 			TEE_Panic(0);
421334316feSJens Wiklander 
422334316feSJens Wiklander 		res = TEE_SeekObjectData(db_hdl, sizeof(*db_main),
423334316feSJens Wiklander 					 TEE_DATA_SEEK_SET);
424334316feSJens Wiklander 		if (res)
425334316feSJens Wiklander 			TEE_Panic(0);
426334316feSJens Wiklander 
427334316feSJens Wiklander 		db_objs->count = 0;
428334316feSJens Wiklander 		res = TEE_WriteObjectData(db_hdl, db_objs, sizeof(*db_objs));
429334316feSJens Wiklander 		if (res)
430334316feSJens Wiklander 			TEE_Panic(0);
431334316feSJens Wiklander 
432c84ccd0aSEtienne Carriere 	} else {
433c84ccd0aSEtienne Carriere 		goto error;
434c84ccd0aSEtienne Carriere 	}
435c84ccd0aSEtienne Carriere 
436c84ccd0aSEtienne Carriere 	token->db_main = db_main;
437334316feSJens Wiklander 	token->db_objs = db_objs;
438c84ccd0aSEtienne Carriere 	TEE_CloseObject(db_hdl);
439c84ccd0aSEtienne Carriere 
440c84ccd0aSEtienne Carriere 	return token;
441c84ccd0aSEtienne Carriere 
442c84ccd0aSEtienne Carriere error:
443c84ccd0aSEtienne Carriere 	TEE_Free(db_main);
444334316feSJens Wiklander 	TEE_Free(db_objs);
445c84ccd0aSEtienne Carriere 	if (db_hdl != TEE_HANDLE_NULL)
446c84ccd0aSEtienne Carriere 		TEE_CloseObject(db_hdl);
447c84ccd0aSEtienne Carriere 
448c84ccd0aSEtienne Carriere 	return NULL;
449c84ccd0aSEtienne Carriere }
450