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