xref: /optee_os/ta/pkcs11/src/processing_asymm.c (revision fb279d8b608ec28f6c0a1d362c1a5a9751db5076)
1*fb279d8bSVesa Jääskeläinen // SPDX-License-Identifier: BSD-2-Clause
2*fb279d8bSVesa Jääskeläinen /*
3*fb279d8bSVesa Jääskeläinen  * Copyright (c) 2018-2020, Linaro Limited
4*fb279d8bSVesa Jääskeläinen  */
5*fb279d8bSVesa Jääskeläinen 
6*fb279d8bSVesa Jääskeläinen #include <assert.h>
7*fb279d8bSVesa Jääskeläinen #include <compiler.h>
8*fb279d8bSVesa Jääskeläinen #include <tee_api_defines.h>
9*fb279d8bSVesa Jääskeläinen #include <tee_internal_api.h>
10*fb279d8bSVesa Jääskeläinen #include <tee_internal_api_extensions.h>
11*fb279d8bSVesa Jääskeläinen 
12*fb279d8bSVesa Jääskeläinen #include "attributes.h"
13*fb279d8bSVesa Jääskeläinen #include "pkcs11_helpers.h"
14*fb279d8bSVesa Jääskeläinen #include "pkcs11_token.h"
15*fb279d8bSVesa Jääskeläinen #include "processing.h"
16*fb279d8bSVesa Jääskeläinen #include "serializer.h"
17*fb279d8bSVesa Jääskeläinen 
18*fb279d8bSVesa Jääskeläinen bool processing_is_tee_asymm(uint32_t proc_id)
19*fb279d8bSVesa Jääskeläinen {
20*fb279d8bSVesa Jääskeläinen 	switch (proc_id) {
21*fb279d8bSVesa Jääskeläinen 	/* EC flavors */
22*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
23*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
24*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
25*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
26*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
27*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
28*fb279d8bSVesa Jääskeläinen 		return true;
29*fb279d8bSVesa Jääskeläinen 	default:
30*fb279d8bSVesa Jääskeläinen 		return false;
31*fb279d8bSVesa Jääskeläinen 	}
32*fb279d8bSVesa Jääskeläinen }
33*fb279d8bSVesa Jääskeläinen 
34*fb279d8bSVesa Jääskeläinen static enum pkcs11_rc
35*fb279d8bSVesa Jääskeläinen pkcs2tee_algorithm(uint32_t *tee_id, uint32_t *tee_hash_id,
36*fb279d8bSVesa Jääskeläinen 		   enum processing_func function __unused,
37*fb279d8bSVesa Jääskeläinen 		   struct pkcs11_attribute_head *proc_params,
38*fb279d8bSVesa Jääskeläinen 		   struct pkcs11_object *obj)
39*fb279d8bSVesa Jääskeläinen {
40*fb279d8bSVesa Jääskeläinen 	static const struct {
41*fb279d8bSVesa Jääskeläinen 		enum pkcs11_mechanism_id mech_id;
42*fb279d8bSVesa Jääskeläinen 		uint32_t tee_id;
43*fb279d8bSVesa Jääskeläinen 		uint32_t tee_hash_id;
44*fb279d8bSVesa Jääskeläinen 	} pkcs2tee_algo[] = {
45*fb279d8bSVesa Jääskeläinen 		/* EC flavors (Must find key size from the object) */
46*fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA, 1, 0 },
47*fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA1, 1, TEE_ALG_SHA1 },
48*fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA224, 1, TEE_ALG_SHA224 },
49*fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA256, 1, TEE_ALG_SHA256 },
50*fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA384, 1, TEE_ALG_SHA384 },
51*fb279d8bSVesa Jääskeläinen 		{ PKCS11_CKM_ECDSA_SHA512, 1, TEE_ALG_SHA512 },
52*fb279d8bSVesa Jääskeläinen 	};
53*fb279d8bSVesa Jääskeläinen 	size_t n = 0;
54*fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
55*fb279d8bSVesa Jääskeläinen 
56*fb279d8bSVesa Jääskeläinen 	for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) {
57*fb279d8bSVesa Jääskeläinen 		if (pkcs2tee_algo[n].mech_id == proc_params->id) {
58*fb279d8bSVesa Jääskeläinen 			*tee_id = pkcs2tee_algo[n].tee_id;
59*fb279d8bSVesa Jääskeläinen 			*tee_hash_id = pkcs2tee_algo[n].tee_hash_id;
60*fb279d8bSVesa Jääskeläinen 			break;
61*fb279d8bSVesa Jääskeläinen 		}
62*fb279d8bSVesa Jääskeläinen 	}
63*fb279d8bSVesa Jääskeläinen 
64*fb279d8bSVesa Jääskeläinen 	if (n == ARRAY_SIZE(pkcs2tee_algo))
65*fb279d8bSVesa Jääskeläinen 		return PKCS11_RV_NOT_IMPLEMENTED;
66*fb279d8bSVesa Jääskeläinen 
67*fb279d8bSVesa Jääskeläinen 	switch (proc_params->id) {
68*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
69*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
70*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
71*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
72*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
73*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
74*fb279d8bSVesa Jääskeläinen 		rc = pkcs2tee_algo_ecdsa(tee_id, proc_params, obj);
75*fb279d8bSVesa Jääskeläinen 		break;
76*fb279d8bSVesa Jääskeläinen 	default:
77*fb279d8bSVesa Jääskeläinen 		rc = PKCS11_CKR_OK;
78*fb279d8bSVesa Jääskeläinen 		break;
79*fb279d8bSVesa Jääskeläinen 	}
80*fb279d8bSVesa Jääskeläinen 
81*fb279d8bSVesa Jääskeläinen 	return rc;
82*fb279d8bSVesa Jääskeläinen }
83*fb279d8bSVesa Jääskeläinen 
84*fb279d8bSVesa Jääskeläinen static enum pkcs11_rc pkcs2tee_key_type(uint32_t *tee_type,
85*fb279d8bSVesa Jääskeläinen 					struct pkcs11_object *obj,
86*fb279d8bSVesa Jääskeläinen 					enum processing_func function)
87*fb279d8bSVesa Jääskeläinen {
88*fb279d8bSVesa Jääskeläinen 	enum pkcs11_class_id class = get_class(obj->attributes);
89*fb279d8bSVesa Jääskeläinen 	enum pkcs11_key_type type = get_key_type(obj->attributes);
90*fb279d8bSVesa Jääskeläinen 
91*fb279d8bSVesa Jääskeläinen 	switch (class) {
92*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKO_PUBLIC_KEY:
93*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKO_PRIVATE_KEY:
94*fb279d8bSVesa Jääskeläinen 		break;
95*fb279d8bSVesa Jääskeläinen 	default:
96*fb279d8bSVesa Jääskeläinen 		TEE_Panic(class);
97*fb279d8bSVesa Jääskeläinen 		break;
98*fb279d8bSVesa Jääskeläinen 	}
99*fb279d8bSVesa Jääskeläinen 
100*fb279d8bSVesa Jääskeläinen 	switch (type) {
101*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKK_EC:
102*fb279d8bSVesa Jääskeläinen 		assert(function != PKCS11_FUNCTION_DERIVE);
103*fb279d8bSVesa Jääskeläinen 
104*fb279d8bSVesa Jääskeläinen 		if (class == PKCS11_CKO_PRIVATE_KEY)
105*fb279d8bSVesa Jääskeläinen 			*tee_type = TEE_TYPE_ECDSA_KEYPAIR;
106*fb279d8bSVesa Jääskeläinen 		else
107*fb279d8bSVesa Jääskeläinen 			*tee_type = TEE_TYPE_ECDSA_PUBLIC_KEY;
108*fb279d8bSVesa Jääskeläinen 		break;
109*fb279d8bSVesa Jääskeläinen 	default:
110*fb279d8bSVesa Jääskeläinen 		TEE_Panic(type);
111*fb279d8bSVesa Jääskeläinen 		break;
112*fb279d8bSVesa Jääskeläinen 	}
113*fb279d8bSVesa Jääskeläinen 
114*fb279d8bSVesa Jääskeläinen 	return PKCS11_CKR_OK;
115*fb279d8bSVesa Jääskeläinen }
116*fb279d8bSVesa Jääskeläinen 
117*fb279d8bSVesa Jääskeläinen static enum pkcs11_rc
118*fb279d8bSVesa Jääskeläinen allocate_tee_operation(struct pkcs11_session *session,
119*fb279d8bSVesa Jääskeläinen 		       enum processing_func function,
120*fb279d8bSVesa Jääskeläinen 		       struct pkcs11_attribute_head *params,
121*fb279d8bSVesa Jääskeläinen 		       struct pkcs11_object *obj)
122*fb279d8bSVesa Jääskeläinen {
123*fb279d8bSVesa Jääskeläinen 	uint32_t size = (uint32_t)get_object_key_bit_size(obj);
124*fb279d8bSVesa Jääskeläinen 	uint32_t algo = 0;
125*fb279d8bSVesa Jääskeläinen 	uint32_t hash_algo = 0;
126*fb279d8bSVesa Jääskeläinen 	uint32_t mode = 0;
127*fb279d8bSVesa Jääskeläinen 	uint32_t hash_mode = 0;
128*fb279d8bSVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
129*fb279d8bSVesa Jääskeläinen 	struct active_processing *processing = session->processing;
130*fb279d8bSVesa Jääskeläinen 
131*fb279d8bSVesa Jääskeläinen 	assert(processing->tee_op_handle == TEE_HANDLE_NULL);
132*fb279d8bSVesa Jääskeläinen 	assert(processing->tee_hash_op_handle == TEE_HANDLE_NULL);
133*fb279d8bSVesa Jääskeläinen 
134*fb279d8bSVesa Jääskeläinen 	if (pkcs2tee_algorithm(&algo, &hash_algo, function, params, obj))
135*fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_FUNCTION_FAILED;
136*fb279d8bSVesa Jääskeläinen 
137*fb279d8bSVesa Jääskeläinen 	pkcs2tee_mode(&mode, function);
138*fb279d8bSVesa Jääskeläinen 
139*fb279d8bSVesa Jääskeläinen 	if (hash_algo) {
140*fb279d8bSVesa Jääskeläinen 		pkcs2tee_mode(&hash_mode, PKCS11_FUNCTION_DIGEST);
141*fb279d8bSVesa Jääskeläinen 
142*fb279d8bSVesa Jääskeläinen 		res = TEE_AllocateOperation(&processing->tee_hash_op_handle,
143*fb279d8bSVesa Jääskeläinen 					    hash_algo, hash_mode, 0);
144*fb279d8bSVesa Jääskeläinen 		if (res) {
145*fb279d8bSVesa Jääskeläinen 			EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32,
146*fb279d8bSVesa Jääskeläinen 			     hash_algo, hash_mode);
147*fb279d8bSVesa Jääskeläinen 
148*fb279d8bSVesa Jääskeläinen 			if (res == TEE_ERROR_NOT_SUPPORTED)
149*fb279d8bSVesa Jääskeläinen 				return PKCS11_CKR_MECHANISM_INVALID;
150*fb279d8bSVesa Jääskeläinen 			return tee2pkcs_error(res);
151*fb279d8bSVesa Jääskeläinen 		}
152*fb279d8bSVesa Jääskeläinen 		processing->tee_hash_algo = hash_algo;
153*fb279d8bSVesa Jääskeläinen 	}
154*fb279d8bSVesa Jääskeläinen 
155*fb279d8bSVesa Jääskeläinen 	res = TEE_AllocateOperation(&processing->tee_op_handle,
156*fb279d8bSVesa Jääskeläinen 				    algo, mode, size);
157*fb279d8bSVesa Jääskeläinen 	if (res)
158*fb279d8bSVesa Jääskeläinen 		EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32" %#"PRIx32,
159*fb279d8bSVesa Jääskeläinen 		     algo, mode, size);
160*fb279d8bSVesa Jääskeläinen 
161*fb279d8bSVesa Jääskeläinen 	if (res == TEE_ERROR_NOT_SUPPORTED)
162*fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_MECHANISM_INVALID;
163*fb279d8bSVesa Jääskeläinen 
164*fb279d8bSVesa Jääskeläinen 	if (res != TEE_SUCCESS &&
165*fb279d8bSVesa Jääskeläinen 	    processing->tee_hash_op_handle != TEE_HANDLE_NULL) {
166*fb279d8bSVesa Jääskeläinen 		TEE_FreeOperation(session->processing->tee_hash_op_handle);
167*fb279d8bSVesa Jääskeläinen 		processing->tee_hash_op_handle = TEE_HANDLE_NULL;
168*fb279d8bSVesa Jääskeläinen 		processing->tee_hash_algo = 0;
169*fb279d8bSVesa Jääskeläinen 	}
170*fb279d8bSVesa Jääskeläinen 
171*fb279d8bSVesa Jääskeläinen 	return tee2pkcs_error(res);
172*fb279d8bSVesa Jääskeläinen }
173*fb279d8bSVesa Jääskeläinen 
174*fb279d8bSVesa Jääskeläinen static enum pkcs11_rc load_tee_key(struct pkcs11_session *session,
175*fb279d8bSVesa Jääskeläinen 				   struct pkcs11_object *obj,
176*fb279d8bSVesa Jääskeläinen 				   enum processing_func function)
177*fb279d8bSVesa Jääskeläinen {
178*fb279d8bSVesa Jääskeläinen 	TEE_Attribute *tee_attrs = NULL;
179*fb279d8bSVesa Jääskeläinen 	size_t tee_attrs_count = 0;
180*fb279d8bSVesa Jääskeläinen 	size_t object_size = 0;
181*fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
182*fb279d8bSVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
183*fb279d8bSVesa Jääskeläinen 	enum pkcs11_class_id __maybe_unused class = get_class(obj->attributes);
184*fb279d8bSVesa Jääskeläinen 	enum pkcs11_key_type type = get_key_type(obj->attributes);
185*fb279d8bSVesa Jääskeläinen 
186*fb279d8bSVesa Jääskeläinen 	assert(class == PKCS11_CKO_PUBLIC_KEY ||
187*fb279d8bSVesa Jääskeläinen 	       class == PKCS11_CKO_PRIVATE_KEY);
188*fb279d8bSVesa Jääskeläinen 
189*fb279d8bSVesa Jääskeläinen 	if (obj->key_handle != TEE_HANDLE_NULL) {
190*fb279d8bSVesa Jääskeläinen 		switch (type) {
191*fb279d8bSVesa Jääskeläinen 		case PKCS11_CKK_EC:
192*fb279d8bSVesa Jääskeläinen 			/* Reuse EC TEE key only if already DSA or DH */
193*fb279d8bSVesa Jääskeläinen 			switch (obj->key_type) {
194*fb279d8bSVesa Jääskeläinen 			case TEE_TYPE_ECDSA_PUBLIC_KEY:
195*fb279d8bSVesa Jääskeläinen 			case TEE_TYPE_ECDSA_KEYPAIR:
196*fb279d8bSVesa Jääskeläinen 				if (function != PKCS11_FUNCTION_DERIVE)
197*fb279d8bSVesa Jääskeläinen 					goto key_ready;
198*fb279d8bSVesa Jääskeläinen 				break;
199*fb279d8bSVesa Jääskeläinen 			default:
200*fb279d8bSVesa Jääskeläinen 				assert(0);
201*fb279d8bSVesa Jääskeläinen 				break;
202*fb279d8bSVesa Jääskeläinen 			}
203*fb279d8bSVesa Jääskeläinen 			break;
204*fb279d8bSVesa Jääskeläinen 		default:
205*fb279d8bSVesa Jääskeläinen 			assert(0);
206*fb279d8bSVesa Jääskeläinen 			break;
207*fb279d8bSVesa Jääskeläinen 		}
208*fb279d8bSVesa Jääskeläinen 
209*fb279d8bSVesa Jääskeläinen 		TEE_CloseObject(obj->key_handle);
210*fb279d8bSVesa Jääskeläinen 		obj->key_handle = TEE_HANDLE_NULL;
211*fb279d8bSVesa Jääskeläinen 	}
212*fb279d8bSVesa Jääskeläinen 
213*fb279d8bSVesa Jääskeläinen 	rc = pkcs2tee_key_type(&obj->key_type, obj, function);
214*fb279d8bSVesa Jääskeläinen 	if (rc)
215*fb279d8bSVesa Jääskeläinen 		return rc;
216*fb279d8bSVesa Jääskeläinen 
217*fb279d8bSVesa Jääskeläinen 	object_size = get_object_key_bit_size(obj);
218*fb279d8bSVesa Jääskeläinen 	if (!object_size)
219*fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_GENERAL_ERROR;
220*fb279d8bSVesa Jääskeläinen 
221*fb279d8bSVesa Jääskeläinen 	switch (type) {
222*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKK_EC:
223*fb279d8bSVesa Jääskeläinen 		rc = load_tee_ec_key_attrs(&tee_attrs, &tee_attrs_count, obj);
224*fb279d8bSVesa Jääskeläinen 		break;
225*fb279d8bSVesa Jääskeläinen 	default:
226*fb279d8bSVesa Jääskeläinen 		break;
227*fb279d8bSVesa Jääskeläinen 	}
228*fb279d8bSVesa Jääskeläinen 	if (rc)
229*fb279d8bSVesa Jääskeläinen 		return rc;
230*fb279d8bSVesa Jääskeläinen 
231*fb279d8bSVesa Jääskeläinen 	res = TEE_AllocateTransientObject(obj->key_type, object_size,
232*fb279d8bSVesa Jääskeläinen 					  &obj->key_handle);
233*fb279d8bSVesa Jääskeläinen 	if (res) {
234*fb279d8bSVesa Jääskeläinen 		DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res);
235*fb279d8bSVesa Jääskeläinen 
236*fb279d8bSVesa Jääskeläinen 		return tee2pkcs_error(res);
237*fb279d8bSVesa Jääskeläinen 	}
238*fb279d8bSVesa Jääskeläinen 
239*fb279d8bSVesa Jääskeläinen 	res = TEE_PopulateTransientObject(obj->key_handle,
240*fb279d8bSVesa Jääskeläinen 					  tee_attrs, tee_attrs_count);
241*fb279d8bSVesa Jääskeläinen 
242*fb279d8bSVesa Jääskeläinen 	TEE_Free(tee_attrs);
243*fb279d8bSVesa Jääskeläinen 
244*fb279d8bSVesa Jääskeläinen 	if (res) {
245*fb279d8bSVesa Jääskeläinen 		DMSG("TEE_PopulateTransientObject failed, %#"PRIx32, res);
246*fb279d8bSVesa Jääskeläinen 
247*fb279d8bSVesa Jääskeläinen 		goto error;
248*fb279d8bSVesa Jääskeläinen 	}
249*fb279d8bSVesa Jääskeläinen 
250*fb279d8bSVesa Jääskeläinen key_ready:
251*fb279d8bSVesa Jääskeläinen 	res = TEE_SetOperationKey(session->processing->tee_op_handle,
252*fb279d8bSVesa Jääskeläinen 				  obj->key_handle);
253*fb279d8bSVesa Jääskeläinen 	if (res) {
254*fb279d8bSVesa Jääskeläinen 		DMSG("TEE_SetOperationKey failed, %#"PRIx32, res);
255*fb279d8bSVesa Jääskeläinen 
256*fb279d8bSVesa Jääskeläinen 		goto error;
257*fb279d8bSVesa Jääskeläinen 	}
258*fb279d8bSVesa Jääskeläinen 
259*fb279d8bSVesa Jääskeläinen 	return PKCS11_CKR_OK;
260*fb279d8bSVesa Jääskeläinen 
261*fb279d8bSVesa Jääskeläinen error:
262*fb279d8bSVesa Jääskeläinen 	TEE_FreeTransientObject(obj->key_handle);
263*fb279d8bSVesa Jääskeläinen 	obj->key_handle = TEE_HANDLE_NULL;
264*fb279d8bSVesa Jääskeläinen 	return tee2pkcs_error(res);
265*fb279d8bSVesa Jääskeläinen }
266*fb279d8bSVesa Jääskeläinen 
267*fb279d8bSVesa Jääskeläinen static enum pkcs11_rc
268*fb279d8bSVesa Jääskeläinen init_tee_operation(struct pkcs11_session *session __unused,
269*fb279d8bSVesa Jääskeläinen 		   struct pkcs11_attribute_head *proc_params __unused)
270*fb279d8bSVesa Jääskeläinen {
271*fb279d8bSVesa Jääskeläinen 	return PKCS11_CKR_OK;
272*fb279d8bSVesa Jääskeläinen }
273*fb279d8bSVesa Jääskeläinen 
274*fb279d8bSVesa Jääskeläinen enum pkcs11_rc init_asymm_operation(struct pkcs11_session *session,
275*fb279d8bSVesa Jääskeläinen 				    enum processing_func function,
276*fb279d8bSVesa Jääskeläinen 				    struct pkcs11_attribute_head *proc_params,
277*fb279d8bSVesa Jääskeläinen 				    struct pkcs11_object *obj)
278*fb279d8bSVesa Jääskeläinen {
279*fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
280*fb279d8bSVesa Jääskeläinen 
281*fb279d8bSVesa Jääskeläinen 	assert(processing_is_tee_asymm(proc_params->id));
282*fb279d8bSVesa Jääskeläinen 
283*fb279d8bSVesa Jääskeläinen 	rc = allocate_tee_operation(session, function, proc_params, obj);
284*fb279d8bSVesa Jääskeläinen 	if (rc)
285*fb279d8bSVesa Jääskeläinen 		return rc;
286*fb279d8bSVesa Jääskeläinen 
287*fb279d8bSVesa Jääskeläinen 	rc = load_tee_key(session, obj, function);
288*fb279d8bSVesa Jääskeläinen 	if (rc)
289*fb279d8bSVesa Jääskeläinen 		return rc;
290*fb279d8bSVesa Jääskeläinen 
291*fb279d8bSVesa Jääskeläinen 	return init_tee_operation(session, proc_params);
292*fb279d8bSVesa Jääskeläinen }
293*fb279d8bSVesa Jääskeläinen 
294*fb279d8bSVesa Jääskeläinen /*
295*fb279d8bSVesa Jääskeläinen  * step_sym_step - step (update/oneshot/final) on a symmetric crypto operation
296*fb279d8bSVesa Jääskeläinen  *
297*fb279d8bSVesa Jääskeläinen  * @session - current session
298*fb279d8bSVesa Jääskeläinen  * @function - processing function (encrypt, decrypt, sign, ...)
299*fb279d8bSVesa Jääskeläinen  * @step - step ID in the processing (oneshot, update, final)
300*fb279d8bSVesa Jääskeläinen  * @ptypes - invocation parameter types
301*fb279d8bSVesa Jääskeläinen  * @params - invocation parameter references
302*fb279d8bSVesa Jääskeläinen  */
303*fb279d8bSVesa Jääskeläinen enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
304*fb279d8bSVesa Jääskeläinen 				    enum processing_func function,
305*fb279d8bSVesa Jääskeläinen 				    enum processing_step step,
306*fb279d8bSVesa Jääskeläinen 				    uint32_t ptypes, TEE_Param *params)
307*fb279d8bSVesa Jääskeläinen {
308*fb279d8bSVesa Jääskeläinen 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
309*fb279d8bSVesa Jääskeläinen 	TEE_Result res = TEE_ERROR_GENERIC;
310*fb279d8bSVesa Jääskeläinen 	void *in_buf = NULL;
311*fb279d8bSVesa Jääskeläinen 	void *in2_buf = NULL;
312*fb279d8bSVesa Jääskeläinen 	void *out_buf = NULL;
313*fb279d8bSVesa Jääskeläinen 	void *hash_buf = NULL;
314*fb279d8bSVesa Jääskeläinen 	uint32_t in_size = 0;
315*fb279d8bSVesa Jääskeläinen 	uint32_t in2_size = 0;
316*fb279d8bSVesa Jääskeläinen 	uint32_t out_size = 0;
317*fb279d8bSVesa Jääskeläinen 	uint32_t hash_size = 0;
318*fb279d8bSVesa Jääskeläinen 	TEE_Attribute *tee_attrs = NULL;
319*fb279d8bSVesa Jääskeläinen 	size_t tee_attrs_count = 0;
320*fb279d8bSVesa Jääskeläinen 	bool output_data = false;
321*fb279d8bSVesa Jääskeläinen 	struct active_processing *proc = session->processing;
322*fb279d8bSVesa Jääskeläinen 	size_t sz = 0;
323*fb279d8bSVesa Jääskeläinen 
324*fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) {
325*fb279d8bSVesa Jääskeläinen 		in_buf = params[1].memref.buffer;
326*fb279d8bSVesa Jääskeläinen 		in_size = params[1].memref.size;
327*fb279d8bSVesa Jääskeläinen 		if (in_size && !in_buf)
328*fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
329*fb279d8bSVesa Jääskeläinen 	}
330*fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_INPUT) {
331*fb279d8bSVesa Jääskeläinen 		in2_buf = params[2].memref.buffer;
332*fb279d8bSVesa Jääskeläinen 		in2_size = params[2].memref.size;
333*fb279d8bSVesa Jääskeläinen 		if (in2_size && !in2_buf)
334*fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
335*fb279d8bSVesa Jääskeläinen 	}
336*fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) {
337*fb279d8bSVesa Jääskeläinen 		out_buf = params[2].memref.buffer;
338*fb279d8bSVesa Jääskeläinen 		out_size = params[2].memref.size;
339*fb279d8bSVesa Jääskeläinen 		if (out_size && !out_buf)
340*fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_ARGUMENTS_BAD;
341*fb279d8bSVesa Jääskeläinen 	}
342*fb279d8bSVesa Jääskeläinen 	if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE)
343*fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_ARGUMENTS_BAD;
344*fb279d8bSVesa Jääskeläinen 
345*fb279d8bSVesa Jääskeläinen 	switch (step) {
346*fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_ONESHOT:
347*fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_UPDATE:
348*fb279d8bSVesa Jääskeläinen 	case PKCS11_FUNC_STEP_FINAL:
349*fb279d8bSVesa Jääskeläinen 		break;
350*fb279d8bSVesa Jääskeläinen 	default:
351*fb279d8bSVesa Jääskeläinen 		return PKCS11_CKR_GENERAL_ERROR;
352*fb279d8bSVesa Jääskeläinen 	}
353*fb279d8bSVesa Jääskeläinen 
354*fb279d8bSVesa Jääskeläinen 	/*
355*fb279d8bSVesa Jääskeläinen 	 * Handle multi stage update step for mechas needing hash
356*fb279d8bSVesa Jääskeläinen 	 * calculation
357*fb279d8bSVesa Jääskeläinen 	 */
358*fb279d8bSVesa Jääskeläinen 	if (step == PKCS11_FUNC_STEP_UPDATE) {
359*fb279d8bSVesa Jääskeläinen 		switch (proc->mecha_type) {
360*fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA1:
361*fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA224:
362*fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA256:
363*fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA384:
364*fb279d8bSVesa Jääskeläinen 		case PKCS11_CKM_ECDSA_SHA512:
365*fb279d8bSVesa Jääskeläinen 			assert(proc->tee_hash_op_handle != TEE_HANDLE_NULL);
366*fb279d8bSVesa Jääskeläinen 
367*fb279d8bSVesa Jääskeläinen 			TEE_DigestUpdate(proc->tee_hash_op_handle, in_buf,
368*fb279d8bSVesa Jääskeläinen 					 in_size);
369*fb279d8bSVesa Jääskeläinen 			break;
370*fb279d8bSVesa Jääskeläinen 		default:
371*fb279d8bSVesa Jääskeläinen 			/*
372*fb279d8bSVesa Jääskeläinen 			 * Other mechanism do not expect multi stage
373*fb279d8bSVesa Jääskeläinen 			 * operation
374*fb279d8bSVesa Jääskeläinen 			 */
375*fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_GENERAL_ERROR;
376*fb279d8bSVesa Jääskeläinen 			break;
377*fb279d8bSVesa Jääskeläinen 		}
378*fb279d8bSVesa Jääskeläinen 
379*fb279d8bSVesa Jääskeläinen 		goto out;
380*fb279d8bSVesa Jääskeläinen 	}
381*fb279d8bSVesa Jääskeläinen 
382*fb279d8bSVesa Jääskeläinen 	/*
383*fb279d8bSVesa Jääskeläinen 	 * Handle multi stage one shot and final steps for mechas needing hash
384*fb279d8bSVesa Jääskeläinen 	 * calculation
385*fb279d8bSVesa Jääskeläinen 	 */
386*fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
387*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
388*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
389*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
390*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
391*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
392*fb279d8bSVesa Jääskeläinen 		assert(proc->tee_hash_op_handle != TEE_HANDLE_NULL);
393*fb279d8bSVesa Jääskeläinen 
394*fb279d8bSVesa Jääskeläinen 		hash_size = TEE_ALG_GET_DIGEST_SIZE(proc->tee_hash_algo);
395*fb279d8bSVesa Jääskeläinen 		hash_buf = TEE_Malloc(hash_size, 0);
396*fb279d8bSVesa Jääskeläinen 		if (!hash_buf)
397*fb279d8bSVesa Jääskeläinen 			return PKCS11_CKR_DEVICE_MEMORY;
398*fb279d8bSVesa Jääskeläinen 
399*fb279d8bSVesa Jääskeläinen 		res = TEE_DigestDoFinal(proc->tee_hash_op_handle,
400*fb279d8bSVesa Jääskeläinen 					in_buf, in_size, hash_buf,
401*fb279d8bSVesa Jääskeläinen 					&hash_size);
402*fb279d8bSVesa Jääskeläinen 
403*fb279d8bSVesa Jääskeläinen 		rc = tee2pkcs_error(res);
404*fb279d8bSVesa Jääskeläinen 		if (rc != PKCS11_CKR_OK)
405*fb279d8bSVesa Jääskeläinen 			goto out;
406*fb279d8bSVesa Jääskeläinen 
407*fb279d8bSVesa Jääskeläinen 		break;
408*fb279d8bSVesa Jääskeläinen 	default:
409*fb279d8bSVesa Jääskeläinen 		break;
410*fb279d8bSVesa Jääskeläinen 	}
411*fb279d8bSVesa Jääskeläinen 
412*fb279d8bSVesa Jääskeläinen 	/*
413*fb279d8bSVesa Jääskeläinen 	 * Finalize either provided hash or calculated hash with signing
414*fb279d8bSVesa Jääskeläinen 	 * operation
415*fb279d8bSVesa Jääskeläinen 	 */
416*fb279d8bSVesa Jääskeläinen 
417*fb279d8bSVesa Jääskeläinen 	/* First determine amount of bytes for signing operation */
418*fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
419*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
420*fb279d8bSVesa Jääskeläinen 		sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle);
421*fb279d8bSVesa Jääskeläinen 		if (!in_size || !sz) {
422*fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_FUNCTION_FAILED;
423*fb279d8bSVesa Jääskeläinen 			goto out;
424*fb279d8bSVesa Jääskeläinen 		}
425*fb279d8bSVesa Jääskeläinen 
426*fb279d8bSVesa Jääskeläinen 		/*
427*fb279d8bSVesa Jääskeläinen 		 * Note 3) Input the entire raw digest. Internally, this will
428*fb279d8bSVesa Jääskeläinen 		 * be truncated to the appropriate number of bits.
429*fb279d8bSVesa Jääskeläinen 		 */
430*fb279d8bSVesa Jääskeläinen 		if (in_size > sz)
431*fb279d8bSVesa Jääskeläinen 			in_size = sz;
432*fb279d8bSVesa Jääskeläinen 
433*fb279d8bSVesa Jääskeläinen 		if (function == PKCS11_FUNCTION_VERIFY && in2_size != 2 * sz) {
434*fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
435*fb279d8bSVesa Jääskeläinen 			goto out;
436*fb279d8bSVesa Jääskeläinen 		}
437*fb279d8bSVesa Jääskeläinen 		break;
438*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
439*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
440*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
441*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
442*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
443*fb279d8bSVesa Jääskeläinen 		/* Get key size in bytes */
444*fb279d8bSVesa Jääskeläinen 		sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle);
445*fb279d8bSVesa Jääskeläinen 		if (!sz) {
446*fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_FUNCTION_FAILED;
447*fb279d8bSVesa Jääskeläinen 			goto out;
448*fb279d8bSVesa Jääskeläinen 		}
449*fb279d8bSVesa Jääskeläinen 
450*fb279d8bSVesa Jääskeläinen 		if (function == PKCS11_FUNCTION_VERIFY &&
451*fb279d8bSVesa Jääskeläinen 		    in2_size != 2 * sz) {
452*fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_SIGNATURE_LEN_RANGE;
453*fb279d8bSVesa Jääskeläinen 			goto out;
454*fb279d8bSVesa Jääskeläinen 		}
455*fb279d8bSVesa Jääskeläinen 		break;
456*fb279d8bSVesa Jääskeläinen 	default:
457*fb279d8bSVesa Jääskeläinen 		break;
458*fb279d8bSVesa Jääskeläinen 	}
459*fb279d8bSVesa Jääskeläinen 
460*fb279d8bSVesa Jääskeläinen 	/* Next perform actual signing operation */
461*fb279d8bSVesa Jääskeläinen 	switch (proc->mecha_type) {
462*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA:
463*fb279d8bSVesa Jääskeläinen 		/* For operations using provided input data */
464*fb279d8bSVesa Jääskeläinen 		switch (function) {
465*fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_ENCRYPT:
466*fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
467*fb279d8bSVesa Jääskeläinen 						    tee_attrs, tee_attrs_count,
468*fb279d8bSVesa Jääskeläinen 						    in_buf, in_size,
469*fb279d8bSVesa Jääskeläinen 						    out_buf, &out_size);
470*fb279d8bSVesa Jääskeläinen 			output_data = true;
471*fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
472*fb279d8bSVesa Jääskeläinen 			break;
473*fb279d8bSVesa Jääskeläinen 
474*fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_DECRYPT:
475*fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
476*fb279d8bSVesa Jääskeläinen 						    tee_attrs, tee_attrs_count,
477*fb279d8bSVesa Jääskeläinen 						    in_buf, in_size,
478*fb279d8bSVesa Jääskeläinen 						    out_buf, &out_size);
479*fb279d8bSVesa Jääskeläinen 			output_data = true;
480*fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
481*fb279d8bSVesa Jääskeläinen 			break;
482*fb279d8bSVesa Jääskeläinen 
483*fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_SIGN:
484*fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricSignDigest(proc->tee_op_handle,
485*fb279d8bSVesa Jääskeläinen 						       tee_attrs,
486*fb279d8bSVesa Jääskeläinen 						       tee_attrs_count,
487*fb279d8bSVesa Jääskeläinen 						       in_buf, in_size,
488*fb279d8bSVesa Jääskeläinen 						       out_buf, &out_size);
489*fb279d8bSVesa Jääskeläinen 			output_data = true;
490*fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
491*fb279d8bSVesa Jääskeläinen 			break;
492*fb279d8bSVesa Jääskeläinen 
493*fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_VERIFY:
494*fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle,
495*fb279d8bSVesa Jääskeläinen 							 tee_attrs,
496*fb279d8bSVesa Jääskeläinen 							 tee_attrs_count,
497*fb279d8bSVesa Jääskeläinen 							 in_buf, in_size,
498*fb279d8bSVesa Jääskeläinen 							 in2_buf, in2_size);
499*fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
500*fb279d8bSVesa Jääskeläinen 			break;
501*fb279d8bSVesa Jääskeläinen 
502*fb279d8bSVesa Jääskeläinen 		default:
503*fb279d8bSVesa Jääskeläinen 			TEE_Panic(function);
504*fb279d8bSVesa Jääskeläinen 			break;
505*fb279d8bSVesa Jääskeläinen 		}
506*fb279d8bSVesa Jääskeläinen 		break;
507*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA1:
508*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA224:
509*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA256:
510*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA384:
511*fb279d8bSVesa Jääskeläinen 	case PKCS11_CKM_ECDSA_SHA512:
512*fb279d8bSVesa Jääskeläinen 		/* For operations having hash operation use calculated hash */
513*fb279d8bSVesa Jääskeläinen 		switch (function) {
514*fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_SIGN:
515*fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricSignDigest(proc->tee_op_handle,
516*fb279d8bSVesa Jääskeläinen 						       tee_attrs,
517*fb279d8bSVesa Jääskeläinen 						       tee_attrs_count,
518*fb279d8bSVesa Jääskeläinen 						       hash_buf, hash_size,
519*fb279d8bSVesa Jääskeläinen 						       out_buf, &out_size);
520*fb279d8bSVesa Jääskeläinen 			output_data = true;
521*fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
522*fb279d8bSVesa Jääskeläinen 			break;
523*fb279d8bSVesa Jääskeläinen 
524*fb279d8bSVesa Jääskeläinen 		case PKCS11_FUNCTION_VERIFY:
525*fb279d8bSVesa Jääskeläinen 			res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle,
526*fb279d8bSVesa Jääskeläinen 							 tee_attrs,
527*fb279d8bSVesa Jääskeläinen 							 tee_attrs_count,
528*fb279d8bSVesa Jääskeläinen 							 hash_buf, hash_size,
529*fb279d8bSVesa Jääskeläinen 							 in2_buf, in2_size);
530*fb279d8bSVesa Jääskeläinen 			rc = tee2pkcs_error(res);
531*fb279d8bSVesa Jääskeläinen 			break;
532*fb279d8bSVesa Jääskeläinen 
533*fb279d8bSVesa Jääskeläinen 		default:
534*fb279d8bSVesa Jääskeläinen 			TEE_Panic(function);
535*fb279d8bSVesa Jääskeläinen 			break;
536*fb279d8bSVesa Jääskeläinen 		}
537*fb279d8bSVesa Jääskeläinen 		break;
538*fb279d8bSVesa Jääskeläinen 	default:
539*fb279d8bSVesa Jääskeläinen 		TEE_Panic(proc->mecha_type);
540*fb279d8bSVesa Jääskeläinen 		break;
541*fb279d8bSVesa Jääskeläinen 	}
542*fb279d8bSVesa Jääskeläinen 
543*fb279d8bSVesa Jääskeläinen out:
544*fb279d8bSVesa Jääskeläinen 	if (output_data &&
545*fb279d8bSVesa Jääskeläinen 	    (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)) {
546*fb279d8bSVesa Jääskeläinen 		switch (TEE_PARAM_TYPE_GET(ptypes, 2)) {
547*fb279d8bSVesa Jääskeläinen 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
548*fb279d8bSVesa Jääskeläinen 		case TEE_PARAM_TYPE_MEMREF_INOUT:
549*fb279d8bSVesa Jääskeläinen 			params[2].memref.size = out_size;
550*fb279d8bSVesa Jääskeläinen 			break;
551*fb279d8bSVesa Jääskeläinen 		default:
552*fb279d8bSVesa Jääskeläinen 			rc = PKCS11_CKR_GENERAL_ERROR;
553*fb279d8bSVesa Jääskeläinen 			break;
554*fb279d8bSVesa Jääskeläinen 		}
555*fb279d8bSVesa Jääskeläinen 	}
556*fb279d8bSVesa Jääskeläinen 
557*fb279d8bSVesa Jääskeläinen 	TEE_Free(hash_buf);
558*fb279d8bSVesa Jääskeläinen 	TEE_Free(tee_attrs);
559*fb279d8bSVesa Jääskeläinen 
560*fb279d8bSVesa Jääskeläinen 	return rc;
561*fb279d8bSVesa Jääskeläinen }
562