xref: /optee_os/ta/pkcs11/src/processing_symm.c (revision 512cbf1d30ddce3513abf2b08d4063d5c8415a40)
1*512cbf1dSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2*512cbf1dSJens Wiklander /*
3*512cbf1dSJens Wiklander  * Copyright (c) 2017-2020, Linaro Limited
4*512cbf1dSJens Wiklander  */
5*512cbf1dSJens Wiklander 
6*512cbf1dSJens Wiklander #include <assert.h>
7*512cbf1dSJens Wiklander #include <pkcs11_ta.h>
8*512cbf1dSJens Wiklander #include <string.h>
9*512cbf1dSJens Wiklander #include <tee_api_defines.h>
10*512cbf1dSJens Wiklander #include <tee_internal_api.h>
11*512cbf1dSJens Wiklander #include <tee_internal_api_extensions.h>
12*512cbf1dSJens Wiklander #include <utee_defines.h>
13*512cbf1dSJens Wiklander #include <util.h>
14*512cbf1dSJens Wiklander 
15*512cbf1dSJens Wiklander #include "attributes.h"
16*512cbf1dSJens Wiklander #include "object.h"
17*512cbf1dSJens Wiklander #include "pkcs11_attributes.h"
18*512cbf1dSJens Wiklander #include "pkcs11_helpers.h"
19*512cbf1dSJens Wiklander #include "pkcs11_token.h"
20*512cbf1dSJens Wiklander #include "processing.h"
21*512cbf1dSJens Wiklander #include "serializer.h"
22*512cbf1dSJens Wiklander 
23*512cbf1dSJens Wiklander bool processing_is_tee_symm(enum pkcs11_mechanism_id proc_id)
24*512cbf1dSJens Wiklander {
25*512cbf1dSJens Wiklander 	switch (proc_id) {
26*512cbf1dSJens Wiklander 	/* Cipherering */
27*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
28*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
29*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC_PAD:
30*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
31*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
32*512cbf1dSJens Wiklander 		return true;
33*512cbf1dSJens Wiklander 	default:
34*512cbf1dSJens Wiklander 		return false;
35*512cbf1dSJens Wiklander 	}
36*512cbf1dSJens Wiklander }
37*512cbf1dSJens Wiklander 
38*512cbf1dSJens Wiklander static enum pkcs11_rc
39*512cbf1dSJens Wiklander pkcs2tee_algorithm(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params)
40*512cbf1dSJens Wiklander {
41*512cbf1dSJens Wiklander 	static const struct {
42*512cbf1dSJens Wiklander 		enum pkcs11_mechanism_id mech_id;
43*512cbf1dSJens Wiklander 		uint32_t tee_id;
44*512cbf1dSJens Wiklander 	} pkcs2tee_algo[] = {
45*512cbf1dSJens Wiklander 		/* AES flavors */
46*512cbf1dSJens Wiklander 		{ PKCS11_CKM_AES_ECB, TEE_ALG_AES_ECB_NOPAD },
47*512cbf1dSJens Wiklander 		{ PKCS11_CKM_AES_CBC, TEE_ALG_AES_CBC_NOPAD },
48*512cbf1dSJens Wiklander 		{ PKCS11_CKM_AES_CBC_PAD, TEE_ALG_AES_CBC_NOPAD },
49*512cbf1dSJens Wiklander 		{ PKCS11_CKM_AES_CTR, TEE_ALG_AES_CTR },
50*512cbf1dSJens Wiklander 		{ PKCS11_CKM_AES_CTS, TEE_ALG_AES_CTS },
51*512cbf1dSJens Wiklander 	};
52*512cbf1dSJens Wiklander 	size_t n = 0;
53*512cbf1dSJens Wiklander 
54*512cbf1dSJens Wiklander 	for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) {
55*512cbf1dSJens Wiklander 		if (proc_params->id == pkcs2tee_algo[n].mech_id) {
56*512cbf1dSJens Wiklander 			*tee_id = pkcs2tee_algo[n].tee_id;
57*512cbf1dSJens Wiklander 			return PKCS11_CKR_OK;
58*512cbf1dSJens Wiklander 		}
59*512cbf1dSJens Wiklander 	}
60*512cbf1dSJens Wiklander 
61*512cbf1dSJens Wiklander 	return PKCS11_RV_NOT_IMPLEMENTED;
62*512cbf1dSJens Wiklander }
63*512cbf1dSJens Wiklander 
64*512cbf1dSJens Wiklander static enum pkcs11_rc pkcs2tee_key_type(uint32_t *tee_type,
65*512cbf1dSJens Wiklander 					struct pkcs11_object *obj)
66*512cbf1dSJens Wiklander {
67*512cbf1dSJens Wiklander 	static const struct {
68*512cbf1dSJens Wiklander 		enum pkcs11_key_type key_type;
69*512cbf1dSJens Wiklander 		uint32_t tee_id;
70*512cbf1dSJens Wiklander 	} pkcs2tee_key_type[] = {
71*512cbf1dSJens Wiklander 		{ PKCS11_CKK_AES, TEE_TYPE_AES },
72*512cbf1dSJens Wiklander 		{ PKCS11_CKK_GENERIC_SECRET, TEE_TYPE_GENERIC_SECRET },
73*512cbf1dSJens Wiklander 		{ PKCS11_CKK_MD5_HMAC, TEE_TYPE_HMAC_MD5 },
74*512cbf1dSJens Wiklander 		{ PKCS11_CKK_SHA_1_HMAC, TEE_TYPE_HMAC_SHA1 },
75*512cbf1dSJens Wiklander 		{ PKCS11_CKK_SHA224_HMAC, TEE_TYPE_HMAC_SHA224 },
76*512cbf1dSJens Wiklander 		{ PKCS11_CKK_SHA256_HMAC, TEE_TYPE_HMAC_SHA256 },
77*512cbf1dSJens Wiklander 		{ PKCS11_CKK_SHA384_HMAC, TEE_TYPE_HMAC_SHA384 },
78*512cbf1dSJens Wiklander 		{ PKCS11_CKK_SHA512_HMAC, TEE_TYPE_HMAC_SHA512 },
79*512cbf1dSJens Wiklander 	};
80*512cbf1dSJens Wiklander 	size_t n = 0;
81*512cbf1dSJens Wiklander 	enum pkcs11_key_type key_type = get_key_type(obj->attributes);
82*512cbf1dSJens Wiklander 
83*512cbf1dSJens Wiklander 	assert(get_class(obj->attributes) == PKCS11_CKO_SECRET_KEY);
84*512cbf1dSJens Wiklander 
85*512cbf1dSJens Wiklander 	for (n = 0; n < ARRAY_SIZE(pkcs2tee_key_type); n++) {
86*512cbf1dSJens Wiklander 		if (pkcs2tee_key_type[n].key_type == key_type) {
87*512cbf1dSJens Wiklander 			*tee_type = pkcs2tee_key_type[n].tee_id;
88*512cbf1dSJens Wiklander 			return PKCS11_CKR_OK;
89*512cbf1dSJens Wiklander 		}
90*512cbf1dSJens Wiklander 	}
91*512cbf1dSJens Wiklander 
92*512cbf1dSJens Wiklander 	return PKCS11_RV_NOT_FOUND;
93*512cbf1dSJens Wiklander }
94*512cbf1dSJens Wiklander 
95*512cbf1dSJens Wiklander static enum pkcs11_rc
96*512cbf1dSJens Wiklander allocate_tee_operation(struct pkcs11_session *session,
97*512cbf1dSJens Wiklander 		       enum processing_func function,
98*512cbf1dSJens Wiklander 		       struct pkcs11_attribute_head *params,
99*512cbf1dSJens Wiklander 		       struct pkcs11_object *obj)
100*512cbf1dSJens Wiklander {
101*512cbf1dSJens Wiklander 	uint32_t size = (uint32_t)get_object_key_bit_size(obj);
102*512cbf1dSJens Wiklander 	uint32_t algo = 0;
103*512cbf1dSJens Wiklander 	uint32_t mode = 0;
104*512cbf1dSJens Wiklander 	TEE_Result res = TEE_ERROR_GENERIC;
105*512cbf1dSJens Wiklander 
106*512cbf1dSJens Wiklander 	assert(session->processing->tee_op_handle == TEE_HANDLE_NULL);
107*512cbf1dSJens Wiklander 
108*512cbf1dSJens Wiklander 	if (pkcs2tee_algorithm(&algo, params))
109*512cbf1dSJens Wiklander 		return PKCS11_CKR_FUNCTION_FAILED;
110*512cbf1dSJens Wiklander 
111*512cbf1dSJens Wiklander 	/* Sign/Verify with AES or generic key relate to TEE MAC operation */
112*512cbf1dSJens Wiklander 	pkcs2tee_mode(&mode, function);
113*512cbf1dSJens Wiklander 
114*512cbf1dSJens Wiklander 	res = TEE_AllocateOperation(&session->processing->tee_op_handle,
115*512cbf1dSJens Wiklander 				    algo, mode, size);
116*512cbf1dSJens Wiklander 	if (res)
117*512cbf1dSJens Wiklander 		EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32" %#"PRIx32,
118*512cbf1dSJens Wiklander 		     algo, mode, size);
119*512cbf1dSJens Wiklander 
120*512cbf1dSJens Wiklander 	if (res == TEE_ERROR_NOT_SUPPORTED)
121*512cbf1dSJens Wiklander 		return PKCS11_CKR_MECHANISM_INVALID;
122*512cbf1dSJens Wiklander 
123*512cbf1dSJens Wiklander 	return tee2pkcs_error(res);
124*512cbf1dSJens Wiklander }
125*512cbf1dSJens Wiklander 
126*512cbf1dSJens Wiklander static enum pkcs11_rc load_tee_key(struct pkcs11_session *session,
127*512cbf1dSJens Wiklander 				   struct pkcs11_object *obj)
128*512cbf1dSJens Wiklander {
129*512cbf1dSJens Wiklander 	TEE_Attribute tee_attr = { };
130*512cbf1dSJens Wiklander 	size_t object_size = 0;
131*512cbf1dSJens Wiklander 	uint32_t tee_key_type = 0;
132*512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
133*512cbf1dSJens Wiklander 	TEE_Result res = TEE_ERROR_GENERIC;
134*512cbf1dSJens Wiklander 
135*512cbf1dSJens Wiklander 	if (obj->key_handle != TEE_HANDLE_NULL) {
136*512cbf1dSJens Wiklander 		/* Key was already loaded and fits current need */
137*512cbf1dSJens Wiklander 		goto key_ready;
138*512cbf1dSJens Wiklander 	}
139*512cbf1dSJens Wiklander 
140*512cbf1dSJens Wiklander 	if (!pkcs2tee_load_attr(&tee_attr, TEE_ATTR_SECRET_VALUE,
141*512cbf1dSJens Wiklander 				obj, PKCS11_CKA_VALUE)) {
142*512cbf1dSJens Wiklander 		EMSG("No secret found");
143*512cbf1dSJens Wiklander 		return PKCS11_CKR_FUNCTION_FAILED;
144*512cbf1dSJens Wiklander 	}
145*512cbf1dSJens Wiklander 
146*512cbf1dSJens Wiklander 	rc = pkcs2tee_key_type(&tee_key_type, obj);
147*512cbf1dSJens Wiklander 	if (rc)
148*512cbf1dSJens Wiklander 		return rc;
149*512cbf1dSJens Wiklander 
150*512cbf1dSJens Wiklander 	object_size = get_object_key_bit_size(obj);
151*512cbf1dSJens Wiklander 	if (!object_size)
152*512cbf1dSJens Wiklander 		return PKCS11_CKR_GENERAL_ERROR;
153*512cbf1dSJens Wiklander 
154*512cbf1dSJens Wiklander 	res = TEE_AllocateTransientObject(tee_key_type, object_size,
155*512cbf1dSJens Wiklander 					  &obj->key_handle);
156*512cbf1dSJens Wiklander 	if (res) {
157*512cbf1dSJens Wiklander 		DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res);
158*512cbf1dSJens Wiklander 		return tee2pkcs_error(res);
159*512cbf1dSJens Wiklander 	}
160*512cbf1dSJens Wiklander 
161*512cbf1dSJens Wiklander 	res = TEE_PopulateTransientObject(obj->key_handle, &tee_attr, 1);
162*512cbf1dSJens Wiklander 	if (res) {
163*512cbf1dSJens Wiklander 		DMSG("TEE_PopulateTransientObject failed, %#"PRIx32, res);
164*512cbf1dSJens Wiklander 		goto error;
165*512cbf1dSJens Wiklander 	}
166*512cbf1dSJens Wiklander 
167*512cbf1dSJens Wiklander key_ready:
168*512cbf1dSJens Wiklander 	res = TEE_SetOperationKey(session->processing->tee_op_handle,
169*512cbf1dSJens Wiklander 				  obj->key_handle);
170*512cbf1dSJens Wiklander 	if (res) {
171*512cbf1dSJens Wiklander 		DMSG("TEE_SetOperationKey failed, %#"PRIx32, res);
172*512cbf1dSJens Wiklander 		goto error;
173*512cbf1dSJens Wiklander 	}
174*512cbf1dSJens Wiklander 
175*512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
176*512cbf1dSJens Wiklander 
177*512cbf1dSJens Wiklander error:
178*512cbf1dSJens Wiklander 	TEE_FreeTransientObject(obj->key_handle);
179*512cbf1dSJens Wiklander 	obj->key_handle = TEE_HANDLE_NULL;
180*512cbf1dSJens Wiklander 
181*512cbf1dSJens Wiklander 	return tee2pkcs_error(res);
182*512cbf1dSJens Wiklander }
183*512cbf1dSJens Wiklander 
184*512cbf1dSJens Wiklander static enum pkcs11_rc
185*512cbf1dSJens Wiklander init_tee_operation(struct pkcs11_session *session,
186*512cbf1dSJens Wiklander 		   struct pkcs11_attribute_head *proc_params)
187*512cbf1dSJens Wiklander {
188*512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
189*512cbf1dSJens Wiklander 
190*512cbf1dSJens Wiklander 	switch (proc_params->id) {
191*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
192*512cbf1dSJens Wiklander 		if (proc_params->size)
193*512cbf1dSJens Wiklander 			return PKCS11_CKR_MECHANISM_PARAM_INVALID;
194*512cbf1dSJens Wiklander 
195*512cbf1dSJens Wiklander 		TEE_CipherInit(session->processing->tee_op_handle, NULL, 0);
196*512cbf1dSJens Wiklander 		rc = PKCS11_CKR_OK;
197*512cbf1dSJens Wiklander 		break;
198*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
199*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC_PAD:
200*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
201*512cbf1dSJens Wiklander 		if (proc_params->size != 16)
202*512cbf1dSJens Wiklander 			return PKCS11_CKR_MECHANISM_PARAM_INVALID;
203*512cbf1dSJens Wiklander 
204*512cbf1dSJens Wiklander 		TEE_CipherInit(session->processing->tee_op_handle,
205*512cbf1dSJens Wiklander 			       proc_params->data, 16);
206*512cbf1dSJens Wiklander 		rc = PKCS11_CKR_OK;
207*512cbf1dSJens Wiklander 		break;
208*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
209*512cbf1dSJens Wiklander 		rc = tee_init_ctr_operation(session->processing,
210*512cbf1dSJens Wiklander 					    proc_params->data,
211*512cbf1dSJens Wiklander 					    proc_params->size);
212*512cbf1dSJens Wiklander 		break;
213*512cbf1dSJens Wiklander 	default:
214*512cbf1dSJens Wiklander 		TEE_Panic(proc_params->id);
215*512cbf1dSJens Wiklander 		break;
216*512cbf1dSJens Wiklander 	}
217*512cbf1dSJens Wiklander 
218*512cbf1dSJens Wiklander 	return rc;
219*512cbf1dSJens Wiklander }
220*512cbf1dSJens Wiklander 
221*512cbf1dSJens Wiklander enum pkcs11_rc init_symm_operation(struct pkcs11_session *session,
222*512cbf1dSJens Wiklander 				   enum processing_func function,
223*512cbf1dSJens Wiklander 				   struct pkcs11_attribute_head *proc_params,
224*512cbf1dSJens Wiklander 				   struct pkcs11_object *obj)
225*512cbf1dSJens Wiklander {
226*512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
227*512cbf1dSJens Wiklander 
228*512cbf1dSJens Wiklander 	assert(processing_is_tee_symm(proc_params->id));
229*512cbf1dSJens Wiklander 
230*512cbf1dSJens Wiklander 	rc = allocate_tee_operation(session, function, proc_params, obj);
231*512cbf1dSJens Wiklander 	if (rc)
232*512cbf1dSJens Wiklander 		return rc;
233*512cbf1dSJens Wiklander 
234*512cbf1dSJens Wiklander 	rc = load_tee_key(session, obj);
235*512cbf1dSJens Wiklander 	if (rc)
236*512cbf1dSJens Wiklander 		return rc;
237*512cbf1dSJens Wiklander 
238*512cbf1dSJens Wiklander 	return init_tee_operation(session, proc_params);
239*512cbf1dSJens Wiklander }
240*512cbf1dSJens Wiklander 
241*512cbf1dSJens Wiklander /* Validate input buffer size as per PKCS#11 constraints */
242*512cbf1dSJens Wiklander static enum pkcs11_rc input_data_size_is_valid(struct active_processing *proc,
243*512cbf1dSJens Wiklander 					       enum processing_func function,
244*512cbf1dSJens Wiklander 					       size_t in_size)
245*512cbf1dSJens Wiklander {
246*512cbf1dSJens Wiklander 	switch (proc->mecha_type) {
247*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
248*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
249*512cbf1dSJens Wiklander 		if (function == PKCS11_FUNCTION_ENCRYPT &&
250*512cbf1dSJens Wiklander 		    in_size % TEE_AES_BLOCK_SIZE)
251*512cbf1dSJens Wiklander 			return PKCS11_CKR_DATA_LEN_RANGE;
252*512cbf1dSJens Wiklander 		if (function == PKCS11_FUNCTION_DECRYPT &&
253*512cbf1dSJens Wiklander 		    in_size % TEE_AES_BLOCK_SIZE)
254*512cbf1dSJens Wiklander 			return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
255*512cbf1dSJens Wiklander 		break;
256*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC_PAD:
257*512cbf1dSJens Wiklander 		if (function == PKCS11_FUNCTION_DECRYPT &&
258*512cbf1dSJens Wiklander 		    in_size % TEE_AES_BLOCK_SIZE)
259*512cbf1dSJens Wiklander 			return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
260*512cbf1dSJens Wiklander 		break;
261*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
262*512cbf1dSJens Wiklander 		if (function == PKCS11_FUNCTION_ENCRYPT &&
263*512cbf1dSJens Wiklander 		    in_size < TEE_AES_BLOCK_SIZE)
264*512cbf1dSJens Wiklander 			return PKCS11_CKR_DATA_LEN_RANGE;
265*512cbf1dSJens Wiklander 		if (function == PKCS11_FUNCTION_DECRYPT &&
266*512cbf1dSJens Wiklander 		    in_size < TEE_AES_BLOCK_SIZE)
267*512cbf1dSJens Wiklander 			return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
268*512cbf1dSJens Wiklander 		break;
269*512cbf1dSJens Wiklander 	default:
270*512cbf1dSJens Wiklander 		break;
271*512cbf1dSJens Wiklander 	}
272*512cbf1dSJens Wiklander 
273*512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
274*512cbf1dSJens Wiklander }
275*512cbf1dSJens Wiklander 
276*512cbf1dSJens Wiklander /*
277*512cbf1dSJens Wiklander  * step_sym_cipher - processing symmetric (and related) cipher operation step
278*512cbf1dSJens Wiklander  *
279*512cbf1dSJens Wiklander  * @session - current session
280*512cbf1dSJens Wiklander  * @function - processing function (encrypt, decrypt, sign, ...)
281*512cbf1dSJens Wiklander  * @step - step ID in the processing (oneshot, update, final)
282*512cbf1dSJens Wiklander  * @ptype - invocation parameter types
283*512cbf1dSJens Wiklander  * @params - invocation parameter references
284*512cbf1dSJens Wiklander  */
285*512cbf1dSJens Wiklander enum pkcs11_rc step_symm_operation(struct pkcs11_session *session,
286*512cbf1dSJens Wiklander 				   enum processing_func function,
287*512cbf1dSJens Wiklander 				   enum processing_step step,
288*512cbf1dSJens Wiklander 				   uint32_t ptypes, TEE_Param *params)
289*512cbf1dSJens Wiklander {
290*512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
291*512cbf1dSJens Wiklander 	TEE_Result res = TEE_ERROR_GENERIC;
292*512cbf1dSJens Wiklander 	void *in_buf = NULL;
293*512cbf1dSJens Wiklander 	size_t in_size = 0;
294*512cbf1dSJens Wiklander 	void *out_buf = NULL;
295*512cbf1dSJens Wiklander 	uint32_t out_size = 0;
296*512cbf1dSJens Wiklander 	void *in2_buf = NULL;
297*512cbf1dSJens Wiklander 	uint32_t in2_size = 0;
298*512cbf1dSJens Wiklander 	bool output_data = false;
299*512cbf1dSJens Wiklander 	struct active_processing *proc = session->processing;
300*512cbf1dSJens Wiklander 
301*512cbf1dSJens Wiklander 	if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) {
302*512cbf1dSJens Wiklander 		in_buf = params[1].memref.buffer;
303*512cbf1dSJens Wiklander 		in_size = params[1].memref.size;
304*512cbf1dSJens Wiklander 		if (in_size && !in_buf)
305*512cbf1dSJens Wiklander 			return PKCS11_CKR_ARGUMENTS_BAD;
306*512cbf1dSJens Wiklander 	}
307*512cbf1dSJens Wiklander 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_INPUT) {
308*512cbf1dSJens Wiklander 		in2_buf = params[2].memref.buffer;
309*512cbf1dSJens Wiklander 		in2_size = params[2].memref.size;
310*512cbf1dSJens Wiklander 		if (in2_size && !in2_buf)
311*512cbf1dSJens Wiklander 			return PKCS11_CKR_ARGUMENTS_BAD;
312*512cbf1dSJens Wiklander 	}
313*512cbf1dSJens Wiklander 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) {
314*512cbf1dSJens Wiklander 		out_buf = params[2].memref.buffer;
315*512cbf1dSJens Wiklander 		out_size = params[2].memref.size;
316*512cbf1dSJens Wiklander 		if (out_size && !out_buf)
317*512cbf1dSJens Wiklander 			return PKCS11_CKR_ARGUMENTS_BAD;
318*512cbf1dSJens Wiklander 	}
319*512cbf1dSJens Wiklander 	if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
320*512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
321*512cbf1dSJens Wiklander 
322*512cbf1dSJens Wiklander 	switch (step) {
323*512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_ONESHOT:
324*512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_UPDATE:
325*512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_FINAL:
326*512cbf1dSJens Wiklander 		break;
327*512cbf1dSJens Wiklander 	default:
328*512cbf1dSJens Wiklander 		return PKCS11_CKR_GENERAL_ERROR;
329*512cbf1dSJens Wiklander 	}
330*512cbf1dSJens Wiklander 
331*512cbf1dSJens Wiklander 	if (step != PKCS11_FUNC_STEP_FINAL) {
332*512cbf1dSJens Wiklander 		rc = input_data_size_is_valid(proc, function, in_size);
333*512cbf1dSJens Wiklander 		if (rc)
334*512cbf1dSJens Wiklander 			return rc;
335*512cbf1dSJens Wiklander 	}
336*512cbf1dSJens Wiklander 
337*512cbf1dSJens Wiklander 	/*
338*512cbf1dSJens Wiklander 	 * Feed active operation with data
339*512cbf1dSJens Wiklander 	 * (PKCS11_FUNC_STEP_UPDATE/_ONESHOT)
340*512cbf1dSJens Wiklander 	 */
341*512cbf1dSJens Wiklander 	switch (proc->mecha_type) {
342*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
343*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
344*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC_PAD:
345*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
346*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
347*512cbf1dSJens Wiklander 		if (step == PKCS11_FUNC_STEP_FINAL ||
348*512cbf1dSJens Wiklander 		    step == PKCS11_FUNC_STEP_ONESHOT)
349*512cbf1dSJens Wiklander 			break;
350*512cbf1dSJens Wiklander 
351*512cbf1dSJens Wiklander 		if (!in_buf) {
352*512cbf1dSJens Wiklander 			EMSG("No input data");
353*512cbf1dSJens Wiklander 			return PKCS11_CKR_ARGUMENTS_BAD;
354*512cbf1dSJens Wiklander 		}
355*512cbf1dSJens Wiklander 
356*512cbf1dSJens Wiklander 		switch (function) {
357*512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_ENCRYPT:
358*512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_DECRYPT:
359*512cbf1dSJens Wiklander 			res = TEE_CipherUpdate(proc->tee_op_handle,
360*512cbf1dSJens Wiklander 					       in_buf, in_size,
361*512cbf1dSJens Wiklander 						out_buf, &out_size);
362*512cbf1dSJens Wiklander 			output_data = true;
363*512cbf1dSJens Wiklander 			rc = tee2pkcs_error(res);
364*512cbf1dSJens Wiklander 			break;
365*512cbf1dSJens Wiklander 		default:
366*512cbf1dSJens Wiklander 			TEE_Panic(function);
367*512cbf1dSJens Wiklander 			break;
368*512cbf1dSJens Wiklander 		}
369*512cbf1dSJens Wiklander 		break;
370*512cbf1dSJens Wiklander 
371*512cbf1dSJens Wiklander 	default:
372*512cbf1dSJens Wiklander 		TEE_Panic(proc->mecha_type);
373*512cbf1dSJens Wiklander 		break;
374*512cbf1dSJens Wiklander 	}
375*512cbf1dSJens Wiklander 
376*512cbf1dSJens Wiklander 	if (step == PKCS11_FUNC_STEP_UPDATE)
377*512cbf1dSJens Wiklander 		goto out;
378*512cbf1dSJens Wiklander 
379*512cbf1dSJens Wiklander 	/*
380*512cbf1dSJens Wiklander 	 * Finalize (PKCS11_FUNC_STEP_ONESHOT/_FINAL) operation
381*512cbf1dSJens Wiklander 	 */
382*512cbf1dSJens Wiklander 	switch (session->processing->mecha_type) {
383*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
384*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
385*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC_PAD:
386*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
387*512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
388*512cbf1dSJens Wiklander 		if (step == PKCS11_FUNC_STEP_ONESHOT && !in_buf) {
389*512cbf1dSJens Wiklander 			EMSG("No input data");
390*512cbf1dSJens Wiklander 			return PKCS11_CKR_ARGUMENTS_BAD;
391*512cbf1dSJens Wiklander 		}
392*512cbf1dSJens Wiklander 
393*512cbf1dSJens Wiklander 		switch (function) {
394*512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_ENCRYPT:
395*512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_DECRYPT:
396*512cbf1dSJens Wiklander 			res = TEE_CipherDoFinal(proc->tee_op_handle,
397*512cbf1dSJens Wiklander 						in_buf, in_size,
398*512cbf1dSJens Wiklander 						out_buf, &out_size);
399*512cbf1dSJens Wiklander 			output_data = true;
400*512cbf1dSJens Wiklander 			rc = tee2pkcs_error(res);
401*512cbf1dSJens Wiklander 			break;
402*512cbf1dSJens Wiklander 		default:
403*512cbf1dSJens Wiklander 			TEE_Panic(function);
404*512cbf1dSJens Wiklander 			break;
405*512cbf1dSJens Wiklander 		}
406*512cbf1dSJens Wiklander 		break;
407*512cbf1dSJens Wiklander 	default:
408*512cbf1dSJens Wiklander 		TEE_Panic(proc->mecha_type);
409*512cbf1dSJens Wiklander 		break;
410*512cbf1dSJens Wiklander 	}
411*512cbf1dSJens Wiklander 
412*512cbf1dSJens Wiklander out:
413*512cbf1dSJens Wiklander 	if (output_data &&
414*512cbf1dSJens Wiklander 	    (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)) {
415*512cbf1dSJens Wiklander 		switch (TEE_PARAM_TYPE_GET(ptypes, 2)) {
416*512cbf1dSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
417*512cbf1dSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
418*512cbf1dSJens Wiklander 			params[2].memref.size = out_size;
419*512cbf1dSJens Wiklander 			break;
420*512cbf1dSJens Wiklander 		default:
421*512cbf1dSJens Wiklander 			rc = PKCS11_CKR_ARGUMENTS_BAD;
422*512cbf1dSJens Wiklander 			break;
423*512cbf1dSJens Wiklander 		}
424*512cbf1dSJens Wiklander 	}
425*512cbf1dSJens Wiklander 
426*512cbf1dSJens Wiklander 	return rc;
427*512cbf1dSJens Wiklander }
428