1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2015, Linaro Limited
4  * All rights reserved.
5  */
6 
7 #include <tee_internal_api_extensions.h>
8 #include <tee_internal_api.h>
9 #include <tee_ta_api.h>
10 #include <string.h>
11 #include <trace.h>
12 
13 #include "ta_aes_perf.h"
14 #include "ta_aes_perf_priv.h"
15 
16 #define CHECK(res, name, action) do {			\
17 		if ((res) != TEE_SUCCESS) {		\
18 			DMSG(name ": 0x%08x", (res));	\
19 			action				\
20 		}					\
21 	} while(0)
22 
23 #define TAG_LEN	128
24 
25 static uint8_t iv[] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
26 			0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF };
27 static int use_iv;
28 
29 static TEE_OperationHandle crypto_op = NULL;
30 static uint32_t algo;
31 
is_inbuf_a_secure_memref(TEE_Param * param)32 static bool is_inbuf_a_secure_memref(TEE_Param *param)
33 {
34 	TEE_Result res = TEE_ERROR_GENERIC;
35 
36 	/*
37 	 * Check secure attribute for the referenced buffer
38 	 * Trust core on validity of the memref size: test only 1st byte
39 	 * instead of the overall buffer, and if it's not secure, assume
40 	 * the buffer is nonsecure.
41 	 */
42 	res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER |
43 					 TEE_MEMORY_ACCESS_READ |
44 					 TEE_MEMORY_ACCESS_SECURE,
45 					 param->memref.buffer, 1);
46 	return (res == TEE_SUCCESS);
47 }
48 
is_outbuf_a_secure_memref(TEE_Param * param)49 static bool is_outbuf_a_secure_memref(TEE_Param *param)
50 {
51 	TEE_Result res = TEE_ERROR_GENERIC;
52 
53 	/*
54 	 * Check secure attribute for the referenced buffer
55 	 * Trust core on validity of the memref size: test only 1st byte
56 	 * instead of the overall buffer, and if it's not secure, assume
57 	 * the buffer is nonsecure.
58 	 */
59 	res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER |
60 					 TEE_MEMORY_ACCESS_WRITE |
61 					 TEE_MEMORY_ACCESS_SECURE,
62 					 param->memref.buffer, 1);
63 	return (res == TEE_SUCCESS);
64 }
65 
66 #if defined(CFG_CACHE_API)
flush_memref_buffer(TEE_Param * param)67 static TEE_Result flush_memref_buffer(TEE_Param *param)
68 {
69 	TEE_Result res = TEE_ERROR_GENERIC;
70 
71 	res = TEE_CacheFlush(param->memref.buffer,
72 			     param->memref.size);
73 	CHECK(res, "TEE_CacheFlush(in)", return res;);
74 	return res;
75 }
76 #else
flush_memref_buffer(TEE_Param * param __unused)77 static __maybe_unused TEE_Result flush_memref_buffer(TEE_Param *param __unused)
78 {
79 	return TEE_SUCCESS;
80 }
81 #endif /* CFG_CACHE_API */
82 
cmd_process(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS],bool use_sdp)83 TEE_Result cmd_process(uint32_t param_types,
84 		       TEE_Param params[TEE_NUM_PARAMS],
85 		       bool use_sdp)
86 {
87 	TEE_Result res = TEE_ERROR_GENERIC;
88 	int n = 0;
89 	int unit = 0;
90 	void *in = NULL;
91 	void *out = NULL;
92 	uint32_t insz = 0;
93 	uint32_t outsz = 0;
94 	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
95 						   TEE_PARAM_TYPE_MEMREF_INOUT,
96 						   TEE_PARAM_TYPE_VALUE_INPUT,
97 						   TEE_PARAM_TYPE_NONE);
98 	bool secure_in = false;
99 	bool secure_out = false;
100 	TEE_Result (*do_update)(TEE_OperationHandle, const void *, uint32_t,
101 				void *, uint32_t *) = NULL;
102 
103 	if (param_types != exp_param_types)
104 		return TEE_ERROR_BAD_PARAMETERS;
105 
106 	if (use_sdp) {
107 		/*
108 		 * Whatever is expected as memory reference, it is mandatory
109 		 * for SDP aware trusted applications of safely indentify all
110 		 * memory reference parameters. Hence these tests must be part
111 		 * of the performance test setup.
112 		 */
113 		secure_in = is_inbuf_a_secure_memref(&params[0]);
114 		secure_out = is_outbuf_a_secure_memref(&params[1]);
115 
116 		/*
117 		 * We could invalidate only the caches. We prefer to flush
118 		 * them in case 2 sub-buffers are accessed by TAs from a single
119 		 * allocated SDP memory buffer, and those are not cache-aligned.
120 		 * Invalidating might cause data loss in cache lines. Hence
121 		 * rather flush them all before accessing (in read or write).
122 		 */
123 		if (secure_in) {
124 			res = flush_memref_buffer(&params[0]);
125 			CHECK(res, "pre-flush in memref param", return res;);
126 		}
127 		if (secure_out) {
128 			res = flush_memref_buffer(&params[1]);
129 			CHECK(res, "pre-flush out memref param", return res;);
130 		}
131 	}
132 
133 	in = params[0].memref.buffer;
134 	insz = params[0].memref.size;
135 	out = params[1].memref.buffer;
136 	outsz = params[1].memref.size;
137 	n = params[2].value.a;
138 	unit = params[2].value.b;
139 	if (!unit)
140 		unit = insz;
141 
142 	if (algo == TEE_ALG_AES_GCM)
143 		do_update = TEE_AEUpdate;
144 	else
145 		do_update = TEE_CipherUpdate;
146 
147 	while (n--) {
148 		uint32_t i = 0;
149 		for (i = 0; i < insz / unit; i++) {
150 			res = do_update(crypto_op, in, unit, out, &outsz);
151 			CHECK(res, "TEE_CipherUpdate/TEE_AEUpdate", return res;);
152 			in  = (void *)((uintptr_t)in + unit);
153 			out = (void *)((uintptr_t)out + unit);
154 		}
155 		if (insz % unit) {
156 			res = do_update(crypto_op, in, insz % unit, out, &outsz);
157 			CHECK(res, "TEE_CipherUpdate/TEE_AEUpdate", return res;);
158 		}
159 	}
160 
161 	if (secure_out) {
162 		/* intentionally flush output data from cache for SDP buffers */
163 		res = flush_memref_buffer(&params[1]);
164 		CHECK(res, "post-flush out memref param", return res;);
165 	}
166 
167 	return TEE_SUCCESS;
168 }
169 
cmd_prepare_key(uint32_t param_types,TEE_Param params[4])170 TEE_Result cmd_prepare_key(uint32_t param_types, TEE_Param params[4])
171 {
172 	TEE_Result res = TEE_ERROR_GENERIC;
173 	TEE_ObjectHandle hkey = TEE_HANDLE_NULL;
174 	TEE_ObjectHandle hkey2 = TEE_HANDLE_NULL;
175 	TEE_Attribute attr = { };
176 	uint32_t mode = 0;
177 	uint32_t op_keysize = 0;
178 	uint32_t keysize = 0;
179 	const uint8_t *ivp = NULL;
180 	size_t ivlen = 0;
181 	static uint8_t aes_key[] = { 0x00, 0x01, 0x02, 0x03,
182 				     0x04, 0x05, 0x06, 0x07,
183 				     0x08, 0x09, 0x0A, 0x0B,
184 				     0x0C, 0x0D, 0x0E, 0x0F,
185 				     0x10, 0x11, 0x12, 0x13,
186 				     0x14, 0x15, 0x16, 0x17,
187 				     0x18, 0x19, 0x1A, 0x1B,
188 				     0x1C, 0x1D, 0x1E, 0x1F };
189 	static uint8_t aes_key2[] = { 0x20, 0x21, 0x22, 0x23,
190 				      0x24, 0x25, 0x26, 0x27,
191 				      0x28, 0x29, 0x2A, 0x2B,
192 				      0x2C, 0x2D, 0x2E, 0x2F,
193 				      0x30, 0x31, 0x32, 0x33,
194 				      0x34, 0x35, 0x36, 0x37,
195 				      0x38, 0x39, 0x3A, 0x3B,
196 				      0x3C, 0x3D, 0x3E, 0x3F };
197 	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
198 						   TEE_PARAM_TYPE_VALUE_INPUT,
199 						   TEE_PARAM_TYPE_NONE,
200 						   TEE_PARAM_TYPE_NONE);
201 
202 	if (param_types != exp_param_types)
203 		return TEE_ERROR_BAD_PARAMETERS;
204 
205 	mode = params[0].value.a ? TEE_MODE_DECRYPT : TEE_MODE_ENCRYPT;
206 	keysize = params[0].value.b;
207 	op_keysize = keysize;
208 
209 	switch (params[1].value.a) {
210 	case TA_AES_ECB:
211 		algo = TEE_ALG_AES_ECB_NOPAD;
212 		use_iv = 0;
213 		break;
214 	case TA_AES_CBC:
215 		algo = TEE_ALG_AES_CBC_NOPAD;
216 		use_iv = 1;
217 		break;
218 	case TA_AES_CTR:
219 		algo = TEE_ALG_AES_CTR;
220 		use_iv = 1;
221 		break;
222 	case TA_AES_XTS:
223 		algo = TEE_ALG_AES_XTS;
224 		use_iv = 1;
225 		op_keysize *= 2;
226 		break;
227 	case TA_AES_GCM:
228 		algo = TEE_ALG_AES_GCM;
229 		use_iv = 1;
230 		break;
231 	default:
232 		return TEE_ERROR_BAD_PARAMETERS;
233 	}
234 
235 	cmd_clean_res();
236 
237 	res = TEE_AllocateOperation(&crypto_op, algo, mode, op_keysize);
238 	CHECK(res, "TEE_AllocateOperation", return res;);
239 
240 	res = TEE_AllocateTransientObject(TEE_TYPE_AES, keysize, &hkey);
241 	CHECK(res, "TEE_AllocateTransientObject", return res;);
242 
243 	attr.attributeID = TEE_ATTR_SECRET_VALUE;
244 	attr.content.ref.buffer = aes_key;
245 	attr.content.ref.length = keysize / 8;
246 
247 	res = TEE_PopulateTransientObject(hkey, &attr, 1);
248 	CHECK(res, "TEE_PopulateTransientObject", return res;);
249 
250 	if (algo == TEE_ALG_AES_XTS) {
251 		res = TEE_AllocateTransientObject(TEE_TYPE_AES, keysize,
252 						  &hkey2);
253 		CHECK(res, "TEE_AllocateTransientObject", return res;);
254 
255 		attr.content.ref.buffer = aes_key2;
256 
257 		res = TEE_PopulateTransientObject(hkey2, &attr, 1);
258 		CHECK(res, "TEE_PopulateTransientObject", return res;);
259 
260 		res = TEE_SetOperationKey2(crypto_op, hkey, hkey2);
261 		CHECK(res, "TEE_SetOperationKey2", return res;);
262 
263 		TEE_FreeTransientObject(hkey2);
264 	} else {
265 		res = TEE_SetOperationKey(crypto_op, hkey);
266 		CHECK(res, "TEE_SetOperationKey", return res;);
267 	}
268 
269 	TEE_FreeTransientObject(hkey);
270 
271 	if (use_iv) {
272 		ivp = iv;
273 		ivlen = sizeof(iv);
274 	} else {
275 		ivp = NULL;
276 		ivlen = 0;
277 	}
278 
279 	if (algo == TEE_ALG_AES_GCM) {
280 		return TEE_AEInit(crypto_op, ivp, ivlen, TAG_LEN, 0, 0);
281 	} else {
282 		TEE_CipherInit(crypto_op, ivp, ivlen);
283 		return TEE_SUCCESS;
284 	}
285 }
286 
cmd_clean_res(void)287 void cmd_clean_res(void)
288 {
289 	if (crypto_op)
290 		TEE_FreeOperation(crypto_op);
291 }
292