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*ef44161fSJens Wiklander #include <kernel/user_access.h>
11c123d804SJens Wiklander #include <mempool.h>
125418501aSMarouene Boubakri #include <stdio.h>
135418501aSMarouene Boubakri #include <stdlib.h>
145418501aSMarouene Boubakri #include <string.h>
155418501aSMarouene Boubakri #include <trace.h>
165418501aSMarouene Boubakri #include <utee_defines.h>
175418501aSMarouene Boubakri #include <util.h>
185418501aSMarouene Boubakri #include <zlib.h>
195418501aSMarouene Boubakri
205418501aSMarouene Boubakri struct ts_store_handle {
215418501aSMarouene Boubakri const struct embedded_ts *ts;
225418501aSMarouene Boubakri size_t offs;
235418501aSMarouene Boubakri z_stream strm;
245418501aSMarouene Boubakri };
255418501aSMarouene Boubakri
zalloc(void * opaque __unused,unsigned int items,unsigned int size)265418501aSMarouene Boubakri static void *zalloc(void *opaque __unused, unsigned int items,
275418501aSMarouene Boubakri unsigned int size)
285418501aSMarouene Boubakri {
29c123d804SJens Wiklander return mempool_alloc(mempool_default, items * size);
305418501aSMarouene Boubakri }
315418501aSMarouene Boubakri
zfree(void * opaque __unused,void * address)325418501aSMarouene Boubakri static void zfree(void *opaque __unused, void *address)
335418501aSMarouene Boubakri {
34c123d804SJens Wiklander mempool_free(mempool_default, address);
355418501aSMarouene Boubakri }
365418501aSMarouene Boubakri
decompression_init(z_stream * strm,const struct embedded_ts * ts)375418501aSMarouene Boubakri static bool decompression_init(z_stream *strm,
385418501aSMarouene Boubakri const struct embedded_ts *ts)
395418501aSMarouene Boubakri {
405418501aSMarouene Boubakri int st = Z_OK;
415418501aSMarouene Boubakri
425418501aSMarouene Boubakri strm->next_in = ts->ts;
435418501aSMarouene Boubakri strm->avail_in = ts->size;
445418501aSMarouene Boubakri strm->zalloc = zalloc;
455418501aSMarouene Boubakri strm->zfree = zfree;
465418501aSMarouene Boubakri st = inflateInit(strm);
475418501aSMarouene Boubakri if (st != Z_OK) {
485418501aSMarouene Boubakri EMSG("Decompression initialization error (%d)", st);
495418501aSMarouene Boubakri return false;
505418501aSMarouene Boubakri }
515418501aSMarouene Boubakri
525418501aSMarouene Boubakri return true;
535418501aSMarouene Boubakri }
545418501aSMarouene Boubakri
emb_ts_open(const TEE_UUID * uuid,struct ts_store_handle ** h,const struct embedded_ts * (* find_ts)(const TEE_UUID * uuid))555418501aSMarouene Boubakri TEE_Result emb_ts_open(const TEE_UUID *uuid,
565418501aSMarouene Boubakri struct ts_store_handle **h,
575418501aSMarouene Boubakri const struct embedded_ts*
585418501aSMarouene Boubakri (*find_ts) (const TEE_UUID *uuid))
595418501aSMarouene Boubakri {
605418501aSMarouene Boubakri struct ts_store_handle *handle = NULL;
615418501aSMarouene Boubakri const struct embedded_ts *ts = NULL;
625418501aSMarouene Boubakri
635418501aSMarouene Boubakri ts = find_ts(uuid);
645418501aSMarouene Boubakri if (!ts)
655418501aSMarouene Boubakri return TEE_ERROR_ITEM_NOT_FOUND;
665418501aSMarouene Boubakri
675418501aSMarouene Boubakri handle = calloc(1, sizeof(*handle));
685418501aSMarouene Boubakri if (!handle)
695418501aSMarouene Boubakri return TEE_ERROR_OUT_OF_MEMORY;
705418501aSMarouene Boubakri
715418501aSMarouene Boubakri if (ts->uncompressed_size) {
725418501aSMarouene Boubakri if (!decompression_init(&handle->strm, ts)) {
735418501aSMarouene Boubakri free(handle);
745418501aSMarouene Boubakri return TEE_ERROR_BAD_FORMAT;
755418501aSMarouene Boubakri }
765418501aSMarouene Boubakri }
775418501aSMarouene Boubakri handle->ts = ts;
785418501aSMarouene Boubakri *h = handle;
795418501aSMarouene Boubakri
805418501aSMarouene Boubakri return TEE_SUCCESS;
815418501aSMarouene Boubakri }
825418501aSMarouene Boubakri
emb_ts_get_size(const struct ts_store_handle * h,size_t * size)835418501aSMarouene Boubakri TEE_Result emb_ts_get_size(const struct ts_store_handle *h, size_t *size)
845418501aSMarouene Boubakri {
855418501aSMarouene Boubakri const struct embedded_ts *ts = h->ts;
865418501aSMarouene Boubakri
875418501aSMarouene Boubakri if (ts->uncompressed_size)
885418501aSMarouene Boubakri *size = ts->uncompressed_size;
895418501aSMarouene Boubakri else
905418501aSMarouene Boubakri *size = ts->size;
915418501aSMarouene Boubakri
925418501aSMarouene Boubakri return TEE_SUCCESS;
935418501aSMarouene Boubakri }
945418501aSMarouene Boubakri
emb_ts_get_tag(const struct ts_store_handle * h,uint8_t * tag,unsigned int * tag_len)955418501aSMarouene Boubakri TEE_Result emb_ts_get_tag(const struct ts_store_handle *h,
965418501aSMarouene Boubakri uint8_t *tag, unsigned int *tag_len)
975418501aSMarouene Boubakri {
985418501aSMarouene Boubakri TEE_Result res = TEE_SUCCESS;
995418501aSMarouene Boubakri void *ctx = NULL;
1005418501aSMarouene Boubakri
1015418501aSMarouene Boubakri if (!tag || *tag_len < TEE_SHA256_HASH_SIZE) {
1025418501aSMarouene Boubakri *tag_len = TEE_SHA256_HASH_SIZE;
1035418501aSMarouene Boubakri return TEE_ERROR_SHORT_BUFFER;
1045418501aSMarouene Boubakri }
1055418501aSMarouene Boubakri *tag_len = TEE_SHA256_HASH_SIZE;
1065418501aSMarouene Boubakri
1075418501aSMarouene Boubakri res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256);
1085418501aSMarouene Boubakri if (res)
1095418501aSMarouene Boubakri return res;
1105418501aSMarouene Boubakri res = crypto_hash_init(ctx);
1115418501aSMarouene Boubakri if (res)
1125418501aSMarouene Boubakri goto out;
1135418501aSMarouene Boubakri res = crypto_hash_update(ctx, h->ts->ts, h->ts->size);
1145418501aSMarouene Boubakri if (res)
1155418501aSMarouene Boubakri goto out;
1165418501aSMarouene Boubakri res = crypto_hash_final(ctx, tag, *tag_len);
1175418501aSMarouene Boubakri out:
1185418501aSMarouene Boubakri crypto_hash_free_ctx(ctx);
1195418501aSMarouene Boubakri return res;
1205418501aSMarouene Boubakri }
1215418501aSMarouene Boubakri
read_uncompressed(struct ts_store_handle * h,void * data_core,void * data_user,size_t len)122*ef44161fSJens Wiklander static TEE_Result read_uncompressed(struct ts_store_handle *h, void *data_core,
123*ef44161fSJens Wiklander void *data_user, size_t len)
1245418501aSMarouene Boubakri {
125*ef44161fSJens Wiklander TEE_Result res = TEE_SUCCESS;
1265418501aSMarouene Boubakri uint8_t *src = (uint8_t *)h->ts->ts + h->offs;
1275418501aSMarouene Boubakri size_t next_offs = 0;
1285418501aSMarouene Boubakri
1295418501aSMarouene Boubakri if (ADD_OVERFLOW(h->offs, len, &next_offs) ||
1305418501aSMarouene Boubakri next_offs > h->ts->size)
1315418501aSMarouene Boubakri return TEE_ERROR_BAD_PARAMETERS;
132*ef44161fSJens Wiklander if (data_core)
133*ef44161fSJens Wiklander memcpy(data_core, src, len);
134*ef44161fSJens Wiklander if (data_user)
135*ef44161fSJens Wiklander res = copy_to_user(data_user, src, len);
136*ef44161fSJens Wiklander if (!res)
1375418501aSMarouene Boubakri h->offs = next_offs;
1385418501aSMarouene Boubakri
139*ef44161fSJens Wiklander return res;
1405418501aSMarouene Boubakri }
1415418501aSMarouene Boubakri
read_compressed(struct ts_store_handle * h,void * data_core,void * data_user,size_t len)142*ef44161fSJens Wiklander static TEE_Result read_compressed(struct ts_store_handle *h, void *data_core,
143*ef44161fSJens Wiklander void *data_user, size_t len)
1445418501aSMarouene Boubakri {
145*ef44161fSJens Wiklander TEE_Result res = TEE_SUCCESS;
1465418501aSMarouene Boubakri z_stream *strm = &h->strm;
1475418501aSMarouene Boubakri size_t total = 0;
148*ef44161fSJens Wiklander uint8_t *bb = NULL;
149*ef44161fSJens Wiklander size_t bb_len = 0;
1505418501aSMarouene Boubakri size_t out = 0;
1515418501aSMarouene Boubakri int st = Z_OK;
1525418501aSMarouene Boubakri
153*ef44161fSJens Wiklander /* Inflate into a 1kB bounce buffer */
154*ef44161fSJens Wiklander bb_len = MIN(len, 1024U);
155*ef44161fSJens Wiklander bb = bb_alloc(bb_len);
156*ef44161fSJens Wiklander if (!bb) {
1575418501aSMarouene Boubakri EMSG("Out of memory");
1585418501aSMarouene Boubakri return TEE_ERROR_OUT_OF_MEMORY;
1595418501aSMarouene Boubakri }
160*ef44161fSJens Wiklander
161*ef44161fSJens Wiklander strm->avail_out = bb_len;
162*ef44161fSJens Wiklander strm->next_out = bb;
163*ef44161fSJens Wiklander
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 FMSG("%zu bytes", out);
179*ef44161fSJens Wiklander if (data_core)
180*ef44161fSJens Wiklander memcpy((uint8_t *)data_core + total, bb, out);
181*ef44161fSJens Wiklander if (data_user) {
182*ef44161fSJens Wiklander res = copy_to_user((uint8_t *)data_user + total, bb,
183*ef44161fSJens Wiklander out);
184*ef44161fSJens Wiklander if (res)
185*ef44161fSJens Wiklander goto out;
1865418501aSMarouene Boubakri }
187*ef44161fSJens Wiklander total += out;
188*ef44161fSJens Wiklander /*
189*ef44161fSJens Wiklander * Reset the pointer since we've just copied out the last
190*ef44161fSJens Wiklander * data.
191*ef44161fSJens Wiklander */
192*ef44161fSJens Wiklander strm->next_out = bb;
193*ef44161fSJens Wiklander strm->avail_out = MIN(len - total, bb_len);
1945418501aSMarouene Boubakri } while ((st == Z_OK || st == Z_BUF_ERROR) && (total != len));
1955418501aSMarouene Boubakri
1965418501aSMarouene Boubakri if (st != Z_OK && st != Z_STREAM_END) {
1975418501aSMarouene Boubakri EMSG("Decompression error (%d)", st);
198*ef44161fSJens Wiklander res = TEE_ERROR_GENERIC;
1995418501aSMarouene Boubakri goto out;
2005418501aSMarouene Boubakri }
201*ef44161fSJens Wiklander res = TEE_SUCCESS;
2025418501aSMarouene Boubakri out:
203*ef44161fSJens Wiklander bb_free(bb, bb_len);
2045418501aSMarouene Boubakri
205*ef44161fSJens Wiklander return res;
2065418501aSMarouene Boubakri }
2075418501aSMarouene Boubakri
emb_ts_read(struct ts_store_handle * h,void * data_core,void * data_user,size_t len)208*ef44161fSJens Wiklander TEE_Result emb_ts_read(struct ts_store_handle *h, void *data_core,
209*ef44161fSJens Wiklander void *data_user, size_t len)
2105418501aSMarouene Boubakri {
2115418501aSMarouene Boubakri if (h->ts->uncompressed_size)
212*ef44161fSJens Wiklander return read_compressed(h, data_core, data_user, len);
2135418501aSMarouene Boubakri else
214*ef44161fSJens Wiklander return read_uncompressed(h, data_core, data_user, len);
2155418501aSMarouene Boubakri }
2165418501aSMarouene Boubakri
emb_ts_close(struct ts_store_handle * h)2175418501aSMarouene Boubakri void emb_ts_close(struct ts_store_handle *h)
2185418501aSMarouene Boubakri {
2195418501aSMarouene Boubakri if (h->ts->uncompressed_size)
2205418501aSMarouene Boubakri inflateEnd(&h->strm);
2215418501aSMarouene Boubakri free(h);
2225418501aSMarouene Boubakri }
2235418501aSMarouene Boubakri
224