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