xref: /optee_os/core/kernel/embedded_ts.c (revision 5418501a95d945f29bb5716fab5f3adcc2b7f3bd)
1*5418501aSMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause
2*5418501aSMarouene Boubakri /*
3*5418501aSMarouene Boubakri  * Copyright (c) 2017, Linaro Limited
4*5418501aSMarouene Boubakri  * Copyright (c) 2020, Arm Limited.
5*5418501aSMarouene Boubakri  */
6*5418501aSMarouene Boubakri #include <crypto/crypto.h>
7*5418501aSMarouene Boubakri #include <initcall.h>
8*5418501aSMarouene Boubakri #include <kernel/embedded_ts.h>
9*5418501aSMarouene Boubakri #include <kernel/ts_store.h>
10*5418501aSMarouene Boubakri #include <stdio.h>
11*5418501aSMarouene Boubakri #include <stdlib.h>
12*5418501aSMarouene Boubakri #include <string.h>
13*5418501aSMarouene Boubakri #include <trace.h>
14*5418501aSMarouene Boubakri #include <utee_defines.h>
15*5418501aSMarouene Boubakri #include <util.h>
16*5418501aSMarouene Boubakri #include <zlib.h>
17*5418501aSMarouene Boubakri 
18*5418501aSMarouene Boubakri struct ts_store_handle {
19*5418501aSMarouene Boubakri 	const struct embedded_ts *ts;
20*5418501aSMarouene Boubakri 	size_t offs;
21*5418501aSMarouene Boubakri 	z_stream strm;
22*5418501aSMarouene Boubakri };
23*5418501aSMarouene Boubakri 
24*5418501aSMarouene Boubakri static void *zalloc(void *opaque __unused, unsigned int items,
25*5418501aSMarouene Boubakri 		    unsigned int size)
26*5418501aSMarouene Boubakri {
27*5418501aSMarouene Boubakri 	return malloc(items * size);
28*5418501aSMarouene Boubakri }
29*5418501aSMarouene Boubakri 
30*5418501aSMarouene Boubakri static void zfree(void *opaque __unused, void *address)
31*5418501aSMarouene Boubakri {
32*5418501aSMarouene Boubakri 	free(address);
33*5418501aSMarouene Boubakri }
34*5418501aSMarouene Boubakri 
35*5418501aSMarouene Boubakri static bool decompression_init(z_stream *strm,
36*5418501aSMarouene Boubakri 			       const struct embedded_ts *ts)
37*5418501aSMarouene Boubakri {
38*5418501aSMarouene Boubakri 	int st = Z_OK;
39*5418501aSMarouene Boubakri 
40*5418501aSMarouene Boubakri 	strm->next_in = ts->ts;
41*5418501aSMarouene Boubakri 	strm->avail_in = ts->size;
42*5418501aSMarouene Boubakri 	strm->zalloc = zalloc;
43*5418501aSMarouene Boubakri 	strm->zfree = zfree;
44*5418501aSMarouene Boubakri 	st = inflateInit(strm);
45*5418501aSMarouene Boubakri 	if (st != Z_OK) {
46*5418501aSMarouene Boubakri 		EMSG("Decompression initialization error (%d)", st);
47*5418501aSMarouene Boubakri 		return false;
48*5418501aSMarouene Boubakri 	}
49*5418501aSMarouene Boubakri 
50*5418501aSMarouene Boubakri 	return true;
51*5418501aSMarouene Boubakri }
52*5418501aSMarouene Boubakri 
53*5418501aSMarouene Boubakri TEE_Result emb_ts_open(const TEE_UUID *uuid,
54*5418501aSMarouene Boubakri 		       struct ts_store_handle **h,
55*5418501aSMarouene Boubakri 		       const struct embedded_ts*
56*5418501aSMarouene Boubakri 		       (*find_ts) (const TEE_UUID *uuid))
57*5418501aSMarouene Boubakri {
58*5418501aSMarouene Boubakri 	struct ts_store_handle *handle = NULL;
59*5418501aSMarouene Boubakri 	const struct embedded_ts *ts = NULL;
60*5418501aSMarouene Boubakri 
61*5418501aSMarouene Boubakri 	ts = find_ts(uuid);
62*5418501aSMarouene Boubakri 	if (!ts)
63*5418501aSMarouene Boubakri 		return TEE_ERROR_ITEM_NOT_FOUND;
64*5418501aSMarouene Boubakri 
65*5418501aSMarouene Boubakri 	handle = calloc(1, sizeof(*handle));
66*5418501aSMarouene Boubakri 	if (!handle)
67*5418501aSMarouene Boubakri 		return TEE_ERROR_OUT_OF_MEMORY;
68*5418501aSMarouene Boubakri 
69*5418501aSMarouene Boubakri 	if (ts->uncompressed_size) {
70*5418501aSMarouene Boubakri 		if (!decompression_init(&handle->strm, ts)) {
71*5418501aSMarouene Boubakri 			free(handle);
72*5418501aSMarouene Boubakri 			return TEE_ERROR_BAD_FORMAT;
73*5418501aSMarouene Boubakri 		}
74*5418501aSMarouene Boubakri 	}
75*5418501aSMarouene Boubakri 	handle->ts = ts;
76*5418501aSMarouene Boubakri 	*h = handle;
77*5418501aSMarouene Boubakri 
78*5418501aSMarouene Boubakri 	return TEE_SUCCESS;
79*5418501aSMarouene Boubakri }
80*5418501aSMarouene Boubakri 
81*5418501aSMarouene Boubakri TEE_Result emb_ts_get_size(const struct ts_store_handle *h, size_t *size)
82*5418501aSMarouene Boubakri {
83*5418501aSMarouene Boubakri 	const struct embedded_ts *ts = h->ts;
84*5418501aSMarouene Boubakri 
85*5418501aSMarouene Boubakri 	if (ts->uncompressed_size)
86*5418501aSMarouene Boubakri 		*size = ts->uncompressed_size;
87*5418501aSMarouene Boubakri 	else
88*5418501aSMarouene Boubakri 		*size = ts->size;
89*5418501aSMarouene Boubakri 
90*5418501aSMarouene Boubakri 	return TEE_SUCCESS;
91*5418501aSMarouene Boubakri }
92*5418501aSMarouene Boubakri 
93*5418501aSMarouene Boubakri TEE_Result emb_ts_get_tag(const struct ts_store_handle *h,
94*5418501aSMarouene Boubakri 			  uint8_t *tag, unsigned int *tag_len)
95*5418501aSMarouene Boubakri {
96*5418501aSMarouene Boubakri 	TEE_Result res = TEE_SUCCESS;
97*5418501aSMarouene Boubakri 	void *ctx = NULL;
98*5418501aSMarouene Boubakri 
99*5418501aSMarouene Boubakri 	if (!tag || *tag_len < TEE_SHA256_HASH_SIZE) {
100*5418501aSMarouene Boubakri 		*tag_len = TEE_SHA256_HASH_SIZE;
101*5418501aSMarouene Boubakri 		return TEE_ERROR_SHORT_BUFFER;
102*5418501aSMarouene Boubakri 	}
103*5418501aSMarouene Boubakri 	*tag_len = TEE_SHA256_HASH_SIZE;
104*5418501aSMarouene Boubakri 
105*5418501aSMarouene Boubakri 	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256);
106*5418501aSMarouene Boubakri 	if (res)
107*5418501aSMarouene Boubakri 		return res;
108*5418501aSMarouene Boubakri 	res = crypto_hash_init(ctx);
109*5418501aSMarouene Boubakri 	if (res)
110*5418501aSMarouene Boubakri 		goto out;
111*5418501aSMarouene Boubakri 	res = crypto_hash_update(ctx, h->ts->ts, h->ts->size);
112*5418501aSMarouene Boubakri 	if (res)
113*5418501aSMarouene Boubakri 		goto out;
114*5418501aSMarouene Boubakri 	res = crypto_hash_final(ctx, tag, *tag_len);
115*5418501aSMarouene Boubakri out:
116*5418501aSMarouene Boubakri 	crypto_hash_free_ctx(ctx);
117*5418501aSMarouene Boubakri 	return res;
118*5418501aSMarouene Boubakri }
119*5418501aSMarouene Boubakri 
120*5418501aSMarouene Boubakri static TEE_Result read_uncompressed(struct ts_store_handle *h, void *data,
121*5418501aSMarouene Boubakri 				    size_t len)
122*5418501aSMarouene Boubakri {
123*5418501aSMarouene Boubakri 	uint8_t *src = (uint8_t *)h->ts->ts + h->offs;
124*5418501aSMarouene Boubakri 	size_t next_offs = 0;
125*5418501aSMarouene Boubakri 
126*5418501aSMarouene Boubakri 	if (ADD_OVERFLOW(h->offs, len, &next_offs) ||
127*5418501aSMarouene Boubakri 	    next_offs > h->ts->size)
128*5418501aSMarouene Boubakri 		return TEE_ERROR_BAD_PARAMETERS;
129*5418501aSMarouene Boubakri 	if (data)
130*5418501aSMarouene Boubakri 		memcpy(data, src, len);
131*5418501aSMarouene Boubakri 	h->offs = next_offs;
132*5418501aSMarouene Boubakri 
133*5418501aSMarouene Boubakri 	return TEE_SUCCESS;
134*5418501aSMarouene Boubakri }
135*5418501aSMarouene Boubakri 
136*5418501aSMarouene Boubakri static TEE_Result read_compressed(struct ts_store_handle *h, void *data,
137*5418501aSMarouene Boubakri 				  size_t len)
138*5418501aSMarouene Boubakri {
139*5418501aSMarouene Boubakri 	z_stream *strm = &h->strm;
140*5418501aSMarouene Boubakri 	size_t total = 0;
141*5418501aSMarouene Boubakri 	uint8_t *tmpbuf = NULL;
142*5418501aSMarouene Boubakri 	TEE_Result ret = TEE_SUCCESS;
143*5418501aSMarouene Boubakri 	size_t out = 0;
144*5418501aSMarouene Boubakri 	int st = Z_OK;
145*5418501aSMarouene Boubakri 
146*5418501aSMarouene Boubakri 	if (data) {
147*5418501aSMarouene Boubakri 		strm->next_out = data;
148*5418501aSMarouene Boubakri 		strm->avail_out = len;
149*5418501aSMarouene Boubakri 	} else {
150*5418501aSMarouene Boubakri 		/*
151*5418501aSMarouene Boubakri 		 * inflate() does not support a NULL strm->next_out. So, to
152*5418501aSMarouene Boubakri 		 * discard data, we have to allocate a temporary buffer. 1K
153*5418501aSMarouene Boubakri 		 * seems reasonable.
154*5418501aSMarouene Boubakri 		 */
155*5418501aSMarouene Boubakri 		strm->avail_out = MIN(len, 1024U);
156*5418501aSMarouene Boubakri 		tmpbuf = malloc(strm->avail_out);
157*5418501aSMarouene Boubakri 		if (!tmpbuf) {
158*5418501aSMarouene Boubakri 			EMSG("Out of memory");
159*5418501aSMarouene Boubakri 			return TEE_ERROR_OUT_OF_MEMORY;
160*5418501aSMarouene Boubakri 		}
161*5418501aSMarouene Boubakri 		strm->next_out = tmpbuf;
162*5418501aSMarouene Boubakri 	}
163*5418501aSMarouene Boubakri 	/*
164*5418501aSMarouene Boubakri 	 * Loop until we get as many bytes as requested, or an error occurs.
165*5418501aSMarouene Boubakri 	 * inflate() returns:
166*5418501aSMarouene Boubakri 	 * - Z_OK when progress was made, but neither the end of the input
167*5418501aSMarouene Boubakri 	 *   stream nor the end of the output buffer were met.
168*5418501aSMarouene Boubakri 	 * - Z_STREAM_END when the end of the intput stream was reached.
169*5418501aSMarouene Boubakri 	 * - Z_BUF_ERROR when there is still input to process but the output
170*5418501aSMarouene Boubakri 	 *   buffer is full (not a "hard" error, decompression can proceeed
171*5418501aSMarouene Boubakri 	 *   later).
172*5418501aSMarouene Boubakri 	 */
173*5418501aSMarouene Boubakri 	do {
174*5418501aSMarouene Boubakri 		out = strm->total_out;
175*5418501aSMarouene Boubakri 		st = inflate(strm, Z_SYNC_FLUSH);
176*5418501aSMarouene Boubakri 		out = strm->total_out - out;
177*5418501aSMarouene Boubakri 		total += out;
178*5418501aSMarouene Boubakri 		FMSG("%zu bytes", out);
179*5418501aSMarouene Boubakri 		if (!data) {
180*5418501aSMarouene Boubakri 			/*
181*5418501aSMarouene Boubakri 			 * Reset the pointer to throw away what we've just read
182*5418501aSMarouene Boubakri 			 * and read again as much as possible.
183*5418501aSMarouene Boubakri 			 */
184*5418501aSMarouene Boubakri 			strm->next_out = tmpbuf;
185*5418501aSMarouene Boubakri 			strm->avail_out = MIN(len - total, 1024U);
186*5418501aSMarouene Boubakri 		}
187*5418501aSMarouene Boubakri 	} while ((st == Z_OK || st == Z_BUF_ERROR) && (total != len));
188*5418501aSMarouene Boubakri 
189*5418501aSMarouene Boubakri 	if (st != Z_OK && st != Z_STREAM_END) {
190*5418501aSMarouene Boubakri 		EMSG("Decompression error (%d)", st);
191*5418501aSMarouene Boubakri 		ret = TEE_ERROR_GENERIC;
192*5418501aSMarouene Boubakri 		goto out;
193*5418501aSMarouene Boubakri 	}
194*5418501aSMarouene Boubakri 	ret = TEE_SUCCESS;
195*5418501aSMarouene Boubakri out:
196*5418501aSMarouene Boubakri 	free(tmpbuf);
197*5418501aSMarouene Boubakri 
198*5418501aSMarouene Boubakri 	return ret;
199*5418501aSMarouene Boubakri }
200*5418501aSMarouene Boubakri 
201*5418501aSMarouene Boubakri TEE_Result emb_ts_read(struct ts_store_handle *h, void *data, size_t len)
202*5418501aSMarouene Boubakri {
203*5418501aSMarouene Boubakri 	if (h->ts->uncompressed_size)
204*5418501aSMarouene Boubakri 		return read_compressed(h, data, len);
205*5418501aSMarouene Boubakri 	else
206*5418501aSMarouene Boubakri 		return read_uncompressed(h, data, len);
207*5418501aSMarouene Boubakri }
208*5418501aSMarouene Boubakri 
209*5418501aSMarouene Boubakri void emb_ts_close(struct ts_store_handle *h)
210*5418501aSMarouene Boubakri {
211*5418501aSMarouene Boubakri 	if (h->ts->uncompressed_size)
212*5418501aSMarouene Boubakri 		inflateEnd(&h->strm);
213*5418501aSMarouene Boubakri 	free(h);
214*5418501aSMarouene Boubakri }
215*5418501aSMarouene Boubakri 
216