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