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