xref: /optee_os/ta/pkcs11/src/processing.c (revision 145ae446b961c32d566596c90d6a9e167c6591e0)
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