1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2017-2020, Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <confine_array_index.h> 8 #include <pkcs11_ta.h> 9 #include <string.h> 10 #include <string_ext.h> 11 #include <sys/queue.h> 12 #include <tee_api_types.h> 13 #include <tee_internal_api_extensions.h> 14 #include <util.h> 15 16 #include "pkcs11_token.h" 17 #include "pkcs11_helpers.h" 18 #include "serializer.h" 19 20 /* Provide 3 slots/tokens, ID is token index */ 21 #ifndef CFG_PKCS11_TA_TOKEN_COUNT 22 #define TOKEN_COUNT 3 23 #else 24 #define TOKEN_COUNT CFG_PKCS11_TA_TOKEN_COUNT 25 #endif 26 27 /* 28 * Structure tracking client applications 29 * 30 * @link - chained list of registered client applications 31 * @sessions - list of the PKCS11 sessions opened by the client application 32 */ 33 struct pkcs11_client { 34 TAILQ_ENTRY(pkcs11_client) link; 35 struct session_list session_list; 36 struct handle_db session_handle_db; 37 }; 38 39 /* Static allocation of tokens runtime instances (reset to 0 at load) */ 40 struct ck_token ck_token[TOKEN_COUNT]; 41 42 static struct client_list pkcs11_client_list = 43 TAILQ_HEAD_INITIALIZER(pkcs11_client_list); 44 45 struct ck_token *get_token(unsigned int token_id) 46 { 47 if (token_id < TOKEN_COUNT) 48 return &ck_token[confine_array_index(token_id, TOKEN_COUNT)]; 49 50 return NULL; 51 } 52 53 unsigned int get_token_id(struct ck_token *token) 54 { 55 ptrdiff_t id = token - ck_token; 56 57 assert(id >= 0 && id < TOKEN_COUNT); 58 return id; 59 } 60 61 struct pkcs11_client *tee_session2client(void *tee_session) 62 { 63 struct pkcs11_client *client = NULL; 64 65 TAILQ_FOREACH(client, &pkcs11_client_list, link) 66 if (client == tee_session) 67 break; 68 69 return client; 70 } 71 72 struct pkcs11_client *register_client(void) 73 { 74 struct pkcs11_client *client = NULL; 75 76 client = TEE_Malloc(sizeof(*client), TEE_MALLOC_FILL_ZERO); 77 if (!client) 78 return NULL; 79 80 TAILQ_INSERT_HEAD(&pkcs11_client_list, client, link); 81 TAILQ_INIT(&client->session_list); 82 handle_db_init(&client->session_handle_db); 83 84 return client; 85 } 86 87 void unregister_client(struct pkcs11_client *client) 88 { 89 if (!client) { 90 EMSG("Invalid TEE session handle"); 91 return; 92 } 93 94 TAILQ_REMOVE(&pkcs11_client_list, client, link); 95 handle_db_destroy(&client->session_handle_db); 96 TEE_Free(client); 97 } 98 99 static TEE_Result pkcs11_token_init(unsigned int id) 100 { 101 struct ck_token *token = init_persistent_db(id); 102 103 if (!token) 104 return TEE_ERROR_SECURITY; 105 106 if (token->state == PKCS11_TOKEN_RESET) { 107 /* As per PKCS#11 spec, token resets to read/write state */ 108 token->state = PKCS11_TOKEN_READ_WRITE; 109 token->session_count = 0; 110 token->rw_session_count = 0; 111 } 112 113 return TEE_SUCCESS; 114 } 115 116 TEE_Result pkcs11_init(void) 117 { 118 unsigned int id = 0; 119 TEE_Result ret = TEE_ERROR_GENERIC; 120 121 for (id = 0; id < TOKEN_COUNT; id++) { 122 ret = pkcs11_token_init(id); 123 if (ret) 124 break; 125 } 126 127 return ret; 128 } 129 130 void pkcs11_deinit(void) 131 { 132 unsigned int id = 0; 133 134 for (id = 0; id < TOKEN_COUNT; id++) 135 close_persistent_db(get_token(id)); 136 } 137 138 uint32_t entry_ck_slot_list(uint32_t ptypes, TEE_Param *params) 139 { 140 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 141 TEE_PARAM_TYPE_NONE, 142 TEE_PARAM_TYPE_MEMREF_OUTPUT, 143 TEE_PARAM_TYPE_NONE); 144 TEE_Param *out = ¶ms[2]; 145 uint32_t token_id = 0; 146 const size_t out_size = sizeof(token_id) * TOKEN_COUNT; 147 uint8_t *id = NULL; 148 149 if (ptypes != exp_pt || 150 params[0].memref.size != TEE_PARAM0_SIZE_MIN) 151 return PKCS11_CKR_ARGUMENTS_BAD; 152 153 if (out->memref.size < out_size) { 154 out->memref.size = out_size; 155 156 if (out->memref.buffer) 157 return PKCS11_CKR_BUFFER_TOO_SMALL; 158 else 159 return PKCS11_CKR_OK; 160 } 161 162 for (token_id = 0, id = out->memref.buffer; token_id < TOKEN_COUNT; 163 token_id++, id += sizeof(token_id)) 164 TEE_MemMove(id, &token_id, sizeof(token_id)); 165 166 out->memref.size = out_size; 167 168 return PKCS11_CKR_OK; 169 } 170 171 static void pad_str(uint8_t *str, size_t size) 172 { 173 int n = strnlen((char *)str, size); 174 175 TEE_MemFill(str + n, ' ', size - n); 176 } 177 178 uint32_t entry_ck_slot_info(uint32_t ptypes, TEE_Param *params) 179 { 180 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 181 TEE_PARAM_TYPE_NONE, 182 TEE_PARAM_TYPE_MEMREF_OUTPUT, 183 TEE_PARAM_TYPE_NONE); 184 TEE_Param *ctrl = ¶ms[0]; 185 TEE_Param *out = ¶ms[2]; 186 uint32_t rv = 0; 187 struct serialargs ctrlargs = { }; 188 uint32_t token_id = 0; 189 struct ck_token *token = NULL; 190 struct pkcs11_slot_info info = { 191 .slot_description = PKCS11_SLOT_DESCRIPTION, 192 .manufacturer_id = PKCS11_SLOT_MANUFACTURER, 193 .flags = PKCS11_CKFS_TOKEN_PRESENT, 194 .hardware_version = PKCS11_SLOT_HW_VERSION, 195 .firmware_version = PKCS11_SLOT_FW_VERSION, 196 }; 197 198 COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_DESCRIPTION) <= 199 sizeof(info.slot_description)); 200 COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_MANUFACTURER) <= 201 sizeof(info.manufacturer_id)); 202 203 if (ptypes != exp_pt || out->memref.size != sizeof(info)) 204 return PKCS11_CKR_ARGUMENTS_BAD; 205 206 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 207 208 rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); 209 if (rv) 210 return rv; 211 212 if (serialargs_remaining_bytes(&ctrlargs)) 213 return PKCS11_CKR_ARGUMENTS_BAD; 214 215 token = get_token(token_id); 216 if (!token) 217 return PKCS11_CKR_SLOT_ID_INVALID; 218 219 pad_str(info.slot_description, sizeof(info.slot_description)); 220 pad_str(info.manufacturer_id, sizeof(info.manufacturer_id)); 221 222 out->memref.size = sizeof(info); 223 TEE_MemMove(out->memref.buffer, &info, out->memref.size); 224 225 return PKCS11_CKR_OK; 226 } 227 228 uint32_t entry_ck_token_info(uint32_t ptypes, TEE_Param *params) 229 { 230 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 231 TEE_PARAM_TYPE_NONE, 232 TEE_PARAM_TYPE_MEMREF_OUTPUT, 233 TEE_PARAM_TYPE_NONE); 234 TEE_Param *ctrl = ¶ms[0]; 235 TEE_Param *out = ¶ms[2]; 236 uint32_t rv = 0; 237 struct serialargs ctrlargs = { }; 238 uint32_t token_id = 0; 239 struct ck_token *token = NULL; 240 struct pkcs11_token_info info = { 241 .manufacturer_id = PKCS11_TOKEN_MANUFACTURER, 242 .model = PKCS11_TOKEN_MODEL, 243 .serial_number = PKCS11_TOKEN_SERIAL_NUMBER, 244 .max_session_count = UINT32_MAX, 245 .max_rw_session_count = UINT32_MAX, 246 .max_pin_len = PKCS11_TOKEN_PIN_SIZE_MAX, 247 .min_pin_len = PKCS11_TOKEN_PIN_SIZE_MIN, 248 .total_public_memory = UINT32_MAX, 249 .free_public_memory = UINT32_MAX, 250 .total_private_memory = UINT32_MAX, 251 .free_private_memory = UINT32_MAX, 252 .hardware_version = PKCS11_TOKEN_HW_VERSION, 253 .firmware_version = PKCS11_TOKEN_FW_VERSION, 254 }; 255 256 if (ptypes != exp_pt || out->memref.size != sizeof(info)) 257 return PKCS11_CKR_ARGUMENTS_BAD; 258 259 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 260 261 rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); 262 if (rv) 263 return rv; 264 265 if (serialargs_remaining_bytes(&ctrlargs)) 266 return PKCS11_CKR_ARGUMENTS_BAD; 267 268 token = get_token(token_id); 269 if (!token) 270 return PKCS11_CKR_SLOT_ID_INVALID; 271 272 pad_str(info.manufacturer_id, sizeof(info.manufacturer_id)); 273 pad_str(info.model, sizeof(info.model)); 274 pad_str(info.serial_number, sizeof(info.serial_number)); 275 276 TEE_MemMove(info.label, token->db_main->label, sizeof(info.label)); 277 278 info.flags = token->db_main->flags; 279 info.session_count = token->session_count; 280 info.rw_session_count = token->rw_session_count; 281 282 TEE_MemMove(out->memref.buffer, &info, sizeof(info)); 283 284 return PKCS11_CKR_OK; 285 } 286 287 static void dmsg_print_supported_mechanism(unsigned int token_id __maybe_unused, 288 uint32_t *array __maybe_unused, 289 size_t count __maybe_unused) 290 { 291 size_t __maybe_unused n = 0; 292 293 if (TRACE_LEVEL < TRACE_DEBUG) 294 return; 295 296 for (n = 0; n < count; n++) 297 DMSG("PKCS11 token %"PRIu32": mechanism 0x%04"PRIx32": %s", 298 token_id, array[n], id2str_mechanism(array[n])); 299 } 300 301 uint32_t entry_ck_token_mecha_ids(uint32_t ptypes, TEE_Param *params) 302 { 303 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 304 TEE_PARAM_TYPE_NONE, 305 TEE_PARAM_TYPE_MEMREF_OUTPUT, 306 TEE_PARAM_TYPE_NONE); 307 TEE_Param *ctrl = ¶ms[0]; 308 TEE_Param *out = ¶ms[2]; 309 uint32_t rv = 0; 310 struct serialargs ctrlargs = { }; 311 uint32_t token_id = 0; 312 struct ck_token __maybe_unused *token = NULL; 313 size_t count = 0; 314 uint32_t *array = NULL; 315 316 if (ptypes != exp_pt) 317 return PKCS11_CKR_ARGUMENTS_BAD; 318 319 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 320 321 rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); 322 if (rv) 323 return rv; 324 325 if (serialargs_remaining_bytes(&ctrlargs)) 326 return PKCS11_CKR_ARGUMENTS_BAD; 327 328 token = get_token(token_id); 329 if (!token) 330 return PKCS11_CKR_SLOT_ID_INVALID; 331 332 count = out->memref.size / sizeof(*array); 333 array = tee_malloc_mechanism_list(&count); 334 335 if (out->memref.size < count * sizeof(*array)) { 336 assert(!array); 337 out->memref.size = count * sizeof(*array); 338 return PKCS11_CKR_BUFFER_TOO_SMALL; 339 } 340 341 if (!array) 342 return PKCS11_CKR_DEVICE_MEMORY; 343 344 dmsg_print_supported_mechanism(token_id, array, count); 345 346 out->memref.size = count * sizeof(*array); 347 TEE_MemMove(out->memref.buffer, array, out->memref.size); 348 349 TEE_Free(array); 350 351 return rv; 352 } 353 354 static void supported_mechanism_key_size(uint32_t proc_id, 355 uint32_t *max_key_size, 356 uint32_t *min_key_size) 357 { 358 switch (proc_id) { 359 /* Will be filled once TA supports mechanisms */ 360 default: 361 *min_key_size = 0; 362 *max_key_size = 0; 363 break; 364 } 365 } 366 367 uint32_t entry_ck_token_mecha_info(uint32_t ptypes, TEE_Param *params) 368 { 369 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 370 TEE_PARAM_TYPE_NONE, 371 TEE_PARAM_TYPE_MEMREF_OUTPUT, 372 TEE_PARAM_TYPE_NONE); 373 TEE_Param *ctrl = ¶ms[0]; 374 TEE_Param *out = ¶ms[2]; 375 uint32_t rv = 0; 376 struct serialargs ctrlargs = { }; 377 uint32_t token_id = 0; 378 uint32_t type = 0; 379 struct ck_token *token = NULL; 380 struct pkcs11_mechanism_info info = { }; 381 382 if (ptypes != exp_pt || out->memref.size != sizeof(info)) 383 return PKCS11_CKR_ARGUMENTS_BAD; 384 385 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 386 387 rv = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t)); 388 if (rv) 389 return rv; 390 391 rv = serialargs_get(&ctrlargs, &type, sizeof(uint32_t)); 392 if (rv) 393 return rv; 394 395 if (serialargs_remaining_bytes(&ctrlargs)) 396 return PKCS11_CKR_ARGUMENTS_BAD; 397 398 token = get_token(token_id); 399 if (!token) 400 return PKCS11_CKR_SLOT_ID_INVALID; 401 402 if (!mechanism_is_valid(type)) 403 return PKCS11_CKR_MECHANISM_INVALID; 404 405 info.flags = mechanism_supported_flags(type); 406 407 supported_mechanism_key_size(type, &info.min_key_size, 408 &info.max_key_size); 409 410 TEE_MemMove(out->memref.buffer, &info, sizeof(info)); 411 412 DMSG("PKCS11 token %"PRIu32": mechanism 0x%"PRIx32" info", 413 token_id, type); 414 415 return PKCS11_CKR_OK; 416 } 417