1c84ccd0aSEtienne Carriere // SPDX-License-Identifier: BSD-2-Clause 2c84ccd0aSEtienne Carriere /* 3c84ccd0aSEtienne Carriere * Copyright (c) 2017-2020, Linaro Limited 4c84ccd0aSEtienne Carriere */ 5c84ccd0aSEtienne Carriere 6c84ccd0aSEtienne Carriere #include <assert.h> 71a27b197SVesa Jääskeläinen #include <config.h> 8d38f9635SEtienne Carriere #include <confine_array_index.h> 9c84ccd0aSEtienne Carriere #include <pkcs11_ta.h> 10d628ebd9SEtienne Carriere #include <printk.h> 1122587dc4SVesa Jääskeläinen #include <pta_system.h> 12c84ccd0aSEtienne Carriere #include <string.h> 13c84ccd0aSEtienne Carriere #include <string_ext.h> 14c84ccd0aSEtienne Carriere #include <sys/queue.h> 15c84ccd0aSEtienne Carriere #include <tee_api_types.h> 16c84ccd0aSEtienne Carriere #include <tee_internal_api_extensions.h> 17c84ccd0aSEtienne Carriere #include <util.h> 18c84ccd0aSEtienne Carriere 19512cbf1dSJens Wiklander #include "attributes.h" 2049443fc0SEtienne Carriere #include "handle.h" 21c84ccd0aSEtienne Carriere #include "pkcs11_helpers.h" 22ee49d9f2SEtienne Carriere #include "pkcs11_token.h" 2355e6965cSEtienne Carriere #include "processing.h" 2422ac6984SEtienne Carriere #include "serializer.h" 2549443fc0SEtienne Carriere #include "token_capabilities.h" 26c84ccd0aSEtienne Carriere 27c84ccd0aSEtienne Carriere /* Provide 3 slots/tokens, ID is token index */ 28c84ccd0aSEtienne Carriere #ifndef CFG_PKCS11_TA_TOKEN_COUNT 29c84ccd0aSEtienne Carriere #define TOKEN_COUNT 3 30c84ccd0aSEtienne Carriere #else 31c84ccd0aSEtienne Carriere #define TOKEN_COUNT CFG_PKCS11_TA_TOKEN_COUNT 32c84ccd0aSEtienne Carriere #endif 33c84ccd0aSEtienne Carriere 3422587dc4SVesa Jääskeläinen /* RNG chunk size used to split RNG generation to smaller sizes */ 3522587dc4SVesa Jääskeläinen #define RNG_CHUNK_SIZE 512U 3622587dc4SVesa Jääskeläinen 37e084583eSEtienne Carriere /* 38e084583eSEtienne Carriere * Structure tracking client applications 39e084583eSEtienne Carriere * 40e084583eSEtienne Carriere * @link - chained list of registered client applications 41e084583eSEtienne Carriere * @sessions - list of the PKCS11 sessions opened by the client application 42e084583eSEtienne Carriere */ 43e084583eSEtienne Carriere struct pkcs11_client { 44e084583eSEtienne Carriere TAILQ_ENTRY(pkcs11_client) link; 45e084583eSEtienne Carriere struct session_list session_list; 46e084583eSEtienne Carriere struct handle_db session_handle_db; 47e084583eSEtienne Carriere }; 48e084583eSEtienne Carriere 49c84ccd0aSEtienne Carriere /* Static allocation of tokens runtime instances (reset to 0 at load) */ 50c84ccd0aSEtienne Carriere struct ck_token ck_token[TOKEN_COUNT]; 51c84ccd0aSEtienne Carriere 52e084583eSEtienne Carriere static struct client_list pkcs11_client_list = 53e084583eSEtienne Carriere TAILQ_HEAD_INITIALIZER(pkcs11_client_list); 54e084583eSEtienne Carriere 556e4f8f17SEtienne Carriere static void close_ck_session(struct pkcs11_session *session); 566e4f8f17SEtienne Carriere 57c84ccd0aSEtienne Carriere struct ck_token *get_token(unsigned int token_id) 58c84ccd0aSEtienne Carriere { 59d38f9635SEtienne Carriere if (token_id < TOKEN_COUNT) 60d38f9635SEtienne Carriere return &ck_token[confine_array_index(token_id, TOKEN_COUNT)]; 61c84ccd0aSEtienne Carriere 62d38f9635SEtienne Carriere return NULL; 63c84ccd0aSEtienne Carriere } 64c84ccd0aSEtienne Carriere 65c84ccd0aSEtienne Carriere unsigned int get_token_id(struct ck_token *token) 66c84ccd0aSEtienne Carriere { 67c84ccd0aSEtienne Carriere ptrdiff_t id = token - ck_token; 68c84ccd0aSEtienne Carriere 69c84ccd0aSEtienne Carriere assert(id >= 0 && id < TOKEN_COUNT); 70c84ccd0aSEtienne Carriere return id; 71c84ccd0aSEtienne Carriere } 72c84ccd0aSEtienne Carriere 73e084583eSEtienne Carriere struct pkcs11_client *tee_session2client(void *tee_session) 74e084583eSEtienne Carriere { 75e084583eSEtienne Carriere struct pkcs11_client *client = NULL; 76e084583eSEtienne Carriere 77e084583eSEtienne Carriere TAILQ_FOREACH(client, &pkcs11_client_list, link) 78e084583eSEtienne Carriere if (client == tee_session) 79e084583eSEtienne Carriere break; 80e084583eSEtienne Carriere 81e084583eSEtienne Carriere return client; 82e084583eSEtienne Carriere } 83e084583eSEtienne Carriere 846e4f8f17SEtienne Carriere struct pkcs11_session *pkcs11_handle2session(uint32_t handle, 856e4f8f17SEtienne Carriere struct pkcs11_client *client) 866e4f8f17SEtienne Carriere { 876e4f8f17SEtienne Carriere return handle_lookup(&client->session_handle_db, handle); 886e4f8f17SEtienne Carriere } 896e4f8f17SEtienne Carriere 90e084583eSEtienne Carriere struct pkcs11_client *register_client(void) 91e084583eSEtienne Carriere { 92e084583eSEtienne Carriere struct pkcs11_client *client = NULL; 93e084583eSEtienne Carriere 94e084583eSEtienne Carriere client = TEE_Malloc(sizeof(*client), TEE_MALLOC_FILL_ZERO); 95e084583eSEtienne Carriere if (!client) 96e084583eSEtienne Carriere return NULL; 97e084583eSEtienne Carriere 98e084583eSEtienne Carriere TAILQ_INSERT_HEAD(&pkcs11_client_list, client, link); 99e084583eSEtienne Carriere TAILQ_INIT(&client->session_list); 100e084583eSEtienne Carriere handle_db_init(&client->session_handle_db); 101e084583eSEtienne Carriere 102e084583eSEtienne Carriere return client; 103e084583eSEtienne Carriere } 104e084583eSEtienne Carriere 105e084583eSEtienne Carriere void unregister_client(struct pkcs11_client *client) 106e084583eSEtienne Carriere { 1076e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL; 1086e4f8f17SEtienne Carriere struct pkcs11_session *next = NULL; 1096e4f8f17SEtienne Carriere 110e084583eSEtienne Carriere if (!client) { 111e084583eSEtienne Carriere EMSG("Invalid TEE session handle"); 112e084583eSEtienne Carriere return; 113e084583eSEtienne Carriere } 114e084583eSEtienne Carriere 1156e4f8f17SEtienne Carriere TAILQ_FOREACH_SAFE(session, &client->session_list, link, next) 1166e4f8f17SEtienne Carriere close_ck_session(session); 1176e4f8f17SEtienne Carriere 118e084583eSEtienne Carriere TAILQ_REMOVE(&pkcs11_client_list, client, link); 119e084583eSEtienne Carriere handle_db_destroy(&client->session_handle_db); 120e084583eSEtienne Carriere TEE_Free(client); 121e084583eSEtienne Carriere } 122e084583eSEtienne Carriere 123c84ccd0aSEtienne Carriere static TEE_Result pkcs11_token_init(unsigned int id) 124c84ccd0aSEtienne Carriere { 125c84ccd0aSEtienne Carriere struct ck_token *token = init_persistent_db(id); 126c84ccd0aSEtienne Carriere 127c84ccd0aSEtienne Carriere if (!token) 128c84ccd0aSEtienne Carriere return TEE_ERROR_SECURITY; 129c84ccd0aSEtienne Carriere 130c84ccd0aSEtienne Carriere if (token->state == PKCS11_TOKEN_RESET) { 131c84ccd0aSEtienne Carriere /* As per PKCS#11 spec, token resets to read/write state */ 132c84ccd0aSEtienne Carriere token->state = PKCS11_TOKEN_READ_WRITE; 133c84ccd0aSEtienne Carriere token->session_count = 0; 134c84ccd0aSEtienne Carriere token->rw_session_count = 0; 135c84ccd0aSEtienne Carriere } 136c84ccd0aSEtienne Carriere 137c84ccd0aSEtienne Carriere return TEE_SUCCESS; 138c84ccd0aSEtienne Carriere } 139c84ccd0aSEtienne Carriere 140c84ccd0aSEtienne Carriere TEE_Result pkcs11_init(void) 141c84ccd0aSEtienne Carriere { 142c84ccd0aSEtienne Carriere unsigned int id = 0; 143c84ccd0aSEtienne Carriere TEE_Result ret = TEE_ERROR_GENERIC; 144c84ccd0aSEtienne Carriere 145c84ccd0aSEtienne Carriere for (id = 0; id < TOKEN_COUNT; id++) { 146c84ccd0aSEtienne Carriere ret = pkcs11_token_init(id); 147c84ccd0aSEtienne Carriere if (ret) 148e084583eSEtienne Carriere break; 149c84ccd0aSEtienne Carriere } 150c84ccd0aSEtienne Carriere 151c84ccd0aSEtienne Carriere return ret; 152c84ccd0aSEtienne Carriere } 153c84ccd0aSEtienne Carriere 154c84ccd0aSEtienne Carriere void pkcs11_deinit(void) 155c84ccd0aSEtienne Carriere { 156c84ccd0aSEtienne Carriere unsigned int id = 0; 157c84ccd0aSEtienne Carriere 158c84ccd0aSEtienne Carriere for (id = 0; id < TOKEN_COUNT; id++) 159c84ccd0aSEtienne Carriere close_persistent_db(get_token(id)); 160c84ccd0aSEtienne Carriere } 16122ac6984SEtienne Carriere 162512cbf1dSJens Wiklander /* 163512cbf1dSJens Wiklander * Currently no support for dual operations. 164512cbf1dSJens Wiklander */ 165512cbf1dSJens Wiklander enum pkcs11_rc set_processing_state(struct pkcs11_session *session, 166512cbf1dSJens Wiklander enum processing_func function, 167512cbf1dSJens Wiklander struct pkcs11_object *obj1, 168512cbf1dSJens Wiklander struct pkcs11_object *obj2) 169512cbf1dSJens Wiklander { 170512cbf1dSJens Wiklander enum pkcs11_proc_state state = PKCS11_SESSION_READY; 171512cbf1dSJens Wiklander struct active_processing *proc = NULL; 172512cbf1dSJens Wiklander 173512cbf1dSJens Wiklander if (session->processing) 174512cbf1dSJens Wiklander return PKCS11_CKR_OPERATION_ACTIVE; 175512cbf1dSJens Wiklander 176512cbf1dSJens Wiklander switch (function) { 177512cbf1dSJens Wiklander case PKCS11_FUNCTION_ENCRYPT: 178512cbf1dSJens Wiklander state = PKCS11_SESSION_ENCRYPTING; 179512cbf1dSJens Wiklander break; 180512cbf1dSJens Wiklander case PKCS11_FUNCTION_DECRYPT: 181512cbf1dSJens Wiklander state = PKCS11_SESSION_DECRYPTING; 182512cbf1dSJens Wiklander break; 183512cbf1dSJens Wiklander case PKCS11_FUNCTION_SIGN: 184512cbf1dSJens Wiklander state = PKCS11_SESSION_SIGNING; 185512cbf1dSJens Wiklander break; 186512cbf1dSJens Wiklander case PKCS11_FUNCTION_VERIFY: 187512cbf1dSJens Wiklander state = PKCS11_SESSION_VERIFYING; 188512cbf1dSJens Wiklander break; 189512cbf1dSJens Wiklander case PKCS11_FUNCTION_DIGEST: 190512cbf1dSJens Wiklander state = PKCS11_SESSION_DIGESTING; 191512cbf1dSJens Wiklander break; 192512cbf1dSJens Wiklander case PKCS11_FUNCTION_DERIVE: 193512cbf1dSJens Wiklander state = PKCS11_SESSION_READY; 194512cbf1dSJens Wiklander break; 195512cbf1dSJens Wiklander default: 196512cbf1dSJens Wiklander TEE_Panic(function); 197512cbf1dSJens Wiklander return -1; 198512cbf1dSJens Wiklander } 199512cbf1dSJens Wiklander 200512cbf1dSJens Wiklander proc = TEE_Malloc(sizeof(*proc), TEE_MALLOC_FILL_ZERO); 201512cbf1dSJens Wiklander if (!proc) 202512cbf1dSJens Wiklander return PKCS11_CKR_DEVICE_MEMORY; 203512cbf1dSJens Wiklander 204512cbf1dSJens Wiklander /* Boolean are default to false and pointers to NULL */ 205512cbf1dSJens Wiklander proc->state = state; 206512cbf1dSJens Wiklander proc->tee_op_handle = TEE_HANDLE_NULL; 207512cbf1dSJens Wiklander 208512cbf1dSJens Wiklander if (obj1 && get_bool(obj1->attributes, PKCS11_CKA_ALWAYS_AUTHENTICATE)) 209512cbf1dSJens Wiklander proc->always_authen = true; 210512cbf1dSJens Wiklander 211512cbf1dSJens Wiklander if (obj2 && get_bool(obj2->attributes, PKCS11_CKA_ALWAYS_AUTHENTICATE)) 212512cbf1dSJens Wiklander proc->always_authen = true; 213512cbf1dSJens Wiklander 214512cbf1dSJens Wiklander session->processing = proc; 215512cbf1dSJens Wiklander 216512cbf1dSJens Wiklander return PKCS11_CKR_OK; 217512cbf1dSJens Wiklander } 218512cbf1dSJens Wiklander 2194daf39b3SJens Wiklander enum pkcs11_rc entry_ck_slot_list(uint32_t ptypes, TEE_Param *params) 22022ac6984SEtienne Carriere { 22122ac6984SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 22222ac6984SEtienne Carriere TEE_PARAM_TYPE_NONE, 22322ac6984SEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 22422ac6984SEtienne Carriere TEE_PARAM_TYPE_NONE); 22539b43b78SJens Wiklander TEE_Param *out = params + 2; 22622ac6984SEtienne Carriere uint32_t token_id = 0; 22722ac6984SEtienne Carriere const size_t out_size = sizeof(token_id) * TOKEN_COUNT; 22822ac6984SEtienne Carriere uint8_t *id = NULL; 22922ac6984SEtienne Carriere 23022ac6984SEtienne Carriere if (ptypes != exp_pt || 23122ac6984SEtienne Carriere params[0].memref.size != TEE_PARAM0_SIZE_MIN) 23222ac6984SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 23322ac6984SEtienne Carriere 23422ac6984SEtienne Carriere if (out->memref.size < out_size) { 23522ac6984SEtienne Carriere out->memref.size = out_size; 23622ac6984SEtienne Carriere 23722ac6984SEtienne Carriere if (out->memref.buffer) 23822ac6984SEtienne Carriere return PKCS11_CKR_BUFFER_TOO_SMALL; 23922ac6984SEtienne Carriere else 24022ac6984SEtienne Carriere return PKCS11_CKR_OK; 24122ac6984SEtienne Carriere } 24222ac6984SEtienne Carriere 24322ac6984SEtienne Carriere for (token_id = 0, id = out->memref.buffer; token_id < TOKEN_COUNT; 24422ac6984SEtienne Carriere token_id++, id += sizeof(token_id)) 24522ac6984SEtienne Carriere TEE_MemMove(id, &token_id, sizeof(token_id)); 24622ac6984SEtienne Carriere 24722ac6984SEtienne Carriere out->memref.size = out_size; 24822ac6984SEtienne Carriere 24922ac6984SEtienne Carriere return PKCS11_CKR_OK; 25022ac6984SEtienne Carriere } 251ce94efefSEtienne Carriere 252b3ac5035SEtienne Carriere static void pad_str(uint8_t *str, size_t size) 253b3ac5035SEtienne Carriere { 254b3ac5035SEtienne Carriere int n = strnlen((char *)str, size); 255b3ac5035SEtienne Carriere 256b3ac5035SEtienne Carriere TEE_MemFill(str + n, ' ', size - n); 257b3ac5035SEtienne Carriere } 258b3ac5035SEtienne Carriere 259d628ebd9SEtienne Carriere static void set_token_description(struct pkcs11_slot_info *info) 260d628ebd9SEtienne Carriere { 261d628ebd9SEtienne Carriere char desc[sizeof(info->slot_description) + 1] = { 0 }; 262d628ebd9SEtienne Carriere TEE_UUID dev_id = { }; 263d628ebd9SEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC; 264d628ebd9SEtienne Carriere int n = 0; 265d628ebd9SEtienne Carriere 266d628ebd9SEtienne Carriere res = TEE_GetPropertyAsUUID(TEE_PROPSET_TEE_IMPLEMENTATION, 267d628ebd9SEtienne Carriere "gpd.tee.deviceID", &dev_id); 268d628ebd9SEtienne Carriere if (res == TEE_SUCCESS) { 269d628ebd9SEtienne Carriere n = snprintk(desc, sizeof(desc), PKCS11_SLOT_DESCRIPTION 270d628ebd9SEtienne Carriere " - TEE UUID %pUl", (void *)&dev_id); 271d628ebd9SEtienne Carriere } else { 272d628ebd9SEtienne Carriere n = snprintf(desc, sizeof(desc), PKCS11_SLOT_DESCRIPTION 273d628ebd9SEtienne Carriere " - No TEE UUID"); 274d628ebd9SEtienne Carriere } 275d628ebd9SEtienne Carriere if (n < 0 || n >= (int)sizeof(desc)) 276d628ebd9SEtienne Carriere TEE_Panic(0); 277d628ebd9SEtienne Carriere 278d628ebd9SEtienne Carriere TEE_MemMove(info->slot_description, desc, n); 279d628ebd9SEtienne Carriere pad_str(info->slot_description, sizeof(info->slot_description)); 280d628ebd9SEtienne Carriere } 281d628ebd9SEtienne Carriere 2824daf39b3SJens Wiklander enum pkcs11_rc entry_ck_slot_info(uint32_t ptypes, TEE_Param *params) 283ce94efefSEtienne Carriere { 284ce94efefSEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 285ce94efefSEtienne Carriere TEE_PARAM_TYPE_NONE, 286ce94efefSEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 287ce94efefSEtienne Carriere TEE_PARAM_TYPE_NONE); 28839b43b78SJens Wiklander TEE_Param *ctrl = params; 28939b43b78SJens Wiklander TEE_Param *out = params + 2; 2904daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 291ce94efefSEtienne Carriere struct serialargs ctrlargs = { }; 292ce94efefSEtienne Carriere uint32_t token_id = 0; 293ce94efefSEtienne Carriere struct pkcs11_slot_info info = { 294ce94efefSEtienne Carriere .slot_description = PKCS11_SLOT_DESCRIPTION, 295ce94efefSEtienne Carriere .manufacturer_id = PKCS11_SLOT_MANUFACTURER, 296ce94efefSEtienne Carriere .flags = PKCS11_CKFS_TOKEN_PRESENT, 297ce94efefSEtienne Carriere .hardware_version = PKCS11_SLOT_HW_VERSION, 298ce94efefSEtienne Carriere .firmware_version = PKCS11_SLOT_FW_VERSION, 299ce94efefSEtienne Carriere }; 300ce94efefSEtienne Carriere 301ce94efefSEtienne Carriere COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_DESCRIPTION) <= 302ce94efefSEtienne Carriere sizeof(info.slot_description)); 303ce94efefSEtienne Carriere COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_MANUFACTURER) <= 304ce94efefSEtienne Carriere sizeof(info.manufacturer_id)); 305ce94efefSEtienne Carriere 306ce94efefSEtienne Carriere if (ptypes != exp_pt || out->memref.size != sizeof(info)) 307ce94efefSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 308ce94efefSEtienne Carriere 309ce94efefSEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 310ce94efefSEtienne Carriere 3114daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); 3124daf39b3SJens Wiklander if (rc) 3134daf39b3SJens Wiklander return rc; 314ce94efefSEtienne Carriere 315ce94efefSEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 316ce94efefSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 317ce94efefSEtienne Carriere 31829b0949aSEtienne Carriere if (!get_token(token_id)) 319ce94efefSEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID; 320ce94efefSEtienne Carriere 321d628ebd9SEtienne Carriere set_token_description(&info); 322d628ebd9SEtienne Carriere 323b3ac5035SEtienne Carriere pad_str(info.manufacturer_id, sizeof(info.manufacturer_id)); 324ce94efefSEtienne Carriere 325ce94efefSEtienne Carriere out->memref.size = sizeof(info); 326ce94efefSEtienne Carriere TEE_MemMove(out->memref.buffer, &info, out->memref.size); 327ce94efefSEtienne Carriere 328ce94efefSEtienne Carriere return PKCS11_CKR_OK; 329ce94efefSEtienne Carriere } 330030e7392SEtienne Carriere 3314daf39b3SJens Wiklander enum pkcs11_rc entry_ck_token_info(uint32_t ptypes, TEE_Param *params) 332030e7392SEtienne Carriere { 333030e7392SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 334030e7392SEtienne Carriere TEE_PARAM_TYPE_NONE, 335030e7392SEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 336030e7392SEtienne Carriere TEE_PARAM_TYPE_NONE); 33739b43b78SJens Wiklander TEE_Param *ctrl = params; 33839b43b78SJens Wiklander TEE_Param *out = params + 2; 3394daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 340030e7392SEtienne Carriere struct serialargs ctrlargs = { }; 341030e7392SEtienne Carriere uint32_t token_id = 0; 342030e7392SEtienne Carriere struct ck_token *token = NULL; 343030e7392SEtienne Carriere struct pkcs11_token_info info = { 344030e7392SEtienne Carriere .manufacturer_id = PKCS11_TOKEN_MANUFACTURER, 345030e7392SEtienne Carriere .model = PKCS11_TOKEN_MODEL, 346030e7392SEtienne Carriere .max_session_count = UINT32_MAX, 347030e7392SEtienne Carriere .max_rw_session_count = UINT32_MAX, 348030e7392SEtienne Carriere .max_pin_len = PKCS11_TOKEN_PIN_SIZE_MAX, 349030e7392SEtienne Carriere .min_pin_len = PKCS11_TOKEN_PIN_SIZE_MIN, 350030e7392SEtienne Carriere .total_public_memory = UINT32_MAX, 351030e7392SEtienne Carriere .free_public_memory = UINT32_MAX, 352030e7392SEtienne Carriere .total_private_memory = UINT32_MAX, 353030e7392SEtienne Carriere .free_private_memory = UINT32_MAX, 354030e7392SEtienne Carriere .hardware_version = PKCS11_TOKEN_HW_VERSION, 355030e7392SEtienne Carriere .firmware_version = PKCS11_TOKEN_FW_VERSION, 356030e7392SEtienne Carriere }; 35702b4d42aSEtienne Carriere char sn[sizeof(info.serial_number) + 1] = { 0 }; 35802b4d42aSEtienne Carriere int n = 0; 359030e7392SEtienne Carriere 360030e7392SEtienne Carriere if (ptypes != exp_pt || out->memref.size != sizeof(info)) 361030e7392SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 362030e7392SEtienne Carriere 363030e7392SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 364030e7392SEtienne Carriere 3654daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); 3664daf39b3SJens Wiklander if (rc) 3674daf39b3SJens Wiklander return rc; 368030e7392SEtienne Carriere 369030e7392SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 370030e7392SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 371030e7392SEtienne Carriere 372030e7392SEtienne Carriere token = get_token(token_id); 373030e7392SEtienne Carriere if (!token) 374030e7392SEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID; 375030e7392SEtienne Carriere 376030e7392SEtienne Carriere pad_str(info.manufacturer_id, sizeof(info.manufacturer_id)); 377030e7392SEtienne Carriere pad_str(info.model, sizeof(info.model)); 37802b4d42aSEtienne Carriere 37902b4d42aSEtienne Carriere n = snprintf(sn, sizeof(sn), "%0*"PRIu32, 38002b4d42aSEtienne Carriere (int)sizeof(info.serial_number), token_id); 38102b4d42aSEtienne Carriere if (n != (int)sizeof(info.serial_number)) 38202b4d42aSEtienne Carriere TEE_Panic(0); 38302b4d42aSEtienne Carriere 38402b4d42aSEtienne Carriere TEE_MemMove(info.serial_number, sn, sizeof(info.serial_number)); 385030e7392SEtienne Carriere pad_str(info.serial_number, sizeof(info.serial_number)); 386030e7392SEtienne Carriere 387030e7392SEtienne Carriere TEE_MemMove(info.label, token->db_main->label, sizeof(info.label)); 388030e7392SEtienne Carriere 389030e7392SEtienne Carriere info.flags = token->db_main->flags; 390030e7392SEtienne Carriere info.session_count = token->session_count; 391030e7392SEtienne Carriere info.rw_session_count = token->rw_session_count; 392030e7392SEtienne Carriere 393030e7392SEtienne Carriere TEE_MemMove(out->memref.buffer, &info, sizeof(info)); 394030e7392SEtienne Carriere 395030e7392SEtienne Carriere return PKCS11_CKR_OK; 396030e7392SEtienne Carriere } 3976f74919dSEtienne Carriere 3986f74919dSEtienne Carriere static void dmsg_print_supported_mechanism(unsigned int token_id __maybe_unused, 3996f74919dSEtienne Carriere uint32_t *array __maybe_unused, 4006f74919dSEtienne Carriere size_t count __maybe_unused) 4016f74919dSEtienne Carriere { 4026f74919dSEtienne Carriere size_t __maybe_unused n = 0; 4036f74919dSEtienne Carriere 4046f74919dSEtienne Carriere if (TRACE_LEVEL < TRACE_DEBUG) 4056f74919dSEtienne Carriere return; 4066f74919dSEtienne Carriere 4076f74919dSEtienne Carriere for (n = 0; n < count; n++) 4086f74919dSEtienne Carriere DMSG("PKCS11 token %"PRIu32": mechanism 0x%04"PRIx32": %s", 4096f74919dSEtienne Carriere token_id, array[n], id2str_mechanism(array[n])); 4106f74919dSEtienne Carriere } 4116f74919dSEtienne Carriere 4124daf39b3SJens Wiklander enum pkcs11_rc entry_ck_token_mecha_ids(uint32_t ptypes, TEE_Param *params) 4136f74919dSEtienne Carriere { 4146f74919dSEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 4156f74919dSEtienne Carriere TEE_PARAM_TYPE_NONE, 4166f74919dSEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 4176f74919dSEtienne Carriere TEE_PARAM_TYPE_NONE); 41839b43b78SJens Wiklander TEE_Param *ctrl = params; 41939b43b78SJens Wiklander TEE_Param *out = params + 2; 4204daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 4216f74919dSEtienne Carriere struct serialargs ctrlargs = { }; 4226f74919dSEtienne Carriere uint32_t token_id = 0; 4236f74919dSEtienne Carriere struct ck_token __maybe_unused *token = NULL; 4246f74919dSEtienne Carriere size_t count = 0; 4256f74919dSEtienne Carriere uint32_t *array = NULL; 4266f74919dSEtienne Carriere 4276f74919dSEtienne Carriere if (ptypes != exp_pt) 4286f74919dSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 4296f74919dSEtienne Carriere 4306f74919dSEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 4316f74919dSEtienne Carriere 4324daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); 4334daf39b3SJens Wiklander if (rc) 4344daf39b3SJens Wiklander return rc; 4356f74919dSEtienne Carriere 4366f74919dSEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 4376f74919dSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 4386f74919dSEtienne Carriere 4396f74919dSEtienne Carriere token = get_token(token_id); 4406f74919dSEtienne Carriere if (!token) 4416f74919dSEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID; 4426f74919dSEtienne Carriere 4436f74919dSEtienne Carriere count = out->memref.size / sizeof(*array); 4446f74919dSEtienne Carriere array = tee_malloc_mechanism_list(&count); 4456f74919dSEtienne Carriere 4466f74919dSEtienne Carriere if (out->memref.size < count * sizeof(*array)) { 4476f74919dSEtienne Carriere assert(!array); 4486f74919dSEtienne Carriere out->memref.size = count * sizeof(*array); 4496459f267SEtienne Carriere if (out->memref.buffer) 4506f74919dSEtienne Carriere return PKCS11_CKR_BUFFER_TOO_SMALL; 4516459f267SEtienne Carriere else 4526459f267SEtienne Carriere return PKCS11_CKR_OK; 4536f74919dSEtienne Carriere } 4546f74919dSEtienne Carriere 4556f74919dSEtienne Carriere if (!array) 4566f74919dSEtienne Carriere return PKCS11_CKR_DEVICE_MEMORY; 4576f74919dSEtienne Carriere 4586f74919dSEtienne Carriere dmsg_print_supported_mechanism(token_id, array, count); 4596f74919dSEtienne Carriere 4606f74919dSEtienne Carriere out->memref.size = count * sizeof(*array); 4616f74919dSEtienne Carriere TEE_MemMove(out->memref.buffer, array, out->memref.size); 4626f74919dSEtienne Carriere 4636f74919dSEtienne Carriere TEE_Free(array); 4646f74919dSEtienne Carriere 4654daf39b3SJens Wiklander return rc; 4666f74919dSEtienne Carriere } 4671d3ebedbSEtienne Carriere 4684daf39b3SJens Wiklander enum pkcs11_rc entry_ck_token_mecha_info(uint32_t ptypes, TEE_Param *params) 4691d3ebedbSEtienne Carriere { 4701d3ebedbSEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 4711d3ebedbSEtienne Carriere TEE_PARAM_TYPE_NONE, 4721d3ebedbSEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 4731d3ebedbSEtienne Carriere TEE_PARAM_TYPE_NONE); 47439b43b78SJens Wiklander TEE_Param *ctrl = params; 47539b43b78SJens Wiklander TEE_Param *out = params + 2; 4764daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 4771d3ebedbSEtienne Carriere struct serialargs ctrlargs = { }; 4781d3ebedbSEtienne Carriere uint32_t token_id = 0; 4791d3ebedbSEtienne Carriere uint32_t type = 0; 4801d3ebedbSEtienne Carriere struct ck_token *token = NULL; 4811d3ebedbSEtienne Carriere struct pkcs11_mechanism_info info = { }; 4821d3ebedbSEtienne Carriere 4831d3ebedbSEtienne Carriere if (ptypes != exp_pt || out->memref.size != sizeof(info)) 4841d3ebedbSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 4851d3ebedbSEtienne Carriere 4861d3ebedbSEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 4871d3ebedbSEtienne Carriere 4884daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t)); 4894daf39b3SJens Wiklander if (rc) 4904daf39b3SJens Wiklander return rc; 4911d3ebedbSEtienne Carriere 4924daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &type, sizeof(uint32_t)); 4934daf39b3SJens Wiklander if (rc) 4944daf39b3SJens Wiklander return rc; 4951d3ebedbSEtienne Carriere 4961d3ebedbSEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 4971d3ebedbSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 4981d3ebedbSEtienne Carriere 4991d3ebedbSEtienne Carriere token = get_token(token_id); 5001d3ebedbSEtienne Carriere if (!token) 5011d3ebedbSEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID; 5021d3ebedbSEtienne Carriere 5031d3ebedbSEtienne Carriere if (!mechanism_is_valid(type)) 5041d3ebedbSEtienne Carriere return PKCS11_CKR_MECHANISM_INVALID; 5051d3ebedbSEtienne Carriere 5061d3ebedbSEtienne Carriere info.flags = mechanism_supported_flags(type); 5071d3ebedbSEtienne Carriere 508*2d0cd829SRuchika Gupta pkcs11_mechanism_supported_key_sizes(type, &info.min_key_size, 5091d3ebedbSEtienne Carriere &info.max_key_size); 5101d3ebedbSEtienne Carriere 5111d3ebedbSEtienne Carriere TEE_MemMove(out->memref.buffer, &info, sizeof(info)); 5121d3ebedbSEtienne Carriere 5131d3ebedbSEtienne Carriere DMSG("PKCS11 token %"PRIu32": mechanism 0x%"PRIx32" info", 5141d3ebedbSEtienne Carriere token_id, type); 5151d3ebedbSEtienne Carriere 5161d3ebedbSEtienne Carriere return PKCS11_CKR_OK; 5171d3ebedbSEtienne Carriere } 5186e4f8f17SEtienne Carriere 5196e4f8f17SEtienne Carriere /* Select the ReadOnly or ReadWrite state for session login state */ 5206e4f8f17SEtienne Carriere static void set_session_state(struct pkcs11_client *client, 5216e4f8f17SEtienne Carriere struct pkcs11_session *session, bool readonly) 5226e4f8f17SEtienne Carriere { 5236e4f8f17SEtienne Carriere struct pkcs11_session *sess = NULL; 5246e4f8f17SEtienne Carriere enum pkcs11_session_state state = PKCS11_CKS_RO_PUBLIC_SESSION; 5256e4f8f17SEtienne Carriere 5266e4f8f17SEtienne Carriere /* Default to public session if no session already registered */ 5276e4f8f17SEtienne Carriere if (readonly) 5286e4f8f17SEtienne Carriere state = PKCS11_CKS_RO_PUBLIC_SESSION; 5296e4f8f17SEtienne Carriere else 5306e4f8f17SEtienne Carriere state = PKCS11_CKS_RW_PUBLIC_SESSION; 5316e4f8f17SEtienne Carriere 5326e4f8f17SEtienne Carriere /* 5336e4f8f17SEtienne Carriere * No need to check all client sessions, the first found in 5346e4f8f17SEtienne Carriere * target token gives client login configuration. 5356e4f8f17SEtienne Carriere */ 5366e4f8f17SEtienne Carriere TAILQ_FOREACH(sess, &client->session_list, link) { 5376e4f8f17SEtienne Carriere assert(sess != session); 5386e4f8f17SEtienne Carriere 5396e4f8f17SEtienne Carriere if (sess->token == session->token) { 5406e4f8f17SEtienne Carriere switch (sess->state) { 5416e4f8f17SEtienne Carriere case PKCS11_CKS_RW_PUBLIC_SESSION: 5426e4f8f17SEtienne Carriere case PKCS11_CKS_RO_PUBLIC_SESSION: 5436e4f8f17SEtienne Carriere if (readonly) 5446e4f8f17SEtienne Carriere state = PKCS11_CKS_RO_PUBLIC_SESSION; 5456e4f8f17SEtienne Carriere else 5466e4f8f17SEtienne Carriere state = PKCS11_CKS_RW_PUBLIC_SESSION; 5476e4f8f17SEtienne Carriere break; 5486e4f8f17SEtienne Carriere case PKCS11_CKS_RO_USER_FUNCTIONS: 5496e4f8f17SEtienne Carriere case PKCS11_CKS_RW_USER_FUNCTIONS: 5506e4f8f17SEtienne Carriere if (readonly) 5516e4f8f17SEtienne Carriere state = PKCS11_CKS_RO_USER_FUNCTIONS; 5526e4f8f17SEtienne Carriere else 5536e4f8f17SEtienne Carriere state = PKCS11_CKS_RW_USER_FUNCTIONS; 5546e4f8f17SEtienne Carriere break; 5556e4f8f17SEtienne Carriere case PKCS11_CKS_RW_SO_FUNCTIONS: 5566e4f8f17SEtienne Carriere if (readonly) 5576e4f8f17SEtienne Carriere TEE_Panic(0); 5586e4f8f17SEtienne Carriere else 5596e4f8f17SEtienne Carriere state = PKCS11_CKS_RW_SO_FUNCTIONS; 5606e4f8f17SEtienne Carriere break; 5616e4f8f17SEtienne Carriere default: 5626e4f8f17SEtienne Carriere TEE_Panic(0); 5636e4f8f17SEtienne Carriere } 5646e4f8f17SEtienne Carriere break; 5656e4f8f17SEtienne Carriere } 5666e4f8f17SEtienne Carriere } 5676e4f8f17SEtienne Carriere 5686e4f8f17SEtienne Carriere session->state = state; 5696e4f8f17SEtienne Carriere } 5706e4f8f17SEtienne Carriere 5714daf39b3SJens Wiklander enum pkcs11_rc entry_ck_open_session(struct pkcs11_client *client, 5726e4f8f17SEtienne Carriere uint32_t ptypes, TEE_Param *params) 5736e4f8f17SEtienne Carriere { 5746e4f8f17SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 5756e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE, 5766e4f8f17SEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 5776e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE); 57839b43b78SJens Wiklander TEE_Param *ctrl = params; 57939b43b78SJens Wiklander TEE_Param *out = params + 2; 5804daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 5816e4f8f17SEtienne Carriere struct serialargs ctrlargs = { }; 5826e4f8f17SEtienne Carriere uint32_t token_id = 0; 5836e4f8f17SEtienne Carriere uint32_t flags = 0; 5846e4f8f17SEtienne Carriere struct ck_token *token = NULL; 5856e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL; 5866e4f8f17SEtienne Carriere bool readonly = false; 5876e4f8f17SEtienne Carriere 5886e4f8f17SEtienne Carriere if (!client || ptypes != exp_pt || 5896e4f8f17SEtienne Carriere out->memref.size != sizeof(session->handle)) 5906e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 5916e4f8f17SEtienne Carriere 5926e4f8f17SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 5936e4f8f17SEtienne Carriere 5944daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); 5954daf39b3SJens Wiklander if (rc) 5964daf39b3SJens Wiklander return rc; 5976e4f8f17SEtienne Carriere 5984daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &flags, sizeof(flags)); 5994daf39b3SJens Wiklander if (rc) 6004daf39b3SJens Wiklander return rc; 6016e4f8f17SEtienne Carriere 6026e4f8f17SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 6036e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 6046e4f8f17SEtienne Carriere 6056e4f8f17SEtienne Carriere token = get_token(token_id); 6066e4f8f17SEtienne Carriere if (!token) 6076e4f8f17SEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID; 6086e4f8f17SEtienne Carriere 6096e4f8f17SEtienne Carriere /* Sanitize session flags */ 61008774c86SVesa Jääskeläinen if (!(flags & PKCS11_CKFSS_SERIAL_SESSION)) 61108774c86SVesa Jääskeläinen return PKCS11_CKR_SESSION_PARALLEL_NOT_SUPPORTED; 61208774c86SVesa Jääskeläinen 61308774c86SVesa Jääskeläinen if (flags & ~(PKCS11_CKFSS_RW_SESSION | PKCS11_CKFSS_SERIAL_SESSION)) 6146e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 6156e4f8f17SEtienne Carriere 6166e4f8f17SEtienne Carriere readonly = !(flags & PKCS11_CKFSS_RW_SESSION); 6176e4f8f17SEtienne Carriere 6186e4f8f17SEtienne Carriere if (!readonly && token->state == PKCS11_TOKEN_READ_ONLY) 6196e4f8f17SEtienne Carriere return PKCS11_CKR_TOKEN_WRITE_PROTECTED; 6206e4f8f17SEtienne Carriere 6216e4f8f17SEtienne Carriere if (readonly) { 6226e4f8f17SEtienne Carriere /* Specifically reject read-only session under SO login */ 6236e4f8f17SEtienne Carriere TAILQ_FOREACH(session, &client->session_list, link) 6246e4f8f17SEtienne Carriere if (pkcs11_session_is_so(session)) 6256e4f8f17SEtienne Carriere return PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS; 6266e4f8f17SEtienne Carriere } 6276e4f8f17SEtienne Carriere 6286e4f8f17SEtienne Carriere session = TEE_Malloc(sizeof(*session), TEE_MALLOC_FILL_ZERO); 6296e4f8f17SEtienne Carriere if (!session) 6306e4f8f17SEtienne Carriere return PKCS11_CKR_DEVICE_MEMORY; 6316e4f8f17SEtienne Carriere 6326e4f8f17SEtienne Carriere session->handle = handle_get(&client->session_handle_db, session); 6336e4f8f17SEtienne Carriere if (!session->handle) { 6346e4f8f17SEtienne Carriere TEE_Free(session); 6356e4f8f17SEtienne Carriere return PKCS11_CKR_DEVICE_MEMORY; 6366e4f8f17SEtienne Carriere } 6376e4f8f17SEtienne Carriere 6386e4f8f17SEtienne Carriere session->token = token; 6396e4f8f17SEtienne Carriere session->client = client; 6406e4f8f17SEtienne Carriere 641b56b3d07SJens Wiklander LIST_INIT(&session->object_list); 642b56b3d07SJens Wiklander handle_db_init(&session->object_handle_db); 643b56b3d07SJens Wiklander 6446e4f8f17SEtienne Carriere set_session_state(client, session, readonly); 6456e4f8f17SEtienne Carriere 6466e4f8f17SEtienne Carriere TAILQ_INSERT_HEAD(&client->session_list, session, link); 6476e4f8f17SEtienne Carriere 6486e4f8f17SEtienne Carriere session->token->session_count++; 6496e4f8f17SEtienne Carriere if (!readonly) 6506e4f8f17SEtienne Carriere session->token->rw_session_count++; 6516e4f8f17SEtienne Carriere 6526e4f8f17SEtienne Carriere TEE_MemMove(out->memref.buffer, &session->handle, 6536e4f8f17SEtienne Carriere sizeof(session->handle)); 6546e4f8f17SEtienne Carriere 6556e4f8f17SEtienne Carriere DMSG("Open PKCS11 session %"PRIu32, session->handle); 6566e4f8f17SEtienne Carriere 6576e4f8f17SEtienne Carriere return PKCS11_CKR_OK; 6586e4f8f17SEtienne Carriere } 6596e4f8f17SEtienne Carriere 6606e4f8f17SEtienne Carriere static void close_ck_session(struct pkcs11_session *session) 6616e4f8f17SEtienne Carriere { 66255e6965cSEtienne Carriere release_active_processing(session); 66355e6965cSEtienne Carriere 664b56b3d07SJens Wiklander /* No need to put object handles, the whole database is destroyed */ 665b56b3d07SJens Wiklander while (!LIST_EMPTY(&session->object_list)) 666b56b3d07SJens Wiklander destroy_object(session, 667b56b3d07SJens Wiklander LIST_FIRST(&session->object_list), true); 668b56b3d07SJens Wiklander 669dc99b202SRuchika Gupta release_session_find_obj_context(session); 670dc99b202SRuchika Gupta 6716e4f8f17SEtienne Carriere TAILQ_REMOVE(&session->client->session_list, session, link); 6726e4f8f17SEtienne Carriere handle_put(&session->client->session_handle_db, session->handle); 673b56b3d07SJens Wiklander handle_db_destroy(&session->object_handle_db); 6746e4f8f17SEtienne Carriere 6756e4f8f17SEtienne Carriere session->token->session_count--; 6766e4f8f17SEtienne Carriere if (pkcs11_session_is_read_write(session)) 6776e4f8f17SEtienne Carriere session->token->rw_session_count--; 6786e4f8f17SEtienne Carriere 6796e4f8f17SEtienne Carriere TEE_Free(session); 6806e4f8f17SEtienne Carriere 6816e4f8f17SEtienne Carriere DMSG("Close PKCS11 session %"PRIu32, session->handle); 6826e4f8f17SEtienne Carriere } 6836e4f8f17SEtienne Carriere 6844daf39b3SJens Wiklander enum pkcs11_rc entry_ck_close_session(struct pkcs11_client *client, 6856e4f8f17SEtienne Carriere uint32_t ptypes, TEE_Param *params) 6866e4f8f17SEtienne Carriere { 6876e4f8f17SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 6886e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE, 6896e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE, 6906e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE); 69139b43b78SJens Wiklander TEE_Param *ctrl = params; 6924daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 6936e4f8f17SEtienne Carriere struct serialargs ctrlargs = { }; 6946e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL; 6956e4f8f17SEtienne Carriere 6966e4f8f17SEtienne Carriere if (!client || ptypes != exp_pt) 6976e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 6986e4f8f17SEtienne Carriere 6996e4f8f17SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 7006e4f8f17SEtienne Carriere 7014daf39b3SJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 7024daf39b3SJens Wiklander if (rc) 7034daf39b3SJens Wiklander return rc; 7046e4f8f17SEtienne Carriere 7056e4f8f17SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 7066e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 7076e4f8f17SEtienne Carriere 7086e4f8f17SEtienne Carriere close_ck_session(session); 7096e4f8f17SEtienne Carriere 7106e4f8f17SEtienne Carriere return PKCS11_CKR_OK; 7116e4f8f17SEtienne Carriere } 7126e4f8f17SEtienne Carriere 7134daf39b3SJens Wiklander enum pkcs11_rc entry_ck_close_all_sessions(struct pkcs11_client *client, 7146e4f8f17SEtienne Carriere uint32_t ptypes, TEE_Param *params) 7156e4f8f17SEtienne Carriere { 7166e4f8f17SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 7176e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE, 7186e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE, 7196e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE); 72039b43b78SJens Wiklander TEE_Param *ctrl = params; 7214daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 7226e4f8f17SEtienne Carriere struct serialargs ctrlargs = { }; 7236e4f8f17SEtienne Carriere uint32_t token_id = 0; 7246e4f8f17SEtienne Carriere struct ck_token *token = NULL; 7256e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL; 7266e4f8f17SEtienne Carriere struct pkcs11_session *next = NULL; 7276e4f8f17SEtienne Carriere 7286e4f8f17SEtienne Carriere if (!client || ptypes != exp_pt) 7296e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 7306e4f8f17SEtienne Carriere 7316e4f8f17SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 7326e4f8f17SEtienne Carriere 7334daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t)); 7344daf39b3SJens Wiklander if (rc) 7354daf39b3SJens Wiklander return rc; 7366e4f8f17SEtienne Carriere 7376e4f8f17SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 7386e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 7396e4f8f17SEtienne Carriere 7406e4f8f17SEtienne Carriere token = get_token(token_id); 7416e4f8f17SEtienne Carriere if (!token) 7426e4f8f17SEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID; 7436e4f8f17SEtienne Carriere 7446e4f8f17SEtienne Carriere DMSG("Close all sessions for PKCS11 token %"PRIu32, token_id); 7456e4f8f17SEtienne Carriere 7466e4f8f17SEtienne Carriere TAILQ_FOREACH_SAFE(session, &client->session_list, link, next) 7476e4f8f17SEtienne Carriere if (session->token == token) 7486e4f8f17SEtienne Carriere close_ck_session(session); 7496e4f8f17SEtienne Carriere 7506e4f8f17SEtienne Carriere return PKCS11_CKR_OK; 7516e4f8f17SEtienne Carriere } 7526e4f8f17SEtienne Carriere 7534daf39b3SJens Wiklander enum pkcs11_rc entry_ck_session_info(struct pkcs11_client *client, 7546e4f8f17SEtienne Carriere uint32_t ptypes, TEE_Param *params) 7556e4f8f17SEtienne Carriere { 7566e4f8f17SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 7576e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE, 7586e4f8f17SEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 7596e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE); 76039b43b78SJens Wiklander TEE_Param *ctrl = params; 76139b43b78SJens Wiklander TEE_Param *out = params + 2; 7624daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 7636e4f8f17SEtienne Carriere struct serialargs ctrlargs = { }; 7646e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL; 7656e4f8f17SEtienne Carriere struct pkcs11_session_info info = { 7666e4f8f17SEtienne Carriere .flags = PKCS11_CKFSS_SERIAL_SESSION, 7676e4f8f17SEtienne Carriere }; 7686e4f8f17SEtienne Carriere 7696e4f8f17SEtienne Carriere if (!client || ptypes != exp_pt || out->memref.size != sizeof(info)) 7706e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 7716e4f8f17SEtienne Carriere 7726e4f8f17SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 7736e4f8f17SEtienne Carriere 7744daf39b3SJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 7754daf39b3SJens Wiklander if (rc) 7764daf39b3SJens Wiklander return rc; 7776e4f8f17SEtienne Carriere 7786e4f8f17SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 7796e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 7806e4f8f17SEtienne Carriere 7816e4f8f17SEtienne Carriere info.slot_id = get_token_id(session->token); 7826e4f8f17SEtienne Carriere info.state = session->state; 7836e4f8f17SEtienne Carriere if (pkcs11_session_is_read_write(session)) 7846e4f8f17SEtienne Carriere info.flags |= PKCS11_CKFSS_RW_SESSION; 7856e4f8f17SEtienne Carriere 7866e4f8f17SEtienne Carriere TEE_MemMove(out->memref.buffer, &info, sizeof(info)); 7876e4f8f17SEtienne Carriere 7886e4f8f17SEtienne Carriere DMSG("Get find on PKCS11 session %"PRIu32, session->handle); 7896e4f8f17SEtienne Carriere 7906e4f8f17SEtienne Carriere return PKCS11_CKR_OK; 7916e4f8f17SEtienne Carriere } 792f485be04SJens Wiklander 7934daf39b3SJens Wiklander enum pkcs11_rc entry_ck_token_initialize(uint32_t ptypes, TEE_Param *params) 794f485be04SJens Wiklander { 795f485be04SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 796f485be04SJens Wiklander TEE_PARAM_TYPE_NONE, 797f485be04SJens Wiklander TEE_PARAM_TYPE_NONE, 798f485be04SJens Wiklander TEE_PARAM_TYPE_NONE); 799f485be04SJens Wiklander char label[PKCS11_TOKEN_LABEL_SIZE] = { 0 }; 800f485be04SJens Wiklander struct pkcs11_client *client = NULL; 801f485be04SJens Wiklander struct pkcs11_session *sess = NULL; 802f485be04SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 803f485be04SJens Wiklander struct serialargs ctrlargs = { }; 804f485be04SJens Wiklander struct ck_token *token = NULL; 805f485be04SJens Wiklander TEE_Param *ctrl = params; 806f485be04SJens Wiklander uint32_t token_id = 0; 807f485be04SJens Wiklander uint32_t pin_size = 0; 808f485be04SJens Wiklander void *pin = NULL; 8097f12c782SRobin van der Gracht struct pkcs11_object *obj = NULL; 810f485be04SJens Wiklander 811f485be04SJens Wiklander if (ptypes != exp_pt) 812f485be04SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 813f485be04SJens Wiklander 814f485be04SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 815f485be04SJens Wiklander 816f485be04SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t)); 817f485be04SJens Wiklander if (rc) 818f485be04SJens Wiklander return rc; 819f485be04SJens Wiklander 820f485be04SJens Wiklander rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); 821f485be04SJens Wiklander if (rc) 822f485be04SJens Wiklander return rc; 823f485be04SJens Wiklander 824f485be04SJens Wiklander rc = serialargs_get(&ctrlargs, &label, PKCS11_TOKEN_LABEL_SIZE); 825f485be04SJens Wiklander if (rc) 826f485be04SJens Wiklander return rc; 827f485be04SJens Wiklander 828f485be04SJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); 829f485be04SJens Wiklander if (rc) 830f485be04SJens Wiklander return rc; 831f485be04SJens Wiklander 832f485be04SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 833f485be04SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 834f485be04SJens Wiklander 835f485be04SJens Wiklander token = get_token(token_id); 836f485be04SJens Wiklander if (!token) 837f485be04SJens Wiklander return PKCS11_CKR_SLOT_ID_INVALID; 838f485be04SJens Wiklander 839f485be04SJens Wiklander if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) { 840f485be04SJens Wiklander IMSG("Token %"PRIu32": SO PIN locked", token_id); 841f485be04SJens Wiklander return PKCS11_CKR_PIN_LOCKED; 842f485be04SJens Wiklander } 843f485be04SJens Wiklander 844f485be04SJens Wiklander /* Check there's no open session on this token */ 845f485be04SJens Wiklander TAILQ_FOREACH(client, &pkcs11_client_list, link) 846f485be04SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link) 847f485be04SJens Wiklander if (sess->token == token) 848f485be04SJens Wiklander return PKCS11_CKR_SESSION_EXISTS; 849f485be04SJens Wiklander 8501a27b197SVesa Jääskeläinen #if defined(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) 8511a27b197SVesa Jääskeläinen /* Check TEE Identity based authentication if enabled */ 8521a27b197SVesa Jääskeläinen if (token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) { 853f44a7a58SEtienne Carriere rc = verify_identity_auth(token, PKCS11_CKU_SO); 8541a27b197SVesa Jääskeläinen if (rc) 8551a27b197SVesa Jääskeläinen return rc; 8561a27b197SVesa Jääskeläinen } 8571a27b197SVesa Jääskeläinen 8581a27b197SVesa Jääskeläinen /* Detect TEE Identity based ACL usage activation with NULL PIN */ 8591a27b197SVesa Jääskeläinen if (!pin) { 8601a27b197SVesa Jääskeläinen rc = setup_so_identity_auth_from_client(token); 8611a27b197SVesa Jääskeläinen if (rc) 8621a27b197SVesa Jääskeläinen return rc; 8631a27b197SVesa Jääskeläinen 8641a27b197SVesa Jääskeläinen goto inited; 8651a27b197SVesa Jääskeläinen } else { 8661a27b197SVesa Jääskeläinen /* De-activate TEE Identity based authentication */ 8671a27b197SVesa Jääskeläinen token->db_main->flags &= 8681a27b197SVesa Jääskeläinen ~PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH; 8691a27b197SVesa Jääskeläinen } 8701a27b197SVesa Jääskeläinen #endif /* CFG_PKCS11_TA_AUTH_TEE_IDENTITY */ 8711a27b197SVesa Jääskeläinen 872f485be04SJens Wiklander if (!token->db_main->so_pin_salt) { 873f485be04SJens Wiklander /* 874f485be04SJens Wiklander * The spec doesn't permit returning 875f485be04SJens Wiklander * PKCS11_CKR_PIN_LEN_RANGE for this function, take another 876f485be04SJens Wiklander * error code. 877f485be04SJens Wiklander */ 878f485be04SJens Wiklander if (pin_size < PKCS11_TOKEN_PIN_SIZE_MIN || 879f485be04SJens Wiklander pin_size > PKCS11_TOKEN_PIN_SIZE_MAX) 880f485be04SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 881f485be04SJens Wiklander 882f485be04SJens Wiklander rc = hash_pin(PKCS11_CKU_SO, pin, pin_size, 883f485be04SJens Wiklander &token->db_main->so_pin_salt, 884f485be04SJens Wiklander token->db_main->so_pin_hash); 885f485be04SJens Wiklander if (rc) 886f485be04SJens Wiklander return rc; 887f485be04SJens Wiklander 888f485be04SJens Wiklander goto inited; 889f485be04SJens Wiklander } 890f485be04SJens Wiklander 891f485be04SJens Wiklander rc = verify_pin(PKCS11_CKU_SO, pin, pin_size, 892f485be04SJens Wiklander token->db_main->so_pin_salt, 893f485be04SJens Wiklander token->db_main->so_pin_hash); 894f485be04SJens Wiklander if (rc) { 895f485be04SJens Wiklander unsigned int pin_count = 0; 896f485be04SJens Wiklander 897f485be04SJens Wiklander if (rc != PKCS11_CKR_PIN_INCORRECT) 898f485be04SJens Wiklander return rc; 899f485be04SJens Wiklander 900f485be04SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW; 901f485be04SJens Wiklander token->db_main->so_pin_count++; 902f485be04SJens Wiklander 903f485be04SJens Wiklander pin_count = token->db_main->so_pin_count; 904f485be04SJens Wiklander if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) 905f485be04SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY; 906f485be04SJens Wiklander if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX) 907f485be04SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED; 908f485be04SJens Wiklander 909f485be04SJens Wiklander update_persistent_db(token); 910f485be04SJens Wiklander 911f485be04SJens Wiklander return PKCS11_CKR_PIN_INCORRECT; 912f485be04SJens Wiklander } 913f485be04SJens Wiklander 91412253e9eSVesa Jääskeläinen inited: 91512253e9eSVesa Jääskeläinen /* Make sure SO PIN counters are zeroed */ 916f485be04SJens Wiklander token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW | 91712253e9eSVesa Jääskeläinen PKCS11_CKFT_SO_PIN_FINAL_TRY | 91812253e9eSVesa Jääskeläinen PKCS11_CKFT_SO_PIN_LOCKED | 91912253e9eSVesa Jääskeläinen PKCS11_CKFT_SO_PIN_TO_BE_CHANGED); 920f485be04SJens Wiklander token->db_main->so_pin_count = 0; 921f485be04SJens Wiklander 922f485be04SJens Wiklander TEE_MemMove(token->db_main->label, label, PKCS11_TOKEN_LABEL_SIZE); 923f485be04SJens Wiklander token->db_main->flags |= PKCS11_CKFT_TOKEN_INITIALIZED; 924f485be04SJens Wiklander /* Reset user PIN */ 925f485be04SJens Wiklander token->db_main->user_pin_salt = 0; 926f485be04SJens Wiklander token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_INITIALIZED | 927f485be04SJens Wiklander PKCS11_CKFT_USER_PIN_COUNT_LOW | 928f485be04SJens Wiklander PKCS11_CKFT_USER_PIN_FINAL_TRY | 929f485be04SJens Wiklander PKCS11_CKFT_USER_PIN_LOCKED | 930f485be04SJens Wiklander PKCS11_CKFT_USER_PIN_TO_BE_CHANGED); 931f485be04SJens Wiklander 932f485be04SJens Wiklander update_persistent_db(token); 933f485be04SJens Wiklander 9347f12c782SRobin van der Gracht /* Remove all persistent objects */ 9357f12c782SRobin van der Gracht while (!LIST_EMPTY(&token->object_list)) { 9367f12c782SRobin van der Gracht obj = LIST_FIRST(&token->object_list); 9377f12c782SRobin van der Gracht 9387f12c782SRobin van der Gracht /* Try twice otherwise panic! */ 9397f12c782SRobin van der Gracht if (unregister_persistent_object(token, obj->uuid) && 9407f12c782SRobin van der Gracht unregister_persistent_object(token, obj->uuid)) 9417f12c782SRobin van der Gracht TEE_Panic(0); 9427f12c782SRobin van der Gracht 9437f12c782SRobin van der Gracht cleanup_persistent_object(obj, token); 9447f12c782SRobin van der Gracht } 9457f12c782SRobin van der Gracht 946f485be04SJens Wiklander IMSG("PKCS11 token %"PRIu32": initialized", token_id); 947f485be04SJens Wiklander 948f485be04SJens Wiklander return PKCS11_CKR_OK; 949f485be04SJens Wiklander } 950e8dbd92cSJens Wiklander 951e8dbd92cSJens Wiklander static enum pkcs11_rc set_pin(struct pkcs11_session *session, 952e8dbd92cSJens Wiklander uint8_t *new_pin, size_t new_pin_size, 953e8dbd92cSJens Wiklander enum pkcs11_user_type user_type) 954e8dbd92cSJens Wiklander { 9551e497011SVesa Jääskeläinen struct ck_token *token = session->token; 956e8dbd92cSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 957e8dbd92cSJens Wiklander uint32_t flags_clear = 0; 958e8dbd92cSJens Wiklander uint32_t flags_set = 0; 959e8dbd92cSJens Wiklander 9601e497011SVesa Jääskeläinen if (token->db_main->flags & PKCS11_CKFT_WRITE_PROTECTED) 961e8dbd92cSJens Wiklander return PKCS11_CKR_TOKEN_WRITE_PROTECTED; 962e8dbd92cSJens Wiklander 963e8dbd92cSJens Wiklander if (!pkcs11_session_is_read_write(session)) 964e8dbd92cSJens Wiklander return PKCS11_CKR_SESSION_READ_ONLY; 965e8dbd92cSJens Wiklander 9661a27b197SVesa Jääskeläinen if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && 9671a27b197SVesa Jääskeläinen token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) { 9681a27b197SVesa Jääskeläinen rc = setup_identity_auth_from_pin(token, user_type, new_pin, 9691a27b197SVesa Jääskeläinen new_pin_size); 9701a27b197SVesa Jääskeläinen if (rc) 9711a27b197SVesa Jääskeläinen return rc; 9721a27b197SVesa Jääskeläinen 9731a27b197SVesa Jääskeläinen goto update_db; 9741a27b197SVesa Jääskeläinen } 9751a27b197SVesa Jääskeläinen 976e8dbd92cSJens Wiklander if (new_pin_size < PKCS11_TOKEN_PIN_SIZE_MIN || 977e8dbd92cSJens Wiklander new_pin_size > PKCS11_TOKEN_PIN_SIZE_MAX) 978e8dbd92cSJens Wiklander return PKCS11_CKR_PIN_LEN_RANGE; 979e8dbd92cSJens Wiklander 980e8dbd92cSJens Wiklander switch (user_type) { 981e8dbd92cSJens Wiklander case PKCS11_CKU_SO: 982e8dbd92cSJens Wiklander rc = hash_pin(user_type, new_pin, new_pin_size, 9831e497011SVesa Jääskeläinen &token->db_main->so_pin_salt, 9841e497011SVesa Jääskeläinen token->db_main->so_pin_hash); 985e8dbd92cSJens Wiklander if (rc) 986e8dbd92cSJens Wiklander return rc; 9871e497011SVesa Jääskeläinen token->db_main->so_pin_count = 0; 988e8dbd92cSJens Wiklander flags_clear = PKCS11_CKFT_SO_PIN_COUNT_LOW | 989e8dbd92cSJens Wiklander PKCS11_CKFT_SO_PIN_FINAL_TRY | 990e8dbd92cSJens Wiklander PKCS11_CKFT_SO_PIN_LOCKED | 991e8dbd92cSJens Wiklander PKCS11_CKFT_SO_PIN_TO_BE_CHANGED; 992e8dbd92cSJens Wiklander break; 993e8dbd92cSJens Wiklander case PKCS11_CKU_USER: 994e8dbd92cSJens Wiklander rc = hash_pin(user_type, new_pin, new_pin_size, 9951e497011SVesa Jääskeläinen &token->db_main->user_pin_salt, 9961e497011SVesa Jääskeläinen token->db_main->user_pin_hash); 997e8dbd92cSJens Wiklander if (rc) 998e8dbd92cSJens Wiklander return rc; 9991e497011SVesa Jääskeläinen token->db_main->user_pin_count = 0; 1000e8dbd92cSJens Wiklander flags_clear = PKCS11_CKFT_USER_PIN_COUNT_LOW | 1001e8dbd92cSJens Wiklander PKCS11_CKFT_USER_PIN_FINAL_TRY | 1002e8dbd92cSJens Wiklander PKCS11_CKFT_USER_PIN_LOCKED | 1003e8dbd92cSJens Wiklander PKCS11_CKFT_USER_PIN_TO_BE_CHANGED; 1004e8dbd92cSJens Wiklander flags_set = PKCS11_CKFT_USER_PIN_INITIALIZED; 1005e8dbd92cSJens Wiklander break; 1006e8dbd92cSJens Wiklander default: 1007e8dbd92cSJens Wiklander return PKCS11_CKR_FUNCTION_FAILED; 1008e8dbd92cSJens Wiklander } 1009e8dbd92cSJens Wiklander 10101a27b197SVesa Jääskeläinen update_db: 10111e497011SVesa Jääskeläinen token->db_main->flags &= ~flags_clear; 10121e497011SVesa Jääskeläinen token->db_main->flags |= flags_set; 1013e8dbd92cSJens Wiklander 10141e497011SVesa Jääskeläinen update_persistent_db(token); 1015e8dbd92cSJens Wiklander 1016e8dbd92cSJens Wiklander return PKCS11_CKR_OK; 1017e8dbd92cSJens Wiklander } 1018e8dbd92cSJens Wiklander 10194daf39b3SJens Wiklander enum pkcs11_rc entry_ck_init_pin(struct pkcs11_client *client, 1020e8dbd92cSJens Wiklander uint32_t ptypes, TEE_Param *params) 1021e8dbd92cSJens Wiklander { 1022e8dbd92cSJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 1023e8dbd92cSJens Wiklander TEE_PARAM_TYPE_NONE, 1024e8dbd92cSJens Wiklander TEE_PARAM_TYPE_NONE, 1025e8dbd92cSJens Wiklander TEE_PARAM_TYPE_NONE); 1026e8dbd92cSJens Wiklander struct pkcs11_session *session = NULL; 1027e8dbd92cSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 1028e8dbd92cSJens Wiklander struct serialargs ctrlargs = { }; 1029e8dbd92cSJens Wiklander TEE_Param *ctrl = params; 1030e8dbd92cSJens Wiklander uint32_t pin_size = 0; 1031e8dbd92cSJens Wiklander void *pin = NULL; 1032e8dbd92cSJens Wiklander 1033e8dbd92cSJens Wiklander if (!client || ptypes != exp_pt) 1034e8dbd92cSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 1035e8dbd92cSJens Wiklander 1036e8dbd92cSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 1037e8dbd92cSJens Wiklander 1038f40f331fSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 1039e8dbd92cSJens Wiklander if (rc) 1040e8dbd92cSJens Wiklander return rc; 1041e8dbd92cSJens Wiklander 1042e8dbd92cSJens Wiklander rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); 1043e8dbd92cSJens Wiklander if (rc) 1044e8dbd92cSJens Wiklander return rc; 1045e8dbd92cSJens Wiklander 1046e8dbd92cSJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); 1047e8dbd92cSJens Wiklander if (rc) 1048e8dbd92cSJens Wiklander return rc; 1049e8dbd92cSJens Wiklander 1050e8dbd92cSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 1051e8dbd92cSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 1052e8dbd92cSJens Wiklander 1053e8dbd92cSJens Wiklander if (!pkcs11_session_is_so(session)) 1054e8dbd92cSJens Wiklander return PKCS11_CKR_USER_NOT_LOGGED_IN; 1055e8dbd92cSJens Wiklander 1056e8dbd92cSJens Wiklander assert(session->token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED); 1057e8dbd92cSJens Wiklander 1058f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": init PIN", session->handle); 1059e8dbd92cSJens Wiklander 1060e8dbd92cSJens Wiklander return set_pin(session, pin, pin_size, PKCS11_CKU_USER); 1061e8dbd92cSJens Wiklander } 10621dbb91e7SJens Wiklander 10634daf39b3SJens Wiklander static enum pkcs11_rc check_so_pin(struct pkcs11_session *session, 10641dbb91e7SJens Wiklander uint8_t *pin, size_t pin_size) 10651dbb91e7SJens Wiklander { 10661dbb91e7SJens Wiklander struct ck_token *token = session->token; 10671dbb91e7SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 10681dbb91e7SJens Wiklander 10691dbb91e7SJens Wiklander assert(token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED); 10701dbb91e7SJens Wiklander 10711a27b197SVesa Jääskeläinen if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && 10721a27b197SVesa Jääskeläinen token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) 10731a27b197SVesa Jääskeläinen return verify_identity_auth(token, PKCS11_CKU_SO); 10741a27b197SVesa Jääskeläinen 10751dbb91e7SJens Wiklander if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) 10761dbb91e7SJens Wiklander return PKCS11_CKR_PIN_LOCKED; 10771dbb91e7SJens Wiklander 10781dbb91e7SJens Wiklander rc = verify_pin(PKCS11_CKU_SO, pin, pin_size, 10791dbb91e7SJens Wiklander token->db_main->so_pin_salt, 10801dbb91e7SJens Wiklander token->db_main->so_pin_hash); 10811dbb91e7SJens Wiklander if (rc) { 10821dbb91e7SJens Wiklander unsigned int pin_count = 0; 10831dbb91e7SJens Wiklander 10841dbb91e7SJens Wiklander if (rc != PKCS11_CKR_PIN_INCORRECT) 10851dbb91e7SJens Wiklander return rc; 10861dbb91e7SJens Wiklander 10871dbb91e7SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW; 10881dbb91e7SJens Wiklander token->db_main->so_pin_count++; 10891dbb91e7SJens Wiklander 10901dbb91e7SJens Wiklander pin_count = token->db_main->so_pin_count; 10911dbb91e7SJens Wiklander if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) 10921dbb91e7SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY; 10931dbb91e7SJens Wiklander if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX) 10941dbb91e7SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED; 10951dbb91e7SJens Wiklander 10961dbb91e7SJens Wiklander update_persistent_db(token); 10971dbb91e7SJens Wiklander 10981dbb91e7SJens Wiklander if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) 10991dbb91e7SJens Wiklander return PKCS11_CKR_PIN_LOCKED; 11001dbb91e7SJens Wiklander 11011dbb91e7SJens Wiklander return PKCS11_CKR_PIN_INCORRECT; 11021dbb91e7SJens Wiklander } 11031dbb91e7SJens Wiklander 11041dbb91e7SJens Wiklander if (token->db_main->so_pin_count) { 11051dbb91e7SJens Wiklander token->db_main->so_pin_count = 0; 11061dbb91e7SJens Wiklander 11071dbb91e7SJens Wiklander update_persistent_db(token); 11081dbb91e7SJens Wiklander } 11091dbb91e7SJens Wiklander 11101dbb91e7SJens Wiklander if (token->db_main->flags & (PKCS11_CKFT_SO_PIN_COUNT_LOW | 11111dbb91e7SJens Wiklander PKCS11_CKFT_SO_PIN_FINAL_TRY)) { 11121dbb91e7SJens Wiklander token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW | 11131dbb91e7SJens Wiklander PKCS11_CKFT_SO_PIN_FINAL_TRY); 11141dbb91e7SJens Wiklander 11151dbb91e7SJens Wiklander update_persistent_db(token); 11161dbb91e7SJens Wiklander } 11171dbb91e7SJens Wiklander 11181dbb91e7SJens Wiklander return PKCS11_CKR_OK; 11191dbb91e7SJens Wiklander } 11201dbb91e7SJens Wiklander 11214daf39b3SJens Wiklander static enum pkcs11_rc check_user_pin(struct pkcs11_session *session, 11221dbb91e7SJens Wiklander uint8_t *pin, size_t pin_size) 11231dbb91e7SJens Wiklander { 11241dbb91e7SJens Wiklander struct ck_token *token = session->token; 11251dbb91e7SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 11261dbb91e7SJens Wiklander 11271a27b197SVesa Jääskeläinen if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && 11281a27b197SVesa Jääskeläinen token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) 11291a27b197SVesa Jääskeläinen return verify_identity_auth(token, PKCS11_CKU_USER); 11301a27b197SVesa Jääskeläinen 11311dbb91e7SJens Wiklander if (!token->db_main->user_pin_salt) 11321dbb91e7SJens Wiklander return PKCS11_CKR_USER_PIN_NOT_INITIALIZED; 11331dbb91e7SJens Wiklander 11341dbb91e7SJens Wiklander if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED) 11351dbb91e7SJens Wiklander return PKCS11_CKR_PIN_LOCKED; 11361dbb91e7SJens Wiklander 11371dbb91e7SJens Wiklander rc = verify_pin(PKCS11_CKU_USER, pin, pin_size, 11381dbb91e7SJens Wiklander token->db_main->user_pin_salt, 11391dbb91e7SJens Wiklander token->db_main->user_pin_hash); 11401dbb91e7SJens Wiklander if (rc) { 11411dbb91e7SJens Wiklander unsigned int pin_count = 0; 11421dbb91e7SJens Wiklander 11431dbb91e7SJens Wiklander if (rc != PKCS11_CKR_PIN_INCORRECT) 11441dbb91e7SJens Wiklander return rc; 11451dbb91e7SJens Wiklander 11461dbb91e7SJens Wiklander token->db_main->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW; 11471dbb91e7SJens Wiklander token->db_main->user_pin_count++; 11481dbb91e7SJens Wiklander 11491dbb91e7SJens Wiklander pin_count = token->db_main->user_pin_count; 11501dbb91e7SJens Wiklander if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1) 11511dbb91e7SJens Wiklander token->db_main->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY; 11521dbb91e7SJens Wiklander if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX) 11531dbb91e7SJens Wiklander token->db_main->flags |= PKCS11_CKFT_USER_PIN_LOCKED; 11541dbb91e7SJens Wiklander 11551dbb91e7SJens Wiklander update_persistent_db(token); 11561dbb91e7SJens Wiklander 11571dbb91e7SJens Wiklander if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED) 11581dbb91e7SJens Wiklander return PKCS11_CKR_PIN_LOCKED; 11591dbb91e7SJens Wiklander 11601dbb91e7SJens Wiklander return PKCS11_CKR_PIN_INCORRECT; 11611dbb91e7SJens Wiklander } 11621dbb91e7SJens Wiklander 11631dbb91e7SJens Wiklander if (token->db_main->user_pin_count) { 11641dbb91e7SJens Wiklander token->db_main->user_pin_count = 0; 11651dbb91e7SJens Wiklander 11661dbb91e7SJens Wiklander update_persistent_db(token); 11671dbb91e7SJens Wiklander } 11681dbb91e7SJens Wiklander 11691dbb91e7SJens Wiklander if (token->db_main->flags & (PKCS11_CKFT_USER_PIN_COUNT_LOW | 11701dbb91e7SJens Wiklander PKCS11_CKFT_USER_PIN_FINAL_TRY)) { 11711dbb91e7SJens Wiklander token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_COUNT_LOW | 11721dbb91e7SJens Wiklander PKCS11_CKFT_USER_PIN_FINAL_TRY); 11731dbb91e7SJens Wiklander 11741dbb91e7SJens Wiklander update_persistent_db(token); 11751dbb91e7SJens Wiklander } 11761dbb91e7SJens Wiklander 11771dbb91e7SJens Wiklander return PKCS11_CKR_OK; 11781dbb91e7SJens Wiklander } 11791dbb91e7SJens Wiklander 11804daf39b3SJens Wiklander enum pkcs11_rc entry_ck_set_pin(struct pkcs11_client *client, 11811dbb91e7SJens Wiklander uint32_t ptypes, TEE_Param *params) 11821dbb91e7SJens Wiklander { 11831dbb91e7SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 11841dbb91e7SJens Wiklander TEE_PARAM_TYPE_NONE, 11851dbb91e7SJens Wiklander TEE_PARAM_TYPE_NONE, 11861dbb91e7SJens Wiklander TEE_PARAM_TYPE_NONE); 11871dbb91e7SJens Wiklander struct pkcs11_session *session = NULL; 11881dbb91e7SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 11891dbb91e7SJens Wiklander struct serialargs ctrlargs = { }; 11901dbb91e7SJens Wiklander uint32_t old_pin_size = 0; 11911dbb91e7SJens Wiklander TEE_Param *ctrl = params; 11921dbb91e7SJens Wiklander uint32_t pin_size = 0; 11931dbb91e7SJens Wiklander void *old_pin = NULL; 11941dbb91e7SJens Wiklander void *pin = NULL; 11951dbb91e7SJens Wiklander 11961dbb91e7SJens Wiklander if (!client || ptypes != exp_pt) 11971dbb91e7SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 11981dbb91e7SJens Wiklander 11991dbb91e7SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 12001dbb91e7SJens Wiklander 1201f40f331fSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 12021dbb91e7SJens Wiklander if (rc) 12031dbb91e7SJens Wiklander return rc; 12041dbb91e7SJens Wiklander 12051dbb91e7SJens Wiklander rc = serialargs_get(&ctrlargs, &old_pin_size, sizeof(uint32_t)); 12061dbb91e7SJens Wiklander if (rc) 12071dbb91e7SJens Wiklander return rc; 12081dbb91e7SJens Wiklander 12091dbb91e7SJens Wiklander rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); 12101dbb91e7SJens Wiklander if (rc) 12111dbb91e7SJens Wiklander return rc; 12121dbb91e7SJens Wiklander 12131dbb91e7SJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &old_pin, old_pin_size); 12141dbb91e7SJens Wiklander if (rc) 12151dbb91e7SJens Wiklander return rc; 12161dbb91e7SJens Wiklander 12171dbb91e7SJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); 12181dbb91e7SJens Wiklander if (rc) 12191dbb91e7SJens Wiklander return rc; 12201dbb91e7SJens Wiklander 12211dbb91e7SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 12221dbb91e7SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 12231dbb91e7SJens Wiklander 12241dbb91e7SJens Wiklander if (!pkcs11_session_is_read_write(session)) 12251dbb91e7SJens Wiklander return PKCS11_CKR_SESSION_READ_ONLY; 12261dbb91e7SJens Wiklander 12271dbb91e7SJens Wiklander if (pkcs11_session_is_so(session)) { 12281dbb91e7SJens Wiklander if (!(session->token->db_main->flags & 12291dbb91e7SJens Wiklander PKCS11_CKFT_TOKEN_INITIALIZED)) 12301dbb91e7SJens Wiklander return PKCS11_CKR_GENERAL_ERROR; 12311dbb91e7SJens Wiklander 12321dbb91e7SJens Wiklander rc = check_so_pin(session, old_pin, old_pin_size); 12331dbb91e7SJens Wiklander if (rc) 12341dbb91e7SJens Wiklander return rc; 12351dbb91e7SJens Wiklander 1236f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": set PIN", session->handle); 12371dbb91e7SJens Wiklander 12381dbb91e7SJens Wiklander return set_pin(session, pin, pin_size, PKCS11_CKU_SO); 12391dbb91e7SJens Wiklander } 12401dbb91e7SJens Wiklander 12411dbb91e7SJens Wiklander if (!(session->token->db_main->flags & 12421dbb91e7SJens Wiklander PKCS11_CKFT_USER_PIN_INITIALIZED)) 12431dbb91e7SJens Wiklander return PKCS11_CKR_GENERAL_ERROR; 12441dbb91e7SJens Wiklander 12451dbb91e7SJens Wiklander rc = check_user_pin(session, old_pin, old_pin_size); 12461dbb91e7SJens Wiklander if (rc) 12471dbb91e7SJens Wiklander return rc; 12481dbb91e7SJens Wiklander 1249f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": set PIN", session->handle); 12501dbb91e7SJens Wiklander 12511dbb91e7SJens Wiklander return set_pin(session, pin, pin_size, PKCS11_CKU_USER); 12521dbb91e7SJens Wiklander } 1253f7cc36c0SJens Wiklander 1254f7cc36c0SJens Wiklander static void session_login_user(struct pkcs11_session *session) 1255f7cc36c0SJens Wiklander { 1256f7cc36c0SJens Wiklander struct pkcs11_client *client = session->client; 1257f7cc36c0SJens Wiklander struct pkcs11_session *sess = NULL; 1258f7cc36c0SJens Wiklander 1259f7cc36c0SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link) { 1260f7cc36c0SJens Wiklander if (sess->token != session->token) 1261f7cc36c0SJens Wiklander continue; 1262f7cc36c0SJens Wiklander 1263f7cc36c0SJens Wiklander if (pkcs11_session_is_read_write(sess)) 1264f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RW_USER_FUNCTIONS; 1265f7cc36c0SJens Wiklander else 1266f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RO_USER_FUNCTIONS; 1267f7cc36c0SJens Wiklander } 1268f7cc36c0SJens Wiklander } 1269f7cc36c0SJens Wiklander 1270f7cc36c0SJens Wiklander static void session_login_so(struct pkcs11_session *session) 1271f7cc36c0SJens Wiklander { 1272f7cc36c0SJens Wiklander struct pkcs11_client *client = session->client; 1273f7cc36c0SJens Wiklander struct pkcs11_session *sess = NULL; 1274f7cc36c0SJens Wiklander 1275f7cc36c0SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link) { 1276f7cc36c0SJens Wiklander if (sess->token != session->token) 1277f7cc36c0SJens Wiklander continue; 1278f7cc36c0SJens Wiklander 1279f7cc36c0SJens Wiklander if (pkcs11_session_is_read_write(sess)) 1280f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RW_SO_FUNCTIONS; 1281f7cc36c0SJens Wiklander else 1282f7cc36c0SJens Wiklander TEE_Panic(0); 1283f7cc36c0SJens Wiklander } 1284f7cc36c0SJens Wiklander } 1285f7cc36c0SJens Wiklander 1286f7cc36c0SJens Wiklander static void session_logout(struct pkcs11_session *session) 1287f7cc36c0SJens Wiklander { 1288f7cc36c0SJens Wiklander struct pkcs11_client *client = session->client; 1289f7cc36c0SJens Wiklander struct pkcs11_session *sess = NULL; 1290f7cc36c0SJens Wiklander 1291f7cc36c0SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link) { 129289735787SRuchika Gupta struct pkcs11_object *obj = NULL; 12933bf0e097SRuchika Gupta struct pkcs11_object *tobj = NULL; 129489735787SRuchika Gupta uint32_t handle = 0; 129589735787SRuchika Gupta 1296f7cc36c0SJens Wiklander if (sess->token != session->token) 1297f7cc36c0SJens Wiklander continue; 1298f7cc36c0SJens Wiklander 129989735787SRuchika Gupta release_active_processing(session); 130089735787SRuchika Gupta 130189735787SRuchika Gupta /* Destroy private session objects */ 13023bf0e097SRuchika Gupta LIST_FOREACH_SAFE(obj, &sess->object_list, link, tobj) { 130389735787SRuchika Gupta if (object_is_private(obj->attributes)) 130489735787SRuchika Gupta destroy_object(sess, obj, true); 130589735787SRuchika Gupta } 130689735787SRuchika Gupta 130789735787SRuchika Gupta /* 130889735787SRuchika Gupta * Remove handle of token private objects from 130989735787SRuchika Gupta * sessions object_handle_db 131089735787SRuchika Gupta */ 131189735787SRuchika Gupta LIST_FOREACH(obj, &session->token->object_list, link) { 131289735787SRuchika Gupta handle = pkcs11_object2handle(obj, session); 131389735787SRuchika Gupta 131489735787SRuchika Gupta if (handle && object_is_private(obj->attributes)) 131589735787SRuchika Gupta handle_put(&sess->object_handle_db, handle); 131689735787SRuchika Gupta } 131789735787SRuchika Gupta 131889735787SRuchika Gupta release_session_find_obj_context(session); 131989735787SRuchika Gupta 1320f7cc36c0SJens Wiklander if (pkcs11_session_is_read_write(sess)) 1321f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RW_PUBLIC_SESSION; 1322f7cc36c0SJens Wiklander else 1323f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RO_PUBLIC_SESSION; 1324f7cc36c0SJens Wiklander } 1325f7cc36c0SJens Wiklander } 1326f7cc36c0SJens Wiklander 13274daf39b3SJens Wiklander enum pkcs11_rc entry_ck_login(struct pkcs11_client *client, 1328f7cc36c0SJens Wiklander uint32_t ptypes, TEE_Param *params) 1329f7cc36c0SJens Wiklander { 1330f7cc36c0SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 1331f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE, 1332f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE, 1333f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE); 1334f7cc36c0SJens Wiklander struct pkcs11_session *session = NULL; 1335f7cc36c0SJens Wiklander struct pkcs11_session *sess = NULL; 1336f7cc36c0SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 1337f7cc36c0SJens Wiklander struct serialargs ctrlargs = { }; 1338f7cc36c0SJens Wiklander TEE_Param *ctrl = params; 1339f7cc36c0SJens Wiklander uint32_t user_type = 0; 1340f7cc36c0SJens Wiklander uint32_t pin_size = 0; 1341f7cc36c0SJens Wiklander void *pin = NULL; 1342f7cc36c0SJens Wiklander 1343f7cc36c0SJens Wiklander if (!client || ptypes != exp_pt) 1344f7cc36c0SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 1345f7cc36c0SJens Wiklander 1346f7cc36c0SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 1347f7cc36c0SJens Wiklander 1348f40f331fSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 1349f7cc36c0SJens Wiklander if (rc) 1350f7cc36c0SJens Wiklander return rc; 1351f7cc36c0SJens Wiklander 1352f7cc36c0SJens Wiklander rc = serialargs_get(&ctrlargs, &user_type, sizeof(uint32_t)); 1353f7cc36c0SJens Wiklander if (rc) 1354f7cc36c0SJens Wiklander return rc; 1355f7cc36c0SJens Wiklander 1356f7cc36c0SJens Wiklander rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); 1357f7cc36c0SJens Wiklander if (rc) 1358f7cc36c0SJens Wiklander return rc; 1359f7cc36c0SJens Wiklander 1360f7cc36c0SJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); 1361f7cc36c0SJens Wiklander if (rc) 1362f7cc36c0SJens Wiklander return rc; 1363f7cc36c0SJens Wiklander 1364f7cc36c0SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 1365f7cc36c0SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 1366f7cc36c0SJens Wiklander 1367f7cc36c0SJens Wiklander switch (user_type) { 1368f7cc36c0SJens Wiklander case PKCS11_CKU_SO: 1369f7cc36c0SJens Wiklander if (pkcs11_session_is_so(session)) 1370f7cc36c0SJens Wiklander return PKCS11_CKR_USER_ALREADY_LOGGED_IN; 1371f7cc36c0SJens Wiklander 1372f7cc36c0SJens Wiklander if (pkcs11_session_is_user(session)) 1373f7cc36c0SJens Wiklander return PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN; 1374f7cc36c0SJens Wiklander 1375f7cc36c0SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link) 1376f7cc36c0SJens Wiklander if (sess->token == session->token && 1377f7cc36c0SJens Wiklander !pkcs11_session_is_read_write(sess)) 1378f7cc36c0SJens Wiklander return PKCS11_CKR_SESSION_READ_ONLY_EXISTS; 1379f7cc36c0SJens Wiklander 1380f7cc36c0SJens Wiklander /* 1381f7cc36c0SJens Wiklander * This is the point where we could check if another client 1382f7cc36c0SJens Wiklander * has another user or SO logged in. 1383f7cc36c0SJens Wiklander * 1384f7cc36c0SJens Wiklander * The spec says: 1385f7cc36c0SJens Wiklander * CKR_USER_TOO_MANY_TYPES: An attempt was made to have 1386f7cc36c0SJens Wiklander * more distinct users simultaneously logged into the token 1387f7cc36c0SJens Wiklander * than the token and/or library permits. For example, if 1388f7cc36c0SJens Wiklander * some application has an open SO session, and another 1389f7cc36c0SJens Wiklander * application attempts to log the normal user into a 1390f7cc36c0SJens Wiklander * session, the attempt may return this error. It is not 1391f7cc36c0SJens Wiklander * required to, however. Only if the simultaneous distinct 1392f7cc36c0SJens Wiklander * users cannot be supported does C_Login have to return 1393f7cc36c0SJens Wiklander * this value. Note that this error code generalizes to 1394f7cc36c0SJens Wiklander * true multi-user tokens. 1395f7cc36c0SJens Wiklander * 1396f7cc36c0SJens Wiklander * So it's permitted to have another user or SO logged in 1397f7cc36c0SJens Wiklander * from another client. 1398f7cc36c0SJens Wiklander */ 1399f7cc36c0SJens Wiklander 1400f7cc36c0SJens Wiklander rc = check_so_pin(session, pin, pin_size); 1401f7cc36c0SJens Wiklander if (!rc) 1402f7cc36c0SJens Wiklander session_login_so(session); 1403f7cc36c0SJens Wiklander 1404f7cc36c0SJens Wiklander break; 1405f7cc36c0SJens Wiklander 1406f7cc36c0SJens Wiklander case PKCS11_CKU_USER: 1407f7cc36c0SJens Wiklander if (pkcs11_session_is_so(session)) 1408f7cc36c0SJens Wiklander return PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN; 1409f7cc36c0SJens Wiklander 1410f7cc36c0SJens Wiklander if (pkcs11_session_is_user(session)) 1411f7cc36c0SJens Wiklander return PKCS11_CKR_USER_ALREADY_LOGGED_IN; 1412f7cc36c0SJens Wiklander 1413f7cc36c0SJens Wiklander /* 1414f7cc36c0SJens Wiklander * This is the point where we could check if another client 1415f7cc36c0SJens Wiklander * has another user or SO logged in. 1416f7cc36c0SJens Wiklander * See comment on CKR_USER_TOO_MANY_TYPES above. 1417f7cc36c0SJens Wiklander */ 1418f7cc36c0SJens Wiklander 1419f7cc36c0SJens Wiklander rc = check_user_pin(session, pin, pin_size); 1420f7cc36c0SJens Wiklander if (!rc) 1421f7cc36c0SJens Wiklander session_login_user(session); 1422f7cc36c0SJens Wiklander 1423f7cc36c0SJens Wiklander break; 1424f7cc36c0SJens Wiklander 1425f7cc36c0SJens Wiklander case PKCS11_CKU_CONTEXT_SPECIFIC: 1426f7cc36c0SJens Wiklander return PKCS11_CKR_OPERATION_NOT_INITIALIZED; 1427f7cc36c0SJens Wiklander 1428f7cc36c0SJens Wiklander default: 1429f7cc36c0SJens Wiklander return PKCS11_CKR_USER_TYPE_INVALID; 1430f7cc36c0SJens Wiklander } 1431f7cc36c0SJens Wiklander 1432f7cc36c0SJens Wiklander if (!rc) 1433f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": login", session->handle); 1434f7cc36c0SJens Wiklander 1435f7cc36c0SJens Wiklander return rc; 1436f7cc36c0SJens Wiklander } 1437f7cc36c0SJens Wiklander 14384daf39b3SJens Wiklander enum pkcs11_rc entry_ck_logout(struct pkcs11_client *client, 1439f7cc36c0SJens Wiklander uint32_t ptypes, TEE_Param *params) 1440f7cc36c0SJens Wiklander { 1441f7cc36c0SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 1442f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE, 1443f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE, 1444f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE); 1445f7cc36c0SJens Wiklander struct pkcs11_session *session = NULL; 1446f7cc36c0SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 1447f7cc36c0SJens Wiklander struct serialargs ctrlargs = { }; 1448f7cc36c0SJens Wiklander TEE_Param *ctrl = params; 1449f7cc36c0SJens Wiklander 1450f7cc36c0SJens Wiklander if (!client || ptypes != exp_pt) 1451f7cc36c0SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 1452f7cc36c0SJens Wiklander 1453f7cc36c0SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 1454f7cc36c0SJens Wiklander 1455f40f331fSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 1456f7cc36c0SJens Wiklander if (rc) 1457f7cc36c0SJens Wiklander return rc; 1458f7cc36c0SJens Wiklander 1459f7cc36c0SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 1460f7cc36c0SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 1461f7cc36c0SJens Wiklander 1462f7cc36c0SJens Wiklander if (pkcs11_session_is_public(session)) 1463f7cc36c0SJens Wiklander return PKCS11_CKR_USER_NOT_LOGGED_IN; 1464f7cc36c0SJens Wiklander 1465f7cc36c0SJens Wiklander session_logout(session); 1466f7cc36c0SJens Wiklander 1467f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": logout", session->handle); 1468f7cc36c0SJens Wiklander 1469f7cc36c0SJens Wiklander return PKCS11_CKR_OK; 1470f7cc36c0SJens Wiklander } 147122587dc4SVesa Jääskeläinen 147222587dc4SVesa Jääskeläinen static TEE_Result seed_rng_pool(void *seed, size_t length) 147322587dc4SVesa Jääskeläinen { 147422587dc4SVesa Jääskeläinen static const TEE_UUID system_uuid = PTA_SYSTEM_UUID; 147522587dc4SVesa Jääskeläinen uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 147622587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_NONE, 147722587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_NONE, 147822587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_NONE); 147922587dc4SVesa Jääskeläinen TEE_Param params[TEE_NUM_PARAMS] = { }; 148022587dc4SVesa Jääskeläinen TEE_TASessionHandle sess = TEE_HANDLE_NULL; 148122587dc4SVesa Jääskeläinen TEE_Result res = TEE_ERROR_GENERIC; 148222587dc4SVesa Jääskeläinen uint32_t ret_orig = 0; 148322587dc4SVesa Jääskeläinen 148422587dc4SVesa Jääskeläinen params[0].memref.buffer = seed; 148522587dc4SVesa Jääskeläinen params[0].memref.size = (uint32_t)length; 148622587dc4SVesa Jääskeläinen 148722587dc4SVesa Jääskeläinen res = TEE_OpenTASession(&system_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, 148822587dc4SVesa Jääskeläinen &sess, &ret_orig); 148922587dc4SVesa Jääskeläinen if (res != TEE_SUCCESS) { 149022587dc4SVesa Jääskeläinen EMSG("Can't open session to system PTA"); 149122587dc4SVesa Jääskeläinen return res; 149222587dc4SVesa Jääskeläinen } 149322587dc4SVesa Jääskeläinen 149422587dc4SVesa Jääskeläinen res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, 149522587dc4SVesa Jääskeläinen PTA_SYSTEM_ADD_RNG_ENTROPY, 149622587dc4SVesa Jääskeläinen param_types, params, &ret_orig); 149722587dc4SVesa Jääskeläinen if (res != TEE_SUCCESS) 149822587dc4SVesa Jääskeläinen EMSG("Can't invoke system PTA"); 149922587dc4SVesa Jääskeläinen 150022587dc4SVesa Jääskeläinen TEE_CloseTASession(sess); 150122587dc4SVesa Jääskeläinen return res; 150222587dc4SVesa Jääskeläinen } 150322587dc4SVesa Jääskeläinen 150422587dc4SVesa Jääskeläinen enum pkcs11_rc entry_ck_seed_random(struct pkcs11_client *client, 150522587dc4SVesa Jääskeläinen uint32_t ptypes, TEE_Param *params) 150622587dc4SVesa Jääskeläinen { 150722587dc4SVesa Jääskeläinen const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 150822587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_MEMREF_INPUT, 150922587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_NONE, 151022587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_NONE); 151122587dc4SVesa Jääskeläinen TEE_Param *ctrl = params; 151222587dc4SVesa Jääskeläinen TEE_Param *in = params + 1; 151322587dc4SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_OK; 151422587dc4SVesa Jääskeläinen struct serialargs ctrlargs = { }; 151522587dc4SVesa Jääskeläinen struct pkcs11_session *session = NULL; 151622587dc4SVesa Jääskeläinen TEE_Result res = TEE_SUCCESS; 151722587dc4SVesa Jääskeläinen 151822587dc4SVesa Jääskeläinen if (!client || ptypes != exp_pt) 151922587dc4SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 152022587dc4SVesa Jääskeläinen 152122587dc4SVesa Jääskeläinen serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 152222587dc4SVesa Jääskeläinen 152322587dc4SVesa Jääskeläinen rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 152422587dc4SVesa Jääskeläinen if (rc) 152522587dc4SVesa Jääskeläinen return rc; 152622587dc4SVesa Jääskeläinen 152722587dc4SVesa Jääskeläinen if (serialargs_remaining_bytes(&ctrlargs)) 152822587dc4SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 152922587dc4SVesa Jääskeläinen 153022587dc4SVesa Jääskeläinen if (in->memref.size && !in->memref.buffer) 153122587dc4SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 153222587dc4SVesa Jääskeläinen 153322587dc4SVesa Jääskeläinen if (!in->memref.size) 153422587dc4SVesa Jääskeläinen return PKCS11_CKR_OK; 153522587dc4SVesa Jääskeläinen 153622587dc4SVesa Jääskeläinen res = seed_rng_pool(in->memref.buffer, in->memref.size); 153722587dc4SVesa Jääskeläinen if (res != TEE_SUCCESS) 153822587dc4SVesa Jääskeläinen return PKCS11_CKR_FUNCTION_FAILED; 153922587dc4SVesa Jääskeläinen 154022587dc4SVesa Jääskeläinen DMSG("PKCS11 session %"PRIu32": seed random", session->handle); 154122587dc4SVesa Jääskeläinen 154222587dc4SVesa Jääskeläinen return PKCS11_CKR_OK; 154322587dc4SVesa Jääskeläinen } 154422587dc4SVesa Jääskeläinen 154522587dc4SVesa Jääskeläinen enum pkcs11_rc entry_ck_generate_random(struct pkcs11_client *client, 154622587dc4SVesa Jääskeläinen uint32_t ptypes, TEE_Param *params) 154722587dc4SVesa Jääskeläinen { 154822587dc4SVesa Jääskeläinen const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 154922587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_NONE, 155022587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_MEMREF_OUTPUT, 155122587dc4SVesa Jääskeläinen TEE_PARAM_TYPE_NONE); 155222587dc4SVesa Jääskeläinen TEE_Param *ctrl = params; 155322587dc4SVesa Jääskeläinen TEE_Param *out = params + 2; 155422587dc4SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_OK; 155522587dc4SVesa Jääskeläinen struct serialargs ctrlargs = { }; 155622587dc4SVesa Jääskeläinen struct pkcs11_session *session = NULL; 155722587dc4SVesa Jääskeläinen void *buffer = NULL; 155822587dc4SVesa Jääskeläinen size_t buffer_size = 0; 155922587dc4SVesa Jääskeläinen uint8_t *data = NULL; 156022587dc4SVesa Jääskeläinen size_t left = 0; 156122587dc4SVesa Jääskeläinen 156222587dc4SVesa Jääskeläinen if (!client || ptypes != exp_pt) 156322587dc4SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 156422587dc4SVesa Jääskeläinen 156522587dc4SVesa Jääskeläinen serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 156622587dc4SVesa Jääskeläinen 156722587dc4SVesa Jääskeläinen rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 156822587dc4SVesa Jääskeläinen if (rc) 156922587dc4SVesa Jääskeläinen return rc; 157022587dc4SVesa Jääskeläinen 157122587dc4SVesa Jääskeläinen if (serialargs_remaining_bytes(&ctrlargs)) 157222587dc4SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 157322587dc4SVesa Jääskeläinen 157422587dc4SVesa Jääskeläinen if (out->memref.size && !out->memref.buffer) 157522587dc4SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 157622587dc4SVesa Jääskeläinen 157722587dc4SVesa Jääskeläinen if (!out->memref.size) 157822587dc4SVesa Jääskeläinen return PKCS11_CKR_OK; 157922587dc4SVesa Jääskeläinen 158022587dc4SVesa Jääskeläinen buffer_size = MIN(out->memref.size, RNG_CHUNK_SIZE); 158122587dc4SVesa Jääskeläinen buffer = TEE_Malloc(buffer_size, TEE_MALLOC_FILL_ZERO); 158222587dc4SVesa Jääskeläinen if (!buffer) 158322587dc4SVesa Jääskeläinen return PKCS11_CKR_DEVICE_MEMORY; 158422587dc4SVesa Jääskeläinen 158522587dc4SVesa Jääskeläinen data = out->memref.buffer; 158622587dc4SVesa Jääskeläinen left = out->memref.size; 158722587dc4SVesa Jääskeläinen 158822587dc4SVesa Jääskeläinen while (left) { 158922587dc4SVesa Jääskeläinen size_t count = MIN(left, buffer_size); 159022587dc4SVesa Jääskeläinen 159122587dc4SVesa Jääskeläinen TEE_GenerateRandom(buffer, count); 159222587dc4SVesa Jääskeläinen TEE_MemMove(data, buffer, count); 159322587dc4SVesa Jääskeläinen 159422587dc4SVesa Jääskeläinen data += count; 159522587dc4SVesa Jääskeläinen left -= count; 159622587dc4SVesa Jääskeläinen } 159722587dc4SVesa Jääskeläinen 159822587dc4SVesa Jääskeläinen DMSG("PKCS11 session %"PRIu32": generate random", session->handle); 159922587dc4SVesa Jääskeläinen 160022587dc4SVesa Jääskeläinen TEE_Free(buffer); 160122587dc4SVesa Jääskeläinen 160222587dc4SVesa Jääskeläinen return PKCS11_CKR_OK; 160322587dc4SVesa Jääskeläinen } 1604