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 1311a27b197SVesa Jääskeläinen #if defined(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) 1321a27b197SVesa Jääskeläinen enum pkcs11_rc setup_so_identity_auth_from_client(struct ck_token *token) 1331a27b197SVesa Jääskeläinen { 1341a27b197SVesa Jääskeläinen TEE_Identity identity = { }; 1351a27b197SVesa Jääskeläinen TEE_Result res = TEE_SUCCESS; 1361a27b197SVesa Jääskeläinen 1371a27b197SVesa Jääskeläinen res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, 1381a27b197SVesa Jääskeläinen "gpd.client.identity", &identity); 1391a27b197SVesa Jääskeläinen if (res != TEE_SUCCESS) { 1401a27b197SVesa Jääskeläinen EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res); 1411a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INVALID; 1421a27b197SVesa Jääskeläinen } 1431a27b197SVesa Jääskeläinen 1441a27b197SVesa Jääskeläinen TEE_MemMove(&token->db_main->so_identity, &identity, sizeof(identity)); 1451a27b197SVesa Jääskeläinen token->db_main->flags |= PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH; 1461a27b197SVesa Jääskeläinen 1471a27b197SVesa Jääskeläinen token->db_main->so_pin_salt = 0; 1481a27b197SVesa Jääskeläinen 1491a27b197SVesa Jääskeläinen return PKCS11_CKR_OK; 1501a27b197SVesa Jääskeläinen } 1511a27b197SVesa Jääskeläinen 1521a27b197SVesa Jääskeläinen enum pkcs11_rc setup_identity_auth_from_pin(struct ck_token *token, 1531a27b197SVesa Jääskeläinen enum pkcs11_user_type user_type, 1541a27b197SVesa Jääskeläinen const uint8_t *pin, 1551a27b197SVesa Jääskeläinen size_t pin_size) 1561a27b197SVesa Jääskeläinen { 1571a27b197SVesa Jääskeläinen TEE_Identity identity = { }; 1581a27b197SVesa Jääskeläinen TEE_Result res = TEE_SUCCESS; 1591a27b197SVesa Jääskeläinen uint32_t flags_clear = 0; 1601a27b197SVesa Jääskeläinen uint32_t flags_set = 0; 1611a27b197SVesa Jääskeläinen char *acl_string = NULL; 1621a27b197SVesa Jääskeläinen char *uuid_str = NULL; 1631a27b197SVesa Jääskeläinen 1641a27b197SVesa Jääskeläinen assert(token->db_main->flags & 1651a27b197SVesa Jääskeläinen PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH); 1661a27b197SVesa Jääskeläinen 1671a27b197SVesa Jääskeläinen if (!pin) { 1681a27b197SVesa Jääskeläinen /* Use client identity */ 1691a27b197SVesa Jääskeläinen res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, 1701a27b197SVesa Jääskeläinen "gpd.client.identity", 1711a27b197SVesa Jääskeläinen &identity); 1721a27b197SVesa Jääskeläinen if (res != TEE_SUCCESS) { 1731a27b197SVesa Jääskeläinen EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, 1741a27b197SVesa Jääskeläinen res); 1751a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INVALID; 1761a27b197SVesa Jääskeläinen } 1771a27b197SVesa Jääskeläinen } else { 1781a27b197SVesa Jääskeläinen /* Parse PIN ACL string: <login type>:<client id> */ 1791a27b197SVesa Jääskeläinen acl_string = TEE_Malloc(pin_size + 1, TEE_MALLOC_FILL_ZERO); 1801a27b197SVesa Jääskeläinen if (!acl_string) 1811a27b197SVesa Jääskeläinen return PKCS11_CKR_DEVICE_MEMORY; 1821a27b197SVesa Jääskeläinen TEE_MemMove(acl_string, pin, pin_size); 1831a27b197SVesa Jääskeläinen 1841a27b197SVesa Jääskeläinen uuid_str = strstr(acl_string, ":"); 1851a27b197SVesa Jääskeläinen if (uuid_str) 1861a27b197SVesa Jääskeläinen uuid_str++; 1871a27b197SVesa Jääskeläinen if (strcmp(PKCS11_AUTH_TEE_IDENTITY_PUBLIC, acl_string) == 0) { 1881a27b197SVesa Jääskeläinen identity.login = TEE_LOGIN_PUBLIC; 1891a27b197SVesa Jääskeläinen } else if (strstr(acl_string, PKCS11_AUTH_TEE_IDENTITY_USER) == 1901a27b197SVesa Jääskeläinen acl_string) { 1911a27b197SVesa Jääskeläinen identity.login = TEE_LOGIN_USER; 1921a27b197SVesa Jääskeläinen } else if (strstr(acl_string, PKCS11_AUTH_TEE_IDENTITY_GROUP) == 1931a27b197SVesa Jääskeläinen acl_string) { 1941a27b197SVesa Jääskeläinen identity.login = TEE_LOGIN_GROUP; 1951a27b197SVesa Jääskeläinen } else { 1961a27b197SVesa Jääskeläinen EMSG("Invalid PIN ACL string - login"); 1971a27b197SVesa Jääskeläinen TEE_Free(acl_string); 1981a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INVALID; 1991a27b197SVesa Jääskeläinen } 2001a27b197SVesa Jääskeläinen 2011a27b197SVesa Jääskeläinen if (identity.login != TEE_LOGIN_PUBLIC) { 2021a27b197SVesa Jääskeläinen if (!uuid_str) { 2031a27b197SVesa Jääskeläinen EMSG("Invalid PIN ACL string - colon"); 2041a27b197SVesa Jääskeläinen TEE_Free(acl_string); 2051a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INVALID; 2061a27b197SVesa Jääskeläinen } 2071a27b197SVesa Jääskeläinen 2081a27b197SVesa Jääskeläinen res = tee_uuid_from_str(&identity.uuid, uuid_str); 2091a27b197SVesa Jääskeläinen if (res) { 2101a27b197SVesa Jääskeläinen EMSG("Invalid PIN ACL string - client id"); 2111a27b197SVesa Jääskeläinen TEE_Free(acl_string); 2121a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INVALID; 2131a27b197SVesa Jääskeläinen } 2141a27b197SVesa Jääskeläinen } 2151a27b197SVesa Jääskeläinen 2161a27b197SVesa Jääskeläinen TEE_Free(acl_string); 2171a27b197SVesa Jääskeläinen } 2181a27b197SVesa Jääskeläinen 2191a27b197SVesa Jääskeläinen switch (user_type) { 2201a27b197SVesa Jääskeläinen case PKCS11_CKU_SO: 2211a27b197SVesa Jääskeläinen token->db_main->so_pin_count = 0; 2221a27b197SVesa Jääskeläinen token->db_main->so_pin_salt = 0; 2231a27b197SVesa Jääskeläinen flags_clear = PKCS11_CKFT_SO_PIN_COUNT_LOW | 2241a27b197SVesa Jääskeläinen PKCS11_CKFT_SO_PIN_FINAL_TRY | 2251a27b197SVesa Jääskeläinen PKCS11_CKFT_SO_PIN_LOCKED | 2261a27b197SVesa Jääskeläinen PKCS11_CKFT_SO_PIN_TO_BE_CHANGED; 2271a27b197SVesa Jääskeläinen 2281a27b197SVesa Jääskeläinen TEE_MemMove(&token->db_main->so_identity, &identity, 2291a27b197SVesa Jääskeläinen sizeof(identity)); 2301a27b197SVesa Jääskeläinen break; 2311a27b197SVesa Jääskeläinen case PKCS11_CKU_USER: 2321a27b197SVesa Jääskeläinen token->db_main->user_pin_count = 0; 2331a27b197SVesa Jääskeläinen token->db_main->user_pin_salt = 0; 2341a27b197SVesa Jääskeläinen flags_clear = PKCS11_CKFT_USER_PIN_COUNT_LOW | 2351a27b197SVesa Jääskeläinen PKCS11_CKFT_USER_PIN_FINAL_TRY | 2361a27b197SVesa Jääskeläinen PKCS11_CKFT_USER_PIN_LOCKED | 2371a27b197SVesa Jääskeläinen PKCS11_CKFT_USER_PIN_TO_BE_CHANGED; 2381a27b197SVesa Jääskeläinen flags_set = PKCS11_CKFT_USER_PIN_INITIALIZED; 2391a27b197SVesa Jääskeläinen 2401a27b197SVesa Jääskeläinen TEE_MemMove(&token->db_main->user_identity, &identity, 2411a27b197SVesa Jääskeläinen sizeof(identity)); 2421a27b197SVesa Jääskeläinen break; 2431a27b197SVesa Jääskeläinen default: 2441a27b197SVesa Jääskeläinen return PKCS11_CKR_FUNCTION_FAILED; 2451a27b197SVesa Jääskeläinen } 2461a27b197SVesa Jääskeläinen 2471a27b197SVesa Jääskeläinen token->db_main->flags &= ~flags_clear; 2481a27b197SVesa Jääskeläinen token->db_main->flags |= flags_set; 2491a27b197SVesa Jääskeläinen 2501a27b197SVesa Jääskeläinen return PKCS11_CKR_OK; 2511a27b197SVesa Jääskeläinen } 2521a27b197SVesa Jääskeläinen 2531a27b197SVesa Jääskeläinen enum pkcs11_rc verify_identity_auth(struct ck_token *token, 2541a27b197SVesa Jääskeläinen enum pkcs11_user_type user_type) 2551a27b197SVesa Jääskeläinen { 2561a27b197SVesa Jääskeläinen TEE_Identity identity = { }; 2571a27b197SVesa Jääskeläinen TEE_Result res = TEE_SUCCESS; 2581a27b197SVesa Jääskeläinen 2591a27b197SVesa Jääskeläinen assert(token->db_main->flags & 2601a27b197SVesa Jääskeläinen PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH); 2611a27b197SVesa Jääskeläinen 2621a27b197SVesa Jääskeläinen res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, 2631a27b197SVesa Jääskeläinen "gpd.client.identity", &identity); 2641a27b197SVesa Jääskeläinen if (res != TEE_SUCCESS) { 2651a27b197SVesa Jääskeläinen EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res); 2661a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INVALID; 2671a27b197SVesa Jääskeläinen } 2681a27b197SVesa Jääskeläinen 2691a27b197SVesa Jääskeläinen if (user_type == PKCS11_CKU_SO) { 2701a27b197SVesa Jääskeläinen if (TEE_MemCompare(&token->db_main->so_identity, &identity, 2711a27b197SVesa Jääskeläinen sizeof(identity))) 2721a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INCORRECT; 2731a27b197SVesa Jääskeläinen } else if (user_type == PKCS11_CKU_USER) { 2741a27b197SVesa Jääskeläinen if (TEE_MemCompare(&token->db_main->user_identity, &identity, 2751a27b197SVesa Jääskeläinen sizeof(identity))) 2761a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INCORRECT; 2771a27b197SVesa Jääskeläinen } else { 2781a27b197SVesa Jääskeläinen return PKCS11_CKR_PIN_INCORRECT; 2791a27b197SVesa Jääskeläinen } 2801a27b197SVesa Jääskeläinen 2811a27b197SVesa Jääskeläinen return PKCS11_CKR_OK; 2821a27b197SVesa Jääskeläinen } 2831a27b197SVesa Jääskeläinen #endif /* CFG_PKCS11_TA_AUTH_TEE_IDENTITY */ 2841a27b197SVesa Jääskeläinen 285c84ccd0aSEtienne Carriere /* 28660659a86SEtienne Carriere * Release resources relate to persistent database 28760659a86SEtienne Carriere */ 28860659a86SEtienne Carriere void close_persistent_db(struct ck_token *token __unused) 28960659a86SEtienne Carriere { 29060659a86SEtienne Carriere } 29160659a86SEtienne Carriere 292334316feSJens Wiklander static int get_persistent_obj_idx(struct ck_token *token, TEE_UUID *uuid) 293334316feSJens Wiklander { 294334316feSJens Wiklander size_t i = 0; 295334316feSJens Wiklander 296334316feSJens Wiklander if (!uuid) 297334316feSJens Wiklander return -1; 298334316feSJens Wiklander 299334316feSJens Wiklander for (i = 0; i < token->db_objs->count; i++) 300334316feSJens Wiklander if (!TEE_MemCompare(token->db_objs->uuids + i, 301334316feSJens Wiklander uuid, sizeof(TEE_UUID))) 302334316feSJens Wiklander return i; 303334316feSJens Wiklander 304334316feSJens Wiklander return -1; 305334316feSJens Wiklander } 306334316feSJens Wiklander 307334316feSJens Wiklander /* UUID for persistent object */ 308334316feSJens Wiklander enum pkcs11_rc create_object_uuid(struct ck_token *token, 309334316feSJens Wiklander struct pkcs11_object *obj) 310334316feSJens Wiklander { 311334316feSJens Wiklander assert(!obj->uuid); 312334316feSJens Wiklander 313334316feSJens Wiklander obj->uuid = TEE_Malloc(sizeof(TEE_UUID), 314334316feSJens Wiklander TEE_USER_MEM_HINT_NO_FILL_ZERO); 315334316feSJens Wiklander if (!obj->uuid) 316334316feSJens Wiklander return PKCS11_CKR_DEVICE_MEMORY; 317334316feSJens Wiklander 318334316feSJens Wiklander do { 319334316feSJens Wiklander TEE_GenerateRandom(obj->uuid, sizeof(TEE_UUID)); 320334316feSJens Wiklander } while (get_persistent_obj_idx(token, obj->uuid) >= 0); 321334316feSJens Wiklander 322334316feSJens Wiklander return PKCS11_CKR_OK; 323334316feSJens Wiklander } 324334316feSJens Wiklander 325334316feSJens Wiklander void destroy_object_uuid(struct ck_token *token __maybe_unused, 326334316feSJens Wiklander struct pkcs11_object *obj) 327334316feSJens Wiklander { 328334316feSJens Wiklander assert(get_persistent_obj_idx(token, obj->uuid) < 0); 329334316feSJens Wiklander 330334316feSJens Wiklander TEE_Free(obj->uuid); 331334316feSJens Wiklander obj->uuid = NULL; 332334316feSJens Wiklander } 333334316feSJens Wiklander 334334316feSJens Wiklander enum pkcs11_rc get_persistent_objects_list(struct ck_token *token, 335334316feSJens Wiklander TEE_UUID *array, size_t *size) 336334316feSJens Wiklander { 337334316feSJens Wiklander size_t out_size = *size; 338334316feSJens Wiklander 339334316feSJens Wiklander *size = token->db_objs->count * sizeof(TEE_UUID); 340334316feSJens Wiklander 341334316feSJens Wiklander if (out_size < *size) 342334316feSJens Wiklander return PKCS11_CKR_BUFFER_TOO_SMALL; 343334316feSJens Wiklander 344334316feSJens Wiklander if (array) 345334316feSJens Wiklander TEE_MemMove(array, token->db_objs->uuids, *size); 346334316feSJens Wiklander 347334316feSJens Wiklander return PKCS11_CKR_OK; 348334316feSJens Wiklander } 349334316feSJens Wiklander 350334316feSJens Wiklander enum pkcs11_rc unregister_persistent_object(struct ck_token *token, 351334316feSJens Wiklander TEE_UUID *uuid) 352334316feSJens Wiklander { 353334316feSJens Wiklander TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; 354334316feSJens Wiklander struct token_persistent_objs *ptr = NULL; 355334316feSJens Wiklander TEE_Result res = TEE_ERROR_GENERIC; 356334316feSJens Wiklander int count = 0; 357334316feSJens Wiklander int idx = 0; 358334316feSJens Wiklander 359334316feSJens Wiklander if (!uuid) 360334316feSJens Wiklander return PKCS11_CKR_OK; 361334316feSJens Wiklander 362334316feSJens Wiklander idx = get_persistent_obj_idx(token, uuid); 363334316feSJens Wiklander if (idx < 0) { 364334316feSJens Wiklander DMSG("Cannot unregister an invalid persistent object"); 365334316feSJens Wiklander return PKCS11_RV_NOT_FOUND; 366334316feSJens Wiklander } 367334316feSJens Wiklander 368334316feSJens Wiklander ptr = TEE_Malloc(sizeof(struct token_persistent_objs) + 369334316feSJens Wiklander ((token->db_objs->count - 1) * sizeof(TEE_UUID)), 370334316feSJens Wiklander TEE_USER_MEM_HINT_NO_FILL_ZERO); 371334316feSJens Wiklander if (!ptr) 372334316feSJens Wiklander return PKCS11_CKR_DEVICE_MEMORY; 373334316feSJens Wiklander 374334316feSJens Wiklander res = open_db_file(token, &db_hdl); 375334316feSJens Wiklander if (res) 376334316feSJens Wiklander goto out; 377334316feSJens Wiklander 378334316feSJens Wiklander res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main), 379334316feSJens Wiklander TEE_DATA_SEEK_SET); 380334316feSJens Wiklander if (res) { 381334316feSJens Wiklander DMSG("Failed to read database"); 382334316feSJens Wiklander goto out; 383334316feSJens Wiklander } 384334316feSJens Wiklander 385334316feSJens Wiklander TEE_MemMove(ptr, token->db_objs, 386334316feSJens Wiklander sizeof(struct token_persistent_objs) + 387334316feSJens Wiklander idx * sizeof(TEE_UUID)); 388334316feSJens Wiklander 389334316feSJens Wiklander ptr->count--; 390334316feSJens Wiklander count = ptr->count - idx; 391334316feSJens Wiklander 392334316feSJens Wiklander TEE_MemMove(&ptr->uuids[idx], 393334316feSJens Wiklander &token->db_objs->uuids[idx + 1], 394334316feSJens Wiklander count * sizeof(TEE_UUID)); 395334316feSJens Wiklander 396334316feSJens Wiklander res = TEE_WriteObjectData(db_hdl, ptr, 397334316feSJens Wiklander sizeof(struct token_persistent_objs) + 398334316feSJens Wiklander ptr->count * sizeof(TEE_UUID)); 399334316feSJens Wiklander if (res) 400334316feSJens Wiklander DMSG("Failed to update database"); 401334316feSJens Wiklander TEE_Free(token->db_objs); 402334316feSJens Wiklander token->db_objs = ptr; 403334316feSJens Wiklander ptr = NULL; 404334316feSJens Wiklander 405334316feSJens Wiklander out: 406334316feSJens Wiklander TEE_CloseObject(db_hdl); 407334316feSJens Wiklander TEE_Free(ptr); 408334316feSJens Wiklander 409334316feSJens Wiklander return tee2pkcs_error(res); 410334316feSJens Wiklander } 411334316feSJens Wiklander 412334316feSJens Wiklander enum pkcs11_rc register_persistent_object(struct ck_token *token, 413334316feSJens Wiklander TEE_UUID *uuid) 414334316feSJens Wiklander { 415334316feSJens Wiklander TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; 416334316feSJens Wiklander TEE_Result res = TEE_ERROR_GENERIC; 417334316feSJens Wiklander void *ptr = NULL; 418334316feSJens Wiklander size_t size = 0; 419334316feSJens Wiklander int count = 0; 420334316feSJens Wiklander 421334316feSJens Wiklander if (get_persistent_obj_idx(token, uuid) >= 0) 422334316feSJens Wiklander TEE_Panic(0); 423334316feSJens Wiklander 424334316feSJens Wiklander count = token->db_objs->count; 425334316feSJens Wiklander ptr = TEE_Realloc(token->db_objs, 426334316feSJens Wiklander sizeof(struct token_persistent_objs) + 427334316feSJens Wiklander ((count + 1) * sizeof(TEE_UUID))); 428334316feSJens Wiklander if (!ptr) 429334316feSJens Wiklander return PKCS11_CKR_DEVICE_MEMORY; 430334316feSJens Wiklander 431334316feSJens Wiklander token->db_objs = ptr; 432334316feSJens Wiklander TEE_MemMove(token->db_objs->uuids + count, uuid, sizeof(TEE_UUID)); 433334316feSJens Wiklander 434334316feSJens Wiklander size = sizeof(struct token_persistent_main) + 435334316feSJens Wiklander sizeof(struct token_persistent_objs) + 436334316feSJens Wiklander count * sizeof(TEE_UUID); 437334316feSJens Wiklander 438334316feSJens Wiklander res = open_db_file(token, &db_hdl); 439334316feSJens Wiklander if (res) 440334316feSJens Wiklander goto out; 441334316feSJens Wiklander 442334316feSJens Wiklander res = TEE_TruncateObjectData(db_hdl, size + sizeof(TEE_UUID)); 443334316feSJens Wiklander if (res) 444334316feSJens Wiklander goto out; 445334316feSJens Wiklander 446334316feSJens Wiklander res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main), 447334316feSJens Wiklander TEE_DATA_SEEK_SET); 448334316feSJens Wiklander if (res) 449334316feSJens Wiklander goto out; 450334316feSJens Wiklander 451334316feSJens Wiklander token->db_objs->count++; 452334316feSJens Wiklander 453334316feSJens Wiklander res = TEE_WriteObjectData(db_hdl, token->db_objs, 454334316feSJens Wiklander sizeof(struct token_persistent_objs) + 455334316feSJens Wiklander token->db_objs->count * sizeof(TEE_UUID)); 456334316feSJens Wiklander if (res) 457334316feSJens Wiklander token->db_objs->count--; 458334316feSJens Wiklander 459334316feSJens Wiklander out: 460334316feSJens Wiklander TEE_CloseObject(db_hdl); 461334316feSJens Wiklander 462334316feSJens Wiklander return tee2pkcs_error(res); 463334316feSJens Wiklander } 464334316feSJens Wiklander 465*fa1ac767SRobin van der Gracht enum pkcs11_rc load_persistent_object_attributes(struct pkcs11_object *obj) 466*fa1ac767SRobin van der Gracht { 467*fa1ac767SRobin van der Gracht enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 468*fa1ac767SRobin van der Gracht TEE_Result res = TEE_ERROR_GENERIC; 469*fa1ac767SRobin van der Gracht TEE_ObjectHandle hdl = obj->attribs_hdl; 470*fa1ac767SRobin van der Gracht TEE_ObjectInfo info = { }; 471*fa1ac767SRobin van der Gracht struct obj_attrs *attr = NULL; 472*fa1ac767SRobin van der Gracht uint32_t read_bytes = 0; 473*fa1ac767SRobin van der Gracht 474*fa1ac767SRobin van der Gracht if (obj->attributes) 475*fa1ac767SRobin van der Gracht return PKCS11_CKR_OK; 476*fa1ac767SRobin van der Gracht 477*fa1ac767SRobin van der Gracht if (hdl == TEE_HANDLE_NULL) { 478*fa1ac767SRobin van der Gracht res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, 479*fa1ac767SRobin van der Gracht obj->uuid, sizeof(*obj->uuid), 480*fa1ac767SRobin van der Gracht TEE_DATA_FLAG_ACCESS_READ, &hdl); 481*fa1ac767SRobin van der Gracht if (res) { 482*fa1ac767SRobin van der Gracht EMSG("OpenPersistent failed %#"PRIx32, res); 483*fa1ac767SRobin van der Gracht return tee2pkcs_error(res); 484*fa1ac767SRobin van der Gracht } 485*fa1ac767SRobin van der Gracht } 486*fa1ac767SRobin van der Gracht 487*fa1ac767SRobin van der Gracht TEE_MemFill(&info, 0, sizeof(info)); 488*fa1ac767SRobin van der Gracht res = TEE_GetObjectInfo1(hdl, &info); 489*fa1ac767SRobin van der Gracht if (res) { 490*fa1ac767SRobin van der Gracht EMSG("GetObjectInfo failed %#"PRIx32, res); 491*fa1ac767SRobin van der Gracht rc = tee2pkcs_error(res); 492*fa1ac767SRobin van der Gracht goto out; 493*fa1ac767SRobin van der Gracht } 494*fa1ac767SRobin van der Gracht 495*fa1ac767SRobin van der Gracht attr = TEE_Malloc(info.dataSize, TEE_MALLOC_FILL_ZERO); 496*fa1ac767SRobin van der Gracht if (!attr) { 497*fa1ac767SRobin van der Gracht rc = PKCS11_CKR_DEVICE_MEMORY; 498*fa1ac767SRobin van der Gracht goto out; 499*fa1ac767SRobin van der Gracht } 500*fa1ac767SRobin van der Gracht 501*fa1ac767SRobin van der Gracht res = TEE_ReadObjectData(hdl, attr, info.dataSize, &read_bytes); 502*fa1ac767SRobin van der Gracht if (!res) { 503*fa1ac767SRobin van der Gracht res = TEE_SeekObjectData(hdl, 0, TEE_DATA_SEEK_SET); 504*fa1ac767SRobin van der Gracht if (res) 505*fa1ac767SRobin van der Gracht EMSG("Seek to 0 failed %#"PRIx32, res); 506*fa1ac767SRobin van der Gracht } 507*fa1ac767SRobin van der Gracht 508*fa1ac767SRobin van der Gracht if (res) { 509*fa1ac767SRobin van der Gracht rc = tee2pkcs_error(res); 510*fa1ac767SRobin van der Gracht EMSG("Read %"PRIu32" bytes, failed %#"PRIx32, 511*fa1ac767SRobin van der Gracht read_bytes, res); 512*fa1ac767SRobin van der Gracht goto out; 513*fa1ac767SRobin van der Gracht } 514*fa1ac767SRobin van der Gracht if (read_bytes != info.dataSize) { 515*fa1ac767SRobin van der Gracht EMSG("Read %"PRIu32" bytes, expected %"PRIu32, 516*fa1ac767SRobin van der Gracht read_bytes, info.dataSize); 517*fa1ac767SRobin van der Gracht rc = PKCS11_CKR_GENERAL_ERROR; 518*fa1ac767SRobin van der Gracht goto out; 519*fa1ac767SRobin van der Gracht } 520*fa1ac767SRobin van der Gracht 521*fa1ac767SRobin van der Gracht obj->attributes = attr; 522*fa1ac767SRobin van der Gracht attr = NULL; 523*fa1ac767SRobin van der Gracht 524*fa1ac767SRobin van der Gracht rc = PKCS11_CKR_OK; 525*fa1ac767SRobin van der Gracht 526*fa1ac767SRobin van der Gracht out: 527*fa1ac767SRobin van der Gracht TEE_Free(attr); 528*fa1ac767SRobin van der Gracht /* Close object only if it was open from this function */ 529*fa1ac767SRobin van der Gracht if (obj->attribs_hdl == TEE_HANDLE_NULL) 530*fa1ac767SRobin van der Gracht TEE_CloseObject(hdl); 531*fa1ac767SRobin van der Gracht 532*fa1ac767SRobin van der Gracht return rc; 533*fa1ac767SRobin van der Gracht } 534*fa1ac767SRobin van der Gracht 535*fa1ac767SRobin van der Gracht void release_persistent_object_attributes(struct pkcs11_object *obj) 536*fa1ac767SRobin van der Gracht { 537*fa1ac767SRobin van der Gracht TEE_Free(obj->attributes); 538*fa1ac767SRobin van der Gracht obj->attributes = NULL; 539*fa1ac767SRobin van der Gracht } 540*fa1ac767SRobin van der Gracht 54160659a86SEtienne Carriere /* 542c84ccd0aSEtienne Carriere * Return the token instance, either initialized from reset or initialized 543c84ccd0aSEtienne Carriere * from the token persistent state if found. 544c84ccd0aSEtienne Carriere */ 545c84ccd0aSEtienne Carriere struct ck_token *init_persistent_db(unsigned int token_id) 546c84ccd0aSEtienne Carriere { 547c84ccd0aSEtienne Carriere struct ck_token *token = get_token(token_id); 548c84ccd0aSEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC; 549c84ccd0aSEtienne Carriere TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; 55060659a86SEtienne Carriere /* Copy persistent database: main db and object db */ 551c84ccd0aSEtienne Carriere struct token_persistent_main *db_main = NULL; 552334316feSJens Wiklander struct token_persistent_objs *db_objs = NULL; 553334316feSJens Wiklander void *ptr = NULL; 554c84ccd0aSEtienne Carriere 555c84ccd0aSEtienne Carriere if (!token) 556c84ccd0aSEtienne Carriere return NULL; 557c84ccd0aSEtienne Carriere 558334316feSJens Wiklander LIST_INIT(&token->object_list); 559334316feSJens Wiklander 560c84ccd0aSEtienne Carriere db_main = TEE_Malloc(sizeof(*db_main), TEE_MALLOC_FILL_ZERO); 561334316feSJens Wiklander db_objs = TEE_Malloc(sizeof(*db_objs), TEE_MALLOC_FILL_ZERO); 562334316feSJens Wiklander if (!db_main || !db_objs) 563c84ccd0aSEtienne Carriere goto error; 564c84ccd0aSEtienne Carriere 56560659a86SEtienne Carriere res = open_db_file(token, &db_hdl); 566c84ccd0aSEtienne Carriere 567c84ccd0aSEtienne Carriere if (res == TEE_SUCCESS) { 568c84ccd0aSEtienne Carriere uint32_t size = 0; 569334316feSJens Wiklander size_t idx = 0; 570c84ccd0aSEtienne Carriere 571c84ccd0aSEtienne Carriere IMSG("PKCS11 token %u: load db", token_id); 572c84ccd0aSEtienne Carriere 573c84ccd0aSEtienne Carriere size = sizeof(*db_main); 574c84ccd0aSEtienne Carriere res = TEE_ReadObjectData(db_hdl, db_main, size, &size); 575c84ccd0aSEtienne Carriere if (res || size != sizeof(*db_main)) 576c84ccd0aSEtienne Carriere TEE_Panic(0); 577334316feSJens Wiklander 578334316feSJens Wiklander size = sizeof(*db_objs); 579334316feSJens Wiklander res = TEE_ReadObjectData(db_hdl, db_objs, size, &size); 580334316feSJens Wiklander if (res || size != sizeof(*db_objs)) 581334316feSJens Wiklander TEE_Panic(0); 582334316feSJens Wiklander 583974adb9fSRobin van der Gracht if (db_objs->count > 0) { 584334316feSJens Wiklander size += db_objs->count * sizeof(TEE_UUID); 585334316feSJens Wiklander ptr = TEE_Realloc(db_objs, size); 586334316feSJens Wiklander if (!ptr) 587334316feSJens Wiklander goto error; 588334316feSJens Wiklander 589334316feSJens Wiklander db_objs = ptr; 590a3c511dfSRobin van der Gracht size -= sizeof(*db_objs); 591974adb9fSRobin van der Gracht res = TEE_ReadObjectData(db_hdl, db_objs->uuids, size, 592974adb9fSRobin van der Gracht &size); 593334316feSJens Wiklander if (res || size != (db_objs->count * sizeof(TEE_UUID))) 594334316feSJens Wiklander TEE_Panic(0); 595974adb9fSRobin van der Gracht } 596334316feSJens Wiklander 597334316feSJens Wiklander for (idx = 0; idx < db_objs->count; idx++) { 598334316feSJens Wiklander /* Create an empty object instance */ 599334316feSJens Wiklander struct pkcs11_object *obj = NULL; 600334316feSJens Wiklander TEE_UUID *uuid = NULL; 601334316feSJens Wiklander 602334316feSJens Wiklander uuid = TEE_Malloc(sizeof(TEE_UUID), 603334316feSJens Wiklander TEE_USER_MEM_HINT_NO_FILL_ZERO); 604334316feSJens Wiklander if (!uuid) 605334316feSJens Wiklander goto error; 606334316feSJens Wiklander 607334316feSJens Wiklander TEE_MemMove(uuid, &db_objs->uuids[idx], sizeof(*uuid)); 608334316feSJens Wiklander 609334316feSJens Wiklander obj = create_token_object(NULL, uuid); 610334316feSJens Wiklander if (!obj) 611334316feSJens Wiklander TEE_Panic(0); 612334316feSJens Wiklander 613334316feSJens Wiklander LIST_INSERT_HEAD(&token->object_list, obj, link); 614334316feSJens Wiklander } 615334316feSJens Wiklander 616c84ccd0aSEtienne Carriere } else if (res == TEE_ERROR_ITEM_NOT_FOUND) { 61760659a86SEtienne Carriere char file[PERSISTENT_OBJECT_ID_LEN] = { }; 61860659a86SEtienne Carriere 619c84ccd0aSEtienne Carriere IMSG("PKCS11 token %u: init db", token_id); 620c84ccd0aSEtienne Carriere 621c84ccd0aSEtienne Carriere TEE_MemFill(db_main, 0, sizeof(*db_main)); 622c84ccd0aSEtienne Carriere TEE_MemFill(db_main->label, '*', sizeof(db_main->label)); 623c84ccd0aSEtienne Carriere 624c84ccd0aSEtienne Carriere db_main->flags = PKCS11_CKFT_SO_PIN_TO_BE_CHANGED | 625c84ccd0aSEtienne Carriere PKCS11_CKFT_USER_PIN_TO_BE_CHANGED | 626c84ccd0aSEtienne Carriere PKCS11_CKFT_RNG | 627c84ccd0aSEtienne Carriere PKCS11_CKFT_DUAL_CRYPTO_OPERATIONS | 628c84ccd0aSEtienne Carriere PKCS11_CKFT_LOGIN_REQUIRED; 629c84ccd0aSEtienne Carriere 63060659a86SEtienne Carriere res = get_db_file_name(token, file, sizeof(file)); 63160659a86SEtienne Carriere if (res) 63260659a86SEtienne Carriere TEE_Panic(0); 63360659a86SEtienne Carriere 634334316feSJens Wiklander /* 635334316feSJens Wiklander * Object stores persistent state + persistent object 636334316feSJens Wiklander * references. 637334316feSJens Wiklander */ 638c84ccd0aSEtienne Carriere res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, 63960659a86SEtienne Carriere file, sizeof(file), 640c84ccd0aSEtienne Carriere TEE_DATA_FLAG_ACCESS_READ | 641c84ccd0aSEtienne Carriere TEE_DATA_FLAG_ACCESS_WRITE, 642c84ccd0aSEtienne Carriere TEE_HANDLE_NULL, 643c84ccd0aSEtienne Carriere db_main, sizeof(*db_main), 644c84ccd0aSEtienne Carriere &db_hdl); 645c84ccd0aSEtienne Carriere if (res) { 64659a5257eSEtienne Carriere EMSG("Failed to create db: %#"PRIx32, res); 647c84ccd0aSEtienne Carriere goto error; 648c84ccd0aSEtienne Carriere } 649334316feSJens Wiklander 650334316feSJens Wiklander res = TEE_TruncateObjectData(db_hdl, sizeof(*db_main) + 651334316feSJens Wiklander sizeof(*db_objs)); 652334316feSJens Wiklander if (res) 653334316feSJens Wiklander TEE_Panic(0); 654334316feSJens Wiklander 655334316feSJens Wiklander res = TEE_SeekObjectData(db_hdl, sizeof(*db_main), 656334316feSJens Wiklander TEE_DATA_SEEK_SET); 657334316feSJens Wiklander if (res) 658334316feSJens Wiklander TEE_Panic(0); 659334316feSJens Wiklander 660334316feSJens Wiklander db_objs->count = 0; 661334316feSJens Wiklander res = TEE_WriteObjectData(db_hdl, db_objs, sizeof(*db_objs)); 662334316feSJens Wiklander if (res) 663334316feSJens Wiklander TEE_Panic(0); 664334316feSJens Wiklander 665c84ccd0aSEtienne Carriere } else { 666c84ccd0aSEtienne Carriere goto error; 667c84ccd0aSEtienne Carriere } 668c84ccd0aSEtienne Carriere 669c84ccd0aSEtienne Carriere token->db_main = db_main; 670334316feSJens Wiklander token->db_objs = db_objs; 671c84ccd0aSEtienne Carriere TEE_CloseObject(db_hdl); 672c84ccd0aSEtienne Carriere 673c84ccd0aSEtienne Carriere return token; 674c84ccd0aSEtienne Carriere 675c84ccd0aSEtienne Carriere error: 676c84ccd0aSEtienne Carriere TEE_Free(db_main); 677334316feSJens Wiklander TEE_Free(db_objs); 678c84ccd0aSEtienne Carriere if (db_hdl != TEE_HANDLE_NULL) 679c84ccd0aSEtienne Carriere TEE_CloseObject(db_hdl); 680c84ccd0aSEtienne Carriere 681c84ccd0aSEtienne Carriere return NULL; 682c84ccd0aSEtienne Carriere } 683