xref: /optee_os/ta/pkcs11/src/processing_symm.c (revision de94d6f8e9de06887add06b81454db479aa8c232)
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 <utee_defines.h>
13 #include <util.h>
14 
15 #include "attributes.h"
16 #include "object.h"
17 #include "pkcs11_attributes.h"
18 #include "pkcs11_helpers.h"
19 #include "pkcs11_token.h"
20 #include "processing.h"
21 #include "serializer.h"
22 
23 bool processing_is_tee_symm(enum pkcs11_mechanism_id proc_id)
24 {
25 	switch (proc_id) {
26 	/* Authentication */
27 	case PKCS11_CKM_MD5_HMAC:
28 	case PKCS11_CKM_SHA_1_HMAC:
29 	case PKCS11_CKM_SHA224_HMAC:
30 	case PKCS11_CKM_SHA256_HMAC:
31 	case PKCS11_CKM_SHA384_HMAC:
32 	case PKCS11_CKM_SHA512_HMAC:
33 	/* Cipherering */
34 	case PKCS11_CKM_AES_ECB:
35 	case PKCS11_CKM_AES_CBC:
36 	case PKCS11_CKM_AES_CBC_PAD:
37 	case PKCS11_CKM_AES_CTS:
38 	case PKCS11_CKM_AES_CTR:
39 		return true;
40 	default:
41 		return false;
42 	}
43 }
44 
45 static enum pkcs11_rc
46 pkcs2tee_algorithm(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params)
47 {
48 	static const struct {
49 		enum pkcs11_mechanism_id mech_id;
50 		uint32_t tee_id;
51 	} pkcs2tee_algo[] = {
52 		/* AES flavors */
53 		{ PKCS11_CKM_AES_ECB, TEE_ALG_AES_ECB_NOPAD },
54 		{ PKCS11_CKM_AES_CBC, TEE_ALG_AES_CBC_NOPAD },
55 		{ PKCS11_CKM_AES_CBC_PAD, TEE_ALG_AES_CBC_NOPAD },
56 		{ PKCS11_CKM_AES_CTR, TEE_ALG_AES_CTR },
57 		{ PKCS11_CKM_AES_CTS, TEE_ALG_AES_CTS },
58 		/* HMAC flavors */
59 		{ PKCS11_CKM_MD5_HMAC, TEE_ALG_HMAC_MD5 },
60 		{ PKCS11_CKM_SHA_1_HMAC, TEE_ALG_HMAC_SHA1 },
61 		{ PKCS11_CKM_SHA224_HMAC, TEE_ALG_HMAC_SHA224 },
62 		{ PKCS11_CKM_SHA256_HMAC, TEE_ALG_HMAC_SHA256 },
63 		{ PKCS11_CKM_SHA384_HMAC, TEE_ALG_HMAC_SHA384 },
64 		{ PKCS11_CKM_SHA512_HMAC, TEE_ALG_HMAC_SHA512 },
65 	};
66 	size_t n = 0;
67 
68 	for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) {
69 		if (proc_params->id == pkcs2tee_algo[n].mech_id) {
70 			*tee_id = pkcs2tee_algo[n].tee_id;
71 			return PKCS11_CKR_OK;
72 		}
73 	}
74 
75 	return PKCS11_RV_NOT_IMPLEMENTED;
76 }
77 
78 static enum pkcs11_rc pkcs2tee_key_type(uint32_t *tee_type,
79 					struct pkcs11_object *obj)
80 {
81 	static const struct {
82 		enum pkcs11_key_type key_type;
83 		uint32_t tee_id;
84 	} pkcs2tee_key_type[] = {
85 		{ PKCS11_CKK_AES, TEE_TYPE_AES },
86 		{ PKCS11_CKK_GENERIC_SECRET, TEE_TYPE_GENERIC_SECRET },
87 		{ PKCS11_CKK_MD5_HMAC, TEE_TYPE_HMAC_MD5 },
88 		{ PKCS11_CKK_SHA_1_HMAC, TEE_TYPE_HMAC_SHA1 },
89 		{ PKCS11_CKK_SHA224_HMAC, TEE_TYPE_HMAC_SHA224 },
90 		{ PKCS11_CKK_SHA256_HMAC, TEE_TYPE_HMAC_SHA256 },
91 		{ PKCS11_CKK_SHA384_HMAC, TEE_TYPE_HMAC_SHA384 },
92 		{ PKCS11_CKK_SHA512_HMAC, TEE_TYPE_HMAC_SHA512 },
93 	};
94 	size_t n = 0;
95 	enum pkcs11_key_type key_type = get_key_type(obj->attributes);
96 
97 	assert(get_class(obj->attributes) == PKCS11_CKO_SECRET_KEY);
98 
99 	for (n = 0; n < ARRAY_SIZE(pkcs2tee_key_type); n++) {
100 		if (pkcs2tee_key_type[n].key_type == key_type) {
101 			*tee_type = pkcs2tee_key_type[n].tee_id;
102 			return PKCS11_CKR_OK;
103 		}
104 	}
105 
106 	return PKCS11_RV_NOT_FOUND;
107 }
108 
109 static enum pkcs11_rc pkcsmech2tee_key_type(uint32_t *tee_type,
110 					    enum pkcs11_mechanism_id mech_id)
111 {
112 	static const struct {
113 		enum pkcs11_mechanism_id mech;
114 		uint32_t tee_id;
115 	} pkcs2tee_key_type[] = {
116 		{ PKCS11_CKM_MD5_HMAC, TEE_TYPE_HMAC_MD5 },
117 		{ PKCS11_CKM_SHA_1_HMAC, TEE_TYPE_HMAC_SHA1 },
118 		{ PKCS11_CKM_SHA224_HMAC, TEE_TYPE_HMAC_SHA224 },
119 		{ PKCS11_CKM_SHA256_HMAC, TEE_TYPE_HMAC_SHA256 },
120 		{ PKCS11_CKM_SHA384_HMAC, TEE_TYPE_HMAC_SHA384 },
121 		{ PKCS11_CKM_SHA512_HMAC, TEE_TYPE_HMAC_SHA512 },
122 	};
123 	size_t n = 0;
124 
125 	for (n = 0; n < ARRAY_SIZE(pkcs2tee_key_type); n++) {
126 		if (pkcs2tee_key_type[n].mech == mech_id) {
127 			*tee_type = pkcs2tee_key_type[n].tee_id;
128 			return PKCS11_CKR_OK;
129 		}
130 	}
131 
132 	return PKCS11_RV_NOT_FOUND;
133 }
134 
135 static enum pkcs11_rc
136 allocate_tee_operation(struct pkcs11_session *session,
137 		       enum processing_func function,
138 		       struct pkcs11_attribute_head *params,
139 		       struct pkcs11_object *obj)
140 {
141 	uint32_t size = (uint32_t)get_object_key_bit_size(obj);
142 	uint32_t algo = 0;
143 	uint32_t mode = 0;
144 	TEE_Result res = TEE_ERROR_GENERIC;
145 
146 	assert(session->processing->tee_op_handle == TEE_HANDLE_NULL);
147 
148 	if (pkcs2tee_algorithm(&algo, params))
149 		return PKCS11_CKR_FUNCTION_FAILED;
150 
151 	/* Sign/Verify with AES or generic key relate to TEE MAC operation */
152 	switch (params->id) {
153 	case PKCS11_CKM_MD5_HMAC:
154 	case PKCS11_CKM_SHA_1_HMAC:
155 	case PKCS11_CKM_SHA224_HMAC:
156 	case PKCS11_CKM_SHA256_HMAC:
157 	case PKCS11_CKM_SHA384_HMAC:
158 	case PKCS11_CKM_SHA512_HMAC:
159 		mode = TEE_MODE_MAC;
160 		break;
161 	default:
162 		pkcs2tee_mode(&mode, function);
163 		break;
164 	}
165 
166 	res = TEE_AllocateOperation(&session->processing->tee_op_handle,
167 				    algo, mode, size);
168 	if (res)
169 		EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32" %#"PRIx32,
170 		     algo, mode, size);
171 
172 	if (res == TEE_ERROR_NOT_SUPPORTED)
173 		return PKCS11_CKR_MECHANISM_INVALID;
174 
175 	return tee2pkcs_error(res);
176 }
177 
178 static enum pkcs11_rc load_tee_key(struct pkcs11_session *session,
179 				   struct pkcs11_object *obj,
180 				   struct pkcs11_attribute_head *proc_params)
181 {
182 	TEE_Attribute tee_attr = { };
183 	size_t object_size = 0;
184 	uint32_t tee_key_type = 0;
185 	enum pkcs11_key_type key_type = 0;
186 	enum pkcs11_rc rc = PKCS11_CKR_OK;
187 	TEE_Result res = TEE_ERROR_GENERIC;
188 
189 	if (obj->key_handle != TEE_HANDLE_NULL) {
190 		/* Key was already loaded and fits current need */
191 		goto key_ready;
192 	}
193 
194 	if (!pkcs2tee_load_attr(&tee_attr, TEE_ATTR_SECRET_VALUE,
195 				obj, PKCS11_CKA_VALUE)) {
196 		EMSG("No secret found");
197 		return PKCS11_CKR_FUNCTION_FAILED;
198 	}
199 
200 	switch (proc_params->id) {
201 	case PKCS11_CKM_MD5_HMAC:
202 	case PKCS11_CKM_SHA_1_HMAC:
203 	case PKCS11_CKM_SHA224_HMAC:
204 	case PKCS11_CKM_SHA256_HMAC:
205 	case PKCS11_CKM_SHA384_HMAC:
206 	case PKCS11_CKM_SHA512_HMAC:
207 		key_type = get_key_type(obj->attributes);
208 		/*
209 		 * If Object Key type is PKCS11_CKK_GENERIC_SECRET,
210 		 * determine the tee_key_type using the
211 		 * mechanism instead of object key_type.
212 		 */
213 		if (key_type == PKCS11_CKK_GENERIC_SECRET)
214 			rc = pkcsmech2tee_key_type(&tee_key_type,
215 						   proc_params->id);
216 		else
217 			rc = pkcs2tee_key_type(&tee_key_type, obj);
218 
219 		break;
220 	default:
221 		/*
222 		 * For all other mechanisms, use object key_type
223 		 * to determine the corresponding tee_key_type
224 		 */
225 		rc = pkcs2tee_key_type(&tee_key_type, obj);
226 		break;
227 	}
228 
229 	if (rc)
230 		return rc;
231 
232 	object_size = get_object_key_bit_size(obj);
233 	if (!object_size)
234 		return PKCS11_CKR_GENERAL_ERROR;
235 
236 	res = TEE_AllocateTransientObject(tee_key_type, object_size,
237 					  &obj->key_handle);
238 	if (res) {
239 		DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res);
240 		return tee2pkcs_error(res);
241 	}
242 
243 	res = TEE_PopulateTransientObject(obj->key_handle, &tee_attr, 1);
244 	if (res) {
245 		DMSG("TEE_PopulateTransientObject failed, %#"PRIx32, res);
246 		goto error;
247 	}
248 
249 key_ready:
250 	res = TEE_SetOperationKey(session->processing->tee_op_handle,
251 				  obj->key_handle);
252 	if (res) {
253 		DMSG("TEE_SetOperationKey failed, %#"PRIx32, res);
254 		goto error;
255 	}
256 
257 	return PKCS11_CKR_OK;
258 
259 error:
260 	TEE_FreeTransientObject(obj->key_handle);
261 	obj->key_handle = TEE_HANDLE_NULL;
262 
263 	return tee2pkcs_error(res);
264 }
265 
266 static enum pkcs11_rc
267 init_tee_operation(struct pkcs11_session *session,
268 		   struct pkcs11_attribute_head *proc_params)
269 {
270 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
271 
272 	switch (proc_params->id) {
273 	case PKCS11_CKM_MD5_HMAC:
274 	case PKCS11_CKM_SHA_1_HMAC:
275 	case PKCS11_CKM_SHA224_HMAC:
276 	case PKCS11_CKM_SHA256_HMAC:
277 	case PKCS11_CKM_SHA384_HMAC:
278 	case PKCS11_CKM_SHA512_HMAC:
279 		if (proc_params->size)
280 			return PKCS11_CKR_MECHANISM_PARAM_INVALID;
281 
282 		TEE_MACInit(session->processing->tee_op_handle, NULL, 0);
283 		rc = PKCS11_CKR_OK;
284 		break;
285 	case PKCS11_CKM_AES_ECB:
286 		if (proc_params->size)
287 			return PKCS11_CKR_MECHANISM_PARAM_INVALID;
288 
289 		TEE_CipherInit(session->processing->tee_op_handle, NULL, 0);
290 		rc = PKCS11_CKR_OK;
291 		break;
292 	case PKCS11_CKM_AES_CBC:
293 	case PKCS11_CKM_AES_CBC_PAD:
294 	case PKCS11_CKM_AES_CTS:
295 		if (proc_params->size != 16)
296 			return PKCS11_CKR_MECHANISM_PARAM_INVALID;
297 
298 		TEE_CipherInit(session->processing->tee_op_handle,
299 			       proc_params->data, 16);
300 		rc = PKCS11_CKR_OK;
301 		break;
302 	case PKCS11_CKM_AES_CTR:
303 		rc = tee_init_ctr_operation(session->processing,
304 					    proc_params->data,
305 					    proc_params->size);
306 		break;
307 	default:
308 		TEE_Panic(proc_params->id);
309 		break;
310 	}
311 
312 	return rc;
313 }
314 
315 enum pkcs11_rc init_symm_operation(struct pkcs11_session *session,
316 				   enum processing_func function,
317 				   struct pkcs11_attribute_head *proc_params,
318 				   struct pkcs11_object *obj)
319 {
320 	enum pkcs11_rc rc = PKCS11_CKR_OK;
321 
322 	assert(processing_is_tee_symm(proc_params->id));
323 
324 	rc = allocate_tee_operation(session, function, proc_params, obj);
325 	if (rc)
326 		return rc;
327 
328 	rc = load_tee_key(session, obj, proc_params);
329 	if (rc)
330 		return rc;
331 
332 	return init_tee_operation(session, proc_params);
333 }
334 
335 /* Validate input buffer size as per PKCS#11 constraints */
336 static enum pkcs11_rc input_data_size_is_valid(struct active_processing *proc,
337 					       enum processing_func function,
338 					       size_t in_size)
339 {
340 	switch (proc->mecha_type) {
341 	case PKCS11_CKM_AES_ECB:
342 	case PKCS11_CKM_AES_CBC:
343 		if (function == PKCS11_FUNCTION_ENCRYPT &&
344 		    in_size % TEE_AES_BLOCK_SIZE)
345 			return PKCS11_CKR_DATA_LEN_RANGE;
346 		if (function == PKCS11_FUNCTION_DECRYPT &&
347 		    in_size % TEE_AES_BLOCK_SIZE)
348 			return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
349 		break;
350 	case PKCS11_CKM_AES_CBC_PAD:
351 		if (function == PKCS11_FUNCTION_DECRYPT &&
352 		    in_size % TEE_AES_BLOCK_SIZE)
353 			return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
354 		break;
355 	case PKCS11_CKM_AES_CTS:
356 		if (function == PKCS11_FUNCTION_ENCRYPT &&
357 		    in_size < TEE_AES_BLOCK_SIZE)
358 			return PKCS11_CKR_DATA_LEN_RANGE;
359 		if (function == PKCS11_FUNCTION_DECRYPT &&
360 		    in_size < TEE_AES_BLOCK_SIZE)
361 			return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
362 		break;
363 	default:
364 		break;
365 	}
366 
367 	return PKCS11_CKR_OK;
368 }
369 
370 /* Validate input buffer size as per PKCS#11 constraints */
371 static enum pkcs11_rc input_sign_size_is_valid(struct active_processing *proc,
372 					       size_t in_size)
373 {
374 	size_t sign_sz = 0;
375 
376 	switch (proc->mecha_type) {
377 	case PKCS11_CKM_MD5_HMAC:
378 		sign_sz = TEE_MD5_HASH_SIZE;
379 		break;
380 	case PKCS11_CKM_SHA_1_HMAC:
381 		sign_sz = TEE_SHA1_HASH_SIZE;
382 		break;
383 	case PKCS11_CKM_SHA224_HMAC:
384 		sign_sz = TEE_SHA224_HASH_SIZE;
385 		break;
386 	case PKCS11_CKM_SHA256_HMAC:
387 		sign_sz = TEE_SHA256_HASH_SIZE;
388 		break;
389 	case PKCS11_CKM_SHA384_HMAC:
390 		sign_sz = TEE_SHA384_HASH_SIZE;
391 		break;
392 	case PKCS11_CKM_SHA512_HMAC:
393 		sign_sz = TEE_SHA512_HASH_SIZE;
394 		break;
395 	default:
396 		return PKCS11_CKR_GENERAL_ERROR;
397 	}
398 
399 	if (in_size < sign_sz)
400 		return PKCS11_CKR_SIGNATURE_LEN_RANGE;
401 
402 	return PKCS11_CKR_OK;
403 }
404 
405 /*
406  * step_sym_cipher - processing symmetric (and related) cipher operation step
407  *
408  * @session - current session
409  * @function - processing function (encrypt, decrypt, sign, ...)
410  * @step - step ID in the processing (oneshot, update, final)
411  * @ptype - invocation parameter types
412  * @params - invocation parameter references
413  */
414 enum pkcs11_rc step_symm_operation(struct pkcs11_session *session,
415 				   enum processing_func function,
416 				   enum processing_step step,
417 				   uint32_t ptypes, TEE_Param *params)
418 {
419 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
420 	TEE_Result res = TEE_ERROR_GENERIC;
421 	void *in_buf = NULL;
422 	size_t in_size = 0;
423 	void *out_buf = NULL;
424 	uint32_t out_size = 0;
425 	void *in2_buf = NULL;
426 	uint32_t in2_size = 0;
427 	bool output_data = false;
428 	struct active_processing *proc = session->processing;
429 
430 	if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) {
431 		in_buf = params[1].memref.buffer;
432 		in_size = params[1].memref.size;
433 		if (in_size && !in_buf)
434 			return PKCS11_CKR_ARGUMENTS_BAD;
435 	}
436 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_INPUT) {
437 		in2_buf = params[2].memref.buffer;
438 		in2_size = params[2].memref.size;
439 		if (in2_size && !in2_buf)
440 			return PKCS11_CKR_ARGUMENTS_BAD;
441 	}
442 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) {
443 		out_buf = params[2].memref.buffer;
444 		out_size = params[2].memref.size;
445 		if (out_size && !out_buf)
446 			return PKCS11_CKR_ARGUMENTS_BAD;
447 	}
448 	if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
449 		return PKCS11_CKR_ARGUMENTS_BAD;
450 
451 	switch (step) {
452 	case PKCS11_FUNC_STEP_ONESHOT:
453 	case PKCS11_FUNC_STEP_UPDATE:
454 	case PKCS11_FUNC_STEP_FINAL:
455 		break;
456 	default:
457 		return PKCS11_CKR_GENERAL_ERROR;
458 	}
459 
460 	if (step != PKCS11_FUNC_STEP_FINAL) {
461 		rc = input_data_size_is_valid(proc, function, in_size);
462 		if (rc)
463 			return rc;
464 	}
465 
466 	/*
467 	 * Feed active operation with data
468 	 */
469 	switch (proc->mecha_type) {
470 	case PKCS11_CKM_MD5_HMAC:
471 	case PKCS11_CKM_SHA_1_HMAC:
472 	case PKCS11_CKM_SHA224_HMAC:
473 	case PKCS11_CKM_SHA256_HMAC:
474 	case PKCS11_CKM_SHA384_HMAC:
475 	case PKCS11_CKM_SHA512_HMAC:
476 		if (step == PKCS11_FUNC_STEP_FINAL ||
477 		    step == PKCS11_FUNC_STEP_ONESHOT)
478 			break;
479 
480 		if (!in_buf) {
481 			DMSG("No input data");
482 			return PKCS11_CKR_ARGUMENTS_BAD;
483 		}
484 
485 		switch (function) {
486 		case PKCS11_FUNCTION_SIGN:
487 		case PKCS11_FUNCTION_VERIFY:
488 			TEE_MACUpdate(proc->tee_op_handle, in_buf, in_size);
489 			rc = PKCS11_CKR_OK;
490 			break;
491 		default:
492 			TEE_Panic(function);
493 			break;
494 		}
495 		break;
496 
497 	case PKCS11_CKM_AES_ECB:
498 	case PKCS11_CKM_AES_CBC:
499 	case PKCS11_CKM_AES_CBC_PAD:
500 	case PKCS11_CKM_AES_CTS:
501 	case PKCS11_CKM_AES_CTR:
502 		if (step == PKCS11_FUNC_STEP_FINAL ||
503 		    step == PKCS11_FUNC_STEP_ONESHOT)
504 			break;
505 
506 		if (!in_buf) {
507 			EMSG("No input data");
508 			return PKCS11_CKR_ARGUMENTS_BAD;
509 		}
510 
511 		switch (function) {
512 		case PKCS11_FUNCTION_ENCRYPT:
513 		case PKCS11_FUNCTION_DECRYPT:
514 			res = TEE_CipherUpdate(proc->tee_op_handle,
515 					       in_buf, in_size,
516 						out_buf, &out_size);
517 			output_data = true;
518 			rc = tee2pkcs_error(res);
519 			break;
520 		default:
521 			TEE_Panic(function);
522 			break;
523 		}
524 		break;
525 
526 	default:
527 		TEE_Panic(proc->mecha_type);
528 		break;
529 	}
530 
531 	if (step == PKCS11_FUNC_STEP_UPDATE)
532 		goto out;
533 
534 	/*
535 	 * Finalize (PKCS11_FUNC_STEP_ONESHOT/_FINAL) operation
536 	 */
537 	switch (session->processing->mecha_type) {
538 	case PKCS11_CKM_MD5_HMAC:
539 	case PKCS11_CKM_SHA_1_HMAC:
540 	case PKCS11_CKM_SHA224_HMAC:
541 	case PKCS11_CKM_SHA256_HMAC:
542 	case PKCS11_CKM_SHA384_HMAC:
543 	case PKCS11_CKM_SHA512_HMAC:
544 		switch (function) {
545 		case PKCS11_FUNCTION_SIGN:
546 			res = TEE_MACComputeFinal(proc->tee_op_handle,
547 						  in_buf, in_size, out_buf,
548 						  &out_size);
549 			output_data = true;
550 			rc = tee2pkcs_error(res);
551 			break;
552 		case PKCS11_FUNCTION_VERIFY:
553 			rc = input_sign_size_is_valid(proc, in2_size);
554 			if (rc)
555 				return rc;
556 			res = TEE_MACCompareFinal(proc->tee_op_handle,
557 						  in_buf, in_size, in2_buf,
558 						  in2_size);
559 			rc = tee2pkcs_error(res);
560 			break;
561 		default:
562 			TEE_Panic(function);
563 			break;
564 		}
565 		break;
566 
567 	case PKCS11_CKM_AES_ECB:
568 	case PKCS11_CKM_AES_CBC:
569 	case PKCS11_CKM_AES_CBC_PAD:
570 	case PKCS11_CKM_AES_CTS:
571 	case PKCS11_CKM_AES_CTR:
572 		if (step == PKCS11_FUNC_STEP_ONESHOT && !in_buf) {
573 			EMSG("No input data");
574 			return PKCS11_CKR_ARGUMENTS_BAD;
575 		}
576 
577 		switch (function) {
578 		case PKCS11_FUNCTION_ENCRYPT:
579 		case PKCS11_FUNCTION_DECRYPT:
580 			res = TEE_CipherDoFinal(proc->tee_op_handle,
581 						in_buf, in_size,
582 						out_buf, &out_size);
583 			output_data = true;
584 			rc = tee2pkcs_error(res);
585 			break;
586 		default:
587 			TEE_Panic(function);
588 			break;
589 		}
590 		break;
591 	default:
592 		TEE_Panic(proc->mecha_type);
593 		break;
594 	}
595 
596 out:
597 	if (output_data &&
598 	    (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)) {
599 		switch (TEE_PARAM_TYPE_GET(ptypes, 2)) {
600 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
601 		case TEE_PARAM_TYPE_MEMREF_INOUT:
602 			params[2].memref.size = out_size;
603 			break;
604 		default:
605 			rc = PKCS11_CKR_ARGUMENTS_BAD;
606 			break;
607 		}
608 	}
609 
610 	return rc;
611 }
612