1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (C) 2024, Institute of Information Security (IISEC) 4 */ 5 6 #include <crypto/crypto.h> 7 #include <kernel/user_mode_ctx.h> 8 9 #include "hash.h" 10 11 /* 12 * Is region valid for hashing? 13 * Exclude writable regions as well as those that are not specific to the TA 14 * (ldelf, kernel or temporary mappings). 15 */ 16 static bool is_region_valid(struct vm_region *r) 17 { 18 uint32_t dontwant = VM_FLAG_EPHEMERAL | VM_FLAG_PERMANENT | 19 VM_FLAG_LDELF; 20 uint32_t want = VM_FLAG_READONLY; 21 22 return ((r->flags & want) == want && !(r->flags & dontwant)); 23 } 24 25 /* 26 * With this comparison function, we're hashing the smaller regions first. 27 * Regions of equal size are ordered based on their content (memcmp()). 28 * Identical regions can be in any order since they will yield the same hash 29 * anyways. 30 */ 31 static int cmp_regions(const void *a, const void *b) 32 { 33 const struct vm_region *r1 = *(const struct vm_region **)a; 34 const struct vm_region *r2 = *(const struct vm_region **)b; 35 36 if (r1->size < r2->size) 37 return -1; 38 39 if (r1->size > r2->size) 40 return 1; 41 42 return memcmp((void *)r1->va, (void *)r2->va, r1->size); 43 } 44 45 static TEE_Result hash_regions(struct vm_info *vm_info, 46 uint8_t hash[TEE_SHA256_HASH_SIZE]) 47 { 48 TEE_Result res = TEE_SUCCESS; 49 struct vm_region *r = NULL; 50 struct vm_region **regions = NULL; 51 size_t nregions = 0; 52 void *ctx = NULL; 53 size_t i = 0; 54 55 res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256); 56 if (res) 57 return res; 58 59 res = crypto_hash_init(ctx); 60 if (res) 61 goto out; 62 63 /* 64 * Make an array of region pointers so we can use qsort() to order it. 65 */ 66 67 TAILQ_FOREACH(r, &vm_info->regions, link) 68 if (is_region_valid(r)) 69 nregions++; 70 71 regions = calloc(nregions, sizeof(*regions)); 72 if (!regions) { 73 res = TEE_ERROR_OUT_OF_MEMORY; 74 goto out; 75 } 76 77 TAILQ_FOREACH(r, &vm_info->regions, link) 78 if (is_region_valid(r)) 79 regions[i++] = r; 80 81 /* 82 * Sort regions so that they are in a consistent order even when TA ASLR 83 * is enabled. 84 */ 85 qsort(regions, nregions, sizeof(*regions), cmp_regions); 86 87 /* Hash regions in order */ 88 for (i = 0; i < nregions; i++) { 89 r = regions[i]; 90 DMSG("va %p size %zu", (void *)r->va, r->size); 91 res = crypto_hash_update(ctx, (uint8_t *)r->va, r->size); 92 if (res) 93 goto out; 94 } 95 96 res = crypto_hash_final(ctx, hash, TEE_SHA256_HASH_SIZE); 97 out: 98 free(regions); 99 crypto_hash_free_ctx(ctx); 100 return res; 101 } 102 103 TEE_Result get_hash_ta_memory(uint8_t out[TEE_SHA256_HASH_SIZE]) 104 { 105 struct user_mode_ctx *uctx = NULL; 106 TEE_Result res = TEE_SUCCESS; 107 struct ts_session *s = NULL; 108 109 /* Check that we're called from a user TA */ 110 s = ts_get_calling_session(); 111 if (!s) 112 return TEE_ERROR_ACCESS_DENIED; 113 uctx = to_user_mode_ctx(s->ctx); 114 if (!uctx) 115 return TEE_ERROR_ACCESS_DENIED; 116 117 s = ts_pop_current_session(); 118 res = hash_regions(&uctx->vm_info, out); 119 ts_push_current_session(s); 120 return res; 121 } 122