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> 7d38f9635SEtienne Carriere #include <confine_array_index.h> 8c84ccd0aSEtienne Carriere #include <pkcs11_ta.h> 9d628ebd9SEtienne Carriere #include <printk.h> 10c84ccd0aSEtienne Carriere #include <string.h> 11c84ccd0aSEtienne Carriere #include <string_ext.h> 12c84ccd0aSEtienne Carriere #include <sys/queue.h> 13c84ccd0aSEtienne Carriere #include <tee_api_types.h> 14c84ccd0aSEtienne Carriere #include <tee_internal_api_extensions.h> 15c84ccd0aSEtienne Carriere #include <util.h> 16c84ccd0aSEtienne Carriere 17512cbf1dSJens Wiklander #include "attributes.h" 1849443fc0SEtienne Carriere #include "handle.h" 19c84ccd0aSEtienne Carriere #include "pkcs11_helpers.h" 20ee49d9f2SEtienne Carriere #include "pkcs11_token.h" 2155e6965cSEtienne Carriere #include "processing.h" 2222ac6984SEtienne Carriere #include "serializer.h" 2349443fc0SEtienne Carriere #include "token_capabilities.h" 24c84ccd0aSEtienne Carriere 25c84ccd0aSEtienne Carriere /* Provide 3 slots/tokens, ID is token index */ 26c84ccd0aSEtienne Carriere #ifndef CFG_PKCS11_TA_TOKEN_COUNT 27c84ccd0aSEtienne Carriere #define TOKEN_COUNT 3 28c84ccd0aSEtienne Carriere #else 29c84ccd0aSEtienne Carriere #define TOKEN_COUNT CFG_PKCS11_TA_TOKEN_COUNT 30c84ccd0aSEtienne Carriere #endif 31c84ccd0aSEtienne Carriere 32e084583eSEtienne Carriere /* 33e084583eSEtienne Carriere * Structure tracking client applications 34e084583eSEtienne Carriere * 35e084583eSEtienne Carriere * @link - chained list of registered client applications 36e084583eSEtienne Carriere * @sessions - list of the PKCS11 sessions opened by the client application 37e084583eSEtienne Carriere */ 38e084583eSEtienne Carriere struct pkcs11_client { 39e084583eSEtienne Carriere TAILQ_ENTRY(pkcs11_client) link; 40e084583eSEtienne Carriere struct session_list session_list; 41e084583eSEtienne Carriere struct handle_db session_handle_db; 42e084583eSEtienne Carriere }; 43e084583eSEtienne Carriere 44c84ccd0aSEtienne Carriere /* Static allocation of tokens runtime instances (reset to 0 at load) */ 45c84ccd0aSEtienne Carriere struct ck_token ck_token[TOKEN_COUNT]; 46c84ccd0aSEtienne Carriere 47e084583eSEtienne Carriere static struct client_list pkcs11_client_list = 48e084583eSEtienne Carriere TAILQ_HEAD_INITIALIZER(pkcs11_client_list); 49e084583eSEtienne Carriere 506e4f8f17SEtienne Carriere static void close_ck_session(struct pkcs11_session *session); 516e4f8f17SEtienne Carriere 52c84ccd0aSEtienne Carriere struct ck_token *get_token(unsigned int token_id) 53c84ccd0aSEtienne Carriere { 54d38f9635SEtienne Carriere if (token_id < TOKEN_COUNT) 55d38f9635SEtienne Carriere return &ck_token[confine_array_index(token_id, TOKEN_COUNT)]; 56c84ccd0aSEtienne Carriere 57d38f9635SEtienne Carriere return NULL; 58c84ccd0aSEtienne Carriere } 59c84ccd0aSEtienne Carriere 60c84ccd0aSEtienne Carriere unsigned int get_token_id(struct ck_token *token) 61c84ccd0aSEtienne Carriere { 62c84ccd0aSEtienne Carriere ptrdiff_t id = token - ck_token; 63c84ccd0aSEtienne Carriere 64c84ccd0aSEtienne Carriere assert(id >= 0 && id < TOKEN_COUNT); 65c84ccd0aSEtienne Carriere return id; 66c84ccd0aSEtienne Carriere } 67c84ccd0aSEtienne Carriere 68e084583eSEtienne Carriere struct pkcs11_client *tee_session2client(void *tee_session) 69e084583eSEtienne Carriere { 70e084583eSEtienne Carriere struct pkcs11_client *client = NULL; 71e084583eSEtienne Carriere 72e084583eSEtienne Carriere TAILQ_FOREACH(client, &pkcs11_client_list, link) 73e084583eSEtienne Carriere if (client == tee_session) 74e084583eSEtienne Carriere break; 75e084583eSEtienne Carriere 76e084583eSEtienne Carriere return client; 77e084583eSEtienne Carriere } 78e084583eSEtienne Carriere 796e4f8f17SEtienne Carriere struct pkcs11_session *pkcs11_handle2session(uint32_t handle, 806e4f8f17SEtienne Carriere struct pkcs11_client *client) 816e4f8f17SEtienne Carriere { 826e4f8f17SEtienne Carriere return handle_lookup(&client->session_handle_db, handle); 836e4f8f17SEtienne Carriere } 846e4f8f17SEtienne Carriere 85e084583eSEtienne Carriere struct pkcs11_client *register_client(void) 86e084583eSEtienne Carriere { 87e084583eSEtienne Carriere struct pkcs11_client *client = NULL; 88e084583eSEtienne Carriere 89e084583eSEtienne Carriere client = TEE_Malloc(sizeof(*client), TEE_MALLOC_FILL_ZERO); 90e084583eSEtienne Carriere if (!client) 91e084583eSEtienne Carriere return NULL; 92e084583eSEtienne Carriere 93e084583eSEtienne Carriere TAILQ_INSERT_HEAD(&pkcs11_client_list, client, link); 94e084583eSEtienne Carriere TAILQ_INIT(&client->session_list); 95e084583eSEtienne Carriere handle_db_init(&client->session_handle_db); 96e084583eSEtienne Carriere 97e084583eSEtienne Carriere return client; 98e084583eSEtienne Carriere } 99e084583eSEtienne Carriere 100e084583eSEtienne Carriere void unregister_client(struct pkcs11_client *client) 101e084583eSEtienne Carriere { 1026e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL; 1036e4f8f17SEtienne Carriere struct pkcs11_session *next = NULL; 1046e4f8f17SEtienne Carriere 105e084583eSEtienne Carriere if (!client) { 106e084583eSEtienne Carriere EMSG("Invalid TEE session handle"); 107e084583eSEtienne Carriere return; 108e084583eSEtienne Carriere } 109e084583eSEtienne Carriere 1106e4f8f17SEtienne Carriere TAILQ_FOREACH_SAFE(session, &client->session_list, link, next) 1116e4f8f17SEtienne Carriere close_ck_session(session); 1126e4f8f17SEtienne Carriere 113e084583eSEtienne Carriere TAILQ_REMOVE(&pkcs11_client_list, client, link); 114e084583eSEtienne Carriere handle_db_destroy(&client->session_handle_db); 115e084583eSEtienne Carriere TEE_Free(client); 116e084583eSEtienne Carriere } 117e084583eSEtienne Carriere 118c84ccd0aSEtienne Carriere static TEE_Result pkcs11_token_init(unsigned int id) 119c84ccd0aSEtienne Carriere { 120c84ccd0aSEtienne Carriere struct ck_token *token = init_persistent_db(id); 121c84ccd0aSEtienne Carriere 122c84ccd0aSEtienne Carriere if (!token) 123c84ccd0aSEtienne Carriere return TEE_ERROR_SECURITY; 124c84ccd0aSEtienne Carriere 125c84ccd0aSEtienne Carriere if (token->state == PKCS11_TOKEN_RESET) { 126c84ccd0aSEtienne Carriere /* As per PKCS#11 spec, token resets to read/write state */ 127c84ccd0aSEtienne Carriere token->state = PKCS11_TOKEN_READ_WRITE; 128c84ccd0aSEtienne Carriere token->session_count = 0; 129c84ccd0aSEtienne Carriere token->rw_session_count = 0; 130c84ccd0aSEtienne Carriere } 131c84ccd0aSEtienne Carriere 132c84ccd0aSEtienne Carriere return TEE_SUCCESS; 133c84ccd0aSEtienne Carriere } 134c84ccd0aSEtienne Carriere 135c84ccd0aSEtienne Carriere TEE_Result pkcs11_init(void) 136c84ccd0aSEtienne Carriere { 137c84ccd0aSEtienne Carriere unsigned int id = 0; 138c84ccd0aSEtienne Carriere TEE_Result ret = TEE_ERROR_GENERIC; 139c84ccd0aSEtienne Carriere 140c84ccd0aSEtienne Carriere for (id = 0; id < TOKEN_COUNT; id++) { 141c84ccd0aSEtienne Carriere ret = pkcs11_token_init(id); 142c84ccd0aSEtienne Carriere if (ret) 143e084583eSEtienne Carriere break; 144c84ccd0aSEtienne Carriere } 145c84ccd0aSEtienne Carriere 146c84ccd0aSEtienne Carriere return ret; 147c84ccd0aSEtienne Carriere } 148c84ccd0aSEtienne Carriere 149c84ccd0aSEtienne Carriere void pkcs11_deinit(void) 150c84ccd0aSEtienne Carriere { 151c84ccd0aSEtienne Carriere unsigned int id = 0; 152c84ccd0aSEtienne Carriere 153c84ccd0aSEtienne Carriere for (id = 0; id < TOKEN_COUNT; id++) 154c84ccd0aSEtienne Carriere close_persistent_db(get_token(id)); 155c84ccd0aSEtienne Carriere } 15622ac6984SEtienne Carriere 157512cbf1dSJens Wiklander /* 158512cbf1dSJens Wiklander * Currently no support for dual operations. 159512cbf1dSJens Wiklander */ 160512cbf1dSJens Wiklander enum pkcs11_rc set_processing_state(struct pkcs11_session *session, 161512cbf1dSJens Wiklander enum processing_func function, 162512cbf1dSJens Wiklander struct pkcs11_object *obj1, 163512cbf1dSJens Wiklander struct pkcs11_object *obj2) 164512cbf1dSJens Wiklander { 165512cbf1dSJens Wiklander enum pkcs11_proc_state state = PKCS11_SESSION_READY; 166512cbf1dSJens Wiklander struct active_processing *proc = NULL; 167512cbf1dSJens Wiklander 168512cbf1dSJens Wiklander if (session->processing) 169512cbf1dSJens Wiklander return PKCS11_CKR_OPERATION_ACTIVE; 170512cbf1dSJens Wiklander 171512cbf1dSJens Wiklander switch (function) { 172512cbf1dSJens Wiklander case PKCS11_FUNCTION_ENCRYPT: 173512cbf1dSJens Wiklander state = PKCS11_SESSION_ENCRYPTING; 174512cbf1dSJens Wiklander break; 175512cbf1dSJens Wiklander case PKCS11_FUNCTION_DECRYPT: 176512cbf1dSJens Wiklander state = PKCS11_SESSION_DECRYPTING; 177512cbf1dSJens Wiklander break; 178512cbf1dSJens Wiklander case PKCS11_FUNCTION_SIGN: 179512cbf1dSJens Wiklander state = PKCS11_SESSION_SIGNING; 180512cbf1dSJens Wiklander break; 181512cbf1dSJens Wiklander case PKCS11_FUNCTION_VERIFY: 182512cbf1dSJens Wiklander state = PKCS11_SESSION_VERIFYING; 183512cbf1dSJens Wiklander break; 184512cbf1dSJens Wiklander case PKCS11_FUNCTION_DIGEST: 185512cbf1dSJens Wiklander state = PKCS11_SESSION_DIGESTING; 186512cbf1dSJens Wiklander break; 187512cbf1dSJens Wiklander case PKCS11_FUNCTION_DERIVE: 188512cbf1dSJens Wiklander state = PKCS11_SESSION_READY; 189512cbf1dSJens Wiklander break; 190512cbf1dSJens Wiklander default: 191512cbf1dSJens Wiklander TEE_Panic(function); 192512cbf1dSJens Wiklander return -1; 193512cbf1dSJens Wiklander } 194512cbf1dSJens Wiklander 195512cbf1dSJens Wiklander proc = TEE_Malloc(sizeof(*proc), TEE_MALLOC_FILL_ZERO); 196512cbf1dSJens Wiklander if (!proc) 197512cbf1dSJens Wiklander return PKCS11_CKR_DEVICE_MEMORY; 198512cbf1dSJens Wiklander 199512cbf1dSJens Wiklander /* Boolean are default to false and pointers to NULL */ 200512cbf1dSJens Wiklander proc->state = state; 201512cbf1dSJens Wiklander proc->tee_op_handle = TEE_HANDLE_NULL; 202512cbf1dSJens Wiklander 203512cbf1dSJens Wiklander if (obj1 && get_bool(obj1->attributes, PKCS11_CKA_ALWAYS_AUTHENTICATE)) 204512cbf1dSJens Wiklander proc->always_authen = true; 205512cbf1dSJens Wiklander 206512cbf1dSJens Wiklander if (obj2 && get_bool(obj2->attributes, PKCS11_CKA_ALWAYS_AUTHENTICATE)) 207512cbf1dSJens Wiklander proc->always_authen = true; 208512cbf1dSJens Wiklander 209512cbf1dSJens Wiklander session->processing = proc; 210512cbf1dSJens Wiklander 211512cbf1dSJens Wiklander return PKCS11_CKR_OK; 212512cbf1dSJens Wiklander } 213512cbf1dSJens Wiklander 2144daf39b3SJens Wiklander enum pkcs11_rc entry_ck_slot_list(uint32_t ptypes, TEE_Param *params) 21522ac6984SEtienne Carriere { 21622ac6984SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 21722ac6984SEtienne Carriere TEE_PARAM_TYPE_NONE, 21822ac6984SEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 21922ac6984SEtienne Carriere TEE_PARAM_TYPE_NONE); 22039b43b78SJens Wiklander TEE_Param *out = params + 2; 22122ac6984SEtienne Carriere uint32_t token_id = 0; 22222ac6984SEtienne Carriere const size_t out_size = sizeof(token_id) * TOKEN_COUNT; 22322ac6984SEtienne Carriere uint8_t *id = NULL; 22422ac6984SEtienne Carriere 22522ac6984SEtienne Carriere if (ptypes != exp_pt || 22622ac6984SEtienne Carriere params[0].memref.size != TEE_PARAM0_SIZE_MIN) 22722ac6984SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 22822ac6984SEtienne Carriere 22922ac6984SEtienne Carriere if (out->memref.size < out_size) { 23022ac6984SEtienne Carriere out->memref.size = out_size; 23122ac6984SEtienne Carriere 23222ac6984SEtienne Carriere if (out->memref.buffer) 23322ac6984SEtienne Carriere return PKCS11_CKR_BUFFER_TOO_SMALL; 23422ac6984SEtienne Carriere else 23522ac6984SEtienne Carriere return PKCS11_CKR_OK; 23622ac6984SEtienne Carriere } 23722ac6984SEtienne Carriere 23822ac6984SEtienne Carriere for (token_id = 0, id = out->memref.buffer; token_id < TOKEN_COUNT; 23922ac6984SEtienne Carriere token_id++, id += sizeof(token_id)) 24022ac6984SEtienne Carriere TEE_MemMove(id, &token_id, sizeof(token_id)); 24122ac6984SEtienne Carriere 24222ac6984SEtienne Carriere out->memref.size = out_size; 24322ac6984SEtienne Carriere 24422ac6984SEtienne Carriere return PKCS11_CKR_OK; 24522ac6984SEtienne Carriere } 246ce94efefSEtienne Carriere 247b3ac5035SEtienne Carriere static void pad_str(uint8_t *str, size_t size) 248b3ac5035SEtienne Carriere { 249b3ac5035SEtienne Carriere int n = strnlen((char *)str, size); 250b3ac5035SEtienne Carriere 251b3ac5035SEtienne Carriere TEE_MemFill(str + n, ' ', size - n); 252b3ac5035SEtienne Carriere } 253b3ac5035SEtienne Carriere 254d628ebd9SEtienne Carriere static void set_token_description(struct pkcs11_slot_info *info) 255d628ebd9SEtienne Carriere { 256d628ebd9SEtienne Carriere char desc[sizeof(info->slot_description) + 1] = { 0 }; 257d628ebd9SEtienne Carriere TEE_UUID dev_id = { }; 258d628ebd9SEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC; 259d628ebd9SEtienne Carriere int n = 0; 260d628ebd9SEtienne Carriere 261d628ebd9SEtienne Carriere res = TEE_GetPropertyAsUUID(TEE_PROPSET_TEE_IMPLEMENTATION, 262d628ebd9SEtienne Carriere "gpd.tee.deviceID", &dev_id); 263d628ebd9SEtienne Carriere if (res == TEE_SUCCESS) { 264d628ebd9SEtienne Carriere n = snprintk(desc, sizeof(desc), PKCS11_SLOT_DESCRIPTION 265d628ebd9SEtienne Carriere " - TEE UUID %pUl", (void *)&dev_id); 266d628ebd9SEtienne Carriere } else { 267d628ebd9SEtienne Carriere n = snprintf(desc, sizeof(desc), PKCS11_SLOT_DESCRIPTION 268d628ebd9SEtienne Carriere " - No TEE UUID"); 269d628ebd9SEtienne Carriere } 270d628ebd9SEtienne Carriere if (n < 0 || n >= (int)sizeof(desc)) 271d628ebd9SEtienne Carriere TEE_Panic(0); 272d628ebd9SEtienne Carriere 273d628ebd9SEtienne Carriere TEE_MemMove(info->slot_description, desc, n); 274d628ebd9SEtienne Carriere pad_str(info->slot_description, sizeof(info->slot_description)); 275d628ebd9SEtienne Carriere } 276d628ebd9SEtienne Carriere 2774daf39b3SJens Wiklander enum pkcs11_rc entry_ck_slot_info(uint32_t ptypes, TEE_Param *params) 278ce94efefSEtienne Carriere { 279ce94efefSEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 280ce94efefSEtienne Carriere TEE_PARAM_TYPE_NONE, 281ce94efefSEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 282ce94efefSEtienne Carriere TEE_PARAM_TYPE_NONE); 28339b43b78SJens Wiklander TEE_Param *ctrl = params; 28439b43b78SJens Wiklander TEE_Param *out = params + 2; 2854daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 286ce94efefSEtienne Carriere struct serialargs ctrlargs = { }; 287ce94efefSEtienne Carriere uint32_t token_id = 0; 288ce94efefSEtienne Carriere struct pkcs11_slot_info info = { 289ce94efefSEtienne Carriere .slot_description = PKCS11_SLOT_DESCRIPTION, 290ce94efefSEtienne Carriere .manufacturer_id = PKCS11_SLOT_MANUFACTURER, 291ce94efefSEtienne Carriere .flags = PKCS11_CKFS_TOKEN_PRESENT, 292ce94efefSEtienne Carriere .hardware_version = PKCS11_SLOT_HW_VERSION, 293ce94efefSEtienne Carriere .firmware_version = PKCS11_SLOT_FW_VERSION, 294ce94efefSEtienne Carriere }; 295ce94efefSEtienne Carriere 296ce94efefSEtienne Carriere COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_DESCRIPTION) <= 297ce94efefSEtienne Carriere sizeof(info.slot_description)); 298ce94efefSEtienne Carriere COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_MANUFACTURER) <= 299ce94efefSEtienne Carriere sizeof(info.manufacturer_id)); 300ce94efefSEtienne Carriere 301ce94efefSEtienne Carriere if (ptypes != exp_pt || out->memref.size != sizeof(info)) 302ce94efefSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 303ce94efefSEtienne Carriere 304ce94efefSEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 305ce94efefSEtienne Carriere 3064daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); 3074daf39b3SJens Wiklander if (rc) 3084daf39b3SJens Wiklander return rc; 309ce94efefSEtienne Carriere 310ce94efefSEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 311ce94efefSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 312ce94efefSEtienne Carriere 31329b0949aSEtienne Carriere if (!get_token(token_id)) 314ce94efefSEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID; 315ce94efefSEtienne Carriere 316d628ebd9SEtienne Carriere set_token_description(&info); 317d628ebd9SEtienne Carriere 318b3ac5035SEtienne Carriere pad_str(info.manufacturer_id, sizeof(info.manufacturer_id)); 319ce94efefSEtienne Carriere 320ce94efefSEtienne Carriere out->memref.size = sizeof(info); 321ce94efefSEtienne Carriere TEE_MemMove(out->memref.buffer, &info, out->memref.size); 322ce94efefSEtienne Carriere 323ce94efefSEtienne Carriere return PKCS11_CKR_OK; 324ce94efefSEtienne Carriere } 325030e7392SEtienne Carriere 3264daf39b3SJens Wiklander enum pkcs11_rc entry_ck_token_info(uint32_t ptypes, TEE_Param *params) 327030e7392SEtienne Carriere { 328030e7392SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 329030e7392SEtienne Carriere TEE_PARAM_TYPE_NONE, 330030e7392SEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 331030e7392SEtienne Carriere TEE_PARAM_TYPE_NONE); 33239b43b78SJens Wiklander TEE_Param *ctrl = params; 33339b43b78SJens Wiklander TEE_Param *out = params + 2; 3344daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 335030e7392SEtienne Carriere struct serialargs ctrlargs = { }; 336030e7392SEtienne Carriere uint32_t token_id = 0; 337030e7392SEtienne Carriere struct ck_token *token = NULL; 338030e7392SEtienne Carriere struct pkcs11_token_info info = { 339030e7392SEtienne Carriere .manufacturer_id = PKCS11_TOKEN_MANUFACTURER, 340030e7392SEtienne Carriere .model = PKCS11_TOKEN_MODEL, 341030e7392SEtienne Carriere .max_session_count = UINT32_MAX, 342030e7392SEtienne Carriere .max_rw_session_count = UINT32_MAX, 343030e7392SEtienne Carriere .max_pin_len = PKCS11_TOKEN_PIN_SIZE_MAX, 344030e7392SEtienne Carriere .min_pin_len = PKCS11_TOKEN_PIN_SIZE_MIN, 345030e7392SEtienne Carriere .total_public_memory = UINT32_MAX, 346030e7392SEtienne Carriere .free_public_memory = UINT32_MAX, 347030e7392SEtienne Carriere .total_private_memory = UINT32_MAX, 348030e7392SEtienne Carriere .free_private_memory = UINT32_MAX, 349030e7392SEtienne Carriere .hardware_version = PKCS11_TOKEN_HW_VERSION, 350030e7392SEtienne Carriere .firmware_version = PKCS11_TOKEN_FW_VERSION, 351030e7392SEtienne Carriere }; 35202b4d42aSEtienne Carriere char sn[sizeof(info.serial_number) + 1] = { 0 }; 35302b4d42aSEtienne Carriere int n = 0; 354030e7392SEtienne Carriere 355030e7392SEtienne Carriere if (ptypes != exp_pt || out->memref.size != sizeof(info)) 356030e7392SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 357030e7392SEtienne Carriere 358030e7392SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 359030e7392SEtienne Carriere 3604daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); 3614daf39b3SJens Wiklander if (rc) 3624daf39b3SJens Wiklander return rc; 363030e7392SEtienne Carriere 364030e7392SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 365030e7392SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 366030e7392SEtienne Carriere 367030e7392SEtienne Carriere token = get_token(token_id); 368030e7392SEtienne Carriere if (!token) 369030e7392SEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID; 370030e7392SEtienne Carriere 371030e7392SEtienne Carriere pad_str(info.manufacturer_id, sizeof(info.manufacturer_id)); 372030e7392SEtienne Carriere pad_str(info.model, sizeof(info.model)); 37302b4d42aSEtienne Carriere 37402b4d42aSEtienne Carriere n = snprintf(sn, sizeof(sn), "%0*"PRIu32, 37502b4d42aSEtienne Carriere (int)sizeof(info.serial_number), token_id); 37602b4d42aSEtienne Carriere if (n != (int)sizeof(info.serial_number)) 37702b4d42aSEtienne Carriere TEE_Panic(0); 37802b4d42aSEtienne Carriere 37902b4d42aSEtienne Carriere TEE_MemMove(info.serial_number, sn, sizeof(info.serial_number)); 380030e7392SEtienne Carriere pad_str(info.serial_number, sizeof(info.serial_number)); 381030e7392SEtienne Carriere 382030e7392SEtienne Carriere TEE_MemMove(info.label, token->db_main->label, sizeof(info.label)); 383030e7392SEtienne Carriere 384030e7392SEtienne Carriere info.flags = token->db_main->flags; 385030e7392SEtienne Carriere info.session_count = token->session_count; 386030e7392SEtienne Carriere info.rw_session_count = token->rw_session_count; 387030e7392SEtienne Carriere 388030e7392SEtienne Carriere TEE_MemMove(out->memref.buffer, &info, sizeof(info)); 389030e7392SEtienne Carriere 390030e7392SEtienne Carriere return PKCS11_CKR_OK; 391030e7392SEtienne Carriere } 3926f74919dSEtienne Carriere 3936f74919dSEtienne Carriere static void dmsg_print_supported_mechanism(unsigned int token_id __maybe_unused, 3946f74919dSEtienne Carriere uint32_t *array __maybe_unused, 3956f74919dSEtienne Carriere size_t count __maybe_unused) 3966f74919dSEtienne Carriere { 3976f74919dSEtienne Carriere size_t __maybe_unused n = 0; 3986f74919dSEtienne Carriere 3996f74919dSEtienne Carriere if (TRACE_LEVEL < TRACE_DEBUG) 4006f74919dSEtienne Carriere return; 4016f74919dSEtienne Carriere 4026f74919dSEtienne Carriere for (n = 0; n < count; n++) 4036f74919dSEtienne Carriere DMSG("PKCS11 token %"PRIu32": mechanism 0x%04"PRIx32": %s", 4046f74919dSEtienne Carriere token_id, array[n], id2str_mechanism(array[n])); 4056f74919dSEtienne Carriere } 4066f74919dSEtienne Carriere 4074daf39b3SJens Wiklander enum pkcs11_rc entry_ck_token_mecha_ids(uint32_t ptypes, TEE_Param *params) 4086f74919dSEtienne Carriere { 4096f74919dSEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 4106f74919dSEtienne Carriere TEE_PARAM_TYPE_NONE, 4116f74919dSEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 4126f74919dSEtienne Carriere TEE_PARAM_TYPE_NONE); 41339b43b78SJens Wiklander TEE_Param *ctrl = params; 41439b43b78SJens Wiklander TEE_Param *out = params + 2; 4154daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 4166f74919dSEtienne Carriere struct serialargs ctrlargs = { }; 4176f74919dSEtienne Carriere uint32_t token_id = 0; 4186f74919dSEtienne Carriere struct ck_token __maybe_unused *token = NULL; 4196f74919dSEtienne Carriere size_t count = 0; 4206f74919dSEtienne Carriere uint32_t *array = NULL; 4216f74919dSEtienne Carriere 4226f74919dSEtienne Carriere if (ptypes != exp_pt) 4236f74919dSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 4246f74919dSEtienne Carriere 4256f74919dSEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 4266f74919dSEtienne Carriere 4274daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); 4284daf39b3SJens Wiklander if (rc) 4294daf39b3SJens Wiklander return rc; 4306f74919dSEtienne Carriere 4316f74919dSEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 4326f74919dSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 4336f74919dSEtienne Carriere 4346f74919dSEtienne Carriere token = get_token(token_id); 4356f74919dSEtienne Carriere if (!token) 4366f74919dSEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID; 4376f74919dSEtienne Carriere 4386f74919dSEtienne Carriere count = out->memref.size / sizeof(*array); 4396f74919dSEtienne Carriere array = tee_malloc_mechanism_list(&count); 4406f74919dSEtienne Carriere 4416f74919dSEtienne Carriere if (out->memref.size < count * sizeof(*array)) { 4426f74919dSEtienne Carriere assert(!array); 4436f74919dSEtienne Carriere out->memref.size = count * sizeof(*array); 4446459f267SEtienne Carriere if (out->memref.buffer) 4456f74919dSEtienne Carriere return PKCS11_CKR_BUFFER_TOO_SMALL; 4466459f267SEtienne Carriere else 4476459f267SEtienne Carriere return PKCS11_CKR_OK; 4486f74919dSEtienne Carriere } 4496f74919dSEtienne Carriere 4506f74919dSEtienne Carriere if (!array) 4516f74919dSEtienne Carriere return PKCS11_CKR_DEVICE_MEMORY; 4526f74919dSEtienne Carriere 4536f74919dSEtienne Carriere dmsg_print_supported_mechanism(token_id, array, count); 4546f74919dSEtienne Carriere 4556f74919dSEtienne Carriere out->memref.size = count * sizeof(*array); 4566f74919dSEtienne Carriere TEE_MemMove(out->memref.buffer, array, out->memref.size); 4576f74919dSEtienne Carriere 4586f74919dSEtienne Carriere TEE_Free(array); 4596f74919dSEtienne Carriere 4604daf39b3SJens Wiklander return rc; 4616f74919dSEtienne Carriere } 4621d3ebedbSEtienne Carriere 4634daf39b3SJens Wiklander enum pkcs11_rc entry_ck_token_mecha_info(uint32_t ptypes, TEE_Param *params) 4641d3ebedbSEtienne Carriere { 4651d3ebedbSEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 4661d3ebedbSEtienne Carriere TEE_PARAM_TYPE_NONE, 4671d3ebedbSEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 4681d3ebedbSEtienne Carriere TEE_PARAM_TYPE_NONE); 46939b43b78SJens Wiklander TEE_Param *ctrl = params; 47039b43b78SJens Wiklander TEE_Param *out = params + 2; 4714daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 4721d3ebedbSEtienne Carriere struct serialargs ctrlargs = { }; 4731d3ebedbSEtienne Carriere uint32_t token_id = 0; 4741d3ebedbSEtienne Carriere uint32_t type = 0; 4751d3ebedbSEtienne Carriere struct ck_token *token = NULL; 4761d3ebedbSEtienne Carriere struct pkcs11_mechanism_info info = { }; 4771d3ebedbSEtienne Carriere 4781d3ebedbSEtienne Carriere if (ptypes != exp_pt || out->memref.size != sizeof(info)) 4791d3ebedbSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 4801d3ebedbSEtienne Carriere 4811d3ebedbSEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 4821d3ebedbSEtienne Carriere 4834daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t)); 4844daf39b3SJens Wiklander if (rc) 4854daf39b3SJens Wiklander return rc; 4861d3ebedbSEtienne Carriere 4874daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &type, sizeof(uint32_t)); 4884daf39b3SJens Wiklander if (rc) 4894daf39b3SJens Wiklander return rc; 4901d3ebedbSEtienne Carriere 4911d3ebedbSEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 4921d3ebedbSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 4931d3ebedbSEtienne Carriere 4941d3ebedbSEtienne Carriere token = get_token(token_id); 4951d3ebedbSEtienne Carriere if (!token) 4961d3ebedbSEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID; 4971d3ebedbSEtienne Carriere 4981d3ebedbSEtienne Carriere if (!mechanism_is_valid(type)) 4991d3ebedbSEtienne Carriere return PKCS11_CKR_MECHANISM_INVALID; 5001d3ebedbSEtienne Carriere 5011d3ebedbSEtienne Carriere info.flags = mechanism_supported_flags(type); 5021d3ebedbSEtienne Carriere 50378adf52fSEtienne Carriere mechanism_supported_key_sizes(type, &info.min_key_size, 5041d3ebedbSEtienne Carriere &info.max_key_size); 5051d3ebedbSEtienne Carriere 5061d3ebedbSEtienne Carriere TEE_MemMove(out->memref.buffer, &info, sizeof(info)); 5071d3ebedbSEtienne Carriere 5081d3ebedbSEtienne Carriere DMSG("PKCS11 token %"PRIu32": mechanism 0x%"PRIx32" info", 5091d3ebedbSEtienne Carriere token_id, type); 5101d3ebedbSEtienne Carriere 5111d3ebedbSEtienne Carriere return PKCS11_CKR_OK; 5121d3ebedbSEtienne Carriere } 5136e4f8f17SEtienne Carriere 5146e4f8f17SEtienne Carriere /* Select the ReadOnly or ReadWrite state for session login state */ 5156e4f8f17SEtienne Carriere static void set_session_state(struct pkcs11_client *client, 5166e4f8f17SEtienne Carriere struct pkcs11_session *session, bool readonly) 5176e4f8f17SEtienne Carriere { 5186e4f8f17SEtienne Carriere struct pkcs11_session *sess = NULL; 5196e4f8f17SEtienne Carriere enum pkcs11_session_state state = PKCS11_CKS_RO_PUBLIC_SESSION; 5206e4f8f17SEtienne Carriere 5216e4f8f17SEtienne Carriere /* Default to public session if no session already registered */ 5226e4f8f17SEtienne Carriere if (readonly) 5236e4f8f17SEtienne Carriere state = PKCS11_CKS_RO_PUBLIC_SESSION; 5246e4f8f17SEtienne Carriere else 5256e4f8f17SEtienne Carriere state = PKCS11_CKS_RW_PUBLIC_SESSION; 5266e4f8f17SEtienne Carriere 5276e4f8f17SEtienne Carriere /* 5286e4f8f17SEtienne Carriere * No need to check all client sessions, the first found in 5296e4f8f17SEtienne Carriere * target token gives client login configuration. 5306e4f8f17SEtienne Carriere */ 5316e4f8f17SEtienne Carriere TAILQ_FOREACH(sess, &client->session_list, link) { 5326e4f8f17SEtienne Carriere assert(sess != session); 5336e4f8f17SEtienne Carriere 5346e4f8f17SEtienne Carriere if (sess->token == session->token) { 5356e4f8f17SEtienne Carriere switch (sess->state) { 5366e4f8f17SEtienne Carriere case PKCS11_CKS_RW_PUBLIC_SESSION: 5376e4f8f17SEtienne Carriere case PKCS11_CKS_RO_PUBLIC_SESSION: 5386e4f8f17SEtienne Carriere if (readonly) 5396e4f8f17SEtienne Carriere state = PKCS11_CKS_RO_PUBLIC_SESSION; 5406e4f8f17SEtienne Carriere else 5416e4f8f17SEtienne Carriere state = PKCS11_CKS_RW_PUBLIC_SESSION; 5426e4f8f17SEtienne Carriere break; 5436e4f8f17SEtienne Carriere case PKCS11_CKS_RO_USER_FUNCTIONS: 5446e4f8f17SEtienne Carriere case PKCS11_CKS_RW_USER_FUNCTIONS: 5456e4f8f17SEtienne Carriere if (readonly) 5466e4f8f17SEtienne Carriere state = PKCS11_CKS_RO_USER_FUNCTIONS; 5476e4f8f17SEtienne Carriere else 5486e4f8f17SEtienne Carriere state = PKCS11_CKS_RW_USER_FUNCTIONS; 5496e4f8f17SEtienne Carriere break; 5506e4f8f17SEtienne Carriere case PKCS11_CKS_RW_SO_FUNCTIONS: 5516e4f8f17SEtienne Carriere if (readonly) 5526e4f8f17SEtienne Carriere TEE_Panic(0); 5536e4f8f17SEtienne Carriere else 5546e4f8f17SEtienne Carriere state = PKCS11_CKS_RW_SO_FUNCTIONS; 5556e4f8f17SEtienne Carriere break; 5566e4f8f17SEtienne Carriere default: 5576e4f8f17SEtienne Carriere TEE_Panic(0); 5586e4f8f17SEtienne Carriere } 5596e4f8f17SEtienne Carriere break; 5606e4f8f17SEtienne Carriere } 5616e4f8f17SEtienne Carriere } 5626e4f8f17SEtienne Carriere 5636e4f8f17SEtienne Carriere session->state = state; 5646e4f8f17SEtienne Carriere } 5656e4f8f17SEtienne Carriere 5664daf39b3SJens Wiklander enum pkcs11_rc entry_ck_open_session(struct pkcs11_client *client, 5676e4f8f17SEtienne Carriere uint32_t ptypes, TEE_Param *params) 5686e4f8f17SEtienne Carriere { 5696e4f8f17SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 5706e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE, 5716e4f8f17SEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 5726e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE); 57339b43b78SJens Wiklander TEE_Param *ctrl = params; 57439b43b78SJens Wiklander TEE_Param *out = params + 2; 5754daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 5766e4f8f17SEtienne Carriere struct serialargs ctrlargs = { }; 5776e4f8f17SEtienne Carriere uint32_t token_id = 0; 5786e4f8f17SEtienne Carriere uint32_t flags = 0; 5796e4f8f17SEtienne Carriere struct ck_token *token = NULL; 5806e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL; 5816e4f8f17SEtienne Carriere bool readonly = false; 5826e4f8f17SEtienne Carriere 5836e4f8f17SEtienne Carriere if (!client || ptypes != exp_pt || 5846e4f8f17SEtienne Carriere out->memref.size != sizeof(session->handle)) 5856e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 5866e4f8f17SEtienne Carriere 5876e4f8f17SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 5886e4f8f17SEtienne Carriere 5894daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); 5904daf39b3SJens Wiklander if (rc) 5914daf39b3SJens Wiklander return rc; 5926e4f8f17SEtienne Carriere 5934daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &flags, sizeof(flags)); 5944daf39b3SJens Wiklander if (rc) 5954daf39b3SJens Wiklander return rc; 5966e4f8f17SEtienne Carriere 5976e4f8f17SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 5986e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 5996e4f8f17SEtienne Carriere 6006e4f8f17SEtienne Carriere token = get_token(token_id); 6016e4f8f17SEtienne Carriere if (!token) 6026e4f8f17SEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID; 6036e4f8f17SEtienne Carriere 6046e4f8f17SEtienne Carriere /* Sanitize session flags */ 60508774c86SVesa Jääskeläinen if (!(flags & PKCS11_CKFSS_SERIAL_SESSION)) 60608774c86SVesa Jääskeläinen return PKCS11_CKR_SESSION_PARALLEL_NOT_SUPPORTED; 60708774c86SVesa Jääskeläinen 60808774c86SVesa Jääskeläinen if (flags & ~(PKCS11_CKFSS_RW_SESSION | PKCS11_CKFSS_SERIAL_SESSION)) 6096e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 6106e4f8f17SEtienne Carriere 6116e4f8f17SEtienne Carriere readonly = !(flags & PKCS11_CKFSS_RW_SESSION); 6126e4f8f17SEtienne Carriere 6136e4f8f17SEtienne Carriere if (!readonly && token->state == PKCS11_TOKEN_READ_ONLY) 6146e4f8f17SEtienne Carriere return PKCS11_CKR_TOKEN_WRITE_PROTECTED; 6156e4f8f17SEtienne Carriere 6166e4f8f17SEtienne Carriere if (readonly) { 6176e4f8f17SEtienne Carriere /* Specifically reject read-only session under SO login */ 6186e4f8f17SEtienne Carriere TAILQ_FOREACH(session, &client->session_list, link) 6196e4f8f17SEtienne Carriere if (pkcs11_session_is_so(session)) 6206e4f8f17SEtienne Carriere return PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS; 6216e4f8f17SEtienne Carriere } 6226e4f8f17SEtienne Carriere 6236e4f8f17SEtienne Carriere session = TEE_Malloc(sizeof(*session), TEE_MALLOC_FILL_ZERO); 6246e4f8f17SEtienne Carriere if (!session) 6256e4f8f17SEtienne Carriere return PKCS11_CKR_DEVICE_MEMORY; 6266e4f8f17SEtienne Carriere 6276e4f8f17SEtienne Carriere session->handle = handle_get(&client->session_handle_db, session); 6286e4f8f17SEtienne Carriere if (!session->handle) { 6296e4f8f17SEtienne Carriere TEE_Free(session); 6306e4f8f17SEtienne Carriere return PKCS11_CKR_DEVICE_MEMORY; 6316e4f8f17SEtienne Carriere } 6326e4f8f17SEtienne Carriere 6336e4f8f17SEtienne Carriere session->token = token; 6346e4f8f17SEtienne Carriere session->client = client; 6356e4f8f17SEtienne Carriere 636b56b3d07SJens Wiklander LIST_INIT(&session->object_list); 637b56b3d07SJens Wiklander handle_db_init(&session->object_handle_db); 638b56b3d07SJens Wiklander 6396e4f8f17SEtienne Carriere set_session_state(client, session, readonly); 6406e4f8f17SEtienne Carriere 6416e4f8f17SEtienne Carriere TAILQ_INSERT_HEAD(&client->session_list, session, link); 6426e4f8f17SEtienne Carriere 6436e4f8f17SEtienne Carriere session->token->session_count++; 6446e4f8f17SEtienne Carriere if (!readonly) 6456e4f8f17SEtienne Carriere session->token->rw_session_count++; 6466e4f8f17SEtienne Carriere 6476e4f8f17SEtienne Carriere TEE_MemMove(out->memref.buffer, &session->handle, 6486e4f8f17SEtienne Carriere sizeof(session->handle)); 6496e4f8f17SEtienne Carriere 6506e4f8f17SEtienne Carriere DMSG("Open PKCS11 session %"PRIu32, session->handle); 6516e4f8f17SEtienne Carriere 6526e4f8f17SEtienne Carriere return PKCS11_CKR_OK; 6536e4f8f17SEtienne Carriere } 6546e4f8f17SEtienne Carriere 6556e4f8f17SEtienne Carriere static void close_ck_session(struct pkcs11_session *session) 6566e4f8f17SEtienne Carriere { 65755e6965cSEtienne Carriere release_active_processing(session); 65855e6965cSEtienne Carriere 659b56b3d07SJens Wiklander /* No need to put object handles, the whole database is destroyed */ 660b56b3d07SJens Wiklander while (!LIST_EMPTY(&session->object_list)) 661b56b3d07SJens Wiklander destroy_object(session, 662b56b3d07SJens Wiklander LIST_FIRST(&session->object_list), true); 663b56b3d07SJens Wiklander 6646e4f8f17SEtienne Carriere TAILQ_REMOVE(&session->client->session_list, session, link); 6656e4f8f17SEtienne Carriere handle_put(&session->client->session_handle_db, session->handle); 666b56b3d07SJens Wiklander handle_db_destroy(&session->object_handle_db); 6676e4f8f17SEtienne Carriere 6686e4f8f17SEtienne Carriere session->token->session_count--; 6696e4f8f17SEtienne Carriere if (pkcs11_session_is_read_write(session)) 6706e4f8f17SEtienne Carriere session->token->rw_session_count--; 6716e4f8f17SEtienne Carriere 6726e4f8f17SEtienne Carriere TEE_Free(session); 6736e4f8f17SEtienne Carriere 6746e4f8f17SEtienne Carriere DMSG("Close PKCS11 session %"PRIu32, session->handle); 6756e4f8f17SEtienne Carriere } 6766e4f8f17SEtienne Carriere 6774daf39b3SJens Wiklander enum pkcs11_rc entry_ck_close_session(struct pkcs11_client *client, 6786e4f8f17SEtienne Carriere uint32_t ptypes, TEE_Param *params) 6796e4f8f17SEtienne Carriere { 6806e4f8f17SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 6816e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE, 6826e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE, 6836e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE); 68439b43b78SJens Wiklander TEE_Param *ctrl = params; 6854daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 6866e4f8f17SEtienne Carriere struct serialargs ctrlargs = { }; 6876e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL; 6886e4f8f17SEtienne Carriere 6896e4f8f17SEtienne Carriere if (!client || ptypes != exp_pt) 6906e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 6916e4f8f17SEtienne Carriere 6926e4f8f17SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 6936e4f8f17SEtienne Carriere 6944daf39b3SJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 6954daf39b3SJens Wiklander if (rc) 6964daf39b3SJens Wiklander return rc; 6976e4f8f17SEtienne Carriere 6986e4f8f17SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 6996e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 7006e4f8f17SEtienne Carriere 7016e4f8f17SEtienne Carriere close_ck_session(session); 7026e4f8f17SEtienne Carriere 7036e4f8f17SEtienne Carriere return PKCS11_CKR_OK; 7046e4f8f17SEtienne Carriere } 7056e4f8f17SEtienne Carriere 7064daf39b3SJens Wiklander enum pkcs11_rc entry_ck_close_all_sessions(struct pkcs11_client *client, 7076e4f8f17SEtienne Carriere uint32_t ptypes, TEE_Param *params) 7086e4f8f17SEtienne Carriere { 7096e4f8f17SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 7106e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE, 7116e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE, 7126e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE); 71339b43b78SJens Wiklander TEE_Param *ctrl = params; 7144daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 7156e4f8f17SEtienne Carriere struct serialargs ctrlargs = { }; 7166e4f8f17SEtienne Carriere uint32_t token_id = 0; 7176e4f8f17SEtienne Carriere struct ck_token *token = NULL; 7186e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL; 7196e4f8f17SEtienne Carriere struct pkcs11_session *next = NULL; 7206e4f8f17SEtienne Carriere 7216e4f8f17SEtienne Carriere if (!client || ptypes != exp_pt) 7226e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 7236e4f8f17SEtienne Carriere 7246e4f8f17SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 7256e4f8f17SEtienne Carriere 7264daf39b3SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t)); 7274daf39b3SJens Wiklander if (rc) 7284daf39b3SJens Wiklander return rc; 7296e4f8f17SEtienne Carriere 7306e4f8f17SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 7316e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 7326e4f8f17SEtienne Carriere 7336e4f8f17SEtienne Carriere token = get_token(token_id); 7346e4f8f17SEtienne Carriere if (!token) 7356e4f8f17SEtienne Carriere return PKCS11_CKR_SLOT_ID_INVALID; 7366e4f8f17SEtienne Carriere 7376e4f8f17SEtienne Carriere DMSG("Close all sessions for PKCS11 token %"PRIu32, token_id); 7386e4f8f17SEtienne Carriere 7396e4f8f17SEtienne Carriere TAILQ_FOREACH_SAFE(session, &client->session_list, link, next) 7406e4f8f17SEtienne Carriere if (session->token == token) 7416e4f8f17SEtienne Carriere close_ck_session(session); 7426e4f8f17SEtienne Carriere 7436e4f8f17SEtienne Carriere return PKCS11_CKR_OK; 7446e4f8f17SEtienne Carriere } 7456e4f8f17SEtienne Carriere 7464daf39b3SJens Wiklander enum pkcs11_rc entry_ck_session_info(struct pkcs11_client *client, 7476e4f8f17SEtienne Carriere uint32_t ptypes, TEE_Param *params) 7486e4f8f17SEtienne Carriere { 7496e4f8f17SEtienne Carriere const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 7506e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE, 7516e4f8f17SEtienne Carriere TEE_PARAM_TYPE_MEMREF_OUTPUT, 7526e4f8f17SEtienne Carriere TEE_PARAM_TYPE_NONE); 75339b43b78SJens Wiklander TEE_Param *ctrl = params; 75439b43b78SJens Wiklander TEE_Param *out = params + 2; 7554daf39b3SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 7566e4f8f17SEtienne Carriere struct serialargs ctrlargs = { }; 7576e4f8f17SEtienne Carriere struct pkcs11_session *session = NULL; 7586e4f8f17SEtienne Carriere struct pkcs11_session_info info = { 7596e4f8f17SEtienne Carriere .flags = PKCS11_CKFSS_SERIAL_SESSION, 7606e4f8f17SEtienne Carriere }; 7616e4f8f17SEtienne Carriere 7626e4f8f17SEtienne Carriere if (!client || ptypes != exp_pt || out->memref.size != sizeof(info)) 7636e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 7646e4f8f17SEtienne Carriere 7656e4f8f17SEtienne Carriere serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 7666e4f8f17SEtienne Carriere 7674daf39b3SJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 7684daf39b3SJens Wiklander if (rc) 7694daf39b3SJens Wiklander return rc; 7706e4f8f17SEtienne Carriere 7716e4f8f17SEtienne Carriere if (serialargs_remaining_bytes(&ctrlargs)) 7726e4f8f17SEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 7736e4f8f17SEtienne Carriere 7746e4f8f17SEtienne Carriere info.slot_id = get_token_id(session->token); 7756e4f8f17SEtienne Carriere info.state = session->state; 7766e4f8f17SEtienne Carriere if (pkcs11_session_is_read_write(session)) 7776e4f8f17SEtienne Carriere info.flags |= PKCS11_CKFSS_RW_SESSION; 7786e4f8f17SEtienne Carriere 7796e4f8f17SEtienne Carriere TEE_MemMove(out->memref.buffer, &info, sizeof(info)); 7806e4f8f17SEtienne Carriere 7816e4f8f17SEtienne Carriere DMSG("Get find on PKCS11 session %"PRIu32, session->handle); 7826e4f8f17SEtienne Carriere 7836e4f8f17SEtienne Carriere return PKCS11_CKR_OK; 7846e4f8f17SEtienne Carriere } 785f485be04SJens Wiklander 7864daf39b3SJens Wiklander enum pkcs11_rc entry_ck_token_initialize(uint32_t ptypes, TEE_Param *params) 787f485be04SJens Wiklander { 788f485be04SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 789f485be04SJens Wiklander TEE_PARAM_TYPE_NONE, 790f485be04SJens Wiklander TEE_PARAM_TYPE_NONE, 791f485be04SJens Wiklander TEE_PARAM_TYPE_NONE); 792f485be04SJens Wiklander char label[PKCS11_TOKEN_LABEL_SIZE] = { 0 }; 793f485be04SJens Wiklander struct pkcs11_client *client = NULL; 794f485be04SJens Wiklander struct pkcs11_session *sess = NULL; 795f485be04SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 796f485be04SJens Wiklander struct serialargs ctrlargs = { }; 797f485be04SJens Wiklander struct ck_token *token = NULL; 798f485be04SJens Wiklander TEE_Param *ctrl = params; 799f485be04SJens Wiklander uint32_t token_id = 0; 800f485be04SJens Wiklander uint32_t pin_size = 0; 801f485be04SJens Wiklander void *pin = NULL; 802f485be04SJens Wiklander 803f485be04SJens Wiklander if (ptypes != exp_pt) 804f485be04SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 805f485be04SJens Wiklander 806f485be04SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 807f485be04SJens Wiklander 808f485be04SJens Wiklander rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t)); 809f485be04SJens Wiklander if (rc) 810f485be04SJens Wiklander return rc; 811f485be04SJens Wiklander 812f485be04SJens Wiklander rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); 813f485be04SJens Wiklander if (rc) 814f485be04SJens Wiklander return rc; 815f485be04SJens Wiklander 816f485be04SJens Wiklander rc = serialargs_get(&ctrlargs, &label, PKCS11_TOKEN_LABEL_SIZE); 817f485be04SJens Wiklander if (rc) 818f485be04SJens Wiklander return rc; 819f485be04SJens Wiklander 820f485be04SJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); 821f485be04SJens Wiklander if (rc) 822f485be04SJens Wiklander return rc; 823f485be04SJens Wiklander 824f485be04SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 825f485be04SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 826f485be04SJens Wiklander 827f485be04SJens Wiklander token = get_token(token_id); 828f485be04SJens Wiklander if (!token) 829f485be04SJens Wiklander return PKCS11_CKR_SLOT_ID_INVALID; 830f485be04SJens Wiklander 831f485be04SJens Wiklander if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) { 832f485be04SJens Wiklander IMSG("Token %"PRIu32": SO PIN locked", token_id); 833f485be04SJens Wiklander return PKCS11_CKR_PIN_LOCKED; 834f485be04SJens Wiklander } 835f485be04SJens Wiklander 836f485be04SJens Wiklander /* Check there's no open session on this token */ 837f485be04SJens Wiklander TAILQ_FOREACH(client, &pkcs11_client_list, link) 838f485be04SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link) 839f485be04SJens Wiklander if (sess->token == token) 840f485be04SJens Wiklander return PKCS11_CKR_SESSION_EXISTS; 841f485be04SJens Wiklander 842f485be04SJens Wiklander if (!token->db_main->so_pin_salt) { 843f485be04SJens Wiklander /* 844f485be04SJens Wiklander * The spec doesn't permit returning 845f485be04SJens Wiklander * PKCS11_CKR_PIN_LEN_RANGE for this function, take another 846f485be04SJens Wiklander * error code. 847f485be04SJens Wiklander */ 848f485be04SJens Wiklander if (pin_size < PKCS11_TOKEN_PIN_SIZE_MIN || 849f485be04SJens Wiklander pin_size > PKCS11_TOKEN_PIN_SIZE_MAX) 850f485be04SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 851f485be04SJens Wiklander 852f485be04SJens Wiklander rc = hash_pin(PKCS11_CKU_SO, pin, pin_size, 853f485be04SJens Wiklander &token->db_main->so_pin_salt, 854f485be04SJens Wiklander token->db_main->so_pin_hash); 855f485be04SJens Wiklander if (rc) 856f485be04SJens Wiklander return rc; 857f485be04SJens Wiklander 858f485be04SJens Wiklander goto inited; 859f485be04SJens Wiklander } 860f485be04SJens Wiklander 861f485be04SJens Wiklander rc = verify_pin(PKCS11_CKU_SO, pin, pin_size, 862f485be04SJens Wiklander token->db_main->so_pin_salt, 863f485be04SJens Wiklander token->db_main->so_pin_hash); 864f485be04SJens Wiklander if (rc) { 865f485be04SJens Wiklander unsigned int pin_count = 0; 866f485be04SJens Wiklander 867f485be04SJens Wiklander if (rc != PKCS11_CKR_PIN_INCORRECT) 868f485be04SJens Wiklander return rc; 869f485be04SJens Wiklander 870f485be04SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW; 871f485be04SJens Wiklander token->db_main->so_pin_count++; 872f485be04SJens Wiklander 873f485be04SJens Wiklander pin_count = token->db_main->so_pin_count; 874f485be04SJens Wiklander if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) 875f485be04SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY; 876f485be04SJens Wiklander if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX) 877f485be04SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED; 878f485be04SJens Wiklander 879f485be04SJens Wiklander update_persistent_db(token); 880f485be04SJens Wiklander 881f485be04SJens Wiklander return PKCS11_CKR_PIN_INCORRECT; 882f485be04SJens Wiklander } 883f485be04SJens Wiklander 88412253e9eSVesa Jääskeläinen inited: 88512253e9eSVesa Jääskeläinen /* Make sure SO PIN counters are zeroed */ 886f485be04SJens Wiklander token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW | 88712253e9eSVesa Jääskeläinen PKCS11_CKFT_SO_PIN_FINAL_TRY | 88812253e9eSVesa Jääskeläinen PKCS11_CKFT_SO_PIN_LOCKED | 88912253e9eSVesa Jääskeläinen PKCS11_CKFT_SO_PIN_TO_BE_CHANGED); 890f485be04SJens Wiklander token->db_main->so_pin_count = 0; 891f485be04SJens Wiklander 892f485be04SJens Wiklander TEE_MemMove(token->db_main->label, label, PKCS11_TOKEN_LABEL_SIZE); 893f485be04SJens Wiklander token->db_main->flags |= PKCS11_CKFT_TOKEN_INITIALIZED; 894f485be04SJens Wiklander /* Reset user PIN */ 895f485be04SJens Wiklander token->db_main->user_pin_salt = 0; 896f485be04SJens Wiklander token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_INITIALIZED | 897f485be04SJens Wiklander PKCS11_CKFT_USER_PIN_COUNT_LOW | 898f485be04SJens Wiklander PKCS11_CKFT_USER_PIN_FINAL_TRY | 899f485be04SJens Wiklander PKCS11_CKFT_USER_PIN_LOCKED | 900f485be04SJens Wiklander PKCS11_CKFT_USER_PIN_TO_BE_CHANGED); 901f485be04SJens Wiklander 902f485be04SJens Wiklander update_persistent_db(token); 903f485be04SJens Wiklander 904f485be04SJens Wiklander IMSG("PKCS11 token %"PRIu32": initialized", token_id); 905f485be04SJens Wiklander 906f485be04SJens Wiklander return PKCS11_CKR_OK; 907f485be04SJens Wiklander } 908e8dbd92cSJens Wiklander 909e8dbd92cSJens Wiklander static enum pkcs11_rc set_pin(struct pkcs11_session *session, 910e8dbd92cSJens Wiklander uint8_t *new_pin, size_t new_pin_size, 911e8dbd92cSJens Wiklander enum pkcs11_user_type user_type) 912e8dbd92cSJens Wiklander { 913*1e497011SVesa Jääskeläinen struct ck_token *token = session->token; 914e8dbd92cSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 915e8dbd92cSJens Wiklander uint32_t flags_clear = 0; 916e8dbd92cSJens Wiklander uint32_t flags_set = 0; 917e8dbd92cSJens Wiklander 918*1e497011SVesa Jääskeläinen if (token->db_main->flags & PKCS11_CKFT_WRITE_PROTECTED) 919e8dbd92cSJens Wiklander return PKCS11_CKR_TOKEN_WRITE_PROTECTED; 920e8dbd92cSJens Wiklander 921e8dbd92cSJens Wiklander if (!pkcs11_session_is_read_write(session)) 922e8dbd92cSJens Wiklander return PKCS11_CKR_SESSION_READ_ONLY; 923e8dbd92cSJens Wiklander 924e8dbd92cSJens Wiklander if (new_pin_size < PKCS11_TOKEN_PIN_SIZE_MIN || 925e8dbd92cSJens Wiklander new_pin_size > PKCS11_TOKEN_PIN_SIZE_MAX) 926e8dbd92cSJens Wiklander return PKCS11_CKR_PIN_LEN_RANGE; 927e8dbd92cSJens Wiklander 928e8dbd92cSJens Wiklander switch (user_type) { 929e8dbd92cSJens Wiklander case PKCS11_CKU_SO: 930e8dbd92cSJens Wiklander rc = hash_pin(user_type, new_pin, new_pin_size, 931*1e497011SVesa Jääskeläinen &token->db_main->so_pin_salt, 932*1e497011SVesa Jääskeläinen token->db_main->so_pin_hash); 933e8dbd92cSJens Wiklander if (rc) 934e8dbd92cSJens Wiklander return rc; 935*1e497011SVesa Jääskeläinen token->db_main->so_pin_count = 0; 936e8dbd92cSJens Wiklander flags_clear = PKCS11_CKFT_SO_PIN_COUNT_LOW | 937e8dbd92cSJens Wiklander PKCS11_CKFT_SO_PIN_FINAL_TRY | 938e8dbd92cSJens Wiklander PKCS11_CKFT_SO_PIN_LOCKED | 939e8dbd92cSJens Wiklander PKCS11_CKFT_SO_PIN_TO_BE_CHANGED; 940e8dbd92cSJens Wiklander break; 941e8dbd92cSJens Wiklander case PKCS11_CKU_USER: 942e8dbd92cSJens Wiklander rc = hash_pin(user_type, new_pin, new_pin_size, 943*1e497011SVesa Jääskeläinen &token->db_main->user_pin_salt, 944*1e497011SVesa Jääskeläinen token->db_main->user_pin_hash); 945e8dbd92cSJens Wiklander if (rc) 946e8dbd92cSJens Wiklander return rc; 947*1e497011SVesa Jääskeläinen token->db_main->user_pin_count = 0; 948e8dbd92cSJens Wiklander flags_clear = PKCS11_CKFT_USER_PIN_COUNT_LOW | 949e8dbd92cSJens Wiklander PKCS11_CKFT_USER_PIN_FINAL_TRY | 950e8dbd92cSJens Wiklander PKCS11_CKFT_USER_PIN_LOCKED | 951e8dbd92cSJens Wiklander PKCS11_CKFT_USER_PIN_TO_BE_CHANGED; 952e8dbd92cSJens Wiklander flags_set = PKCS11_CKFT_USER_PIN_INITIALIZED; 953e8dbd92cSJens Wiklander break; 954e8dbd92cSJens Wiklander default: 955e8dbd92cSJens Wiklander return PKCS11_CKR_FUNCTION_FAILED; 956e8dbd92cSJens Wiklander } 957e8dbd92cSJens Wiklander 958*1e497011SVesa Jääskeläinen token->db_main->flags &= ~flags_clear; 959*1e497011SVesa Jääskeläinen token->db_main->flags |= flags_set; 960e8dbd92cSJens Wiklander 961*1e497011SVesa Jääskeläinen update_persistent_db(token); 962e8dbd92cSJens Wiklander 963e8dbd92cSJens Wiklander return PKCS11_CKR_OK; 964e8dbd92cSJens Wiklander } 965e8dbd92cSJens Wiklander 9664daf39b3SJens Wiklander enum pkcs11_rc entry_ck_init_pin(struct pkcs11_client *client, 967e8dbd92cSJens Wiklander uint32_t ptypes, TEE_Param *params) 968e8dbd92cSJens Wiklander { 969e8dbd92cSJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 970e8dbd92cSJens Wiklander TEE_PARAM_TYPE_NONE, 971e8dbd92cSJens Wiklander TEE_PARAM_TYPE_NONE, 972e8dbd92cSJens Wiklander TEE_PARAM_TYPE_NONE); 973e8dbd92cSJens Wiklander struct pkcs11_session *session = NULL; 974e8dbd92cSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 975e8dbd92cSJens Wiklander struct serialargs ctrlargs = { }; 976e8dbd92cSJens Wiklander TEE_Param *ctrl = params; 977e8dbd92cSJens Wiklander uint32_t pin_size = 0; 978e8dbd92cSJens Wiklander void *pin = NULL; 979e8dbd92cSJens Wiklander 980e8dbd92cSJens Wiklander if (!client || ptypes != exp_pt) 981e8dbd92cSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 982e8dbd92cSJens Wiklander 983e8dbd92cSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 984e8dbd92cSJens Wiklander 985f40f331fSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 986e8dbd92cSJens Wiklander if (rc) 987e8dbd92cSJens Wiklander return rc; 988e8dbd92cSJens Wiklander 989e8dbd92cSJens Wiklander rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); 990e8dbd92cSJens Wiklander if (rc) 991e8dbd92cSJens Wiklander return rc; 992e8dbd92cSJens Wiklander 993e8dbd92cSJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); 994e8dbd92cSJens Wiklander if (rc) 995e8dbd92cSJens Wiklander return rc; 996e8dbd92cSJens Wiklander 997e8dbd92cSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 998e8dbd92cSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 999e8dbd92cSJens Wiklander 1000e8dbd92cSJens Wiklander if (!pkcs11_session_is_so(session)) 1001e8dbd92cSJens Wiklander return PKCS11_CKR_USER_NOT_LOGGED_IN; 1002e8dbd92cSJens Wiklander 1003e8dbd92cSJens Wiklander assert(session->token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED); 1004e8dbd92cSJens Wiklander 1005f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": init PIN", session->handle); 1006e8dbd92cSJens Wiklander 1007e8dbd92cSJens Wiklander return set_pin(session, pin, pin_size, PKCS11_CKU_USER); 1008e8dbd92cSJens Wiklander } 10091dbb91e7SJens Wiklander 10104daf39b3SJens Wiklander static enum pkcs11_rc check_so_pin(struct pkcs11_session *session, 10111dbb91e7SJens Wiklander uint8_t *pin, size_t pin_size) 10121dbb91e7SJens Wiklander { 10131dbb91e7SJens Wiklander struct ck_token *token = session->token; 10141dbb91e7SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 10151dbb91e7SJens Wiklander 10161dbb91e7SJens Wiklander assert(token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED); 10171dbb91e7SJens Wiklander 10181dbb91e7SJens Wiklander if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) 10191dbb91e7SJens Wiklander return PKCS11_CKR_PIN_LOCKED; 10201dbb91e7SJens Wiklander 10211dbb91e7SJens Wiklander rc = verify_pin(PKCS11_CKU_SO, pin, pin_size, 10221dbb91e7SJens Wiklander token->db_main->so_pin_salt, 10231dbb91e7SJens Wiklander token->db_main->so_pin_hash); 10241dbb91e7SJens Wiklander if (rc) { 10251dbb91e7SJens Wiklander unsigned int pin_count = 0; 10261dbb91e7SJens Wiklander 10271dbb91e7SJens Wiklander if (rc != PKCS11_CKR_PIN_INCORRECT) 10281dbb91e7SJens Wiklander return rc; 10291dbb91e7SJens Wiklander 10301dbb91e7SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW; 10311dbb91e7SJens Wiklander token->db_main->so_pin_count++; 10321dbb91e7SJens Wiklander 10331dbb91e7SJens Wiklander pin_count = token->db_main->so_pin_count; 10341dbb91e7SJens Wiklander if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) 10351dbb91e7SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY; 10361dbb91e7SJens Wiklander if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX) 10371dbb91e7SJens Wiklander token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED; 10381dbb91e7SJens Wiklander 10391dbb91e7SJens Wiklander update_persistent_db(token); 10401dbb91e7SJens Wiklander 10411dbb91e7SJens Wiklander if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) 10421dbb91e7SJens Wiklander return PKCS11_CKR_PIN_LOCKED; 10431dbb91e7SJens Wiklander 10441dbb91e7SJens Wiklander return PKCS11_CKR_PIN_INCORRECT; 10451dbb91e7SJens Wiklander } 10461dbb91e7SJens Wiklander 10471dbb91e7SJens Wiklander if (token->db_main->so_pin_count) { 10481dbb91e7SJens Wiklander token->db_main->so_pin_count = 0; 10491dbb91e7SJens Wiklander 10501dbb91e7SJens Wiklander update_persistent_db(token); 10511dbb91e7SJens Wiklander } 10521dbb91e7SJens Wiklander 10531dbb91e7SJens Wiklander if (token->db_main->flags & (PKCS11_CKFT_SO_PIN_COUNT_LOW | 10541dbb91e7SJens Wiklander PKCS11_CKFT_SO_PIN_FINAL_TRY)) { 10551dbb91e7SJens Wiklander token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW | 10561dbb91e7SJens Wiklander PKCS11_CKFT_SO_PIN_FINAL_TRY); 10571dbb91e7SJens Wiklander 10581dbb91e7SJens Wiklander update_persistent_db(token); 10591dbb91e7SJens Wiklander } 10601dbb91e7SJens Wiklander 10611dbb91e7SJens Wiklander return PKCS11_CKR_OK; 10621dbb91e7SJens Wiklander } 10631dbb91e7SJens Wiklander 10644daf39b3SJens Wiklander static enum pkcs11_rc check_user_pin(struct pkcs11_session *session, 10651dbb91e7SJens Wiklander uint8_t *pin, size_t pin_size) 10661dbb91e7SJens Wiklander { 10671dbb91e7SJens Wiklander struct ck_token *token = session->token; 10681dbb91e7SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 10691dbb91e7SJens Wiklander 10701dbb91e7SJens Wiklander if (!token->db_main->user_pin_salt) 10711dbb91e7SJens Wiklander return PKCS11_CKR_USER_PIN_NOT_INITIALIZED; 10721dbb91e7SJens Wiklander 10731dbb91e7SJens Wiklander if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED) 10741dbb91e7SJens Wiklander return PKCS11_CKR_PIN_LOCKED; 10751dbb91e7SJens Wiklander 10761dbb91e7SJens Wiklander rc = verify_pin(PKCS11_CKU_USER, pin, pin_size, 10771dbb91e7SJens Wiklander token->db_main->user_pin_salt, 10781dbb91e7SJens Wiklander token->db_main->user_pin_hash); 10791dbb91e7SJens Wiklander if (rc) { 10801dbb91e7SJens Wiklander unsigned int pin_count = 0; 10811dbb91e7SJens Wiklander 10821dbb91e7SJens Wiklander if (rc != PKCS11_CKR_PIN_INCORRECT) 10831dbb91e7SJens Wiklander return rc; 10841dbb91e7SJens Wiklander 10851dbb91e7SJens Wiklander token->db_main->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW; 10861dbb91e7SJens Wiklander token->db_main->user_pin_count++; 10871dbb91e7SJens Wiklander 10881dbb91e7SJens Wiklander pin_count = token->db_main->user_pin_count; 10891dbb91e7SJens Wiklander if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1) 10901dbb91e7SJens Wiklander token->db_main->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY; 10911dbb91e7SJens Wiklander if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX) 10921dbb91e7SJens Wiklander token->db_main->flags |= PKCS11_CKFT_USER_PIN_LOCKED; 10931dbb91e7SJens Wiklander 10941dbb91e7SJens Wiklander update_persistent_db(token); 10951dbb91e7SJens Wiklander 10961dbb91e7SJens Wiklander if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED) 10971dbb91e7SJens Wiklander return PKCS11_CKR_PIN_LOCKED; 10981dbb91e7SJens Wiklander 10991dbb91e7SJens Wiklander return PKCS11_CKR_PIN_INCORRECT; 11001dbb91e7SJens Wiklander } 11011dbb91e7SJens Wiklander 11021dbb91e7SJens Wiklander if (token->db_main->user_pin_count) { 11031dbb91e7SJens Wiklander token->db_main->user_pin_count = 0; 11041dbb91e7SJens Wiklander 11051dbb91e7SJens Wiklander update_persistent_db(token); 11061dbb91e7SJens Wiklander } 11071dbb91e7SJens Wiklander 11081dbb91e7SJens Wiklander if (token->db_main->flags & (PKCS11_CKFT_USER_PIN_COUNT_LOW | 11091dbb91e7SJens Wiklander PKCS11_CKFT_USER_PIN_FINAL_TRY)) { 11101dbb91e7SJens Wiklander token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_COUNT_LOW | 11111dbb91e7SJens Wiklander PKCS11_CKFT_USER_PIN_FINAL_TRY); 11121dbb91e7SJens Wiklander 11131dbb91e7SJens Wiklander update_persistent_db(token); 11141dbb91e7SJens Wiklander } 11151dbb91e7SJens Wiklander 11161dbb91e7SJens Wiklander return PKCS11_CKR_OK; 11171dbb91e7SJens Wiklander } 11181dbb91e7SJens Wiklander 11194daf39b3SJens Wiklander enum pkcs11_rc entry_ck_set_pin(struct pkcs11_client *client, 11201dbb91e7SJens Wiklander uint32_t ptypes, TEE_Param *params) 11211dbb91e7SJens Wiklander { 11221dbb91e7SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 11231dbb91e7SJens Wiklander TEE_PARAM_TYPE_NONE, 11241dbb91e7SJens Wiklander TEE_PARAM_TYPE_NONE, 11251dbb91e7SJens Wiklander TEE_PARAM_TYPE_NONE); 11261dbb91e7SJens Wiklander struct pkcs11_session *session = NULL; 11271dbb91e7SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 11281dbb91e7SJens Wiklander struct serialargs ctrlargs = { }; 11291dbb91e7SJens Wiklander uint32_t old_pin_size = 0; 11301dbb91e7SJens Wiklander TEE_Param *ctrl = params; 11311dbb91e7SJens Wiklander uint32_t pin_size = 0; 11321dbb91e7SJens Wiklander void *old_pin = NULL; 11331dbb91e7SJens Wiklander void *pin = NULL; 11341dbb91e7SJens Wiklander 11351dbb91e7SJens Wiklander if (!client || ptypes != exp_pt) 11361dbb91e7SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 11371dbb91e7SJens Wiklander 11381dbb91e7SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 11391dbb91e7SJens Wiklander 1140f40f331fSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 11411dbb91e7SJens Wiklander if (rc) 11421dbb91e7SJens Wiklander return rc; 11431dbb91e7SJens Wiklander 11441dbb91e7SJens Wiklander rc = serialargs_get(&ctrlargs, &old_pin_size, sizeof(uint32_t)); 11451dbb91e7SJens Wiklander if (rc) 11461dbb91e7SJens Wiklander return rc; 11471dbb91e7SJens Wiklander 11481dbb91e7SJens Wiklander rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); 11491dbb91e7SJens Wiklander if (rc) 11501dbb91e7SJens Wiklander return rc; 11511dbb91e7SJens Wiklander 11521dbb91e7SJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &old_pin, old_pin_size); 11531dbb91e7SJens Wiklander if (rc) 11541dbb91e7SJens Wiklander return rc; 11551dbb91e7SJens Wiklander 11561dbb91e7SJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); 11571dbb91e7SJens Wiklander if (rc) 11581dbb91e7SJens Wiklander return rc; 11591dbb91e7SJens Wiklander 11601dbb91e7SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 11611dbb91e7SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 11621dbb91e7SJens Wiklander 11631dbb91e7SJens Wiklander if (!pkcs11_session_is_read_write(session)) 11641dbb91e7SJens Wiklander return PKCS11_CKR_SESSION_READ_ONLY; 11651dbb91e7SJens Wiklander 11661dbb91e7SJens Wiklander if (pkcs11_session_is_so(session)) { 11671dbb91e7SJens Wiklander if (!(session->token->db_main->flags & 11681dbb91e7SJens Wiklander PKCS11_CKFT_TOKEN_INITIALIZED)) 11691dbb91e7SJens Wiklander return PKCS11_CKR_GENERAL_ERROR; 11701dbb91e7SJens Wiklander 11711dbb91e7SJens Wiklander rc = check_so_pin(session, old_pin, old_pin_size); 11721dbb91e7SJens Wiklander if (rc) 11731dbb91e7SJens Wiklander return rc; 11741dbb91e7SJens Wiklander 1175f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": set PIN", session->handle); 11761dbb91e7SJens Wiklander 11771dbb91e7SJens Wiklander return set_pin(session, pin, pin_size, PKCS11_CKU_SO); 11781dbb91e7SJens Wiklander } 11791dbb91e7SJens Wiklander 11801dbb91e7SJens Wiklander if (!(session->token->db_main->flags & 11811dbb91e7SJens Wiklander PKCS11_CKFT_USER_PIN_INITIALIZED)) 11821dbb91e7SJens Wiklander return PKCS11_CKR_GENERAL_ERROR; 11831dbb91e7SJens Wiklander 11841dbb91e7SJens Wiklander rc = check_user_pin(session, old_pin, old_pin_size); 11851dbb91e7SJens Wiklander if (rc) 11861dbb91e7SJens Wiklander return rc; 11871dbb91e7SJens Wiklander 1188f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": set PIN", session->handle); 11891dbb91e7SJens Wiklander 11901dbb91e7SJens Wiklander return set_pin(session, pin, pin_size, PKCS11_CKU_USER); 11911dbb91e7SJens Wiklander } 1192f7cc36c0SJens Wiklander 1193f7cc36c0SJens Wiklander static void session_login_user(struct pkcs11_session *session) 1194f7cc36c0SJens Wiklander { 1195f7cc36c0SJens Wiklander struct pkcs11_client *client = session->client; 1196f7cc36c0SJens Wiklander struct pkcs11_session *sess = NULL; 1197f7cc36c0SJens Wiklander 1198f7cc36c0SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link) { 1199f7cc36c0SJens Wiklander if (sess->token != session->token) 1200f7cc36c0SJens Wiklander continue; 1201f7cc36c0SJens Wiklander 1202f7cc36c0SJens Wiklander if (pkcs11_session_is_read_write(sess)) 1203f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RW_USER_FUNCTIONS; 1204f7cc36c0SJens Wiklander else 1205f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RO_USER_FUNCTIONS; 1206f7cc36c0SJens Wiklander } 1207f7cc36c0SJens Wiklander } 1208f7cc36c0SJens Wiklander 1209f7cc36c0SJens Wiklander static void session_login_so(struct pkcs11_session *session) 1210f7cc36c0SJens Wiklander { 1211f7cc36c0SJens Wiklander struct pkcs11_client *client = session->client; 1212f7cc36c0SJens Wiklander struct pkcs11_session *sess = NULL; 1213f7cc36c0SJens Wiklander 1214f7cc36c0SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link) { 1215f7cc36c0SJens Wiklander if (sess->token != session->token) 1216f7cc36c0SJens Wiklander continue; 1217f7cc36c0SJens Wiklander 1218f7cc36c0SJens Wiklander if (pkcs11_session_is_read_write(sess)) 1219f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RW_SO_FUNCTIONS; 1220f7cc36c0SJens Wiklander else 1221f7cc36c0SJens Wiklander TEE_Panic(0); 1222f7cc36c0SJens Wiklander } 1223f7cc36c0SJens Wiklander } 1224f7cc36c0SJens Wiklander 1225f7cc36c0SJens Wiklander static void session_logout(struct pkcs11_session *session) 1226f7cc36c0SJens Wiklander { 1227f7cc36c0SJens Wiklander struct pkcs11_client *client = session->client; 1228f7cc36c0SJens Wiklander struct pkcs11_session *sess = NULL; 1229f7cc36c0SJens Wiklander 1230f7cc36c0SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link) { 1231f7cc36c0SJens Wiklander if (sess->token != session->token) 1232f7cc36c0SJens Wiklander continue; 1233f7cc36c0SJens Wiklander 1234f7cc36c0SJens Wiklander if (pkcs11_session_is_read_write(sess)) 1235f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RW_PUBLIC_SESSION; 1236f7cc36c0SJens Wiklander else 1237f7cc36c0SJens Wiklander sess->state = PKCS11_CKS_RO_PUBLIC_SESSION; 1238f7cc36c0SJens Wiklander } 1239f7cc36c0SJens Wiklander } 1240f7cc36c0SJens Wiklander 12414daf39b3SJens Wiklander enum pkcs11_rc entry_ck_login(struct pkcs11_client *client, 1242f7cc36c0SJens Wiklander uint32_t ptypes, TEE_Param *params) 1243f7cc36c0SJens Wiklander { 1244f7cc36c0SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 1245f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE, 1246f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE, 1247f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE); 1248f7cc36c0SJens Wiklander struct pkcs11_session *session = NULL; 1249f7cc36c0SJens Wiklander struct pkcs11_session *sess = NULL; 1250f7cc36c0SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 1251f7cc36c0SJens Wiklander struct serialargs ctrlargs = { }; 1252f7cc36c0SJens Wiklander TEE_Param *ctrl = params; 1253f7cc36c0SJens Wiklander uint32_t user_type = 0; 1254f7cc36c0SJens Wiklander uint32_t pin_size = 0; 1255f7cc36c0SJens Wiklander void *pin = NULL; 1256f7cc36c0SJens Wiklander 1257f7cc36c0SJens Wiklander if (!client || ptypes != exp_pt) 1258f7cc36c0SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 1259f7cc36c0SJens Wiklander 1260f7cc36c0SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 1261f7cc36c0SJens Wiklander 1262f40f331fSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 1263f7cc36c0SJens Wiklander if (rc) 1264f7cc36c0SJens Wiklander return rc; 1265f7cc36c0SJens Wiklander 1266f7cc36c0SJens Wiklander rc = serialargs_get(&ctrlargs, &user_type, sizeof(uint32_t)); 1267f7cc36c0SJens Wiklander if (rc) 1268f7cc36c0SJens Wiklander return rc; 1269f7cc36c0SJens Wiklander 1270f7cc36c0SJens Wiklander rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); 1271f7cc36c0SJens Wiklander if (rc) 1272f7cc36c0SJens Wiklander return rc; 1273f7cc36c0SJens Wiklander 1274f7cc36c0SJens Wiklander rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); 1275f7cc36c0SJens Wiklander if (rc) 1276f7cc36c0SJens Wiklander return rc; 1277f7cc36c0SJens Wiklander 1278f7cc36c0SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 1279f7cc36c0SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 1280f7cc36c0SJens Wiklander 1281f7cc36c0SJens Wiklander switch (user_type) { 1282f7cc36c0SJens Wiklander case PKCS11_CKU_SO: 1283f7cc36c0SJens Wiklander if (pkcs11_session_is_so(session)) 1284f7cc36c0SJens Wiklander return PKCS11_CKR_USER_ALREADY_LOGGED_IN; 1285f7cc36c0SJens Wiklander 1286f7cc36c0SJens Wiklander if (pkcs11_session_is_user(session)) 1287f7cc36c0SJens Wiklander return PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN; 1288f7cc36c0SJens Wiklander 1289f7cc36c0SJens Wiklander TAILQ_FOREACH(sess, &client->session_list, link) 1290f7cc36c0SJens Wiklander if (sess->token == session->token && 1291f7cc36c0SJens Wiklander !pkcs11_session_is_read_write(sess)) 1292f7cc36c0SJens Wiklander return PKCS11_CKR_SESSION_READ_ONLY_EXISTS; 1293f7cc36c0SJens Wiklander 1294f7cc36c0SJens Wiklander /* 1295f7cc36c0SJens Wiklander * This is the point where we could check if another client 1296f7cc36c0SJens Wiklander * has another user or SO logged in. 1297f7cc36c0SJens Wiklander * 1298f7cc36c0SJens Wiklander * The spec says: 1299f7cc36c0SJens Wiklander * CKR_USER_TOO_MANY_TYPES: An attempt was made to have 1300f7cc36c0SJens Wiklander * more distinct users simultaneously logged into the token 1301f7cc36c0SJens Wiklander * than the token and/or library permits. For example, if 1302f7cc36c0SJens Wiklander * some application has an open SO session, and another 1303f7cc36c0SJens Wiklander * application attempts to log the normal user into a 1304f7cc36c0SJens Wiklander * session, the attempt may return this error. It is not 1305f7cc36c0SJens Wiklander * required to, however. Only if the simultaneous distinct 1306f7cc36c0SJens Wiklander * users cannot be supported does C_Login have to return 1307f7cc36c0SJens Wiklander * this value. Note that this error code generalizes to 1308f7cc36c0SJens Wiklander * true multi-user tokens. 1309f7cc36c0SJens Wiklander * 1310f7cc36c0SJens Wiklander * So it's permitted to have another user or SO logged in 1311f7cc36c0SJens Wiklander * from another client. 1312f7cc36c0SJens Wiklander */ 1313f7cc36c0SJens Wiklander 1314f7cc36c0SJens Wiklander rc = check_so_pin(session, pin, pin_size); 1315f7cc36c0SJens Wiklander if (!rc) 1316f7cc36c0SJens Wiklander session_login_so(session); 1317f7cc36c0SJens Wiklander 1318f7cc36c0SJens Wiklander break; 1319f7cc36c0SJens Wiklander 1320f7cc36c0SJens Wiklander case PKCS11_CKU_USER: 1321f7cc36c0SJens Wiklander if (pkcs11_session_is_so(session)) 1322f7cc36c0SJens Wiklander return PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN; 1323f7cc36c0SJens Wiklander 1324f7cc36c0SJens Wiklander if (pkcs11_session_is_user(session)) 1325f7cc36c0SJens Wiklander return PKCS11_CKR_USER_ALREADY_LOGGED_IN; 1326f7cc36c0SJens Wiklander 1327f7cc36c0SJens Wiklander /* 1328f7cc36c0SJens Wiklander * This is the point where we could check if another client 1329f7cc36c0SJens Wiklander * has another user or SO logged in. 1330f7cc36c0SJens Wiklander * See comment on CKR_USER_TOO_MANY_TYPES above. 1331f7cc36c0SJens Wiklander */ 1332f7cc36c0SJens Wiklander 1333f7cc36c0SJens Wiklander rc = check_user_pin(session, pin, pin_size); 1334f7cc36c0SJens Wiklander if (!rc) 1335f7cc36c0SJens Wiklander session_login_user(session); 1336f7cc36c0SJens Wiklander 1337f7cc36c0SJens Wiklander break; 1338f7cc36c0SJens Wiklander 1339f7cc36c0SJens Wiklander case PKCS11_CKU_CONTEXT_SPECIFIC: 1340f7cc36c0SJens Wiklander return PKCS11_CKR_OPERATION_NOT_INITIALIZED; 1341f7cc36c0SJens Wiklander 1342f7cc36c0SJens Wiklander default: 1343f7cc36c0SJens Wiklander return PKCS11_CKR_USER_TYPE_INVALID; 1344f7cc36c0SJens Wiklander } 1345f7cc36c0SJens Wiklander 1346f7cc36c0SJens Wiklander if (!rc) 1347f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": login", session->handle); 1348f7cc36c0SJens Wiklander 1349f7cc36c0SJens Wiklander return rc; 1350f7cc36c0SJens Wiklander } 1351f7cc36c0SJens Wiklander 13524daf39b3SJens Wiklander enum pkcs11_rc entry_ck_logout(struct pkcs11_client *client, 1353f7cc36c0SJens Wiklander uint32_t ptypes, TEE_Param *params) 1354f7cc36c0SJens Wiklander { 1355f7cc36c0SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 1356f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE, 1357f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE, 1358f7cc36c0SJens Wiklander TEE_PARAM_TYPE_NONE); 1359f7cc36c0SJens Wiklander struct pkcs11_session *session = NULL; 1360f7cc36c0SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 1361f7cc36c0SJens Wiklander struct serialargs ctrlargs = { }; 1362f7cc36c0SJens Wiklander TEE_Param *ctrl = params; 1363f7cc36c0SJens Wiklander 1364f7cc36c0SJens Wiklander if (!client || ptypes != exp_pt) 1365f7cc36c0SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 1366f7cc36c0SJens Wiklander 1367f7cc36c0SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 1368f7cc36c0SJens Wiklander 1369f40f331fSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 1370f7cc36c0SJens Wiklander if (rc) 1371f7cc36c0SJens Wiklander return rc; 1372f7cc36c0SJens Wiklander 1373f7cc36c0SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 1374f7cc36c0SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 1375f7cc36c0SJens Wiklander 1376f7cc36c0SJens Wiklander if (pkcs11_session_is_public(session)) 1377f7cc36c0SJens Wiklander return PKCS11_CKR_USER_NOT_LOGGED_IN; 1378f7cc36c0SJens Wiklander 1379f7cc36c0SJens Wiklander session_logout(session); 1380f7cc36c0SJens Wiklander 1381f40f331fSEtienne Carriere IMSG("PKCS11 session %"PRIu32": logout", session->handle); 1382f7cc36c0SJens Wiklander 1383f7cc36c0SJens Wiklander return PKCS11_CKR_OK; 1384f7cc36c0SJens Wiklander } 1385