blob: 6a64f4b53eb00be37a6a93a84b584155dabbe334 [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;
110 void *in, *out;
111 uint32_t insz;
112 uint32_t outsz;
113 uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
114 TEE_PARAM_TYPE_MEMREF_INOUT,
115 TEE_PARAM_TYPE_VALUE_INPUT,
116 TEE_PARAM_TYPE_NONE);
Etienne Carriereb85a5f92017-05-03 18:21:56 +0200117 bool secure_in;
118 bool secure_out = false;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300119
120 if (param_types != exp_param_types)
121 return TEE_ERROR_BAD_PARAMETERS;
122
Etienne Carriereb85a5f92017-05-03 18:21:56 +0200123 if (use_sdp) {
124 /*
125 * Whatever is expected as memory reference, it is mandatory
126 * for SDP aware trusted applications of safely indentify all
127 * memory reference parameters. Hence these tests must be part
128 * of the performance test setup.
129 */
130 secure_in = is_inbuf_a_secure_memref(&params[0]);
131 secure_out = is_outbuf_a_secure_memref(&params[1]);
132
133 /*
134 * We could invalidate only the caches. We prefer to flush
135 * them in case 2 sub-buffers are accessed by TAs from a single
136 * allocated SDP memory buffer, and those are not cache-aligned.
137 * Invalidating might cause data loss in cache lines. Hence
138 * rather flush them all before accessing (in read or write).
139 */
140 if (secure_in) {
141 res = flush_memref_buffer(&params[0]);
142 CHECK(res, "pre-flush in memref param", return res;);
143 }
144 if (secure_out) {
145 res = flush_memref_buffer(&params[1]);
146 CHECK(res, "pre-flush out memref param", return res;);
147 }
148 }
149
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300150 in = params[0].memref.buffer;
151 insz = params[0].memref.size;
152 out = params[1].memref.buffer;
153 outsz = params[1].memref.size;
154 n = params[2].value.a;
155
Jens Wiklander3b2da642017-10-19 13:50:04 +0200156 if (algo == TEE_ALG_AES_GCM) {
157 while (n--) {
158 res = TEE_AEUpdate(crypto_op, in, insz, out, &outsz);
159 CHECK(res, "TEE_AEUpdate", return res;);
160 }
161 } else {
162 while (n--) {
163 res = TEE_CipherUpdate(crypto_op, in, insz,
164 out, &outsz);
165 CHECK(res, "TEE_CipherUpdate", return res;);
166 }
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300167 }
Etienne Carriereb85a5f92017-05-03 18:21:56 +0200168
169 if (secure_out) {
170 /* intentionally flush output data from cache for SDP buffers */
171 res = flush_memref_buffer(&params[1]);
172 CHECK(res, "post-flush out memref param", return res;);
173 }
174
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300175 return TEE_SUCCESS;
176}
177
178TEE_Result cmd_prepare_key(uint32_t param_types, TEE_Param params[4])
179{
180 TEE_Result res;
181 TEE_ObjectHandle hkey;
182 TEE_ObjectHandle hkey2;
183 TEE_Attribute attr;
184 uint32_t mode;
185 uint32_t op_keysize;
186 uint32_t keysize;
Jens Wiklander3b2da642017-10-19 13:50:04 +0200187 const uint8_t *ivp;
188 size_t ivlen;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300189 static uint8_t aes_key[] = { 0x00, 0x01, 0x02, 0x03,
190 0x04, 0x05, 0x06, 0x07,
191 0x08, 0x09, 0x0A, 0x0B,
192 0x0C, 0x0D, 0x0E, 0x0F,
193 0x10, 0x11, 0x12, 0x13,
194 0x14, 0x15, 0x16, 0x17,
195 0x18, 0x19, 0x1A, 0x1B,
196 0x1C, 0x1D, 0x1E, 0x1F };
197 static uint8_t aes_key2[] = { 0x20, 0x21, 0x22, 0x23,
198 0x24, 0x25, 0x26, 0x27,
199 0x28, 0x29, 0x2A, 0x2B,
200 0x2C, 0x2D, 0x2E, 0x2F,
201 0x30, 0x31, 0x32, 0x33,
202 0x34, 0x35, 0x36, 0x37,
203 0x38, 0x39, 0x3A, 0x3B,
204 0x3C, 0x3D, 0x3E, 0x3F };
205
206 uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
207 TEE_PARAM_TYPE_VALUE_INPUT,
208 TEE_PARAM_TYPE_NONE,
209 TEE_PARAM_TYPE_NONE);
210 if (param_types != exp_param_types)
211 return TEE_ERROR_BAD_PARAMETERS;
212
213 mode = params[0].value.a ? TEE_MODE_DECRYPT : TEE_MODE_ENCRYPT;
214 keysize = params[0].value.b;
215 op_keysize = keysize;
216
217 switch (params[1].value.a) {
218 case TA_AES_ECB:
219 algo = TEE_ALG_AES_ECB_NOPAD;
220 use_iv = 0;
221 break;
222 case TA_AES_CBC:
223 algo = TEE_ALG_AES_CBC_NOPAD;
224 use_iv = 1;
225 break;
226 case TA_AES_CTR:
227 algo = TEE_ALG_AES_CTR;
228 use_iv = 1;
229 break;
230 case TA_AES_XTS:
231 algo = TEE_ALG_AES_XTS;
232 use_iv = 1;
233 op_keysize *= 2;
234 break;
Jens Wiklander3b2da642017-10-19 13:50:04 +0200235 case TA_AES_GCM:
236 algo = TEE_ALG_AES_GCM;
237 use_iv = 1;
238 break;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300239 default:
240 return TEE_ERROR_BAD_PARAMETERS;
241 }
242
243 cmd_clean_res();
244
245 res = TEE_AllocateOperation(&crypto_op, algo, mode, op_keysize);
246 CHECK(res, "TEE_AllocateOperation", return res;);
247
248 res = TEE_AllocateTransientObject(TEE_TYPE_AES, keysize, &hkey);
249 CHECK(res, "TEE_AllocateTransientObject", return res;);
250
251 attr.attributeID = TEE_ATTR_SECRET_VALUE;
252 attr.content.ref.buffer = aes_key;
253 attr.content.ref.length = keysize / 8;
254
255 res = TEE_PopulateTransientObject(hkey, &attr, 1);
256 CHECK(res, "TEE_PopulateTransientObject", return res;);
257
258 if (algo == TEE_ALG_AES_XTS) {
259 res = TEE_AllocateTransientObject(TEE_TYPE_AES, keysize,
260 &hkey2);
261 CHECK(res, "TEE_AllocateTransientObject", return res;);
262
263 attr.content.ref.buffer = aes_key2;
264
265 res = TEE_PopulateTransientObject(hkey2, &attr, 1);
266 CHECK(res, "TEE_PopulateTransientObject", return res;);
267
268 res = TEE_SetOperationKey2(crypto_op, hkey, hkey2);
269 CHECK(res, "TEE_SetOperationKey2", return res;);
270
271 TEE_FreeTransientObject(hkey2);
272 } else {
273 res = TEE_SetOperationKey(crypto_op, hkey);
274 CHECK(res, "TEE_SetOperationKey", return res;);
275 }
276
277 TEE_FreeTransientObject(hkey);
278
Jens Wiklander3b2da642017-10-19 13:50:04 +0200279 if (use_iv) {
280 ivp = iv;
281 ivlen = sizeof(iv);
282 } else {
283 ivp = NULL;
284 ivlen = 0;
285 }
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300286
Jens Wiklander3b2da642017-10-19 13:50:04 +0200287 if (algo == TEE_ALG_AES_GCM) {
288 return TEE_AEInit(crypto_op, ivp, ivlen, TAG_LEN, 0, 0);
289 } else {
290 TEE_CipherInit(crypto_op, ivp, ivlen);
291 return TEE_SUCCESS;
292 }
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300293}
294
295void cmd_clean_res(void)
296{
297 if (crypto_op)
298 TEE_FreeOperation(crypto_op);
299}