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