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, unsigned int uid) 77 { 78 TEE_Result res = TEE_ERROR_GENERIC; 79 TEE_ObjectHandle key_hdl = TEE_HANDLE_NULL; 80 enum pkcs11_user_type user = uid; 81 82 res = open_pin_file(token, user, &key_hdl); 83 84 if (res == TEE_SUCCESS) 85 DMSG("PIN key found"); 86 87 if (res == TEE_ERROR_ITEM_NOT_FOUND) { 88 TEE_Attribute attr = { }; 89 TEE_ObjectHandle hdl = TEE_HANDLE_NULL; 90 uint8_t pin_key[16] = { }; 91 char file[PERSISTENT_OBJECT_ID_LEN] = { }; 92 93 TEE_MemFill(&attr, 0, sizeof(attr)); 94 95 TEE_GenerateRandom(pin_key, sizeof(pin_key)); 96 TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, 97 pin_key, sizeof(pin_key)); 98 99 res = TEE_AllocateTransientObject(TEE_TYPE_AES, 128, &hdl); 100 if (res) 101 TEE_Panic(0); 102 103 res = TEE_PopulateTransientObject(hdl, &attr, 1); 104 if (res) 105 TEE_Panic(0); 106 107 res = get_pin_file_name(token, user, file, sizeof(file)); 108 if (res) 109 TEE_Panic(0); 110 111 res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, 112 file, sizeof(file), 0, hdl, 113 pin_key, sizeof(pin_key), 114 &key_hdl); 115 TEE_CloseObject(hdl); 116 117 if (res == TEE_SUCCESS) 118 DMSG("Token %u: PIN key created", get_token_id(token)); 119 } 120 121 if (res) 122 TEE_Panic(res); 123 124 TEE_CloseObject(key_hdl); 125 } 126 127 /* 128 * Release resources relate to persistent database 129 */ 130 void close_persistent_db(struct ck_token *token __unused) 131 { 132 } 133 134 /* 135 * Return the token instance, either initialized from reset or initialized 136 * from the token persistent state if found. 137 */ 138 struct ck_token *init_persistent_db(unsigned int token_id) 139 { 140 struct ck_token *token = get_token(token_id); 141 TEE_Result res = TEE_ERROR_GENERIC; 142 TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; 143 /* Copy persistent database: main db and object db */ 144 struct token_persistent_main *db_main = NULL; 145 146 if (!token) 147 return NULL; 148 149 init_pin_keys(token, PKCS11_CKU_SO); 150 init_pin_keys(token, PKCS11_CKU_USER); 151 COMPILE_TIME_ASSERT(PKCS11_CKU_SO == 0 && PKCS11_CKU_USER == 1 && 152 PKCS11_MAX_USERS >= 2); 153 154 db_main = TEE_Malloc(sizeof(*db_main), TEE_MALLOC_FILL_ZERO); 155 if (!db_main) 156 goto error; 157 158 res = open_db_file(token, &db_hdl); 159 160 if (res == TEE_SUCCESS) { 161 uint32_t size = 0; 162 163 IMSG("PKCS11 token %u: load db", token_id); 164 165 size = sizeof(*db_main); 166 res = TEE_ReadObjectData(db_hdl, db_main, size, &size); 167 if (res || size != sizeof(*db_main)) 168 TEE_Panic(0); 169 } else if (res == TEE_ERROR_ITEM_NOT_FOUND) { 170 char file[PERSISTENT_OBJECT_ID_LEN] = { }; 171 172 IMSG("PKCS11 token %u: init db", token_id); 173 174 TEE_MemFill(db_main, 0, sizeof(*db_main)); 175 TEE_MemFill(db_main->label, '*', sizeof(db_main->label)); 176 177 db_main->flags = PKCS11_CKFT_SO_PIN_TO_BE_CHANGED | 178 PKCS11_CKFT_USER_PIN_TO_BE_CHANGED | 179 PKCS11_CKFT_RNG | 180 PKCS11_CKFT_DUAL_CRYPTO_OPERATIONS | 181 PKCS11_CKFT_LOGIN_REQUIRED; 182 183 res = get_db_file_name(token, file, sizeof(file)); 184 if (res) 185 TEE_Panic(0); 186 187 /* 2 files: persistent state + persistent object references */ 188 res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, 189 file, sizeof(file), 190 TEE_DATA_FLAG_ACCESS_READ | 191 TEE_DATA_FLAG_ACCESS_WRITE, 192 TEE_HANDLE_NULL, 193 db_main, sizeof(*db_main), 194 &db_hdl); 195 if (res) { 196 EMSG("Failed to create db: %"PRIx32, res); 197 goto error; 198 } 199 } else { 200 goto error; 201 } 202 203 token->db_main = db_main; 204 TEE_CloseObject(db_hdl); 205 206 return token; 207 208 error: 209 TEE_Free(db_main); 210 if (db_hdl != TEE_HANDLE_NULL) 211 TEE_CloseObject(db_hdl); 212 213 return NULL; 214 } 215