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