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