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 "pkcs11_token.h" 14 #include "pkcs11_helpers.h" 15 16 #define PERSISTENT_OBJECT_ID_LEN 32 17 18 /* 19 * Token persistent objects 20 */ 21 static TEE_Result get_db_file_name(struct ck_token *token, 22 char *name, size_t size) 23 { 24 int n = snprintf(name, size, "token.db.%u", get_token_id(token)); 25 26 if (n < 0 || (size_t)n >= size) 27 return TEE_ERROR_SECURITY; 28 else 29 return TEE_SUCCESS; 30 } 31 32 static TEE_Result open_db_file(struct ck_token *token, 33 TEE_ObjectHandle *out_hdl) 34 { 35 char file[PERSISTENT_OBJECT_ID_LEN] = { }; 36 TEE_Result res = TEE_ERROR_GENERIC; 37 38 res = get_db_file_name(token, file, sizeof(file)); 39 if (res) 40 return res; 41 42 return TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, file, sizeof(file), 43 TEE_DATA_FLAG_ACCESS_READ | 44 TEE_DATA_FLAG_ACCESS_WRITE, 45 out_hdl); 46 } 47 48 static TEE_Result get_pin_file_name(struct ck_token *token, 49 enum pkcs11_user_type user, 50 char *name, size_t size) 51 { 52 int n = snprintf(name, size, 53 "token.db.%u-pin%d", get_token_id(token), user); 54 55 if (n < 0 || (size_t)n >= size) 56 return TEE_ERROR_SECURITY; 57 else 58 return TEE_SUCCESS; 59 } 60 61 static TEE_Result open_pin_file(struct ck_token *token, 62 enum pkcs11_user_type user, 63 TEE_ObjectHandle *out_hdl) 64 { 65 char file[PERSISTENT_OBJECT_ID_LEN] = { }; 66 TEE_Result res = TEE_ERROR_GENERIC; 67 68 res = get_pin_file_name(token, user, file, sizeof(file)); 69 if (res) 70 return res; 71 72 return TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, file, sizeof(file), 73 0, out_hdl); 74 } 75 76 static void init_pin_keys(struct ck_token *token, enum pkcs11_user_type user) 77 { 78 TEE_Result res = TEE_ERROR_GENERIC; 79 TEE_ObjectHandle key_hdl = TEE_HANDLE_NULL; 80 81 res = open_pin_file(token, user, &key_hdl); 82 83 if (res == TEE_SUCCESS) 84 DMSG("PIN key found"); 85 86 if (res == TEE_ERROR_ITEM_NOT_FOUND) { 87 TEE_Attribute attr = { }; 88 TEE_ObjectHandle hdl = TEE_HANDLE_NULL; 89 uint8_t pin_key[16] = { }; 90 char file[PERSISTENT_OBJECT_ID_LEN] = { }; 91 92 TEE_MemFill(&attr, 0, sizeof(attr)); 93 94 TEE_GenerateRandom(pin_key, sizeof(pin_key)); 95 TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, 96 pin_key, sizeof(pin_key)); 97 98 res = TEE_AllocateTransientObject(TEE_TYPE_AES, 128, &hdl); 99 if (res) 100 TEE_Panic(0); 101 102 res = TEE_PopulateTransientObject(hdl, &attr, 1); 103 if (res) 104 TEE_Panic(0); 105 106 res = get_pin_file_name(token, user, file, sizeof(file)); 107 if (res) 108 TEE_Panic(0); 109 110 res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, 111 file, sizeof(file), 0, hdl, 112 pin_key, sizeof(pin_key), 113 &key_hdl); 114 TEE_CloseObject(hdl); 115 116 if (res == TEE_SUCCESS) 117 DMSG("Token %u: PIN key created", get_token_id(token)); 118 } 119 120 if (res) 121 TEE_Panic(res); 122 123 TEE_CloseObject(key_hdl); 124 } 125 126 /* 127 * Release resources relate to persistent database 128 */ 129 void close_persistent_db(struct ck_token *token __unused) 130 { 131 } 132 133 /* 134 * Return the token instance, either initialized from reset or initialized 135 * from the token persistent state if found. 136 */ 137 struct ck_token *init_persistent_db(unsigned int token_id) 138 { 139 struct ck_token *token = get_token(token_id); 140 TEE_Result res = TEE_ERROR_GENERIC; 141 TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; 142 /* Copy persistent database: main db and object db */ 143 struct token_persistent_main *db_main = NULL; 144 145 if (!token) 146 return NULL; 147 148 init_pin_keys(token, PKCS11_CKU_SO); 149 init_pin_keys(token, PKCS11_CKU_USER); 150 COMPILE_TIME_ASSERT(PKCS11_CKU_SO == 0 && PKCS11_CKU_USER == 1 && 151 PKCS11_MAX_USERS >= 2); 152 153 db_main = TEE_Malloc(sizeof(*db_main), TEE_MALLOC_FILL_ZERO); 154 if (!db_main) 155 goto error; 156 157 res = open_db_file(token, &db_hdl); 158 159 if (res == TEE_SUCCESS) { 160 uint32_t size = 0; 161 162 IMSG("PKCS11 token %u: load db", token_id); 163 164 size = sizeof(*db_main); 165 res = TEE_ReadObjectData(db_hdl, db_main, size, &size); 166 if (res || size != sizeof(*db_main)) 167 TEE_Panic(0); 168 } else if (res == TEE_ERROR_ITEM_NOT_FOUND) { 169 char file[PERSISTENT_OBJECT_ID_LEN] = { }; 170 171 IMSG("PKCS11 token %u: init db", token_id); 172 173 TEE_MemFill(db_main, 0, sizeof(*db_main)); 174 TEE_MemFill(db_main->label, '*', sizeof(db_main->label)); 175 176 db_main->flags = PKCS11_CKFT_SO_PIN_TO_BE_CHANGED | 177 PKCS11_CKFT_USER_PIN_TO_BE_CHANGED | 178 PKCS11_CKFT_RNG | 179 PKCS11_CKFT_DUAL_CRYPTO_OPERATIONS | 180 PKCS11_CKFT_LOGIN_REQUIRED; 181 182 res = get_db_file_name(token, file, sizeof(file)); 183 if (res) 184 TEE_Panic(0); 185 186 res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, 187 file, sizeof(file), 188 TEE_DATA_FLAG_ACCESS_READ | 189 TEE_DATA_FLAG_ACCESS_WRITE, 190 TEE_HANDLE_NULL, 191 db_main, sizeof(*db_main), 192 &db_hdl); 193 if (res) { 194 EMSG("Failed to create db: %"PRIx32, res); 195 goto error; 196 } 197 } else { 198 goto error; 199 } 200 201 token->db_main = db_main; 202 TEE_CloseObject(db_hdl); 203 204 return token; 205 206 error: 207 TEE_Free(db_main); 208 if (db_hdl != TEE_HANDLE_NULL) 209 TEE_CloseObject(db_hdl); 210 211 return NULL; 212 } 213