1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2017-2020, Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <pkcs11_ta.h> 8 #include <string.h> 9 #include <tee_api_defines.h> 10 #include <tee_internal_api.h> 11 #include <tee_internal_api_extensions.h> 12 #include <util.h> 13 14 #include "attributes.h" 15 #include "object.h" 16 #include "pkcs11_attributes.h" 17 #include "pkcs11_helpers.h" 18 #include "pkcs11_token.h" 19 #include "processing.h" 20 #include "serializer.h" 21 22 static enum pkcs11_rc get_ready_session(struct pkcs11_session *session) 23 { 24 if (session_is_active(session)) 25 return PKCS11_CKR_OPERATION_ACTIVE; 26 27 return PKCS11_CKR_OK; 28 } 29 30 static bool func_matches_state(enum processing_func function, 31 enum pkcs11_proc_state state) 32 { 33 switch (function) { 34 case PKCS11_FUNCTION_ENCRYPT: 35 return state == PKCS11_SESSION_ENCRYPTING || 36 state == PKCS11_SESSION_DIGESTING_ENCRYPTING || 37 state == PKCS11_SESSION_SIGNING_ENCRYPTING; 38 case PKCS11_FUNCTION_DECRYPT: 39 return state == PKCS11_SESSION_DECRYPTING || 40 state == PKCS11_SESSION_DECRYPTING_DIGESTING || 41 state == PKCS11_SESSION_DECRYPTING_VERIFYING; 42 case PKCS11_FUNCTION_DIGEST: 43 return state == PKCS11_SESSION_DIGESTING || 44 state == PKCS11_SESSION_DIGESTING_ENCRYPTING; 45 case PKCS11_FUNCTION_SIGN: 46 return state == PKCS11_SESSION_SIGNING || 47 state == PKCS11_SESSION_SIGNING_ENCRYPTING; 48 case PKCS11_FUNCTION_VERIFY: 49 return state == PKCS11_SESSION_VERIFYING || 50 state == PKCS11_SESSION_DECRYPTING_VERIFYING; 51 case PKCS11_FUNCTION_SIGN_RECOVER: 52 return state == PKCS11_SESSION_SIGNING_RECOVER; 53 case PKCS11_FUNCTION_VERIFY_RECOVER: 54 return state == PKCS11_SESSION_SIGNING_RECOVER; 55 default: 56 TEE_Panic(function); 57 return false; 58 } 59 } 60 61 static enum pkcs11_rc get_active_session(struct pkcs11_session *session, 62 enum processing_func function) 63 { 64 enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED; 65 66 if (session->processing && 67 func_matches_state(function, session->processing->state)) 68 rc = PKCS11_CKR_OK; 69 70 return rc; 71 } 72 73 void release_active_processing(struct pkcs11_session *session) 74 { 75 if (!session->processing) 76 return; 77 78 switch (session->processing->mecha_type) { 79 case PKCS11_CKM_AES_CTR: 80 tee_release_ctr_operation(session->processing); 81 break; 82 default: 83 break; 84 } 85 86 if (session->processing->tee_op_handle != TEE_HANDLE_NULL) { 87 TEE_FreeOperation(session->processing->tee_op_handle); 88 session->processing->tee_op_handle = TEE_HANDLE_NULL; 89 } 90 91 TEE_Free(session->processing); 92 session->processing = NULL; 93 } 94 95 size_t get_object_key_bit_size(struct pkcs11_object *obj) 96 { 97 uint32_t a_size = 0; 98 struct obj_attrs *attrs = obj->attributes; 99 100 switch (get_key_type(attrs)) { 101 case PKCS11_CKK_AES: 102 if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size)) 103 return 0; 104 105 return a_size * 8; 106 default: 107 TEE_Panic(0); 108 return 0; 109 } 110 } 111 112 /* 113 * entry_processing_init - Generic entry for initializing a processing 114 * 115 * @client = client reference 116 * @ptype = Invocation parameter types 117 * @params = Invocation parameters reference 118 * @function - encrypt, decrypt, sign, verify, digest, ... 119 */ 120 enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, 121 uint32_t ptypes, TEE_Param *params, 122 enum processing_func function) 123 { 124 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 125 TEE_PARAM_TYPE_NONE, 126 TEE_PARAM_TYPE_NONE, 127 TEE_PARAM_TYPE_NONE); 128 TEE_Param *ctrl = params; 129 enum pkcs11_rc rc = PKCS11_CKR_OK; 130 struct serialargs ctrlargs = { }; 131 struct pkcs11_session *session = NULL; 132 struct pkcs11_attribute_head *proc_params = NULL; 133 uint32_t key_handle = 0; 134 struct pkcs11_object *obj = NULL; 135 136 if (!client || ptypes != exp_pt) 137 return PKCS11_CKR_ARGUMENTS_BAD; 138 139 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 140 141 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 142 if (rc) 143 return rc; 144 145 rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 146 if (rc) 147 return rc; 148 149 rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 150 if (rc) 151 return rc; 152 153 if (serialargs_remaining_bytes(&ctrlargs)) { 154 rc = PKCS11_CKR_ARGUMENTS_BAD; 155 goto out; 156 } 157 158 rc = get_ready_session(session); 159 if (rc) 160 goto out; 161 162 obj = pkcs11_handle2object(key_handle, session); 163 if (!obj) { 164 rc = PKCS11_CKR_KEY_HANDLE_INVALID; 165 goto out; 166 } 167 168 rc = set_processing_state(session, function, obj, NULL); 169 if (rc) 170 goto out; 171 172 rc = check_mechanism_against_processing(session, proc_params->id, 173 function, 174 PKCS11_FUNC_STEP_INIT); 175 if (rc) 176 goto out; 177 178 rc = check_parent_attrs_against_processing(proc_params->id, function, 179 obj->attributes); 180 if (rc) 181 goto out; 182 183 rc = check_access_attrs_against_token(session, obj->attributes); 184 if (rc) 185 goto out; 186 187 if (processing_is_tee_symm(proc_params->id)) 188 rc = init_symm_operation(session, function, proc_params, obj); 189 else 190 rc = PKCS11_CKR_MECHANISM_INVALID; 191 192 if (rc == PKCS11_CKR_OK) { 193 session->processing->mecha_type = proc_params->id; 194 DMSG("PKCS11 session %"PRIu32": init processing %s %s", 195 session->handle, id2str_proc(proc_params->id), 196 id2str_function(function)); 197 } 198 199 out: 200 if (rc && session) 201 release_active_processing(session); 202 203 TEE_Free(proc_params); 204 205 return rc; 206 } 207 208 /* 209 * entry_processing_step - Generic entry on active processing 210 * 211 * @client = client reference 212 * @ptype = Invocation parameter types 213 * @params = Invocation parameters reference 214 * @function - encrypt, decrypt, sign, verify, digest, ... 215 * @step - update, oneshot, final 216 */ 217 enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, 218 uint32_t ptypes, TEE_Param *params, 219 enum processing_func function, 220 enum processing_step step) 221 { 222 TEE_Param *ctrl = params; 223 enum pkcs11_rc rc = PKCS11_CKR_OK; 224 struct serialargs ctrlargs = { }; 225 struct pkcs11_session *session = NULL; 226 enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; 227 228 if (!client || 229 TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) 230 return PKCS11_CKR_ARGUMENTS_BAD; 231 232 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 233 234 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 235 if (rc) 236 return rc; 237 238 if (serialargs_remaining_bytes(&ctrlargs)) 239 return PKCS11_CKR_ARGUMENTS_BAD; 240 241 rc = get_active_session(session, function); 242 if (rc) 243 return rc; 244 245 mecha_type = session->processing->mecha_type; 246 rc = check_mechanism_against_processing(session, mecha_type, 247 function, step); 248 if (rc) 249 goto out; 250 251 if (processing_is_tee_symm(mecha_type)) 252 rc = step_symm_operation(session, function, step, 253 ptypes, params); 254 else 255 rc = PKCS11_CKR_MECHANISM_INVALID; 256 257 if (rc == PKCS11_CKR_OK) { 258 session->processing->updated = true; 259 DMSG("PKCS11 session%"PRIu32": processing %s %s", 260 session->handle, id2str_proc(mecha_type), 261 id2str_function(function)); 262 } 263 264 out: 265 switch (step) { 266 case PKCS11_FUNC_STEP_UPDATE: 267 if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL) 268 release_active_processing(session); 269 break; 270 default: 271 /* ONESHOT and FINAL terminates processing on success */ 272 if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) 273 release_active_processing(session); 274 break; 275 } 276 277 return rc; 278 } 279 280 /* 281 * entry_verify_oneshot - Run a single part verification processing 282 * 283 * @client = client reference 284 * @ptype = Invocation parameter types 285 * @params = Invocation parameters reference 286 * @function - encrypt, decrypt, sign, verify, digest, ... 287 * @step - update, oneshot, final 288 */ 289 enum pkcs11_rc entry_verify_oneshot(struct pkcs11_client *client, 290 uint32_t ptypes, TEE_Param *params, 291 enum processing_func function, 292 enum processing_step step) 293 294 { 295 TEE_Param *ctrl = params; 296 enum pkcs11_rc rc = PKCS11_CKR_OK; 297 struct serialargs ctrlargs = { }; 298 struct pkcs11_session *session = NULL; 299 enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; 300 301 assert(function == PKCS11_FUNCTION_VERIFY); 302 if (!client || 303 TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) 304 return PKCS11_CKR_ARGUMENTS_BAD; 305 306 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 307 308 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 309 if (rc) 310 return rc; 311 312 if (serialargs_remaining_bytes(&ctrlargs)) 313 return PKCS11_CKR_ARGUMENTS_BAD; 314 315 rc = get_active_session(session, function); 316 if (rc) 317 return rc; 318 319 mecha_type = session->processing->mecha_type; 320 rc = check_mechanism_against_processing(session, mecha_type, 321 function, step); 322 if (rc) 323 goto out; 324 325 if (processing_is_tee_symm(mecha_type)) 326 rc = step_symm_operation(session, function, step, 327 ptypes, params); 328 else 329 rc = PKCS11_CKR_MECHANISM_INVALID; 330 331 DMSG("PKCS11 session %"PRIu32": verify %s %s: %s", session->handle, 332 id2str_proc(mecha_type), id2str_function(function), 333 id2str_rc(rc)); 334 335 out: 336 if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) 337 release_active_processing(session); 338 339 return rc; 340 } 341