blob: f99f3e8e58b9aaa625f43331c2577b024c6cbd04 [file] [log] [blame]
Igor Opaniuk44aff4b2016-09-16 10:18:00 +03001/*
2 * Copyright (c) 2015, Linaro Limited
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
Etienne Carriereb85a5f92017-05-03 18:21:56 +020028#include <tee_internal_api_extensions.h>
Igor Opaniuk44aff4b2016-09-16 10:18:00 +030029#include <tee_internal_api.h>
30#include <tee_ta_api.h>
31#include <string.h>
32#include <trace.h>
33
34#include "ta_aes_perf.h"
35#include "ta_aes_perf_priv.h"
36
37#define CHECK(res, name, action) do { \
38 if ((res) != TEE_SUCCESS) { \
39 DMSG(name ": 0x%08x", (res)); \
40 action \
41 } \
42 } while(0)
43
Jens Wiklander3b2da642017-10-19 13:50:04 +020044#define TAG_LEN 128
45
Igor Opaniuk44aff4b2016-09-16 10:18:00 +030046static uint8_t iv[] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
47 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF };
48static int use_iv;
49
50static TEE_OperationHandle crypto_op = NULL;
Jens Wiklander3b2da642017-10-19 13:50:04 +020051static uint32_t algo;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +030052
Etienne Carriereb85a5f92017-05-03 18:21:56 +020053static bool is_inbuf_a_secure_memref(TEE_Param *param)
54{
Etienne Carriere102092e2019-03-28 15:24:22 +010055 TEE_Result res = TEE_ERROR_GENERIC;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +030056
Etienne Carriereb85a5f92017-05-03 18:21:56 +020057 /*
58 * Check secure attribute for the referenced buffer
59 * Trust core on validity of the memref size: test only 1st byte
60 * instead of the overall buffer, and if it's not secure, assume
61 * the buffer is nonsecure.
62 */
63 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER |
64 TEE_MEMORY_ACCESS_READ |
65 TEE_MEMORY_ACCESS_SECURE,
66 param->memref.buffer, 1);
67 return (res == TEE_SUCCESS);
68}
Igor Opaniuk44aff4b2016-09-16 10:18:00 +030069
Etienne Carriereb85a5f92017-05-03 18:21:56 +020070static bool is_outbuf_a_secure_memref(TEE_Param *param)
71{
Etienne Carriere102092e2019-03-28 15:24:22 +010072 TEE_Result res = TEE_ERROR_GENERIC;
Etienne Carriereb85a5f92017-05-03 18:21:56 +020073
74 /*
75 * Check secure attribute for the referenced buffer
76 * Trust core on validity of the memref size: test only 1st byte
77 * instead of the overall buffer, and if it's not secure, assume
78 * the buffer is nonsecure.
79 */
80 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER |
81 TEE_MEMORY_ACCESS_WRITE |
82 TEE_MEMORY_ACCESS_SECURE,
83 param->memref.buffer, 1);
84 return (res == TEE_SUCCESS);
85}
86
87#if defined(CFG_CACHE_API)
88static TEE_Result flush_memref_buffer(TEE_Param *param)
89{
Etienne Carriere102092e2019-03-28 15:24:22 +010090 TEE_Result res = TEE_ERROR_GENERIC;
Etienne Carriereb85a5f92017-05-03 18:21:56 +020091
92 res = TEE_CacheFlush(param->memref.buffer,
93 param->memref.size);
94 CHECK(res, "TEE_CacheFlush(in)", return res;);
95 return res;
96}
97#else
98static __maybe_unused TEE_Result flush_memref_buffer(TEE_Param *param __unused)
99{
100 return TEE_SUCCESS;
101}
102#endif /* CFG_CACHE_API */
103
104TEE_Result cmd_process(uint32_t param_types,
105 TEE_Param params[TEE_NUM_PARAMS],
106 bool use_sdp)
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300107{
Etienne Carriere102092e2019-03-28 15:24:22 +0100108 TEE_Result res = TEE_ERROR_GENERIC;
109 int n = 0;
110 int unit = 0;
111 void *in = NULL;
112 void *out = NULL;
113 uint32_t insz = 0;
114 uint32_t outsz = 0;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300115 uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
116 TEE_PARAM_TYPE_MEMREF_INOUT,
117 TEE_PARAM_TYPE_VALUE_INPUT,
118 TEE_PARAM_TYPE_NONE);
Etienne Carriere102092e2019-03-28 15:24:22 +0100119 bool secure_in = false;
Etienne Carriereb85a5f92017-05-03 18:21:56 +0200120 bool secure_out = false;
Jerome Forissiera410edb2018-03-08 10:36:37 +0100121 TEE_Result (*do_update)(TEE_OperationHandle, const void *, uint32_t,
Etienne Carriere102092e2019-03-28 15:24:22 +0100122 void *, uint32_t *) = NULL;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300123
124 if (param_types != exp_param_types)
125 return TEE_ERROR_BAD_PARAMETERS;
126
Etienne Carriereb85a5f92017-05-03 18:21:56 +0200127 if (use_sdp) {
128 /*
129 * Whatever is expected as memory reference, it is mandatory
130 * for SDP aware trusted applications of safely indentify all
131 * memory reference parameters. Hence these tests must be part
132 * of the performance test setup.
133 */
134 secure_in = is_inbuf_a_secure_memref(&params[0]);
135 secure_out = is_outbuf_a_secure_memref(&params[1]);
136
137 /*
138 * We could invalidate only the caches. We prefer to flush
139 * them in case 2 sub-buffers are accessed by TAs from a single
140 * allocated SDP memory buffer, and those are not cache-aligned.
141 * Invalidating might cause data loss in cache lines. Hence
142 * rather flush them all before accessing (in read or write).
143 */
144 if (secure_in) {
145 res = flush_memref_buffer(&params[0]);
146 CHECK(res, "pre-flush in memref param", return res;);
147 }
148 if (secure_out) {
149 res = flush_memref_buffer(&params[1]);
150 CHECK(res, "pre-flush out memref param", return res;);
151 }
152 }
153
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300154 in = params[0].memref.buffer;
155 insz = params[0].memref.size;
156 out = params[1].memref.buffer;
157 outsz = params[1].memref.size;
158 n = params[2].value.a;
Jerome Forissiera410edb2018-03-08 10:36:37 +0100159 unit = params[2].value.b;
160 if (!unit)
161 unit = insz;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300162
Jerome Forissiera410edb2018-03-08 10:36:37 +0100163 if (algo == TEE_ALG_AES_GCM)
164 do_update = TEE_AEUpdate;
165 else
166 do_update = TEE_CipherUpdate;
167
168 while (n--) {
Etienne Carriere102092e2019-03-28 15:24:22 +0100169 uint32_t i = 0;
Jerome Forissiera410edb2018-03-08 10:36:37 +0100170 for (i = 0; i < insz / unit; i++) {
171 res = do_update(crypto_op, in, unit, out, &outsz);
172 CHECK(res, "TEE_CipherUpdate/TEE_AEUpdate", return res;);
173 in = (void *)((uintptr_t)in + unit);
174 out = (void *)((uintptr_t)out + unit);
Jens Wiklander3b2da642017-10-19 13:50:04 +0200175 }
Jerome Forissiera410edb2018-03-08 10:36:37 +0100176 if (insz % unit) {
177 res = do_update(crypto_op, in, insz % unit, out, &outsz);
178 CHECK(res, "TEE_CipherUpdate/TEE_AEUpdate", return res;);
Jens Wiklander3b2da642017-10-19 13:50:04 +0200179 }
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300180 }
Etienne Carriereb85a5f92017-05-03 18:21:56 +0200181
182 if (secure_out) {
183 /* intentionally flush output data from cache for SDP buffers */
184 res = flush_memref_buffer(&params[1]);
185 CHECK(res, "post-flush out memref param", return res;);
186 }
187
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300188 return TEE_SUCCESS;
189}
190
191TEE_Result cmd_prepare_key(uint32_t param_types, TEE_Param params[4])
192{
Etienne Carriere102092e2019-03-28 15:24:22 +0100193 TEE_Result res = TEE_ERROR_GENERIC;
194 TEE_ObjectHandle hkey = TEE_HANDLE_NULL;
195 TEE_ObjectHandle hkey2 = TEE_HANDLE_NULL;
196 TEE_Attribute attr = { };
197 uint32_t mode = 0;
198 uint32_t op_keysize = 0;
199 uint32_t keysize = 0;
200 const uint8_t *ivp = NULL;
201 size_t ivlen = 0;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300202 static uint8_t aes_key[] = { 0x00, 0x01, 0x02, 0x03,
203 0x04, 0x05, 0x06, 0x07,
204 0x08, 0x09, 0x0A, 0x0B,
205 0x0C, 0x0D, 0x0E, 0x0F,
206 0x10, 0x11, 0x12, 0x13,
207 0x14, 0x15, 0x16, 0x17,
208 0x18, 0x19, 0x1A, 0x1B,
209 0x1C, 0x1D, 0x1E, 0x1F };
210 static uint8_t aes_key2[] = { 0x20, 0x21, 0x22, 0x23,
211 0x24, 0x25, 0x26, 0x27,
212 0x28, 0x29, 0x2A, 0x2B,
213 0x2C, 0x2D, 0x2E, 0x2F,
214 0x30, 0x31, 0x32, 0x33,
215 0x34, 0x35, 0x36, 0x37,
216 0x38, 0x39, 0x3A, 0x3B,
217 0x3C, 0x3D, 0x3E, 0x3F };
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300218 uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
219 TEE_PARAM_TYPE_VALUE_INPUT,
220 TEE_PARAM_TYPE_NONE,
221 TEE_PARAM_TYPE_NONE);
Etienne Carriere102092e2019-03-28 15:24:22 +0100222
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300223 if (param_types != exp_param_types)
224 return TEE_ERROR_BAD_PARAMETERS;
225
226 mode = params[0].value.a ? TEE_MODE_DECRYPT : TEE_MODE_ENCRYPT;
227 keysize = params[0].value.b;
228 op_keysize = keysize;
229
230 switch (params[1].value.a) {
231 case TA_AES_ECB:
232 algo = TEE_ALG_AES_ECB_NOPAD;
233 use_iv = 0;
234 break;
235 case TA_AES_CBC:
236 algo = TEE_ALG_AES_CBC_NOPAD;
237 use_iv = 1;
238 break;
239 case TA_AES_CTR:
240 algo = TEE_ALG_AES_CTR;
241 use_iv = 1;
242 break;
243 case TA_AES_XTS:
244 algo = TEE_ALG_AES_XTS;
245 use_iv = 1;
246 op_keysize *= 2;
247 break;
Jens Wiklander3b2da642017-10-19 13:50:04 +0200248 case TA_AES_GCM:
249 algo = TEE_ALG_AES_GCM;
250 use_iv = 1;
251 break;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300252 default:
253 return TEE_ERROR_BAD_PARAMETERS;
254 }
255
256 cmd_clean_res();
257
258 res = TEE_AllocateOperation(&crypto_op, algo, mode, op_keysize);
259 CHECK(res, "TEE_AllocateOperation", return res;);
260
261 res = TEE_AllocateTransientObject(TEE_TYPE_AES, keysize, &hkey);
262 CHECK(res, "TEE_AllocateTransientObject", return res;);
263
264 attr.attributeID = TEE_ATTR_SECRET_VALUE;
265 attr.content.ref.buffer = aes_key;
266 attr.content.ref.length = keysize / 8;
267
268 res = TEE_PopulateTransientObject(hkey, &attr, 1);
269 CHECK(res, "TEE_PopulateTransientObject", return res;);
270
271 if (algo == TEE_ALG_AES_XTS) {
272 res = TEE_AllocateTransientObject(TEE_TYPE_AES, keysize,
273 &hkey2);
274 CHECK(res, "TEE_AllocateTransientObject", return res;);
275
276 attr.content.ref.buffer = aes_key2;
277
278 res = TEE_PopulateTransientObject(hkey2, &attr, 1);
279 CHECK(res, "TEE_PopulateTransientObject", return res;);
280
281 res = TEE_SetOperationKey2(crypto_op, hkey, hkey2);
282 CHECK(res, "TEE_SetOperationKey2", return res;);
283
284 TEE_FreeTransientObject(hkey2);
285 } else {
286 res = TEE_SetOperationKey(crypto_op, hkey);
287 CHECK(res, "TEE_SetOperationKey", return res;);
288 }
289
290 TEE_FreeTransientObject(hkey);
291
Jens Wiklander3b2da642017-10-19 13:50:04 +0200292 if (use_iv) {
293 ivp = iv;
294 ivlen = sizeof(iv);
295 } else {
296 ivp = NULL;
297 ivlen = 0;
298 }
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300299
Jens Wiklander3b2da642017-10-19 13:50:04 +0200300 if (algo == TEE_ALG_AES_GCM) {
301 return TEE_AEInit(crypto_op, ivp, ivlen, TAG_LEN, 0, 0);
302 } else {
303 TEE_CipherInit(crypto_op, ivp, ivlen);
304 return TEE_SUCCESS;
305 }
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300306}
307
308void cmd_clean_res(void)
309{
310 if (crypto_op)
311 TEE_FreeOperation(crypto_op);
312}