Skip to content

Commit f0c8431

Browse files
jenswi-linarostorulf
authored andcommitted
optee: probe RPMB device using RPMB subsystem
Adds support in the OP-TEE drivers (both SMC and FF-A ABIs) to probe and use an RPMB device via the RPMB subsystem instead of passing the RPMB frames via tee-supplicant in user space. A fallback mechanism is kept to route RPMB frames via tee-supplicant if the RPMB subsystem isn't available. The OP-TEE RPC ABI is extended to support iterating over all RPMB devices until one is found with the expected RPMB key already programmed. Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org> Tested-by: Manuel Traut <manut@mecka.net> Reviewed-by: Sumit Garg <sumit.garg@linaro.org> Link: https://lore.kernel.org/r/20240814153558.708365-5-jens.wiklander@linaro.org Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
1 parent c30b855 commit f0c8431

File tree

11 files changed

+387
-2
lines changed

11 files changed

+387
-2
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
What: /sys/class/tee/tee{,priv}X/rpmb_routing_model
2+
Date: May 2024
3+
KernelVersion: 6.10
4+
Contact: op-tee@lists.trustedfirmware.org
5+
Description:
6+
RPMB frames can be routed to the RPMB device via the
7+
user-space daemon tee-supplicant or the RPMB subsystem
8+
in the kernel. The value "user" means that the driver
9+
will route the RPMB frames via user space. Conversely,
10+
"kernel" means that the frames are routed via the RPMB
11+
subsystem without assistance from tee-supplicant. It
12+
should be assumed that RPMB frames are routed via user
13+
space if the variable is absent. The primary purpose
14+
of this variable is to let systemd know whether
15+
tee-supplicant is needed in the early boot with initramfs.

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22458,6 +22458,7 @@ M: Jens Wiklander <jens.wiklander@linaro.org>
2245822458
R: Sumit Garg <sumit.garg@linaro.org>
2245922459
L: op-tee@lists.trustedfirmware.org
2246022460
S: Maintained
22461+
F: Documentation/ABI/testing/sysfs-class-tee
2246122462
F: Documentation/driver-api/tee.rst
2246222463
F: Documentation/tee/
2246322464
F: Documentation/userspace-api/tee.rst

drivers/tee/optee/core.c

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,85 @@
1010
#include <linux/errno.h>
1111
#include <linux/io.h>
1212
#include <linux/module.h>
13+
#include <linux/rpmb.h>
1314
#include <linux/slab.h>
1415
#include <linux/string.h>
1516
#include <linux/tee_core.h>
1617
#include <linux/types.h>
1718
#include "optee_private.h"
1819

20+
struct blocking_notifier_head optee_rpmb_intf_added =
21+
BLOCKING_NOTIFIER_INIT(optee_rpmb_intf_added);
22+
23+
static int rpmb_add_dev(struct device *dev)
24+
{
25+
blocking_notifier_call_chain(&optee_rpmb_intf_added, 0,
26+
to_rpmb_dev(dev));
27+
28+
return 0;
29+
}
30+
31+
static struct class_interface rpmb_class_intf = {
32+
.add_dev = rpmb_add_dev,
33+
};
34+
35+
void optee_bus_scan_rpmb(struct work_struct *work)
36+
{
37+
struct optee *optee = container_of(work, struct optee,
38+
rpmb_scan_bus_work);
39+
int ret;
40+
41+
if (!optee->rpmb_scan_bus_done) {
42+
ret = optee_enumerate_devices(PTA_CMD_GET_DEVICES_RPMB);
43+
optee->rpmb_scan_bus_done = !ret;
44+
if (ret && ret != -ENODEV)
45+
pr_info("Scanning for RPMB device: ret %d\n", ret);
46+
}
47+
}
48+
49+
int optee_rpmb_intf_rdev(struct notifier_block *intf, unsigned long action,
50+
void *data)
51+
{
52+
struct optee *optee = container_of(intf, struct optee, rpmb_intf);
53+
54+
schedule_work(&optee->rpmb_scan_bus_work);
55+
56+
return 0;
57+
}
58+
1959
static void optee_bus_scan(struct work_struct *work)
2060
{
2161
WARN_ON(optee_enumerate_devices(PTA_CMD_GET_DEVICES_SUPP));
2262
}
2363

