1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * Copyright (C) 2018-2019 Linaro Ltd.
4   */
5  
6  #include <linux/delay.h>
7  #include <linux/of.h>
8  #include <linux/hw_random.h>
9  #include <linux/kernel.h>
10  #include <linux/module.h>
11  #include <linux/slab.h>
12  #include <linux/tee_drv.h>
13  #include <linux/uuid.h>
14  
15  #define DRIVER_NAME "optee-rng"
16  
17  #define TEE_ERROR_HEALTH_TEST_FAIL	0x00000001
18  
19  /*
20   * TA_CMD_GET_ENTROPY - Get Entropy from RNG
21   *
22   * param[0] (inout memref) - Entropy buffer memory reference
23   * param[1] unused
24   * param[2] unused
25   * param[3] unused
26   *
27   * Result:
28   * TEE_SUCCESS - Invoke command success
29   * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
30   * TEE_ERROR_NOT_SUPPORTED - Requested entropy size greater than size of pool
31   * TEE_ERROR_HEALTH_TEST_FAIL - Continuous health testing failed
32   */
33  #define TA_CMD_GET_ENTROPY		0x0
34  
35  /*
36   * TA_CMD_GET_RNG_INFO - Get RNG information
37   *
38   * param[0] (out value) - value.a: RNG data-rate in bytes per second
39   *                        value.b: Quality/Entropy per 1024 bit of data
40   * param[1] unused
41   * param[2] unused
42   * param[3] unused
43   *
44   * Result:
45   * TEE_SUCCESS - Invoke command success
46   * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
47   */
48  #define TA_CMD_GET_RNG_INFO		0x1
49  
50  #define MAX_ENTROPY_REQ_SZ		(4 * 1024)
51  
52  /**
53   * struct optee_rng_private - OP-TEE Random Number Generator private data
54   * @dev:		OP-TEE based RNG device.
55   * @ctx:		OP-TEE context handler.
56   * @session_id:		RNG TA session identifier.
57   * @data_rate:		RNG data rate.
58   * @entropy_shm_pool:	Memory pool shared with RNG device.
59   * @optee_rng:		OP-TEE RNG driver structure.
60   */
61  struct optee_rng_private {
62  	struct device *dev;
63  	struct tee_context *ctx;
64  	u32 session_id;
65  	u32 data_rate;
66  	struct tee_shm *entropy_shm_pool;
67  	struct hwrng optee_rng;
68  };
69  
70  #define to_optee_rng_private(r) \
71  		container_of(r, struct optee_rng_private, optee_rng)
72  
get_optee_rng_data(struct optee_rng_private * pvt_data,void * buf,size_t req_size)73  static size_t get_optee_rng_data(struct optee_rng_private *pvt_data,
74  				 void *buf, size_t req_size)
75  {
76  	int ret = 0;
77  	u8 *rng_data = NULL;
78  	size_t rng_size = 0;
79  	struct tee_ioctl_invoke_arg inv_arg;
80  	struct tee_param param[4];
81  
82  	memset(&inv_arg, 0, sizeof(inv_arg));
83  	memset(&param, 0, sizeof(param));
84  
85  	/* Invoke TA_CMD_GET_ENTROPY function of Trusted App */
86  	inv_arg.func = TA_CMD_GET_ENTROPY;
87  	inv_arg.session = pvt_data->session_id;
88  	inv_arg.num_params = 4;
89  
90  	/* Fill invoke cmd params */
91  	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
92  	param[0].u.memref.shm = pvt_data->entropy_shm_pool;
93  	param[0].u.memref.size = req_size;
94  	param[0].u.memref.shm_offs = 0;
95  
96  	ret = tee_client_invoke_func(pvt_data->ctx, &inv_arg, param);
97  	if ((ret < 0) || (inv_arg.ret != 0)) {
98  		dev_err(pvt_data->dev, "TA_CMD_GET_ENTROPY invoke err: %x\n",
99  			inv_arg.ret);
100  		return 0;
101  	}
102  
103  	rng_data = tee_shm_get_va(pvt_data->entropy_shm_pool, 0);
104  	if (IS_ERR(rng_data)) {
105  		dev_err(pvt_data->dev, "tee_shm_get_va failed\n");
106  		return 0;
107  	}
108  
109  	rng_size = param[0].u.memref.size;
110  	memcpy(buf, rng_data, rng_size);
111  
112  	return rng_size;
113  }
114  
optee_rng_read(struct hwrng * rng,void * buf,size_t max,bool wait)115  static int optee_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
116  {
117  	struct optee_rng_private *pvt_data = to_optee_rng_private(rng);
118  	size_t read = 0, rng_size;
119  	int timeout = 1;
120  	u8 *data = buf;
121  
122  	if (max > MAX_ENTROPY_REQ_SZ)
123  		max = MAX_ENTROPY_REQ_SZ;
124  
125  	while (read < max) {
126  		rng_size = get_optee_rng_data(pvt_data, data, (max - read));
127  
128  		data += rng_size;
129  		read += rng_size;
130  
131  		if (wait && pvt_data->data_rate) {
132  			if ((timeout-- == 0) || (read == max))
133  				return read;
134  			msleep((1000 * (max - read)) / pvt_data->data_rate);
135  		} else {
136  			return read;
137  		}
138  	}
139  
140  	return read;
141  }
142  
optee_rng_init(struct hwrng * rng)143  static int optee_rng_init(struct hwrng *rng)
144  {
145  	struct optee_rng_private *pvt_data = to_optee_rng_private(rng);
146  	struct tee_shm *entropy_shm_pool = NULL;
147  
148  	entropy_shm_pool = tee_shm_alloc_kernel_buf(pvt_data->ctx,
149  						    MAX_ENTROPY_REQ_SZ);
150  	if (IS_ERR(entropy_shm_pool)) {
151  		dev_err(pvt_data->dev, "tee_shm_alloc_kernel_buf failed\n");
152  		return PTR_ERR(entropy_shm_pool);
153  	}
154  
155  	pvt_data->entropy_shm_pool = entropy_shm_pool;
156  
157  	return 0;
158  }
159  
optee_rng_cleanup(struct hwrng * rng)160  static void optee_rng_cleanup(struct hwrng *rng)
161  {
162  	struct optee_rng_private *pvt_data = to_optee_rng_private(rng);
163  
164  	tee_shm_free(pvt_data->entropy_shm_pool);
165  }
166  
167  static struct optee_rng_private pvt_data = {
168  	.optee_rng = {
169  		.name		= DRIVER_NAME,
170  		.init		= optee_rng_init,
171  		.cleanup	= optee_rng_cleanup,
172  		.read		= optee_rng_read,
173  	}
174  };
175  
get_optee_rng_info(struct device * dev)176  static int get_optee_rng_info(struct device *dev)
177  {
178  	int ret = 0;
179  	struct tee_ioctl_invoke_arg inv_arg;
180  	struct tee_param param[4];
181  
182  	memset(&inv_arg, 0, sizeof(inv_arg));
183  	memset(&param, 0, sizeof(param));
184  
185  	/* Invoke TA_CMD_GET_RNG_INFO function of Trusted App */
186  	inv_arg.func = TA_CMD_GET_RNG_INFO;
187  	inv_arg.session = pvt_data.session_id;
188  	inv_arg.num_params = 4;
189  
190  	/* Fill invoke cmd params */
191  	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT;
192  
193  	ret = tee_client_invoke_func(pvt_data.ctx, &inv_arg, param);
194  	if ((ret < 0) || (inv_arg.ret != 0)) {
195  		dev_err(dev, "TA_CMD_GET_RNG_INFO invoke err: %x\n",
196  			inv_arg.ret);
197  		return -EINVAL;
198  	}
199  
200  	pvt_data.data_rate = param[0].u.value.a;
201  	pvt_data.optee_rng.quality = param[0].u.value.b;
202  
203  	return 0;
204  }
205  
optee_ctx_match(struct tee_ioctl_version_data * ver,const void * data)206  static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
207  {
208  	if (ver->impl_id == TEE_IMPL_ID_OPTEE)
209  		return 1;
210  	else
211  		return 0;
212  }
213  
optee_rng_probe(struct device * dev)214  static int optee_rng_probe(struct device *dev)
215  {
216  	struct tee_client_device *rng_device = to_tee_client_device(dev);
217  	int ret = 0, err = -ENODEV;
218  	struct tee_ioctl_open_session_arg sess_arg;
219  
220  	memset(&sess_arg, 0, sizeof(sess_arg));
221  
222  	/* Open context with TEE driver */
223  	pvt_data.ctx = tee_client_open_context(NULL, optee_ctx_match, NULL,
224  					       NULL);
225  	if (IS_ERR(pvt_data.ctx))
226  		return -ENODEV;
227  
228  	/* Open session with hwrng Trusted App */
229  	export_uuid(sess_arg.uuid, &rng_device->id.uuid);
230  	sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
231  	sess_arg.num_params = 0;
232  
233  	ret = tee_client_open_session(pvt_data.ctx, &sess_arg, NULL);
234  	if ((ret < 0) || (sess_arg.ret != 0)) {
235  		dev_err(dev, "tee_client_open_session failed, err: %x\n",
236  			sess_arg.ret);
237  		err = -EINVAL;
238  		goto out_ctx;
239  	}
240  	pvt_data.session_id = sess_arg.session;
241  
242  	err = get_optee_rng_info(dev);
243  	if (err)
244  		goto out_sess;
245  
246  	err = devm_hwrng_register(dev, &pvt_data.optee_rng);
247  	if (err) {
248  		dev_err(dev, "hwrng registration failed (%d)\n", err);
249  		goto out_sess;
250  	}
251  
252  	pvt_data.dev = dev;
253  
254  	return 0;
255  
256  out_sess:
257  	tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
258  out_ctx:
259  	tee_client_close_context(pvt_data.ctx);
260  
261  	return err;
262  }
263  
optee_rng_remove(struct device * dev)264  static int optee_rng_remove(struct device *dev)
265  {
266  	tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
267  	tee_client_close_context(pvt_data.ctx);
268  
269  	return 0;
270  }
271  
272  static const struct tee_client_device_id optee_rng_id_table[] = {
273  	{UUID_INIT(0xab7a617c, 0xb8e7, 0x4d8f,
274  		   0x83, 0x01, 0xd0, 0x9b, 0x61, 0x03, 0x6b, 0x64)},
275  	{}
276  };
277  
278  MODULE_DEVICE_TABLE(tee, optee_rng_id_table);
279  
280  static struct tee_client_driver optee_rng_driver = {
281  	.id_table	= optee_rng_id_table,
282  	.driver		= {
283  		.name		= DRIVER_NAME,
284  		.bus		= &tee_bus_type,
285  		.probe		= optee_rng_probe,
286  		.remove		= optee_rng_remove,
287  	},
288  };
289  
optee_rng_mod_init(void)290  static int __init optee_rng_mod_init(void)
291  {
292  	return driver_register(&optee_rng_driver.driver);
293  }
294  
optee_rng_mod_exit(void)295  static void __exit optee_rng_mod_exit(void)
296  {
297  	driver_unregister(&optee_rng_driver.driver);
298  }
299  
300  module_init(optee_rng_mod_init);
301  module_exit(optee_rng_mod_exit);
302  
303  MODULE_LICENSE("GPL v2");
304  MODULE_AUTHOR("Sumit Garg <sumit.garg@linaro.org>");
305  MODULE_DESCRIPTION("OP-TEE based random number generator driver");
306