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