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