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