mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Michael Tretter <m.tretter@pengutronix.de>
To: Sascha Hauer <s.hauer@pengutronix.de>,
	 BAREBOX <barebox@lists.infradead.org>
Cc: Michael Tretter <m.tretter@pengutronix.de>
Subject: [PATCH RFC 2/3] tee: drivers: add driver for Rockchip Secure Boot PTA
Date: Mon, 05 Jan 2026 15:32:32 +0100	[thread overview]
Message-ID: <20260105-rockchip-secure-boot-v1-2-eaf5053a7d7e@pengutronix.de> (raw)
In-Reply-To: <20260105-rockchip-secure-boot-v1-0-eaf5053a7d7e@pengutronix.de>

The OTP fuses for secure boot are only accessible from the secure world.
Therefore, burning the fuses has to be delegated to the Rockchip Secure
Boot PTA running in the secure world.

The alternative to burn the fuses while barebox is still in the secure
world prevents user interaction and costs a lot of flexibility.

Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
---
 drivers/tee/optee/Kconfig              |   7 ++
 drivers/tee/optee/Makefile             |   1 +
 drivers/tee/optee/pta_rk_secure_boot.h |  48 ++++++++
 drivers/tee/optee/rksecure.c           | 196 +++++++++++++++++++++++++++++++++
 include/rk_secure_boot.h               |  21 ++++
 5 files changed, 273 insertions(+)

diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
index 805aba65edb7..fcaca29a5df7 100644
--- a/drivers/tee/optee/Kconfig
+++ b/drivers/tee/optee/Kconfig
@@ -40,6 +40,13 @@ config OPTEE_AVB_PERSISTENT_VALUES
 	  pairs. AVB itself is not implemented in barebox, but enabling this option
 	  allows barebox to use the AVB persistent value store.
 
+config OPTEE_RKSECURE
+	bool "Rockchip Secure Boot PTA support"
+	depends on OPTEE
+	help
+	  Enable this option to use the Rockchip Secure Boot PTA to read or
+	  write the secure boot OTP fuses of an rk3588 SoC.
+
 endif
 
 config OF_FIXUP_OPTEE
diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
index 1fbeb39fb8ba..e89edc876d6f 100644
--- a/drivers/tee/optee/Makefile
+++ b/drivers/tee/optee/Makefile
@@ -8,3 +8,4 @@ optee-objs += device.o
 optee-objs += smc_abi.o
 obj-$(CONFIG_MCI_MMC_RPMB) += rpmb.o
 obj-$(CONFIG_OPTEE_AVB_PERSISTENT_VALUES) += avb.o
