blob: bc79cbd39b46db0c62d275ebc493762b07caed92 [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
44static uint8_t iv[] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
45 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF };
46static int use_iv;
47
48static TEE_OperationHandle crypto_op = NULL;
49
Etienne Carriereb85a5f92017-05-03 18:21:56 +020050static bool is_inbuf_a_secure_memref(TEE_Param *param)
51{
52 TEE_Result res;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +030053
Etienne Carriereb85a5f92017-05-03 18:21:56 +020054 /*
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_READ |
62 TEE_MEMORY_ACCESS_SECURE,
63 param->memref.buffer, 1);
64 return (res == TEE_SUCCESS);
65}
Igor Opaniuk44aff4b2016-09-16 10:18:00 +030066
Etienne Carriereb85a5f92017-05-03 18:21:56 +020067static bool is_outbuf_a_secure_memref(TEE_Param *param)
68{
69 TEE_Result res;
70
71 /*
72 * Check secure attribute for the referenced buffer
73 * Trust core on validity of the memref size: test only 1st byte
74 * instead of the overall buffer, and if it's not secure, assume
75 * the buffer is nonsecure.
76 */
77 res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER |
78 TEE_MEMORY_ACCESS_WRITE |
79 TEE_MEMORY_ACCESS_SECURE,
80 param->memref.buffer, 1);
81 return (res == TEE_SUCCESS);
82}
83
84#if defined(CFG_CACHE_API)
85static TEE_Result flush_memref_buffer(TEE_Param *param)
86{
87 TEE_Result res;
88
89 res = TEE_CacheFlush(param->memref.buffer,
90 param->memref.size);
91 CHECK(res, "TEE_CacheFlush(in)", return res;);
92 return res;
93}
94#else
95static __maybe_unused TEE_Result flush_memref_buffer(TEE_Param *param __unused)
96{
97 return TEE_SUCCESS;
98}
99#endif /* CFG_CACHE_API */
100
101TEE_Result cmd_process(uint32_t param_types,
102 TEE_Param params[TEE_NUM_PARAMS],
103 bool use_sdp)
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300104{
105 TEE_Result res;
106 int n;
107 void *in, *out;
108 uint32_t insz;
109 uint32_t outsz;
110 uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
111 TEE_PARAM_TYPE_MEMREF_INOUT,
112 TEE_PARAM_TYPE_VALUE_INPUT,
113 TEE_PARAM_TYPE_NONE);
Etienne Carriereb85a5f92017-05-03 18:21:56 +0200114 bool secure_in;
115 bool secure_out = false;
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300116
117 if (param_types != exp_param_types)
118 return TEE_ERROR_BAD_PARAMETERS;
119
Etienne Carriereb85a5f92017-05-03 18:21:56 +0200120 if (use_sdp) {
121 /*
122 * Whatever is expected as memory reference, it is mandatory
123 * for SDP aware trusted applications of safely indentify all
124 * memory reference parameters. Hence these tests must be part
125 * of the performance test setup.
126 */
127 secure_in = is_inbuf_a_secure_memref(&params[0]);
128 secure_out = is_outbuf_a_secure_memref(&params[1]);
129
130 /*
131 * We could invalidate only the caches. We prefer to flush
132 * them in case 2 sub-buffers are accessed by TAs from a single
133 * allocated SDP memory buffer, and those are not cache-aligned.
134 * Invalidating might cause data loss in cache lines. Hence
135 * rather flush them all before accessing (in read or write).
136 */
137 if (secure_in) {
138 res = flush_memref_buffer(&params[0]);
139 CHECK(res, "pre-flush in memref param", return res;);
140 }
141 if (secure_out) {
142 res = flush_memref_buffer(&params[1]);
143 CHECK(res, "pre-flush out memref param", return res;);
144 }
145 }
146
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300147 in = params[0].memref.buffer;
148 insz = params[0].memref.size;
149 out = params[1].memref.buffer;
150 outsz = params[1].memref.size;
151 n = params[2].value.a;
152
153 while (n--) {
154 res = TEE_CipherUpdate(crypto_op, in, insz, out, &outsz);
155 CHECK(res, "TEE_CipherUpdate", return res;);
156 }
Etienne Carriereb85a5f92017-05-03 18:21:56 +0200157
158 if (secure_out) {
159 /* intentionally flush output data from cache for SDP buffers */
160 res = flush_memref_buffer(&params[1]);
161 CHECK(res, "post-flush out memref param", return res;);
162 }
163
Igor Opaniuk44aff4b2016-09-16 10:18:00 +0300164 return TEE_SUCCESS;
165}
166
167TEE_Result cmd_prepare_key(uint32_t param_types, TEE_Param params[4])
168{
169 TEE_Result res;
170 TEE_ObjectHandle hkey;
171 TEE_ObjectHandle hkey2;
172 TEE_Attribute attr;
173 uint32_t mode;
174 uint32_t op_keysize;
175 uint32_t keysize;
176 uint32_t algo;
177 static uint8_t aes_key[] = { 0x00, 0x01, 0x02, 0x03,
178 0x04, 0x05, 0x06, 0x07,
179 0x08, 0x09, 0x0A, 0x0B,
180 0x0C, 0x0D, 0x0E, 0x0F,
181 0x10, 0x11, 0x12, 0x13,
182 0x14, 0x15, 0x16, 0x17,
183 0x18, 0x19, 0x1A, 0x1B,
184 0x1C, 0x1D, 0x1E, 0x1F };
185 static uint8_t aes_key2[] = { 0x20, 0x21, 0x22, 0x23,
186 0x24, 0x25, 0x26, 0x27,
187 0x28, 0x29, 0x2A, 0x2B,
188 0x2C, 0x2D, 0x2E, 0x2F,
189 0x30, 0x31, 0x32, 0x33,
190 0x34, 0x35, 0x36, 0x37,
191 0x38, 0x39, 0x3A, 0x3B,
192 0x3C, 0x3D, 0x3E, 0x3F };
193
194 uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
195 TEE_PARAM_TYPE_VALUE_INPUT,
196 TEE_PARAM_TYPE_NONE,
197 TEE_PARAM_TYPE_NONE);
198 if (param_types != exp_param_types)
199 return TEE_ERROR_BAD_PARAMETERS;
200
201 mode = params[0].value.a ? TEE_MODE_DECRYPT : TEE_MODE_ENCRYPT;
202 keysize = params[0].value.b;
203 op_keysize = keysize;
204
205 switch (params[1].value.a) {
206 case TA_AES_ECB:
207 algo = TEE_ALG_AES_ECB_NOPAD;
208 use_iv = 0;
209 break;
210 case TA_AES_CBC:
211 algo = TEE_ALG_AES_CBC_NOPAD;
212 use_iv = 1;
213 break;
214 case TA_AES_CTR:
215 algo = TEE_ALG_AES_CTR;
216 use_iv = 1;
217 break;
218 case TA_AES_XTS:
219 algo = TEE_ALG_AES_XTS;
220 use_iv = 1;
221 op_keysize *= 2;
222 break;
223 default:
224 return TEE_ERROR_BAD_PARAMETERS;
225 }
226
227 cmd_clean_res();
228
229 res = TEE_AllocateOperation(&crypto_op, algo, mode, op_keysize);
230 CHECK(res, "TEE_AllocateOperation", return res;);
231
232 res = TEE_AllocateTransientObject(TEE_TYPE_AES, keysize, &hkey);
233 CHECK(res, "TEE_AllocateTransientObject", return res;);
234
235 attr.attributeID = TEE_ATTR_SECRET_VALUE;
236 attr.content.ref.buffer = aes_key;
237 attr.content.ref.length = keysize / 8;
238
239 res = TEE_PopulateTransientObject(hkey, &attr, 1);
240 CHECK(res, "TEE_PopulateTransientObject", return res;);
241
242 if (algo == TEE_ALG_AES_XTS) {
243 res = TEE_AllocateTransientObject(TEE_TYPE_AES, keysize,
244 &hkey2);
245 CHECK(res, "TEE_AllocateTransientObject", return res;);
246
247 attr.content.ref.buffer = aes_key2;
248
249 res = TEE_PopulateTransientObject(hkey2, &attr, 1);
250 CHECK(res, "TEE_PopulateTransientObject", return res;);
251
252 res = TEE_SetOperationKey2(crypto_op, hkey, hkey2);
253 CHECK(res, "TEE_SetOperationKey2", return res;);
254
255 TEE_FreeTransientObject(hkey2);
256 } else {
257 res = TEE_SetOperationKey(crypto_op, hkey);
258 CHECK(res, "TEE_SetOperationKey", return res;);
259 }
260
261 TEE_FreeTransientObject(hkey);
262
263 if (use_iv)
264 TEE_CipherInit(crypto_op, iv, sizeof(iv));
265 else
266 TEE_CipherInit(crypto_op, NULL, 0);
267
268 return TEE_SUCCESS;
269}
270
271void cmd_clean_res(void)
272{
273 if (crypto_op)
274 TEE_FreeOperation(crypto_op);
275}