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