xref: /optee_os/ta/pkcs11/src/processing_symm.c (revision de94d6f8e9de06887add06b81454db479aa8c232)
1512cbf1dSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2512cbf1dSJens Wiklander /*
3512cbf1dSJens Wiklander  * Copyright (c) 2017-2020, Linaro Limited
4512cbf1dSJens Wiklander  */
5512cbf1dSJens Wiklander 
6512cbf1dSJens Wiklander #include <assert.h>
7512cbf1dSJens Wiklander #include <pkcs11_ta.h>
8512cbf1dSJens Wiklander #include <string.h>
9512cbf1dSJens Wiklander #include <tee_api_defines.h>
10512cbf1dSJens Wiklander #include <tee_internal_api.h>
11512cbf1dSJens Wiklander #include <tee_internal_api_extensions.h>
12512cbf1dSJens Wiklander #include <utee_defines.h>
13512cbf1dSJens Wiklander #include <util.h>
14512cbf1dSJens Wiklander 
15512cbf1dSJens Wiklander #include "attributes.h"
16512cbf1dSJens Wiklander #include "object.h"
17512cbf1dSJens Wiklander #include "pkcs11_attributes.h"
18512cbf1dSJens Wiklander #include "pkcs11_helpers.h"
19512cbf1dSJens Wiklander #include "pkcs11_token.h"
20512cbf1dSJens Wiklander #include "processing.h"
21512cbf1dSJens Wiklander #include "serializer.h"
22512cbf1dSJens Wiklander 
23512cbf1dSJens Wiklander bool processing_is_tee_symm(enum pkcs11_mechanism_id proc_id)
24512cbf1dSJens Wiklander {
25512cbf1dSJens Wiklander 	switch (proc_id) {
26689f4e5bSRuchika Gupta 	/* Authentication */
27689f4e5bSRuchika Gupta 	case PKCS11_CKM_MD5_HMAC:
28689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA_1_HMAC:
29689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA224_HMAC:
30689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA256_HMAC:
31689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA384_HMAC:
32689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA512_HMAC:
33512cbf1dSJens Wiklander 	/* Cipherering */
34512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
35512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
36512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC_PAD:
37512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
38512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
39512cbf1dSJens Wiklander 		return true;
40512cbf1dSJens Wiklander 	default:
41512cbf1dSJens Wiklander 		return false;
42512cbf1dSJens Wiklander 	}
43512cbf1dSJens Wiklander }
44512cbf1dSJens Wiklander 
45512cbf1dSJens Wiklander static enum pkcs11_rc
46512cbf1dSJens Wiklander pkcs2tee_algorithm(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params)
47512cbf1dSJens Wiklander {
48512cbf1dSJens Wiklander 	static const struct {
49512cbf1dSJens Wiklander 		enum pkcs11_mechanism_id mech_id;
50512cbf1dSJens Wiklander 		uint32_t tee_id;
51512cbf1dSJens Wiklander 	} pkcs2tee_algo[] = {
52512cbf1dSJens Wiklander 		/* AES flavors */
53512cbf1dSJens Wiklander 		{ PKCS11_CKM_AES_ECB, TEE_ALG_AES_ECB_NOPAD },
54512cbf1dSJens Wiklander 		{ PKCS11_CKM_AES_CBC, TEE_ALG_AES_CBC_NOPAD },
55512cbf1dSJens Wiklander 		{ PKCS11_CKM_AES_CBC_PAD, TEE_ALG_AES_CBC_NOPAD },
56512cbf1dSJens Wiklander 		{ PKCS11_CKM_AES_CTR, TEE_ALG_AES_CTR },
57512cbf1dSJens Wiklander 		{ PKCS11_CKM_AES_CTS, TEE_ALG_AES_CTS },
58689f4e5bSRuchika Gupta 		/* HMAC flavors */
59689f4e5bSRuchika Gupta 		{ PKCS11_CKM_MD5_HMAC, TEE_ALG_HMAC_MD5 },
60689f4e5bSRuchika Gupta 		{ PKCS11_CKM_SHA_1_HMAC, TEE_ALG_HMAC_SHA1 },
61689f4e5bSRuchika Gupta 		{ PKCS11_CKM_SHA224_HMAC, TEE_ALG_HMAC_SHA224 },
62689f4e5bSRuchika Gupta 		{ PKCS11_CKM_SHA256_HMAC, TEE_ALG_HMAC_SHA256 },
63689f4e5bSRuchika Gupta 		{ PKCS11_CKM_SHA384_HMAC, TEE_ALG_HMAC_SHA384 },
64689f4e5bSRuchika Gupta 		{ PKCS11_CKM_SHA512_HMAC, TEE_ALG_HMAC_SHA512 },
65512cbf1dSJens Wiklander 	};
66512cbf1dSJens Wiklander 	size_t n = 0;
67512cbf1dSJens Wiklander 
68512cbf1dSJens Wiklander 	for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) {
69512cbf1dSJens Wiklander 		if (proc_params->id == pkcs2tee_algo[n].mech_id) {
70512cbf1dSJens Wiklander 			*tee_id = pkcs2tee_algo[n].tee_id;
71512cbf1dSJens Wiklander 			return PKCS11_CKR_OK;
72512cbf1dSJens Wiklander 		}
73512cbf1dSJens Wiklander 	}
74512cbf1dSJens Wiklander 
75512cbf1dSJens Wiklander 	return PKCS11_RV_NOT_IMPLEMENTED;
76512cbf1dSJens Wiklander }
77512cbf1dSJens Wiklander 
78512cbf1dSJens Wiklander static enum pkcs11_rc pkcs2tee_key_type(uint32_t *tee_type,
79512cbf1dSJens Wiklander 					struct pkcs11_object *obj)
80512cbf1dSJens Wiklander {
81512cbf1dSJens Wiklander 	static const struct {
82512cbf1dSJens Wiklander 		enum pkcs11_key_type key_type;
83512cbf1dSJens Wiklander 		uint32_t tee_id;
84512cbf1dSJens Wiklander 	} pkcs2tee_key_type[] = {
85512cbf1dSJens Wiklander 		{ PKCS11_CKK_AES, TEE_TYPE_AES },
86512cbf1dSJens Wiklander 		{ PKCS11_CKK_GENERIC_SECRET, TEE_TYPE_GENERIC_SECRET },
87512cbf1dSJens Wiklander 		{ PKCS11_CKK_MD5_HMAC, TEE_TYPE_HMAC_MD5 },
88512cbf1dSJens Wiklander 		{ PKCS11_CKK_SHA_1_HMAC, TEE_TYPE_HMAC_SHA1 },
89512cbf1dSJens Wiklander 		{ PKCS11_CKK_SHA224_HMAC, TEE_TYPE_HMAC_SHA224 },
90512cbf1dSJens Wiklander 		{ PKCS11_CKK_SHA256_HMAC, TEE_TYPE_HMAC_SHA256 },
91512cbf1dSJens Wiklander 		{ PKCS11_CKK_SHA384_HMAC, TEE_TYPE_HMAC_SHA384 },
92512cbf1dSJens Wiklander 		{ PKCS11_CKK_SHA512_HMAC, TEE_TYPE_HMAC_SHA512 },
93512cbf1dSJens Wiklander 	};
94512cbf1dSJens Wiklander 	size_t n = 0;
95512cbf1dSJens Wiklander 	enum pkcs11_key_type key_type = get_key_type(obj->attributes);
96512cbf1dSJens Wiklander 
97512cbf1dSJens Wiklander 	assert(get_class(obj->attributes) == PKCS11_CKO_SECRET_KEY);
98512cbf1dSJens Wiklander 
99512cbf1dSJens Wiklander 	for (n = 0; n < ARRAY_SIZE(pkcs2tee_key_type); n++) {
100512cbf1dSJens Wiklander 		if (pkcs2tee_key_type[n].key_type == key_type) {
101512cbf1dSJens Wiklander 			*tee_type = pkcs2tee_key_type[n].tee_id;
102512cbf1dSJens Wiklander 			return PKCS11_CKR_OK;
103512cbf1dSJens Wiklander 		}
104512cbf1dSJens Wiklander 	}
105512cbf1dSJens Wiklander 
106512cbf1dSJens Wiklander 	return PKCS11_RV_NOT_FOUND;
107512cbf1dSJens Wiklander }
108512cbf1dSJens Wiklander 
109*de94d6f8SRuchika Gupta static enum pkcs11_rc pkcsmech2tee_key_type(uint32_t *tee_type,
110*de94d6f8SRuchika Gupta 					    enum pkcs11_mechanism_id mech_id)
111*de94d6f8SRuchika Gupta {
112*de94d6f8SRuchika Gupta 	static const struct {
113*de94d6f8SRuchika Gupta 		enum pkcs11_mechanism_id mech;
114*de94d6f8SRuchika Gupta 		uint32_t tee_id;
115*de94d6f8SRuchika Gupta 	} pkcs2tee_key_type[] = {
116*de94d6f8SRuchika Gupta 		{ PKCS11_CKM_MD5_HMAC, TEE_TYPE_HMAC_MD5 },
117*de94d6f8SRuchika Gupta 		{ PKCS11_CKM_SHA_1_HMAC, TEE_TYPE_HMAC_SHA1 },
118*de94d6f8SRuchika Gupta 		{ PKCS11_CKM_SHA224_HMAC, TEE_TYPE_HMAC_SHA224 },
119*de94d6f8SRuchika Gupta 		{ PKCS11_CKM_SHA256_HMAC, TEE_TYPE_HMAC_SHA256 },
120*de94d6f8SRuchika Gupta 		{ PKCS11_CKM_SHA384_HMAC, TEE_TYPE_HMAC_SHA384 },
121*de94d6f8SRuchika Gupta 		{ PKCS11_CKM_SHA512_HMAC, TEE_TYPE_HMAC_SHA512 },
122*de94d6f8SRuchika Gupta 	};
123*de94d6f8SRuchika Gupta 	size_t n = 0;
124*de94d6f8SRuchika Gupta 
125*de94d6f8SRuchika Gupta 	for (n = 0; n < ARRAY_SIZE(pkcs2tee_key_type); n++) {
126*de94d6f8SRuchika Gupta 		if (pkcs2tee_key_type[n].mech == mech_id) {
127*de94d6f8SRuchika Gupta 			*tee_type = pkcs2tee_key_type[n].tee_id;
128*de94d6f8SRuchika Gupta 			return PKCS11_CKR_OK;
129*de94d6f8SRuchika Gupta 		}
130*de94d6f8SRuchika Gupta 	}
131*de94d6f8SRuchika Gupta 
132*de94d6f8SRuchika Gupta 	return PKCS11_RV_NOT_FOUND;
133*de94d6f8SRuchika Gupta }
134*de94d6f8SRuchika Gupta 
135512cbf1dSJens Wiklander static enum pkcs11_rc
136512cbf1dSJens Wiklander allocate_tee_operation(struct pkcs11_session *session,
137512cbf1dSJens Wiklander 		       enum processing_func function,
138512cbf1dSJens Wiklander 		       struct pkcs11_attribute_head *params,
139512cbf1dSJens Wiklander 		       struct pkcs11_object *obj)
140512cbf1dSJens Wiklander {
141512cbf1dSJens Wiklander 	uint32_t size = (uint32_t)get_object_key_bit_size(obj);
142512cbf1dSJens Wiklander 	uint32_t algo = 0;
143512cbf1dSJens Wiklander 	uint32_t mode = 0;
144512cbf1dSJens Wiklander 	TEE_Result res = TEE_ERROR_GENERIC;
145512cbf1dSJens Wiklander 
146512cbf1dSJens Wiklander 	assert(session->processing->tee_op_handle == TEE_HANDLE_NULL);
147512cbf1dSJens Wiklander 
148512cbf1dSJens Wiklander 	if (pkcs2tee_algorithm(&algo, params))
149512cbf1dSJens Wiklander 		return PKCS11_CKR_FUNCTION_FAILED;
150512cbf1dSJens Wiklander 
151512cbf1dSJens Wiklander 	/* Sign/Verify with AES or generic key relate to TEE MAC operation */
152689f4e5bSRuchika Gupta 	switch (params->id) {
153689f4e5bSRuchika Gupta 	case PKCS11_CKM_MD5_HMAC:
154689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA_1_HMAC:
155689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA224_HMAC:
156689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA256_HMAC:
157689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA384_HMAC:
158689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA512_HMAC:
159689f4e5bSRuchika Gupta 		mode = TEE_MODE_MAC;
160689f4e5bSRuchika Gupta 		break;
161689f4e5bSRuchika Gupta 	default:
162512cbf1dSJens Wiklander 		pkcs2tee_mode(&mode, function);
163689f4e5bSRuchika Gupta 		break;
164689f4e5bSRuchika Gupta 	}
165512cbf1dSJens Wiklander 
166512cbf1dSJens Wiklander 	res = TEE_AllocateOperation(&session->processing->tee_op_handle,
167512cbf1dSJens Wiklander 				    algo, mode, size);
168512cbf1dSJens Wiklander 	if (res)
169512cbf1dSJens Wiklander 		EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32" %#"PRIx32,
170512cbf1dSJens Wiklander 		     algo, mode, size);
171512cbf1dSJens Wiklander 
172512cbf1dSJens Wiklander 	if (res == TEE_ERROR_NOT_SUPPORTED)
173512cbf1dSJens Wiklander 		return PKCS11_CKR_MECHANISM_INVALID;
174512cbf1dSJens Wiklander 
175512cbf1dSJens Wiklander 	return tee2pkcs_error(res);
176512cbf1dSJens Wiklander }
177512cbf1dSJens Wiklander 
178512cbf1dSJens Wiklander static enum pkcs11_rc load_tee_key(struct pkcs11_session *session,
179*de94d6f8SRuchika Gupta 				   struct pkcs11_object *obj,
180*de94d6f8SRuchika Gupta 				   struct pkcs11_attribute_head *proc_params)
181512cbf1dSJens Wiklander {
182512cbf1dSJens Wiklander 	TEE_Attribute tee_attr = { };
183512cbf1dSJens Wiklander 	size_t object_size = 0;
184512cbf1dSJens Wiklander 	uint32_t tee_key_type = 0;
185*de94d6f8SRuchika Gupta 	enum pkcs11_key_type key_type = 0;
186512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
187512cbf1dSJens Wiklander 	TEE_Result res = TEE_ERROR_GENERIC;
188512cbf1dSJens Wiklander 
189512cbf1dSJens Wiklander 	if (obj->key_handle != TEE_HANDLE_NULL) {
190512cbf1dSJens Wiklander 		/* Key was already loaded and fits current need */
191512cbf1dSJens Wiklander 		goto key_ready;
192512cbf1dSJens Wiklander 	}
193512cbf1dSJens Wiklander 
194512cbf1dSJens Wiklander 	if (!pkcs2tee_load_attr(&tee_attr, TEE_ATTR_SECRET_VALUE,
195512cbf1dSJens Wiklander 				obj, PKCS11_CKA_VALUE)) {
196512cbf1dSJens Wiklander 		EMSG("No secret found");
197512cbf1dSJens Wiklander 		return PKCS11_CKR_FUNCTION_FAILED;
198512cbf1dSJens Wiklander 	}
199512cbf1dSJens Wiklander 
200*de94d6f8SRuchika Gupta 	switch (proc_params->id) {
201*de94d6f8SRuchika Gupta 	case PKCS11_CKM_MD5_HMAC:
202*de94d6f8SRuchika Gupta 	case PKCS11_CKM_SHA_1_HMAC:
203*de94d6f8SRuchika Gupta 	case PKCS11_CKM_SHA224_HMAC:
204*de94d6f8SRuchika Gupta 	case PKCS11_CKM_SHA256_HMAC:
205*de94d6f8SRuchika Gupta 	case PKCS11_CKM_SHA384_HMAC:
206*de94d6f8SRuchika Gupta 	case PKCS11_CKM_SHA512_HMAC:
207*de94d6f8SRuchika Gupta 		key_type = get_key_type(obj->attributes);
208*de94d6f8SRuchika Gupta 		/*
209*de94d6f8SRuchika Gupta 		 * If Object Key type is PKCS11_CKK_GENERIC_SECRET,
210*de94d6f8SRuchika Gupta 		 * determine the tee_key_type using the
211*de94d6f8SRuchika Gupta 		 * mechanism instead of object key_type.
212*de94d6f8SRuchika Gupta 		 */
213*de94d6f8SRuchika Gupta 		if (key_type == PKCS11_CKK_GENERIC_SECRET)
214*de94d6f8SRuchika Gupta 			rc = pkcsmech2tee_key_type(&tee_key_type,
215*de94d6f8SRuchika Gupta 						   proc_params->id);
216*de94d6f8SRuchika Gupta 		else
217512cbf1dSJens Wiklander 			rc = pkcs2tee_key_type(&tee_key_type, obj);
218*de94d6f8SRuchika Gupta 
219*de94d6f8SRuchika Gupta 		break;
220*de94d6f8SRuchika Gupta 	default:
221*de94d6f8SRuchika Gupta 		/*
222*de94d6f8SRuchika Gupta 		 * For all other mechanisms, use object key_type
223*de94d6f8SRuchika Gupta 		 * to determine the corresponding tee_key_type
224*de94d6f8SRuchika Gupta 		 */
225*de94d6f8SRuchika Gupta 		rc = pkcs2tee_key_type(&tee_key_type, obj);
226*de94d6f8SRuchika Gupta 		break;
227*de94d6f8SRuchika Gupta 	}
228*de94d6f8SRuchika Gupta 
229512cbf1dSJens Wiklander 	if (rc)
230512cbf1dSJens Wiklander 		return rc;
231512cbf1dSJens Wiklander 
232512cbf1dSJens Wiklander 	object_size = get_object_key_bit_size(obj);
233512cbf1dSJens Wiklander 	if (!object_size)
234512cbf1dSJens Wiklander 		return PKCS11_CKR_GENERAL_ERROR;
235512cbf1dSJens Wiklander 
236512cbf1dSJens Wiklander 	res = TEE_AllocateTransientObject(tee_key_type, object_size,
237512cbf1dSJens Wiklander 					  &obj->key_handle);
238512cbf1dSJens Wiklander 	if (res) {
239512cbf1dSJens Wiklander 		DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res);
240512cbf1dSJens Wiklander 		return tee2pkcs_error(res);
241512cbf1dSJens Wiklander 	}
242512cbf1dSJens Wiklander 
243512cbf1dSJens Wiklander 	res = TEE_PopulateTransientObject(obj->key_handle, &tee_attr, 1);
244512cbf1dSJens Wiklander 	if (res) {
245512cbf1dSJens Wiklander 		DMSG("TEE_PopulateTransientObject failed, %#"PRIx32, res);
246512cbf1dSJens Wiklander 		goto error;
247512cbf1dSJens Wiklander 	}
248512cbf1dSJens Wiklander 
249512cbf1dSJens Wiklander key_ready:
250512cbf1dSJens Wiklander 	res = TEE_SetOperationKey(session->processing->tee_op_handle,
251512cbf1dSJens Wiklander 				  obj->key_handle);
252512cbf1dSJens Wiklander 	if (res) {
253512cbf1dSJens Wiklander 		DMSG("TEE_SetOperationKey failed, %#"PRIx32, res);
254512cbf1dSJens Wiklander 		goto error;
255512cbf1dSJens Wiklander 	}
256512cbf1dSJens Wiklander 
257512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
258512cbf1dSJens Wiklander 
259512cbf1dSJens Wiklander error:
260512cbf1dSJens Wiklander 	TEE_FreeTransientObject(obj->key_handle);
261512cbf1dSJens Wiklander 	obj->key_handle = TEE_HANDLE_NULL;
262512cbf1dSJens Wiklander 
263512cbf1dSJens Wiklander 	return tee2pkcs_error(res);
264512cbf1dSJens Wiklander }
265512cbf1dSJens Wiklander 
266512cbf1dSJens Wiklander static enum pkcs11_rc
267512cbf1dSJens Wiklander init_tee_operation(struct pkcs11_session *session,
268512cbf1dSJens Wiklander 		   struct pkcs11_attribute_head *proc_params)
269512cbf1dSJens Wiklander {
270512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
271512cbf1dSJens Wiklander 
272512cbf1dSJens Wiklander 	switch (proc_params->id) {
273689f4e5bSRuchika Gupta 	case PKCS11_CKM_MD5_HMAC:
274689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA_1_HMAC:
275689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA224_HMAC:
276689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA256_HMAC:
277689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA384_HMAC:
278689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA512_HMAC:
279689f4e5bSRuchika Gupta 		if (proc_params->size)
280689f4e5bSRuchika Gupta 			return PKCS11_CKR_MECHANISM_PARAM_INVALID;
281689f4e5bSRuchika Gupta 
282689f4e5bSRuchika Gupta 		TEE_MACInit(session->processing->tee_op_handle, NULL, 0);
283689f4e5bSRuchika Gupta 		rc = PKCS11_CKR_OK;
284689f4e5bSRuchika Gupta 		break;
285512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
286512cbf1dSJens Wiklander 		if (proc_params->size)
287512cbf1dSJens Wiklander 			return PKCS11_CKR_MECHANISM_PARAM_INVALID;
288512cbf1dSJens Wiklander 
289512cbf1dSJens Wiklander 		TEE_CipherInit(session->processing->tee_op_handle, NULL, 0);
290512cbf1dSJens Wiklander 		rc = PKCS11_CKR_OK;
291512cbf1dSJens Wiklander 		break;
292512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
293512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC_PAD:
294512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
295512cbf1dSJens Wiklander 		if (proc_params->size != 16)
296512cbf1dSJens Wiklander 			return PKCS11_CKR_MECHANISM_PARAM_INVALID;
297512cbf1dSJens Wiklander 
298512cbf1dSJens Wiklander 		TEE_CipherInit(session->processing->tee_op_handle,
299512cbf1dSJens Wiklander 			       proc_params->data, 16);
300512cbf1dSJens Wiklander 		rc = PKCS11_CKR_OK;
301512cbf1dSJens Wiklander 		break;
302512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
303512cbf1dSJens Wiklander 		rc = tee_init_ctr_operation(session->processing,
304512cbf1dSJens Wiklander 					    proc_params->data,
305512cbf1dSJens Wiklander 					    proc_params->size);
306512cbf1dSJens Wiklander 		break;
307512cbf1dSJens Wiklander 	default:
308512cbf1dSJens Wiklander 		TEE_Panic(proc_params->id);
309512cbf1dSJens Wiklander 		break;
310512cbf1dSJens Wiklander 	}
311512cbf1dSJens Wiklander 
312512cbf1dSJens Wiklander 	return rc;
313512cbf1dSJens Wiklander }
314512cbf1dSJens Wiklander 
315512cbf1dSJens Wiklander enum pkcs11_rc init_symm_operation(struct pkcs11_session *session,
316512cbf1dSJens Wiklander 				   enum processing_func function,
317512cbf1dSJens Wiklander 				   struct pkcs11_attribute_head *proc_params,
318512cbf1dSJens Wiklander 				   struct pkcs11_object *obj)
319512cbf1dSJens Wiklander {
320512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_OK;
321512cbf1dSJens Wiklander 
322512cbf1dSJens Wiklander 	assert(processing_is_tee_symm(proc_params->id));
323512cbf1dSJens Wiklander 
324512cbf1dSJens Wiklander 	rc = allocate_tee_operation(session, function, proc_params, obj);
325512cbf1dSJens Wiklander 	if (rc)
326512cbf1dSJens Wiklander 		return rc;
327512cbf1dSJens Wiklander 
328*de94d6f8SRuchika Gupta 	rc = load_tee_key(session, obj, proc_params);
329512cbf1dSJens Wiklander 	if (rc)
330512cbf1dSJens Wiklander 		return rc;
331512cbf1dSJens Wiklander 
332512cbf1dSJens Wiklander 	return init_tee_operation(session, proc_params);
333512cbf1dSJens Wiklander }
334512cbf1dSJens Wiklander 
335512cbf1dSJens Wiklander /* Validate input buffer size as per PKCS#11 constraints */
336512cbf1dSJens Wiklander static enum pkcs11_rc input_data_size_is_valid(struct active_processing *proc,
337512cbf1dSJens Wiklander 					       enum processing_func function,
338512cbf1dSJens Wiklander 					       size_t in_size)
339512cbf1dSJens Wiklander {
340512cbf1dSJens Wiklander 	switch (proc->mecha_type) {
341512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
342512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
343512cbf1dSJens Wiklander 		if (function == PKCS11_FUNCTION_ENCRYPT &&
344512cbf1dSJens Wiklander 		    in_size % TEE_AES_BLOCK_SIZE)
345512cbf1dSJens Wiklander 			return PKCS11_CKR_DATA_LEN_RANGE;
346512cbf1dSJens Wiklander 		if (function == PKCS11_FUNCTION_DECRYPT &&
347512cbf1dSJens Wiklander 		    in_size % TEE_AES_BLOCK_SIZE)
348512cbf1dSJens Wiklander 			return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
349512cbf1dSJens Wiklander 		break;
350512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC_PAD:
351512cbf1dSJens Wiklander 		if (function == PKCS11_FUNCTION_DECRYPT &&
352512cbf1dSJens Wiklander 		    in_size % TEE_AES_BLOCK_SIZE)
353512cbf1dSJens Wiklander 			return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
354512cbf1dSJens Wiklander 		break;
355512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
356512cbf1dSJens Wiklander 		if (function == PKCS11_FUNCTION_ENCRYPT &&
357512cbf1dSJens Wiklander 		    in_size < TEE_AES_BLOCK_SIZE)
358512cbf1dSJens Wiklander 			return PKCS11_CKR_DATA_LEN_RANGE;
359512cbf1dSJens Wiklander 		if (function == PKCS11_FUNCTION_DECRYPT &&
360512cbf1dSJens Wiklander 		    in_size < TEE_AES_BLOCK_SIZE)
361512cbf1dSJens Wiklander 			return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
362512cbf1dSJens Wiklander 		break;
363512cbf1dSJens Wiklander 	default:
364512cbf1dSJens Wiklander 		break;
365512cbf1dSJens Wiklander 	}
366512cbf1dSJens Wiklander 
367512cbf1dSJens Wiklander 	return PKCS11_CKR_OK;
368512cbf1dSJens Wiklander }
369512cbf1dSJens Wiklander 
370689f4e5bSRuchika Gupta /* Validate input buffer size as per PKCS#11 constraints */
371689f4e5bSRuchika Gupta static enum pkcs11_rc input_sign_size_is_valid(struct active_processing *proc,
372689f4e5bSRuchika Gupta 					       size_t in_size)
373689f4e5bSRuchika Gupta {
374689f4e5bSRuchika Gupta 	size_t sign_sz = 0;
375689f4e5bSRuchika Gupta 
376689f4e5bSRuchika Gupta 	switch (proc->mecha_type) {
377689f4e5bSRuchika Gupta 	case PKCS11_CKM_MD5_HMAC:
378689f4e5bSRuchika Gupta 		sign_sz = TEE_MD5_HASH_SIZE;
379689f4e5bSRuchika Gupta 		break;
380689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA_1_HMAC:
381689f4e5bSRuchika Gupta 		sign_sz = TEE_SHA1_HASH_SIZE;
382689f4e5bSRuchika Gupta 		break;
383689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA224_HMAC:
384689f4e5bSRuchika Gupta 		sign_sz = TEE_SHA224_HASH_SIZE;
385689f4e5bSRuchika Gupta 		break;
386689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA256_HMAC:
387689f4e5bSRuchika Gupta 		sign_sz = TEE_SHA256_HASH_SIZE;
388689f4e5bSRuchika Gupta 		break;
389689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA384_HMAC:
390689f4e5bSRuchika Gupta 		sign_sz = TEE_SHA384_HASH_SIZE;
391689f4e5bSRuchika Gupta 		break;
392689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA512_HMAC:
393689f4e5bSRuchika Gupta 		sign_sz = TEE_SHA512_HASH_SIZE;
394689f4e5bSRuchika Gupta 		break;
395689f4e5bSRuchika Gupta 	default:
396689f4e5bSRuchika Gupta 		return PKCS11_CKR_GENERAL_ERROR;
397689f4e5bSRuchika Gupta 	}
398689f4e5bSRuchika Gupta 
399689f4e5bSRuchika Gupta 	if (in_size < sign_sz)
400689f4e5bSRuchika Gupta 		return PKCS11_CKR_SIGNATURE_LEN_RANGE;
401689f4e5bSRuchika Gupta 
402689f4e5bSRuchika Gupta 	return PKCS11_CKR_OK;
403689f4e5bSRuchika Gupta }
404689f4e5bSRuchika Gupta 
405512cbf1dSJens Wiklander /*
406512cbf1dSJens Wiklander  * step_sym_cipher - processing symmetric (and related) cipher operation step
407512cbf1dSJens Wiklander  *
408512cbf1dSJens Wiklander  * @session - current session
409512cbf1dSJens Wiklander  * @function - processing function (encrypt, decrypt, sign, ...)
410512cbf1dSJens Wiklander  * @step - step ID in the processing (oneshot, update, final)
411512cbf1dSJens Wiklander  * @ptype - invocation parameter types
412512cbf1dSJens Wiklander  * @params - invocation parameter references
413512cbf1dSJens Wiklander  */
414512cbf1dSJens Wiklander enum pkcs11_rc step_symm_operation(struct pkcs11_session *session,
415512cbf1dSJens Wiklander 				   enum processing_func function,
416512cbf1dSJens Wiklander 				   enum processing_step step,
417512cbf1dSJens Wiklander 				   uint32_t ptypes, TEE_Param *params)
418512cbf1dSJens Wiklander {
419512cbf1dSJens Wiklander 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
420512cbf1dSJens Wiklander 	TEE_Result res = TEE_ERROR_GENERIC;
421512cbf1dSJens Wiklander 	void *in_buf = NULL;
422512cbf1dSJens Wiklander 	size_t in_size = 0;
423512cbf1dSJens Wiklander 	void *out_buf = NULL;
424512cbf1dSJens Wiklander 	uint32_t out_size = 0;
425512cbf1dSJens Wiklander 	void *in2_buf = NULL;
426512cbf1dSJens Wiklander 	uint32_t in2_size = 0;
427512cbf1dSJens Wiklander 	bool output_data = false;
428512cbf1dSJens Wiklander 	struct active_processing *proc = session->processing;
429512cbf1dSJens Wiklander 
430512cbf1dSJens Wiklander 	if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) {
431512cbf1dSJens Wiklander 		in_buf = params[1].memref.buffer;
432512cbf1dSJens Wiklander 		in_size = params[1].memref.size;
433512cbf1dSJens Wiklander 		if (in_size && !in_buf)
434512cbf1dSJens Wiklander 			return PKCS11_CKR_ARGUMENTS_BAD;
435512cbf1dSJens Wiklander 	}
436512cbf1dSJens Wiklander 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_INPUT) {
437512cbf1dSJens Wiklander 		in2_buf = params[2].memref.buffer;
438512cbf1dSJens Wiklander 		in2_size = params[2].memref.size;
439512cbf1dSJens Wiklander 		if (in2_size && !in2_buf)
440512cbf1dSJens Wiklander 			return PKCS11_CKR_ARGUMENTS_BAD;
441512cbf1dSJens Wiklander 	}
442512cbf1dSJens Wiklander 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) {
443512cbf1dSJens Wiklander 		out_buf = params[2].memref.buffer;
444512cbf1dSJens Wiklander 		out_size = params[2].memref.size;
445512cbf1dSJens Wiklander 		if (out_size && !out_buf)
446512cbf1dSJens Wiklander 			return PKCS11_CKR_ARGUMENTS_BAD;
447512cbf1dSJens Wiklander 	}
448512cbf1dSJens Wiklander 	if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
449512cbf1dSJens Wiklander 		return PKCS11_CKR_ARGUMENTS_BAD;
450512cbf1dSJens Wiklander 
451512cbf1dSJens Wiklander 	switch (step) {
452512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_ONESHOT:
453512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_UPDATE:
454512cbf1dSJens Wiklander 	case PKCS11_FUNC_STEP_FINAL:
455512cbf1dSJens Wiklander 		break;
456512cbf1dSJens Wiklander 	default:
457512cbf1dSJens Wiklander 		return PKCS11_CKR_GENERAL_ERROR;
458512cbf1dSJens Wiklander 	}
459512cbf1dSJens Wiklander 
460512cbf1dSJens Wiklander 	if (step != PKCS11_FUNC_STEP_FINAL) {
461512cbf1dSJens Wiklander 		rc = input_data_size_is_valid(proc, function, in_size);
462512cbf1dSJens Wiklander 		if (rc)
463512cbf1dSJens Wiklander 			return rc;
464512cbf1dSJens Wiklander 	}
465512cbf1dSJens Wiklander 
466512cbf1dSJens Wiklander 	/*
467512cbf1dSJens Wiklander 	 * Feed active operation with data
468512cbf1dSJens Wiklander 	 */
469512cbf1dSJens Wiklander 	switch (proc->mecha_type) {
470689f4e5bSRuchika Gupta 	case PKCS11_CKM_MD5_HMAC:
471689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA_1_HMAC:
472689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA224_HMAC:
473689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA256_HMAC:
474689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA384_HMAC:
475689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA512_HMAC:
476689f4e5bSRuchika Gupta 		if (step == PKCS11_FUNC_STEP_FINAL ||
477689f4e5bSRuchika Gupta 		    step == PKCS11_FUNC_STEP_ONESHOT)
478689f4e5bSRuchika Gupta 			break;
479689f4e5bSRuchika Gupta 
480689f4e5bSRuchika Gupta 		if (!in_buf) {
481689f4e5bSRuchika Gupta 			DMSG("No input data");
482689f4e5bSRuchika Gupta 			return PKCS11_CKR_ARGUMENTS_BAD;
483689f4e5bSRuchika Gupta 		}
484689f4e5bSRuchika Gupta 
485689f4e5bSRuchika Gupta 		switch (function) {
486689f4e5bSRuchika Gupta 		case PKCS11_FUNCTION_SIGN:
487689f4e5bSRuchika Gupta 		case PKCS11_FUNCTION_VERIFY:
488689f4e5bSRuchika Gupta 			TEE_MACUpdate(proc->tee_op_handle, in_buf, in_size);
489689f4e5bSRuchika Gupta 			rc = PKCS11_CKR_OK;
490689f4e5bSRuchika Gupta 			break;
491689f4e5bSRuchika Gupta 		default:
492689f4e5bSRuchika Gupta 			TEE_Panic(function);
493689f4e5bSRuchika Gupta 			break;
494689f4e5bSRuchika Gupta 		}
495689f4e5bSRuchika Gupta 		break;
496689f4e5bSRuchika Gupta 
497512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
498512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
499512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC_PAD:
500512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
501512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
502512cbf1dSJens Wiklander 		if (step == PKCS11_FUNC_STEP_FINAL ||
503512cbf1dSJens Wiklander 		    step == PKCS11_FUNC_STEP_ONESHOT)
504512cbf1dSJens Wiklander 			break;
505512cbf1dSJens Wiklander 
506512cbf1dSJens Wiklander 		if (!in_buf) {
507512cbf1dSJens Wiklander 			EMSG("No input data");
508512cbf1dSJens Wiklander 			return PKCS11_CKR_ARGUMENTS_BAD;
509512cbf1dSJens Wiklander 		}
510512cbf1dSJens Wiklander 
511512cbf1dSJens Wiklander 		switch (function) {
512512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_ENCRYPT:
513512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_DECRYPT:
514512cbf1dSJens Wiklander 			res = TEE_CipherUpdate(proc->tee_op_handle,
515512cbf1dSJens Wiklander 					       in_buf, in_size,
516512cbf1dSJens Wiklander 						out_buf, &out_size);
517512cbf1dSJens Wiklander 			output_data = true;
518512cbf1dSJens Wiklander 			rc = tee2pkcs_error(res);
519512cbf1dSJens Wiklander 			break;
520512cbf1dSJens Wiklander 		default:
521512cbf1dSJens Wiklander 			TEE_Panic(function);
522512cbf1dSJens Wiklander 			break;
523512cbf1dSJens Wiklander 		}
524512cbf1dSJens Wiklander 		break;
525512cbf1dSJens Wiklander 
526512cbf1dSJens Wiklander 	default:
527512cbf1dSJens Wiklander 		TEE_Panic(proc->mecha_type);
528512cbf1dSJens Wiklander 		break;
529512cbf1dSJens Wiklander 	}
530512cbf1dSJens Wiklander 
531512cbf1dSJens Wiklander 	if (step == PKCS11_FUNC_STEP_UPDATE)
532512cbf1dSJens Wiklander 		goto out;
533512cbf1dSJens Wiklander 
534512cbf1dSJens Wiklander 	/*
535512cbf1dSJens Wiklander 	 * Finalize (PKCS11_FUNC_STEP_ONESHOT/_FINAL) operation
536512cbf1dSJens Wiklander 	 */
537512cbf1dSJens Wiklander 	switch (session->processing->mecha_type) {
538689f4e5bSRuchika Gupta 	case PKCS11_CKM_MD5_HMAC:
539689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA_1_HMAC:
540689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA224_HMAC:
541689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA256_HMAC:
542689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA384_HMAC:
543689f4e5bSRuchika Gupta 	case PKCS11_CKM_SHA512_HMAC:
544689f4e5bSRuchika Gupta 		switch (function) {
545689f4e5bSRuchika Gupta 		case PKCS11_FUNCTION_SIGN:
546689f4e5bSRuchika Gupta 			res = TEE_MACComputeFinal(proc->tee_op_handle,
547689f4e5bSRuchika Gupta 						  in_buf, in_size, out_buf,
548689f4e5bSRuchika Gupta 						  &out_size);
549689f4e5bSRuchika Gupta 			output_data = true;
550689f4e5bSRuchika Gupta 			rc = tee2pkcs_error(res);
551689f4e5bSRuchika Gupta 			break;
552689f4e5bSRuchika Gupta 		case PKCS11_FUNCTION_VERIFY:
553689f4e5bSRuchika Gupta 			rc = input_sign_size_is_valid(proc, in2_size);
554689f4e5bSRuchika Gupta 			if (rc)
555689f4e5bSRuchika Gupta 				return rc;
556689f4e5bSRuchika Gupta 			res = TEE_MACCompareFinal(proc->tee_op_handle,
557689f4e5bSRuchika Gupta 						  in_buf, in_size, in2_buf,
558689f4e5bSRuchika Gupta 						  in2_size);
559689f4e5bSRuchika Gupta 			rc = tee2pkcs_error(res);
560689f4e5bSRuchika Gupta 			break;
561689f4e5bSRuchika Gupta 		default:
562689f4e5bSRuchika Gupta 			TEE_Panic(function);
563689f4e5bSRuchika Gupta 			break;
564689f4e5bSRuchika Gupta 		}
565689f4e5bSRuchika Gupta 		break;
566689f4e5bSRuchika Gupta 
567512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_ECB:
568512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC:
569512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CBC_PAD:
570512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTS:
571512cbf1dSJens Wiklander 	case PKCS11_CKM_AES_CTR:
572512cbf1dSJens Wiklander 		if (step == PKCS11_FUNC_STEP_ONESHOT && !in_buf) {
573512cbf1dSJens Wiklander 			EMSG("No input data");
574512cbf1dSJens Wiklander 			return PKCS11_CKR_ARGUMENTS_BAD;
575512cbf1dSJens Wiklander 		}
576512cbf1dSJens Wiklander 
577512cbf1dSJens Wiklander 		switch (function) {
578512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_ENCRYPT:
579512cbf1dSJens Wiklander 		case PKCS11_FUNCTION_DECRYPT:
580512cbf1dSJens Wiklander 			res = TEE_CipherDoFinal(proc->tee_op_handle,
581512cbf1dSJens Wiklander 						in_buf, in_size,
582512cbf1dSJens Wiklander 						out_buf, &out_size);
583512cbf1dSJens Wiklander 			output_data = true;
584512cbf1dSJens Wiklander 			rc = tee2pkcs_error(res);
585512cbf1dSJens Wiklander 			break;
586512cbf1dSJens Wiklander 		default:
587512cbf1dSJens Wiklander 			TEE_Panic(function);
588512cbf1dSJens Wiklander 			break;
589512cbf1dSJens Wiklander 		}
590512cbf1dSJens Wiklander 		break;
591512cbf1dSJens Wiklander 	default:
592512cbf1dSJens Wiklander 		TEE_Panic(proc->mecha_type);
593512cbf1dSJens Wiklander 		break;
594512cbf1dSJens Wiklander 	}
595512cbf1dSJens Wiklander 
596512cbf1dSJens Wiklander out:
597512cbf1dSJens Wiklander 	if (output_data &&
598512cbf1dSJens Wiklander 	    (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)) {
599512cbf1dSJens Wiklander 		switch (TEE_PARAM_TYPE_GET(ptypes, 2)) {
600512cbf1dSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
601512cbf1dSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
602512cbf1dSJens Wiklander 			params[2].memref.size = out_size;
603512cbf1dSJens Wiklander 			break;
604512cbf1dSJens Wiklander 		default:
605512cbf1dSJens Wiklander 			rc = PKCS11_CKR_ARGUMENTS_BAD;
606512cbf1dSJens Wiklander 			break;
607512cbf1dSJens Wiklander 		}
608512cbf1dSJens Wiklander 	}
609512cbf1dSJens Wiklander 
610512cbf1dSJens Wiklander 	return rc;
611512cbf1dSJens Wiklander }
612