15418501aSMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause 25418501aSMarouene Boubakri /* 35418501aSMarouene Boubakri * Copyright (c) 2017, Linaro Limited 45418501aSMarouene Boubakri * Copyright (c) 2020, Arm Limited. 55418501aSMarouene Boubakri */ 65418501aSMarouene Boubakri #include <crypto/crypto.h> 75418501aSMarouene Boubakri #include <initcall.h> 85418501aSMarouene Boubakri #include <kernel/embedded_ts.h> 95418501aSMarouene Boubakri #include <kernel/ts_store.h> 10*c123d804SJens Wiklander #include <mempool.h> 115418501aSMarouene Boubakri #include <stdio.h> 125418501aSMarouene Boubakri #include <stdlib.h> 135418501aSMarouene Boubakri #include <string.h> 145418501aSMarouene Boubakri #include <trace.h> 155418501aSMarouene Boubakri #include <utee_defines.h> 165418501aSMarouene Boubakri #include <util.h> 175418501aSMarouene Boubakri #include <zlib.h> 185418501aSMarouene Boubakri 195418501aSMarouene Boubakri struct ts_store_handle { 205418501aSMarouene Boubakri const struct embedded_ts *ts; 215418501aSMarouene Boubakri size_t offs; 225418501aSMarouene Boubakri z_stream strm; 235418501aSMarouene Boubakri }; 245418501aSMarouene Boubakri 255418501aSMarouene Boubakri static void *zalloc(void *opaque __unused, unsigned int items, 265418501aSMarouene Boubakri unsigned int size) 275418501aSMarouene Boubakri { 28*c123d804SJens Wiklander return mempool_alloc(mempool_default, items * size); 295418501aSMarouene Boubakri } 305418501aSMarouene Boubakri 315418501aSMarouene Boubakri static void zfree(void *opaque __unused, void *address) 325418501aSMarouene Boubakri { 33*c123d804SJens Wiklander mempool_free(mempool_default, address); 345418501aSMarouene Boubakri } 355418501aSMarouene Boubakri 365418501aSMarouene Boubakri static bool decompression_init(z_stream *strm, 375418501aSMarouene Boubakri const struct embedded_ts *ts) 385418501aSMarouene Boubakri { 395418501aSMarouene Boubakri int st = Z_OK; 405418501aSMarouene Boubakri 415418501aSMarouene Boubakri strm->next_in = ts->ts; 425418501aSMarouene Boubakri strm->avail_in = ts->size; 435418501aSMarouene Boubakri strm->zalloc = zalloc; 445418501aSMarouene Boubakri strm->zfree = zfree; 455418501aSMarouene Boubakri st = inflateInit(strm); 465418501aSMarouene Boubakri if (st != Z_OK) { 475418501aSMarouene Boubakri EMSG("Decompression initialization error (%d)", st); 485418501aSMarouene Boubakri return false; 495418501aSMarouene Boubakri } 505418501aSMarouene Boubakri 515418501aSMarouene Boubakri return true; 525418501aSMarouene Boubakri } 535418501aSMarouene Boubakri 545418501aSMarouene Boubakri TEE_Result emb_ts_open(const TEE_UUID *uuid, 555418501aSMarouene Boubakri struct ts_store_handle **h, 565418501aSMarouene Boubakri const struct embedded_ts* 575418501aSMarouene Boubakri (*find_ts) (const TEE_UUID *uuid)) 585418501aSMarouene Boubakri { 595418501aSMarouene Boubakri struct ts_store_handle *handle = NULL; 605418501aSMarouene Boubakri const struct embedded_ts *ts = NULL; 615418501aSMarouene Boubakri 625418501aSMarouene Boubakri ts = find_ts(uuid); 635418501aSMarouene Boubakri if (!ts) 645418501aSMarouene Boubakri return TEE_ERROR_ITEM_NOT_FOUND; 655418501aSMarouene Boubakri 665418501aSMarouene Boubakri handle = calloc(1, sizeof(*handle)); 675418501aSMarouene Boubakri if (!handle) 685418501aSMarouene Boubakri return TEE_ERROR_OUT_OF_MEMORY; 695418501aSMarouene Boubakri 705418501aSMarouene Boubakri if (ts->uncompressed_size) { 715418501aSMarouene Boubakri if (!decompression_init(&handle->strm, ts)) { 725418501aSMarouene Boubakri free(handle); 735418501aSMarouene Boubakri return TEE_ERROR_BAD_FORMAT; 745418501aSMarouene Boubakri } 755418501aSMarouene Boubakri } 765418501aSMarouene Boubakri handle->ts = ts; 775418501aSMarouene Boubakri *h = handle; 785418501aSMarouene Boubakri 795418501aSMarouene Boubakri return TEE_SUCCESS; 805418501aSMarouene Boubakri } 815418501aSMarouene Boubakri 825418501aSMarouene Boubakri TEE_Result emb_ts_get_size(const struct ts_store_handle *h, size_t *size) 835418501aSMarouene Boubakri { 845418501aSMarouene Boubakri const struct embedded_ts *ts = h->ts; 855418501aSMarouene Boubakri 865418501aSMarouene Boubakri if (ts->uncompressed_size) 875418501aSMarouene Boubakri *size = ts->uncompressed_size; 885418501aSMarouene Boubakri else 895418501aSMarouene Boubakri *size = ts->size; 905418501aSMarouene Boubakri 915418501aSMarouene Boubakri return TEE_SUCCESS; 925418501aSMarouene Boubakri } 935418501aSMarouene Boubakri 945418501aSMarouene Boubakri TEE_Result emb_ts_get_tag(const struct ts_store_handle *h, 955418501aSMarouene Boubakri uint8_t *tag, unsigned int *tag_len) 965418501aSMarouene Boubakri { 975418501aSMarouene Boubakri TEE_Result res = TEE_SUCCESS; 985418501aSMarouene Boubakri void *ctx = NULL; 995418501aSMarouene Boubakri 1005418501aSMarouene Boubakri if (!tag || *tag_len < TEE_SHA256_HASH_SIZE) { 1015418501aSMarouene Boubakri *tag_len = TEE_SHA256_HASH_SIZE; 1025418501aSMarouene Boubakri return TEE_ERROR_SHORT_BUFFER; 1035418501aSMarouene Boubakri } 1045418501aSMarouene Boubakri *tag_len = TEE_SHA256_HASH_SIZE; 1055418501aSMarouene Boubakri 1065418501aSMarouene Boubakri res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256); 1075418501aSMarouene Boubakri if (res) 1085418501aSMarouene Boubakri return res; 1095418501aSMarouene Boubakri res = crypto_hash_init(ctx); 1105418501aSMarouene Boubakri if (res) 1115418501aSMarouene Boubakri goto out; 1125418501aSMarouene Boubakri res = crypto_hash_update(ctx, h->ts->ts, h->ts->size); 1135418501aSMarouene Boubakri if (res) 1145418501aSMarouene Boubakri goto out; 1155418501aSMarouene Boubakri res = crypto_hash_final(ctx, tag, *tag_len); 1165418501aSMarouene Boubakri out: 1175418501aSMarouene Boubakri crypto_hash_free_ctx(ctx); 1185418501aSMarouene Boubakri return res; 1195418501aSMarouene Boubakri } 1205418501aSMarouene Boubakri 1215418501aSMarouene Boubakri static TEE_Result read_uncompressed(struct ts_store_handle *h, void *data, 1225418501aSMarouene Boubakri size_t len) 1235418501aSMarouene Boubakri { 1245418501aSMarouene Boubakri uint8_t *src = (uint8_t *)h->ts->ts + h->offs; 1255418501aSMarouene Boubakri size_t next_offs = 0; 1265418501aSMarouene Boubakri 1275418501aSMarouene Boubakri if (ADD_OVERFLOW(h->offs, len, &next_offs) || 1285418501aSMarouene Boubakri next_offs > h->ts->size) 1295418501aSMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS; 1305418501aSMarouene Boubakri if (data) 1315418501aSMarouene Boubakri memcpy(data, src, len); 1325418501aSMarouene Boubakri h->offs = next_offs; 1335418501aSMarouene Boubakri 1345418501aSMarouene Boubakri return TEE_SUCCESS; 1355418501aSMarouene Boubakri } 1365418501aSMarouene Boubakri 1375418501aSMarouene Boubakri static TEE_Result read_compressed(struct ts_store_handle *h, void *data, 1385418501aSMarouene Boubakri size_t len) 1395418501aSMarouene Boubakri { 1405418501aSMarouene Boubakri z_stream *strm = &h->strm; 1415418501aSMarouene Boubakri size_t total = 0; 1425418501aSMarouene Boubakri uint8_t *tmpbuf = NULL; 1435418501aSMarouene Boubakri TEE_Result ret = TEE_SUCCESS; 1445418501aSMarouene Boubakri size_t out = 0; 1455418501aSMarouene Boubakri int st = Z_OK; 1465418501aSMarouene Boubakri 1475418501aSMarouene Boubakri if (data) { 1485418501aSMarouene Boubakri strm->next_out = data; 1495418501aSMarouene Boubakri strm->avail_out = len; 1505418501aSMarouene Boubakri } else { 1515418501aSMarouene Boubakri /* 1525418501aSMarouene Boubakri * inflate() does not support a NULL strm->next_out. So, to 1535418501aSMarouene Boubakri * discard data, we have to allocate a temporary buffer. 1K 1545418501aSMarouene Boubakri * seems reasonable. 1555418501aSMarouene Boubakri */ 1565418501aSMarouene Boubakri strm->avail_out = MIN(len, 1024U); 1575418501aSMarouene Boubakri tmpbuf = malloc(strm->avail_out); 1585418501aSMarouene Boubakri if (!tmpbuf) { 1595418501aSMarouene Boubakri EMSG("Out of memory"); 1605418501aSMarouene Boubakri return TEE_ERROR_OUT_OF_MEMORY; 1615418501aSMarouene Boubakri } 1625418501aSMarouene Boubakri strm->next_out = tmpbuf; 1635418501aSMarouene Boubakri } 1645418501aSMarouene Boubakri /* 1655418501aSMarouene Boubakri * Loop until we get as many bytes as requested, or an error occurs. 1665418501aSMarouene Boubakri * inflate() returns: 1675418501aSMarouene Boubakri * - Z_OK when progress was made, but neither the end of the input 1685418501aSMarouene Boubakri * stream nor the end of the output buffer were met. 1695418501aSMarouene Boubakri * - Z_STREAM_END when the end of the intput stream was reached. 1705418501aSMarouene Boubakri * - Z_BUF_ERROR when there is still input to process but the output 1715418501aSMarouene Boubakri * buffer is full (not a "hard" error, decompression can proceeed 1725418501aSMarouene Boubakri * later). 1735418501aSMarouene Boubakri */ 1745418501aSMarouene Boubakri do { 1755418501aSMarouene Boubakri out = strm->total_out; 1765418501aSMarouene Boubakri st = inflate(strm, Z_SYNC_FLUSH); 1775418501aSMarouene Boubakri out = strm->total_out - out; 1785418501aSMarouene Boubakri total += out; 1795418501aSMarouene Boubakri FMSG("%zu bytes", out); 1805418501aSMarouene Boubakri if (!data) { 1815418501aSMarouene Boubakri /* 1825418501aSMarouene Boubakri * Reset the pointer to throw away what we've just read 1835418501aSMarouene Boubakri * and read again as much as possible. 1845418501aSMarouene Boubakri */ 1855418501aSMarouene Boubakri strm->next_out = tmpbuf; 1865418501aSMarouene Boubakri strm->avail_out = MIN(len - total, 1024U); 1875418501aSMarouene Boubakri } 1885418501aSMarouene Boubakri } while ((st == Z_OK || st == Z_BUF_ERROR) && (total != len)); 1895418501aSMarouene Boubakri 1905418501aSMarouene Boubakri if (st != Z_OK && st != Z_STREAM_END) { 1915418501aSMarouene Boubakri EMSG("Decompression error (%d)", st); 1925418501aSMarouene Boubakri ret = TEE_ERROR_GENERIC; 1935418501aSMarouene Boubakri goto out; 1945418501aSMarouene Boubakri } 1955418501aSMarouene Boubakri ret = TEE_SUCCESS; 1965418501aSMarouene Boubakri out: 1975418501aSMarouene Boubakri free(tmpbuf); 1985418501aSMarouene Boubakri 1995418501aSMarouene Boubakri return ret; 2005418501aSMarouene Boubakri } 2015418501aSMarouene Boubakri 2025418501aSMarouene Boubakri TEE_Result emb_ts_read(struct ts_store_handle *h, void *data, size_t len) 2035418501aSMarouene Boubakri { 2045418501aSMarouene Boubakri if (h->ts->uncompressed_size) 2055418501aSMarouene Boubakri return read_compressed(h, data, len); 2065418501aSMarouene Boubakri else 2075418501aSMarouene Boubakri return read_uncompressed(h, data, len); 2085418501aSMarouene Boubakri } 2095418501aSMarouene Boubakri 2105418501aSMarouene Boubakri void emb_ts_close(struct ts_store_handle *h) 2115418501aSMarouene Boubakri { 2125418501aSMarouene Boubakri if (h->ts->uncompressed_size) 2135418501aSMarouene Boubakri inflateEnd(&h->strm); 2145418501aSMarouene Boubakri free(h); 2155418501aSMarouene Boubakri } 2165418501aSMarouene Boubakri 217