xref: /optee_os/core/kernel/embedded_ts.c (revision c123d80431428aa73551e611904bb2c1a32cf9fa)
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