xref: /optee_os/core/pta/attestation.c (revision ac4987864470333ffb78c8abe7d81a2b4ff766e8)
17e05ec25SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
27e05ec25SJerome Forissier /*
37e05ec25SJerome Forissier  * Copyright (C) 2021, Huawei Technologies Co., Ltd
47e05ec25SJerome Forissier  */
57e05ec25SJerome Forissier 
67e05ec25SJerome Forissier #include <config.h>
77e05ec25SJerome Forissier #include <crypto/crypto.h>
87e05ec25SJerome Forissier #include <kernel/linker.h>
97e05ec25SJerome Forissier #include <kernel/pseudo_ta.h>
107e05ec25SJerome Forissier #include <kernel/ts_store.h>
11*ac498786SJerome Forissier #include <kernel/user_access.h>
127e05ec25SJerome Forissier #include <kernel/user_mode_ctx.h>
137e05ec25SJerome Forissier #include <mm/file.h>
147e05ec25SJerome Forissier #include <pta_attestation.h>
157e05ec25SJerome Forissier #include <stdlib.h>
167e05ec25SJerome Forissier #include <string.h>
177e05ec25SJerome Forissier #include <tee/entry_std.h>
187e05ec25SJerome Forissier #include <tee/tee_fs.h>
197e05ec25SJerome Forissier #include <tee/tee_pobj.h>
207e05ec25SJerome Forissier #include <tee/uuid.h>
217e05ec25SJerome Forissier #include <utee_defines.h>
227e05ec25SJerome Forissier 
237e05ec25SJerome Forissier #define PTA_NAME "attestation.pta"
247e05ec25SJerome Forissier 
257e05ec25SJerome Forissier #define MAX_KEY_SIZE 4096
267e05ec25SJerome Forissier 
277e05ec25SJerome Forissier static TEE_UUID pta_uuid = PTA_ATTESTATION_UUID;
287e05ec25SJerome Forissier 
297e05ec25SJerome Forissier static struct rsa_keypair *key;
307e05ec25SJerome Forissier 
317e05ec25SJerome Forissier static const uint8_t key_file_name[] = "key";
327e05ec25SJerome Forissier 
337e05ec25SJerome Forissier static TEE_Result allocate_key(void)
347e05ec25SJerome Forissier {
357e05ec25SJerome Forissier 	assert(!key);
367e05ec25SJerome Forissier 
377e05ec25SJerome Forissier 	key = calloc(1, sizeof(*key));
387e05ec25SJerome Forissier 	if (!key)
397e05ec25SJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
407e05ec25SJerome Forissier 
417e05ec25SJerome Forissier 	COMPILE_TIME_ASSERT(CFG_ATTESTATION_PTA_KEY_SIZE <= MAX_KEY_SIZE);
427e05ec25SJerome Forissier 	return crypto_acipher_alloc_rsa_keypair(key, MAX_KEY_SIZE);
437e05ec25SJerome Forissier }
447e05ec25SJerome Forissier 
457e05ec25SJerome Forissier static void free_key(void)
467e05ec25SJerome Forissier {
477e05ec25SJerome Forissier 	crypto_acipher_free_rsa_keypair(key);
487e05ec25SJerome Forissier 	free(key);
497e05ec25SJerome Forissier 	key = NULL;
507e05ec25SJerome Forissier }
517e05ec25SJerome Forissier 
527e05ec25SJerome Forissier static TEE_Result generate_key(void)
537e05ec25SJerome Forissier {
547e05ec25SJerome Forissier 	uint32_t e = TEE_U32_TO_BIG_ENDIAN(65537);
557e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
567e05ec25SJerome Forissier 
577e05ec25SJerome Forissier 	res = allocate_key();
587e05ec25SJerome Forissier 	if (res)
597e05ec25SJerome Forissier 		return res;
607e05ec25SJerome Forissier 
617e05ec25SJerome Forissier 	crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key->e);
627e05ec25SJerome Forissier 
637e05ec25SJerome Forissier 	/*
647e05ec25SJerome Forissier 	 * For security reasons, the RSA modulus size has to be at least the
657e05ec25SJerome Forissier 	 * size of the data to be signed.
667e05ec25SJerome Forissier 	 */
677e05ec25SJerome Forissier 	DMSG("Generating %u bit RSA key pair", CFG_ATTESTATION_PTA_KEY_SIZE);
687e05ec25SJerome Forissier 	COMPILE_TIME_ASSERT(CFG_ATTESTATION_PTA_KEY_SIZE >=
697e05ec25SJerome Forissier 			    TEE_SHA256_HASH_SIZE);
707e05ec25SJerome Forissier 	res = crypto_acipher_gen_rsa_key(key, CFG_ATTESTATION_PTA_KEY_SIZE);
717e05ec25SJerome Forissier 	if (res)
727e05ec25SJerome Forissier 		free_key();
737e05ec25SJerome Forissier 
747e05ec25SJerome Forissier 	return res;
757e05ec25SJerome Forissier }
767e05ec25SJerome Forissier 
777e05ec25SJerome Forissier /*
787e05ec25SJerome Forissier  * Return values:
797e05ec25SJerome Forissier  * > 0 : Number of bytes written to buf
807e05ec25SJerome Forissier  *   0 : @sz too large (> UINT16_MAX) or @buf_sz too small
817e05ec25SJerome Forissier  */
827e05ec25SJerome Forissier static size_t serialize_bignum(uint8_t *buf, size_t buf_sz, struct bignum *bn)
837e05ec25SJerome Forissier {
847e05ec25SJerome Forissier 	uint8_t *p = buf;
857e05ec25SJerome Forissier 	size_t sz = crypto_bignum_num_bytes(bn);
867e05ec25SJerome Forissier 	uint16_t val = TEE_U16_TO_BIG_ENDIAN(sz);
877e05ec25SJerome Forissier 	size_t total_sz = sizeof(val) + sz;
887e05ec25SJerome Forissier 
897e05ec25SJerome Forissier 	if (sz > UINT16_MAX || total_sz > buf_sz)
907e05ec25SJerome Forissier 		return 0;
917e05ec25SJerome Forissier 
927e05ec25SJerome Forissier 	memcpy(p, &val, sizeof(val));
937e05ec25SJerome Forissier 	p += sizeof(val);
947e05ec25SJerome Forissier 
957e05ec25SJerome Forissier 	crypto_bignum_bn2bin(bn, p);
967e05ec25SJerome Forissier 
977e05ec25SJerome Forissier 	return total_sz;
987e05ec25SJerome Forissier }
997e05ec25SJerome Forissier 
1007e05ec25SJerome Forissier static size_t bufsize(size_t e_sz, size_t d_sz, size_t n_sz)
1017e05ec25SJerome Forissier {
1027e05ec25SJerome Forissier 	/*
1037e05ec25SJerome Forissier 	 * Serialized key pair is 3 bignums (e, p and n) plus their sizes
1047e05ec25SJerome Forissier 	 * encoded as uint16_t.
1057e05ec25SJerome Forissier 	 */
1067e05ec25SJerome Forissier 	return e_sz + d_sz + n_sz + 3 * sizeof(uint16_t);
1077e05ec25SJerome Forissier }
1087e05ec25SJerome Forissier 
1097e05ec25SJerome Forissier static TEE_Result serialize_key(uint8_t *buf, size_t size)
1107e05ec25SJerome Forissier {
1117e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
1127e05ec25SJerome Forissier 	uint8_t *p = buf;
1137e05ec25SJerome Forissier 	size_t needed_sz = 0;
1147e05ec25SJerome Forissier 	size_t e_sz = 0;
1157e05ec25SJerome Forissier 	size_t d_sz = 0;
1167e05ec25SJerome Forissier 	size_t n_sz = 0;
1177e05ec25SJerome Forissier 	size_t sz = 0;
1187e05ec25SJerome Forissier 
1197e05ec25SJerome Forissier 	assert(key);
1207e05ec25SJerome Forissier 
1217e05ec25SJerome Forissier 	e_sz = crypto_bignum_num_bytes(key->e);
1227e05ec25SJerome Forissier 	d_sz = crypto_bignum_num_bytes(key->d);
1237e05ec25SJerome Forissier 	n_sz = crypto_bignum_num_bytes(key->n);
1247e05ec25SJerome Forissier 	if (e_sz > UINT16_MAX || d_sz > UINT16_MAX || n_sz > UINT16_MAX)
1257e05ec25SJerome Forissier 		goto err;
1267e05ec25SJerome Forissier 
1277e05ec25SJerome Forissier 	needed_sz = bufsize(e_sz, d_sz, n_sz);
1287e05ec25SJerome Forissier 	if (size < needed_sz)
1297e05ec25SJerome Forissier 		goto err;
1307e05ec25SJerome Forissier 
1317e05ec25SJerome Forissier 	sz = serialize_bignum(p, needed_sz, key->e);
1327e05ec25SJerome Forissier 	if (!sz)
1337e05ec25SJerome Forissier 		goto err;
1347e05ec25SJerome Forissier 	p += sz;
1357e05ec25SJerome Forissier 	needed_sz -= sz;
1367e05ec25SJerome Forissier 	sz = serialize_bignum(p, needed_sz, key->d);
1377e05ec25SJerome Forissier 	if (!sz)
1387e05ec25SJerome Forissier 		goto err;
1397e05ec25SJerome Forissier 	p += sz;
1407e05ec25SJerome Forissier 	needed_sz -= sz;
1417e05ec25SJerome Forissier 	sz = serialize_bignum(p, needed_sz, key->n);
1427e05ec25SJerome Forissier 	if (!sz)
1437e05ec25SJerome Forissier 		goto err;
1447e05ec25SJerome Forissier 	needed_sz -= sz;
1457e05ec25SJerome Forissier 	assert(!needed_sz);
1467e05ec25SJerome Forissier 
1477e05ec25SJerome Forissier 	return TEE_SUCCESS;
1487e05ec25SJerome Forissier err:
1497e05ec25SJerome Forissier 	return res;
1507e05ec25SJerome Forissier }
1517e05ec25SJerome Forissier 
1527e05ec25SJerome Forissier static size_t deserialize_bignum(uint8_t *buf, size_t max_sz, struct bignum *bn)
1537e05ec25SJerome Forissier {
1547e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
1557e05ec25SJerome Forissier 	uint8_t *p = buf;
1567e05ec25SJerome Forissier 	uint16_t val = 0;
1577e05ec25SJerome Forissier 	size_t sz = 0;
1587e05ec25SJerome Forissier 
1597e05ec25SJerome Forissier 	if (max_sz < sizeof(val))
1607e05ec25SJerome Forissier 		return 0;
1617e05ec25SJerome Forissier 
1627e05ec25SJerome Forissier 	memcpy(&val, p, sizeof(val));
1637e05ec25SJerome Forissier 	sz = TEE_U16_FROM_BIG_ENDIAN(val);
1647e05ec25SJerome Forissier 	p += sizeof(val);
1657e05ec25SJerome Forissier 	max_sz -= sizeof(val);
1667e05ec25SJerome Forissier 	if (max_sz < sz)
1677e05ec25SJerome Forissier 		return 0;
1687e05ec25SJerome Forissier 
1697e05ec25SJerome Forissier 	res = crypto_bignum_bin2bn(p, sz, bn);
1707e05ec25SJerome Forissier 	if (res)
1717e05ec25SJerome Forissier 		return 0;
1727e05ec25SJerome Forissier 
1737e05ec25SJerome Forissier 	return sizeof(val) + sz;
1747e05ec25SJerome Forissier }
1757e05ec25SJerome Forissier 
1767e05ec25SJerome Forissier static TEE_Result deserialize_key(uint8_t *buf, size_t buf_sz)
1777e05ec25SJerome Forissier {
1787e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
1797e05ec25SJerome Forissier 	uint8_t *p = buf;
1807e05ec25SJerome Forissier 	size_t sz = 0;
1817e05ec25SJerome Forissier 
1827e05ec25SJerome Forissier 	res = allocate_key();
1837e05ec25SJerome Forissier 	if (res)
184e2cac47bSClement Faure 		return res;
1857e05ec25SJerome Forissier 
1867e05ec25SJerome Forissier 	sz = deserialize_bignum(p, buf_sz, key->e);
1877e05ec25SJerome Forissier 	if (!sz)
188e2cac47bSClement Faure 		goto err;
1897e05ec25SJerome Forissier 	p += sz;
1907e05ec25SJerome Forissier 	buf_sz -= sz;
1917e05ec25SJerome Forissier 	sz = deserialize_bignum(p, buf_sz, key->d);
1927e05ec25SJerome Forissier 	if (!sz)
193e2cac47bSClement Faure 		goto err;
1947e05ec25SJerome Forissier 	p += sz;
1957e05ec25SJerome Forissier 	buf_sz -= sz;
1967e05ec25SJerome Forissier 	sz = deserialize_bignum(p, buf_sz, key->n);
1977e05ec25SJerome Forissier 	if (!sz)
198e2cac47bSClement Faure 		goto err;
199e2cac47bSClement Faure 
200e2cac47bSClement Faure 	return TEE_SUCCESS;
201e2cac47bSClement Faure err:
202e2cac47bSClement Faure 	free_key();
203e2cac47bSClement Faure 	return TEE_ERROR_GENERIC;
2047e05ec25SJerome Forissier }
2057e05ec25SJerome Forissier 
2067e05ec25SJerome Forissier static TEE_Result sec_storage_obj_read(TEE_UUID *uuid, uint32_t storage_id,
2077e05ec25SJerome Forissier 				       const uint8_t *obj_id,
2087e05ec25SJerome Forissier 				       size_t obj_id_len,
2097e05ec25SJerome Forissier 				       uint8_t *data, size_t *len,
2107e05ec25SJerome Forissier 				       size_t offset, uint32_t flags)
2117e05ec25SJerome Forissier {
2127e05ec25SJerome Forissier 	const struct tee_file_operations *fops = NULL;
2137e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_BAD_STATE;
2147e05ec25SJerome Forissier 	struct tee_file_handle *fh = NULL;
2157e05ec25SJerome Forissier 	struct tee_pobj *po = NULL;
2167e05ec25SJerome Forissier 	size_t file_size = 0;
2177e05ec25SJerome Forissier 	size_t read_len = 0;
2187e05ec25SJerome Forissier 
2197e05ec25SJerome Forissier 	fops = tee_svc_storage_file_ops(storage_id);
2207e05ec25SJerome Forissier 	if (!fops)
2217e05ec25SJerome Forissier 		return TEE_ERROR_NOT_IMPLEMENTED;
2227e05ec25SJerome Forissier 
2237e05ec25SJerome Forissier 	if (obj_id_len > TEE_OBJECT_ID_MAX_LEN)
2247e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
2257e05ec25SJerome Forissier 
2267e05ec25SJerome Forissier 	res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, false, fops,
2277e05ec25SJerome Forissier 			   &po);
2287e05ec25SJerome Forissier 	if (res)
2297e05ec25SJerome Forissier 		return res;
2307e05ec25SJerome Forissier 
2317e05ec25SJerome Forissier 	res = po->fops->open(po, &file_size, &fh);
2327e05ec25SJerome Forissier 	if (res)
2337e05ec25SJerome Forissier 		goto out;
2347e05ec25SJerome Forissier 
2357e05ec25SJerome Forissier 	read_len = *len;
236b2284b11SJens Wiklander 	res = po->fops->read(fh, offset, data, NULL, &read_len);
2377e05ec25SJerome Forissier 	if (res == TEE_ERROR_CORRUPT_OBJECT) {
2387e05ec25SJerome Forissier 		EMSG("Object corrupt");
2397e05ec25SJerome Forissier 		po->fops->remove(po);
2407e05ec25SJerome Forissier 	} else if (!res) {
2417e05ec25SJerome Forissier 		*len = read_len;
2427e05ec25SJerome Forissier 	}
2437e05ec25SJerome Forissier 
2447e05ec25SJerome Forissier 	po->fops->close(&fh);
2457e05ec25SJerome Forissier out:
2467e05ec25SJerome Forissier 	tee_pobj_release(po);
2477e05ec25SJerome Forissier 
2487e05ec25SJerome Forissier 	return res;
2497e05ec25SJerome Forissier }
2507e05ec25SJerome Forissier 
2517e05ec25SJerome Forissier static TEE_Result sec_storage_obj_write(TEE_UUID *uuid, uint32_t storage_id,
2527e05ec25SJerome Forissier 					const uint8_t *obj_id,
2537e05ec25SJerome Forissier 					size_t obj_id_len,
2547e05ec25SJerome Forissier 					const uint8_t *data, size_t len,
2557e05ec25SJerome Forissier 					size_t offset, uint32_t flags)
2567e05ec25SJerome Forissier 
2577e05ec25SJerome Forissier {
2587e05ec25SJerome Forissier 	const struct tee_file_operations *fops = NULL;
2597e05ec25SJerome Forissier 	struct tee_file_handle *fh = NULL;
2607e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
2617e05ec25SJerome Forissier 	struct tee_pobj *po = NULL;
2627e05ec25SJerome Forissier 
2637e05ec25SJerome Forissier 	fops = tee_svc_storage_file_ops(storage_id);
2647e05ec25SJerome Forissier 	if (!fops)
2657e05ec25SJerome Forissier 		return TEE_ERROR_NOT_IMPLEMENTED;
2667e05ec25SJerome Forissier 
2677e05ec25SJerome Forissier 	if (obj_id_len > TEE_OBJECT_ID_MAX_LEN)
2687e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
2697e05ec25SJerome Forissier 
2707e05ec25SJerome Forissier 	res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, false,
2717e05ec25SJerome Forissier 			   fops, &po);
2727e05ec25SJerome Forissier 	if (res)
2737e05ec25SJerome Forissier 		return res;
2747e05ec25SJerome Forissier 
2757e05ec25SJerome Forissier 	res = po->fops->open(po, NULL, &fh);
2767e05ec25SJerome Forissier 	if (res == TEE_ERROR_ITEM_NOT_FOUND)
277b2284b11SJens Wiklander 		res = po->fops->create(po, false, NULL, 0, NULL, 0,
278b2284b11SJens Wiklander 				       NULL, NULL, 0, &fh);
2797e05ec25SJerome Forissier 	if (!res) {
280b2284b11SJens Wiklander 		res = po->fops->write(fh, offset, data, NULL, len);
2817e05ec25SJerome Forissier 		po->fops->close(&fh);
2827e05ec25SJerome Forissier 	}
2837e05ec25SJerome Forissier 
2847e05ec25SJerome Forissier 	tee_pobj_release(po);
2857e05ec25SJerome Forissier 
2867e05ec25SJerome Forissier 	return res;
2877e05ec25SJerome Forissier }
2887e05ec25SJerome Forissier 
2897e05ec25SJerome Forissier static TEE_Result load_key(uint8_t *buf, size_t size)
2907e05ec25SJerome Forissier {
2917e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
2927e05ec25SJerome Forissier 
2937e05ec25SJerome Forissier 	DMSG("Loading RSA key pair from secure storage");
2947e05ec25SJerome Forissier 	res = sec_storage_obj_read(&pta_uuid, TEE_STORAGE_PRIVATE,
2957e05ec25SJerome Forissier 				   key_file_name, sizeof(key_file_name) - 1,
2967e05ec25SJerome Forissier 				   buf, &size, 0, TEE_DATA_FLAG_ACCESS_READ);
2977e05ec25SJerome Forissier 	if (res)
2987e05ec25SJerome Forissier 		return res;
2997e05ec25SJerome Forissier 	DMSG("Read %zu bytes", size);
3007e05ec25SJerome Forissier 	res = deserialize_key(buf, size);
3017e05ec25SJerome Forissier 	if (!res)
3027e05ec25SJerome Forissier 		DMSG("Loaded %zu bit key pair", crypto_bignum_num_bits(key->n));
3037e05ec25SJerome Forissier 
3047e05ec25SJerome Forissier 	return res;
3057e05ec25SJerome Forissier }
3067e05ec25SJerome Forissier 
3077e05ec25SJerome Forissier static TEE_Result write_key(uint8_t *buf, size_t size)
3087e05ec25SJerome Forissier {
3097e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
3107e05ec25SJerome Forissier 
3117e05ec25SJerome Forissier 	DMSG("Saving key pair");
3127e05ec25SJerome Forissier 	res = serialize_key(buf, size);
3137e05ec25SJerome Forissier 	if (res)
3147e05ec25SJerome Forissier 		return res;
3157e05ec25SJerome Forissier 
3167e05ec25SJerome Forissier 	res = sec_storage_obj_write(&pta_uuid, TEE_STORAGE_PRIVATE,
3177e05ec25SJerome Forissier 				    key_file_name, sizeof(key_file_name) - 1,
3187e05ec25SJerome Forissier 				    buf, size, 0, TEE_DATA_FLAG_ACCESS_WRITE);
3197e05ec25SJerome Forissier 	if (!res)
3207e05ec25SJerome Forissier 		DMSG("Wrote %zu bytes", size);
3217e05ec25SJerome Forissier 	return res;
3227e05ec25SJerome Forissier }
3237e05ec25SJerome Forissier 
3247e05ec25SJerome Forissier static TEE_Result init_key(void)
3257e05ec25SJerome Forissier {
3267e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
3277e05ec25SJerome Forissier 	uint8_t *buf = NULL;
3287e05ec25SJerome Forissier 	size_t size = 0;
3297e05ec25SJerome Forissier 
3307e05ec25SJerome Forissier 	if (!key) {
3317e05ec25SJerome Forissier 		/*
3327e05ec25SJerome Forissier 		 * e is 65537 so its bignum size is 3 bytes. d and n can be up
3337e05ec25SJerome Forissier 		 * to MAX_KEY_SIZE bits.
3347e05ec25SJerome Forissier 		 */
3357e05ec25SJerome Forissier 		size = bufsize(3, MAX_KEY_SIZE / 8, MAX_KEY_SIZE / 8);
3367e05ec25SJerome Forissier 		buf = calloc(1, size);
3377e05ec25SJerome Forissier 		if (!buf) {
3387e05ec25SJerome Forissier 			res = TEE_ERROR_OUT_OF_MEMORY;
3397e05ec25SJerome Forissier 			goto out;
3407e05ec25SJerome Forissier 		}
3417e05ec25SJerome Forissier 		res = load_key(buf, size);
3427e05ec25SJerome Forissier 		if (res == TEE_ERROR_ITEM_NOT_FOUND) {
3437e05ec25SJerome Forissier 			res = generate_key();
3447e05ec25SJerome Forissier 			if (res)
3457e05ec25SJerome Forissier 				goto out;
3467e05ec25SJerome Forissier 			res = write_key(buf, size);
3477e05ec25SJerome Forissier 		}
3487e05ec25SJerome Forissier 	}
3497e05ec25SJerome Forissier out:
3507e05ec25SJerome Forissier 	free(buf);
3517e05ec25SJerome Forissier 	return res;
3527e05ec25SJerome Forissier }
3537e05ec25SJerome Forissier 
3547e05ec25SJerome Forissier static TEE_Result cmd_get_pubkey(uint32_t param_types,
3557e05ec25SJerome Forissier 				 TEE_Param params[TEE_NUM_PARAMS])
3567e05ec25SJerome Forissier {
3577e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
3587e05ec25SJerome Forissier 	uint8_t *e = params[0].memref.buffer;
359eb238769SClement Faure 	size_t *e_out_sz = &params[0].memref.size;
3607e05ec25SJerome Forissier 	uint8_t *n = params[1].memref.buffer;
361eb238769SClement Faure 	size_t *n_out_sz = &params[1].memref.size;
3627e05ec25SJerome Forissier 	size_t sz = 0;
3637e05ec25SJerome Forissier 
3647e05ec25SJerome Forissier 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
3657e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_MEMREF_OUTPUT,
3667e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_VALUE_OUTPUT,
3677e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_NONE))
3687e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
3697e05ec25SJerome Forissier 
3707e05ec25SJerome Forissier 	res = init_key();
3717e05ec25SJerome Forissier 	if (res)
3727e05ec25SJerome Forissier 		return res;
3737e05ec25SJerome Forissier 
3747e05ec25SJerome Forissier 	sz = crypto_bignum_num_bytes(key->e);
3757e05ec25SJerome Forissier 	if (*e_out_sz >= sz)
3767e05ec25SJerome Forissier 		crypto_bignum_bn2bin(key->e, e);
3777e05ec25SJerome Forissier 	else
3787e05ec25SJerome Forissier 		res = TEE_ERROR_SHORT_BUFFER;
3797e05ec25SJerome Forissier 	*e_out_sz = sz;
3807e05ec25SJerome Forissier 
3817e05ec25SJerome Forissier 	sz = crypto_bignum_num_bytes(key->n);
3827e05ec25SJerome Forissier 	if (*n_out_sz >= sz)
3837e05ec25SJerome Forissier 		crypto_bignum_bn2bin(key->n, n);
3847e05ec25SJerome Forissier 	else
3857e05ec25SJerome Forissier 		res = TEE_ERROR_SHORT_BUFFER;
3867e05ec25SJerome Forissier 	*n_out_sz = sz;
3877e05ec25SJerome Forissier 
3887e05ec25SJerome Forissier 	params[2].value.a = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256;
3897e05ec25SJerome Forissier 
3907e05ec25SJerome Forissier 	return res;
3917e05ec25SJerome Forissier }
3927e05ec25SJerome Forissier 
3937e05ec25SJerome Forissier static TEE_Result hash_binary(const TEE_UUID *uuid, uint8_t *hash)
3947e05ec25SJerome Forissier {
3957e05ec25SJerome Forissier 	TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND;
3967e05ec25SJerome Forissier 	unsigned int tag_len = FILE_TAG_SIZE;
3977e05ec25SJerome Forissier 	const struct ts_store_ops *ops = NULL;
3987e05ec25SJerome Forissier 	struct ts_store_handle *h = NULL;
3997e05ec25SJerome Forissier 
4007e05ec25SJerome Forissier 	SCATTERED_ARRAY_FOREACH(ops, ta_stores, struct ts_store_ops) {
4017e05ec25SJerome Forissier 		res = ops->open(uuid, &h);
4027e05ec25SJerome Forissier 		if (!res)
4037e05ec25SJerome Forissier 			break;  /* TA found */
4047e05ec25SJerome Forissier 	}
4057e05ec25SJerome Forissier 	if (res)
4067e05ec25SJerome Forissier 		return res;
4077e05ec25SJerome Forissier 
4087e05ec25SJerome Forissier 	/*
4097e05ec25SJerome Forissier 	 * Output hash size is assumed to be the same size as the file tag
4107e05ec25SJerome Forissier 	 * size which is the size of the digest in the TA shdr. If one or the
4117e05ec25SJerome Forissier 	 * other changes, additional hashing will be needed.
4127e05ec25SJerome Forissier 	 */
4137e05ec25SJerome Forissier 	COMPILE_TIME_ASSERT(FILE_TAG_SIZE == TEE_SHA256_HASH_SIZE);
4147e05ec25SJerome Forissier 	assert(ops);
4157e05ec25SJerome Forissier 	res = ops->get_tag(h, hash, &tag_len);
4167e05ec25SJerome Forissier 	if (res)
4177e05ec25SJerome Forissier 		goto out;
4187e05ec25SJerome Forissier 
4197e05ec25SJerome Forissier 	DMSG("TA %pUl hash:", uuid);
4207e05ec25SJerome Forissier 	DHEXDUMP(hash, TEE_SHA256_HASH_SIZE);
4217e05ec25SJerome Forissier out:
4227e05ec25SJerome Forissier 	ops->close(h);
4237e05ec25SJerome Forissier 	return res;
4247e05ec25SJerome Forissier }
4257e05ec25SJerome Forissier 
4267e05ec25SJerome Forissier /* Hash @nonce and @hash into @digest */
4277e05ec25SJerome Forissier static TEE_Result digest_nonce_and_hash(uint8_t *digest, uint8_t *nonce,
4287e05ec25SJerome Forissier 					size_t nonce_sz, uint8_t *hash)
4297e05ec25SJerome Forissier {
4307e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
4317e05ec25SJerome Forissier 	void *ctx = NULL;
4327e05ec25SJerome Forissier 
4337e05ec25SJerome Forissier 	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256);
4347e05ec25SJerome Forissier 	if (res)
4357e05ec25SJerome Forissier 		return res;
4367e05ec25SJerome Forissier 	res = crypto_hash_init(ctx);
4377e05ec25SJerome Forissier 	if (res)
4387e05ec25SJerome Forissier 		goto out;
4397e05ec25SJerome Forissier 	res = crypto_hash_update(ctx, nonce, nonce_sz);
4407e05ec25SJerome Forissier 	if (res)
4417e05ec25SJerome Forissier 		goto out;
4427e05ec25SJerome Forissier 	res = crypto_hash_update(ctx, hash, TEE_SHA256_HASH_SIZE);
4437e05ec25SJerome Forissier 	if (res)
4447e05ec25SJerome Forissier 		goto out;
4457e05ec25SJerome Forissier 	res = crypto_hash_final(ctx, digest, TEE_SHA256_HASH_SIZE);
4467e05ec25SJerome Forissier out:
4477e05ec25SJerome Forissier 	crypto_hash_free_ctx(ctx);
4487e05ec25SJerome Forissier 	return res;
4497e05ec25SJerome Forissier }
4507e05ec25SJerome Forissier 
4517e05ec25SJerome Forissier static TEE_Result sign_digest(uint8_t *sig, size_t sig_len,
4527e05ec25SJerome Forissier 			      const uint8_t *digest)
4537e05ec25SJerome Forissier {
4547e05ec25SJerome Forissier 	return crypto_acipher_rsassa_sign(TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256,
4557e05ec25SJerome Forissier 					  key,
4567e05ec25SJerome Forissier 					  TEE_SHA256_HASH_SIZE, /* salt len */
4577e05ec25SJerome Forissier 					  digest, TEE_SHA256_HASH_SIZE,
4587e05ec25SJerome Forissier 					  sig, &sig_len);
4597e05ec25SJerome Forissier }
4607e05ec25SJerome Forissier 
4617e05ec25SJerome Forissier /*
4627e05ec25SJerome Forissier  * Sign the first 32 bytes contained in @buf and append signature
4637e05ec25SJerome Forissier  * out = [ hash | sig(sha256(nonce | hash)) ]
4647e05ec25SJerome Forissier  *         ^^^^   ^^^^^^^^^^^^^^^^^^^^^^^^^
4657e05ec25SJerome Forissier  *          32B                modulus size
4667e05ec25SJerome Forissier  */
4677e05ec25SJerome Forissier static TEE_Result sign_buffer(uint8_t *buf, size_t buf_sz, uint8_t *nonce,
4687e05ec25SJerome Forissier 			      size_t nonce_sz)
4697e05ec25SJerome Forissier {
4707e05ec25SJerome Forissier 	uint8_t digest[TEE_SHA256_HASH_SIZE] = { };
4717e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
4727e05ec25SJerome Forissier 
4737e05ec25SJerome Forissier 	res = digest_nonce_and_hash(digest, nonce, nonce_sz, buf);
4747e05ec25SJerome Forissier 	if (res)
4757e05ec25SJerome Forissier 		return res;
4767e05ec25SJerome Forissier 	return sign_digest(buf + TEE_SHA256_HASH_SIZE,
4777e05ec25SJerome Forissier 			   buf_sz - TEE_SHA256_HASH_SIZE, digest);
4787e05ec25SJerome Forissier }
4797e05ec25SJerome Forissier 
4807e05ec25SJerome Forissier /*
4817e05ec25SJerome Forissier  * Is region valid for hashing?
4827e05ec25SJerome Forissier  * Exclude writable regions as well as those that are not specific to the TA
4837e05ec25SJerome Forissier  * (ldelf, kernel or temporary mappings).
4847e05ec25SJerome Forissier  */
4857e05ec25SJerome Forissier static bool is_region_valid(struct vm_region *r)
4867e05ec25SJerome Forissier {
487e41da76bSJerome Forissier 	uint32_t dontwant = VM_FLAG_EPHEMERAL | VM_FLAG_PERMANENT |
4887e05ec25SJerome Forissier 			    VM_FLAG_LDELF;
489e41da76bSJerome Forissier 	uint32_t want = VM_FLAG_READONLY;
4907e05ec25SJerome Forissier 
491e41da76bSJerome Forissier 	return ((r->flags & want) == want && !(r->flags & dontwant));
4927e05ec25SJerome Forissier }
4937e05ec25SJerome Forissier 
4947e05ec25SJerome Forissier /*
4957e05ec25SJerome Forissier  * With this comparison function, we're hashing the smaller regions first.
4967e05ec25SJerome Forissier  * Regions of equal size are ordered based on their content (memcmp()).
4977e05ec25SJerome Forissier  * Identical regions can be in any order since they will yield the same hash
4987e05ec25SJerome Forissier  * anyways.
4997e05ec25SJerome Forissier  */
5007e05ec25SJerome Forissier static int cmp_regions(const void *a, const void *b)
5017e05ec25SJerome Forissier {
5027e05ec25SJerome Forissier 	const struct vm_region *r1 = *(const struct vm_region **)a;
5037e05ec25SJerome Forissier 	const struct vm_region *r2 = *(const struct vm_region **)b;
5047e05ec25SJerome Forissier 
5057e05ec25SJerome Forissier 	if (r1->size < r2->size)
5067e05ec25SJerome Forissier 		return -1;
5077e05ec25SJerome Forissier 
5087e05ec25SJerome Forissier 	if (r1->size > r2->size)
5097e05ec25SJerome Forissier 		return 1;
5107e05ec25SJerome Forissier 
5117e05ec25SJerome Forissier 	return memcmp((void *)r1->va, (void *)r2->va, r1->size);
5127e05ec25SJerome Forissier }
5137e05ec25SJerome Forissier 
5147e05ec25SJerome Forissier static TEE_Result hash_regions(struct vm_info *vm_info, uint8_t *hash)
5157e05ec25SJerome Forissier {
5167e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
5177e05ec25SJerome Forissier 	struct vm_region *r = NULL;
5187e05ec25SJerome Forissier 	struct vm_region **regions = NULL;
5197e05ec25SJerome Forissier 	size_t nregions = 0;
5207e05ec25SJerome Forissier 	void *ctx = NULL;
5217e05ec25SJerome Forissier 	size_t i = 0;
5227e05ec25SJerome Forissier 
5237e05ec25SJerome Forissier 	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256);
5247e05ec25SJerome Forissier 	if (res)
5257e05ec25SJerome Forissier 		return res;
5267e05ec25SJerome Forissier 
5277e05ec25SJerome Forissier 	res = crypto_hash_init(ctx);
5287e05ec25SJerome Forissier 	if (res)
5297e05ec25SJerome Forissier 		goto out;
5307e05ec25SJerome Forissier 
5317e05ec25SJerome Forissier 	/*
5327e05ec25SJerome Forissier 	 * Make an array of region pointers so we can use qsort() to order it.
5337e05ec25SJerome Forissier 	 */
5347e05ec25SJerome Forissier 
5357e05ec25SJerome Forissier 	TAILQ_FOREACH(r, &vm_info->regions, link)
5367e05ec25SJerome Forissier 		if (is_region_valid(r))
5377e05ec25SJerome Forissier 			nregions++;
5387e05ec25SJerome Forissier 
5397e05ec25SJerome Forissier 	regions = malloc(nregions * sizeof(*regions));
5407e05ec25SJerome Forissier 	if (!regions) {
5417e05ec25SJerome Forissier 		res = TEE_ERROR_OUT_OF_MEMORY;
5427e05ec25SJerome Forissier 		goto out;
5437e05ec25SJerome Forissier 	}
5447e05ec25SJerome Forissier 
5457e05ec25SJerome Forissier 	TAILQ_FOREACH(r, &vm_info->regions, link)
5467e05ec25SJerome Forissier 		if (is_region_valid(r))
5477e05ec25SJerome Forissier 			regions[i++] = r;
5487e05ec25SJerome Forissier 
549*ac498786SJerome Forissier 	enter_user_access();
550*ac498786SJerome Forissier 
5517e05ec25SJerome Forissier 	/*
5527e05ec25SJerome Forissier 	 * Sort regions so that they are in a consistent order even when TA ASLR
5537e05ec25SJerome Forissier 	 * is enabled.
5547e05ec25SJerome Forissier 	 */
5557e05ec25SJerome Forissier 	qsort(regions, nregions, sizeof(*regions), cmp_regions);
5567e05ec25SJerome Forissier 
5577e05ec25SJerome Forissier 	/* Hash regions in order */
5587e05ec25SJerome Forissier 	for (i = 0; i < nregions; i++) {
5597e05ec25SJerome Forissier 		r = regions[i];
5607e05ec25SJerome Forissier 		DMSG("va %p size %zu", (void *)r->va, r->size);
5617e05ec25SJerome Forissier 		res = crypto_hash_update(ctx, (uint8_t *)r->va, r->size);
5627e05ec25SJerome Forissier 		if (res)
563*ac498786SJerome Forissier 			break;
5647e05ec25SJerome Forissier 	}
5657e05ec25SJerome Forissier 
566*ac498786SJerome Forissier 	exit_user_access();
567*ac498786SJerome Forissier 
568*ac498786SJerome Forissier 	if (res)
569*ac498786SJerome Forissier 		goto out;
570*ac498786SJerome Forissier 
5717e05ec25SJerome Forissier 	res = crypto_hash_final(ctx, hash, TEE_SHA256_HASH_SIZE);
5727e05ec25SJerome Forissier out:
5737e05ec25SJerome Forissier 	free(regions);
5747e05ec25SJerome Forissier 	crypto_hash_free_ctx(ctx);
5757e05ec25SJerome Forissier 	return res;
5767e05ec25SJerome Forissier }
5777e05ec25SJerome Forissier 
5787e05ec25SJerome Forissier static TEE_Result cmd_get_ta_shdr_digest(uint32_t param_types,
5797e05ec25SJerome Forissier 					 TEE_Param params[TEE_NUM_PARAMS])
5807e05ec25SJerome Forissier {
5817e05ec25SJerome Forissier 	TEE_UUID *uuid = params[0].memref.buffer;
5827e05ec25SJerome Forissier 	size_t uuid_sz = params[0].memref.size;
5837e05ec25SJerome Forissier 	uint8_t *nonce = params[1].memref.buffer;
5847e05ec25SJerome Forissier 	size_t nonce_sz = params[1].memref.size;
5857e05ec25SJerome Forissier 	uint8_t *out = params[2].memref.buffer;
5867e05ec25SJerome Forissier 	size_t out_sz = params[2].memref.size;
5877e05ec25SJerome Forissier 	size_t min_out_sz = 0;
5887e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
5897e05ec25SJerome Forissier 
5907e05ec25SJerome Forissier 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
5917e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_MEMREF_INPUT,
5927e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_MEMREF_OUTPUT,
5937e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_NONE))
5947e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
5957e05ec25SJerome Forissier 
5967e05ec25SJerome Forissier 	if (uuid_sz != sizeof(*uuid))
5977e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
5987e05ec25SJerome Forissier 
5997e05ec25SJerome Forissier 	if (!nonce || !nonce_sz)
6007e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
6017e05ec25SJerome Forissier 
6027e05ec25SJerome Forissier 	if (!out && out_sz)
6037e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
6047e05ec25SJerome Forissier 
6057e05ec25SJerome Forissier 	res = init_key();
6067e05ec25SJerome Forissier 	if (res)
6077e05ec25SJerome Forissier 		return res;
6087e05ec25SJerome Forissier 
6097e05ec25SJerome Forissier 	min_out_sz = TEE_SHA256_HASH_SIZE + crypto_bignum_num_bytes(key->n);
6107e05ec25SJerome Forissier 	params[2].memref.size = min_out_sz;
6117e05ec25SJerome Forissier 	if (out_sz < min_out_sz)
6127e05ec25SJerome Forissier 		return TEE_ERROR_SHORT_BUFFER;
6137e05ec25SJerome Forissier 	out_sz = min_out_sz;
6147e05ec25SJerome Forissier 
6157e05ec25SJerome Forissier 	res = hash_binary(uuid, out);
6167e05ec25SJerome Forissier 	if (res)
6177e05ec25SJerome Forissier 		return res;
6187e05ec25SJerome Forissier 	return sign_buffer(out, out_sz, nonce, nonce_sz);
6197e05ec25SJerome Forissier }
6207e05ec25SJerome Forissier 
6217e05ec25SJerome Forissier static TEE_Result cmd_hash_ta_memory(uint32_t param_types,
6227e05ec25SJerome Forissier 				     TEE_Param params[TEE_NUM_PARAMS])
6237e05ec25SJerome Forissier {
6247e05ec25SJerome Forissier 	uint8_t *nonce = params[0].memref.buffer;
6257e05ec25SJerome Forissier 	size_t nonce_sz = params[0].memref.size;
6267e05ec25SJerome Forissier 	uint8_t *out = params[1].memref.buffer;
6277e05ec25SJerome Forissier 	size_t out_sz = params[1].memref.size;
6287e05ec25SJerome Forissier 	struct user_mode_ctx *uctx = NULL;
6297e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
6307e05ec25SJerome Forissier 	struct ts_session *s = NULL;
6317e05ec25SJerome Forissier 	size_t min_out_sz = 0;
6327e05ec25SJerome Forissier 
6337e05ec25SJerome Forissier 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
6347e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_MEMREF_OUTPUT,
6357e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_NONE,
6367e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_NONE))
6377e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
6387e05ec25SJerome Forissier 
6397e05ec25SJerome Forissier 	if (!nonce || !nonce_sz)
6407e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
6417e05ec25SJerome Forissier 
6427e05ec25SJerome Forissier 	if (!out && out_sz)
6437e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
6447e05ec25SJerome Forissier 
6457e05ec25SJerome Forissier 	/* Check that we're called from a user TA */
6467e05ec25SJerome Forissier 	s = ts_get_calling_session();
6477e05ec25SJerome Forissier 	if (!s)
6487e05ec25SJerome Forissier 		return TEE_ERROR_ACCESS_DENIED;
6497e05ec25SJerome Forissier 	uctx = to_user_mode_ctx(s->ctx);
6507e05ec25SJerome Forissier 	if (!uctx)
6517e05ec25SJerome Forissier 		return TEE_ERROR_ACCESS_DENIED;
6527e05ec25SJerome Forissier 
6537e05ec25SJerome Forissier 	res = init_key();
6547e05ec25SJerome Forissier 	if (res)
6557e05ec25SJerome Forissier 		return res;
6567e05ec25SJerome Forissier 
6577e05ec25SJerome Forissier 	min_out_sz = TEE_SHA256_HASH_SIZE + crypto_bignum_num_bytes(key->n);
6587e05ec25SJerome Forissier 	params[1].memref.size = min_out_sz;
6597e05ec25SJerome Forissier 	if (out_sz < min_out_sz)
6607e05ec25SJerome Forissier 		return TEE_ERROR_SHORT_BUFFER;
6617e05ec25SJerome Forissier 	out_sz = min_out_sz;
6627e05ec25SJerome Forissier 
6637e05ec25SJerome Forissier 	s = ts_pop_current_session();
6647e05ec25SJerome Forissier 	res = hash_regions(&uctx->vm_info, out);
6657e05ec25SJerome Forissier 	ts_push_current_session(s);
6667e05ec25SJerome Forissier 	if (res)
6677e05ec25SJerome Forissier 		return res;
6687e05ec25SJerome Forissier 
6697e05ec25SJerome Forissier 	return sign_buffer(out, out_sz, nonce, nonce_sz);
6707e05ec25SJerome Forissier }
6717e05ec25SJerome Forissier 
6727e05ec25SJerome Forissier static TEE_Result cmd_hash_tee_memory(uint32_t param_types,
6737e05ec25SJerome Forissier 				      TEE_Param params[TEE_NUM_PARAMS])
6747e05ec25SJerome Forissier {
6757e05ec25SJerome Forissier 	uint8_t *nonce = params[0].memref.buffer;
6767e05ec25SJerome Forissier 	size_t nonce_sz = params[0].memref.size;
6777e05ec25SJerome Forissier 	uint8_t *out = params[1].memref.buffer;
6787e05ec25SJerome Forissier 	size_t out_sz = params[1].memref.size;
6797e05ec25SJerome Forissier 	TEE_Result res = TEE_SUCCESS;
6807e05ec25SJerome Forissier 	size_t min_out_sz = 0;
6817e05ec25SJerome Forissier 	void *ctx = NULL;
6827e05ec25SJerome Forissier 
6837e05ec25SJerome Forissier 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
6847e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_MEMREF_OUTPUT,
6857e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_NONE,
6867e05ec25SJerome Forissier 					   TEE_PARAM_TYPE_NONE))
6877e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
6887e05ec25SJerome Forissier 
6897e05ec25SJerome Forissier 	if (!nonce || !nonce_sz)
6907e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
6917e05ec25SJerome Forissier 
6927e05ec25SJerome Forissier 	if (!out && out_sz)
6937e05ec25SJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
6947e05ec25SJerome Forissier 
6957e05ec25SJerome Forissier 	res = init_key();
6967e05ec25SJerome Forissier 	if (res)
6977e05ec25SJerome Forissier 		return res;
6987e05ec25SJerome Forissier 
6997e05ec25SJerome Forissier 	min_out_sz = TEE_SHA256_HASH_SIZE + crypto_bignum_num_bytes(key->n);
7007e05ec25SJerome Forissier 	params[1].memref.size = min_out_sz;
7017e05ec25SJerome Forissier 	if (out_sz < min_out_sz)
7027e05ec25SJerome Forissier 		return TEE_ERROR_SHORT_BUFFER;
7037e05ec25SJerome Forissier 	out_sz = min_out_sz;
7047e05ec25SJerome Forissier 
7057e05ec25SJerome Forissier 	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256);
7067e05ec25SJerome Forissier 	if (res)
7077e05ec25SJerome Forissier 		return res;
7087e05ec25SJerome Forissier 	res = crypto_hash_init(ctx);
7097e05ec25SJerome Forissier 	if (res)
7107e05ec25SJerome Forissier 		goto out;
7117e05ec25SJerome Forissier 	res = crypto_hash_update(ctx, __text_start,
7127e05ec25SJerome Forissier 				 __text_data_start - __text_start);
7137e05ec25SJerome Forissier 	if (res)
7147e05ec25SJerome Forissier 		goto out;
7157e05ec25SJerome Forissier 	res = crypto_hash_update(ctx, __text_data_end,
7167e05ec25SJerome Forissier 				 __text_end - __text_data_end);
7177e05ec25SJerome Forissier 	if (IS_ENABLED(CFG_WITH_PAGER)) {
7187e05ec25SJerome Forissier 		res = crypto_hash_update(ctx, __text_init_start,
7197e05ec25SJerome Forissier 					 __text_init_end - __text_init_start);
7207e05ec25SJerome Forissier 		if (res)
7217e05ec25SJerome Forissier 			goto out;
7227e05ec25SJerome Forissier 		res = crypto_hash_update(ctx, __text_pageable_start,
7237e05ec25SJerome Forissier 					 __text_pageable_end -
7247e05ec25SJerome Forissier 						__text_pageable_start);
7257e05ec25SJerome Forissier 		if (res)
7267e05ec25SJerome Forissier 			goto out;
7277e05ec25SJerome Forissier 	}
7287e05ec25SJerome Forissier 	if (res)
7297e05ec25SJerome Forissier 		goto out;
7307e05ec25SJerome Forissier 	res = crypto_hash_update(ctx, __rodata_start,
7317e05ec25SJerome Forissier 				 __rodata_end - __rodata_start);
7327e05ec25SJerome Forissier 	if (res)
7337e05ec25SJerome Forissier 		goto out;
7347e05ec25SJerome Forissier 	if (IS_ENABLED(CFG_WITH_PAGER)) {
7357e05ec25SJerome Forissier 		res = crypto_hash_update(ctx, __rodata_init_start,
7367e05ec25SJerome Forissier 					 __rodata_init_end -
7377e05ec25SJerome Forissier 						__rodata_init_start);
7387e05ec25SJerome Forissier 		if (res)
7397e05ec25SJerome Forissier 			goto out;
7407e05ec25SJerome Forissier 		res = crypto_hash_update(ctx, __rodata_pageable_start,
7417e05ec25SJerome Forissier 					 __rodata_pageable_end -
7427e05ec25SJerome Forissier 						__rodata_pageable_start);
7437e05ec25SJerome Forissier 		if (res)
7447e05ec25SJerome Forissier 			goto out;
7457e05ec25SJerome Forissier 	}
7467e05ec25SJerome Forissier 	res = crypto_hash_final(ctx, out, TEE_SHA256_HASH_SIZE);
7477e05ec25SJerome Forissier 	if (res)
7487e05ec25SJerome Forissier 		goto out;
7497e05ec25SJerome Forissier 
7507e05ec25SJerome Forissier 	DHEXDUMP(out, TEE_SHA256_HASH_SIZE);
7517e05ec25SJerome Forissier 
7527e05ec25SJerome Forissier 	res = sign_buffer(out, out_sz, nonce, nonce_sz);
7537e05ec25SJerome Forissier out:
7547e05ec25SJerome Forissier 	crypto_hash_free_ctx(ctx);
7557e05ec25SJerome Forissier 	return res;
7567e05ec25SJerome Forissier }
7577e05ec25SJerome Forissier 
7587e05ec25SJerome Forissier static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id,
7597e05ec25SJerome Forissier 				 uint32_t param_types,
7607e05ec25SJerome Forissier 				 TEE_Param params[TEE_NUM_PARAMS])
7617e05ec25SJerome Forissier {
762*ac498786SJerome Forissier 	TEE_Result res = TEE_ERROR_BAD_PARAMETERS;
763*ac498786SJerome Forissier 	TEE_Result res2 = TEE_ERROR_GENERIC;
764*ac498786SJerome Forissier 	TEE_Param bparams[TEE_NUM_PARAMS] = { };
765*ac498786SJerome Forissier 	TEE_Param *eparams = NULL;
766*ac498786SJerome Forissier 
767*ac498786SJerome Forissier 	res = to_bounce_params(param_types, params, bparams, &eparams);
768*ac498786SJerome Forissier 	if (res)
769*ac498786SJerome Forissier 		return res;
770*ac498786SJerome Forissier 
7717e05ec25SJerome Forissier 	switch (cmd_id) {
7727e05ec25SJerome Forissier 	case PTA_ATTESTATION_GET_PUBKEY:
773*ac498786SJerome Forissier 		res = cmd_get_pubkey(param_types, eparams);
774*ac498786SJerome Forissier 		break;
7757e05ec25SJerome Forissier 	case PTA_ATTESTATION_GET_TA_SHDR_DIGEST:
776*ac498786SJerome Forissier 		res = cmd_get_ta_shdr_digest(param_types, eparams);
777*ac498786SJerome Forissier 		break;
7787e05ec25SJerome Forissier 	case PTA_ATTESTATION_HASH_TA_MEMORY:
779*ac498786SJerome Forissier 		res = cmd_hash_ta_memory(param_types, eparams);
780*ac498786SJerome Forissier 		break;
7817e05ec25SJerome Forissier 	case PTA_ATTESTATION_HASH_TEE_MEMORY:
782*ac498786SJerome Forissier 		res = cmd_hash_tee_memory(param_types, eparams);
783*ac498786SJerome Forissier 		break;
7847e05ec25SJerome Forissier 	default:
7857e05ec25SJerome Forissier 		break;
7867e05ec25SJerome Forissier 	}
787*ac498786SJerome Forissier 
788*ac498786SJerome Forissier 	res2 = from_bounce_params(param_types, params, bparams, eparams);
789*ac498786SJerome Forissier 	if (!res && res2)
790*ac498786SJerome Forissier 		res = res2;
791*ac498786SJerome Forissier 
792*ac498786SJerome Forissier 	return res;
7937e05ec25SJerome Forissier }
7947e05ec25SJerome Forissier 
7957e05ec25SJerome Forissier pseudo_ta_register(.uuid = PTA_ATTESTATION_UUID, .name = PTA_NAME,
7967e05ec25SJerome Forissier 		   .flags = PTA_DEFAULT_FLAGS,
7977e05ec25SJerome Forissier 		   .invoke_command_entry_point = invoke_command);
798