diff --git a/core/arch/arm/pta/sub.mk b/core/arch/arm/pta/sub.mk
index 8f9451b..131a93e 100644
--- a/core/arch/arm/pta/sub.mk
+++ b/core/arch/arm/pta/sub.mk
@@ -15,3 +15,4 @@ srcs-$(CFG_TEE_BENCHMARK) += benchmark.c
 srcs-$(CFG_SDP_PTA) += sdp_pta.c
 srcs-$(CFG_SYSTEM_PTA) += system.c
 srcs-$(CFG_DEVICE_ENUM_PTA) += device.c
+srcs-y += trusted_key.c
diff --git a/core/arch/arm/pta/trusted_key.c b/core/arch/arm/pta/trusted_key.c
new file mode 100644
index 0000000..350609f
--- /dev/null
+++ b/core/arch/arm/pta/trusted_key.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2019, Linaro Limited
+ */
+
+#include <crypto/crypto.h>
+#include <kernel/pseudo_ta.h>
+#include <kernel/tee_ta_manager.h>
+#include <pta_trusted_key.h>
+#include <string.h>
+#include <tee/tee_fs_key_manager.h>
+#include <tee/uuid.h>
+#include <user_ta_header.h>
+
+#define PTA_NAME "trusted_key.pta"
+
+static TEE_Result get_random(uint32_t types,
+			     TEE_Param params[TEE_NUM_PARAMS])
+{
+	FMSG("Invoked TA_CMD_GET_RANDOM");
+
+	if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
+				     TEE_PARAM_TYPE_NONE,
+				     TEE_PARAM_TYPE_NONE,
+				     TEE_PARAM_TYPE_NONE))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (!params[0].memref.buffer || params[0].memref.size == 0)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	return crypto_rng_read(params[0].memref.buffer, params[0].memref.size);
+}
+
+static TEE_Result seal_trusted_key(uint32_t types,
+				   TEE_Param params[TEE_NUM_PARAMS])
+{
+	TEE_Result res = TEE_SUCCESS;
+	const TEE_UUID uuid = PTA_TRUSTED_KEY_UUID;
+
+	FMSG("Invoked TA_CMD_SEAL");
+
+	if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
+				     TEE_PARAM_TYPE_MEMREF_OUTPUT,
+				     TEE_PARAM_TYPE_NONE,
+				     TEE_PARAM_TYPE_NONE))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (!params[0].memref.buffer || params[0].memref.size == 0)
+		return TEE_ERROR_BAD_PARAMETERS;
+	if (!params[1].memref.buffer || params[1].memref.size == 0)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	res = tee_fs_fek_crypt(&uuid, TEE_MODE_ENCRYPT, params[0].memref.buffer,
+			       params[0].memref.size, params[1].memref.buffer);
+	if (res == TEE_SUCCESS)
+		params[1].memref.size = params[0].memref.size;
+	else
+		params[1].memref.size = 0;
+
+	return res;
+}
+
+static TEE_Result unseal_trusted_key(uint32_t types,
+				     TEE_Param params[TEE_NUM_PARAMS])
+{
+	TEE_Result res = TEE_SUCCESS;
+	const TEE_UUID uuid = PTA_TRUSTED_KEY_UUID;
+
+	FMSG("Invoked TA_CMD_UNSEAL");
+
+	if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
+				     TEE_PARAM_TYPE_MEMREF_OUTPUT,
+				     TEE_PARAM_TYPE_NONE,
+				     TEE_PARAM_TYPE_NONE))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (!params[0].memref.buffer || params[0].memref.size == 0)
+		return TEE_ERROR_BAD_PARAMETERS;
+	if (!params[1].memref.buffer || params[1].memref.size == 0)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	res = tee_fs_fek_crypt(&uuid, TEE_MODE_DECRYPT, params[0].memref.buffer,
+			       params[0].memref.size, params[1].memref.buffer);
+	if (res == TEE_SUCCESS)
+		params[1].memref.size = params[0].memref.size;
+	else
+		params[1].memref.size = 0;
+
+	return res;
+}
+
+static TEE_Result invoke_command(void *pSessionContext __unused,
+				 uint32_t nCommandID, uint32_t nParamTypes,
+				 TEE_Param pParams[TEE_NUM_PARAMS])
+{
+	switch (nCommandID) {
+	case TA_CMD_GET_RANDOM:
+		return get_random(nParamTypes, pParams);
+	case TA_CMD_SEAL:
+		return seal_trusted_key(nParamTypes, pParams);
+	case TA_CMD_UNSEAL:
+		return unseal_trusted_key(nParamTypes, pParams);
+	default:
+		break;
+	}
+
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static TEE_Result open_session(uint32_t param_types __unused,
+			       TEE_Param params[TEE_NUM_PARAMS] __unused,
+			       void **sess_ctx __unused)
+{
+	TEE_Result res = TEE_SUCCESS;
+	struct tee_ta_session *s;
+
+	/* Check that we're called from a REE kernel client */
+	res = tee_ta_get_current_session(&s);
+	if (res != TEE_SUCCESS)
+		return res;
+	if (s->clnt_id.login != TEE_LOGIN_REE_KERNEL)
+		res = TEE_ERROR_ACCESS_DENIED;
+
+	return res;
+}
+
+
+pseudo_ta_register(.uuid = PTA_TRUSTED_KEY_UUID, .name = PTA_NAME,
+		   .flags = PTA_DEFAULT_FLAGS | TA_FLAG_DEVICE_ENUM,
+		   .open_session_entry_point = open_session,
+		   .invoke_command_entry_point = invoke_command);
diff --git a/core/arch/arm/tee/entry_std.c b/core/arch/arm/tee/entry_std.c
index 876f97e..a3ca33c 100644
--- a/core/arch/arm/tee/entry_std.c
+++ b/core/arch/arm/tee/entry_std.c
@@ -281,6 +281,7 @@ static TEE_Result get_open_session_meta(size_t num_params,
 	clnt_id->login = params[1].u.value.c;
 	switch (clnt_id->login) {
 	case TEE_LOGIN_PUBLIC:
+	case TEE_LOGIN_REE_KERNEL:
 		memset(&clnt_id->uuid, 0, sizeof(clnt_id->uuid));
 		break;
 	case TEE_LOGIN_USER:
diff --git a/core/tee/tee_fs_key_manager.c b/core/tee/tee_fs_key_manager.c
index 314554d..560dc4c 100644
--- a/core/tee/tee_fs_key_manager.c
+++ b/core/tee/tee_fs_key_manager.c
@@ -83,7 +83,7 @@ TEE_Result tee_fs_fek_crypt(const TEE_UUID *uuid, TEE_OperationMode mode,
 	if (!in_key || !out_key)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	if (size != TEE_FS_KM_FEK_SIZE)
+	if (size > TEE_SHA256_HASH_SIZE)
 		return TEE_ERROR_BAD_PARAMETERS;
 
 	if (tee_fs_ssk.is_init == 0)
diff --git a/lib/libutee/include/pta_trusted_key.h b/lib/libutee/include/pta_trusted_key.h
new file mode 100644
index 0000000..666ae43
--- /dev/null
+++ b/lib/libutee/include/pta_trusted_key.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2019, Linaro Limited
+ */
+
+/*
+ * Enumerate the pseudo TAs that have the TA_FLAG_DEVICE_ENUM flag enabled.
+ */
+
+#ifndef __PTA_TRUSTED_KEY_H
+#define __PTA_TRUSTED_KEY_H
+
+#define PTA_TRUSTED_KEY_UUID { 0xf04a0fe7, 0x1f5d, 0x4b9b, \
+		{ 0xab, 0xf7, 0x61, 0x9b, 0x85, 0xb4, 0xce, 0x8c } }
+
+/*
+ * Get random data for symmetric key
+ *
+ * [out]     memref[0]        Random data
+ *
+ * Result:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ */
+#define TA_CMD_GET_RANDOM	0x0
+
+/*
+ * Seal trusted key using hardware unique key
+ *
+ * [in]      memref[0]        Plain key
+ * [out]     memref[1]        Sealed key datablob
+ *
+ * Result:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ */
+#define TA_CMD_SEAL		0x1
+
+/*
+ * Unseal trusted key using hardware unique key
+ *
+ * [in]      memref[0]        Sealed key datablob
+ * [out]     memref[1]        Plain key
+ *
+ * Result:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ */
+#define TA_CMD_UNSEAL		0x2
+
+#endif /* __PTA_TRUSTED_KEY_H */
diff --git a/lib/libutee/include/tee_api_defines.h b/lib/libutee/include/tee_api_defines.h
index c71108a..d1dbecc 100644
--- a/lib/libutee/include/tee_api_defines.h
+++ b/lib/libutee/include/tee_api_defines.h
@@ -63,6 +63,8 @@
 #define TEE_LOGIN_APPLICATION_USER      0x00000005
 #define TEE_LOGIN_APPLICATION_GROUP     0x00000006
 #define TEE_LOGIN_TRUSTED_APP           0xF0000000
+/* Private login method for REE kernel clients */
+#define TEE_LOGIN_REE_KERNEL		0x80000000
 
 /* Origin Code Constants */
 #define TEE_ORIGIN_API                  0x00000001
