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 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) 59*8e81e607SClement Faure goto err; 607e05ec25SJerome Forissier 61*8e81e607SClement Faure res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key->e); 62*8e81e607SClement Faure if (res) 63*8e81e607SClement 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); 73*8e81e607SClement Faure if (!res) 74*8e81e607SClement Faure goto out; 757e05ec25SJerome Forissier 76*8e81e607SClement Faure err: 77*8e81e607SClement Faure free_key(); 78*8e81e607SClement 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 */ 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 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 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 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 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 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 2317e05ec25SJerome Forissier res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, false, fops, 2327e05ec25SJerome Forissier &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 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 2757e05ec25SJerome Forissier res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, false, 2767e05ec25SJerome Forissier 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 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 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 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 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 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 */ 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 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 */ 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 */ 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 */ 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 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 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 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 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 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