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