blob: 6fbdca453f8f049b66cc779fdf5307c927124d90 [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{
55 TEE_Result res;
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{
72 TEE_Result res;
73
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{
90 TEE_Result res;
91
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{
108 TEE_Result res;
109 int n;
Jerome Forissiera410edb2018-03-08 10:36:37 +0100110 int unit;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300111 void *in, *out;
112 uint32_t insz;
113 uint32_t outsz;
114 uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
115 TEE_PARAM_TYPE_MEMREF_INOUT,
116 TEE_PARAM_TYPE_VALUE_INPUT,
117 TEE_PARAM_TYPE_NONE);
Etienne Carriereb85a5f92017-05-03 18:21:56 +0200118 bool secure_in;
119 bool secure_out = false;
Jerome Forissiera410edb2018-03-08 10:36:37 +0100120 TEE_Result (*do_update)(TEE_OperationHandle, const void *, uint32_t,
121 void *, uint32_t *);
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300122
123 if (param_types != exp_param_types)
124 return TEE_ERROR_BAD_PARAMETERS;
125
Etienne Carriereb85a5f92017-05-03 18:21:56 +0200126 if (use_sdp) {
127 /*
128 * Whatever is expected as memory reference, it is mandatory
129 * for SDP aware trusted applications of safely indentify all
130 * memory reference parameters. Hence these tests must be part
131 * of the performance test setup.
132 */
133 secure_in = is_inbuf_a_secure_memref(&params[0]);
134 secure_out = is_outbuf_a_secure_memref(&params[1]);
135
136 /*
137 * We could invalidate only the caches. We prefer to flush
138 * them in case 2 sub-buffers are accessed by TAs from a single
139 * allocated SDP memory buffer, and those are not cache-aligned.
140 * Invalidating might cause data loss in cache lines. Hence
141 * rather flush them all before accessing (in read or write).
142 */
143 if (secure_in) {
144 res = flush_memref_buffer(&params[0]);
145 CHECK(res, "pre-flush in memref param", return res;);
146 }
147 if (secure_out) {
148 res = flush_memref_buffer(&params[1]);
149 CHECK(res, "pre-flush out memref param", return res;);
150 }
151 }
152
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300153 in = params[0].memref.buffer;
154 insz = params[0].memref.size;
155 out = params[1].memref.buffer;
156 outsz = params[1].memref.size;
157 n = params[2].value.a;
Jerome Forissiera410edb2018-03-08 10:36:37 +0100158 unit = params[2].value.b;
159 if (!unit)
160 unit = insz;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300161
Jerome Forissiera410edb2018-03-08 10:36:37 +0100162 if (algo == TEE_ALG_AES_GCM)
163 do_update = TEE_AEUpdate;
164 else
165 do_update = TEE_CipherUpdate;
166
167 while (n--) {
168 uint32_t i;
169 for (i = 0; i < insz / unit; i++) {
170 res = do_update(crypto_op, in, unit, out, &outsz);
171 CHECK(res, "TEE_CipherUpdate/TEE_AEUpdate", return res;);
172 in = (void *)((uintptr_t)in + unit);
173 out = (void *)((uintptr_t)out + unit);
Jens Wiklander3b2da642017-10-19 13:50:04 +0200174 }
Jerome Forissiera410edb2018-03-08 10:36:37 +0100175 if (insz % unit) {
176 res = do_update(crypto_op, in, insz % unit, out, &outsz);
177 CHECK(res, "TEE_CipherUpdate/TEE_AEUpdate", return res;);
Jens Wiklander3b2da642017-10-19 13:50:04 +0200178 }
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300179 }
Etienne Carriereb85a5f92017-05-03 18:21:56 +0200180
181 if (secure_out) {
182 /* intentionally flush output data from cache for SDP buffers */
183 res = flush_memref_buffer(&params[1]);
184 CHECK(res, "post-flush out memref param", return res;);
185 }
186
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300187 return TEE_SUCCESS;
188}
189
190TEE_Result cmd_prepare_key(uint32_t param_types, TEE_Param params[4])
191{
192 TEE_Result res;
193 TEE_ObjectHandle hkey;
194 TEE_ObjectHandle hkey2;
195 TEE_Attribute attr;
196 uint32_t mode;
197 uint32_t op_keysize;
198 uint32_t keysize;
Jens Wiklander3b2da642017-10-19 13:50:04 +0200199 const uint8_t *ivp;
200 size_t ivlen;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300201 static uint8_t aes_key[] = { 0x00, 0x01, 0x02, 0x03,
202 0x04, 0x05, 0x06, 0x07,
203 0x08, 0x09, 0x0A, 0x0B,
204 0x0C, 0x0D, 0x0E, 0x0F,
205 0x10, 0x11, 0x12, 0x13,
206 0x14, 0x15, 0x16, 0x17,
207 0x18, 0x19, 0x1A, 0x1B,
208 0x1C, 0x1D, 0x1E, 0x1F };
209 static uint8_t aes_key2[] = { 0x20, 0x21, 0x22, 0x23,
210 0x24, 0x25, 0x26, 0x27,
211 0x28, 0x29, 0x2A, 0x2B,
212 0x2C, 0x2D, 0x2E, 0x2F,
213 0x30, 0x31, 0x32, 0x33,
214 0x34, 0x35, 0x36, 0x37,
215 0x38, 0x39, 0x3A, 0x3B,
216 0x3C, 0x3D, 0x3E, 0x3F };
217
218 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);
222 if (param_types != exp_param_types)
223 return TEE_ERROR_BAD_PARAMETERS;
224
225 mode = params[0].value.a ? TEE_MODE_DECRYPT : TEE_MODE_ENCRYPT;
226 keysize = params[0].value.b;
227 op_keysize = keysize;
228
229 switch (params[1].value.a) {
230 case TA_AES_ECB:
231 algo = TEE_ALG_AES_ECB_NOPAD;
232 use_iv = 0;
233 break;
234 case TA_AES_CBC:
235 algo = TEE_ALG_AES_CBC_NOPAD;
236 use_iv = 1;
237 break;
238 case TA_AES_CTR:
239 algo = TEE_ALG_AES_CTR;
240 use_iv = 1;
241 break;
242 case TA_AES_XTS:
243 algo = TEE_ALG_AES_XTS;
244 use_iv = 1;
245 op_keysize *= 2;
246 break;
Jens Wiklander3b2da642017-10-19 13:50:04 +0200247 case TA_AES_GCM:
248 algo = TEE_ALG_AES_GCM;
249 use_iv = 1;
250 break;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300251 default:
252 return TEE_ERROR_BAD_PARAMETERS;
253 }
254
255 cmd_clean_res();
256
257 res = TEE_AllocateOperation(&crypto_op, algo, mode, op_keysize);
258 CHECK(res, "TEE_AllocateOperation", return res;);
259
260 res = TEE_AllocateTransientObject(TEE_TYPE_AES, keysize, &hkey);
261 CHECK(res, "TEE_AllocateTransientObject", return res;);
262
263 attr.attributeID = TEE_ATTR_SECRET_VALUE;
264 attr.content.ref.buffer = aes_key;
265 attr.content.ref.length = keysize / 8;
266
267 res = TEE_PopulateTransientObject(hkey, &attr, 1);
268 CHECK(res, "TEE_PopulateTransientObject", return res;);
269
270 if (algo == TEE_ALG_AES_XTS) {
271 res = TEE_AllocateTransientObject(TEE_TYPE_AES, keysize,
272 &hkey2);
273 CHECK(res, "TEE_AllocateTransientObject", return res;);
274
275 attr.content.ref.buffer = aes_key2;
276
277 res = TEE_PopulateTransientObject(hkey2, &attr, 1);
278 CHECK(res, "TEE_PopulateTransientObject", return res;);
279
280 res = TEE_SetOperationKey2(crypto_op, hkey, hkey2);
281 CHECK(res, "TEE_SetOperationKey2", return res;);
282
283 TEE_FreeTransientObject(hkey2);
284 } else {
285 res = TEE_SetOperationKey(crypto_op, hkey);
286 CHECK(res, "TEE_SetOperationKey", return res;);
287 }
288
289 TEE_FreeTransientObject(hkey);
290
Jens Wiklander3b2da642017-10-19 13:50:04 +0200291 if (use_iv) {
292 ivp = iv;
293 ivlen = sizeof(iv);
294 } else {
295 ivp = NULL;
296 ivlen = 0;
297 }
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300298
Jens Wiklander3b2da642017-10-19 13:50:04 +0200299 if (algo == TEE_ALG_AES_GCM) {
300 return TEE_AEInit(crypto_op, ivp, ivlen, TAG_LEN, 0, 0);
301 } else {
302 TEE_CipherInit(crypto_op, ivp, ivlen);
303 return TEE_SUCCESS;
304 }
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300305}
306
307void cmd_clean_res(void)
308{
309 if (crypto_op)
310 TEE_FreeOperation(crypto_op);
311}