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 size_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)289 void close_persistent_db(struct ck_token *token)
290 {
291 if (!token)
292 return;
293
294 TEE_Free(token->db_main);
295 token->db_main = NULL;
296
297 TEE_Free(token->db_objs);
298 token->db_objs = NULL;
299 }
300
get_persistent_obj_idx(struct ck_token * token,TEE_UUID * uuid)301 static int get_persistent_obj_idx(struct ck_token *token, TEE_UUID *uuid)
302 {
303 size_t i = 0;
304
305 if (!uuid)
306 return -1;
307
308 for (i = 0; i < token->db_objs->count; i++)
309 if (!TEE_MemCompare(token->db_objs->uuids + i,
310 uuid, sizeof(TEE_UUID)))
311 return i;
312
313 return -1;
314 }
315
316 /* UUID for persistent object */
create_object_uuid(struct ck_token * token,struct pkcs11_object * obj)317 enum pkcs11_rc create_object_uuid(struct ck_token *token,
318 struct pkcs11_object *obj)
319 {
320 assert(!obj->uuid);
321
322 obj->uuid = TEE_Malloc(sizeof(TEE_UUID),
323 TEE_USER_MEM_HINT_NO_FILL_ZERO);
324 if (!obj->uuid)
325 return PKCS11_CKR_DEVICE_MEMORY;
326
327 obj->token = token;
328
329 do {
330 TEE_GenerateRandom(obj->uuid, sizeof(TEE_UUID));
331 } while (get_persistent_obj_idx(token, obj->uuid) >= 0);
332
333 return PKCS11_CKR_OK;
334 }
335
destroy_object_uuid(struct ck_token * token __maybe_unused,struct pkcs11_object * obj)336 void destroy_object_uuid(struct ck_token *token __maybe_unused,
337 struct pkcs11_object *obj)
338 {
339 assert(get_persistent_obj_idx(token, obj->uuid) < 0);
340
341 TEE_Free(obj->uuid);
342 obj->uuid = NULL;
343 }
344
get_persistent_objects_list(struct ck_token * token,TEE_UUID * array,size_t * size)345 enum pkcs11_rc get_persistent_objects_list(struct ck_token *token,
346 TEE_UUID *array, size_t *size)
347 {
348 size_t out_size = *size;
349
350 *size = token->db_objs->count * sizeof(TEE_UUID);
351
352 if (out_size < *size)
353 return PKCS11_CKR_BUFFER_TOO_SMALL;
354
355 if (array)
356 TEE_MemMove(array, token->db_objs->uuids, *size);
357
358 return PKCS11_CKR_OK;
359 }
360
unregister_persistent_object(struct ck_token * token,TEE_UUID * uuid)361 enum pkcs11_rc unregister_persistent_object(struct ck_token *token,
362 TEE_UUID *uuid)
363 {
364 TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
365 struct token_persistent_objs *ptr = NULL;
366 TEE_Result res = TEE_ERROR_GENERIC;
367 int count = 0;
368 int idx = 0;
369
370 if (!uuid)
371 return PKCS11_CKR_OK;
372
373 idx = get_persistent_obj_idx(token, uuid);
374 if (idx < 0) {
375 DMSG("Cannot unregister an invalid persistent object");
376 return PKCS11_RV_NOT_FOUND;
377 }
378
379 ptr = TEE_Malloc(sizeof(struct token_persistent_objs) +
380 ((token->db_objs->count - 1) * sizeof(TEE_UUID)),
381 TEE_USER_MEM_HINT_NO_FILL_ZERO);
382 if (!ptr)
383 return PKCS11_CKR_DEVICE_MEMORY;
384
385 res = open_db_file(token, &db_hdl);
386 if (res)
387 goto out;
388
389 res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main),
390 TEE_DATA_SEEK_SET);
391 if (res) {
392 DMSG("Failed to read database");
393 goto out;
394 }
395
396 TEE_MemMove(ptr, token->db_objs,
397 sizeof(struct token_persistent_objs) +
398 idx * sizeof(TEE_UUID));
399
400 ptr->count--;
401 count = ptr->count - idx;
402
403 TEE_MemMove(&ptr->uuids[idx],
404 &token->db_objs->uuids[idx + 1],
405 count * sizeof(TEE_UUID));
406
407 res = TEE_WriteObjectData(db_hdl, ptr,
408 sizeof(struct token_persistent_objs) +
409 ptr->count * sizeof(TEE_UUID));
410 if (res)
411 DMSG("Failed to update database");
412 TEE_Free(token->db_objs);
413 token->db_objs = ptr;
414 ptr = NULL;
415
416 out:
417 TEE_CloseObject(db_hdl);
418 TEE_Free(ptr);
419
420 return tee2pkcs_error(res);
421 }
422
register_persistent_object(struct ck_token * token,TEE_UUID * uuid)423 enum pkcs11_rc register_persistent_object(struct ck_token *token,
424 TEE_UUID *uuid)
425 {
426 TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
427 TEE_Result res = TEE_ERROR_GENERIC;
428 void *ptr = NULL;
429 size_t size = 0;
430 int count = 0;
431
432 if (get_persistent_obj_idx(token, uuid) >= 0)
433 TEE_Panic(0);
434
435 count = token->db_objs->count;
436 ptr = TEE_Realloc(token->db_objs,
437 sizeof(struct token_persistent_objs) +
438 ((count + 1) * sizeof(TEE_UUID)));
439 if (!ptr)
440 return PKCS11_CKR_DEVICE_MEMORY;
441
442 token->db_objs = ptr;
443 TEE_MemMove(token->db_objs->uuids + count, uuid, sizeof(TEE_UUID));
444
445 size = sizeof(struct token_persistent_main) +
446 sizeof(struct token_persistent_objs) +
447 count * sizeof(TEE_UUID);
448
449 res = open_db_file(token, &db_hdl);
450 if (res)
451 goto out;
452
453 res = TEE_TruncateObjectData(db_hdl, size + sizeof(TEE_UUID));
454 if (res)
455 goto out;
456
457 res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main),
458 TEE_DATA_SEEK_SET);
459 if (res)
460 goto out;
461
462 token->db_objs->count++;
463
464 res = TEE_WriteObjectData(db_hdl, token->db_objs,
465 sizeof(struct token_persistent_objs) +
466 token->db_objs->count * sizeof(TEE_UUID));
467 if (res)
468 token->db_objs->count--;
469
470 out:
471 TEE_CloseObject(db_hdl);
472
473 return tee2pkcs_error(res);
474 }
475
load_persistent_object_attributes(struct pkcs11_object * obj)476 enum pkcs11_rc load_persistent_object_attributes(struct pkcs11_object *obj)
477 {
478 enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
479 TEE_Result res = TEE_ERROR_GENERIC;
480 TEE_ObjectHandle hdl = obj->attribs_hdl;
481 TEE_ObjectInfo info = { };
482 struct obj_attrs *attr = NULL;
483 size_t read_bytes = 0;
484
485 if (obj->attributes)
486 return PKCS11_CKR_OK;
487
488 if (hdl == TEE_HANDLE_NULL) {
489 res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
490 obj->uuid, sizeof(*obj->uuid),
491 TEE_DATA_FLAG_ACCESS_READ, &hdl);
492 if (res) {
493 EMSG("OpenPersistent failed %#"PRIx32, res);
494 return tee2pkcs_error(res);
495 }
496 }
497
498 TEE_MemFill(&info, 0, sizeof(info));
499 res = TEE_GetObjectInfo1(hdl, &info);
500 if (res) {
501 EMSG("GetObjectInfo failed %#"PRIx32, res);
502 rc = tee2pkcs_error(res);
503 goto out;
504 }
505
506 attr = TEE_Malloc(info.dataSize, TEE_MALLOC_FILL_ZERO);
507 if (!attr) {
508 rc = PKCS11_CKR_DEVICE_MEMORY;
509 goto out;
510 }
511
512 res = TEE_ReadObjectData(hdl, attr, info.dataSize, &read_bytes);
513 if (!res) {
514 res = TEE_SeekObjectData(hdl, 0, TEE_DATA_SEEK_SET);
515 if (res)
516 EMSG("Seek to 0 failed %#"PRIx32, res);
517 }
518
519 if (res) {
520 rc = tee2pkcs_error(res);
521 EMSG("Read %zu bytes, failed %#"PRIx32,
522 read_bytes, res);
523 goto out;
524 }
525 if (read_bytes != info.dataSize) {
526 EMSG("Read %zu bytes, expected %zu",
527 read_bytes, info.dataSize);
528 rc = PKCS11_CKR_GENERAL_ERROR;
529 goto out;
530 }
531
532 obj->attributes = attr;
533 attr = NULL;
534
535 rc = PKCS11_CKR_OK;
536
537 out:
538 TEE_Free(attr);
539 /* Close object only if it was open from this function */
540 if (obj->attribs_hdl == TEE_HANDLE_NULL)
541 TEE_CloseObject(hdl);
542
543 return rc;
544 }
545
release_persistent_object_attributes(struct pkcs11_object * obj)546 void release_persistent_object_attributes(struct pkcs11_object *obj)
547 {
548 TEE_Free(obj->attributes);
549 obj->attributes = NULL;
550 }
551
update_persistent_object_attributes(struct pkcs11_object * obj)552 enum pkcs11_rc update_persistent_object_attributes(struct pkcs11_object *obj)
553 {
554 TEE_Result res = TEE_ERROR_GENERIC;
555 TEE_ObjectHandle hdl = TEE_HANDLE_NULL;
556 uint32_t tee_obj_flags = TEE_DATA_FLAG_ACCESS_WRITE;
557 size_t size = 0;
558
559 assert(obj && obj->attributes);
560
561 res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE,
562 obj->uuid, sizeof(*obj->uuid),
563 tee_obj_flags, &hdl);
564 if (res) {
565 EMSG("OpenPersistent failed %#"PRIx32, res);
566 return tee2pkcs_error(res);
567 }
568
569 size = sizeof(struct obj_attrs) + obj->attributes->attrs_size;
570
571 res = TEE_WriteObjectData(hdl, obj->attributes, size);
572 if (res)
573 goto out;
574
575 res = TEE_TruncateObjectData(hdl, size);
576
577 out:
578 TEE_CloseObject(hdl);
579 return tee2pkcs_error(res);
580 }
581
582 /*
583 * Return the token instance, either initialized from reset or initialized
584 * from the token persistent state if found.
585 */
init_persistent_db(unsigned int token_id)586 struct ck_token *init_persistent_db(unsigned int token_id)
587 {
588 struct ck_token *token = get_token(token_id);
589 TEE_Result res = TEE_ERROR_GENERIC;
590 TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL;
591 /* Copy persistent database: main db and object db */
592 struct token_persistent_main *db_main = NULL;
593 struct token_persistent_objs *db_objs = NULL;
594 void *ptr = NULL;
595 void *initial_data = NULL;
596 uint32_t initial_data_size = 0;
597
598 if (!token)
599 return NULL;
600
601 LIST_INIT(&token->object_list);
602
603 db_main = TEE_Malloc(sizeof(*db_main), TEE_MALLOC_FILL_ZERO);
604 db_objs = TEE_Malloc(sizeof(*db_objs), TEE_MALLOC_FILL_ZERO);
605 if (!db_main || !db_objs)
606 goto error;
607
608 res = open_db_file(token, &db_hdl);
609
610 if (res == TEE_SUCCESS) {
611 size_t size = 0;
612 size_t idx = 0;
613
614 IMSG("PKCS11 token %u: load db", token_id);
615
616 size = sizeof(*db_main);
617 res = TEE_ReadObjectData(db_hdl, db_main, size, &size);
618 if (res || size != sizeof(*db_main))
619 TEE_Panic(0);
620
621 size = sizeof(*db_objs);
622 res = TEE_ReadObjectData(db_hdl, db_objs, size, &size);
623 if (res || size != sizeof(*db_objs))
624 TEE_Panic(0);
625
626 if (db_objs->count > 0) {
627 size += db_objs->count * sizeof(TEE_UUID);
628 ptr = TEE_Realloc(db_objs, size);
629 if (!ptr)
630 goto error;
631
632 db_objs = ptr;
633 size -= sizeof(*db_objs);
634 res = TEE_ReadObjectData(db_hdl, db_objs->uuids, size,
635 &size);
636 if (res || size != (db_objs->count * sizeof(TEE_UUID)))
637 TEE_Panic(0);
638 }
639
640 for (idx = 0; idx < db_objs->count; idx++) {
641 /* Create an empty object instance */
642 struct pkcs11_object *obj = NULL;
643 TEE_UUID *uuid = NULL;
644
645 uuid = TEE_Malloc(sizeof(TEE_UUID),
646 TEE_USER_MEM_HINT_NO_FILL_ZERO);
647 if (!uuid)
648 goto error;
649
650 TEE_MemMove(uuid, &db_objs->uuids[idx], sizeof(*uuid));
651
652 obj = create_token_object(NULL, uuid, token);
653 if (!obj)
654 TEE_Panic(0);
655
656 LIST_INSERT_HEAD(&token->object_list, obj, link);
657 }
658
659 } else if (res == TEE_ERROR_ITEM_NOT_FOUND) {
660 char file[PERSISTENT_OBJECT_ID_LEN] = { };
661
662 IMSG("PKCS11 token %u: init db", token_id);
663
664 TEE_MemFill(db_main, 0, sizeof(*db_main));
665 TEE_MemFill(db_main->label, '*', sizeof(db_main->label));
666
667 db_main->flags = PKCS11_CKFT_SO_PIN_TO_BE_CHANGED |
668 PKCS11_CKFT_USER_PIN_TO_BE_CHANGED |
669 PKCS11_CKFT_RNG |
670 PKCS11_CKFT_LOGIN_REQUIRED;
671
672 res = get_db_file_name(token, file, sizeof(file));
673 if (res)
674 TEE_Panic(0);
675
676 /*
677 * Object stores persistent state + persistent object
678 * references.
679 *
680 * Allocate the initial_data buffer to encompass the data from
681 * both db_main and db_objs. Since the initial data for the
682 * objects will be zeroed out upon creation, there’s no need
683 * to copy it from db_objs.
684 */
685 initial_data_size = sizeof(*db_main) + sizeof(*db_objs);
686 initial_data = TEE_Malloc(initial_data_size,
687 TEE_MALLOC_FILL_ZERO);
688 if (!initial_data) {
689 EMSG("Failed to allocate initial_data buffer");
690 goto error;
691 }
692 TEE_MemMove(initial_data, db_main, sizeof(*db_main));
693 res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
694 file, sizeof(file),
695 TEE_DATA_FLAG_ACCESS_READ |
696 TEE_DATA_FLAG_ACCESS_WRITE,
697 TEE_HANDLE_NULL,
698 initial_data,
699 initial_data_size,
700 &db_hdl);
701 TEE_Free(initial_data);
702 if (res) {
703 EMSG("Failed to create db: %#"PRIx32, res);
704 goto error;
705 }
706
707 } else {
708 goto error;
709 }
710
711 token->db_main = db_main;
712 token->db_objs = db_objs;
713 TEE_CloseObject(db_hdl);
714
715 return token;
716
717 error:
718 TEE_Free(db_main);
719 TEE_Free(db_objs);
720 if (db_hdl != TEE_HANDLE_NULL)
721 TEE_CloseObject(db_hdl);
722
723 return NULL;
724 }
725