+obj-$(CONFIG_OPTEE_RKSECURE) += rksecure.o
diff --git a/drivers/tee/optee/pta_rk_secure_boot.h b/drivers/tee/optee/pta_rk_secure_boot.h
new file mode 100644
index 000000000000..13fa59d9908a
--- /dev/null
+++ b/drivers/tee/optee/pta_rk_secure_boot.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2025, Pengutronix, Michael Tretter <entwicklung@pengutronix.de>
+ */
+
+#ifndef __PTA_RK_SECURE_BOOT_H
+#define __PTA_RK_SECURE_BOOT_H
+
+#include <types.h>
+
+#define PTA_RK_SECURE_BOOT_UUID \
+	UUID_INIT(0x5cfa57f6, 0x1a4c, 0x407f, \
+		  0x94, 0xa7, 0xa5, 0x6c, 0x8c, 0x47, 0x01, 0x9d)
+
+struct pta_rk_secure_boot_hash {
+	/* sha256 has 256 bit */
+	uint8_t value[32];
+};
+
+struct pta_rk_secure_boot_info {
+	uint8_t enabled;
+	uint8_t simulation;
+	struct pta_rk_secure_boot_hash hash;
+};
+
+/*
+ * PTA_RK_SECURE_BOOT_GET_INFO - Get secure boot status info
+ *
+ * [out]    memref[0]   buffer memory reference containing a struct
+ *                      pta_rk_secure_boot_info
+ */
+#define PTA_RK_SECURE_BOOT_GET_INFO		0x0
+
+/*
+ * PTA_RK_SECURE_BOOT_BURN_HASH - Burn the RSA key hash to fuses
+ *
+ * [in]    memref[0]   buffer memory reference containing a struct
+ *                     pta_rk_secure_boot_hash
+ * [in]    value[1].a  bit length of signing key
+ */
+#define PTA_RK_SECURE_BOOT_BURN_HASH		0x1
+
+/*
+ * PTA_RK_SECURE_BOOT_LOCKDOWN_DEVICE - Lockdown the device with secure boot
+ */
+#define PTA_RK_SECURE_BOOT_LOCKDOWN_DEVICE	0x2
+
+#endif /* __PTA_ROCKCHIP_OTP_H */
diff --git a/drivers/tee/optee/rksecure.c b/drivers/tee/optee/rksecure.c
new file mode 100644
index 000000000000..6bc9a61571c2
--- /dev/null
+++ b/drivers/tee/optee/rksecure.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Pengutronix, Michael Tretter <m.tretter@pengutronix.de>
+ */
+
+#include <linux/tee_drv.h>
+#include <linux/uuid.h>
+#include <uapi/linux/tee.h>
+
+#include <rk_secure_boot.h>
+
+#include "optee_private.h"
+#include "pta_rk_secure_boot.h"
+
+const uuid_t ta_uuid = PTA_RK_SECURE_BOOT_UUID;
+
+static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
+{
+	return ver->impl_id == TEE_IMPL_ID_OPTEE ? 1 : 0;
+}
+
+static int rk_secure_open_session(struct tee_context *ctx, __u32 *session)
+{
+	struct tee_ioctl_open_session_arg sess_arg = {};
+	int res = 0;
+
+	export_uuid(sess_arg.uuid, &ta_uuid);
+	sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
+	sess_arg.num_params = 0;
+
+	res = tee_client_open_session(ctx, &sess_arg, NULL);
+	if (res < 0)
+		return res;
+	switch (sess_arg.ret) {
+	case TEEC_SUCCESS:
+		res = 0;
+		break;
+	case TEEC_ERROR_ITEM_NOT_FOUND:
+		pr_err("cannot find TA %pU\n", &sess_arg.uuid);
+		return -ENOENT;
+	default:
+		pr_err("TA %pU: error 0x%x\n", &sess_arg.uuid, sess_arg.ret);
+		return -EINVAL;
+	}
+
+	*session = sess_arg.session;
+	return res;
+}
+
+int rk_secure_boot_get_info(struct rk_secure_boot_info *out)
+{
+	struct tee_context *ctx = NULL;
+	struct tee_ioctl_invoke_arg inv_arg;
+	struct tee_param param[1];
+	struct tee_shm *info_shm;
+	struct pta_rk_secure_boot_info *info;
+	__u32 session = 0;
+	int res = 0;
+
+	ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
+	if (IS_ERR(ctx))
+		return -ENODEV;
+
+	res = rk_secure_open_session(ctx, &session);
+	if (res < 0)
+		goto out_ctx;
+
+	info_shm = tee_shm_alloc_kernel_buf(ctx, sizeof(*info));
+	if (IS_ERR(info_shm)) {
+		res = -ENOMEM;
+		goto close_session;
+	}
+	info = info_shm->kaddr;
+
+	memset(param, 0, sizeof(param));
+	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+	param[0].u.memref.shm = info_shm;
+	param[0].u.memref.size = sizeof(*info);
+
+	inv_arg.func = PTA_RK_SECURE_BOOT_GET_INFO;
+	inv_arg.session = session;
+	inv_arg.num_params = ARRAY_SIZE(param);
+
+	res = tee_client_invoke_func(ctx, &inv_arg, param);
+	if (res)
+		goto out;
+	if (inv_arg.ret) {
+		pr_err("invoke func failed with 0x%08x\n", inv_arg.ret);
+		res = -EIO;
+	}
+
+	memcpy(out->hash, info->hash.value, sizeof(out->hash));
+	out->lockdown = info->enabled;
+	out->simulation = info->simulation;
+
+out:
+	tee_shm_free(info_shm);
+close_session:
+	tee_client_close_session(ctx, session);
+out_ctx:
+	tee_client_close_context(ctx);
+
+	return res;
+}
+
+int rk_secure_boot_burn_hash(const u8 *hash, u32 key_size_bits)
+{
+	struct tee_context *ctx = NULL;
+	struct tee_ioctl_invoke_arg inv_arg;
+	struct tee_param param[2];
+	struct tee_shm *shm_hash;
+	struct pta_rk_secure_boot_hash *pta_hash;
+	__u32 session = 0;
+	int res = 0;
+
+	ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
+	if (IS_ERR(ctx))
+		return -ENODEV;
+
+	res = rk_secure_open_session(ctx, &session);
+	if (res < 0)
+		goto out_ctx;
+
+	shm_hash = tee_shm_alloc_kernel_buf(ctx, sizeof(*pta_hash));
+	if (IS_ERR(shm_hash)) {
+		res = -ENOMEM;
+		goto close_session;
+	}
+	pta_hash = shm_hash->kaddr;
+
+	memcpy(pta_hash->value, hash, sizeof(pta_hash->value));
+
+	memset(param, 0, sizeof(param));
+	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+	param[0].u.memref.shm = shm_hash;
+	param[0].u.memref.size = sizeof(*pta_hash);
+
+	param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+	param[1].u.value.a = key_size_bits;
+
+	inv_arg.func = PTA_RK_SECURE_BOOT_BURN_HASH;
+	inv_arg.session = session;
+	inv_arg.num_params = ARRAY_SIZE(param);
+
+	res = tee_client_invoke_func(ctx, &inv_arg, param);
+	if (res)
+		goto out;
+	if (inv_arg.ret) {
+		pr_err("invoke func failed with 0x%08x\n", inv_arg.ret);
+		res = -EIO;
+	}
+
+out:
+	tee_shm_free(shm_hash);
+close_session:
+	tee_client_close_session(ctx, session);
+out_ctx:
+	tee_client_close_context(ctx);
+
+	return res;
+}
+
+int rk_secure_boot_lockdown_device(void)
+{
+	struct tee_context *ctx = NULL;
+	struct tee_ioctl_invoke_arg inv_arg;
+	__u32 session = 0;
+	int res = 0;
+
+	ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL);
+	if (IS_ERR(ctx))
+		return -ENODEV;
+
+	res = rk_secure_open_session(ctx, &session);
+	if (res < 0)
+		goto out_ctx;
+
+	inv_arg.func = PTA_RK_SECURE_BOOT_LOCKDOWN_DEVICE;
+	inv_arg.session = session;
+	inv_arg.num_params = 0;
+
+	res = tee_client_invoke_func(ctx, &inv_arg, NULL);
+	if (res)
+		goto close_session;
+	if (inv_arg.ret) {
+		pr_err("invoke func failed with 0x%08x\n", inv_arg.ret);
+		res = -EIO;
+	}
+
+close_session:
+	tee_client_close_session(ctx, session);
+out_ctx:
+	tee_client_close_context(ctx);
+
+	return res;
+}
diff --git a/include/rk_secure_boot.h b/include/rk_secure_boot.h
new file mode 100644
index 000000000000..6e247aa7eef3
--- /dev/null
+++ b/include/rk_secure_boot.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2025 Pengutronix, Michael Tretter <m.tretter@pengutronix.de>
+ */
+
+#ifndef __RK_SECURE_BOOT_H
+#define __RK_SECURE_BOOT_H
+
+#include <linux/types.h>
+
+struct rk_secure_boot_info {
+	bool lockdown;
+	bool simulation;
+	u8 hash[32];
+};
+
+int rk_secure_boot_get_info(struct rk_secure_boot_info *info);
+int rk_secure_boot_burn_hash(const u8 *hash, u32 key_size_bits);
+int rk_secure_boot_lockdown_device(void);
+
+#endif /* __RK_SECURE_BOOT_H */

-- 
2.47.3




  parent reply	other threads:[~2026-01-05 14:33 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-05 14:32 [PATCH RFC 0/3] ARM: rockchip: add rockchip secure boot Michael Tretter
2026-01-05 14:32 ` [PATCH RFC 1/3] scripts: rockchip: add script to calculate key hash Michael Tretter
2026-01-05 14:32 ` Michael Tretter [this message]
2026-01-05 14:32 ` [PATCH RFC 3/3] commands: implement rksecure command Michael Tretter
2026-01-06  7:33 ` [PATCH RFC 0/3] ARM: rockchip: add rockchip secure boot Sascha Hauer
2026-01-06 13:18 ` Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260105-rockchip-secure-boot-v1-2-eaf5053a7d7e@pengutronix.de \
    --to=m.tretter@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    --cc=s.hauer@pengutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox