1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2020, Linaro Limited
4 */
5
6 #include <compiler.h>
7 #include <crypto/crypto.h>
8 #include <kernel/tee_time.h>
9 #include <pta_invoke_tests.h>
10 #include <tee_api_defines.h>
11 #include <tee_api_types.h>
12 #include <trace.h>
13 #include <types_ext.h>
14 #include <utee_defines.h>
15
16 #include "misc.h"
17
18 /*
19 * These keys and iv are copied from optee_test/ta/aes_perf/ta_aes_perf.c,
20 * not because their actual values are important, rather that there's no
21 * reason to use different values.
22 */
23
24 static const uint8_t aes_key[] = {
25 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
26 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
27 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
28 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
29 };
30
31 static const uint8_t aes_key2[] = {
32 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
33 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
34 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
35 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F
36 };
37
38 static uint8_t aes_iv[] = {
39 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
40 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF
41 };
42
free_ctx(void ** ctx,uint32_t algo)43 static void free_ctx(void **ctx, uint32_t algo)
44 {
45 if (algo == TEE_ALG_AES_GCM)
46 crypto_authenc_free_ctx(*ctx);
47 else
48 crypto_cipher_free_ctx(*ctx);
49
50 *ctx = NULL;
51 }
52
init_ctx(void ** ctx,uint32_t algo,TEE_OperationMode mode,size_t key_size_bits,size_t payload_len)53 static TEE_Result init_ctx(void **ctx, uint32_t algo, TEE_OperationMode mode,
54 size_t key_size_bits, size_t payload_len)
55 {
56 TEE_Result res = TEE_SUCCESS;
57 const uint8_t *key2 = NULL;
58 const uint8_t *iv = NULL;
59 size_t key2_len = 0;
60 size_t key_len = 0;
61 size_t iv_len = 0;
62
63 if (key_size_bits % 8)
64 return TEE_ERROR_BAD_PARAMETERS;
65 key_len = key_size_bits / 8;
66 if (key_len > sizeof(aes_key))
67 return TEE_ERROR_BAD_PARAMETERS;
68
69 /* Alloc ctx */
70 switch (algo) {
71 case TEE_ALG_AES_XTS:
72 key2_len = key_len;
73 key2 = aes_key2;
74 fallthrough;
75 case TEE_ALG_AES_ECB_NOPAD:
76 case TEE_ALG_AES_CBC_NOPAD:
77 case TEE_ALG_AES_CTR:
78 res = crypto_cipher_alloc_ctx(ctx, algo);
79 break;
80 case TEE_ALG_AES_GCM:
81 res = crypto_authenc_alloc_ctx(ctx, algo);
82 break;
83 default:
84 return TEE_ERROR_BAD_PARAMETERS;
85 }
86 if (res)
87 return res;
88
89 /* Init ctx */
90 switch (algo) {
91 case TEE_ALG_AES_CBC_NOPAD:
92 case TEE_ALG_AES_CTR:
93 case TEE_ALG_AES_XTS:
94 iv = aes_iv;
95 iv_len = sizeof(aes_iv);
96 fallthrough;
97 case TEE_ALG_AES_ECB_NOPAD:
98 res = crypto_cipher_init(*ctx, mode, aes_key, key_len, key2,
99 key2_len, iv, iv_len);
100 break;
101 case TEE_ALG_AES_GCM:
102 res = crypto_authenc_init(*ctx, mode, aes_key, key_len, aes_iv,
103 sizeof(aes_iv), TEE_AES_BLOCK_SIZE,
104 0, payload_len);
105 break;
106 default:
107 return TEE_ERROR_BAD_PARAMETERS;
108 }
109
110 if (res)
111 free_ctx(ctx, algo);
112
113 return res;
114 }
115
update_ae(void * ctx,TEE_OperationMode mode,const void * src,size_t len,void * dst)116 static TEE_Result update_ae(void *ctx, TEE_OperationMode mode,
117 const void *src, size_t len, void *dst)
118 {
119 size_t dlen = len;
120
121 return crypto_authenc_update_payload(ctx, mode, src, len, dst, &dlen);
122 }
123
update_cipher(void * ctx,TEE_OperationMode mode,const void * src,size_t len,void * dst)124 static TEE_Result update_cipher(void *ctx, TEE_OperationMode mode,
125 const void *src, size_t len, void *dst)
126 {
127 return crypto_cipher_update(ctx, mode, false, src, len, dst);
128 }
129
do_update(void * ctx,uint32_t algo,TEE_OperationMode mode,unsigned int rep_count,unsigned int unit_size,const uint8_t * in,size_t sz,uint8_t * out)130 static TEE_Result do_update(void *ctx, uint32_t algo, TEE_OperationMode mode,
131 unsigned int rep_count, unsigned int unit_size,
132 const uint8_t *in, size_t sz, uint8_t *out)
133 {
134 TEE_Result (*update_func)(void *ctx, TEE_OperationMode mode,
135 const void *src, size_t len,
136 void *dst) = NULL;
137 TEE_Result res = TEE_SUCCESS;
138 unsigned int n = 0;
139 unsigned int m = 0;
140
141 if (algo == TEE_ALG_AES_GCM)
142 update_func = update_ae;
143 else
144 update_func = update_cipher;
145
146 for (n = 0; n < rep_count; n++) {
147 for (m = 0; m < sz / unit_size; m++) {
148 res = update_func(ctx, mode, in + m * unit_size,
149 unit_size, out + m * unit_size);
150 if (res)
151 return res;
152 }
153 if (sz % unit_size)
154 res = update_func(ctx, mode, in + m * unit_size,
155 sz % unit_size, out + m * unit_size);
156 }
157
158 return res;
159 }
160
core_aes_perf_tests(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])161 TEE_Result core_aes_perf_tests(uint32_t param_types,
162 TEE_Param params[TEE_NUM_PARAMS])
163 {
164 uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
165 TEE_PARAM_TYPE_VALUE_INPUT,
166 TEE_PARAM_TYPE_MEMREF_INOUT,
167 TEE_PARAM_TYPE_MEMREF_INOUT);
168 TEE_Result res = TEE_SUCCESS;
169 TEE_OperationMode mode = 0;
170 unsigned int rep_count = 0;
171 unsigned int unit_size = 0;
172 size_t key_size_bits = 0;
173 uint32_t algo = 0;
174 void *ctx = NULL;
175
176 if (param_types != exp_param_types)
177 return TEE_ERROR_BAD_PARAMETERS;
178
179 switch (params[0].value.b) {
180 case PTA_INVOKE_TESTS_AES_ECB:
181 algo = TEE_ALG_AES_ECB_NOPAD;
182 break;
183 case PTA_INVOKE_TESTS_AES_CBC:
184 algo = TEE_ALG_AES_CBC_NOPAD;
185 break;
186 case PTA_INVOKE_TESTS_AES_CTR:
187 algo = TEE_ALG_AES_CTR;
188 break;
189 case PTA_INVOKE_TESTS_AES_XTS:
190 algo = TEE_ALG_AES_XTS;
191 break;
192 case PTA_INVOKE_TESTS_AES_GCM:
193 algo = TEE_ALG_AES_GCM;
194 break;
195 default:
196 return TEE_ERROR_BAD_PARAMETERS;
197 }
198
199 if (params[0].value.a >> 16)
200 mode = TEE_MODE_DECRYPT;
201 else
202 mode = TEE_MODE_ENCRYPT;
203
204 key_size_bits = params[0].value.a & 0xffff;
205
206 rep_count = params[1].value.a;
207 unit_size = params[1].value.b;
208
209 if (params[2].memref.size > params[3].memref.size)
210 return TEE_ERROR_BAD_PARAMETERS;
211
212 res = init_ctx(&ctx, algo, mode, key_size_bits, params[2].memref.size);
213 if (res)
214 return res;
215
216 res = do_update(ctx, algo, mode, rep_count, unit_size,
217 params[2].memref.buffer, params[2].memref.size,
218 params[3].memref.buffer);
219
220 free_ctx(&ctx, algo);
221 return res;
222 }
223