xref: /optee_os/core/pta/attestation.c (revision 7e05ec25bd68ba56ba19a450b44d6eea08b18e24)
1*7e05ec25SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2*7e05ec25SJerome Forissier /*
3*7e05ec25SJerome Forissier  * Copyright (C) 2021, Huawei Technologies Co., Ltd
4*7e05ec25SJerome Forissier  */
5*7e05ec25SJerome Forissier 
6*7e05ec25SJerome Forissier #include <config.h>
7*7e05ec25SJerome Forissier #include <crypto/crypto.h>
8*7e05ec25SJerome Forissier #include <kernel/linker.h>
9*7e05ec25SJerome Forissier #include <kernel/pseudo_ta.h>
10*7e05ec25SJerome Forissier #include <kernel/ts_store.h>
11*7e05ec25SJerome Forissier #include <kernel/user_mode_ctx.h>
12*7e05ec25SJerome Forissier #include <mm/file.h>
13*7e05ec25SJerome Forissier #include <pta_attestation.h>
14*7e05ec25SJerome Forissier #include <stdlib.h>
15*7e05ec25SJerome Forissier #include <string.h>
16*7e05ec25SJerome Forissier #include <tee/entry_std.h>
17*7e05ec25SJerome Forissier #include <tee/tee_fs.h>
18*7e05ec25SJerome Forissier #include <tee/tee_pobj.h>
19*7e05ec25SJerome Forissier #include <tee/uuid.h>
20*7e05ec25SJerome Forissier #include <utee_defines.h>
21*7e05ec25SJerome Forissier 
22*7e05ec25SJerome Forissier #define PTA_NAME "attestation.pta"
23*7e05ec25SJerome Forissier 
24*7e05ec25SJerome Forissier #define MAX_KEY_SIZE 4096
25*7e05ec25SJerome Forissier 
26*7e05ec25SJerome Forissier static TEE_UUID pta_uuid = PTA_ATTESTATION_UUID;
27*7e05ec25SJerome Forissier 
28*7e05ec25SJerome Forissier static struct rsa_keypair *key;
29*7e05ec25SJerome Forissier 
30*7e05ec25SJerome Forissier static const uint8_t key_file_name[] = "key";
31*7e05ec25SJerome Forissier 
32*7e05ec25SJerome Forissier static TEE_Result allocate_key(void)
33*7e05ec25SJerome Forissier {
34*7e05ec25SJerome Forissier 	assert(!key);
35*7e05ec25SJerome Forissier 
36*7e05ec25SJerome Forissier 	key = calloc(1, sizeof(*key));
37*7e05ec25SJerome Forissier 	if (!key)
38*7e05ec25SJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
39*7e05ec25SJerome Forissier 
40*7e05ec25SJerome Forissier 	COMPILE_TIME_ASSERT(CFG_ATTESTATION_PTA_KEY_SIZE <= MAX_KEY_SIZE);
41*7e05ec25SJerome Forissier 	return crypto_acipher_alloc_rsa_keypair(key, MAX_KEY_SIZE);
42*7e05ec25SJerome Forissier }
43*7e05ec25SJerome Forissier 
44*7e05ec25SJerome Forissier static void free_key(void)
45*7e05ec25SJerome Forissier {
46*7e05ec25SJerome Forissier 	crypto_acipher_free_rsa_keypair(key);
47*7e05ec25SJerome Forissier 	free(key);
48*7e05ec25SJerome Forissier 	key = NULL;
49*7e05ec25SJerome Forissier }
50*7e05ec25SJerome Forissier 
51*7e05ec25SJerome Forissier static TEE_Result generate_key(void)
52*7e05ec25SJerome Forissier {
53*7e05ec25SJerome Forissier 	uint32_t e = TEE_U32_TO_BIG_ENDIAN(65537);
54*7e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
55*7e05ec25SJerome Forissier 
56*7e05ec25SJerome Forissier 	res = allocate_key();
57*7e05ec25SJerome Forissier 	if (res)
58*7e05ec25SJerome Forissier 		return res;
59*7e05ec25SJerome Forissier 
60*7e05ec25SJerome Forissier 	crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key->e);
61*7e05ec25SJerome Forissier 
62*7e05ec25SJerome Forissier 	/*
63*7e05ec25SJerome Forissier 	 * For security reasons, the RSA modulus size has to be at least the
64*7e05ec25SJerome Forissier 	 * size of the data to be signed.
65*7e05ec25SJerome Forissier 	 */
66*7e05ec25SJerome Forissier 	DMSG("Generating %u bit RSA key pair", CFG_ATTESTATION_PTA_KEY_SIZE);
67*7e05ec25SJerome Forissier 	COMPILE_TIME_ASSERT(CFG_ATTESTATION_PTA_KEY_SIZE >=
68*7e05ec25SJerome Forissier 			    TEE_SHA256_HASH_SIZE);
69*7e05ec25SJerome Forissier 	res = crypto_acipher_gen_rsa_key(key, CFG_ATTESTATION_PTA_KEY_SIZE);
70*7e05ec25SJerome Forissier 	if (res)
71*7e05ec25SJerome Forissier 		free_key();
72*7e05ec25SJerome Forissier 
73*7e05ec25SJerome Forissier 	return res;
74*7e05ec25SJerome Forissier }
75*7e05ec25SJerome Forissier 
76*7e05ec25SJerome Forissier /*
77*7e05ec25SJerome Forissier  * Return values:
78*7e05ec25SJerome Forissier  * > 0 : Number of bytes written to buf
79*7e05ec25SJerome Forissier  *   0 : @sz too large (> UINT16_MAX) or @buf_sz too small
80*7e05ec25SJerome Forissier  */
81*7e05ec25SJerome Forissier static size_t serialize_bignum(uint8_t *buf, size_t buf_sz, struct bignum *bn)
82*7e05ec25SJerome Forissier {
83*7e05ec25SJerome Forissier 	uint8_t *p = buf;
84*7e05ec25SJerome Forissier 	size_t sz = crypto_bignum_num_bytes(bn);
85*7e05ec25SJerome Forissier 	uint16_t val = TEE_U16_TO_BIG_ENDIAN(sz);
86*7e05ec25SJerome Forissier 	size_t total_sz = sizeof(val) + sz;
87*7e05ec25SJerome Forissier 
88*7e05ec25SJerome Forissier 	if (sz > UINT16_MAX || total_sz > buf_sz)
89*7e05ec25SJerome Forissier 		return 0;
90*7e05ec25SJerome Forissier 
91*7e05ec25SJerome Forissier 	memcpy(p, &val, sizeof(val));
92*7e05ec25SJerome Forissier 	p += sizeof(val);
93*7e05ec25SJerome Forissier 
94*7e05ec25SJerome Forissier 	crypto_bignum_bn2bin(bn, p);
95*7e05ec25SJerome Forissier 
96*7e05ec25SJerome Forissier 	return total_sz;
97*7e05ec25SJerome Forissier }
98*7e05ec25SJerome Forissier 
99*7e05ec25SJerome Forissier static size_t bufsize(size_t e_sz, size_t d_sz, size_t n_sz)
100*7e05ec25SJerome Forissier {
101*7e05ec25SJerome Forissier 	/*
102*7e05ec25SJerome Forissier 	 * Serialized key pair is 3 bignums (e, p and n) plus their sizes
103*7e05ec25SJerome Forissier 	 * encoded as uint16_t.
104*7e05ec25SJerome Forissier 	 */
105*7e05ec25SJerome Forissier 	return e_sz + d_sz + n_sz + 3 * sizeof(uint16_t);
106*7e05ec25SJerome Forissier }
107*7e05ec25SJerome Forissier 
108*7e05ec25SJerome Forissier static TEE_Result serialize_key(uint8_t *buf, size_t size)
109*7e05ec25SJerome Forissier {
110*7e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
111*7e05ec25SJerome Forissier 	uint8_t *p = buf;
112*7e05ec25SJerome Forissier 	size_t needed_sz = 0;
113*7e05ec25SJerome Forissier 	size_t e_sz = 0;
114*7e05ec25SJerome Forissier 	size_t d_sz = 0;
115*7e05ec25SJerome Forissier 	size_t n_sz = 0;
116*7e05ec25SJerome Forissier 	size_t sz = 0;
117*7e05ec25SJerome Forissier 
118*7e05ec25SJerome Forissier 	assert(key);
119*7e05ec25SJerome Forissier 
120*7e05ec25SJerome Forissier 	e_sz = crypto_bignum_num_bytes(key->e);
121*7e05ec25SJerome Forissier 	d_sz = crypto_bignum_num_bytes(key->d);
122*7e05ec25SJerome Forissier 	n_sz = crypto_bignum_num_bytes(key->n);
123*7e05ec25SJerome Forissier 	if (e_sz > UINT16_MAX || d_sz > UINT16_MAX || n_sz > UINT16_MAX)
124*7e05ec25SJerome Forissier 		goto err;
125*7e05ec25SJerome Forissier 
126*7e05ec25SJerome Forissier 	needed_sz = bufsize(e_sz, d_sz, n_sz);
127*7e05ec25SJerome Forissier 	if (size < needed_sz)
128*7e05ec25SJerome Forissier 		goto err;
129*7e05ec25SJerome Forissier 
130*7e05ec25SJerome Forissier 	sz = serialize_bignum(p, needed_sz, key->e);
131*7e05ec25SJerome Forissier 	if (!sz)
132*7e05ec25SJerome Forissier 		goto err;
133*7e05ec25SJerome Forissier 	p += sz;
134*7e05ec25SJerome Forissier 	needed_sz -= sz;
135*7e05ec25SJerome Forissier 	sz = serialize_bignum(p, needed_sz, key->d);
136*7e05ec25SJerome Forissier 	if (!sz)
137*7e05ec25SJerome Forissier 		goto err;
138*7e05ec25SJerome Forissier 	p += sz;
139*7e05ec25SJerome Forissier 	needed_sz -= sz;
140*7e05ec25SJerome Forissier 	sz = serialize_bignum(p, needed_sz, key->n);
141*7e05ec25SJerome Forissier 	if (!sz)
142*7e05ec25SJerome Forissier 		goto err;
143*7e05ec25SJerome Forissier 	needed_sz -= sz;
144*7e05ec25SJerome Forissier 	assert(!needed_sz);
145*7e05ec25SJerome Forissier 
146*7e05ec25SJerome Forissier 	return TEE_SUCCESS;
147*7e05ec25SJerome Forissier err:
148*7e05ec25SJerome Forissier 	return res;
149*7e05ec25SJerome Forissier }
150*7e05ec25SJerome Forissier 
151*7e05ec25SJerome Forissier static size_t deserialize_bignum(uint8_t *buf, size_t max_sz, struct bignum *bn)
152*7e05ec25SJerome Forissier {
153*7e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
154*7e05ec25SJerome Forissier 	uint8_t *p = buf;
155*7e05ec25SJerome Forissier 	uint16_t val = 0;
156*7e05ec25SJerome Forissier 	size_t sz = 0;
157*7e05ec25SJerome Forissier 
158*7e05ec25SJerome Forissier 	if (max_sz < sizeof(val))
159*7e05ec25SJerome Forissier 		return 0;
160*7e05ec25SJerome Forissier 
161*7e05ec25SJerome Forissier 	memcpy(&val, p, sizeof(val));
162*7e05ec25SJerome Forissier 	sz = TEE_U16_FROM_BIG_ENDIAN(val);
163*7e05ec25SJerome Forissier 	p += sizeof(val);
164*7e05ec25SJerome Forissier 	max_sz -= sizeof(val);
165*7e05ec25SJerome Forissier 	if (max_sz < sz)
166*7e05ec25SJerome Forissier 		return 0;
167*7e05ec25SJerome Forissier 
168*7e05ec25SJerome Forissier 	res = crypto_bignum_bin2bn(p, sz, bn);
169*7e05ec25SJerome Forissier 	if (res)
170*7e05ec25SJerome Forissier 		return 0;
171*7e05ec25SJerome Forissier 
172*7e05ec25SJerome Forissier 	return sizeof(val) + sz;
173*7e05ec25SJerome Forissier }
174*7e05ec25SJerome Forissier 
175*7e05ec25SJerome Forissier static TEE_Result deserialize_key(uint8_t *buf, size_t buf_sz)
176*7e05ec25SJerome Forissier {
177*7e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
178*7e05ec25SJerome Forissier 	uint8_t *p = buf;
179*7e05ec25SJerome Forissier 	size_t sz = 0;
180*7e05ec25SJerome Forissier 
181*7e05ec25SJerome Forissier 	res = allocate_key();
182*7e05ec25SJerome Forissier 	if (res)
183*7e05ec25SJerome Forissier 		goto out;
184*7e05ec25SJerome Forissier 
185*7e05ec25SJerome Forissier 	sz = deserialize_bignum(p, buf_sz, key->e);
186*7e05ec25SJerome Forissier 	if (!sz)
187*7e05ec25SJerome Forissier 		goto out;
188*7e05ec25SJerome Forissier 	p += sz;
189*7e05ec25SJerome Forissier 	buf_sz -= sz;
190*7e05ec25SJerome Forissier 	sz = deserialize_bignum(p, buf_sz, key->d);
191*7e05ec25SJerome Forissier 	if (!sz)
192*7e05ec25SJerome Forissier 		goto out;
193*7e05ec25SJerome Forissier 	p += sz;
194*7e05ec25SJerome Forissier 	buf_sz -= sz;
195*7e05ec25SJerome Forissier 	sz = deserialize_bignum(p, buf_sz, key->n);
196*7e05ec25SJerome Forissier 	if (!sz)
197*7e05ec25SJerome Forissier 		goto out;
198*7e05ec25SJerome Forissier 	buf_sz -= sz;
199*7e05ec25SJerome Forissier 	assert(!buf_sz);
200*7e05ec25SJerome Forissier out:
201*7e05ec25SJerome Forissier 	return res;
202*7e05ec25SJerome Forissier }
203*7e05ec25SJerome Forissier 
204*7e05ec25SJerome Forissier static TEE_Result sec_storage_obj_read(TEE_UUID *uuid, uint32_t storage_id,
205*7e05ec25SJerome Forissier 				       const uint8_t *obj_id,
206*7e05ec25SJerome Forissier 				       size_t obj_id_len,
207*7e05ec25SJerome Forissier 				       uint8_t *data, size_t *len,
208*7e05ec25SJerome Forissier 				       size_t offset, uint32_t flags)
209*7e05ec25SJerome Forissier {
210*7e05ec25SJerome Forissier 	const struct tee_file_operations *fops = NULL;
211*7e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_BAD_STATE;
212*7e05ec25SJerome Forissier 	struct tee_file_handle *fh = NULL;
213*7e05ec25SJerome Forissier 	struct tee_pobj *po = NULL;
214*7e05ec25SJerome Forissier 	size_t file_size = 0;
215*7e05ec25SJerome Forissier 	size_t read_len = 0;
216*7e05ec25SJerome Forissier 
217*7e05ec25SJerome Forissier 	fops = tee_svc_storage_file_ops(storage_id);
218*7e05ec25SJerome Forissier 	if (!fops)
219*7e05ec25SJerome Forissier 		return TEE_ERROR_NOT_IMPLEMENTED;
220*7e05ec25SJerome Forissier 
221*7e05ec25SJerome Forissier 	if (obj_id_len > TEE_OBJECT_ID_MAX_LEN)
222*7e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
223*7e05ec25SJerome Forissier 
224*7e05ec25SJerome Forissier 	res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, false, fops,
225*7e05ec25SJerome Forissier 			   &po);
226*7e05ec25SJerome Forissier 	if (res)
227*7e05ec25SJerome Forissier 		return res;
228*7e05ec25SJerome Forissier 
229*7e05ec25SJerome Forissier 	res = po->fops->open(po, &file_size, &fh);
230*7e05ec25SJerome Forissier 	if (res)
231*7e05ec25SJerome Forissier 		goto out;
232*7e05ec25SJerome Forissier 
233*7e05ec25SJerome Forissier 	read_len = *len;
234*7e05ec25SJerome Forissier 	res = po->fops->read(fh, offset, data, &read_len);
235*7e05ec25SJerome Forissier 	if (res == TEE_ERROR_CORRUPT_OBJECT) {
236*7e05ec25SJerome Forissier 		EMSG("Object corrupt");
237*7e05ec25SJerome Forissier 		po->fops->remove(po);
238*7e05ec25SJerome Forissier 	} else if (!res) {
239*7e05ec25SJerome Forissier 		*len = read_len;
240*7e05ec25SJerome Forissier 	}
241*7e05ec25SJerome Forissier 
242*7e05ec25SJerome Forissier 	po->fops->close(&fh);
243*7e05ec25SJerome Forissier out:
244*7e05ec25SJerome Forissier 	tee_pobj_release(po);
245*7e05ec25SJerome Forissier 
246*7e05ec25SJerome Forissier 	return res;
247*7e05ec25SJerome Forissier }
248*7e05ec25SJerome Forissier 
249*7e05ec25SJerome Forissier static TEE_Result sec_storage_obj_write(TEE_UUID *uuid, uint32_t storage_id,
250*7e05ec25SJerome Forissier 					const uint8_t *obj_id,
251*7e05ec25SJerome Forissier 					size_t obj_id_len,
252*7e05ec25SJerome Forissier 					const uint8_t *data, size_t len,
253*7e05ec25SJerome Forissier 					size_t offset, uint32_t flags)
254*7e05ec25SJerome Forissier 
255*7e05ec25SJerome Forissier {
256*7e05ec25SJerome Forissier 	const struct tee_file_operations *fops = NULL;
257*7e05ec25SJerome Forissier 	struct tee_file_handle *fh = NULL;
258*7e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
259*7e05ec25SJerome Forissier 	struct tee_pobj *po = NULL;
260*7e05ec25SJerome Forissier 
261*7e05ec25SJerome Forissier 	fops = tee_svc_storage_file_ops(storage_id);
262*7e05ec25SJerome Forissier 	if (!fops)
263*7e05ec25SJerome Forissier 		return TEE_ERROR_NOT_IMPLEMENTED;
264*7e05ec25SJerome Forissier 
265*7e05ec25SJerome Forissier 	if (obj_id_len > TEE_OBJECT_ID_MAX_LEN)
266*7e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
267*7e05ec25SJerome Forissier 
268*7e05ec25SJerome Forissier 	res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, false,
269*7e05ec25SJerome Forissier 			   fops, &po);
270*7e05ec25SJerome Forissier 	if (res)
271*7e05ec25SJerome Forissier 		return res;
272*7e05ec25SJerome Forissier 
273*7e05ec25SJerome Forissier 	res = po->fops->open(po, NULL, &fh);
274*7e05ec25SJerome Forissier 	if (res == TEE_ERROR_ITEM_NOT_FOUND)
275*7e05ec25SJerome Forissier 		res = po->fops->create(po, false, NULL, 0, NULL, 0, NULL, 0,
276*7e05ec25SJerome Forissier 				       &fh);
277*7e05ec25SJerome Forissier 	if (!res) {
278*7e05ec25SJerome Forissier 		res = po->fops->write(fh, offset, data, len);
279*7e05ec25SJerome Forissier 		po->fops->close(&fh);
280*7e05ec25SJerome Forissier 	}
281*7e05ec25SJerome Forissier 
282*7e05ec25SJerome Forissier 	tee_pobj_release(po);
283*7e05ec25SJerome Forissier 
284*7e05ec25SJerome Forissier 	return res;
285*7e05ec25SJerome Forissier }
286*7e05ec25SJerome Forissier 
287*7e05ec25SJerome Forissier static TEE_Result load_key(uint8_t *buf, size_t size)
288*7e05ec25SJerome Forissier {
289*7e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
290*7e05ec25SJerome Forissier 
291*7e05ec25SJerome Forissier 	DMSG("Loading RSA key pair from secure storage");
292*7e05ec25SJerome Forissier 	res = sec_storage_obj_read(&pta_uuid, TEE_STORAGE_PRIVATE,
293*7e05ec25SJerome Forissier 				   key_file_name, sizeof(key_file_name) - 1,
294*7e05ec25SJerome Forissier 				   buf, &size, 0, TEE_DATA_FLAG_ACCESS_READ);
295*7e05ec25SJerome Forissier 	if (res)
296*7e05ec25SJerome Forissier 		return res;
297*7e05ec25SJerome Forissier 	DMSG("Read %zu bytes", size);
298*7e05ec25SJerome Forissier 	res = deserialize_key(buf, size);
299*7e05ec25SJerome Forissier 	if (!res)
300*7e05ec25SJerome Forissier 		DMSG("Loaded %zu bit key pair", crypto_bignum_num_bits(key->n));
301*7e05ec25SJerome Forissier 
302*7e05ec25SJerome Forissier 	return res;
303*7e05ec25SJerome Forissier }
304*7e05ec25SJerome Forissier 
305*7e05ec25SJerome Forissier static TEE_Result write_key(uint8_t *buf, size_t size)
306*7e05ec25SJerome Forissier {
307*7e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
308*7e05ec25SJerome Forissier 
309*7e05ec25SJerome Forissier 	DMSG("Saving key pair");
310*7e05ec25SJerome Forissier 	res = serialize_key(buf, size);
311*7e05ec25SJerome Forissier 	if (res)
312*7e05ec25SJerome Forissier 		return res;
313*7e05ec25SJerome Forissier 
314*7e05ec25SJerome Forissier 	res = sec_storage_obj_write(&pta_uuid, TEE_STORAGE_PRIVATE,
315*7e05ec25SJerome Forissier 				    key_file_name, sizeof(key_file_name) - 1,
316*7e05ec25SJerome Forissier 				    buf, size, 0, TEE_DATA_FLAG_ACCESS_WRITE);
317*7e05ec25SJerome Forissier 	if (!res)
318*7e05ec25SJerome Forissier 		DMSG("Wrote %zu bytes", size);
319*7e05ec25SJerome Forissier 	return res;
320*7e05ec25SJerome Forissier }
321*7e05ec25SJerome Forissier 
322*7e05ec25SJerome Forissier static TEE_Result init_key(void)
323*7e05ec25SJerome Forissier {
324*7e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
325*7e05ec25SJerome Forissier 	uint8_t *buf = NULL;
326*7e05ec25SJerome Forissier 	size_t size = 0;
327*7e05ec25SJerome Forissier 
328*7e05ec25SJerome Forissier 	if (!key) {
329*7e05ec25SJerome Forissier 		/*
330*7e05ec25SJerome Forissier 		 * e is 65537 so its bignum size is 3 bytes. d and n can be up
331*7e05ec25SJerome Forissier 		 * to MAX_KEY_SIZE bits.
332*7e05ec25SJerome Forissier 		 */
333*7e05ec25SJerome Forissier 		size = bufsize(3, MAX_KEY_SIZE / 8, MAX_KEY_SIZE / 8);
334*7e05ec25SJerome Forissier 		buf = calloc(1, size);
335*7e05ec25SJerome Forissier 		if (!buf) {
336*7e05ec25SJerome Forissier 			res = TEE_ERROR_OUT_OF_MEMORY;
337*7e05ec25SJerome Forissier 			goto out;
338*7e05ec25SJerome Forissier 		}
339*7e05ec25SJerome Forissier 		res = load_key(buf, size);
340*7e05ec25SJerome Forissier 		if (res == TEE_ERROR_ITEM_NOT_FOUND) {
341*7e05ec25SJerome Forissier 			res = generate_key();
342*7e05ec25SJerome Forissier 			if (res)
343*7e05ec25SJerome Forissier 				goto out;
344*7e05ec25SJerome Forissier 			res = write_key(buf, size);
345*7e05ec25SJerome Forissier 		}
346*7e05ec25SJerome Forissier 	}
347*7e05ec25SJerome Forissier out:
348*7e05ec25SJerome Forissier 	free(buf);
349*7e05ec25SJerome Forissier 	return res;
350*7e05ec25SJerome Forissier }
351*7e05ec25SJerome Forissier 
352*7e05ec25SJerome Forissier static TEE_Result cmd_get_pubkey(uint32_t param_types,
353*7e05ec25SJerome Forissier 				 TEE_Param params[TEE_NUM_PARAMS])
354*7e05ec25SJerome Forissier {
355*7e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
356*7e05ec25SJerome Forissier 	uint8_t *e = params[0].memref.buffer;
357*7e05ec25SJerome Forissier 	uint32_t *e_out_sz = &params[0].memref.size;
358*7e05ec25SJerome Forissier 	uint8_t *n = params[1].memref.buffer;
359*7e05ec25SJerome Forissier 	uint32_t *n_out_sz = &params[1].memref.size;
360*7e05ec25SJerome Forissier 	size_t sz = 0;
361*7e05ec25SJerome Forissier 
362*7e05ec25SJerome Forissier 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
363*7e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_MEMREF_OUTPUT,
364*7e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_VALUE_OUTPUT,
365*7e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_NONE))
366*7e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
367*7e05ec25SJerome Forissier 
368*7e05ec25SJerome Forissier 	res = init_key();
369*7e05ec25SJerome Forissier 	if (res)
370*7e05ec25SJerome Forissier 		return res;
371*7e05ec25SJerome Forissier 
372*7e05ec25SJerome Forissier 	sz = crypto_bignum_num_bytes(key->e);
373*7e05ec25SJerome Forissier 	if (*e_out_sz >= sz)
374*7e05ec25SJerome Forissier 		crypto_bignum_bn2bin(key->e, e);
375*7e05ec25SJerome Forissier 	else
376*7e05ec25SJerome Forissier 		res = TEE_ERROR_SHORT_BUFFER;
377*7e05ec25SJerome Forissier 	*e_out_sz = sz;
378*7e05ec25SJerome Forissier 
379*7e05ec25SJerome Forissier 	sz = crypto_bignum_num_bytes(key->n);
380*7e05ec25SJerome Forissier 	if (*n_out_sz >= sz)
381*7e05ec25SJerome Forissier 		crypto_bignum_bn2bin(key->n, n);
382*7e05ec25SJerome Forissier 	else
383*7e05ec25SJerome Forissier 		res = TEE_ERROR_SHORT_BUFFER;
384*7e05ec25SJerome Forissier 	*n_out_sz = sz;
385*7e05ec25SJerome Forissier 
386*7e05ec25SJerome Forissier 	params[2].value.a = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256;
387*7e05ec25SJerome Forissier 
388*7e05ec25SJerome Forissier 	return res;
389*7e05ec25SJerome Forissier }
390*7e05ec25SJerome Forissier 
391*7e05ec25SJerome Forissier static TEE_Result hash_binary(const TEE_UUID *uuid, uint8_t *hash)
392*7e05ec25SJerome Forissier {
393*7e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND;
394*7e05ec25SJerome Forissier 	unsigned int tag_len = FILE_TAG_SIZE;
395*7e05ec25SJerome Forissier 	const struct ts_store_ops *ops = NULL;
396*7e05ec25SJerome Forissier 	struct ts_store_handle *h = NULL;
397*7e05ec25SJerome Forissier 
398*7e05ec25SJerome Forissier 	SCATTERED_ARRAY_FOREACH(ops, ta_stores, struct ts_store_ops) {
399*7e05ec25SJerome Forissier 		res = ops->open(uuid, &h);
400*7e05ec25SJerome Forissier 		if (!res)
401*7e05ec25SJerome Forissier 			break;  /* TA found */
402*7e05ec25SJerome Forissier 	}
403*7e05ec25SJerome Forissier 	if (res)
404*7e05ec25SJerome Forissier 		return res;
405*7e05ec25SJerome Forissier 
406*7e05ec25SJerome Forissier 	/*
407*7e05ec25SJerome Forissier 	 * Output hash size is assumed to be the same size as the file tag
408*7e05ec25SJerome Forissier 	 * size which is the size of the digest in the TA shdr. If one or the
409*7e05ec25SJerome Forissier 	 * other changes, additional hashing will be needed.
410*7e05ec25SJerome Forissier 	 */
411*7e05ec25SJerome Forissier 	COMPILE_TIME_ASSERT(FILE_TAG_SIZE == TEE_SHA256_HASH_SIZE);
412*7e05ec25SJerome Forissier 	assert(ops);
413*7e05ec25SJerome Forissier 	res = ops->get_tag(h, hash, &tag_len);
414*7e05ec25SJerome Forissier 	if (res)
415*7e05ec25SJerome Forissier 		goto out;
416*7e05ec25SJerome Forissier 
417*7e05ec25SJerome Forissier 	DMSG("TA %pUl hash:", uuid);
418*7e05ec25SJerome Forissier 	DHEXDUMP(hash, TEE_SHA256_HASH_SIZE);
419*7e05ec25SJerome Forissier out:
420*7e05ec25SJerome Forissier 	ops->close(h);
421*7e05ec25SJerome Forissier 	return res;
422*7e05ec25SJerome Forissier }
423*7e05ec25SJerome Forissier 
424*7e05ec25SJerome Forissier /* Hash @nonce and @hash into @digest */
425*7e05ec25SJerome Forissier static TEE_Result digest_nonce_and_hash(uint8_t *digest, uint8_t *nonce,
426*7e05ec25SJerome Forissier 					size_t nonce_sz, uint8_t *hash)
427*7e05ec25SJerome Forissier {
428*7e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
429*7e05ec25SJerome Forissier 	void *ctx = NULL;
430*7e05ec25SJerome Forissier 
431*7e05ec25SJerome Forissier 	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256);
432*7e05ec25SJerome Forissier 	if (res)
433*7e05ec25SJerome Forissier 		return res;
434*7e05ec25SJerome Forissier 	res = crypto_hash_init(ctx);
435*7e05ec25SJerome Forissier 	if (res)
436*7e05ec25SJerome Forissier 		goto out;
437*7e05ec25SJerome Forissier 	res = crypto_hash_update(ctx, nonce, nonce_sz);
438*7e05ec25SJerome Forissier 	if (res)
439*7e05ec25SJerome Forissier 		goto out;
440*7e05ec25SJerome Forissier 	res = crypto_hash_update(ctx, hash, TEE_SHA256_HASH_SIZE);
441*7e05ec25SJerome Forissier 	if (res)
442*7e05ec25SJerome Forissier 		goto out;
443*7e05ec25SJerome Forissier 	res = crypto_hash_final(ctx, digest, TEE_SHA256_HASH_SIZE);
444*7e05ec25SJerome Forissier out:
445*7e05ec25SJerome Forissier 	crypto_hash_free_ctx(ctx);
446*7e05ec25SJerome Forissier 	return res;
447*7e05ec25SJerome Forissier }
448*7e05ec25SJerome Forissier 
449*7e05ec25SJerome Forissier static TEE_Result sign_digest(uint8_t *sig, size_t sig_len,
450*7e05ec25SJerome Forissier 			      const uint8_t *digest)
451*7e05ec25SJerome Forissier {
452*7e05ec25SJerome Forissier 	return crypto_acipher_rsassa_sign(TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256,
453*7e05ec25SJerome Forissier 					  key,
454*7e05ec25SJerome Forissier 					  TEE_SHA256_HASH_SIZE, /* salt len */
455*7e05ec25SJerome Forissier 					  digest, TEE_SHA256_HASH_SIZE,
456*7e05ec25SJerome Forissier 					  sig, &sig_len);
457*7e05ec25SJerome Forissier }
458*7e05ec25SJerome Forissier 
459*7e05ec25SJerome Forissier /*
460*7e05ec25SJerome Forissier  * Sign the first 32 bytes contained in @buf and append signature
461*7e05ec25SJerome Forissier  * out = [ hash | sig(sha256(nonce | hash)) ]
462*7e05ec25SJerome Forissier  *         ^^^^   ^^^^^^^^^^^^^^^^^^^^^^^^^
463*7e05ec25SJerome Forissier  *          32B                modulus size
464*7e05ec25SJerome Forissier  */
465*7e05ec25SJerome Forissier static TEE_Result sign_buffer(uint8_t *buf, size_t buf_sz, uint8_t *nonce,
466*7e05ec25SJerome Forissier 			      size_t nonce_sz)
467*7e05ec25SJerome Forissier {
468*7e05ec25SJerome Forissier 	uint8_t digest[TEE_SHA256_HASH_SIZE] = { };
469*7e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
470*7e05ec25SJerome Forissier 
471*7e05ec25SJerome Forissier 	res = digest_nonce_and_hash(digest, nonce, nonce_sz, buf);
472*7e05ec25SJerome Forissier 	if (res)
473*7e05ec25SJerome Forissier 		return res;
474*7e05ec25SJerome Forissier 	return sign_digest(buf + TEE_SHA256_HASH_SIZE,
475*7e05ec25SJerome Forissier 			   buf_sz - TEE_SHA256_HASH_SIZE, digest);
476*7e05ec25SJerome Forissier }
477*7e05ec25SJerome Forissier 
478*7e05ec25SJerome Forissier /*
479*7e05ec25SJerome Forissier  * Is region valid for hashing?
480*7e05ec25SJerome Forissier  * Exclude writable regions as well as those that are not specific to the TA
481*7e05ec25SJerome Forissier  * (ldelf, kernel or temporary mappings).
482*7e05ec25SJerome Forissier  */
483*7e05ec25SJerome Forissier static bool is_region_valid(struct vm_region *r)
484*7e05ec25SJerome Forissier {
485*7e05ec25SJerome Forissier 	uint32_t skip_flags = VM_FLAG_EPHEMERAL | VM_FLAG_PERMANENT |
486*7e05ec25SJerome Forissier 			      VM_FLAG_LDELF;
487*7e05ec25SJerome Forissier 
488*7e05ec25SJerome Forissier 	return !(r->flags & skip_flags || r->attr & TEE_MATTR_UW);
489*7e05ec25SJerome Forissier }
490*7e05ec25SJerome Forissier 
491*7e05ec25SJerome Forissier /*
492*7e05ec25SJerome Forissier  * With this comparison function, we're hashing the smaller regions first.
493*7e05ec25SJerome Forissier  * Regions of equal size are ordered based on their content (memcmp()).
494*7e05ec25SJerome Forissier  * Identical regions can be in any order since they will yield the same hash
495*7e05ec25SJerome Forissier  * anyways.
496*7e05ec25SJerome Forissier  */
497*7e05ec25SJerome Forissier static int cmp_regions(const void *a, const void *b)
498*7e05ec25SJerome Forissier {
499*7e05ec25SJerome Forissier 	const struct vm_region *r1 = *(const struct vm_region **)a;
500*7e05ec25SJerome Forissier 	const struct vm_region *r2 = *(const struct vm_region **)b;
501*7e05ec25SJerome Forissier 
502*7e05ec25SJerome Forissier 	if (r1->size < r2->size)
503*7e05ec25SJerome Forissier 		return -1;
504*7e05ec25SJerome Forissier 
505*7e05ec25SJerome Forissier 	if (r1->size > r2->size)
506*7e05ec25SJerome Forissier 		return 1;
507*7e05ec25SJerome Forissier 
508*7e05ec25SJerome Forissier 	return memcmp((void *)r1->va, (void *)r2->va, r1->size);
509*7e05ec25SJerome Forissier }
510*7e05ec25SJerome Forissier 
511*7e05ec25SJerome Forissier static TEE_Result hash_regions(struct vm_info *vm_info, uint8_t *hash)
512*7e05ec25SJerome Forissier {
513*7e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
514*7e05ec25SJerome Forissier 	struct vm_region *r = NULL;
515*7e05ec25SJerome Forissier 	struct vm_region **regions = NULL;
516*7e05ec25SJerome Forissier 	size_t nregions = 0;
517*7e05ec25SJerome Forissier 	void *ctx = NULL;
518*7e05ec25SJerome Forissier 	size_t i = 0;
519*7e05ec25SJerome Forissier 
520*7e05ec25SJerome Forissier 	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256);
521*7e05ec25SJerome Forissier 	if (res)
522*7e05ec25SJerome Forissier 		return res;
523*7e05ec25SJerome Forissier 
524*7e05ec25SJerome Forissier 	res = crypto_hash_init(ctx);
525*7e05ec25SJerome Forissier 	if (res)
526*7e05ec25SJerome Forissier 		goto out;
527*7e05ec25SJerome Forissier 
528*7e05ec25SJerome Forissier 	/*
529*7e05ec25SJerome Forissier 	 * Make an array of region pointers so we can use qsort() to order it.
530*7e05ec25SJerome Forissier 	 */
531*7e05ec25SJerome Forissier 
532*7e05ec25SJerome Forissier 	TAILQ_FOREACH(r, &vm_info->regions, link)
533*7e05ec25SJerome Forissier 		if (is_region_valid(r))
534*7e05ec25SJerome Forissier 			nregions++;
535*7e05ec25SJerome Forissier 
536*7e05ec25SJerome Forissier 	regions = malloc(nregions * sizeof(*regions));
537*7e05ec25SJerome Forissier 	if (!regions) {
538*7e05ec25SJerome Forissier 		res = TEE_ERROR_OUT_OF_MEMORY;
539*7e05ec25SJerome Forissier 		goto out;
540*7e05ec25SJerome Forissier 	}
541*7e05ec25SJerome Forissier 
542*7e05ec25SJerome Forissier 	TAILQ_FOREACH(r, &vm_info->regions, link)
543*7e05ec25SJerome Forissier 		if (is_region_valid(r))
544*7e05ec25SJerome Forissier 			regions[i++] = r;
545*7e05ec25SJerome Forissier 
546*7e05ec25SJerome Forissier 	/*
547*7e05ec25SJerome Forissier 	 * Sort regions so that they are in a consistent order even when TA ASLR
548*7e05ec25SJerome Forissier 	 * is enabled.
549*7e05ec25SJerome Forissier 	 */
550*7e05ec25SJerome Forissier 	qsort(regions, nregions, sizeof(*regions), cmp_regions);
551*7e05ec25SJerome Forissier 
552*7e05ec25SJerome Forissier 	/* Hash regions in order */
553*7e05ec25SJerome Forissier 	for (i = 0; i < nregions; i++) {
554*7e05ec25SJerome Forissier 		r = regions[i];
555*7e05ec25SJerome Forissier 		DMSG("va %p size %zu", (void *)r->va, r->size);
556*7e05ec25SJerome Forissier 		res = crypto_hash_update(ctx, (uint8_t *)r->va, r->size);
557*7e05ec25SJerome Forissier 		if (res)
558*7e05ec25SJerome Forissier 			goto out;
559*7e05ec25SJerome Forissier 	}
560*7e05ec25SJerome Forissier 
561*7e05ec25SJerome Forissier 	res = crypto_hash_final(ctx, hash, TEE_SHA256_HASH_SIZE);
562*7e05ec25SJerome Forissier out:
563*7e05ec25SJerome Forissier 	free(regions);
564*7e05ec25SJerome Forissier 	crypto_hash_free_ctx(ctx);
565*7e05ec25SJerome Forissier 	return res;
566*7e05ec25SJerome Forissier }
567*7e05ec25SJerome Forissier 
568*7e05ec25SJerome Forissier static TEE_Result cmd_get_ta_shdr_digest(uint32_t param_types,
569*7e05ec25SJerome Forissier 					 TEE_Param params[TEE_NUM_PARAMS])
570*7e05ec25SJerome Forissier {
571*7e05ec25SJerome Forissier 	TEE_UUID *uuid = params[0].memref.buffer;
572*7e05ec25SJerome Forissier 	size_t uuid_sz = params[0].memref.size;
573*7e05ec25SJerome Forissier 	uint8_t *nonce = params[1].memref.buffer;
574*7e05ec25SJerome Forissier 	size_t nonce_sz = params[1].memref.size;
575*7e05ec25SJerome Forissier 	uint8_t *out = params[2].memref.buffer;
576*7e05ec25SJerome Forissier 	size_t out_sz = params[2].memref.size;
577*7e05ec25SJerome Forissier 	size_t min_out_sz = 0;
578*7e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
579*7e05ec25SJerome Forissier 
580*7e05ec25SJerome Forissier 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
581*7e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_MEMREF_INPUT,
582*7e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_MEMREF_OUTPUT,
583*7e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_NONE))
584*7e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
585*7e05ec25SJerome Forissier 
586*7e05ec25SJerome Forissier 	if (uuid_sz != sizeof(*uuid))
587*7e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
588*7e05ec25SJerome Forissier 
589*7e05ec25SJerome Forissier 	if (!nonce || !nonce_sz)
590*7e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
591*7e05ec25SJerome Forissier 
592*7e05ec25SJerome Forissier 	if (!out && out_sz)
593*7e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
594*7e05ec25SJerome Forissier 
595*7e05ec25SJerome Forissier 	res = init_key();
596*7e05ec25SJerome Forissier 	if (res)
597*7e05ec25SJerome Forissier 		return res;
598*7e05ec25SJerome Forissier 
599*7e05ec25SJerome Forissier 	min_out_sz = TEE_SHA256_HASH_SIZE + crypto_bignum_num_bytes(key->n);
600*7e05ec25SJerome Forissier 	params[2].memref.size = min_out_sz;
601*7e05ec25SJerome Forissier 	if (out_sz < min_out_sz)
602*7e05ec25SJerome Forissier 		return TEE_ERROR_SHORT_BUFFER;
603*7e05ec25SJerome Forissier 	out_sz = min_out_sz;
604*7e05ec25SJerome Forissier 
605*7e05ec25SJerome Forissier 	res = hash_binary(uuid, out);
606*7e05ec25SJerome Forissier 	if (res)
607*7e05ec25SJerome Forissier 		return res;
608*7e05ec25SJerome Forissier 	return sign_buffer(out, out_sz, nonce, nonce_sz);
609*7e05ec25SJerome Forissier }
610*7e05ec25SJerome Forissier 
611*7e05ec25SJerome Forissier static TEE_Result cmd_hash_ta_memory(uint32_t param_types,
612*7e05ec25SJerome Forissier 				     TEE_Param params[TEE_NUM_PARAMS])
613*7e05ec25SJerome Forissier {
614*7e05ec25SJerome Forissier 	uint8_t *nonce = params[0].memref.buffer;
615*7e05ec25SJerome Forissier 	size_t nonce_sz = params[0].memref.size;
616*7e05ec25SJerome Forissier 	uint8_t *out = params[1].memref.buffer;
617*7e05ec25SJerome Forissier 	size_t out_sz = params[1].memref.size;
618*7e05ec25SJerome Forissier 	struct user_mode_ctx *uctx = NULL;
619*7e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
620*7e05ec25SJerome Forissier 	struct ts_session *s = NULL;
621*7e05ec25SJerome Forissier 	size_t min_out_sz = 0;
622*7e05ec25SJerome Forissier 
623*7e05ec25SJerome Forissier 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
624*7e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_MEMREF_OUTPUT,
625*7e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_NONE,
626*7e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_NONE))
627*7e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
628*7e05ec25SJerome Forissier 
629*7e05ec25SJerome Forissier 	if (!nonce || !nonce_sz)
630*7e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
631*7e05ec25SJerome Forissier 
632*7e05ec25SJerome Forissier 	if (!out && out_sz)
633*7e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
634*7e05ec25SJerome Forissier 
635*7e05ec25SJerome Forissier 	/* Check that we're called from a user TA */
636*7e05ec25SJerome Forissier 	s = ts_get_calling_session();
637*7e05ec25SJerome Forissier 	if (!s)
638*7e05ec25SJerome Forissier 		return TEE_ERROR_ACCESS_DENIED;
639*7e05ec25SJerome Forissier 	uctx = to_user_mode_ctx(s->ctx);
640*7e05ec25SJerome Forissier 	if (!uctx)
641*7e05ec25SJerome Forissier 		return TEE_ERROR_ACCESS_DENIED;
642*7e05ec25SJerome Forissier 
643*7e05ec25SJerome Forissier 	res = init_key();
644*7e05ec25SJerome Forissier 	if (res)
645*7e05ec25SJerome Forissier 		return res;
646*7e05ec25SJerome Forissier 
647*7e05ec25SJerome Forissier 	min_out_sz = TEE_SHA256_HASH_SIZE + crypto_bignum_num_bytes(key->n);
648*7e05ec25SJerome Forissier 	params[1].memref.size = min_out_sz;
649*7e05ec25SJerome Forissier 	if (out_sz < min_out_sz)
650*7e05ec25SJerome Forissier 		return TEE_ERROR_SHORT_BUFFER;
651*7e05ec25SJerome Forissier 	out_sz = min_out_sz;
652*7e05ec25SJerome Forissier 
653*7e05ec25SJerome Forissier 	s = ts_pop_current_session();
654*7e05ec25SJerome Forissier 	res = hash_regions(&uctx->vm_info, out);
655*7e05ec25SJerome Forissier 	ts_push_current_session(s);
656*7e05ec25SJerome Forissier 	if (res)
657*7e05ec25SJerome Forissier 		return res;
658*7e05ec25SJerome Forissier 
659*7e05ec25SJerome Forissier 	return sign_buffer(out, out_sz, nonce, nonce_sz);
660*7e05ec25SJerome Forissier }
661*7e05ec25SJerome Forissier 
662*7e05ec25SJerome Forissier static TEE_Result cmd_hash_tee_memory(uint32_t param_types,
663*7e05ec25SJerome Forissier 				      TEE_Param params[TEE_NUM_PARAMS])
664*7e05ec25SJerome Forissier {
665*7e05ec25SJerome Forissier 	uint8_t *nonce = params[0].memref.buffer;
666*7e05ec25SJerome Forissier 	size_t nonce_sz = params[0].memref.size;
667*7e05ec25SJerome Forissier 	uint8_t *out = params[1].memref.buffer;
668*7e05ec25SJerome Forissier 	size_t out_sz = params[1].memref.size;
669*7e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
670*7e05ec25SJerome Forissier 	size_t min_out_sz = 0;
671*7e05ec25SJerome Forissier 	void *ctx = NULL;
672*7e05ec25SJerome Forissier 
673*7e05ec25SJerome Forissier 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
674*7e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_MEMREF_OUTPUT,
675*7e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_NONE,
676*7e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_NONE))
677*7e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
678*7e05ec25SJerome Forissier 
679*7e05ec25SJerome Forissier 	if (!nonce || !nonce_sz)
680*7e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
681*7e05ec25SJerome Forissier 
682*7e05ec25SJerome Forissier 	if (!out && out_sz)
683*7e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
684*7e05ec25SJerome Forissier 
685*7e05ec25SJerome Forissier 	res = init_key();
686*7e05ec25SJerome Forissier 	if (res)
687*7e05ec25SJerome Forissier 		return res;
688*7e05ec25SJerome Forissier 
689*7e05ec25SJerome Forissier 	min_out_sz = TEE_SHA256_HASH_SIZE + crypto_bignum_num_bytes(key->n);
690*7e05ec25SJerome Forissier 	params[1].memref.size = min_out_sz;
691*7e05ec25SJerome Forissier 	if (out_sz < min_out_sz)
692*7e05ec25SJerome Forissier 		return TEE_ERROR_SHORT_BUFFER;
693*7e05ec25SJerome Forissier 	out_sz = min_out_sz;
694*7e05ec25SJerome Forissier 
695*7e05ec25SJerome Forissier 	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256);
696*7e05ec25SJerome Forissier 	if (res)
697*7e05ec25SJerome Forissier 		return res;
698*7e05ec25SJerome Forissier 	res = crypto_hash_init(ctx);
699*7e05ec25SJerome Forissier 	if (res)
700*7e05ec25SJerome Forissier 		goto out;
701*7e05ec25SJerome Forissier 	res = crypto_hash_update(ctx, __text_start,
702*7e05ec25SJerome Forissier 				 __text_data_start - __text_start);
703*7e05ec25SJerome Forissier 	if (res)
704*7e05ec25SJerome Forissier 		goto out;
705*7e05ec25SJerome Forissier 	res = crypto_hash_update(ctx, __text_data_end,
706*7e05ec25SJerome Forissier 				 __text_end - __text_data_end);
707*7e05ec25SJerome Forissier 	if (IS_ENABLED(CFG_WITH_PAGER)) {
708*7e05ec25SJerome Forissier 		res = crypto_hash_update(ctx, __text_init_start,
709*7e05ec25SJerome Forissier 					 __text_init_end - __text_init_start);
710*7e05ec25SJerome Forissier 		if (res)
711*7e05ec25SJerome Forissier 			goto out;
712*7e05ec25SJerome Forissier 		res = crypto_hash_update(ctx, __text_pageable_start,
713*7e05ec25SJerome Forissier 					 __text_pageable_end -
714*7e05ec25SJerome Forissier 						__text_pageable_start);
715*7e05ec25SJerome Forissier 		if (res)
716*7e05ec25SJerome Forissier 			goto out;
717*7e05ec25SJerome Forissier 	}
718*7e05ec25SJerome Forissier 	if (res)
719*7e05ec25SJerome Forissier 		goto out;
720*7e05ec25SJerome Forissier 	res = crypto_hash_update(ctx, __rodata_start,
721*7e05ec25SJerome Forissier 				 __rodata_end - __rodata_start);
722*7e05ec25SJerome Forissier 	if (res)
723*7e05ec25SJerome Forissier 		goto out;
724*7e05ec25SJerome Forissier 	if (IS_ENABLED(CFG_WITH_PAGER)) {
725*7e05ec25SJerome Forissier 		res = crypto_hash_update(ctx, __rodata_init_start,
726*7e05ec25SJerome Forissier 					 __rodata_init_end -
727*7e05ec25SJerome Forissier 						__rodata_init_start);
728*7e05ec25SJerome Forissier 		if (res)
729*7e05ec25SJerome Forissier 			goto out;
730*7e05ec25SJerome Forissier 		res = crypto_hash_update(ctx, __rodata_pageable_start,
731*7e05ec25SJerome Forissier 					 __rodata_pageable_end -
732*7e05ec25SJerome Forissier 						__rodata_pageable_start);
733*7e05ec25SJerome Forissier 		if (res)
734*7e05ec25SJerome Forissier 			goto out;
735*7e05ec25SJerome Forissier 	}
736*7e05ec25SJerome Forissier 	res = crypto_hash_final(ctx, out, TEE_SHA256_HASH_SIZE);
737*7e05ec25SJerome Forissier 	if (res)
738*7e05ec25SJerome Forissier 		goto out;
739*7e05ec25SJerome Forissier 
740*7e05ec25SJerome Forissier 	DHEXDUMP(out, TEE_SHA256_HASH_SIZE);
741*7e05ec25SJerome Forissier 
742*7e05ec25SJerome Forissier 	res = sign_buffer(out, out_sz, nonce, nonce_sz);
743*7e05ec25SJerome Forissier out:
744*7e05ec25SJerome Forissier 	crypto_hash_free_ctx(ctx);
745*7e05ec25SJerome Forissier 	return res;
746*7e05ec25SJerome Forissier }
747*7e05ec25SJerome Forissier 
748*7e05ec25SJerome Forissier static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id,
749*7e05ec25SJerome Forissier 				 uint32_t param_types,
750*7e05ec25SJerome Forissier 				 TEE_Param params[TEE_NUM_PARAMS])
751*7e05ec25SJerome Forissier {
752*7e05ec25SJerome Forissier 	switch (cmd_id) {
753*7e05ec25SJerome Forissier 	case PTA_ATTESTATION_GET_PUBKEY:
754*7e05ec25SJerome Forissier 		return cmd_get_pubkey(param_types, params);
755*7e05ec25SJerome Forissier 	case PTA_ATTESTATION_GET_TA_SHDR_DIGEST:
756*7e05ec25SJerome Forissier 		return cmd_get_ta_shdr_digest(param_types, params);
757*7e05ec25SJerome Forissier 	case PTA_ATTESTATION_HASH_TA_MEMORY:
758*7e05ec25SJerome Forissier 		return cmd_hash_ta_memory(param_types, params);
759*7e05ec25SJerome Forissier 	case PTA_ATTESTATION_HASH_TEE_MEMORY:
760*7e05ec25SJerome Forissier 		return cmd_hash_tee_memory(param_types, params);
761*7e05ec25SJerome Forissier 	default:
762*7e05ec25SJerome Forissier 		break;
763*7e05ec25SJerome Forissier 	}
764*7e05ec25SJerome Forissier 	return TEE_ERROR_BAD_PARAMETERS;
765*7e05ec25SJerome Forissier }
766*7e05ec25SJerome Forissier 
767*7e05ec25SJerome Forissier pseudo_ta_register(.uuid = PTA_ATTESTATION_UUID, .name = PTA_NAME,
768*7e05ec25SJerome Forissier 		   .flags = PTA_DEFAULT_FLAGS,
769*7e05ec25SJerome Forissier 		   .invoke_command_entry_point = invoke_command);
770