1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include <linux/proc_fs.h>
20 #include <linux/module.h>
21 #include <linux/signal.h>
22 #include <linux/spinlock.h>
23 #include <linux/personality.h>
24 #include <linux/ptrace.h>
25 #include <linux/kallsyms.h>
26 #include <linux/init.h>
27 #include <linux/pci.h>
28 #include <linux/seq_file.h>
29 #include <linux/version.h>
30 #include <linux/sched.h>
31 #include <linux/interrupt.h>
32 #include <linux/mm_types.h>
33 #include <linux/mm.h>
34 #include <asm/atomic.h>
35 #include <asm/cacheflush.h>
36 #include <asm/io.h>
37 #include <asm/uaccess.h>
38 #include <asm/unistd.h>
39 #include <asm/traps.h>
40 #include <linux/miscdevice.h>
41 #include <linux/delay.h>
42 #include <linux/of_device.h>
43 #include "drv_osal_lib.h"
44 #include "drv_symc.h"
45 #include "drv_hash.h"
46
47 #ifdef KAPI_TEST_SUPPORT
48 #include "kapi_symc_test.h"
49 #endif
50
51 #define CIPHER_PROC_NAME "driver/hi_cipher"
52
53 /* ****************************** API Code **************************** */
54 #if (1 == HI_PROC_SUPPORT)
symc_proc_read(struct seq_file * p,hi_void * v)55 hi_s32 symc_proc_read(struct seq_file *p, hi_void *v)
56 {
57 symc_chn_status *status = HI_NULL;
58 hi_u32 i;
59 hi_s32 ret;
60
61 if ((p == HI_NULL) || (v == HI_NULL)) {
62 hi_log_error("Invalid point!\n");
63 return HI_ERR_CIPHER_INVALID_POINT;
64 }
65
66 seq_printf(p, "\n------------------------------------------"
67 "CIPHER STATUS-------------------------------"
68 "--------------------------------------------"
69 "--------------------\n");
70 seq_printf(p, "Chnid Status Decrypt Alg Mode KeyLen "
71 "Addr in/out KeyFrom INT-RAW in/out INT-EN "
72 "in/out INT_OCNTCFG IVOUT\n");
73
74 status = (symc_chn_status *)crypto_calloc(CRYPTO_HARD_CHANNEL_MAX, sizeof(symc_chn_status));
75 if (status == HI_NULL) {
76 return HI_ERR_CIPHER_FAILED_MEM;
77 }
78
79 for (i = 0; i < CRYPTO_HARD_CHANNEL_MAX; i++) {
80 status[i].id = i;
81 }
82
83 ret = drv_symc_proc_status(status);
84 if (ret != HI_SUCCESS) {
85 CRYPTO_PROC_PRINT(p, "CIPHER_ProcGetStatus failed!\n");
86 crypto_free(status);
87 status = NULL;
88 return ret;
89 }
90
91 for (i = 0; i < CRYPTO_HARD_CHANNEL_MAX; i++) {
92 CRYPTO_PROC_PRINT(p, " %u %s %u %s %s %03d %08x/%08x "
93 "%s %u/%u %u/%u %08x %s\n",
94 i,
95 status[i].open, status[i].decrypt, status[i].alg,
96 status[i].mode, status[i].klen, status[i].inaddr,
97 status[i].outaddr, status[i].ksrc, status[i].inraw,
98 status[i].outraw, status[i].inten, status[i].outen,
99 status[i].outintcnt, status[i].iv);
100 }
101
102 #ifdef KAPI_TEST_SUPPORT
103 kapi_test_main();
104 #endif
105
106 crypto_free(status);
107 status = NULL;
108
109 return HI_SUCCESS;
110 }
111
symc_proc_open(struct inode * inode,struct file * file)112 static int symc_proc_open(struct inode *inode, struct file *file)
113 {
114 crypto_unused(inode);
115 return single_open(file, symc_proc_read, NULL);
116 }
117
118 #if LINUX_VERSION_CODE > KERNEL_VERSION(5,6,0)
119 static const struct proc_ops g_drv_cipher_proc_fops = {
120 .proc_open = symc_proc_open,
121 .proc_read = seq_read,
122 .proc_lseek = seq_lseek,
123 .proc_release = single_release,
124 };
125 #else
126 static const struct file_operations g_drv_cipher_proc_fops = {
127 .owner = THIS_MODULE,
128 .open = symc_proc_open,
129 .read = seq_read,
130 .llseek = seq_lseek,
131 .release = single_release,
132 };
133 #endif
134
symc_proc_init(hi_void)135 static hi_void symc_proc_init(hi_void)
136 {
137 struct proc_dir_entry *proc_entry = HI_NULL;
138
139 proc_entry = proc_create(CIPHER_PROC_NAME, 0, NULL, &g_drv_cipher_proc_fops);
140 if (proc_entry == NULL) {
141 hi_log_error("cipher: can't create %s.\n", CIPHER_PROC_NAME);
142 }
143 }
144
symc_proc_deinit(hi_void)145 static hi_void symc_proc_deinit(hi_void)
146 {
147 remove_proc_entry(CIPHER_PROC_NAME, NULL);
148 }
149 #endif /* ****** proc function end ******* */
150
hi_cipher_open(struct inode * inode,struct file * file)151 static hi_s32 hi_cipher_open(struct inode *inode, struct file *file)
152 {
153 crypto_unused(inode);
154 crypto_unused(file);
155 if ((!capable(CAP_SYS_RAWIO)) || (!capable(CAP_SYS_ADMIN))) {
156 return -EPERM;
157 }
158 return HI_SUCCESS;
159 }
160
hi_cipher_ioctl(struct file * ffile,unsigned int cmd,unsigned long arg)161 static long hi_cipher_ioctl(struct file *ffile, unsigned int cmd, unsigned long arg)
162 {
163 long ret;
164 hi_u8 cmd_param[CRYPTO_CMD_PARAM_SIZE] = {0};
165
166 if ((ffile == HI_NULL) || (ffile->f_path.dentry == HI_NULL) || (arg == 0x00)) {
167 hi_log_error("Invalid cmd param size!\n");
168 return HI_ERR_CIPHER_INVALID_POINT;
169 }
170
171 if (_IOC_SIZE(cmd) > sizeof(cmd_param)) {
172 hi_log_error("Invalid cmd param size %d!\n", _IOC_SIZE(cmd));
173 return HI_ERR_CIPHER_INVALID_PARAM;
174 }
175
176 if (((crypto_ioc_dir(cmd) == CRYPTO_IOC_W) || (crypto_ioc_dir(cmd) == CRYPTO_IOC_RW)) && (_IOC_SIZE(cmd) != 0)) {
177 ret = crypto_copy_from_user((hi_void *)cmd_param, CRYPTO_CMD_PARAM_SIZE,
178 (void __user *)(hi_uintptr_t)arg, _IOC_SIZE(cmd));
179 if (ret != HI_SUCCESS) {
180 hi_log_error("copy data from user failed, ret:0x%lx!\n", ret);
181 return HI_ERR_CIPHER_INVALID_PARAM;
182 }
183 }
184
185 ret = crypto_ioctl(cmd, (hi_void *)cmd_param);
186 if (ret != HI_SUCCESS) {
187 hi_log_error("crypto_ioctl failed, ret:0x%lx!\n", ret);
188 return ret;
189 }
190
191 if (((crypto_ioc_dir(cmd) == CRYPTO_IOC_R) || (crypto_ioc_dir(cmd) == CRYPTO_IOC_RW)) && (_IOC_SIZE(cmd) != 0)) {
192 ret = crypto_copy_to_user((hi_void __user *)(hi_uintptr_t)arg, _IOC_SIZE(cmd),
193 (const hi_void *)cmd_param, _IOC_SIZE(cmd));
194 if (ret != HI_SUCCESS) {
195 hi_log_error("copy data to user fail, ret:0x%lx!\n", ret);
196 return HI_ERR_CIPHER_INVALID_PARAM;
197 }
198 }
199 return HI_SUCCESS;
200 }
201
hi_cipher_release(struct inode * inode,struct file * file)202 static hi_s32 hi_cipher_release(struct inode *inode, struct file *file)
203 {
204 crypto_unused(inode);
205 crypto_unused(file);
206 return crypto_release();
207 }
208
209 static struct file_operations g_dev_cipher_fops = {
210 .owner = THIS_MODULE,
211 .open = hi_cipher_open,
212 .unlocked_ioctl = hi_cipher_ioctl,
213 #ifdef CONFIG_COMPAT
214 .compat_ioctl = hi_cipher_ioctl,
215 #endif
216 .release = hi_cipher_release,
217 };
218
219 static struct miscdevice g_cipher_dev = {
220 .minor = MISC_DYNAMIC_MINOR,
221 .name = UMAP_DEVNAME_CIPHER,
222 .fops = &g_dev_cipher_fops,
223 };
224
cipher_get_device(hi_void)225 hi_void *cipher_get_device(hi_void)
226 {
227 return (hi_void *)g_cipher_dev.this_device;
228 }
229
cipher_drv_mod_init(hi_void)230 hi_s32 cipher_drv_mod_init(hi_void)
231 {
232 hi_s32 ret;
233 struct device *dev = HI_NULL;
234
235 if (misc_register(&g_cipher_dev)) {
236 hi_log_error("ERROR: could not register cipher devices\n");
237 return HI_ERR_CIPHER_ILLEGAL_DATA;
238 }
239
240 /* should set bool force_dma in Kernel 4.19.
241 * Whether device is to be set up by of_dma_configure() even if DMA capability
242 * is not explicitly described by firmware.
243 */
244 dev = g_cipher_dev.this_device;
245 dev->dma_mask = &dev->coherent_dma_mask;
246 ret = of_dma_configure(dev, dev->of_node, HI_TRUE);
247 if (ret != HI_SUCCESS) {
248 hi_log_print_func_err(of_dma_configure, ret);
249 misc_deregister(&g_cipher_dev);
250 return ret;
251 }
252
253 ret = crypto_entry();
254 if (ret != HI_SUCCESS) {
255 misc_deregister(&g_cipher_dev);
256 return ret;
257 }
258
259 /* ****** proc function begin ******* */
260 #if (1 == HI_PROC_SUPPORT)
261 symc_proc_init();
262 #endif /* ****** proc function end ******* */
263
264 #ifdef MODULE
265 HI_PRINT("load hi_cipher.ko ....OK!\n");
266 #endif
267
268 return HI_SUCCESS;
269 }
270
cipher_drv_mod_exit(void)271 void cipher_drv_mod_exit(void)
272 {
273 /* ****** proc function begin ******* */
274 #if (1 == HI_PROC_SUPPORT)
275 symc_proc_deinit();
276 #endif /* ****** proc function end ******* */
277 misc_deregister(&g_cipher_dev);
278 crypto_exit();
279
280 #ifdef MODULE
281 HI_PRINT("unload hi_cipher.ko ....OK!\n");
282 #endif
283 }
284