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