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 16c84ccd0aSEtienne Carriere void close_persistent_db(struct ck_token *token __unused) 17c84ccd0aSEtienne Carriere { 18c84ccd0aSEtienne Carriere } 19c84ccd0aSEtienne Carriere 20c84ccd0aSEtienne Carriere static void init_pin_keys(struct ck_token *token, unsigned int uid) 21c84ccd0aSEtienne Carriere { 22c84ccd0aSEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC; 23c84ccd0aSEtienne Carriere unsigned int token_id = get_token_id(token); 24c84ccd0aSEtienne Carriere TEE_ObjectHandle key_hdl = TEE_HANDLE_NULL; 25c84ccd0aSEtienne Carriere char file[32] = { 0 }; 26be1ce869SEtienne Carriere int n = 0; 27c84ccd0aSEtienne Carriere 28c84ccd0aSEtienne Carriere assert(token_id < 10 && uid < 10); 29c84ccd0aSEtienne Carriere 30be1ce869SEtienne Carriere n = snprintf(file, sizeof(file), "token.db.%1d-pin%1d", token_id, uid); 31be1ce869SEtienne Carriere if (n < 0 || (size_t)n >= sizeof(file)) 32c84ccd0aSEtienne Carriere TEE_Panic(0); 33c84ccd0aSEtienne Carriere 34c84ccd0aSEtienne Carriere res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, 35c84ccd0aSEtienne Carriere file, sizeof(file), 0, &key_hdl); 36c84ccd0aSEtienne Carriere 37c84ccd0aSEtienne Carriere if (res == TEE_ERROR_ITEM_NOT_FOUND) { 38c84ccd0aSEtienne Carriere TEE_Attribute attr = { }; 39c84ccd0aSEtienne Carriere TEE_ObjectHandle hdl = TEE_HANDLE_NULL; 40c84ccd0aSEtienne Carriere uint8_t pin_key[16] = { 0 }; 41c84ccd0aSEtienne Carriere 42c84ccd0aSEtienne Carriere TEE_MemFill(&attr, 0, sizeof(attr)); 43c84ccd0aSEtienne Carriere 44c84ccd0aSEtienne Carriere TEE_GenerateRandom(pin_key, sizeof(pin_key)); 45c84ccd0aSEtienne Carriere TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, 46c84ccd0aSEtienne Carriere pin_key, sizeof(pin_key)); 47c84ccd0aSEtienne Carriere 48c84ccd0aSEtienne Carriere res = TEE_AllocateTransientObject(TEE_TYPE_AES, 128, &hdl); 49c84ccd0aSEtienne Carriere if (res) 50c84ccd0aSEtienne Carriere TEE_Panic(0); 51c84ccd0aSEtienne Carriere 52c84ccd0aSEtienne Carriere res = TEE_PopulateTransientObject(hdl, &attr, 1); 53c84ccd0aSEtienne Carriere if (res) 54c84ccd0aSEtienne Carriere TEE_Panic(0); 55c84ccd0aSEtienne Carriere 56c84ccd0aSEtienne Carriere res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, 57c84ccd0aSEtienne Carriere file, sizeof(file), 0, hdl, 58c84ccd0aSEtienne Carriere pin_key, sizeof(pin_key), 59c84ccd0aSEtienne Carriere &key_hdl); 60c84ccd0aSEtienne Carriere TEE_CloseObject(hdl); 61c84ccd0aSEtienne Carriere 62c84ccd0aSEtienne Carriere if (res == TEE_SUCCESS) 63c84ccd0aSEtienne Carriere DMSG("Token %u: PIN key created", token_id); 64c84ccd0aSEtienne Carriere } 65c84ccd0aSEtienne Carriere 66c84ccd0aSEtienne Carriere if (res) 67c84ccd0aSEtienne Carriere TEE_Panic(res); 68c84ccd0aSEtienne Carriere 69c84ccd0aSEtienne Carriere TEE_CloseObject(key_hdl); 70c84ccd0aSEtienne Carriere } 71c84ccd0aSEtienne Carriere 72c84ccd0aSEtienne Carriere /* 73c84ccd0aSEtienne Carriere * Return the token instance, either initialized from reset or initialized 74c84ccd0aSEtienne Carriere * from the token persistent state if found. 75c84ccd0aSEtienne Carriere */ 76c84ccd0aSEtienne Carriere struct ck_token *init_persistent_db(unsigned int token_id) 77c84ccd0aSEtienne Carriere { 78c84ccd0aSEtienne Carriere struct ck_token *token = get_token(token_id); 79c84ccd0aSEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC; 80c84ccd0aSEtienne Carriere char db_file[32] = { 0 }; 81c84ccd0aSEtienne Carriere TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; 82c84ccd0aSEtienne Carriere struct token_persistent_main *db_main = NULL; 83c84ccd0aSEtienne Carriere int n = 0; 84c84ccd0aSEtienne Carriere 85c84ccd0aSEtienne Carriere if (!token) 86c84ccd0aSEtienne Carriere return NULL; 87c84ccd0aSEtienne Carriere 88*9dbdd8cdSEtienne Carriere init_pin_keys(token, PKCS11_CKU_SO); 89*9dbdd8cdSEtienne Carriere init_pin_keys(token, PKCS11_CKU_USER); 90*9dbdd8cdSEtienne Carriere COMPILE_TIME_ASSERT(PKCS11_CKU_SO == 0 && PKCS11_CKU_USER == 1 && 91*9dbdd8cdSEtienne Carriere PKCS11_MAX_USERS >= 2); 92c84ccd0aSEtienne Carriere 93c84ccd0aSEtienne Carriere db_main = TEE_Malloc(sizeof(*db_main), TEE_MALLOC_FILL_ZERO); 94c84ccd0aSEtienne Carriere if (!db_main) 95c84ccd0aSEtienne Carriere goto error; 96c84ccd0aSEtienne Carriere 97be1ce869SEtienne Carriere n = snprintf(db_file, sizeof(db_file), "token.db.%1d", token_id); 98be1ce869SEtienne Carriere if (n < 0 || (size_t)n >= sizeof(db_file)) 99c84ccd0aSEtienne Carriere TEE_Panic(0); 100c84ccd0aSEtienne Carriere 101c84ccd0aSEtienne Carriere res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, 102c84ccd0aSEtienne Carriere db_file, sizeof(db_file), 103c84ccd0aSEtienne Carriere TEE_DATA_FLAG_ACCESS_READ | 104c84ccd0aSEtienne Carriere TEE_DATA_FLAG_ACCESS_WRITE, 105c84ccd0aSEtienne Carriere &db_hdl); 106c84ccd0aSEtienne Carriere if (res == TEE_SUCCESS) { 107c84ccd0aSEtienne Carriere uint32_t size = 0; 108c84ccd0aSEtienne Carriere 109c84ccd0aSEtienne Carriere IMSG("PKCS11 token %u: load db", token_id); 110c84ccd0aSEtienne Carriere 111c84ccd0aSEtienne Carriere size = sizeof(*db_main); 112c84ccd0aSEtienne Carriere res = TEE_ReadObjectData(db_hdl, db_main, size, &size); 113c84ccd0aSEtienne Carriere if (res || size != sizeof(*db_main)) 114c84ccd0aSEtienne Carriere TEE_Panic(0); 115c84ccd0aSEtienne Carriere } else if (res == TEE_ERROR_ITEM_NOT_FOUND) { 116c84ccd0aSEtienne Carriere IMSG("PKCS11 token %u: init db", token_id); 117c84ccd0aSEtienne Carriere 118c84ccd0aSEtienne Carriere TEE_MemFill(db_main, 0, sizeof(*db_main)); 119c84ccd0aSEtienne Carriere TEE_MemFill(db_main->label, '*', sizeof(db_main->label)); 120c84ccd0aSEtienne Carriere 121c84ccd0aSEtienne Carriere db_main->flags = PKCS11_CKFT_SO_PIN_TO_BE_CHANGED | 122c84ccd0aSEtienne Carriere PKCS11_CKFT_USER_PIN_TO_BE_CHANGED | 123c84ccd0aSEtienne Carriere PKCS11_CKFT_RNG | 124c84ccd0aSEtienne Carriere PKCS11_CKFT_DUAL_CRYPTO_OPERATIONS | 125c84ccd0aSEtienne Carriere PKCS11_CKFT_LOGIN_REQUIRED; 126c84ccd0aSEtienne Carriere 127c84ccd0aSEtienne Carriere res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, 128c84ccd0aSEtienne Carriere db_file, sizeof(db_file), 129c84ccd0aSEtienne Carriere TEE_DATA_FLAG_ACCESS_READ | 130c84ccd0aSEtienne Carriere TEE_DATA_FLAG_ACCESS_WRITE, 131c84ccd0aSEtienne Carriere TEE_HANDLE_NULL, 132c84ccd0aSEtienne Carriere db_main, sizeof(*db_main), 133c84ccd0aSEtienne Carriere &db_hdl); 134c84ccd0aSEtienne Carriere if (res) { 135c84ccd0aSEtienne Carriere EMSG("Failed to create db: %"PRIx32, res); 136c84ccd0aSEtienne Carriere goto error; 137c84ccd0aSEtienne Carriere } 138c84ccd0aSEtienne Carriere } else { 139c84ccd0aSEtienne Carriere goto error; 140c84ccd0aSEtienne Carriere } 141c84ccd0aSEtienne Carriere 142c84ccd0aSEtienne Carriere token->db_main = db_main; 143c84ccd0aSEtienne Carriere TEE_CloseObject(db_hdl); 144c84ccd0aSEtienne Carriere 145c84ccd0aSEtienne Carriere return token; 146c84ccd0aSEtienne Carriere 147c84ccd0aSEtienne Carriere error: 148c84ccd0aSEtienne Carriere TEE_Free(db_main); 149c84ccd0aSEtienne Carriere if (db_hdl != TEE_HANDLE_NULL) 150c84ccd0aSEtienne Carriere TEE_CloseObject(db_hdl); 151c84ccd0aSEtienne Carriere 152c84ccd0aSEtienne Carriere return NULL; 153c84ccd0aSEtienne Carriere } 154