• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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