xref: /optee_os/ta/pkcs11/src/persistent_token.c (revision 334316feab7445d4cb040ee11dbbf53d61ad2320)
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
20*334316feSJens Wiklander  *
21*334316feSJens Wiklander  * The persistent objects are each identified by a UUID.
22*334316feSJens Wiklander  * The persistent object database stores the list of the UUIDs registered. For
23*334316feSJens Wiklander  * each it is expected that a file of ID "UUID" is stored in the TA secure
24*334316feSJens 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 
138*334316feSJens Wiklander static int get_persistent_obj_idx(struct ck_token *token, TEE_UUID *uuid)
139*334316feSJens Wiklander {
140*334316feSJens Wiklander 	size_t i = 0;
141*334316feSJens Wiklander 
142*334316feSJens Wiklander 	if (!uuid)
143*334316feSJens Wiklander 		return -1;
144*334316feSJens Wiklander 
145*334316feSJens Wiklander 	for (i = 0; i < token->db_objs->count; i++)
146*334316feSJens Wiklander 		if (!TEE_MemCompare(token->db_objs->uuids + i,
147*334316feSJens Wiklander 				    uuid, sizeof(TEE_UUID)))
148*334316feSJens Wiklander 			return i;
149*334316feSJens Wiklander 
150*334316feSJens Wiklander 	return -1;
151*334316feSJens Wiklander }
152*334316feSJens Wiklander 
153*334316feSJens Wiklander /* UUID for persistent object */
154*334316feSJens Wiklander enum pkcs11_rc create_object_uuid(struct ck_token *token,
155*334316feSJens Wiklander 				  struct pkcs11_object *obj)
156*334316feSJens Wiklander {
157*334316feSJens Wiklander 	assert(!obj->uuid);
158*334316feSJens Wiklander 
159*334316feSJens Wiklander 	obj->uuid = TEE_Malloc(sizeof(TEE_UUID),
160*334316feSJens Wiklander 			       TEE_USER_MEM_HINT_NO_FILL_ZERO);
161*334316feSJens Wiklander 	if (!obj->uuid)
162*334316feSJens Wiklander 		return PKCS11_CKR_DEVICE_MEMORY;
163*334316feSJens Wiklander 
164*334316feSJens Wiklander 	do {
165*334316feSJens Wiklander 		TEE_GenerateRandom(obj->uuid, sizeof(TEE_UUID));
166*334316feSJens Wiklander 	} while (get_persistent_obj_idx(token, obj->uuid) >= 0);
167*334316feSJens Wiklander 
168*334316feSJens Wiklander 	return PKCS11_CKR_OK;
169*334316feSJens Wiklander }
170*334316feSJens Wiklander 
171*334316feSJens Wiklander void destroy_object_uuid(struct ck_token *token __maybe_unused,
172*334316feSJens Wiklander 			 struct pkcs11_object *obj)
173*334316feSJens Wiklander {
174*334316feSJens Wiklander 	assert(get_persistent_obj_idx(token, obj->uuid) < 0);
175*334316feSJens Wiklander 
176*334316feSJens Wiklander 	TEE_Free(obj->uuid);
177*334316feSJens Wiklander 	obj->uuid = NULL;
178*334316feSJens Wiklander }
179*334316feSJens Wiklander 
180*334316feSJens Wiklander enum pkcs11_rc get_persistent_objects_list(struct ck_token *token,
181*334316feSJens Wiklander 					   TEE_UUID *array, size_t *size)
182*334316feSJens Wiklander {
183*334316feSJens Wiklander 	size_t out_size = *size;
184*334316feSJens Wiklander 
185*334316feSJens Wiklander 	*size = token->db_objs->count * sizeof(TEE_UUID);
186*334316feSJens Wiklander 
187*334316feSJens Wiklander 	if (out_size < *size)
188*334316feSJens Wiklander 		return PKCS11_CKR_BUFFER_TOO_SMALL;
189*334316feSJens Wiklander 
190*334316feSJens Wiklander 	if (array)
191*334316feSJens Wiklander 		TEE_MemMove(array, token->db_objs->uuids, *size);
192*334316feSJens Wiklander 
193*334316feSJens Wiklander 	return PKCS11_CKR_OK;
194*334316feSJens Wiklander }
195*334316feSJens Wiklander 
196*334316feSJens Wiklander enum pkcs11_rc unregister_persistent_object(struct ck_token *token,
197*334316feSJens Wiklander 					    TEE_UUID *uuid)
198*334316feSJens Wiklander {
199*334316feSJens Wiklander 	TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
200*334316feSJens Wiklander 	struct token_persistent_objs *ptr = NULL;
201*334316feSJens Wiklander 	TEE_Result res = TEE_ERROR_GENERIC;
202*334316feSJens Wiklander 	int count = 0;
203*334316feSJens Wiklander 	int idx = 0;
204*334316feSJens Wiklander 
205*334316feSJens Wiklander 	if (!uuid)
206*334316feSJens Wiklander 		return PKCS11_CKR_OK;
207*334316feSJens Wiklander 
208*334316feSJens Wiklander 	idx = get_persistent_obj_idx(token, uuid);
209*334316feSJens Wiklander 	if (idx < 0) {
210*334316feSJens Wiklander 		DMSG("Cannot unregister an invalid persistent object");
211*334316feSJens Wiklander 		return PKCS11_RV_NOT_FOUND;
212*334316feSJens Wiklander 	}
213*334316feSJens Wiklander 
214*334316feSJens Wiklander 	ptr = TEE_Malloc(sizeof(struct token_persistent_objs) +
215*334316feSJens Wiklander 			 ((token->db_objs->count - 1) * sizeof(TEE_UUID)),
216*334316feSJens Wiklander 			 TEE_USER_MEM_HINT_NO_FILL_ZERO);
217*334316feSJens Wiklander 	if (!ptr)
218*334316feSJens Wiklander 		return PKCS11_CKR_DEVICE_MEMORY;
219*334316feSJens Wiklander 
220*334316feSJens Wiklander 	res = open_db_file(token, &db_hdl);
221*334316feSJens Wiklander 	if (res)
222*334316feSJens Wiklander 		goto out;
223*334316feSJens Wiklander 
224*334316feSJens Wiklander 	res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main),
225*334316feSJens Wiklander 				 TEE_DATA_SEEK_SET);
226*334316feSJens Wiklander 	if (res) {
227*334316feSJens Wiklander 		DMSG("Failed to read database");
228*334316feSJens Wiklander 		goto out;
229*334316feSJens Wiklander 	}
230*334316feSJens Wiklander 
231*334316feSJens Wiklander 	TEE_MemMove(ptr, token->db_objs,
232*334316feSJens Wiklander 		    sizeof(struct token_persistent_objs) +
233*334316feSJens Wiklander 		    idx * sizeof(TEE_UUID));
234*334316feSJens Wiklander 
235*334316feSJens Wiklander 	ptr->count--;
236*334316feSJens Wiklander 	count = ptr->count - idx;
237*334316feSJens Wiklander 
238*334316feSJens Wiklander 	TEE_MemMove(&ptr->uuids[idx],
239*334316feSJens Wiklander 		    &token->db_objs->uuids[idx + 1],
240*334316feSJens Wiklander 		    count * sizeof(TEE_UUID));
241*334316feSJens Wiklander 
242*334316feSJens Wiklander 	res = TEE_WriteObjectData(db_hdl, ptr,
243*334316feSJens Wiklander 				  sizeof(struct token_persistent_objs) +
244*334316feSJens Wiklander 				  ptr->count * sizeof(TEE_UUID));
245*334316feSJens Wiklander 	if (res)
246*334316feSJens Wiklander 		DMSG("Failed to update database");
247*334316feSJens Wiklander 	TEE_Free(token->db_objs);
248*334316feSJens Wiklander 	token->db_objs = ptr;
249*334316feSJens Wiklander 	ptr = NULL;
250*334316feSJens Wiklander 
251*334316feSJens Wiklander out:
252*334316feSJens Wiklander 	TEE_CloseObject(db_hdl);
253*334316feSJens Wiklander 	TEE_Free(ptr);
254*334316feSJens Wiklander 
255*334316feSJens Wiklander 	return tee2pkcs_error(res);
256*334316feSJens Wiklander }
257*334316feSJens Wiklander 
258*334316feSJens Wiklander enum pkcs11_rc register_persistent_object(struct ck_token *token,
259*334316feSJens Wiklander 					  TEE_UUID *uuid)
260*334316feSJens Wiklander {
261*334316feSJens Wiklander 	TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
262*334316feSJens Wiklander 	TEE_Result res = TEE_ERROR_GENERIC;
263*334316feSJens Wiklander 	void *ptr = NULL;
264*334316feSJens Wiklander 	size_t size = 0;
265*334316feSJens Wiklander 	int count = 0;
266*334316feSJens Wiklander 
267*334316feSJens Wiklander 	if (get_persistent_obj_idx(token, uuid) >= 0)
268*334316feSJens Wiklander 		TEE_Panic(0);
269*334316feSJens Wiklander 
270*334316feSJens Wiklander 	count = token->db_objs->count;
271*334316feSJens Wiklander 	ptr = TEE_Realloc(token->db_objs,
272*334316feSJens Wiklander 			  sizeof(struct token_persistent_objs) +
273*334316feSJens Wiklander 			  ((count + 1) * sizeof(TEE_UUID)));
274*334316feSJens Wiklander 	if (!ptr)
275*334316feSJens Wiklander 		return PKCS11_CKR_DEVICE_MEMORY;
276*334316feSJens Wiklander 
277*334316feSJens Wiklander 	token->db_objs = ptr;
278*334316feSJens Wiklander 	TEE_MemMove(token->db_objs->uuids + count, uuid, sizeof(TEE_UUID));
279*334316feSJens Wiklander 
280*334316feSJens Wiklander 	size = sizeof(struct token_persistent_main) +
281*334316feSJens Wiklander 	       sizeof(struct token_persistent_objs) +
282*334316feSJens Wiklander 	       count * sizeof(TEE_UUID);
283*334316feSJens Wiklander 
284*334316feSJens Wiklander 	res = open_db_file(token, &db_hdl);
285*334316feSJens Wiklander 	if (res)
286*334316feSJens Wiklander 		goto out;
287*334316feSJens Wiklander 
288*334316feSJens Wiklander 	res = TEE_TruncateObjectData(db_hdl, size + sizeof(TEE_UUID));
289*334316feSJens Wiklander 	if (res)
290*334316feSJens Wiklander 		goto out;
291*334316feSJens Wiklander 
292*334316feSJens Wiklander 	res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main),
293*334316feSJens Wiklander 				 TEE_DATA_SEEK_SET);
294*334316feSJens Wiklander 	if (res)
295*334316feSJens Wiklander 		goto out;
296*334316feSJens Wiklander 
297*334316feSJens Wiklander 	token->db_objs->count++;
298*334316feSJens Wiklander 
299*334316feSJens Wiklander 	res = TEE_WriteObjectData(db_hdl, token->db_objs,
300*334316feSJens Wiklander 				  sizeof(struct token_persistent_objs) +
301*334316feSJens Wiklander 				  token->db_objs->count * sizeof(TEE_UUID));
302*334316feSJens Wiklander 	if (res)
303*334316feSJens Wiklander 		token->db_objs->count--;
304*334316feSJens Wiklander 
305*334316feSJens Wiklander out:
306*334316feSJens Wiklander 	TEE_CloseObject(db_hdl);
307*334316feSJens Wiklander 
308*334316feSJens Wiklander 	return tee2pkcs_error(res);
309*334316feSJens Wiklander }
310*334316feSJens 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;
322*334316feSJens Wiklander 	struct token_persistent_objs *db_objs = NULL;
323*334316feSJens Wiklander 	void *ptr = NULL;
324c84ccd0aSEtienne Carriere 
325c84ccd0aSEtienne Carriere 	if (!token)
326c84ccd0aSEtienne Carriere 		return NULL;
327c84ccd0aSEtienne Carriere 
328*334316feSJens Wiklander 	LIST_INIT(&token->object_list);
329*334316feSJens Wiklander 
330c84ccd0aSEtienne Carriere 	db_main = TEE_Malloc(sizeof(*db_main), TEE_MALLOC_FILL_ZERO);
331*334316feSJens Wiklander 	db_objs = TEE_Malloc(sizeof(*db_objs), TEE_MALLOC_FILL_ZERO);
332*334316feSJens 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;
339*334316feSJens 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);
347*334316feSJens Wiklander 
348*334316feSJens Wiklander 		size = sizeof(*db_objs);
349*334316feSJens Wiklander 		res = TEE_ReadObjectData(db_hdl, db_objs, size, &size);
350*334316feSJens Wiklander 		if (res || size != sizeof(*db_objs))
351*334316feSJens Wiklander 			TEE_Panic(0);
352*334316feSJens Wiklander 
353*334316feSJens Wiklander 		size += db_objs->count * sizeof(TEE_UUID);
354*334316feSJens Wiklander 		ptr = TEE_Realloc(db_objs, size);
355*334316feSJens Wiklander 		if (!ptr)
356*334316feSJens Wiklander 			goto error;
357*334316feSJens Wiklander 
358*334316feSJens Wiklander 		db_objs = ptr;
359*334316feSJens Wiklander 		size -= sizeof(struct token_persistent_objs);
360*334316feSJens Wiklander 		res = TEE_ReadObjectData(db_hdl, db_objs->uuids, size, &size);
361*334316feSJens Wiklander 		if (res || size != (db_objs->count * sizeof(TEE_UUID)))
362*334316feSJens Wiklander 			TEE_Panic(0);
363*334316feSJens Wiklander 
364*334316feSJens Wiklander 		for (idx = 0; idx < db_objs->count; idx++) {
365*334316feSJens Wiklander 			/* Create an empty object instance */
366*334316feSJens Wiklander 			struct pkcs11_object *obj = NULL;
367*334316feSJens Wiklander 			TEE_UUID *uuid = NULL;
368*334316feSJens Wiklander 
369*334316feSJens Wiklander 			uuid = TEE_Malloc(sizeof(TEE_UUID),
370*334316feSJens Wiklander 					  TEE_USER_MEM_HINT_NO_FILL_ZERO);
371*334316feSJens Wiklander 			if (!uuid)
372*334316feSJens Wiklander 				goto error;
373*334316feSJens Wiklander 
374*334316feSJens Wiklander 			TEE_MemMove(uuid, &db_objs->uuids[idx], sizeof(*uuid));
375*334316feSJens Wiklander 
376*334316feSJens Wiklander 			obj = create_token_object(NULL, uuid);
377*334316feSJens Wiklander 			if (!obj)
378*334316feSJens Wiklander 				TEE_Panic(0);
379*334316feSJens Wiklander 
380*334316feSJens Wiklander 			LIST_INSERT_HEAD(&token->object_list, obj, link);
381*334316feSJens Wiklander 		}
382*334316feSJens 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 
401*334316feSJens Wiklander 		/*
402*334316feSJens Wiklander 		 * Object stores persistent state + persistent object
403*334316feSJens Wiklander 		 * references.
404*334316feSJens 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) {
413c84ccd0aSEtienne Carriere 			EMSG("Failed to create db: %"PRIx32, res);
414c84ccd0aSEtienne Carriere 			goto error;
415c84ccd0aSEtienne Carriere 		}
416*334316feSJens Wiklander 
417*334316feSJens Wiklander 		res = TEE_TruncateObjectData(db_hdl, sizeof(*db_main) +
418*334316feSJens Wiklander 						     sizeof(*db_objs));
419*334316feSJens Wiklander 		if (res)
420*334316feSJens Wiklander 			TEE_Panic(0);
421*334316feSJens Wiklander 
422*334316feSJens Wiklander 		res = TEE_SeekObjectData(db_hdl, sizeof(*db_main),
423*334316feSJens Wiklander 					 TEE_DATA_SEEK_SET);
424*334316feSJens Wiklander 		if (res)
425*334316feSJens Wiklander 			TEE_Panic(0);
426*334316feSJens Wiklander 
427*334316feSJens Wiklander 		db_objs->count = 0;
428*334316feSJens Wiklander 		res = TEE_WriteObjectData(db_hdl, db_objs, sizeof(*db_objs));
429*334316feSJens Wiklander 		if (res)
430*334316feSJens Wiklander 			TEE_Panic(0);
431*334316feSJens Wiklander 
432c84ccd0aSEtienne Carriere 	} else {
433c84ccd0aSEtienne Carriere 		goto error;
434c84ccd0aSEtienne Carriere 	}
435c84ccd0aSEtienne Carriere 
436c84ccd0aSEtienne Carriere 	token->db_main = db_main;
437*334316feSJens 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);
444*334316feSJens 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