blob: 6f60eb93bc43f80ffa6453ec8e23d880e1ee05a8 [file] [log] [blame]
Zexi Yue18381f2023-10-30 11:29:51 +08001// SPDX-License-Identifier: BSD-2-Clause
2/*
3 * Copyright (c) 2015, Linaro Limited
4 */
5
6#include <string.h>
7#include <tee_internal_api_extensions.h>
8#include <tee_internal_api.h>
9#include <tee_ta_api.h>
10#include <trace.h>
11#include <utee_defines.h>
12#include <util.h>
13
14#include "ta_crypto_perf.h"
15#include "ta_crypto_perf_priv.h"
16
17#define CHECK(res, name, action) do { \
18 if ((res) != TEE_SUCCESS) { \
19 DMSG(name ": 0x%08x", (res)); \
20 action \
21 } \
22 } while(0)
23
24#define TAG_LEN 128
25
26static uint8_t iv[] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
27 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF };
28static int use_iv;
29
30static TEE_OperationHandle crypto_op;
31static uint32_t algo;
32
33static bool is_inbuf_a_secure_memref(TEE_Param *param)
34{
35 TEE_Result res = TEE_ERROR_GENERIC;
36
37 /*
38 * Check secure attribute for the referenced buffer
39 * Trust core on validity of the memref size: test only 1st byte
40 * instead of the overall buffer, and if it's not secure, assume
41 * the buffer is nonsecure.
42 */
43 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER |
44 TEE_MEMORY_ACCESS_READ |
45 TEE_MEMORY_ACCESS_SECURE,
46 param->memref.buffer, 1);
47 return (res == TEE_SUCCESS);
48}
49
50static bool is_outbuf_a_secure_memref(TEE_Param *param)
51{
52 TEE_Result res = TEE_ERROR_GENERIC;
53
54 /*
55 * Check secure attribute for the referenced buffer
56 * Trust core on validity of the memref size: test only 1st byte
57 * instead of the overall buffer, and if it's not secure, assume
58 * the buffer is nonsecure.
59 */
60 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER |
61 TEE_MEMORY_ACCESS_WRITE |
62 TEE_MEMORY_ACCESS_SECURE,
63 param->memref.buffer, 1);
64 return (res == TEE_SUCCESS);
65}
66
67#if defined(CFG_CACHE_API)
68static TEE_Result flush_memref_buffer(TEE_Param *param)
69{
70 TEE_Result res = TEE_ERROR_GENERIC;
71
72 res = TEE_CacheFlush(param->memref.buffer,
73 param->memref.size);
74 CHECK(res, "TEE_CacheFlush(in)", return res;);
75 return res;
76}
77#else
78static __maybe_unused TEE_Result flush_memref_buffer(TEE_Param *param __unused)
79{
80 return TEE_SUCCESS;
81}
82#endif /* CFG_CACHE_API */
83
84TEE_Result cmd_cipher_process(uint32_t param_types,
85 TEE_Param params[TEE_NUM_PARAMS],
86 bool use_sdp)
87{
88 TEE_Result res = TEE_ERROR_GENERIC;
89 int n = 0;
90 int unit = 0;
91 void *in = NULL;
92 void *out = NULL;
93 size_t insz = 0;
94 size_t outsz = 0;
95 uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
96 TEE_PARAM_TYPE_MEMREF_INOUT,
97 TEE_PARAM_TYPE_VALUE_INPUT,
98 TEE_PARAM_TYPE_NONE);
99 bool secure_in = false;
100 bool secure_out = false;
101 TEE_Result (*do_update)(TEE_OperationHandle, const void *, size_t,
102 void *, size_t *) = NULL;
103
104 if (param_types != exp_param_types)
105 return TEE_ERROR_BAD_PARAMETERS;
106
107 if (use_sdp) {
108 /*
109 * Whatever is expected as memory reference, it is mandatory
110 * for SDP aware trusted applications of safely indentify all
111 * memory reference parameters. Hence these tests must be part
112 * of the performance test setup.
113 */
114 secure_in = is_inbuf_a_secure_memref(&params[0]);
115 secure_out = is_outbuf_a_secure_memref(&params[1]);
116
117 /*
118 * We could invalidate only the caches. We prefer to flush
119 * them in case 2 sub-buffers are accessed by TAs from a single
120 * allocated SDP memory buffer, and those are not cache-aligned.
121 * Invalidating might cause data loss in cache lines. Hence
122 * rather flush them all before accessing (in read or write).
123 */
124 if (secure_in) {
125 res = flush_memref_buffer(&params[0]);
126 CHECK(res, "pre-flush in memref param", return res;);
127 }
128 if (secure_out) {
129 res = flush_memref_buffer(&params[1]);
130 CHECK(res, "pre-flush out memref param", return res;);
131 }
132 }
133
134 in = params[0].memref.buffer;
135 insz = params[0].memref.size;
136 out = params[1].memref.buffer;
137 outsz = params[1].memref.size;
138 n = params[2].value.a;
139 unit = params[2].value.b;
140 if (!unit)
141 unit = insz;
142
143 if (algo == TEE_ALG_AES_GCM)
144 do_update = TEE_AEUpdate;
145 else
146 do_update = TEE_CipherUpdate;
147
148 while (n--) {
149 uint32_t i = 0;
150 for (i = 0; i < insz / unit; i++) {
151 res = do_update(crypto_op, in, unit, out, &outsz);
152 CHECK(res, "TEE_CipherUpdate/TEE_AEUpdate", return res;);
153 in = (void *)((uintptr_t)in + unit);
154 out = (void *)((uintptr_t)out + unit);
155 }
156 if (insz % unit) {
157 res = do_update(crypto_op, in, insz % unit, out, &outsz);
158 CHECK(res, "TEE_CipherUpdate/TEE_AEUpdate", return res;);
159 }
160 }
161
162 if (secure_out) {
163 /* intentionally flush output data from cache for SDP buffers */
164 res = flush_memref_buffer(&params[1]);
165 CHECK(res, "post-flush out memref param", return res;);
166 }
167
168 return TEE_SUCCESS;
169}
170
171TEE_Result cmd_cipher_prepare_key(uint32_t param_types, TEE_Param params[4])
172{
173 TEE_Result res = TEE_ERROR_GENERIC;
174 TEE_ObjectHandle hkey = TEE_HANDLE_NULL;
175 TEE_ObjectHandle hkey2 = TEE_HANDLE_NULL;
176 TEE_ObjectType objectType;
177 TEE_Attribute attr = { };
178 uint32_t mode = 0;
179 uint32_t op_keysize = 0;
180 uint32_t keysize = 0;
181 const uint8_t *ivp = NULL;
182 size_t ivlen = 0;
183 static uint8_t cipher_key[] = { 0x00, 0x01, 0x02, 0x03,
184 0x04, 0x05, 0x06, 0x07,
185 0x08, 0x09, 0x0A, 0x0B,
186 0x0C, 0x0D, 0x0E, 0x0F,
187 0x10, 0x11, 0x12, 0x13,
188 0x14, 0x15, 0x16, 0x17,
189 0x18, 0x19, 0x1A, 0x1B,
190 0x1C, 0x1D, 0x1E, 0x1F };
191 static uint8_t cipher_key2[] = { 0x20, 0x21, 0x22, 0x23,
192 0x24, 0x25, 0x26, 0x27,
193 0x28, 0x29, 0x2A, 0x2B,
194 0x2C, 0x2D, 0x2E, 0x2F,
195 0x30, 0x31, 0x32, 0x33,
196 0x34, 0x35, 0x36, 0x37,
197 0x38, 0x39, 0x3A, 0x3B,
198 0x3C, 0x3D, 0x3E, 0x3F };
199 uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
200 TEE_PARAM_TYPE_VALUE_INPUT,
201 TEE_PARAM_TYPE_NONE,
202 TEE_PARAM_TYPE_NONE);
203
204 if (param_types != exp_param_types)
205 return TEE_ERROR_BAD_PARAMETERS;
206
207 mode = params[0].value.a ? TEE_MODE_DECRYPT : TEE_MODE_ENCRYPT;
208 keysize = params[0].value.b;
209 op_keysize = keysize;
210
211 switch (params[1].value.a) {
212 case TA_AES_ECB:
213 algo = TEE_ALG_AES_ECB_NOPAD;
214 objectType = TEE_TYPE_AES;
215 use_iv = 0;
216 break;
217 case TA_AES_CBC:
218 algo = TEE_ALG_AES_CBC_NOPAD;
219 objectType = TEE_TYPE_AES;
220 use_iv = 1;
221 break;
222 case TA_AES_CTR:
223 algo = TEE_ALG_AES_CTR;
224 objectType = TEE_TYPE_AES;
225 use_iv = 1;
226 break;
227 case TA_AES_XTS:
228 algo = TEE_ALG_AES_XTS;
229 objectType = TEE_TYPE_AES;
230 use_iv = 1;
231 op_keysize *= 2;
232 break;
233 case TA_AES_GCM:
234 algo = TEE_ALG_AES_GCM;
235 objectType = TEE_TYPE_AES;
236 use_iv = 1;
237 break;
238 default:
239 return TEE_ERROR_BAD_PARAMETERS;
240 }
241
242 cmd_clean_res();
243
244 res = TEE_AllocateOperation(&crypto_op, algo, mode, op_keysize);
245 CHECK(res, "TEE_AllocateOperation", return res;);
246
247 res = TEE_AllocateTransientObject(objectType, keysize, &hkey);
248 CHECK(res, "TEE_AllocateTransientObject", return res;);
249
250 attr.attributeID = TEE_ATTR_SECRET_VALUE;
251 attr.content.ref.buffer = cipher_key;
252 attr.content.ref.length = keysize / 8;
253
254 res = TEE_PopulateTransientObject(hkey, &attr, 1);
255 CHECK(res, "TEE_PopulateTransientObject", return res;);
256
257 if (algo == TEE_ALG_AES_XTS) {
258 res = TEE_AllocateTransientObject(objectType, keysize,
259 &hkey2);
260 CHECK(res, "TEE_AllocateTransientObject", return res;);
261
262 attr.content.ref.buffer = cipher_key2;
263
264 res = TEE_PopulateTransientObject(hkey2, &attr, 1);
265 CHECK(res, "TEE_PopulateTransientObject", return res;);
266
267 res = TEE_SetOperationKey2(crypto_op, hkey, hkey2);
268 CHECK(res, "TEE_SetOperationKey2", return res;);
269
270 TEE_FreeTransientObject(hkey2);
271 } else {
272 res = TEE_SetOperationKey(crypto_op, hkey);
273 CHECK(res, "TEE_SetOperationKey", return res;);
274 }
275
276 TEE_FreeTransientObject(hkey);
277
278 if (use_iv) {
279 ivp = iv;
280 ivlen = sizeof(iv);
281 } else {
282 ivp = NULL;
283 ivlen = 0;
284 }
285
286 if (algo == TEE_ALG_AES_GCM) {
287 return TEE_AEInit(crypto_op, ivp, ivlen, TAG_LEN, 0, 0);
288 } else {
289 TEE_CipherInit(crypto_op, ivp, ivlen);
290 return TEE_SUCCESS;
291 }
292}
293
294static bool is_mac(uint32_t hash_algo)
295{
296 switch (hash_algo) {
297 case TEE_ALG_HMAC_SHA1:
298 case TEE_ALG_HMAC_SHA224:
299 case TEE_ALG_HMAC_SHA256:
300 case TEE_ALG_HMAC_SHA384:
301 case TEE_ALG_HMAC_SHA512:
302 case TEE_ALG_HMAC_SM3:
303 return true;
304 default:
305 return false;
306 }
307}
308
309TEE_Result cmd_hash_process(uint32_t param_types, TEE_Param params[4])
310{
311 TEE_Result res = TEE_ERROR_GENERIC;
312 TEE_OperationInfo info = { };
313 int n = 0;
314 void *in = NULL;
315 void *out = NULL;
316 size_t insz = 0;
317 size_t outsz = 0;
318 uint32_t offset = 0;
319 uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
320 TEE_PARAM_TYPE_MEMREF_OUTPUT,
321 TEE_PARAM_TYPE_VALUE_INPUT,
322 TEE_PARAM_TYPE_NONE);
323
324 if (param_types != exp_param_types)
325 return TEE_ERROR_BAD_PARAMETERS;
326
327 offset = params[2].value.b;
328 in = (uint8_t *)params[0].memref.buffer + offset;
329 insz = params[0].memref.size - offset;
330 out = params[1].memref.buffer;
331 outsz = params[1].memref.size;
332 n = params[2].value.a;
333
334 TEE_GetOperationInfo(crypto_op, &info);
335
336 if (is_mac(info.algorithm)) {
337 while (n--) {
338 TEE_MACInit(crypto_op, NULL, 0);
339 res = TEE_MACComputeFinal(crypto_op, in, insz, out, &outsz);
340 CHECK(res, "TEE_MACComputeFinal", return res;);
341 }
342 } else {
343 while (n--) {
344 res = TEE_DigestDoFinal(crypto_op, in, insz, out, &outsz);
345 CHECK(res, "TEE_DigestDoFinal", return res;);
346 }
347 }
348
349 return TEE_SUCCESS;
350}
351
352TEE_Result cmd_hash_prepare_op(uint32_t param_types, TEE_Param params[4])
353{
354 TEE_ObjectHandle hkey = TEE_HANDLE_NULL;
355 TEE_Result res = TEE_ERROR_GENERIC;
356 TEE_Attribute attr = { };
357 uint32_t key_type = TEE_TYPE_HMAC_SHA1;
358 uint32_t mac_key_size = 512;
359 uint32_t max_key_size = 0;
360 uint32_t hash_algo = 0;
361 static uint8_t mac_key[] = {
362 0x00, 0x01, 0x02, 0x03,
363 0x04, 0x05, 0x06, 0x07,
364 0x08, 0x09, 0x0A, 0x0B,
365 0x0C, 0x0D, 0x0E, 0x0F,
366 0x10, 0x11, 0x12, 0x13,
367 0x14, 0x15, 0x16, 0x17,
368 0x18, 0x19, 0x1A, 0x1B,
369 0x1C, 0x1D, 0x1E, 0x1F,
370 0x20, 0x21, 0x22, 0x23,
371 0x24, 0x25, 0x26, 0x27,
372 0x28, 0x29, 0x2A, 0x2B,
373 0x2C, 0x2D, 0x2E, 0x2F,
374 0x30, 0x31, 0x32, 0x33,
375 0x34, 0x35, 0x36, 0x37,
376 0x38, 0x39, 0x3A, 0x3B,
377 0x3C, 0x3D, 0x3E, 0x3F
378 };
379 uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
380 TEE_PARAM_TYPE_NONE,
381 TEE_PARAM_TYPE_NONE,
382 TEE_PARAM_TYPE_NONE);
383
384 if (param_types != exp_param_types)
385 return TEE_ERROR_BAD_PARAMETERS;
386
387 switch (params[0].value.a) {
388 case TA_SHA_SHA1:
389 hash_algo = TEE_ALG_SHA1;
390 break;
391 case TA_SHA_SHA224:
392 hash_algo = TEE_ALG_SHA224;
393 break;
394 case TA_SHA_SHA256:
395 hash_algo = TEE_ALG_SHA256;
396 break;
397 case TA_SHA_SHA384:
398 hash_algo = TEE_ALG_SHA384;
399 break;
400 case TA_SHA_SHA512:
401 hash_algo = TEE_ALG_SHA512;
402 break;
403 case TA_SM3:
404 hash_algo = TEE_ALG_SM3;
405 break;
406 case TA_HMAC_SHA1:
407 key_type = TEE_TYPE_HMAC_SHA1;
408 hash_algo = TEE_ALG_HMAC_SHA1;
409 max_key_size = 512;
410 break;
411 case TA_HMAC_SHA224:
412 key_type = TEE_TYPE_HMAC_SHA224;
413 hash_algo = TEE_ALG_HMAC_SHA224;
414 max_key_size = 512;
415 break;
416 case TA_HMAC_SHA256:
417 key_type = TEE_TYPE_HMAC_SHA256;
418 hash_algo = TEE_ALG_HMAC_SHA256;
419 max_key_size = 512;
420 break;
421 case TA_HMAC_SHA384:
422 key_type = TEE_TYPE_HMAC_SHA384;
423 hash_algo = TEE_ALG_HMAC_SHA384;
424 max_key_size = 1024;
425 break;
426 case TA_HMAC_SHA512:
427 key_type = TEE_TYPE_HMAC_SHA512;
428 hash_algo = TEE_ALG_HMAC_SHA512;
429 max_key_size = 1024;
430 break;
431 case TA_HMAC_SM3:
432 key_type = TEE_TYPE_HMAC_SM3;
433 hash_algo = TEE_ALG_HMAC_SM3;
434 max_key_size = 512;
435 break;
436 default:
437 return TEE_ERROR_BAD_PARAMETERS;
438 }
439
440 if (crypto_op)
441 TEE_FreeOperation(crypto_op);
442
443 if (is_mac(hash_algo)) {
444 res = TEE_AllocateOperation(&crypto_op, hash_algo, TEE_MODE_MAC, max_key_size);
445 CHECK(res, "TEE_AllocateOperation", return res;);
446
447 res = TEE_AllocateTransientObject(key_type, max_key_size, &hkey);
448 CHECK(res, "TEE_AllocateTransientObject", return res;);
449
450 attr.attributeID = TEE_ATTR_SECRET_VALUE;
451 attr.content.ref.buffer = mac_key;
452 attr.content.ref.length = mac_key_size / 8;
453
454 res = TEE_PopulateTransientObject(hkey, &attr, 1);
455 CHECK(res, "TEE_PopulateTransientObject", return res;);
456
457 res = TEE_SetOperationKey(crypto_op, hkey);
458 CHECK(res, "TEE_SetOperationKey", return res;);
459
460 TEE_FreeTransientObject(hkey);
461 } else {
462 res = TEE_AllocateOperation(&crypto_op, hash_algo, TEE_MODE_DIGEST, 0);
463 CHECK(res, "TEE_AllocateOperation", return res;);
464 }
465 return TEE_SUCCESS;
466}
467
468void cmd_clean_res(void)
469{
470 if (crypto_op)
471 TEE_FreeOperation(crypto_op);
472}