⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cryptocop.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id: cryptocop.c,v 1.13 2005/04/21 17:27:55 henriken Exp $ * * Stream co-processor driver for the ETRAX FS * *    Copyright (C) 2003-2005  Axis Communications AB */#include <linux/init.h>#include <linux/sched.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/spinlock.h>#include <linux/stddef.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/atomic.h>#include <linux/list.h>#include <linux/interrupt.h>#include <asm/signal.h>#include <asm/irq.h>#include <asm/arch/dma.h>#include <asm/arch/hwregs/dma.h>#include <asm/arch/hwregs/reg_map.h>#include <asm/arch/hwregs/reg_rdwr.h>#include <asm/arch/hwregs/intr_vect_defs.h>#include <asm/arch/hwregs/strcop.h>#include <asm/arch/hwregs/strcop_defs.h>#include <asm/arch/cryptocop.h>#define DESCR_ALLOC_PAD  (31)struct cryptocop_dma_desc {	char *free_buf; /* If non-null will be kfreed in free_cdesc() */	dma_descr_data *dma_descr;	unsigned char dma_descr_buf[sizeof(dma_descr_data) + DESCR_ALLOC_PAD];	unsigned int from_pool:1; /* If 1 'allocated' from the descriptor pool. */	struct cryptocop_dma_desc *next;};struct cryptocop_int_operation{	void                        *alloc_ptr;	cryptocop_session_id        sid;	dma_descr_context           ctx_out;	dma_descr_context           ctx_in;	/* DMA descriptors allocated by driver. */	struct cryptocop_dma_desc   *cdesc_out;	struct cryptocop_dma_desc   *cdesc_in;	/* Strcop config to use. */	cryptocop_3des_mode         tdes_mode;	cryptocop_csum_type         csum_mode;	/* DMA descrs provided by consumer. */	dma_descr_data              *ddesc_out;	dma_descr_data              *ddesc_in;};struct cryptocop_tfrm_ctx {	cryptocop_tfrm_id tid;	unsigned int blocklength;	unsigned int start_ix;	struct cryptocop_tfrm_cfg *tcfg;	struct cryptocop_transform_ctx *tctx;	unsigned char previous_src;	unsigned char current_src;	/* Values to use in metadata out. */	unsigned char hash_conf;	unsigned char hash_mode;	unsigned char ciph_conf;	unsigned char cbcmode;	unsigned char decrypt;	unsigned int requires_padding:1;	unsigned int strict_block_length:1;	unsigned int active:1;	unsigned int done:1;	size_t consumed;	size_t produced;	/* Pad (input) descriptors to put in the DMA out list when the transform	 * output is put on the DMA in list. */	struct cryptocop_dma_desc *pad_descs;	struct cryptocop_tfrm_ctx *prev_src;	struct cryptocop_tfrm_ctx *curr_src;	/* Mapping to HW. */	unsigned char unit_no;};struct cryptocop_private{	cryptocop_session_id sid;	struct cryptocop_private *next;};/* Session list. */struct cryptocop_transform_ctx{	struct cryptocop_transform_init init;	unsigned char dec_key[CRYPTOCOP_MAX_KEY_LENGTH];	unsigned int dec_key_set:1;	struct cryptocop_transform_ctx *next;};struct cryptocop_session{	cryptocop_session_id sid;	struct cryptocop_transform_ctx *tfrm_ctx;	struct cryptocop_session *next;};/* Priority levels for jobs sent to the cryptocop.  Checksum operations from   kernel have highest priority since TCPIP stack processing must not   be a bottleneck. */typedef enum {	cryptocop_prio_kernel_csum = 0,	cryptocop_prio_kernel = 1,	cryptocop_prio_user = 2,	cryptocop_prio_no_prios = 3} cryptocop_queue_priority;struct cryptocop_prio_queue{	struct list_head jobs;	cryptocop_queue_priority prio;};struct cryptocop_prio_job{	struct list_head node;	cryptocop_queue_priority prio;	struct cryptocop_operation *oper;	struct cryptocop_int_operation *iop;};struct ioctl_job_cb_ctx {	unsigned int processed:1;};static struct cryptocop_session *cryptocop_sessions = NULL;spinlock_t cryptocop_sessions_lock;/* Next Session ID to assign. */static cryptocop_session_id next_sid = 1;/* Pad for checksum. */static const char csum_zero_pad[1] = {0x00};/* Trash buffer for mem2mem operations. */#define MEM2MEM_DISCARD_BUF_LENGTH  (512)static unsigned char mem2mem_discard_buf[MEM2MEM_DISCARD_BUF_LENGTH];/* Descriptor pool. *//* FIXME Tweak this value. */#define CRYPTOCOP_DESCRIPTOR_POOL_SIZE   (100)static struct cryptocop_dma_desc descr_pool[CRYPTOCOP_DESCRIPTOR_POOL_SIZE];static struct cryptocop_dma_desc *descr_pool_free_list;static int descr_pool_no_free;static spinlock_t descr_pool_lock;/* Lock to stop cryptocop to start processing of a new operation. The holder   of this lock MUST call cryptocop_start_job() after it is unlocked. */spinlock_t cryptocop_process_lock;static struct cryptocop_prio_queue cryptocop_job_queues[cryptocop_prio_no_prios];static spinlock_t cryptocop_job_queue_lock;static struct cryptocop_prio_job *cryptocop_running_job = NULL;static spinlock_t running_job_lock;/* The interrupt handler appends completed jobs to this list. The scehduled * tasklet removes them upon sending the response to the crypto consumer. */static struct list_head cryptocop_completed_jobs;static spinlock_t cryptocop_completed_jobs_lock;DECLARE_WAIT_QUEUE_HEAD(cryptocop_ioc_process_wq);/** Local functions. **/static int cryptocop_open(struct inode *, struct file *);static int cryptocop_release(struct inode *, struct file *);static int cryptocop_ioctl(struct inode *inode, struct file *file,			   unsigned int cmd, unsigned long arg);static void cryptocop_start_job(void);static int cryptocop_job_queue_insert(cryptocop_queue_priority prio, struct cryptocop_operation *operation);static int cryptocop_job_setup(struct cryptocop_prio_job **pj, struct cryptocop_operation *operation);static int cryptocop_job_queue_init(void);static void cryptocop_job_queue_close(void);static int create_md5_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length);static int create_sha1_pad(int alloc_flag, unsigned long long hashed_length, char **pad, size_t *pad_length);static int transform_ok(struct cryptocop_transform_init *tinit);static struct cryptocop_session *get_session(cryptocop_session_id sid);static struct cryptocop_transform_ctx *get_transform_ctx(struct cryptocop_session *sess, cryptocop_tfrm_id tid);static void delete_internal_operation(struct cryptocop_int_operation *iop);static void get_aes_decrypt_key(unsigned char *dec_key, const unsigned  char *key, unsigned int keylength);static int init_stream_coprocessor(void);static void __exit exit_stream_coprocessor(void);/*#define LDEBUG*/#ifdef LDEBUG#define DEBUG(s) s#define DEBUG_API(s) sstatic void print_cryptocop_operation(struct cryptocop_operation *cop);static void print_dma_descriptors(struct cryptocop_int_operation *iop);static void print_strcop_crypto_op(struct strcop_crypto_op *cop);static void print_lock_status(void);static void print_user_dma_lists(struct cryptocop_dma_list_operation *dma_op);#define assert(s) do{if (!(s)) panic(#s);} while(0);#else#define DEBUG(s)#define DEBUG_API(s)#define assert(s)#endif/* Transform constants. */#define DES_BLOCK_LENGTH   (8)#define AES_BLOCK_LENGTH   (16)#define MD5_BLOCK_LENGTH   (64)#define SHA1_BLOCK_LENGTH  (64)#define CSUM_BLOCK_LENGTH  (2)#define MD5_STATE_LENGTH   (16)#define SHA1_STATE_LENGTH  (20)/* The device number. */#define CRYPTOCOP_MAJOR    (254)#define CRYPTOCOP_MINOR    (0)const struct file_operations cryptocop_fops = {	.owner =	THIS_MODULE,	.open =		cryptocop_open,	.release =	cryptocop_release,	.ioctl =	cryptocop_ioctl};static void free_cdesc(struct cryptocop_dma_desc *cdesc){	DEBUG(printk("free_cdesc: cdesc 0x%p, from_pool=%d\n", cdesc, cdesc->from_pool));	kfree(cdesc->free_buf);	if (cdesc->from_pool) {		unsigned long int flags;		spin_lock_irqsave(&descr_pool_lock, flags);		cdesc->next = descr_pool_free_list;		descr_pool_free_list = cdesc;		++descr_pool_no_free;		spin_unlock_irqrestore(&descr_pool_lock, flags);	} else {		kfree(cdesc);	}}static struct cryptocop_dma_desc *alloc_cdesc(int alloc_flag){	int use_pool = (alloc_flag & GFP_ATOMIC) ? 1 : 0;	struct cryptocop_dma_desc *cdesc;	if (use_pool) {		unsigned long int flags;		spin_lock_irqsave(&descr_pool_lock, flags);		if (!descr_pool_free_list) {			spin_unlock_irqrestore(&descr_pool_lock, flags);			DEBUG_API(printk("alloc_cdesc: pool is empty\n"));			return NULL;		}		cdesc = descr_pool_free_list;		descr_pool_free_list = descr_pool_free_list->next;		--descr_pool_no_free;		spin_unlock_irqrestore(&descr_pool_lock, flags);		cdesc->from_pool = 1;	} else {		cdesc = kmalloc(sizeof(struct cryptocop_dma_desc), alloc_flag);		if (!cdesc) {			DEBUG_API(printk("alloc_cdesc: kmalloc\n"));			return NULL;		}		cdesc->from_pool = 0;	}	cdesc->dma_descr = (dma_descr_data*)(((unsigned long int)cdesc + offsetof(struct cryptocop_dma_desc, dma_descr_buf) + DESCR_ALLOC_PAD) & ~0x0000001F);	cdesc->next = NULL;	cdesc->free_buf = NULL;	cdesc->dma_descr->out_eop = 0;	cdesc->dma_descr->in_eop = 0;	cdesc->dma_descr->intr = 0;	cdesc->dma_descr->eol = 0;	cdesc->dma_descr->wait = 0;	cdesc->dma_descr->buf = NULL;	cdesc->dma_descr->after = NULL;	DEBUG_API(printk("alloc_cdesc: return 0x%p, cdesc->dma_descr=0x%p, from_pool=%d\n", cdesc, cdesc->dma_descr, cdesc->from_pool));	return cdesc;}static void setup_descr_chain(struct cryptocop_dma_desc *cd){	DEBUG(printk("setup_descr_chain: entering\n"));	while (cd) {		if (cd->next) {			cd->dma_descr->next = (dma_descr_data*)virt_to_phys(cd->next->dma_descr);		} else {			cd->dma_descr->next = NULL;		}		cd = cd->next;	}	DEBUG(printk("setup_descr_chain: exit\n"));}/* Create a pad descriptor for the transform. * Return -1 for error, 0 if pad created. */static int create_pad_descriptor(struct cryptocop_tfrm_ctx *tc, struct cryptocop_dma_desc **pad_desc, int alloc_flag){	struct cryptocop_dma_desc        *cdesc = NULL;	int                              error = 0;	struct strcop_meta_out           mo = {		.ciphsel = src_none,		.hashsel = src_none,		.csumsel = src_none	};	char                             *pad;	size_t                           plen;	DEBUG(printk("create_pad_descriptor: start.\n"));	/* Setup pad descriptor. */	DEBUG(printk("create_pad_descriptor: setting up padding.\n"));	cdesc = alloc_cdesc(alloc_flag);	if (!cdesc){		DEBUG_API(printk("create_pad_descriptor: alloc pad desc\n"));		goto error_cleanup;	}	switch (tc->unit_no) {	case src_md5:		error = create_md5_pad(alloc_flag, tc->consumed, &pad, &plen);		if (error){			DEBUG_API(printk("create_pad_descriptor: create_md5_pad_failed\n"));			goto error_cleanup;		}		cdesc->free_buf = pad;		mo.hashsel = src_dma;		mo.hashconf = tc->hash_conf;		mo.hashmode = tc->hash_mode;		break;	case src_sha1:		error = create_sha1_pad(alloc_flag, tc->consumed, &pad, &plen);		if (error){			DEBUG_API(printk("create_pad_descriptor: create_sha1_pad_failed\n"));			goto error_cleanup;		}		cdesc->free_buf = pad;		mo.hashsel = src_dma;		mo.hashconf = tc->hash_conf;		mo.hashmode = tc->hash_mode;		break;	case src_csum:		if (tc->consumed % tc->blocklength){			pad = (char*)csum_zero_pad;			plen = 1;		} else {			pad = (char*)cdesc; /* Use any pointer. */			plen = 0;		}		mo.csumsel = src_dma;		break;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -