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 if (session->processing->tee_op_handle != TEE_HANDLE_NULL) { 79 TEE_FreeOperation(session->processing->tee_op_handle); 80 session->processing->tee_op_handle = TEE_HANDLE_NULL; 81 } 82 83 TEE_Free(session->processing->extra_ctx); 84 85 TEE_Free(session->processing); 86 session->processing = NULL; 87 } 88 89 size_t get_object_key_bit_size(struct pkcs11_object *obj) 90 { 91 uint32_t a_size = 0; 92 struct obj_attrs *attrs = obj->attributes; 93 94 switch (get_key_type(attrs)) { 95 case PKCS11_CKK_AES: 96 case PKCS11_CKK_GENERIC_SECRET: 97 case PKCS11_CKK_MD5_HMAC: 98 case PKCS11_CKK_SHA_1_HMAC: 99 case PKCS11_CKK_SHA224_HMAC: 100 case PKCS11_CKK_SHA256_HMAC: 101 case PKCS11_CKK_SHA384_HMAC: 102 case PKCS11_CKK_SHA512_HMAC: 103 if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size)) 104 return 0; 105 106 return a_size * 8; 107 default: 108 TEE_Panic(0); 109 return 0; 110 } 111 } 112 113 /* 114 * entry_processing_init - Generic entry for initializing a processing 115 * 116 * @client = client reference 117 * @ptype = Invocation parameter types 118 * @params = Invocation parameters reference 119 * @function - encrypt, decrypt, sign, verify, digest, ... 120 */ 121 enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, 122 uint32_t ptypes, TEE_Param *params, 123 enum processing_func function) 124 { 125 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 126 TEE_PARAM_TYPE_NONE, 127 TEE_PARAM_TYPE_NONE, 128 TEE_PARAM_TYPE_NONE); 129 TEE_Param *ctrl = params; 130 enum pkcs11_rc rc = PKCS11_CKR_OK; 131 struct serialargs ctrlargs = { }; 132 struct pkcs11_session *session = NULL; 133 struct pkcs11_attribute_head *proc_params = NULL; 134 uint32_t key_handle = 0; 135 struct pkcs11_object *obj = NULL; 136 137 if (!client || ptypes != exp_pt) 138 return PKCS11_CKR_ARGUMENTS_BAD; 139 140 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 141 142 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 143 if (rc) 144 return rc; 145 146 rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 147 if (rc) 148 return rc; 149 150 rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 151 if (rc) 152 return rc; 153 154 if (serialargs_remaining_bytes(&ctrlargs)) { 155 rc = PKCS11_CKR_ARGUMENTS_BAD; 156 goto out; 157 } 158 159 rc = get_ready_session(session); 160 if (rc) 161 goto out; 162 163 obj = pkcs11_handle2object(key_handle, session); 164 if (!obj) { 165 rc = PKCS11_CKR_KEY_HANDLE_INVALID; 166 goto out; 167 } 168 169 rc = set_processing_state(session, function, obj, NULL); 170 if (rc) 171 goto out; 172 173 rc = check_mechanism_against_processing(session, proc_params->id, 174 function, 175 PKCS11_FUNC_STEP_INIT); 176 if (rc) 177 goto out; 178 179 rc = check_parent_attrs_against_processing(proc_params->id, function, 180 obj->attributes); 181 if (rc) 182 goto out; 183 184 rc = check_access_attrs_against_token(session, obj->attributes); 185 if (rc) 186 goto out; 187 188 if (processing_is_tee_symm(proc_params->id)) 189 rc = init_symm_operation(session, function, proc_params, obj); 190 else 191 rc = PKCS11_CKR_MECHANISM_INVALID; 192 193 if (rc == PKCS11_CKR_OK) { 194 session->processing->mecha_type = proc_params->id; 195 DMSG("PKCS11 session %"PRIu32": init processing %s %s", 196 session->handle, id2str_proc(proc_params->id), 197 id2str_function(function)); 198 } 199 200 out: 201 if (rc && session) 202 release_active_processing(session); 203 204 TEE_Free(proc_params); 205 206 return rc; 207 } 208 209 /* 210 * entry_processing_step - Generic entry on active processing 211 * 212 * @client = client reference 213 * @ptype = Invocation parameter types 214 * @params = Invocation parameters reference 215 * @function - encrypt, decrypt, sign, verify, digest, ... 216 * @step - update, oneshot, final 217 */ 218 enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, 219 uint32_t ptypes, TEE_Param *params, 220 enum processing_func function, 221 enum processing_step step) 222 { 223 TEE_Param *ctrl = params; 224 enum pkcs11_rc rc = PKCS11_CKR_OK; 225 struct serialargs ctrlargs = { }; 226 struct pkcs11_session *session = NULL; 227 enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; 228 229 if (!client || 230 TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) 231 return PKCS11_CKR_ARGUMENTS_BAD; 232 233 serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 234 235 rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 236 if (rc) 237 return rc; 238 239 if (serialargs_remaining_bytes(&ctrlargs)) 240 return PKCS11_CKR_ARGUMENTS_BAD; 241 242 rc = get_active_session(session, function); 243 if (rc) 244 return rc; 245 246 mecha_type = session->processing->mecha_type; 247 rc = check_mechanism_against_processing(session, mecha_type, 248 function, step); 249 if (rc) 250 goto out; 251 252 if (processing_is_tee_symm(mecha_type)) 253 rc = step_symm_operation(session, function, step, 254 ptypes, params); 255 else 256 rc = PKCS11_CKR_MECHANISM_INVALID; 257 258 if (rc == PKCS11_CKR_OK && step == PKCS11_FUNC_STEP_UPDATE) { 259 session->processing->updated = true; 260 DMSG("PKCS11 session%"PRIu32": processing %s %s", 261 session->handle, id2str_proc(mecha_type), 262 id2str_function(function)); 263 } 264 265 out: 266 switch (step) { 267 case PKCS11_FUNC_STEP_UPDATE: 268 if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL) 269 release_active_processing(session); 270 break; 271 default: 272 /* ONESHOT and FINAL terminates processing on success */ 273 if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) 274 release_active_processing(session); 275 break; 276 } 277 278 return rc; 279 } 280