1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2017-2020, Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <confine_array_index.h> 8 #include <pkcs11_ta.h> 9 #include <string.h> 10 #include <string_ext.h> 11 #include <sys/queue.h> 12 #include <tee_api_types.h> 13 #include <tee_internal_api_extensions.h> 14 #include <util.h> 15 16 #include "pkcs11_token.h" 17 #include "pkcs11_helpers.h" 18 #include "serializer.h" 19 20 /* Provide 3 slots/tokens, ID is token index */ 21 #ifndef CFG_PKCS11_TA_TOKEN_COUNT 22 #define TOKEN_COUNT 3 23 #else 24 #define TOKEN_COUNT CFG_PKCS11_TA_TOKEN_COUNT 25 #endif 26 27 /* Static allocation of tokens runtime instances (reset to 0 at load) */ 28 struct ck_token ck_token[TOKEN_COUNT]; 29 30 struct ck_token *get_token(unsigned int token_id) 31 { 32 if (token_id < TOKEN_COUNT) 33 return &ck_token[confine_array_index(token_id, TOKEN_COUNT)]; 34 35 return NULL; 36 } 37 38 unsigned int get_token_id(struct ck_token *token) 39 { 40 ptrdiff_t id = token - ck_token; 41 42 assert(id >= 0 && id < TOKEN_COUNT); 43 return id; 44 } 45 46 static TEE_Result pkcs11_token_init(unsigned int id) 47 { 48 struct ck_token *token = init_persistent_db(id); 49 50 if (!token) 51 return TEE_ERROR_SECURITY; 52 53 if (token->state == PKCS11_TOKEN_RESET) { 54 /* As per PKCS#11 spec, token resets to read/write state */ 55 token->state = PKCS11_TOKEN_READ_WRITE; 56 token->session_count = 0; 57 token->rw_session_count = 0; 58 } 59 60 return TEE_SUCCESS; 61 } 62 63 TEE_Result pkcs11_init(void) 64 { 65 unsigned int id = 0; 66 TEE_Result ret = TEE_ERROR_GENERIC; 67 68 for (id = 0; id < TOKEN_COUNT; id++) { 69 ret = pkcs11_token_init(id); 70 if (ret) 71 return ret; 72 } 73 74 return ret; 75 } 76 77 void pkcs11_deinit(void) 78 { 79 unsigned int id = 0; 80 81 for (id = 0; id < TOKEN_COUNT; id++) 82 close_persistent_db(get_token(id)); 83 } 84 85 uint32_t entry_ck_slot_list(uint32_t ptypes, TEE_Param *params) 86 { 87 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 88 TEE_PARAM_TYPE_NONE, 89 TEE_PARAM_TYPE_MEMREF_OUTPUT, 90 TEE_PARAM_TYPE_NONE); 91 TEE_Param *out = ¶ms[2]; 92 uint32_t token_id = 0; 93 const size_t out_size = sizeof(token_id) * TOKEN_COUNT; 94 uint8_t *id = NULL; 95 96 if (ptypes != exp_pt || 97 params[0].memref.size != TEE_PARAM0_SIZE_MIN) 98 return PKCS11_CKR_ARGUMENTS_BAD; 99 100 if (out->memref.size < out_size) { 101 out->memref.size = out_size; 102 103 if (out->memref.buffer) 104 return PKCS11_CKR_BUFFER_TOO_SMALL; 105 else 106 return PKCS11_CKR_OK; 107 } 108 109 for (token_id = 0, id = out->memref.buffer; token_id < TOKEN_COUNT; 110 token_id++, id += sizeof(token_id)) 111 TEE_MemMove(id, &token_id, sizeof(token_id)); 112 113 out->memref.size = out_size; 114 115 return PKCS11_CKR_OK; 116 } 117 118 uint32_t entry_ck_slot_info(uint32_t ptypes, TEE_Param *params) 119 { 120 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 121 TEE_PARAM_TYPE_NONE, 122 TEE_PARAM_TYPE_MEMREF_OUTPUT, 123 TEE_PARAM_TYPE_NONE); 124 TEE_Param *ctrl = ¶ms[0]; 125 TEE_Param *out = ¶ms[2]; 126 uint32_t rv = 0; 127 struct serialargs ctrlargs = { }; 128 uint32_t token_id = 0; 129 struct ck_token *token = NULL; 130 struct pkcs11_slot_info info = { 131 .slot_description = PKCS11_SLOT_DESCRIPTION, 132 .manufacturer_id = PKCS11_SLOT_MANUFACTURER, 133 .flags = PKCS11_CKFS_TOKEN_PRESENT, 134 .hardware_version = PKCS11_SLOT_HW_VERSION, 135 .firmware_version = PKCS11_SLOT_FW_VERSION, 136 }; 137 int n = 0; 138 139 COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_DESCRIPTION) <= 140 sizeof(info.slot_description)); 141 COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_MANUFACTURER) <= 142 sizeof(info.manufacturer_id)); 143 144 if (ptypes != exp_pt || out->memref.size != sizeof(info)) 145 return PKCS11_CKR_ARGUMENTS_BAD; 146 147 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 148 149 rv = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); 150 if (rv) 151 return rv; 152 153 if (serialargs_remaining_bytes(&ctrlargs)) 154 return PKCS11_CKR_ARGUMENTS_BAD; 155 156 token = get_token(token_id); 157 if (!token) 158 return PKCS11_CKR_SLOT_ID_INVALID; 159 160 /* Pad string identifiers with blank characters */ 161 n = strnlen((char *)info.slot_description, 162 sizeof(info.slot_description)); 163 TEE_MemFill(&info.slot_description[n], ' ', 164 sizeof(info.slot_description) - n); 165 166 n = strnlen((char *)info.manufacturer_id, 167 sizeof(info.manufacturer_id)); 168 TEE_MemFill(&info.manufacturer_id[n], ' ', 169 sizeof(info.manufacturer_id) - n); 170 171 out->memref.size = sizeof(info); 172 TEE_MemMove(out->memref.buffer, &info, out->memref.size); 173 174 return PKCS11_CKR_OK; 175 } 176