blob: d16aea089044e0a2b49ede57e65aeb5eaf465731 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001#include <linux/module.h>
2#include <linux/slab.h>
3#include <linux/err.h>
4#include <linux/clk-provider.h>
5#include <linux/clk.h>
6#include <linux/io.h>
7#include <linux/hw_random.h>
8#include <linux/platform_device.h>
9#include <linux/of_device.h>
10#include <linux/mutex.h>
11#include <linux/device.h>
12#include <linux/init.h>
13#include <linux/delay.h>
14#include <asm/uaccess.h>
15#include <uapi/linux/hwrsa_ioctl.h>
16#ifdef CONFIG_TEE
17#include <linux/tee_drv.h>
18#endif
19
20#include "asr-te200-optee.h"
21#include "asr-rsa-optee.h"
22
23static struct teec_uuid pta_rsa_uuid = ASR_RSA_ACCESS_UUID;
24
25static int asr_optee_rsa_sign(struct hwrsa_arg *rsa_arg, u_int cmd)
26{
27 struct tee_ioctl_invoke_arg invoke_arg;
28 struct tee_param params[4];
29 struct asrte200_tee_context asrte200_tee_ctx;
30 struct tee_shm *shm;
31 int ret = 0;
32 char *ma = NULL;
33 struct rsa_ioctl_key *key = rsa_arg->rsa_key;
34 uint8_t *n = key->n, *e = key->e, *d = key->d, *p = key->p, *q= key->q;
35 size_t n_size = key->n_size, e_size = key->e_size, d_size = key->d_size;
36 size_t p_size = key->p_size, q_size = key->q_size;
37 uint8_t *msg = rsa_arg->msg, *sign = rsa_arg->sign;
38 size_t msg_size = rsa_arg->msg_size, sign_size = key->n_size;
39 int is_blinding;
40 u_int optee_cmd;
41
42 switch (cmd) {
43 case HWRSA_SIGN_PKCS_V15_SHA1:
44 optee_cmd = CMD_RSA_SIGN_PKCS_V15_SHA1;
45 break;
46 case HWRSA_SIGN_PKCS_V15_SHA256:
47 optee_cmd = CMD_RSA_SIGN_PKCS_V15_SHA256;
48 break;
49 case HWRSA_SIGN_PKCS_V21_SHA1:
50 optee_cmd = CMD_RSA_SIGN_PKCS_V21_SHA1;
51 break;
52 case HWRSA_SIGN_PKCS_V21_SHA256:
53 optee_cmd = CMD_RSA_SIGN_PKCS_V21_SHA256;
54 break;
55 default:
56 ret = -EINVAL;
57 goto exit;
58 }
59
60 if (!p || !q || !p_size || !q_size) {
61 is_blinding = 0;
62 } else {
63 is_blinding = 1;
64 }
65
66 ret = asrte200_optee_open_ta(&asrte200_tee_ctx, &pta_rsa_uuid);
67 if (ret != 0) {
68 return ret;
69 }
70
71 memset(&invoke_arg, 0x0, sizeof(struct tee_ioctl_invoke_arg));
72 invoke_arg.func = optee_cmd;
73 invoke_arg.session = asrte200_tee_ctx.session;
74
75 if (is_blinding) {
76 shm = tee_shm_alloc(asrte200_tee_ctx.tee_ctx,
77 n_size + e_size + d_size + p_size + q_size + msg_size + sign_size,
78 TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
79 } else {
80 shm = tee_shm_alloc(asrte200_tee_ctx.tee_ctx,
81 n_size + e_size + d_size + msg_size + sign_size,
82 TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
83 }
84 if (!shm) {
85 ret = -EINVAL;
86 goto exit;
87 }
88
89 ma = tee_shm_get_va(shm, 0);
90 memcpy(ma, n, n_size);
91 memcpy(ma + n_size, e, e_size);
92 memcpy(ma + n_size + e_size, d, d_size);
93 if (is_blinding) {
94 memcpy(ma + n_size + e_size + d_size, p, p_size);
95 memcpy(ma + n_size + e_size + d_size + q_size, q, q_size);
96 }
97
98 /* import rsa key */
99 params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
100 params[0].u.memref.shm_offs = 0;
101 if (is_blinding) {
102 params[0].u.memref.size = n_size + e_size + d_size + p_size + q_size;
103 } else {
104 params[0].u.memref.size = n_size + e_size + d_size;
105 }
106 params[0].u.memref.shm = shm;
107
108 params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
109 params[1].u.value.a = 0;
110 params[1].u.value.a |= n_size;
111 params[1].u.value.a |= e_size << 10;
112 params[1].u.value.a |= d_size << 20;
113 params[1].u.value.a |= is_blinding << 30;
114 if (is_blinding) {
115 params[1].u.value.b = 0;
116 params[1].u.value.b |= p_size;
117 params[1].u.value.b |= q_size << 10;
118 }
119
120 /* import message */
121 params[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
122 if (is_blinding) {
123 memcpy(ma + n_size + e_size + d_size + p_size + q_size, msg, msg_size);
124 params[2].u.memref.shm_offs = n_size + e_size + d_size + p_size + q_size;
125 } else {
126 memcpy(ma + n_size + e_size + d_size, msg, msg_size);
127 params[2].u.memref.shm_offs = n_size + e_size + d_size;
128 }
129 params[2].u.memref.size = msg_size;
130 params[2].u.memref.shm = shm;
131
132 /* import signature */
133 params[3].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
134 if (is_blinding) {
135 params[3].u.memref.shm_offs = n_size + e_size + d_size + p_size + q_size + msg_size;
136 } else {
137 params[3].u.memref.shm_offs = n_size + e_size + d_size + msg_size;
138 }
139 params[3].u.memref.size = sign_size;
140 params[3].u.memref.shm = shm;
141
142 invoke_arg.num_params = 4;
143
144 ret = tee_client_invoke_func(asrte200_tee_ctx.tee_ctx, &invoke_arg, params);
145 if (ret != 0) {
146 rsa_arg->result = 0;
147 } else if (invoke_arg.ret != 0) {
148 rsa_arg->result = 0;
149 goto free_shm;
150 }
151
152 rsa_arg->result = 1;
153
154 if (is_blinding) {
155 memcpy(sign, ma + n_size + e_size + d_size + p_size + q_size + msg_size, sign_size);
156 } else {
157 memcpy(sign, ma + n_size + e_size + d_size + msg_size, sign_size);
158 }
159
160free_shm:
161 tee_shm_free(shm);
162exit:
163 asrte200_optee_close_ta(&asrte200_tee_ctx);
164 return ret;
165}
166
167static int asr_optee_rsa_verify(struct hwrsa_arg *rsa_arg, u_int cmd)
168{
169 struct tee_ioctl_invoke_arg invoke_arg;
170 struct tee_param params[4];
171 struct asrte200_tee_context asrte200_tee_ctx;
172 struct tee_shm *shm;
173 int ret = 0;
174 char *ma = NULL;
175 struct rsa_ioctl_key *key = rsa_arg->rsa_key;
176 uint8_t *n = key->n, *e = key->e;
177 size_t n_size = key->n_size, e_size = key->e_size;
178 uint8_t *msg = rsa_arg->msg, *sign = rsa_arg->sign;
179 size_t msg_size = rsa_arg->msg_size, sign_size = rsa_arg->sign_size;
180 u_int optee_cmd;
181
182 switch (cmd) {
183 case HWRSA_VERIFY_PKCS_V15_SHA1:
184 optee_cmd = CMD_RSA_VERIFY_PKCS_V15_SHA1;
185 break;
186 case HWRSA_VERIFY_PKCS_V15_SHA256:
187 optee_cmd = CMD_RSA_VERIFY_PKCS_V15_SHA256;
188 break;
189 case HWRSA_VERIFY_PKCS_V21_SHA1:
190 optee_cmd = CMD_RSA_VERIFY_PKCS_V21_SHA1;
191 break;
192 case HWRSA_VERIFY_PKCS_V21_SHA256:
193 optee_cmd = CMD_RSA_VERIFY_PKCS_V21_SHA256;
194 break;
195 default:
196 ret = -EINVAL;
197 goto exit;
198 }
199
200 ret = asrte200_optee_open_ta(&asrte200_tee_ctx, &pta_rsa_uuid);
201 if (ret != 0) {
202 return ret;
203 }
204
205 memset(&invoke_arg, 0x0, sizeof(struct tee_ioctl_invoke_arg));
206 invoke_arg.func = optee_cmd;
207 invoke_arg.session = asrte200_tee_ctx.session;
208
209 shm = tee_shm_alloc(asrte200_tee_ctx.tee_ctx,
210 n_size + e_size + msg_size + sign_size,
211 TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
212
213 if (!shm) {
214 ret = -EINVAL;
215 goto exit;
216 }
217
218 ma = tee_shm_get_va(shm, 0);
219 memcpy(ma, n, n_size);
220 memcpy(ma + n_size, e, e_size);
221
222 /* import rsa key */
223 params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
224 params[0].u.memref.shm_offs = 0;
225 params[0].u.memref.size = n_size + e_size;
226 params[0].u.memref.shm = shm;
227
228 /* import msg */
229 memcpy(ma + n_size + e_size, msg, msg_size);
230 params[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
231 params[1].u.memref.shm_offs = n_size + e_size;
232 params[1].u.memref.size = msg_size;
233 params[1].u.memref.shm = shm;
234
235 /* import sign */
236 memcpy(ma + n_size + e_size + msg_size, sign, sign_size);
237 params[2].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
238 params[2].u.memref.shm_offs = n_size + e_size + msg_size;
239 params[2].u.memref.size = sign_size;
240 params[2].u.memref.shm = shm;
241
242 params[3].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
243 params[3].u.value.a = n_size;
244
245 invoke_arg.num_params = 4;
246
247 ret = tee_client_invoke_func(asrte200_tee_ctx.tee_ctx, &invoke_arg, params);
248 if (ret != 0) {
249 rsa_arg->result = 0;
250 goto free_shm;
251 } else if (invoke_arg.ret != 0) {
252 rsa_arg->result = 0;
253 goto free_shm;
254 }
255
256 rsa_arg->result = 1;
257
258free_shm:
259 tee_shm_free(shm);
260exit:
261 asrte200_optee_close_ta(&asrte200_tee_ctx);
262 return ret;
263}
264
265static int asr_rsa_open(struct inode *inode, struct file *file)
266{
267 return 0;
268}
269
270static int asr_rsa_close(struct inode *inode, struct file *file)
271{
272 return 0;
273}
274
275static long asr_rsa_ioctl(struct file *file, u_int cmd, u_long arg)
276{
277 int ret = 0;
278 struct miscdevice *miscdev;
279 struct asr_te200_rsa *rsa;
280 struct hwrsa_arg rsa_arg;
281 struct rsa_ioctl_key *key;
282 struct hwrsa_arg *u_arg = (void __user *)arg;
283
284 miscdev = file->private_data;
285 rsa = container_of(miscdev, struct asr_te200_rsa, rsa_misc);
286
287 if (copy_from_user(&rsa_arg, (void __user *)arg, sizeof(rsa_arg))) {
288 return -EFAULT;
289 }
290
291 key = rsa_arg.rsa_key;
292
293 if (!rsa_arg.rsa_key) {
294 return -EFAULT;
295 }
296
297 if (!rsa_arg.msg || !rsa_arg.msg_size) {
298 return -EFAULT;
299 }
300
301 switch (cmd) {
302 case HWRSA_SIGN_PKCS_V15_SHA1:
303 case HWRSA_SIGN_PKCS_V15_SHA256:
304 case HWRSA_SIGN_PKCS_V21_SHA1:
305 case HWRSA_SIGN_PKCS_V21_SHA256:
306 if (!rsa_arg.sign || !key->is_private) {
307 ret = -EINVAL;
308 goto exit;
309 }
310 ret = asr_optee_rsa_sign(&rsa_arg, cmd);
311 put_user(rsa_arg.result, &u_arg->result);
312 break;
313 case HWRSA_VERIFY_PKCS_V15_SHA1:
314 case HWRSA_VERIFY_PKCS_V15_SHA256:
315 case HWRSA_VERIFY_PKCS_V21_SHA1:
316 case HWRSA_VERIFY_PKCS_V21_SHA256:
317 if (!rsa_arg.sign || !rsa_arg.sign_size || key->is_private) {
318 ret = -EINVAL;
319 goto exit;
320 }
321 ret = asr_optee_rsa_verify(&rsa_arg, cmd);
322 put_user(rsa_arg.result, &u_arg->result);
323 break;
324 default:
325 dev_err(rsa->dev, "asr te200: rsa iotcl invald command %x\n", cmd);
326 ret = -EINVAL;
327 goto exit;
328 }
329
330exit:
331 return ret;
332}
333
334static const struct file_operations asr_rsa_fops = {
335 .owner = THIS_MODULE,
336 .open = asr_rsa_open,
337 .release = asr_rsa_close,
338 .unlocked_ioctl = asr_rsa_ioctl,
339};
340
341int asr_te200_rsa_register(struct asr_te200_dev *te200_dd)
342{
343 int ret = 0;
344 struct asr_te200_rsa *prsa;
345 struct miscdevice *misc;
346 struct device *dev = te200_dd->dev;
347
348 prsa = &te200_dd->asr_rsa;
349 misc = &prsa->rsa_misc;
350
351 misc->name = "hwrsa";
352 misc->minor = MISC_DYNAMIC_MINOR;
353 misc->fops = &asr_rsa_fops;
354 misc->this_device = NULL;
355 prsa->dev = te200_dd->dev;
356
357 /* register the device */
358 ret = misc_register(misc);
359 if (ret < 0) {
360 dev_err(dev,
361 "asr rsa: unable to register device node /dev/hwrsa\n");
362 return ret;
363 }
364
365 return 0;
366}
367EXPORT_SYMBOL_GPL(asr_te200_rsa_register);
368
369int asr_te200_rsa_unregister(struct asr_te200_dev *te200_dd)
370{
371 struct miscdevice *miscdev;
372
373 miscdev = &te200_dd->asr_rsa.rsa_misc;
374
375 misc_deregister(miscdev);
376
377 return 0;
378}
379EXPORT_SYMBOL_GPL(asr_te200_rsa_unregister);
380
381MODULE_LICENSE("GPL");
382MODULE_AUTHOR("Yonggan Wang <yongganwang@asrmicro.com>");
383MODULE_DESCRIPTION("ASR hwrsa driver");