1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
6 #include <app_common.h>
7 #include <assert.h>
8 #include <attest_app.h>
9 #include <attest_defs.h>
10 #include <cpuid.h>
11 #include <debug.h>
12 #include <errno.h>
13 #include <limits.h>
14 #include <simd.h>
15
16 /*
17 * The number of pages that is allocated in the .bss for each per-cpu attest app
18 * instance. This number must be at least the the number of per-instance pages
19 * necessary for initiate an attestation app.
20 */
21 #define ATTESTATION_APP_PAGE_COUNT 8U
22
23 /*
24 * This array will hold the pages for the instance specific memory for all the
25 * per-cpu instances of the attestation app. These instances are used for
26 * measurement related operations when Aux granule is not available.
27 */
28 static unsigned char rmm_attest_app_pages
29 [MAX_CPUS][ATTESTATION_APP_PAGE_COUNT][GRANULE_SIZE] __aligned(GRANULE_SIZE) = {0};
30 /* The app config data for the per-cpu instances */
31 static struct app_data_cfg rmm_attest_app_datas[MAX_CPUS] __aligned(GRANULE_SIZE) = {0};
32 static bool attest_app_init_done[MAX_CPUS];
33
global_init_attest_app(struct app_data_cfg * app_data)34 static unsigned long global_init_attest_app(struct app_data_cfg *app_data)
35 {
36 unsigned long ret;
37
38 app_map_shared_page(app_data);
39 SIMD_FPU_ALLOW(
40 ret = app_run(app_data, ATTESTATION_APP_FUNC_ID_GLOBAL_INIT, 0, 0, 0, 0));
41 assert(app_data->exit_flag != APP_EXIT_SVC_YIELD_FLAG);
42 app_unmap_shared_page(app_data);
43 return ret;
44 }
45
attest_app_init(struct app_data_cfg * app_data,uintptr_t granule_pas[],size_t granule_pa_count,void * granule_va_start)46 int attest_app_init(
47 struct app_data_cfg *app_data,
48 uintptr_t granule_pas[],
49 size_t granule_pa_count,
50 void *granule_va_start)
51 {
52 return app_init_data(app_data,
53 ATTESTATION_APP_ID,
54 granule_pas,
55 granule_pa_count,
56 granule_va_start);
57 }
58
attest_app_global_init(void)59 int attest_app_global_init(void)
60 {
61 struct app_data_cfg app_data;
62 uintptr_t granule_pas[ATTESTATION_APP_PAGE_COUNT];
63 int ret = 0;
64 unsigned long uret = 0;
65 unsigned int cpuid = my_cpuid();
66
67 /*
68 * Reuse the pages that were allocated for the per-cpu instances.
69 * This function is run before any other instance is run, so this is
70 * safe.
71 */
72 for (unsigned int i = 0 ; i < ATTESTATION_APP_PAGE_COUNT; ++i) {
73 granule_pas[i] = (uintptr_t)rmm_attest_app_pages[cpuid][i];
74 }
75
76 ret = app_init_data(&app_data,
77 ATTESTATION_APP_ID,
78 granule_pas,
79 ARRAY_SIZE(granule_pas),
80 rmm_attest_app_pages[cpuid][0]);
81 if (ret != 0) {
82 return ret;
83 }
84
85 uret = global_init_attest_app(&app_data);
86
87 /* Restore the per-cpu instance pages to the state they were */
88 (void)memset((void *)&(rmm_attest_app_pages[cpuid][0]), 0,
89 ATTESTATION_APP_PAGE_COUNT * GRANULE_SIZE);
90
91 if (uret > (unsigned long)INT_MAX) {
92 return -EINVAL;
93 } else {
94 return (int)uret;
95 }
96
97 }
98
99 /* Forward declare function to prevent static checker warning */
100 void attest_app_get_bss(uintptr_t *bss_pa, size_t *bss_size);
101
attest_app_get_bss(uintptr_t * bss_pa,size_t * bss_size)102 void attest_app_get_bss(uintptr_t *bss_pa, size_t *bss_size)
103 {
104 static char attest_app_bss[3U * GRANULE_SIZE] __aligned(GRANULE_SIZE);
105 *bss_pa = (uintptr_t)attest_app_bss;
106 *bss_size = sizeof(attest_app_bss);
107 }
108
attest_app_init_per_cpu_instance(void)109 void attest_app_init_per_cpu_instance(void)
110 {
111 unsigned int cpuid = my_cpuid();
112
113 /* Only need to be initialised during coldboot */
114 if (attest_app_init_done[cpuid]) {
115 return;
116 }
117
118 /* Initialise the attestation applications for this CPU */
119 int ret;
120 uintptr_t granule_pas[ATTESTATION_APP_PAGE_COUNT];
121
122 for (size_t i = 0; i < ATTESTATION_APP_PAGE_COUNT; ++i) {
123 granule_pas[i] = (uintptr_t)&rmm_attest_app_pages[cpuid][i][0];
124 }
125
126 ret = attest_app_init(&rmm_attest_app_datas[cpuid],
127 granule_pas,
128 ATTESTATION_APP_PAGE_COUNT,
129 &rmm_attest_app_pages[cpuid][0][0]);
130 if (ret != 0) {
131 panic();
132 }
133 attest_app_init_done[cpuid] = true;
134 }
135
attest_do_hash(unsigned int algorithm,void * data,size_t size,unsigned char * out)136 void attest_do_hash(unsigned int algorithm,
137 void *data,
138 size_t size,
139 unsigned char *out)
140 {
141 size_t hash_size;
142 struct app_data_cfg *app_data;
143
144 if (size > GRANULE_SIZE) {
145 panic();
146 }
147
148 assert(attest_app_init_done[my_cpuid()]);
149 app_data = &rmm_attest_app_datas[my_cpuid()];
150
151 app_map_shared_page(app_data);
152 assert(app_data->el2_shared_page != NULL);
153 (void)memcpy(app_data->el2_shared_page, data, size);
154
155 SIMD_FPU_ALLOW(
156 hash_size = app_run(app_data,
157 ATTESTATION_APP_FUNC_ID_DO_HASH,
158 algorithm, size, 0, 0));
159 assert(app_data->exit_flag != APP_EXIT_SVC_YIELD_FLAG);
160 (void)memcpy((void *)out, app_data->el2_shared_page, hash_size);
161 app_unmap_shared_page(app_data);
162 }
163
164
attest_do_extend(struct app_data_cfg * app_data,enum hash_algo algorithm,void * current_measurement,void * extend_measurement,size_t extend_measurement_size,unsigned char * out,size_t out_size)165 void attest_do_extend(struct app_data_cfg *app_data,
166 enum hash_algo algorithm,
167 void *current_measurement,
168 void *extend_measurement,
169 size_t extend_measurement_size,
170 unsigned char *out,
171 size_t out_size)
172 {
173 size_t hash_size;
174 struct attest_extend_measurement_buffers *shared_page;
175 struct attest_extend_measurement_return_buffer *shared_page_ret;
176
177 (void)out_size;
178
179 if (app_data == NULL) {
180 assert(attest_app_init_done[my_cpuid()]);
181 app_data = &rmm_attest_app_datas[my_cpuid()];
182 }
183
184 app_map_shared_page(app_data);
185 assert(app_data->el2_shared_page != NULL);
186 shared_page = app_data->el2_shared_page;
187 shared_page->current_measurement_buf_offset = 0;
188 shared_page->current_measurement_buf_size = MAX_MEASUREMENT_SIZE;
189 (void)memcpy((void *)&(shared_page->buf[shared_page->current_measurement_buf_offset]),
190 current_measurement,
191 shared_page->current_measurement_buf_size);
192 shared_page->extend_measurement_buf_offset = MAX_MEASUREMENT_SIZE;
193 shared_page->extend_measurement_buf_size = MAX_MEASUREMENT_SIZE;
194 (void)memcpy((void *)&(shared_page->buf[shared_page->extend_measurement_buf_offset]),
195 extend_measurement,
196 shared_page->extend_measurement_buf_size);
197
198 SIMD_FPU_ALLOW(
199 hash_size = app_run(app_data,
200 ATTESTATION_APP_FUNC_ID_EXTEND_MEASUREMENT,
201 (unsigned long)algorithm,
202 extend_measurement_size, 0, 0));
203 assert(app_data->exit_flag != APP_EXIT_SVC_YIELD_FLAG);
204 shared_page_ret = (struct attest_extend_measurement_return_buffer *)
205 app_data->el2_shared_page;
206 assert(hash_size == shared_page_ret->measurement_size);
207 assert(hash_size <= out_size);
208 (void)memcpy(out, &(shared_page_ret->measurement_buf), hash_size);
209 app_unmap_shared_page(app_data);
210 }
211
attest_realm_token_sign(struct app_data_cfg * app_data,size_t * realm_token_len)212 enum attest_token_err_t attest_realm_token_sign(
213 struct app_data_cfg *app_data,
214 size_t *realm_token_len)
215 {
216 unsigned long retval;
217
218 app_map_shared_page(app_data);
219 SIMD_FPU_ALLOW(
220 retval = app_run(app_data,
221 ATTESTATION_APP_FUNC_ID_TOKEN_SIGN,
222 0, 0, 0, 0));
223 assert(app_data->exit_flag != APP_EXIT_SVC_YIELD_FLAG);
224 assert(app_data->el2_shared_page != NULL);
225 *realm_token_len = *(size_t *)app_data->el2_shared_page;
226 app_unmap_shared_page(app_data);
227 return (enum attest_token_err_t)retval;
228 }
229
attest_cca_token_create(struct app_data_cfg * app_data,size_t * attest_token_len)230 enum attest_token_err_t attest_cca_token_create(
231 struct app_data_cfg *app_data,
232 size_t *attest_token_len)
233 {
234 /* Call the actual token creation */
235 unsigned long ret;
236
237 app_map_shared_page(app_data);
238 SIMD_FPU_ALLOW(
239 ret = app_run(app_data,
240 ATTESTATION_APP_FUNC_ID_DO_CCA_TOKEN_CREATION,
241 0, 0, 0, 0));
242
243 assert(app_data->exit_flag != APP_EXIT_SVC_YIELD_FLAG);
244 if (ret != (unsigned long)ATTEST_TOKEN_ERR_SUCCESS) {
245 app_unmap_shared_page(app_data);
246 return (enum attest_token_err_t)ret;
247 }
248
249 assert(app_data->el2_shared_page != NULL);
250 *attest_token_len = *(size_t *)app_data->el2_shared_page;
251 app_unmap_shared_page(app_data);
252 return (enum attest_token_err_t)ret;
253 }
254
attest_token_sign_ctx_init(struct app_data_cfg * app_data,uintptr_t cookie)255 enum attest_token_err_t attest_token_sign_ctx_init(struct app_data_cfg *app_data, uintptr_t cookie)
256 {
257 enum attest_token_err_t ret;
258
259 ret = (enum attest_token_err_t)app_run(app_data,
260 ATTESTATION_APP_FUNC_ID_TOKEN_CTX_INIT,
261 cookie, 0, 0, 0);
262 assert(app_data->exit_flag != APP_EXIT_SVC_YIELD_FLAG);
263 return ret;
264 }
265
attest_realm_token_create(struct app_data_cfg * app_data,enum hash_algo algorithm,unsigned char measurements[][MAX_MEASUREMENT_SIZE],const void * rpv_buf,const void * challenge_buf)266 enum attest_token_err_t attest_realm_token_create(struct app_data_cfg *app_data,
267 enum hash_algo algorithm,
268 unsigned char measurements[][MAX_MEASUREMENT_SIZE],
269 const void *rpv_buf,
270 const void *challenge_buf)
271 {
272 struct attest_realm_token_create_params *shared_page;
273 enum attest_token_err_t ret;
274
275 app_map_shared_page(app_data);
276 assert(app_data->el2_shared_page != NULL);
277 shared_page = app_data->el2_shared_page;
278 (void)memcpy(&(shared_page->measurements),
279 measurements,
280 (size_t)(MEASUREMENT_SLOT_NR * MAX_MEASUREMENT_SIZE));
281 (void)memcpy((void *)&(shared_page->rpv),
282 rpv_buf,
283 RPV_SIZE);
284 (void)memcpy((void *)&(shared_page->challenge),
285 challenge_buf,
286 ATTEST_CHALLENGE_SIZE);
287 ret = (enum attest_token_err_t)app_run(app_data,
288 ATTESTATION_APP_FUNC_ID_REALM_TOKEN_CREATE,
289 (unsigned long)algorithm, 0, 0, 0);
290 assert(app_data->exit_flag != APP_EXIT_SVC_YIELD_FLAG);
291 app_unmap_shared_page(app_data);
292 return ret;
293 }
294
295 #if ATTEST_EL3_TOKEN_SIGN
attest_app_el3_token_write_response_to_ctx(struct app_data_cfg * app_data,uint64_t req_ticket,size_t signature_buf_len,uint8_t signature_buf[])296 int attest_app_el3_token_write_response_to_ctx(struct app_data_cfg *app_data,
297 uint64_t req_ticket,
298 size_t signature_buf_len,
299 uint8_t signature_buf[])
300 {
301 unsigned long ret;
302
303 app_map_shared_page(app_data);
304 assert(signature_buf_len <= GRANULE_SIZE);
305 memcpy(app_data->el2_shared_page, signature_buf, signature_buf_len);
306 SIMD_FPU_ALLOW(
307 ret = app_run(app_data,
308 EL3_TOKEN_WRITE_RESPONSE_TO_CTX,
309 req_ticket, signature_buf_len, 0, 0));
310 assert(app_data->exit_flag != APP_EXIT_SVC_YIELD_FLAG);
311 app_unmap_shared_page(app_data);
312 return ret;
313 }
314 #endif
315