64+
static ssize_t rpmb_routing_model_show(struct device *dev,
65+
struct device_attribute *attr, char *buf)
66+
{
67+
struct optee *optee = dev_get_drvdata(dev);
68+
const char *s;
69+
70+
if (optee->in_kernel_rpmb_routing)
71+
s = "kernel";
72+
else
73+
s = "user";
74+
75+
return scnprintf(buf, PAGE_SIZE, "%s\n", s);
76+
}
77+
static DEVICE_ATTR_RO(rpmb_routing_model);
78+
79+
static struct attribute *optee_dev_attrs[] = {
80+
&dev_attr_rpmb_routing_model.attr,
81+
NULL
82+
};
83+
84+
ATTRIBUTE_GROUPS(optee_dev);
85+
86+
void optee_set_dev_group(struct optee *optee)
87+
{
88+
tee_device_set_dev_groups(optee->teedev, optee_dev_groups);
89+
tee_device_set_dev_groups(optee->supp_teedev, optee_dev_groups);
90+
}
91+
2492
int optee_open(struct tee_context *ctx, bool cap_memref_null)
2593
{
2694
struct optee_context_data *ctxdata;
@@ -97,6 +165,9 @@ void optee_release_supp(struct tee_context *ctx)
97165

98166
void optee_remove_common(struct optee *optee)
99167
{
168+
blocking_notifier_chain_unregister(&optee_rpmb_intf_added,
169+
&optee->rpmb_intf);
170+
cancel_work_sync(&optee->rpmb_scan_bus_work);
100171
/* Unregister OP-TEE specific client devices on TEE bus */
101172
optee_unregister_devices();
102173

@@ -113,13 +184,18 @@ void optee_remove_common(struct optee *optee)
113184
tee_shm_pool_free(optee->pool);
114185
optee_supp_uninit(&optee->supp);
115186
mutex_destroy(&optee->call_queue.mutex);
187+
rpmb_dev_put(optee->rpmb_dev);
188+
mutex_destroy(&optee->rpmb_dev_mutex);
116189
}
117190

118191
static int smc_abi_rc;
119192
static int ffa_abi_rc;
193+
static bool intf_is_regged;
120194

121195
static int __init optee_core_init(void)
122196
{
197+
int rc;
198+
123199
/*
124200
* The kernel may have crashed at the same time that all available
125201
* secure world threads were suspended and we cannot reschedule the
@@ -130,18 +206,36 @@ static int __init optee_core_init(void)
130206
if (is_kdump_kernel())
131207
return -ENODEV;
132208

209+
if (IS_REACHABLE(CONFIG_RPMB)) {
210+
rc = rpmb_interface_register(&rpmb_class_intf);
211+
if (rc)
212+
return rc;
213+
intf_is_regged = true;
214+
}
215+
133216
smc_abi_rc = optee_smc_abi_register();
134217
ffa_abi_rc = optee_ffa_abi_register();
135218

136219
/* If both failed there's no point with this module */
137-
if (smc_abi_rc && ffa_abi_rc)
220+
if (smc_abi_rc && ffa_abi_rc) {
221+
if (IS_REACHABLE(CONFIG_RPMB)) {
222+
rpmb_interface_unregister(&rpmb_class_intf);
223+
intf_is_regged = false;
224+
}
138225
return smc_abi_rc;
226+
}
227+
139228
return 0;
140229
}
141230
module_init(optee_core_init);
142231

143232
static void __exit optee_core_exit(void)
144233
{
234+
if (IS_REACHABLE(CONFIG_RPMB) && intf_is_regged) {
235+
rpmb_interface_unregister(&rpmb_class_intf);
236+
intf_is_regged = false;
237+
}
238+
145239
if (!smc_abi_rc)
146240
optee_smc_abi_unregister();
147241
if (!ffa_abi_rc)

drivers/tee/optee/device.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ static int get_devices(struct tee_context *ctx, u32 session,
4343
ret = tee_client_invoke_func(ctx, &inv_arg, param);
4444
if ((ret < 0) || ((inv_arg.ret != TEEC_SUCCESS) &&
4545
(inv_arg.ret != TEEC_ERROR_SHORT_BUFFER))) {
46+
/*
47+
* TEE_ERROR_STORAGE_NOT_AVAILABLE is returned when getting
48+
* the list of device TAs that depends on RPMB but a usable
49+
* RPMB device isn't found.
50+
*/
51+
if (inv_arg.ret == TEE_ERROR_STORAGE_NOT_AVAILABLE)
52+
return -ENODEV;
4653
pr_err("PTA_CMD_GET_DEVICES invoke function err: %x\n",
4754
inv_arg.ret);
4855
return -EINVAL;

drivers/tee/optee/ffa_abi.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <linux/arm_ffa.h>
99
#include <linux/errno.h>
10+
#include <linux/rpmb.h>
1011
#include <linux/scatterlist.h>
1112
#include <linux/sched.h>
1213
#include <linux/slab.h>
@@ -909,6 +910,10 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
909910
optee->ffa.bottom_half_value = U32_MAX;
910911
optee->rpc_param_count = rpc_param_count;
911912

913+
if (IS_REACHABLE(CONFIG_RPMB) &&
914+
(sec_caps & OPTEE_FFA_SEC_CAP_RPMB_PROBE))
915+
optee->in_kernel_rpmb_routing = true;
916+
912917
teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool,
913918
optee);
914919
if (IS_ERR(teedev)) {
@@ -925,6 +930,8 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
925930
}
926931
optee->supp_teedev = teedev;
927932

933+
optee_set_dev_group(optee);
934+
928935
rc = tee_device_register(optee->teedev);
929936
if (rc)
930937
goto err_unreg_supp_teedev;
@@ -940,6 +947,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
940947
optee_cq_init(&optee->call_queue, 0);
941948
optee_supp_init(&optee->supp);
942949
optee_shm_arg_cache_init(optee, arg_cache_flags);
950+
mutex_init(&optee->rpmb_dev_mutex);
943951
ffa_dev_set_drvdata(ffa_dev, optee);
944952
ctx = teedev_open(optee->teedev);
945953
if (IS_ERR(ctx)) {
@@ -961,6 +969,10 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
961969
if (rc)
962970
goto err_unregister_devices;
963971

972+
INIT_WORK(&optee->rpmb_scan_bus_work, optee_bus_scan_rpmb);
973+
optee->rpmb_intf.notifier_call = optee_rpmb_intf_rdev;
974+
blocking_notifier_chain_register(&optee_rpmb_intf_added,
975+
&optee->rpmb_intf);
964976
pr_info("initialized driver\n");
965977
return 0;
966978

@@ -974,6 +986,8 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
974986
teedev_close_context(ctx);
975987
err_rhashtable_free:
976988
rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL);
989+
rpmb_dev_put(optee->rpmb_dev);
990+
mutex_destroy(&optee->rpmb_dev_mutex);
977991
optee_supp_uninit(&optee->supp);
978992
mutex_destroy(&optee->call_queue.mutex);
979993
mutex_destroy(&optee->ffa.mutex);

drivers/tee/optee/optee_ffa.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@
9292
#define OPTEE_FFA_SEC_CAP_ARG_OFFSET BIT(0)
9393
/* OP-TEE supports asynchronous notification via FF-A */
9494
#define OPTEE_FFA_SEC_CAP_ASYNC_NOTIF BIT(1)
95+
/* OP-TEE supports probing for RPMB device if needed */
96+
#define OPTEE_FFA_SEC_CAP_RPMB_PROBE BIT(2)
9597

9698
#define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2)
9799

drivers/tee/optee/optee_private.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
#define OPTEE_PRIVATE_H
88

99
#include <linux/arm-smccc.h>
10+
#include <linux/notifier.h>
1011
#include <linux/rhashtable.h>
12+
#include <linux/rpmb.h>
1113
#include <linux/semaphore.h>
1214
#include <linux/tee_core.h>
1315
#include <linux/types.h>
@@ -20,6 +22,7 @@
2022
/* Some Global Platform error codes used in this driver */
2123
#define TEEC_SUCCESS 0x00000000
2224
#define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006
25+
#define TEEC_ERROR_ITEM_NOT_FOUND 0xFFFF0008
2326
#define TEEC_ERROR_NOT_SUPPORTED 0xFFFF000A
2427
#define TEEC_ERROR_COMMUNICATION 0xFFFF000E
2528
#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C
@@ -28,6 +31,7 @@
2831

2932
/* API Return Codes are from the GP TEE Internal Core API Specification */
3033
#define TEE_ERROR_TIMEOUT 0xFFFF3001
34+
#define TEE_ERROR_STORAGE_NOT_AVAILABLE 0xF0100003
3135

3236
#define TEEC_ORIGIN_COMMS 0x00000002
3337

@@ -200,6 +204,12 @@ struct optee_ops {
200204
* @notif: notification synchronization struct
201205
* @supp: supplicant synchronization struct for RPC to supplicant
202206
* @pool: shared memory pool
207+
* @mutex: mutex protecting @rpmb_dev
208+
* @rpmb_dev: current RPMB device or NULL
209+
* @rpmb_scan_bus_done flag if device registation of RPMB dependent devices
210+
* was already done
211+
* @rpmb_scan_bus_work workq to for an RPMB device and to scan optee bus
212+
* and register RPMB dependent optee drivers
203213
* @rpc_param_count: If > 0 number of RPC parameters to make room for
204214
* @scan_bus_done flag if device registation was already done.
205215
* @scan_bus_work workq to scan optee bus and register optee drivers
@@ -218,9 +228,16 @@ struct optee {
218228
struct optee_notif notif;
219229
struct optee_supp supp;
220230
struct tee_shm_pool *pool;
231+
/* Protects rpmb_dev pointer */
232+
struct mutex rpmb_dev_mutex;
233+
struct rpmb_dev *rpmb_dev;
234+
struct notifier_block rpmb_intf;
221235
unsigned int rpc_param_count;
222-
bool scan_bus_done;
236+
bool scan_bus_done;
237+
bool rpmb_scan_bus_done;
238+
bool in_kernel_rpmb_routing;
223239
struct work_struct scan_bus_work;
240+
struct work_struct rpmb_scan_bus_work;
224241
};
225242

226243
struct optee_session {
@@ -253,6 +270,8 @@ struct optee_call_ctx {
253270
size_t num_entries;
254271
};
255272

273+
extern struct blocking_notifier_head optee_rpmb_intf_added;
274+
256275
int optee_notif_init(struct optee *optee, u_int max_key);
257276
void optee_notif_uninit(struct optee *optee);
258277
int optee_notif_wait(struct optee *optee, u_int key, u32 timeout);
@@ -283,9 +302,14 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session);
283302

284303
#define PTA_CMD_GET_DEVICES 0x0
285304
#define PTA_CMD_GET_DEVICES_SUPP 0x1
305+
#define PTA_CMD_GET_DEVICES_RPMB 0x2
286306
int optee_enumerate_devices(u32 func);
287307
void optee_unregister_devices(void);
308+
void optee_bus_scan_rpmb(struct work_struct *work);
309+
int optee_rpmb_intf_rdev(struct notifier_block *intf, unsigned long action,
310+
void *data);
288311

312+
void optee_set_dev_group(struct optee *optee);
289313
void optee_remove_common(struct optee *optee);
290314
int optee_open(struct tee_context *ctx, bool cap_memref_null);
291315
void optee_release(struct tee_context *ctx);

drivers/tee/optee/optee_rpc_cmd.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,39 @@
104104
/* I2C master control flags */
105105
#define OPTEE_RPC_I2C_FLAGS_TEN_BIT BIT(0)
106106

107+
/*
108+
* Reset RPMB probing
109+
*
110+
* Releases an eventually already used RPMB devices and starts over searching
111+
* for RPMB devices. Returns the kind of shared memory to use in subsequent
112+
* OPTEE_RPC_CMD_RPMB_PROBE_NEXT and OPTEE_RPC_CMD_RPMB calls.
113+
*
114+
* [out] value[0].a OPTEE_RPC_SHM_TYPE_*, the parameter for
115+
* OPTEE_RPC_CMD_SHM_ALLOC
116+
*/
117+
#define OPTEE_RPC_CMD_RPMB_PROBE_RESET 22
118+
119+
/*
120+
* Probe next RPMB device
121+
*
122+
* [out] value[0].a Type of RPMB device, OPTEE_RPC_RPMB_*
123+
* [out] value[0].b EXT CSD-slice 168 "RPMB Size"
124+
* [out] value[0].c EXT CSD-slice 222 "Reliable Write Sector Count"
125+
* [out] memref[1] Buffer with the raw CID
126+
*/
127+
#define OPTEE_RPC_CMD_RPMB_PROBE_NEXT 23
128+
129+
/* Type of RPMB device */
130+
#define OPTEE_RPC_RPMB_EMMC 0
131+
#define OPTEE_RPC_RPMB_UFS 1
132+
#define OPTEE_RPC_RPMB_NVME 2
133+
134+
/*
135+
* Replay Protected Memory Block access
136+
*
137+
* [in] memref[0] Frames to device
138+
* [out] memref[1] Frames from device
139+
*/
140+
#define OPTEE_RPC_CMD_RPMB_FRAMES 24
141+
107142
#endif /*__OPTEE_RPC_CMD_H*/

drivers/tee/optee/optee_smc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ struct optee_smc_get_shm_config_result {
278278
#define OPTEE_SMC_SEC_CAP_ASYNC_NOTIF BIT(5)
279279
/* Secure world supports pre-allocating RPC arg struct */
280280
#define OPTEE_SMC_SEC_CAP_RPC_ARG BIT(6)
281+
/* Secure world supports probing for RPMB device if needed */
282+
#define OPTEE_SMC_SEC_CAP_RPMB_PROBE BIT(7)
281283

282284
#define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9
283285
#define OPTEE_SMC_EXCHANGE_CAPABILITIES \

0 commit comments

Comments
 (0)