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