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 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 31 static void zfree(void *opaque __unused, void *address) 32 { 33 mempool_free(mempool_default, address); 34 } 35 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 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 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 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 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 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 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 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