ta/storage: use private buffers where needed

The GP specification [1] requires buffer for certain functions to reside
in TA private memory. Fix this by allocating a temporary buffer where
needed. Some buffers are rather large so increase the size of heap too.

[1] GlobalPlatform TEE Internal Core API Specification v1.1
Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Reviewed-by: Joakim Bech <joakim.bech@linaro.org>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
diff --git a/ta/storage/include/user_ta_header_defines.h b/ta/storage/include/user_ta_header_defines.h
index e994162..1d92759 100644
--- a/ta/storage/include/user_ta_header_defines.h
+++ b/ta/storage/include/user_ta_header_defines.h
@@ -18,6 +18,6 @@
 #define TA_FLAGS		(TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR | \
 				TA_FLAG_MULTI_SESSION)
 #define TA_STACK_SIZE		(2 * 1024)
-#define TA_DATA_SIZE		(32 * 1024)
+#define TA_DATA_SIZE		(64 * 1024)
 
 #endif
diff --git a/ta/storage/storage.c b/ta/storage/storage.c
index 432ca52..7e639f3 100644
--- a/ta/storage/storage.c
+++ b/ta/storage/storage.c
@@ -161,27 +161,47 @@
 TEE_Result ta_storage_cmd_read(uint32_t param_types, TEE_Param params[4])
 {
 	TEE_ObjectHandle o = VAL2HANDLE(params[1].value.a);
+	TEE_Result res = TEE_SUCCESS;
+	void *b0 = NULL;
 
 	ASSERT_PARAM_TYPE(TEE_PARAM_TYPES
 			  (TEE_PARAM_TYPE_MEMREF_OUTPUT,
 			   TEE_PARAM_TYPE_VALUE_INOUT, TEE_PARAM_TYPE_NONE,
 			   TEE_PARAM_TYPE_NONE));
 
-	return TEE_ReadObjectData(o, params[0].memref.buffer,
-				  params[0].memref.size, &params[1].value.b);
+	b0 = TEE_Malloc(params[0].memref.size, 0);
+	if (!b0)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	res = TEE_ReadObjectData(o, b0, params[0].memref.size,
+				 &params[1].value.b);
+	if (!res)
+		TEE_MemMove(params[0].memref.buffer, b0, params[0].memref.size);
+	TEE_Free(b0);
+
+	return res;
 }
 
 TEE_Result ta_storage_cmd_write(uint32_t param_types, TEE_Param params[4])
 {
 	TEE_ObjectHandle o = VAL2HANDLE(params[1].value.a);
+	TEE_Result res = TEE_SUCCESS;
+	void *b0 = NULL;
 
 	ASSERT_PARAM_TYPE(TEE_PARAM_TYPES
 			  (TEE_PARAM_TYPE_MEMREF_INPUT,
 			   TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE,
 			   TEE_PARAM_TYPE_NONE));
 
-	return TEE_WriteObjectData(o, params[0].memref.buffer,
-				   params[0].memref.size);
+	b0 = TEE_Malloc(params[0].memref.size, 0);
+	if (!b0)
+		return TEE_ERROR_OUT_OF_MEMORY;
+	TEE_MemMove(b0, params[0].memref.buffer, params[0].memref.size);
+
+	res = TEE_WriteObjectData(o, b0, params[0].memref.size);
+	TEE_Free(b0);
+
+	return res;
 }
 
 TEE_Result ta_storage_cmd_seek(uint32_t param_types, TEE_Param params[4])
@@ -319,7 +339,9 @@
 TEE_Result ta_storage_cmd_next_enum(uint32_t param_types, TEE_Param params[4])
 {
 	TEE_ObjectEnumHandle oe = VAL2HANDLE(params[0].value.a);
+	TEE_Result res = TEE_SUCCESS;
 	TEE_ObjectInfo *obj = NULL;
+	void *b2 = NULL;
 
 	if (TEE_PARAM_TYPE_GET(param_types, 0) != TEE_PARAM_TYPE_VALUE_INPUT)
 		return TEE_ERROR_BAD_PARAMETERS;
@@ -328,6 +350,9 @@
 	if (TEE_PARAM_TYPE_GET(param_types, 3) != TEE_PARAM_TYPE_NONE)
 		return TEE_ERROR_BAD_PARAMETERS;
 
+	if (params[2].memref.size < TEE_OBJECT_ID_MAX_LEN)
+		return TEE_ERROR_SHORT_BUFFER;
+
 	if (TEE_PARAM_TYPE_GET(param_types, 1) == TEE_PARAM_TYPE_NONE)
 		obj = NULL;
 	else if (TEE_PARAM_TYPE_GET(param_types, 1) ==
@@ -337,16 +362,30 @@
 			return TEE_ERROR_SHORT_BUFFER;
 		}
 		params[1].memref.size = sizeof(TEE_ObjectInfo);
-		obj = (TEE_ObjectInfo *)params[1].memref.buffer;
+		obj = TEE_Malloc(sizeof(TEE_ObjectInfo), 0);
+		if (!obj)
+			return TEE_ERROR_OUT_OF_MEMORY;
 	} else
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	if (params[2].memref.size < TEE_OBJECT_ID_MAX_LEN)
-		return TEE_ERROR_SHORT_BUFFER;
+	b2 = TEE_Malloc(params[2].memref.size, 0);
+	if (!b2) {
+		res = TEE_ERROR_OUT_OF_MEMORY;
+		goto out;
+	}
 
-	return TEE_GetNextPersistentObject(oe, obj,
-					   params[2].memref.buffer,
-					   &params[2].memref.size);
+	res = TEE_GetNextPersistentObject(oe, obj, b2, &params[2].memref.size);
+	if (res)
+		goto out;
+
+	TEE_MemMove(params[2].memref.buffer, b2, params[2].memref.size);
+	if (obj)
+		TEE_MemMove(params[1].memref.buffer, obj, sizeof(*obj));
+out:
+	TEE_Free(b2);
+	TEE_Free(obj);
+
+	return res;
 }
 
 static TEE_Result check_obj(TEE_ObjectInfo *o1, TEE_ObjectInfo *o2)
@@ -568,7 +607,7 @@
 					    TEE_Param params[4])
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
-	TEE_ObjectInfo *info = NULL;
+	TEE_ObjectInfo info = { };
 	TEE_ObjectHandle o = VAL2HANDLE(params[0].value.a);
 
 	ASSERT_PARAM_TYPE(TEE_PARAM_TYPES
@@ -576,8 +615,13 @@
 			   TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE,
 			   TEE_PARAM_TYPE_NONE));
 
-	info = (TEE_ObjectInfo *)params[1].memref.buffer;
-	res = TEE_GetObjectInfo1(o, info);
+	if (params[1].memref.size < sizeof(info))
+		return TEE_ERROR_SHORT_BUFFER;
+	res = TEE_GetObjectInfo1(o, &info);
+	if (!res) {
+		params[1].memref.size = sizeof(info);
+		TEE_MemMove(params[1].memref.buffer, &info, sizeof(info));
+	}
 
 	return res;
 }