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