阅读:1952回复:6
就freeswan的硬件加密的第二桶水
hifn7811中 Cryptolib.c
/************************************************ Cryptolib.c Cryptographic front end. *************************************************/ #include <linux/kernel.h> #include <linux/module.h> #include <linux/if_crypto.h> #include <linux/slab.h> #include <linux/errno.h> #include <linux/random.h> #include <linux/init.h> /* S/W crypto includes */ #include <openssl/rc4.h> #include <linux/des.h> #include <linux/md5.h> #include <linux/sha1.h> #define ENGINE_MAX 5 #ifndef TRUE #define TRUE (1==1) #define FALSE !TRUE #endif static struct crypto_engine_def *engine_db[ENGINE_MAX]; struct crypto_request *crypto_alloc_request(int flags) { struct crypto_request *req; req = kmalloc(sizeof(struct crypto_request),flags); if(req == NULL) return NULL; memset(req,0,sizeof(struct crypto_request)); return req; } struct crypto_engine_def *crypto_open_engine(crypto_cmd_t cap,unsigned int attrib) { struct crypto_engine_def *eng; int t; for(t=0;t<ENGINE_MAX;t++) { eng = engine_db[t]; if(eng == NULL) continue; if((cap & eng->capability) == cap && (attrib & eng->attributes) == attrib) { if(eng->open != NULL) eng->open(); return eng; } } return NULL; } void crypto_close_engine(struct crypto_engine_def *eng) { if(eng != NULL && eng->close != NULL) eng->close(); } #define BASIC_CMDS (CRYPT_RC4|CRYPT_DES|CRYPT_3DES|CRYPT_MD5|CRYPT_SHA|CRYPT_RANDOM) int crypto_execute(struct crypto_request *req) { struct crypto_engine_def *eng; int t,ret; if(req != NULL) { if(req->engine == NULL) { for(t=0;t<ENGINE_MAX;t++) { eng = engine_db[t]; if(eng == NULL) continue; /* Engines are sorted in performance order, take first one that matches */ if((req->op.cmd & eng->capability) == (req->op.cmd & BASIC_CMDS)) break; } } else eng = req->engine; if(eng != NULL && eng->request_handler != NULL) { ret = eng->request_handler(req); if(ret == CRYPT_READY && req->callback != NULL) req->callback(req); return ret; } } return CRYPT_ERROR; } int crypto_query(crypto_cmd_t cap,unsigned int attrib) { struct crypto_engine_def *eng; int t; for(t=0;t<ENGINE_MAX;t++) { eng = engine_db[t]; if(eng == NULL) continue; if((cap & eng->capability) == cap && (attrib & eng->attributes) == attrib) return TRUE; } return FALSE; } int crypto_register_engine(struct crypto_engine_def *eng) { int t,r; struct crypto_engine_def **slot = NULL; if(eng == NULL || eng->name == NULL) return -EINVAL; eng->capability &= BASIC_CMDS; for(t=0;t<ENGINE_MAX;t++) { /* Put S/W last, H/W first */ if(eng->attributes & IS_HARDWARE) r = (ENGINE_MAX-1) - t; else r = t; if(engine_db[r] == NULL) { slot = &engine_db[r]; } else { if(strcmp(eng->name,engine_db[r]->name) == 0) return -EEXIST; } } if(slot == NULL) return -EMFILE; *slot = eng; printk(KERN_INFO \"Crypto engine %s registered\\n\",eng->name); return 0; } int crypto_unregister_engine(char *name) { int t; for(t=0;t<ENGINE_MAX;t++) { if(engine_db[t] != NULL && strcmp(engine_db[t]->name,name) == 0) { printk(KERN_INFO \"Crypto engine %s unregistered\\n\",engine_db[t]->name); engine_db[t] = NULL; return 0; } } return -ENOENT; } /*************************************************** * S/W crypto engine ****************************************************/ static inline int do_hmac(struct crypto_request *req,struct crypto_operation *op) { unsigned char digest[20]; int hash_len,i; MD5_CTX md5_ctx; SHA1_CTX sha1_ctx; unsigned char k_ipad[65]; /* inner padding - * key XORd with ipad */ unsigned char k_opad[65]; /* outer padding - * key XORd with opad */ /* start out by storing key in pads */ memset(k_ipad, 0, sizeof k_ipad); memset(k_opad, 0, sizeof k_opad); memcpy(k_ipad, op->u.hash.hmac_key,op->u.hash.hmac_key_len); memcpy(k_opad, op->u.hash.hmac_key,op->u.hash.hmac_key_len); /* XOR key with ipad and opad values */ for (i=0; i<64; i++) { k_ipad ^= 0x36; k_opad ^= 0x5c; } if(op->cmd & CRYPT_MD5) { /* * perform inner MD5 */ hash_len = 16; MD5Init(&md5_ctx); /* init md5_ctx for 1st * pass */ MD5Update(&md5_ctx, k_ipad, 64); /* start with inner pad */ MD5Update(&md5_ctx, &req->outbuf[op->offset], op->len); /* then text of datagram */ MD5Final(digest, &md5_ctx); /* finish up 1st pass */ /* * perform outer MD5 */ MD5Init(&md5_ctx); /* init md5_ctx for 2nd * pass */ MD5Update(&md5_ctx, k_opad, 64); /* start with outer pad */ MD5Update(&md5_ctx, digest, 16); /* then results of 1st * hash */ MD5Final(digest, &md5_ctx); /* finish up 2nd pass */ } else if(op->cmd & CRYPT_SHA) { hash_len = 20; SHA1Init(&sha1_ctx); /* init sha1_ctx for 1st * pass */ SHA1Update(&sha1_ctx, k_ipad, 64); /* start with inner pad */ SHA1Update(&sha1_ctx, &req->outbuf[op->offset], op->len); /* then text of datagram */ SHA1Final(digest, &sha1_ctx); /* finish up 1st pass */ /* * perform outer */ SHA1Init(&sha1_ctx); /* init sha1_ctx for 2nd * pass */ SHA1Update(&sha1_ctx, k_opad, 64); /* start with outer pad */ SHA1Update(&sha1_ctx, digest, 20); /* then results of 1st * hash */ SHA1Final(digest, &sha1_ctx); /* finish up 2nd pass */ } if(op->cmd & CRYPT_96) { hash_len = 96/8; /* Truncate digest */ } if(op->cmd & CRYPT_APPEND) { if(req->outlen < (req->inlen + hash_len)) return CRYPT_ERROR; memcpy(req->outbuf + req->inlen, digest, hash_len); req->outlen = req->inlen + hash_len; } if(req->outlen < hash_len) return CRYPT_ERROR; memcpy(op->u.hash.result, digest, hash_len); op->u.hash.reslen= hash_len; return CRYPT_READY; } static inline int do_regular_hash(struct crypto_request *req,struct crypto_operation *op) { unsigned char digest[20]; int hash_len; MD5_CTX md5_ctx; SHA1_CTX sha1_ctx; if(op->cmd & CRYPT_MD5) { hash_len = 16; MD5Init(&md5_ctx); MD5Update(&md5_ctx, &req->outbuf[op->offset], op->len); MD5Final(digest, &md5_ctx); } else if(op->cmd & CRYPT_SHA) { hash_len = 20; SHA1Init(&sha1_ctx); SHA1Update(&sha1_ctx, &req->outbuf[op->offset], op->len); /* then text of datagram */ SHA1Final(digest, &sha1_ctx); /* finish up 1st pass */ } if(op->cmd & CRYPT_96) { hash_len = 96/8; /* Truncate digest */ } if(op->cmd & CRYPT_APPEND) { if(req->outlen < (req->inlen + hash_len)) return CRYPT_ERROR; memcpy(req->outbuf + req->inlen, digest, hash_len); req->outlen = req->inlen + hash_len; } memcpy(op->u.hash.result, digest, hash_len); op->u.hash.reslen= hash_len; return CRYPT_READY; } static int sw_request_handler(struct crypto_request *req) { unsigned char *in, *out; int t,ret,maxout,reslen=0; struct crypto_operation *op; maxout = req->outlen; if(req->outlen < req->inlen) return CRYPT_ERROR; if(req->inbuf != NULL && req->inbuf != req->outbuf) memcpy(req->outbuf,req->inbuf,req->inlen); for(op = &req->op;op != NULL;op=op->next) { in = &req->outbuf[op->offset]; out = &req->outbuf[op->offset]; if(op->cmd & CRYPT_RANDOM) { get_random_bytes(req->outbuf,req->outlen); reslen = req->outlen; break; /* Should be the only real operation... */ } if(op->cmd & CRYPT_RC4) { RC4_KEY key; if(maxout < req->inlen || req->op.u.rc4.key == NULL) return CRYPT_ERROR; RC4_set_key(&key,op->u.rc4.key->len,op->u.rc4.key->raw); RC4(&key,op->len,in,out); req->outlen = req->inlen; } if(op->cmd & CRYPT_DES) { /* To do */ return CRYPT_ERROR; } if(op->cmd & CRYPT_3DES) { if(maxout < req->inlen) return CRYPT_ERROR; if(op->cmd & CRYPT_CBC) { des_key_schedule sched[3]; des_cblock ivec; memcpy(&ivec, op->u.des.ivec, 8); for(t=0;t<3;t++) des_set_key(&(op->u.des.key[t]),sched[t]); des_ede3_cbc_encrypt((des_cblock*)in,(des_cblock*)out,op->len,sched[0],sched[1],sched[2] ,&ivec,(op->cmd & CRYPT_DECODE)?0:1); req->outlen = req->inlen; } if(op->cmd & CRYPT_ECB) { /* Todo */ return CRYPT_ERROR; } } if(op->cmd & (CRYPT_MD5|CRYPT_SHA)) { if(op->cmd & CRYPT_HMAC) { ret = do_hmac(req,op); if(ret != CRYPT_READY) return ret; } else { ret = do_regular_hash(req,op); if(ret != CRYPT_READY) return ret; } } reslen = req->outlen > reslen? req->outlen: reslen; req->outlen = maxout; } req->outlen = reslen; req->flags |= CRYPT_SOFTWARE; return CRYPT_READY; } /****** RANDOM NUMBERS HANDLING HERE ********/ static struct wait_queue *crypto_random_read_wait; struct random_priv { ssize_t nbytes,count; char *buf; }; static void crypto_random_callback(struct crypto_request *req) { struct random_priv *rp = (struct random_priv *) req->priv; rp->count += req->outlen; rp->buf += req->outlen; rp->nbytes -= req->outlen; crypto_free_request(req); wake_up_interruptible(&crypto_random_read_wait); } static ssize_t crypto_random_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos) { struct wait_queue wait = { current, NULL }; ssize_t n, retval = 0; struct crypto_request *req; struct random_priv rpriv; if (nbytes == 0) return 0; rpriv.nbytes = nbytes; rpriv.count = 0; rpriv.buf = buf; add_wait_queue(&crypto_random_read_wait, &wait); current->state = TASK_INTERRUPTIBLE; n = rpriv.nbytes; if (file->f_flags & O_NONBLOCK) { return -EAGAIN; } if (signal_pending(current)) { return -ERESTARTSYS; } /* Go and get random data */ req = crypto_alloc_request(GFP_KERNEL); req->op.cmd = CRYPT_RANDOM; req->op.offset = 0; req->op.len = n; req->inbuf = NULL; req->inlen = 0; req->outlen = n; req->outbuf = rpriv.buf; req->flags = 0; req->callback = crypto_random_callback; req->priv = (void*) &rpriv; crypto_execute(req); schedule(); current->state = TASK_RUNNING; remove_wait_queue(&crypto_random_read_wait, &wait); /* * If we gave the user some bytes, update the access time. */ if (rpriv.count != 0) { UPDATE_ATIME(file->f_dentry->d_inode); } return (rpriv.count ? rpriv.count : retval); } static struct file_operations crypto_random_fops = { #if LINUX_VERSION_CODE >= 0x20300 /* Someone knows when these made their debut? */ owner: THIS_MODULE, #endif read: crypto_random_read /* read */ }; static void __init crypto_random_init(void) { if (register_chrdev(121, \"crypto_random\", &crypto_random_fops)) { printk(KERN_NOTICE \"Can\'t allocate major number 121 for random.\\n\"); } } static struct crypto_engine_def sw_def = { name : \"S/W\", capability: (CRYPT_RC4|CRYPT_DES|CRYPT_3DES|CRYPT_MD5|CRYPT_SHA), attributes: IS_SOFTWARE | IS_SYNC, request_handler: sw_request_handler }; int __init crypto_init(void) { crypto_register_engine(&sw_def); crypto_random_init(); return 0; } #ifdef MODULE mod_exit_t crypto_cleanup (void) { crypto_unregister_engine(sw.def.name); } module_exit(crypto_cleanup); #endif //#if LINUX_VERSION_CODE > 0x20300 module_init(crypto_init); //#endif |
|
|
沙发#
发布于:2002-06-21 13:14
hifn7811.c 驱动程序
/****************************************************************************/ /* * hifn7811.c -- Driver for Hi/fn 7811 encryption engine. * * (C) Copyright 2001, Colubris Networks, Inc (sources.colubris.com) * (C) Copyright 2000, Lineo, Inc (www.lineo.com) * (C) Copyright 2000, Greg Ungerer (gerg@lineo.com) * * History: * - Major modifications by Martin Gadbois (Colubris Networks Inc.) Almost no original code remains from * initial release from Lineo. * * * This program is a part of the Linux kernel, and may be freely * copied under the terms of the GNU General Public License (GPL), * version 2, or at your option any later version. */ /****************************************************************************/ #include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/fs.h> #include <linux/mm.h> #include <linux/interrupt.h> #include <linux/string.h> #include <linux/module.h> #include <linux/init.h> #include <linux/smp_lock.h> #include <linux/slab.h> #include <linux/tqueue.h> #include <linux/proc_fs.h> #include <linux/timer.h> #include <linux/if_crypto.h> #include <linux/pci.h> #include <asm/io.h> #include <asm/system.h> #include <asm/delay.h> #include <asm/irq.h> #include <asm/bitops.h> #include <asm/processor.h> #include <asm/cache.h> #include \"hifn7811.h\" /*********i386*************************/ #define flush_dcache_range(a,b) #define invalidate_dcache_range(a,b) /***********************************/ /* Borrow a BH for our usage... */ #define HIFN_BH RISCOM8_BH /* Won\'t be needing this... Must be < NET_BH */ #define hifn7811_memcpyto(dst,src,len) memcpy((void *)dst,src,len) #define hifn7811_memcpyfrom hifn7811_memcpyto #define MGTEST #define PRINT_USAGE #define SMAX 1024 #undef TRACING #ifdef DEBUG #define SIG_ON(req) if(req->flags & CRYPT_DATA) { cn1000_BSCR_biton(BCSR0_LED_POWEROFF); } #define SIG_OFF(req) if(req->flags & CRYPT_DATA) { cn1000_BSCR_bitoff(BCSR0_LED_POWEROFF); } #else #define SIG_ON(req) #define SIG_OFF(req) #endif #define SIG_MARK(req) SIG_OFF(req) SIG_ON(req) static int disable = 0; /* Set to 1 while loading module to start task */ static int always = 1; /* Set to 1 to force HW only, to 2 to force SW only */ MODULE_PARM(disable, \"i\"); MODULE_PARM(always, \"i\"); /* Set to 1 to force H/W */ static DECLARE_WAIT_QUEUE_HEAD(hifn_wait); /* Local prototype */ static void hifn7811_interrupt(int, void *, struct pt_regs *); static void hifn7811_bh(void); static int process_hw_crypto(void); static int hw_crypto_request_fnc(struct crypto_request *req); #define HIFN_INC_PTR(h,f,type) h->f##type++; if(h->f##type->cmd & HIFN7811_DESC_JUMP) h->f##type = &h->desc->f[0] #define P(code) code; mb() /* Protect code (similar to writel() but I\'m lazy) */ #define FUNC_IN(h) /* printk(\"Entering %s GS=%x\\n\",__FUNCTION__,read_pci(h->grp1->global_status)) */ #define FUNC_OUT(h) /* printk(\"Leaving %s GS=%x\\n\",__FUNCTION__,read_pci(h->grp1->global_status)) */ struct HIFN_ALLOC { unsigned int alloc_map; unsigned int group[32]; unsigned char *mem; } hifn_mem; #define HIFN_BLOCK_SIZE (PAGE_SIZE/(sizeof(unsigned int /* hifn_mem.alloc_map */)*8)) struct xreq { struct crypto_request *req; struct hifn7811cmd *cmdp; char *resp; struct timeval in_time; char hash_len; struct xreq *next,*prev; } dummy[3],*to_crypt,*in_hifn,*to_crypt_high; struct HIFN_DESCRIPTORS { struct hifn7811desc cmd[HIFN7811_DESCR_CNT+1]; struct hifn7811desc src[HIFN7811_DESCR_CNT+1]; struct hifn7811desc res[HIFN7811_DESCR_CNT+1]; struct hifn7811desc dst[HIFN7811_DESCR_CNT+1]; }; char hifn_in_use = 0; struct HIFN_GLOBAL { /* Statistics */ volatile unsigned int ints; unsigned int bh,req,inq,cb,sw,hw,retry; /* Various stats */ unsigned int deepness,max,process_time; unsigned char dev_dst_index,dev_res_index; unsigned char normal_in_hifn; /* Number of low-priority in in_hifn queue */ struct timeval usage_time,usage_start,start; /* Duplicate, for debugging only */ char *hifn_in_use; struct xreq *to_crypt,*in_hifn; /* PCI info structs */ struct pci_dev *pci_dev; volatile struct hifn7811grp0 *grp0; volatile struct hifn7811grp1 *grp1; unsigned char myirq; dma_addr_t pci_ring_base; /* Contains the PCI address of *desc */ /* Descriptors */ volatile struct HIFN_DESCRIPTORS *desc; volatile struct hifn7811desc *cmdPtr,*srcPtr,*resPtr,*dstPtr; volatile struct hifn7811desc *resDone,*dstDone; unsigned char slotin,slotout; struct timer_list timer; } hifn; #if defined(TRACING) && defined(CONFIG_8xx) #define BIT_ON(bit) set_tracing(get_tracing() | (1<<bit)) #define BIT_OFF(bit) set_tracing(get_tracing() & ~(1<<bit)) #define BIT_MARK(bit) do { char _c = get_tracing(); set_tracing(_c ^ (1<<bit)); set_tracing(_c ^ (1<<bit)); } while(0) #include <asm/8xx_immap.h> void tracing_setup(void) { volatile immap_t *imp; imp = (immap_t *)IMAP_ADDR; imp->im_cpm.cp_pbpar &= ~0xc0; /* Set PB24-25 to I/O */ imp->im_cpm.cp_pbdir |= 0xc0; /* Set PB24-25 to Output */ imp->im_cpm.cp_pbodr &= ~0xc0; /* Set PB24-25 to General output */ } char get_tracing(void) { volatile immap_t *imp; imp = (immap_t *)IMAP_ADDR; return (imp->im_cpm.cp_pbdat & 0xc0) >> 6; } char set_tracing(char m) { volatile immap_t *imp; char c; imp = (immap_t *)IMAP_ADDR; c = m & 0x3; imp->im_cpm.cp_pbdat = (imp->im_cpm.cp_pbdat & ~0xc0) | (c << 6); return c; } #else #define BIT_ON(bit) #define BIT_OFF(bit) #define BIT_MARK(bit) #endif #ifdef PRINT_USAGE /* Calc arg1 - arg2 */ static inline struct timeval timeval_diff(struct timeval *arg1, struct timeval *arg2) { struct timeval diff; int carry_sec=0,carry_usec=0; if(arg2->tv_usec > arg1->tv_usec) { carry_sec = -1; carry_usec = 1000000; } diff.tv_sec = arg1->tv_sec + carry_sec - arg2->tv_sec; diff.tv_usec = arg1->tv_usec + carry_usec - arg2->tv_usec; return diff; } /* Calc arg1 + arg2 */ static inline struct timeval timeval_add(struct timeval *arg1, struct timeval *arg2) { struct timeval add; add.tv_sec = arg1->tv_sec + arg2->tv_sec; add.tv_usec = arg1->tv_usec + arg2->tv_usec; add.tv_sec += add.tv_usec/1000000; add.tv_usec %= 1000000; return add; } void start_usage(struct HIFN_GLOBAL *h) { do_gettimeofday(&h->usage_start); } void stop_usage(struct HIFN_GLOBAL *h) { struct timeval now,usage; if(h->usage_start.tv_sec == 0) return; do_gettimeofday(&now); usage = timeval_diff(&now,&h->usage_start); h->usage_time = timeval_add(&h->usage_time,&usage); memset(&h->usage_start,0,sizeof(h->usage_start)); } #else #define start_usage(h) do { } while(0) #define stop_usage(h) do { } while(0) #endif /* PRINT_USAGE */ /* Q prototype */ typedef struct xreq qhead; void put_queue(qhead *q,struct xreq *item); struct xreq *get_queue(qhead *q); inline void re_queue(qhead *q,struct xreq *item); void put_queue(qhead *q,struct xreq *i) { unsigned long flags; save_flags(flags); cli(); i->next = q->next; i->prev = q; q->next->prev = i; q->next = i; restore_flags(flags); return; } struct xreq *get_queue(qhead *q) { struct xreq *i; unsigned long flags; if(q->prev == q) { return NULL; } save_flags(flags); cli(); i = q->prev; q->prev = i->prev; i->prev->next = i->next; restore_flags(flags); i->next = i->prev = NULL; return i; } inline void re_queue(qhead *q,struct xreq *item) { put_queue(q->prev,item); } inline struct xreq *peek_queue(qhead *q) { if(q->prev == q) return NULL; return q->prev; } /* Simple alloc functions, to allocate internal HiFn memory. */ inline void *hifn_alloc(int size) { int t; unsigned long pattern; char blocks; // printk(\"Alloc %u size\\n\",size); size = (size + (HIFN_BLOCK_SIZE-1)) & ~(HIFN_BLOCK_SIZE-1); /*Round up */ blocks = size/HIFN_BLOCK_SIZE; pattern = (1<<blocks) -1; for(t=0;t<(32-blocks);t++) { if((hifn_mem.alloc_map & pattern) == 0) { /* Found section with all pattern bits 0 */ hifn_mem.alloc_map |= pattern; hifn_mem.group[t] = pattern; //printk(\"map: 0x%x group %u = 0x%x\\n\",hifn_mem.alloc_map,t,pattern); return (void*) &(hifn_mem.mem[t*HIFN_BLOCK_SIZE]); } pattern <<= 1; } printk(\"Alloc failed map: 0x%x asking for %u blocks\\n\",hifn_mem.alloc_map,blocks); return NULL; } inline void hifn_free(void *ptr) { int index; if(ptr == NULL) return; index = ((unsigned int) ptr - (unsigned int)hifn_mem.mem)/HIFN_BLOCK_SIZE; if(index >= 32 || index < 0) { printk(KERN_DEBUG \"Free: Bad %x [%x]\\n\",ptr,index); return; } if((hifn_mem.alloc_map & hifn_mem.group[index]) != hifn_mem.group[index]) { printk(KERN_DEBUG \"Free: Not alloc\'d %x Free-> %x\\n\",hifn_mem.alloc_map,hifn_mem.group[index]); } hifn_mem.alloc_map &= ~hifn_mem.group[index]; // printk(\"Free Index %u, pattern 0x%x, map=%x\\n\",index,hifn_mem.group[index],hifn_mem.alloc_map); hifn_mem.group[index] = 0; return; } #if 1 #define read_pci(a) readl(&(a)) #define write_pci(a,v) do { volatile unsigned int dummy; \\ /* printk(\"Writing %x at %x\\n\",v,a); */ \\ writel(v,a); dummy=readl(a); } while(0) #else static inline u32 read_pci(u32 a) { #if 0 u32 r = (((a)>>24) | (((a)>>8)&0xff00) | (((a)<<8)&0xff0000) | ((a)<<24)); rmb(); return r; #endif rmb(); return a; } static inline void write_pci(u32 *addr,u32 a) { *addr = read_pci(a); printk(\"Writing %x at %x\\n\",a,addr); wmb(); } #endif static kmem_cache_t *xreq_cache = NULL; static inline struct xreq *hifn_alloc_xreq(void) { return kmem_cache_alloc(xreq_cache,GFP_ATOMIC); } static inline void hifn_free_xreq(struct xreq *xreq) { kmem_cache_free(xreq_cache,xreq); } #ifdef MGTEST static void hifn7811_RC4_set_key(RC4_KEY_HW *key, int len, const unsigned char *data) { /* Use key->data as a char array, key->x as the length and key->y as a flag to see if the key was changed. */ unsigned char *rc4key; int t; memcpy(key->raw,data,len); key->len = len; #if 0 rc4key = (unsigned char *)key->data; for(t=0;t<256;t+=len) memcpy(rc4key+t,data,(256-t)<len?256-t:len); rc4key[256] = rc4key[257] = rc4key[258] = rc4key[259] = 0; key->y = 1; key->x = 260; #endif } #endif #define HIFN7811_TEST #ifdef HIFN7811_TEST static int bench = 0; /* Set to 1 while loading module to start task */ MODULE_PARM(bench, \"i\"); static int debug = 0; MODULE_PARM(debug, \"i\"); #define DEBUG(n, args...) \\ do { \\ if (debug>(n)) \\ printk(KERN_DEBUG \"hifn7811: \" args); \\ } while(0) #else #define DEBUG(n, args...) #endif static void hifn7811_dec_use_count(void) { MOD_DEC_USE_COUNT; } static void hifn7811_inc_use_count(void) { MOD_INC_USE_COUNT; } /****************************************************************************/ /* * Hifn 7811 hardware support. */ int hifn7811_present; /* * Macro to calculate a relative pointer based on Hifn memory address. */ #define HIFN7811_PTR(x) (virt_to_bus(x)) #define HIFN7811_DSOFF(x) (((x) % 8) * sizeof(struct hifn7811desc)) /* * If testing or debugging agaisnt a real libdes then use these * redefines to rename functions so both can co-exist. */ #if defined(HIFN7811_TEST) || defined(MGTEST) #define lib_des_set_key des_set_key #define lib_des_cbc_encrypt des_cbc_encrypt #define lib_des_ede3_cbc_encrypt des_ede3_cbc_encrypt #else //#define hifn7811_des_set_key des_set_key //#define hifn7811_des_cbc_encrypt des_cbc_encrypt //#define hifn7811_des_ede3_cbc_encrypt des_ede3_cbc_encrypt #endif //#define hifn7811_des_ede3_cbc_encrypt des_ede3_cbc_encrypt //#define hifn7811_des_set_key des_set_key /****************************************************************************/ /* * Fast 32bit based memory set for Hifn. It is actually better * (and smaller) to inline this. */ void __inline__ *hifn7811_memset (void *s, int c, int len) { register volatile unsigned long *sp; sp = (volatile unsigned long *) s; len >>= 2; for (; len; len--) *sp++ = c; return (s); } /****************************************************************************/ /* * An efficent key copy function. We know keys are 8 bytes, * so I will just do 2 int copies (better then memcpy for this). * This optimizes very nicely... */ void __inline__ hifn7811_keycpy (void *dst, void *src) { unsigned int *dp = (unsigned int *) dst; unsigned int *sp = (unsigned int *) src; dp[0] = sp[0]; dp[1] = sp[1]; } /****************************************************************************/ /* * As per standard DES library functions. */ int hifn7811_des_set_key (des_cblock * key, des_key_schedule schedule) { DEBUG(2, \"des_set_key(key=%x,schedule=%x) -> key=%08x%08x\\n\", (int) key, (int) schedule, ((unsigned int *) key)[0], ((unsigned int *) key)[1]); /* FIXME: need to check for non-odd parity of key, return -1 */ /* FIXME: need to check for illegal week key, return -2 */ memcpy (schedule, key, sizeof (*key)); return (0); } /****************************************************************************/ /* * As per standard DES library functions. */ void hifn7811_des_ede3_cbc_encrypt (des_cblock * input, des_cblock * output, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, des_cblock * ivec, int enc) { struct crypto_request *req; DEBUG(2, \"des_ede3_cbc_encrypt(input=%x,output=%x,length=%d,\" \"ks1=%x,ks2=%x,ks3=%x,ivec=%x,encrypt=%d)\\n\", (int) input, (int) output, (int) length, (int) ks1, (int) ks2, (int) ks3, (int) ivec, enc); req = crypto_alloc_request(GFP_ATOMIC); req->op.cmd = (enc ? CRYPT_ENCODE:CRYPT_DECODE) | CRYPT_3DES | CRYPT_CBC; req->inbuf = (unsigned char *)input; req->inlen = length; req->outlen = length; req->outbuf = (unsigned char *)output; req->flags = CRYPT_SYNC; hifn7811_keycpy (&req->op.u.des.key[0], ks1); hifn7811_keycpy (&req->op.u.des.key[1], ks2); hifn7811_keycpy (&req->op.u.des.key[2], ks3); req->op.u.des.ivec = ivec; req->op.offset = 0; req->op.len = length; hw_crypto_request_fnc(req); crypto_free_request(req); } /************************************************** Generic H/W crypto request **************************************************/ int hifn7811_start_xreq (struct xreq *xreq) { struct hifn7811cmd *hifncmd; struct hifn7811comp *hifncomp; struct hifn7811enc *hifnenc; struct hifn7811mac *hifnmac; unsigned char *mp; int cmdlen, reslen; unsigned long cmd,cmdenc,cmdcomp,cmdmac; void *key; int keysize; des_cblock * ivec; struct crypto_request *req; struct crypto_operation *op,*op_mac=NULL,*op_crypt=NULL; struct HIFN_GLOBAL *h = &hifn; h->req++; FUNC_IN(h); BIT_ON(0); xreq->cmdp = NULL; req = xreq->req; // Point D // Point D-B: 115us // Point D-C: 2.2us cmd = 0; cmdenc = 0; cmdcomp = 0; cmdmac = 0; key = NULL; keysize = 0; ivec = NULL; for(op = &req->op; op != NULL; op=op->next) { cmd |= ((op->cmd & CRYPT_DECODE) ? HIFN7811_CMD_DECODE:HIFN7811_CMD_ENCODE); if(op->cmd & (CRYPT_RC4 | CRYPT_3DES)) { cmd |= HIFN7811_CMD_ENCRYPT; op_crypt = op; if(op->cmd & CRYPT_RC4) { cmdenc = HIFN7811_ENC_RC4; key = op->u.rc4.key->raw; keysize = op->u.rc4.key->len; if(key != NULL && keysize == 0) { // printk(KERN_DEBUG \"Hifn: Key not ready\\n\"); goto no_ressource; } } else { cmdenc = HIFN7811_ENC_3DES; if(op_crypt->cmd & CRYPT_ECB) cmdenc |= HIFN7811_ENC_ECB; else if(op_crypt->cmd & CRYPT_CBC) { cmdenc |= HIFN7811_ENC_CBC; ivec = op_crypt->u.des.ivec; } key = op_crypt->u.des.key; keysize = sizeof(op_crypt->u.des.key[0])*3; } } else if(op->cmd & (CRYPT_MD5 | CRYPT_SHA)) { op_mac = op; cmd |= HIFN7811_CMD_MAC; } } req->flags |= CRYPT_HARDWARE; if(!(req->flags & CRYPT_HIGH_PRIORITY)) h->normal_in_hifn++; reslen = sizeof(*hifncmd) + sizeof (*hifncomp) + sizeof (*hifnenc) + sizeof(*hifnmac) + sizeof(struct hifn7811res); if (cmd & HIFN7811_CMD_COMP) reslen += sizeof (struct hifn7811compres); if (cmd & HIFN7811_CMD_ENCRYPT) reslen += sizeof (struct hifn7811encres); if(key) { if(cmd & HIFN7811_CMD_ENCRYPT) { if(key) reslen += (cmdenc & HIFN7811_ENC_RC4)?260:24; if(ivec) reslen += 8; } } xreq->hash_len = 0; if((cmd & HIFN7811_CMD_MAC)) { reslen += sizeof(struct hifn7811macres); if(op_mac->cmd & CRYPT_96) { xreq->hash_len = 96/8; } else { if(op_mac->cmd & CRYPT_MD5) { xreq->hash_len = 16; } if(op_mac->cmd & CRYPT_SHA) { xreq->hash_len = 20; } } reslen += xreq->hash_len; if(op_mac->cmd & CRYPT_HMAC) reslen += 64; } reslen += 4; /* For rounding */ if((mp = hifn_alloc(reslen)) == NULL) goto no_ressource; xreq->cmdp = (struct hifn7811cmd *)mp; /* Base command structure. */ hifncmd = (struct hifn7811cmd *)mp; hifncmd->cmd = cmd; hifncmd->scount = HIFN7811_SWAPB (req->inlen); hifncmd->dcount = HIFN7811_SWAPB (req->outlen); mp += sizeof (*hifncmd); memset(mp,0,16-sizeof(*hifncmd)); /* Pad with 0s if necessary */ /* Compression command structure. */ if (cmd & HIFN7811_CMD_COMP) { hifncomp = (struct hifn7811comp *) mp; hifncomp->cmd = cmdcomp; hifncomp->hdrcnt = HIFN7811_SWAPB (0); hifncomp->srccnt = HIFN7811_SWAPB (req->inlen); hifncomp->reserved = 0; mp += sizeof (*hifncomp); } /* Padding would go here... */ /* Mac command structure. */ if (cmd & HIFN7811_CMD_MAC) { unsigned short cmdmac; cmdmac = HIFN7811_MAC_AEBD | HIFN7811_MAC_RESULT | HIFN7811_MAC_CNTMODE | ((op_mac->cmd & CRYPT_MD5)? HIFN7811_MAC_MD5:0) | ((op_mac->cmd & CRYPT_SHA)? HIFN7811_MAC_SHA:0) | ((op_mac->cmd & CRYPT_HMAC)? (HIFN7811_MAC_HMAC|HIFN7811_MAC_NEWKEY):HIFN7811_MAC_HASH) | ((op_mac->cmd & CRYPT_96)? HIFN7811_MAC_TRUNC:0) | ((op_mac->cmd & CRYPT_APPEND)? HIFN7811_MAC_INSERT:0); hifnmac = (struct hifn7811mac *) mp; hifnmac->cmd = cmdmac; hifnmac->hdrcnt = HIFN7811_SWAPB (op_mac->offset); hifnmac->srccnt = HIFN7811_SWAPB (op_mac->len); hifnmac->reserved = 0; mp += sizeof (*hifnmac); } /* Encryption command structure. */ if (cmd & HIFN7811_CMD_ENCRYPT) { hifnenc = (struct hifn7811enc *)mp; hifnenc->cmd = cmdenc | HIFN7811_ENC_CLEAR | ((key != NULL)?HIFN7811_ENC_NEWKEY:0) | ((ivec != NULL)?HIFN7811_ENC_NEWIV:0); hifnenc->hdrcnt = HIFN7811_SWAPB (op_crypt->offset); hifnenc->srccnt = HIFN7811_SWAPB (op_crypt->len); hifnenc->reserved = 0; mp += sizeof (*hifnenc); } if (op_mac != NULL && (op_mac->cmd & CRYPT_HMAC)) { memset(mp,0,64); hifn7811_memcpyto (mp, op_mac->u.hash.hmac_key, op_mac->u.hash.hmac_key_len); mp += 64; } if (key) { int t; if(cmdenc & HIFN7811_ENC_RC4) { for(t=0;t<256;t+=keysize) hifn7811_memcpyto(mp + t,key,(256-t)<keysize?256-t:keysize); mp[256] = mp[257] = mp[258] = mp[259] = 0; mp += 260; } else { hifn7811_memcpyto(mp,key,keysize); mp += keysize; } } if (ivec) { hifn7811_memcpyto (mp, ivec, 8); mp += 8; } // #define PRINT_DESCR(p) printk(#p \" cmd: %x ptr: %x\\n\",h->p##Ptr->cmd,h->p##Ptr->ptr) #define PRINT_DESCR(p) do { ; } while(0) //#define HENDIAN HIFN7811_DESC_BE #define HENDIAN 0 /* Setup Command descriptor */ cmdlen = (unsigned int) mp - (unsigned int) hifncmd; /* Command length including keys and ivec. */ if(cmdlen < 16) cmdlen = 16; /* Minimum cmd length */ h->cmdPtr->cmd = (cmdlen & HIFN7811_DESC_LENMASK) | HIFN7811_DESC_LAST | HENDIAN; h->cmdPtr->ptr = HIFN7811_PTR (xreq->cmdp); PRINT_DESCR(cmd); /* Setup memory space for the results structure. */ reslen = (reslen - cmdlen + 3)&(~0x3); mp = (unsigned char *)(((unsigned long)mp+3) & (~0x3)); h->resPtr->cmd = (reslen & HIFN7811_DESC_LENMASK) | HIFN7811_DESC_LAST | HENDIAN; h->resPtr->ptr = HIFN7811_PTR (mp); PRINT_DESCR(res); xreq->resp = (char*)mp; /* Setup source descriptor */ h->srcPtr->cmd = (req->inlen & HIFN7811_DESC_LENMASK) | HIFN7811_DESC_LAST | HENDIAN; h->srcPtr->ptr = (unsigned long) pci_map_single(h->pci_dev,req->inbuf,req->inlen,PCI_DMA_TODEVICE); PRINT_DESCR(src); /* Setup destination descriptors */ h->dstPtr->cmd = ((req->outlen+3) & HIFN7811_DESC_LENMASK) | HIFN7811_DESC_LAST | HENDIAN; h->dstPtr->ptr = (unsigned long) pci_map_single(h->pci_dev,req->outbuf,req->outlen,PCI_DMA_FROMDEVICE); PRINT_DESCR(dst); if(h->dstPtr->ptr & 0x3) printk(\"Dst buffer not aligned!\\n\"); if(req->outlen & 0x3) printk(\"Dst len not aligned!\\n\"); put_queue(in_hifn,xreq); // Point E // Point E-D, ping -s 1: 27us SIG_MARK(req); /* Set valid bit */ h->slotin++; #ifdef MG if((h->dstPtr->cmd & HIFN7811_DESC_VALID) || (h->dstPtr->cmd & HIFN7811_DESC_VALID)) { printk(\"Already Valid! In: %u Out: %u\\n\",h->slotin, h->slotout); } #endif #define SET_VALID(f) h->f##Ptr->cmd |= HIFN7811_DESC_VALID SET_VALID(dst); SET_VALID(res); SET_VALID(src); SET_VALID(cmd); #undef SET_VALID HIFN_INC_PTR(h,src,Ptr); HIFN_INC_PTR(h,cmd,Ptr); HIFN_INC_PTR(h,res,Ptr); HIFN_INC_PTR(h,dst,Ptr); BIT_OFF(0); BIT_ON(1); FUNC_OUT(h); return CRYPT_OK; no_ressource: hifn_free(xreq->cmdp); hifn.retry++; printk(\"No Ressources\"); FUNC_OUT(h); return CRYPT_NO_RESSOURCE; } static void hifn_dump_register(void); static void hifn7811_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct HIFN_GLOBAL *h = &hifn; u32 reg; if(hifn_in_use == 0) printk(KERN_ERR \"HIFN Int: Hifh Not in use\\n\"); reg = read_pci(h->grp1->se_status_ctrl); write_pci(&h->grp1->se_status_ctrl,reg); if(reg & (STATUS_BITS(RING_RES,CMD_IS_PCI_ABORT) | STATUS_BITS(RING_CMD,CMD_IS_PCI_ABORT) | STATUS_BITS(RING_SRC,CMD_IS_PCI_ABORT) | STATUS_BITS(RING_DST,CMD_IS_PCI_ABORT) )) { printk(\"PCI abort reg=%x, Status\\n\",reg); hifn_dump_register(); return; } if(!(reg & STATUS_BITS(RING_RES,CMD_IS_DONE))) { struct timeval tm; do_gettimeofday(&tm); printk(\"Hifn Int: unexpected interrupt: %x\\n\",reg); write_pci(&h->grp1->pci_int_reg,0); printk(\"INT at %u:%u\\n\",tm.tv_sec,tm.tv_usec); } mark_bh(HIFN_BH); h->ints++; } static void hifn7811_bh(void) { struct hifn7811res *res; int size; struct xreq *xreq; struct crypto_request *req; struct crypto_operation *op; struct HIFN_GLOBAL *h = &hifn; unsigned char *c; struct timeval now; BIT_OFF(1); FUNC_IN(h); h->bh++; while(h->slotout != h->slotin && !(h->dstDone->cmd & HIFN7811_DESC_VALID) && !(h->resDone->cmd & HIFN7811_DESC_VALID)) { xreq = get_queue(in_hifn); if(xreq == NULL) { printk(KERN_ERR \"HiFnBH: queue empty\\n\"); hifn_in_use = 0; return; } req = xreq->req; SIG_MARK(req); h->hw++; // Point F // Point E-F: 62us, ping -s 1 SIG_MARK(req); /* Get results structure... */ res = (struct hifn7811res *) xreq->resp; if(res->cmd & HIFN7811_RES_DSTOVERRUN) { printk(KERN_ERR \"Hifn: dest Overrun\\n\"); } res->srccnt = HIFN7811_SWAPB (res->srccnt); if(res->srccnt != 0) { printk(KERN_DEBUG \"HIfn: Src not 0,=%x\\n\",res->srccnt); } res->dstcnt = HIFN7811_SWAPB (res->dstcnt); size = (int) (req->outlen - res->dstcnt); if (size < 0) size = 0; if (size > req->outlen) size = req->outlen; /* Clear PCI buffers */ pci_unmap_single(h->pci_dev,h->srcPtr->ptr,req->inlen,PCI_DMA_TODEVICE); pci_unmap_single(h->pci_dev,h->dstPtr->ptr,req->outlen,PCI_DMA_FROMDEVICE); /* Get other results */ c = (unsigned char *)xreq->resp; c += sizeof(struct hifn7811res); if(xreq->cmdp->cmd & HIFN7811_CMD_COMP) { /* Skip compression */ c+= sizeof(struct hifn7811compres); } if(xreq->cmdp->cmd & HIFN7811_CMD_MAC) { struct hifn7811macres *mres; mres = (struct hifn7811macres *)c; /* if(mres->cmd & HIFN7811_MACRES_NZERO) printk(KERN_DEBUG \"HIfn: MAC: src NOT 0\\n\"); */ c += sizeof(struct hifn7811macres); for(op = &req->op;op != NULL; op=op->next) { if(op->cmd & (CRYPT_MD5|CRYPT_SHA)) { if(xreq->hash_len != 0) memcpy(op->u.hash.result, c, xreq->hash_len); op->u.hash.reslen = xreq->hash_len; c += xreq->hash_len; break; } } } if((xreq->cmdp->cmd & HIFN7811_CMD_ENCRYPT)) { struct hifn7811encres *eres; eres = (struct hifn7811macres *)c; if(eres->cmd & HIFN7811_ENCRES_NZERO) printk(KERN_DEBUG \"HIfn: Crypt: src NOT 0\\n\"); } req->outlen = size; hifn_free(xreq->cmdp); h->slotout++; HIFN_INC_PTR(h,dst,Done); HIFN_INC_PTR(h,res,Done); hifn_in_use--; process_hw_crypto(); /* Start a new encryption right away */ do_gettimeofday(&now); now.tv_usec += (now.tv_sec - xreq->in_time.tv_sec)*1000000; h->process_time += (now.tv_usec - xreq->in_time.tv_usec); hifn_free_xreq(xreq); h->cb++; // Point G // Point G-F: 9us, ping -s 1 SIG_OFF(req); if(!(req->flags & CRYPT_HIGH_PRIORITY)) h->normal_in_hifn--; if(req->callback != NULL) { req->callback(req); } else crypto_free_request(req); if((h->dstDone->cmd & HIFN7811_DESC_VALID)^ (h->resDone->cmd & HIFN7811_DESC_VALID)) { mark_bh(HIFN_BH); } } process_hw_crypto(); if(hifn_in_use == 0) { stop_usage(h); } FUNC_OUT(h); } static int process_hw_crypto(void) { struct xreq *xreq,*head; unsigned long flags; int err; struct HIFN_GLOBAL *h = &hifn; do { xreq = head = NULL; if(peek_queue(to_crypt_high) != NULL) { head = to_crypt_high; } else if(h->normal_in_hifn < 4) { head = to_crypt; } // head = to_crypt; if(head != NULL) xreq = get_queue(head); save_flags(flags); cli(); // Point C // Point C-B: 120us if(xreq != NULL) { if(hifn_in_use < HIFN7811_DESCR_CNT) { hifn_in_use++; restore_flags(flags); err = hifn7811_start_xreq(xreq); switch(err) { case CRYPT_OK: break; default: /* Error? */ re_queue(head,xreq); xreq = NULL; /* Will exit */ hifn_in_use--; break; } } else { re_queue(head,xreq); break; } } restore_flags(flags); } while(xreq != NULL); return CRYPT_OK; } static int hw_crypto_request_fnc(struct crypto_request *req) { struct xreq *xreq; volatile int busy; struct HIFN_GLOBAL *h; h = &hifn; /* For debugger */ /* Verify request (debug?)*/ if(req->inlen <0 || req->inlen > 2000 || req->outlen <0 || req->outlen > 2000) { printk(KERN_WARNING \"hw_crypto: Bad Request len In:$%x Out:$%x\\n\",req->inlen,req->outlen); return CRYPT_ERROR; } if(req->flags & CRYPT_SYNC) { return CRYPT_ERROR; } // Point A SIG_ON(req); xreq = hifn_alloc_xreq(); if(xreq == NULL) return CRYPT_ERROR; xreq->req = req; xreq->cmdp = NULL; do_gettimeofday(&xreq->in_time); /* Queue request */ if(req->flags & CRYPT_HIGH_PRIORITY) put_queue(to_crypt_high,xreq); else put_queue(to_crypt,xreq); h->inq++; if(h->max < (h->inq - h->cb)) h->max = (h->inq - h->cb); h->deepness += (h->inq - h->cb); if(hifn_in_use == 0) { start_usage(h); } // Point B // Point A-B: 8us /* start H/W if possible */ process_hw_crypto(); return CRYPT_OK; } #define DES_ENCRYPT 1 #define DES_DECRYPT 0 #if LINUX_VERSION_CODE < 0x20300 #ifdef MODULE #define hifn7811_init init_module #define hifn7811_cleanup cleanup_module #endif #define mod_init_t int __init #define mod_exit_t void #else #define mod_init_t static int __init #define mod_exit_t static void __exit #endif #ifdef MGTEST static void print_result(struct crypto_request *req) { int t; struct crypto_operation *op; req->inlen = req->inlen < 10 ? req->inlen: 10; req->outlen = req->outlen < 30 ? req->outlen: 30; printk(\"HiFn Result in %u jiffies\\n\",jiffies-(long)req->priv); printk(\"HIFN In: \"); for(t=0;t<req->inlen;t++) printk(\"%x \",(unsigned char)req->inbuf[t]); printk(\"\\n\"); printk(\"HIFN Out: \"); for(t=0;t<req->outlen;t++) printk(\"%x \",(unsigned char)req->outbuf[t]); printk(\"\\n\"); kfree(req->inbuf); kfree(req->outbuf); for(op=&req->op; op != NULL; op = op->next) { switch(op->cmd) { case CRYPT_ENCODE | CRYPT_RC4: kfree(op->u.rc4.key); break; case CRYPT_ENCODE | CRYPT_3DES: if(op->u.des.ivec) kfree(op->u.des.ivec); break; default: if(op->cmd & (CRYPT_MD5 | CRYPT_SHA)) { printk(\"HIFN MAC: \"); for(t=0;t<op->u.hash.reslen;t++) printk(\"%x \",(unsigned char)op->u.hash.result[t]); printk(\"\\n\"); } break; } if(op != &req->op) kfree(op); } crypto_free_request(req); } #undef SYNC static void irc4(char *key,char *data,int len) { struct crypto_request *req; req = crypto_alloc_request(GFP_KERNEL); req->op.cmd = CRYPT_ENCODE | CRYPT_RC4; req->op.offset = 0; req->op.len = len; req->inbuf = kmalloc(len,GFP_KERNEL); memcpy(req->inbuf,data,len); req->inlen = len; req->outlen = len; req->outbuf = kmalloc(len,GFP_KERNEL); memset(req->outbuf,0,len); #ifdef SYNC req->flags = CRYPT_SYNC; #else req->flags = 0; #endif req->op.u.rc4.key = kmalloc(sizeof(*(req->op.u.rc4.key)),GFP_KERNEL); hifn7811_RC4_set_key(req->op.u.rc4.key, strlen(key),key); #ifndef SYNC req->callback = print_result; req->priv = (void*) jiffies; #endif crypto_execute(req); #ifdef SYNC print_result(req); #endif } //#define DES3_TEST CRYPT_ECB #define DES3_TEST CRYPT_CBC static void ides(char key[3][8],char ivec[8],char *data,int len) { struct crypto_request *req; struct crypto_operation *op; int t; req = crypto_alloc_request(GFP_KERNEL); req->op.cmd = CRYPT_ENCODE | CRYPT_3DES | DES3_TEST; req->op.offset = 0; req->op.len = len; req->inbuf = kmalloc(len,GFP_KERNEL); memcpy(req->inbuf,data,len); req->inlen = len; req->outlen = len+20; req->outbuf = kmalloc(len+20,GFP_KERNEL); memset(req->outbuf,0,len+20); #ifdef SYNC req->flags = CRYPT_SYNC; #else req->flags = 0; #endif for(t=0;t<3;t++) { hifn7811_keycpy(&req->op.u.des.key[t],key[t]); } #if DES3_TEST == CRYPT_CBC req->op.u.des.ivec = kmalloc(sizeof(*(req->op.u.des.ivec)),GFP_KERNEL); hifn7811_keycpy(req->op.u.des.ivec,ivec); #else req->op.u.des.ivec = NULL; #endif req->op.offset = 0; #ifdef MG /* Append MD5 hash to output */ req->op.next = kmalloc(sizeof(*op),GFP_KERNEL); op = req->op.next; op->offset = 0; op->len = len; op->cmd = CRYPT_MD5 /* | CRYPT_APPEND */; op->next = NULL; #endif #ifndef SYNC req->callback = print_result; req->priv = (void*) jiffies; #endif crypto_execute(req); #ifdef SYNC print_result(req); #endif } static void imac(char *data,int len) { struct crypto_request *req; struct crypto_operation *op; int t; req = crypto_alloc_request(GFP_KERNEL); req->op.cmd = CRYPT_ENCODE | CRYPT_MD5; req->op.offset = 0; req->op.len = len; req->inbuf = kmalloc(len,GFP_KERNEL); memcpy(req->inbuf,data,len); req->inlen = len; req->outlen = len+20; req->outbuf = kmalloc(len+20,GFP_KERNEL); memset(req->outbuf,0,len+20); #ifdef SYNC req->flags = CRYPT_SYNC; #else req->flags = 0; #endif req->op.offset = 0; #ifndef SYNC req->callback = print_result; req->priv = (void*) jiffies; #endif crypto_execute(req); #ifdef SYNC print_result(req); #endif } static void test_interrupt(void) { #ifdef MG struct crypto_request *req; char *inbuf,*outbuf,*key; int t; put_queue(to_crypt,(void*)1); put_queue(to_crypt,(void*)2); put_queue(to_crypt,(void*)3); printk(\"Q: %x\\n\",(unsigned int)get_queue(to_crypt)); printk(\"Q: %x\\n\",(unsigned int)get_queue(to_crypt)); printk(\"Q: %x\\n\",(unsigned int)get_queue(to_crypt)); printk(\"Q: %x\\n\",(unsigned int)get_queue(to_crypt)); put_queue(to_crypt,(void*)0xa); put_queue(to_crypt,(void*)0xb); put_queue(to_crypt,(void*)0xc); printk(\"Q: %x\\n\",(unsigned int)get_queue(to_crypt)); printk(\"Q: %x\\n\",(unsigned int)get_queue(to_crypt)); printk(\"Q: %x\\n\",(unsigned int)get_queue(to_crypt)); printk(\"Q: %x\\n\",(unsigned int)get_queue(to_crypt)); printk(\"Q: %x\\n\",(unsigned int)get_queue(to_crypt)); #endif #define DATA(a) a,sizeof(a)-1 //irc4(\"\\x01\\x23\\x45\\x67\\x89\\xab\\xcd\\xef\",DATA(\"\\x01\\x23\\x45\\x67\\x89\\xab\\xcd\\xef\")); irc4(\"\\x01\\xDD\\x45\\xDD\\x89\\xab\\xcd\\xef\",DATA(\"\\xda\\xda\\x00\\x00\\xda\\xda\\x00\\x00\")); //irc4(\"\\xef\\x01\\x23\\x45\",DATA(\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\")); // imac(DATA(\"\\x01\\x23\\x45\\x67\\x89\\xab\\xcd\\xef\")); do { char keys[3][8] = { \"\\x01\\x23\\x45\\x67\\x89\\xab\\xcd\\xef\", \"\\x23\\x45\\x67\\x89\\xab\\xcd\\xef\\x01\", \"\\x45\\x67\\x89\\xab\\xcd\\xef\\x01\\x23\" }; ides(keys,\"\\x12\\x34\\x56\\x78\\x90\\xab\\xcd\\xef\",DATA(\"\\x4e\\x6f\\x77\\x20\\x69\\x73\\x20\\x74\")); } while(0); imac(DATA(\"\\x01\\x23\\x45\\x67\\x89\\xab\\xcd\\xef\")); #ifdef MG inbuf = kmalloc(1024,GFP_KERNEL); outbuf = kmalloc(1024,GFP_KERNEL); key = kmalloc(280,GFP_KERNEL); for(t=0;t<5;t++) { req = kmalloc(sizeof(struct crypto_request),GFP_KERNEL); req->op.cmd = CRYPT_ENCODE | CRYPT_RC4; req->inbuf = inbuf; req->inlen = 1024; req->outlen = 1024; req->outbuf = outbuf; req->flags = 0; req->op.u.rc4.key = key; req->callback = NULL; hw_crypto_request(req); } kfree(inbuf); kfree(outbuf); kfree(key); #endif } #endif // MGTEST static struct proc_dir_entry *proc_hifn; static void hifn_dump_register(void) { int t; printk(\"SE ctrl: %x\\n\",read_pci(hifn.grp0->se_control)); printk( \"SE CTRL:%x MIPS_CFG:%x GPDMA src:%x\\n\",read_pci(hifn.grp1->se_status_ctrl),read_pci(hifn.grp1->mips_config),read_pci(hifn.grp1->GPDMA1_src)); #define ARG(c) hifn.desc->c[t].cmd,hifn.desc->c[t].ptr for(t=0;t<9;t++) printk(\"%u: Cmd:%08x/%08x Src:%08x/%08x Dst:%08x/%08x Res:%08x/%08x \\n\",t,ARG(cmd),ARG(src),ARG(dst),ARG(res)); #undef ARG } static int hifn_read_proc ( char *page, char **start, off_t off,int count ,int *eof, void *data_unused ) { int len = 0; off_t begin = 0; int t; len = sprintf(page + len, \"InQ Req Ints BH CB Retry H/W S/W In_Use\\n\"); len += sprintf(page + len, \"%u %u %u %u %u %u %u %u %u\\n\",hifn.inq,hifn.req,hifn.ints,hifn.bh,hifn.cb,hifn.retry,hifn.hw,hifn.sw,hifn_in_use); len += sprintf(page + len, \"Avg deepness %u/%u, Max: %u Ptime:%uus\\n\",hifn.deepness,hifn.inq,hifn.max,hifn.cb?hifn.process_time/hifn.cb:0); len += sprintf(page + len, \"SE ctrl: %x\\n\",read_pci(hifn.grp0->se_control)); len += sprintf(page + len, \"SE CTRL:%x MIPS_CFG:%x GPDMA src:%x\\n\",read_pci(hifn.grp1->se_status_ctrl),read_pci(hifn.grp1->mips_config),read_pci(hifn.grp1->GPDMA1_src)); len += sprintf(page + len, \"GlobalSt:%x seDMA:%x Grp0Stat:%x\\n\",read_pci(hifn.grp1->global_status),read_pci(hifn.grp1->se_dma_config),read_pci(hifn.grp0->se_status)); len += sprintf(page + len, \"SlotIn:%x Out:%x AllocMap:%x Addr:%x\\n\",hifn.slotin,hifn.slotout,hifn_mem.alloc_map,hifn_mem.mem); for(t=0;t<9;t++) len += sprintf(page + len, \"%u: Cmd:%08x Src:%08x Dst:%08x Res:%08x \\n\",t,hifn.desc->cmd[t].cmd,hifn.desc->src[t].cmd,hifn.desc->dst[t].cmd,hifn.desc->res[t].cmd); *eof = 1; /* if (off >= len+begin) return 0; *start = page + (begin-off); return ((count < begin+len-off) ? count : begin+len-off); */ if(len > PAGE_SIZE) printk(\"proc: len > 4096\\n\"); return len; } static int hifn_write_proc(struct file *file, const char *buffer,unsigned long count, void *data) { int t; switch(*buffer) { case \'A\': always = buffer[1]-\'0\'; break; case \'D\': disable = buffer[1]-\'0\'; hifn7811_present = disable; break; case \'T\': #ifdef MGTEST t=1; if(buffer[1] > \'0\' && buffer[1] <= \'9\') t = buffer[1]-\'0\'; while(t-->0) test_interrupt(); if(0) { int t; struct timeval tm; write_pci(&hifn.grp1->pci_ier,1); do_gettimeofday(&tm); write_pci(&hifn.grp1->pci_int_reg,1); for(t=0;t<0x100000;t++); printk(\"INT done, started %u:%u\\n\",tm.tv_sec,tm.tv_usec); } #endif break; } return count; } //#ifdef __BIG_ENDIAN //#define HIFN7811_ENDIAN HIFN7811_DESC_BE //#else #define HIFN7811_ENDIAN 0 //#endif void hifn7811_setup(struct HIFN_GLOBAL *h) { struct hifn7811grp0 *grp0 = h->grp0; struct hifn7811grp1 *grp1 = h->grp1; int t; /****** Setup *******/ write_pci(&grp0->se_isr,0xffffffff); write_pci(&grp0->se_config, SE_CONFIG_DEFAULT); write_pci(&grp0->se_fifo_config, SE_FIFO_CONFIG_DEFAULT); write_pci(&grp0->se_ier, 0); /* Disable all interrupts */ /* Setup rings */ h->desc = pci_alloc_consistent(h->pci_dev,PAGE_SIZE,&h->pci_ring_base); #define INIT_DESC(type) h->desc->type[t].cmd = HIFN7811_ENDIAN | HIFN7811_DESC_LAST; \\ h->desc->type[t].ptr = 0 for(t=0;t<HIFN7811_DESCR_CNT;t++) { INIT_DESC(cmd); INIT_DESC(src); INIT_DESC(res); INIT_DESC(dst); } #undef INIT_DESC #define DO_JUMP(f) h->desc->f[t].cmd = HIFN7811_ENDIAN | HIFN7811_DESC_NOVALID \\ | HIFN7811_DESC_VALID | HIFN7811_DESC_JUMP; \\ h->desc->f[t].ptr = virt_to_bus(&h->desc->f[0]); h->f##Ptr = &h->desc->f[0] DO_JUMP(cmd); DO_JUMP(src); DO_JUMP(dst); DO_JUMP(res); #undef DO_JUMP #define SET_RING_REG(f) write_pci(&grp1->se_##f.reg,virt_to_bus(&h->desc->f[0])) SET_RING_REG(dst); SET_RING_REG(src); SET_RING_REG(res); SET_RING_REG(cmd); #undef SET_RING_REG h->dstDone = h->dstPtr; h->resDone = h->resPtr; /* Setup memory for command and result structure */ hifn_mem.mem = (unsigned char *)h->desc; /* Block 0/1/2 are reseved for descriptors */ hifn_mem.alloc_map = (1<<((sizeof(struct HIFN_DESCRIPTORS)+HIFN_BLOCK_SIZE-1) & ~(HIFN_BLOCK_SIZE-1))/HIFN_BLOCK_SIZE)-1; printk(\"Sizeof HIFN_BLOCK_SIZE %u, %x->%x, map=%x\\n\",HIFN_BLOCK_SIZE,hifn_mem.mem,hifn_mem.mem+PAGE_SIZE,hifn_mem.alloc_map); /* Setup DMA config */ #ifdef __BIG_ENDIAN write_pci(&grp1->se_dma_config, SE_INBOUND_BE | SE_OUTBOUND_BE | SE_POLL_FREQ(1) | SE_POLL_SCALE(1)); #else write_pci(&grp1->se_dma_config, SE_POLL_FREQ(3) | SE_POLL_SCALE(3)); #endif /* No RNG needed... */ /* No MIPS stuff needed. */ /* No GPRAM, no GPDMA */ /*********** Enable *************/ /* Enable DMA, Interrupts */ write_pci(&grp1->se_status_ctrl, STATUS_BITS(RING_DST,CMD_ENABLE) | STATUS_BITS(RING_RES,CMD_ENABLE) | STATUS_BITS(RING_CMD,CMD_ENABLE) | STATUS_BITS(RING_SRC,CMD_ENABLE)); write_pci(&grp1->se_ier, STATUS_BITS(RING_RES,CMD_IS_DONE) | STATUS_BITS(RING_CMD,CMD_IS_PCI_ABORT) | STATUS_BITS(RING_SRC,CMD_IS_PCI_ABORT) | STATUS_BITS(RING_DST,CMD_IS_PCI_ABORT) | STATUS_BITS(RING_RES,CMD_IS_PCI_ABORT) ); } #ifdef PRINT_USAGE void hifn_sample(unsigned long arg) { struct HIFN_GLOBAL *h = (struct HIFN_GLOBAL *)arg; struct timeval now; unsigned int ttl,usage; int was_running; do_gettimeofday(&now); if(h->usage_start.tv_sec != 0) { stop_usage(h); was_running = 1; } else was_running = 0; usage = (h->usage_time.tv_sec)*1000000 + h->usage_time.tv_usec; ttl = (now.tv_sec - h->start.tv_sec)*1000000 + (now.tv_usec - h->start.tv_usec); /* printk(\"Hifn: Usage time: %u:%uus Total time %uus\\n\", (h->usage_time.tv_sec), h->usage_time.tv_usec, (now.tv_sec - h->start.tv_sec)*1000000 + (now.tv_usec - h->start.tv_usec)); */ printk(\"Hifn Occ: %3u.%u%%\\n\",100*usage/ttl,(1000*usage/ttl) %10); h->start = now; memset(&h->usage_time,0,sizeof(h->usage_time)); if(was_running) start_usage(h); mod_timer(&h->timer,jiffies+HZ); } #endif static struct crypto_engine_def hifn7811_def = { name : \"HiFn7811\", capability: (CRYPT_RC4|CRYPT_DES|CRYPT_3DES|CRYPT_MD5|CRYPT_SHA), attributes: IS_HARDWARE | IS_ASYNC, request_handler: hw_crypto_request_fnc, open: hifn7811_inc_use_count, close: hifn7811_dec_use_count }; mod_init_t hifn7811_init(void) { int i; struct HIFN_GLOBAL *h = &hifn; /* To debug modules...*/ #if 0 hifn7811_diags (); #endif #ifdef TRACING tracing_setup(); set_tracing(0); set_tracing(0); set_tracing(1); set_tracing(1); set_tracing(2); set_tracing(2); set_tracing(3); set_tracing(3); set_tracing(0); set_tracing(0); #endif printk (\"HIFN7811: cryptographic accelerator \"); if (!disable) { h->pci_dev = pci_find_device(HIFN_PCI_VENDOR_ID,HIFN_PCI_DEVICE_ID,NULL); if(h->pci_dev != NULL) { int err; printk(\"Found!\\n\"); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_enable_device(h->pci_dev); #endif h->grp0 = h->pci_dev->resource[0].start; h->grp1 = h->pci_dev->resource[1].start; printk(KERN_DEBUG \"GRP0:%x GRP1:%x\\n\",h->grp0,h->grp1); pci_set_master(h->pci_dev); h->grp0 = ioremap_nocache((unsigned long)h->grp0,1024*4); h->grp1 = ioremap_nocache((unsigned long)h->grp1,1024*4); /* h->grp0 = ioremap((unsigned long)h->grp0,1024*4); h->grp1 = ioremap((unsigned long)h->grp1,1024*4); */ printk(KERN_DEBUG \"Remap GRP0:%x GRP1:%x\\n\",h->grp0,h->grp1); hifn7811_present = 1; printk (\"PRESENT, Rev=%x\\n\",readl(&h->grp1->revision_number)); } else { printk (\"NOT present\\n\"); } } else { printk(\"DISABLED\\n\"); } printk (\"HIFN7811: Copyright (C) 2000, Lineo (www.lineo.com)\\n\"); printk (\"HIFN7811: Copyright (C) 2001, Colubris Networks\\n\"); #ifdef MG { unsigned long vaddr = (unsigned long) &h->grp0->se_control; pgd_t *pgd; pmd_t *pmd; pte_t *pte, old_pte; pgd = swapper_pg_dir + __pgd_offset(vaddr); pmd = pmd_offset(pgd, vaddr); pte = pte_offset(pmd, vaddr); printk(\"Value of PTE for se-control: %x\\n\",pte_val(*pte)); old_pte = *pte; } #endif if (hifn7811_present) { /* Reset the hifn chip */ printk(\"Resetting board...\\n\"); // write_pci(&h->grp1->GPDMA1_src,0x12345678); // printk(\"Wrote 0x12345678 == 0x%x\\n\",read_pci(h->grp1->GPDMA1_src)); // printk(\"Reset Failed! Wrote:%x Read:%x\\n\",SE_CONTROL_RESET|SE_CONTROL_MUST_BIT,read_pci(h->grp0->se_control)); // write_pci(&h->grp0->se_control,SE_CONTROL_RESET|SE_CONTROL_MUST_BIT); // writel(SE_CONTROL_RESET|SE_CONTROL_MUST_BIT,&h->grp0->se_control); write_pci(&h->grp0->se_control,0xffffffff); write_pci(&h->grp1->se_dma_config,SE_MSTRRESET); // h->grp0->se_control = SE_CONTROL_RESET|SE_CONTROL_MUST_BIT; // barrier(); // printk(\"A1\\n\"); for (i = 0; (i < 100); i++) { udelay(10000); if ( (read_pci(h->grp0->se_control)&SE_CONTROL_RESET) == 0) break; } // printk(\"Does reset work? is 0x12345678 == 0x%x\\n\",read_pci(h->grp1->GPDMA1_src)); if(i == 100) { printk(\"Reset Failed! Wrote:%x Read:%x\\n\",SE_CONTROL_RESET|SE_CONTROL_MUST_BIT,read_pci(h->grp0->se_control)); printk(\"Is endian ok? does 0x4040 == 0x%x\\n\",read_pci(h->grp0->se_fifo_status)); printk(\"Is endian ok? does 0x40000000 == 0x%x\\n\",read_pci(h->grp1->mips_pci1_addr)); /* iounmap(h->grp0); iounmap(h->grp1); return -1; */ } else printk(\"Reset ok: %u\\n\",i); if ((proc_hifn = create_proc_entry( \"hifn\", 0, 0 ))) { proc_hifn->read_proc = hifn_read_proc; proc_hifn->write_proc = hifn_write_proc; } /* Reset all events */ hifn7811_setup(h); xreq_cache = kmem_cache_create(\"hifn_xreq\",sizeof(struct xreq), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); /* Install interrupt request */ pci_read_config_byte(h->pci_dev,PCI_INTERRUPT_LINE,&(h->myirq)); printk(KERN_DEBUG \" Using IRQ %d\\n\",h->myirq); request_irq(h->myirq,hifn7811_interrupt,0,\"hifn7811\",NULL); // request_8xxirq(h->myirq,hifn7811_interrupt,0,\"hifn7811\",NULL); /* Setup BH */ init_bh(HIFN_BH,hifn7811_bh); to_crypt=&dummy[0]; to_crypt->next = to_crypt->prev = to_crypt; in_hifn=&dummy[1]; in_hifn->next = in_hifn->prev = in_hifn; to_crypt_high=&dummy[2]; to_crypt_high->next = to_crypt_high->prev = to_crypt_high; hifn.to_crypt = to_crypt; hifn.in_hifn = in_hifn; hifn.hifn_in_use = &hifn_in_use; #ifdef MGTEST printk(\"SW only\\n\"); test_interrupt(); #endif crypto_register_engine(&hifn7811_def); init_timer(&h->timer); h->timer.expires=jiffies+HZ; h->timer.data = h; h->timer.function = hifn_sample; add_timer(&h->timer); } return 0; } #ifdef MODULE mod_exit_t hifn7811_cleanup (void) { int i; struct HIFN_GLOBAL *h = &hifn; /* To debug modules...*/ DEBUG(0, \"Unloading module hifn7811\\n\"); write_pci(&h->grp0->se_control,SE_CONTROL_RESET|SE_CONTROL_MUST_BIT); for (i = 0; (i < 0x100000); i++) { if ( (h->grp0->se_control&SE_CONTROL_RESET) == 0) break; } del_timer(&h->timer); iounmap(h->grp0); iounmap(h->grp1); if(h->pci_dev != NULL && h->desc != NULL) pci_free_consistent(h->pci_dev,PAGE_SIZE,(void*)h->desc,h->pci_ring_base); free_irq(hifn.myirq,NULL); remove_proc_entry(\"hifn\",NULL); if(xreq_cache != NULL) kmem_cache_destroy(xreq_cache); xreq_cache = NULL; crypto_unregister_engine(hifn7811_def.name); } #endif #if LINUX_VERSION_CODE > 0x20300 module_init(hifn7811_init); module_exit(hifn7811_cleanup); #endif |
|
|
板凳#
发布于:2002-06-21 13:20
为了关税,把头文件也加上,只是,偶不是用这卡
/****************************************************************************/ /* * hifn7811.h -- Definitions for Hi/fn 7811 encryption engine. * * (C) Copyright 2000, Lineo, Inc. (www.lineo.com) * (C) Copyright 2000, Greg Ungerer (gerg@lineo.com) * * This program is a part of the Linux kernel, and may be freely * copied under the terms of the GNU General Public License (GPL), * version 2, or at your option any later version. */ /****************************************************************************/ #ifndef _HIFN7811_H_ #define _HIFN7811_H_ /****************************************************************************/ #define HIFN_PCI_VENDOR_ID 0x13a3 /* HIFN */ #define HIFN_PCI_DEVICE_ID 0x7 /* 7811 */ /* * Address offsets in 7811 memory mapping. */ #define HIFN7811_REGBASE 0 /* Register Base Address */ #define HIFN7811_MEMBASE 0x2000 /* Memory Base Address */ #define HIFN7811_CMDD 0x2000 /* Command Descriptors */ #define HIFN7811_SRCD 0x2040 /* Source Decsriptors */ #define HIFN7811_RESD 0x2080 /* Result Descriptors */ #define HIFN7811_DSTD 0x20c0 /* Destination Descriptors */ #define HIFN7811_PKTDATA 0x2100 /* Packet data */ #define HIFN7811_MEMMAX 0x4000 /* Maximum address offset */ #define HIFN7811_MEMSIZE 0x2000 /* Size of internal memory */ /* * Register offsets within register table. */ #define HIFN7811_GC 0x0004 /* General Configuration */ #define HIFN7811_ID 0x0008 /* Chip ID */ #define HIFN7811_HCI 0x0080 /* Host Command Index */ #define HIFN7811_HSI 0x0084 /* Host Source Index */ #define HIFN7811_HRI 0x0088 /* Host Result Index */ #define HIFN7811_HDI 0x008c /* Host Destination Index */ #define HIFN7811_PKTS 0x0090 /* Packet Status */ #define HIFN7811_PKTIE 0x0094 /* Packet Interrupt Enable */ #define HIFN7811_PKTC 0x0098 /* Packet Configuration */ #define HIFN7811_PBA 0x0100 /* Public Base Address */ #define HIFN7811_POL 0x0104 /* Public Operand Length */ #define HIFN7811_PO 0x0108 /* Public Operand */ #define HIFN7811_PS 0x010c /* Public Status */ #define HIFN7811_PIE 0x0110 /* Public Interrupt Enable */ #define HIFN7811_RNGC 0x0114 /* RNG Configuration */ #define HIFN7811_RNGD 0x0118 /* RNG Data */ #define HIFN7811_PKTS_DLAST(x) (((x) >> 24) & 0x1) #define HIFN7811_PKTS_DINDEX(x) (((x) >> 20) & 0xf) #define HIFN7811_PKTS_RINDEX(x) (((x) >> 14) & 0xf) #define HIFN7811_PKTS_SINDEX(x) (((x) >> 8) & 0xf) #define HIFN7811_PKTS_CINDEX(x) (((x) >> 2) & 0xf) /* * Defines to support the Security Engine Control register. */ /* * Defines to support Chip ID register. */ #define HIFN7811_ID_PRODREV 0x00000800 /* Product/Revision ID 7811 */ /* * Define Random Number Generator Configuration flags. */ #define HIFN7811_RNGC_ENABLE 0x00000001 /* Enable RNG */ #define HIFN7811_DESCR_CNT (8) //#define LE32(a) (((a)>>24) | (((a)>>8)&0xff00) | (((a)<<8)&0xff0000) | ((a)<<24)) #define LE32(a) a /*************************************** GROUP 0 Registers definition ***************************************/ enum grp0_se_control { SE_CONTROL_MUST_BIT = LE32(0x2), SE_CONTROL_RESET = LE32(0x1) }; /* This works for ISR and IER */ enum grp0_se_interrupts { SE_INVCMD = LE32(0x8000), SE_DATAERR = LE32(0x4000), SE_SRC_FIFO_READY = LE32(0x2000), SE_DST_FIFO_READY = LE32(0x1000), SE_DST_OVERRUN = LE32(0x0200), SE_SRC_CMD = LE32(0x0080), SE_SRC_CONTEXT = LE32(0x0040), SE_SRC_DATA = LE32(0x0020), SE_DST_DATA = LE32(0x0010), SE_DST_RESULT = LE32(0x0004) }; enum grp0_se_config { SE_CONFIG_DEFAULT = LE32(0x340), SE_CONFIG_COMP_CFG=LE32(0x344), SE_CONFIG_ENCRYPT_CFG=LE32(0x342) }; #define SE_FIFO_CONFIG_DEFAULT LE32(0x00000400) /* Group 0 PCI register set */ struct hifn7811grp0 { u32 se_data; u32 se_control; u32 se_isr; /* Interrupt Status Reg */ u32 se_config; u32 se_ier; /* Interrupt Enable Reg */ u32 se_status; u32 se_fifo_status; u32 se_fifo_config; }; /***************************************** GROUP 1 Register definition ******************************************/ /* Group 1 PCI registers */ #define SE_RING_MASK LE32(0xfffffffc) enum grp1_se_status_ctrl { /* See STATUS_BITS macro as well */ SE_ILLEGAL_WRITE= LE32(0x200), SE_ILLEGAL_READ= LE32(0x100), SE_ENGINE_IRQ= LE32(0x001) /* Rings */ #define RING_DST 3 #define RING_SRC 1 #define RING_CMD 0 #define RING_RES 2 /* cmd */ #define CMD_ENABLE 0x80 #define CMD_DISABLE 0x40 #define CMD_IS_PCI_ABORT 0x20 #define CMD_IS_LAST 0x08 #define CMD_IS_DONE 0x10 #define CMD_IS_WAITING 0x04 #define CMD_IS_OVER 0x02 /* For DST and RES ring only */ #define STATUS_BITS(ring,cmd) LE32(((cmd) << ((ring)*8)) ) /* USE ME!! */ }; /* DMA configuration */ enum grp1_dma_config { SE_INBOUND_BE= LE32(0x20000003), SE_OUTBOUND_BE= LE32(0x10000003), SE_DST_ADDR_MIPS= LE32(0x08000003), SE_RES_ADDR_MIPS= LE32(0x04000003), SE_SRC_ADDR_MIPS= LE32(0x02000003), SE_CMD_ADDR_MIPS= LE32(0x01000003), #define SE_POLL_FREQ(freq) LE32(((((unsigned char)freq) << 16) | 0x3)) SE_GPRAM_BE= LE32(0x00008003), /* ProtMem left as exercise */ #define SE_POLL_SCALE(sc) LE32(((((sc) & 0x7) << 8) | 0x3)) SE_SW_LAST= LE32(0x00000013), SE_DMARESET= LE32(0x00000001), SE_MSTRRESET= LE32(0x00000002) }; /* Random Number Generator */ #define RNG_ENABLE LE32(0x1) #define RNG_DISABLE LE32(0x0) #define RNG_PRESCALE(a) LE32((((unsigned char)(a)) << 8)) #define RNG_READY LE32(0x4000) #define RNG_UNDERFLOW LE32(0x1000) /* No MIPS register . Today\'s friday. (and not required...) */ #define MIPS_CFG_SE_PCI_INTS LE32(0x4000) /* No GPRAM registers. Idem. */ enum grp1_global_status { GL_SE_DST_DONE= LE32(0x80000000), GL_SE_DST_WAITING= LE32(0x40000000), GL_SE_RES_DONE= LE32(0x20000000), GL_SE_RES_WAITING= LE32(0x10000000), GL_SE_SRC_DONE= LE32(0x08000000), GL_SE_SRC_WAITING= LE32(0x04000000), GL_SE_CMD_DONE= LE32(0x02000000), GL_SE_CMD_WAITING= LE32(0x01000000), /* DO the GPDMA stuff..............later (ie: never) */ GL_ABORT_OVERFLOW= LE32(0x00000080), GL_MIPS_RW_ERROR= LE32(0x00000040), GL_PIPELINE_INT= LE32(0x00000020), GL_PCI_INTERRUPT= LE32(0x00000010), GL_MIPS_INTERRUPT= LE32(0x00000008), GL_SE_INTERRUPT= LE32(0x00000004), GL_GPDMA3_4_INT= LE32(0x00000002), GL_GPDMA1_2_INT= LE32(0X00000001) }; struct hifn7811_ring { u32 dummy[3]; u32 reg; }; #define se_cmd_addr se_cmd.reg #define se_src_addr se_src.reg #define se_res_addr se_res.reg #define se_dst_addr se_dst.reg struct hifn7811grp1 { struct hifn7811_ring se_cmd; struct hifn7811_ring se_src; struct hifn7811_ring se_res; struct hifn7811_ring se_dst; u32 se_status_ctrl; u32 se_ier; /* Interrupt Enable Reg */ u32 se_dma_config; u32 pci_addr_or_mask; u32 pci_int_reg; u32 pci_ier; u32 mips_int_reg; u32 mips_imr; /* Interrupt Mask register */ u32 rng_enable; u32 rng_config; u32 rng_data; u32 rng_status; u32 mips_SDRAM1_addr; u32 mips_SDRAM2_addr; u32 mips_Group1_addr; u32 mips_Group0_addr; u32 mips_pci1_addr; u32 mips_pci2_addr; u32 mips_pci1_tran; u32 mips_pci2_tran; u32 mips_config; u32 mips_reset; u32 revision_number; u32 EEPROM_data; u32 GPDMA1_src; u32 GPDMA2_src; u32 GPDMA1_dst; u32 GPDMA2_dst; u32 GPDMA1_2_arbitration; u32 GPDMA1_2_config; u32 GPDMA1_2_status; u32 GPDMA1_2_ier; u32 pci_BAR0_shadow; u32 pci_BAR1_shadow; u32 pci_BAR2_shadow; u32 SDRAM_config; u32 GPDMA3_src; u32 GPDMA4_src; u32 GPDMA3_dst; u32 GPDMA4_dst; u32 GPDMA3_4_arbitration; u32 GPDMA3_4_config; u32 GPDMA3_4_status; u32 GPDMA3_4_ier; u32 global_status; u32 test_set; }; /* * Descriptor defines. */ struct hifn7811desc { unsigned long cmd; unsigned long ptr; }; #define HIFN7811_DESC_LAST 0x20000000 /* Last fragment */ #define HIFN7811_DESC_MASKDONE 0x02000000 /* Mask done status */ #define HIFN7811_DESC_VALID 0x80000000 /* Valid bit */ #define HIFN7811_DESC_JUMP 0x40000000 #define HIFN7811_DESC_NOVALID 0x01000000 #define HIFN7811_DESC_ADD32 0x00800000 #define HIFN7811_DESC_MIPSADDR 0x00400000 #define HIFN7811_DESC_BE 0x00200000 /* Big Endian? */ #define HIFN7811_DESC_LENMASK 0x0000ffff /* Mask for buffer length */ /* Set by chip, results */ #define HIFN7811_DESC_OVERFLOW 0x08000000 #define HIFN7811_DESC_DST_OVERFLOW 0x04000000 /* * Base Command Structure. */ struct hifn7811cmd { unsigned long cmd; unsigned short scount; unsigned short dcount; }; #define HIFN7811_CMD_SES(x) ((((x) & 0xff) << 8) | (((x) >> 8) & 0xf)) #define HIFN7811_CMD_COMP 0x00010000 /* Enable compression */ #define HIFN7811_CMD_PAD 0x00020000 /* Enable padding */ #define HIFN7811_CMD_MAC 0x00040000 /* Enable mac processing */ #define HIFN7811_CMD_ENCRYPT 0x00080000 /* Enable encryption */ #define HIFN7811_CMD_ENCODE 0x00000000 /* Encode basic command */ #define HIFN7811_CMD_DECODE 0x00200000 /* Decode basic command */ #define HIFN7811_CMD_READRAM 0x00400000 /* Read RAM basic command */ #define HIFN7811_CMD_WRITERAM 0x00600000 /* Write RAM basic command */ #define HIFN7811_SWAPB(x) ((((x) & 0xff) << 8) | (((x) >> 8) & 0xff)) /* * Compress Command Structure. */ struct hifn7811comp { unsigned short cmd; unsigned short hdrcnt; unsigned short srccnt; unsigned short reserved; }; #define HIFN7811_COMP_LZS 0x0001 /* LZS compression */ #define HIFN7811_COMP_MPPC 0x0101 /* MPPC compression */ #define HIFN7811_COMP_STRIP0 0x0400 /* LZS strip 0 mode */ #define HIFN7811_COMP_RESTART 0x0400 /* MPPC restart mode */ #define HIFN7811_COMP_UPDTHIST 0x0800 /* Update decompress history */ #define HIFN7811_COMP_CLEARHIST 0x1000 /* Clear compress history */ /* * Pad Command Structure. */ struct hifn7811pad { unsigned short cmd; unsigned short srccnt; }; #define HIFN7811_PAD_MODE0 0x00000000 /* Mode 0 algorithm */ #define HIFN7811_PAD_MODE1 0x01000000 /* Mode 1 algorithm */ #define HIFN7811_PAD_MODE2 0x02000000 /* Mode 2 algorithm */ #define HIFN7811_PAD_MODE3 0x03000000 /* Mode 3 algorithm */ #define HIFN7811_PAD_CNTMODEM 0x00200000 /* Decrement count mode */ /* * MAC Command Structure. */ struct hifn7811mac { unsigned short cmd; unsigned short hdrcnt; unsigned short srccnt; unsigned short reserved; }; #define HIFN7811_MAC_COMP2PAD 0x0000 /* Compress->MAC->Padding */ #define HIFN7811_MAC_PAD2ENC 0x0001 /* Padding->MAC->Encryption */ #define HIFN7811_MAC_AEBD 0x0002 /* After encode,before decode */ #define HIFN7811_MAC_NEWKEY 0x0008 /* New key */ #define HIFN7811_MAC_CNTMODE 0x0020 /* Continue counting */ #define HIFN7811_MAC_SHA 0x0000 /* SHA mode */ #define HIFN7811_MAC_MD5 0x0100 /* MD5 mode */ #define HIFN7811_MAC_HMAC 0x0000 /* HMAC mode */ #define HIFN7811_MAC_SSL 0x0400 /* SSL MAC mode */ #define HIFN7811_MAC_HASH 0x0800 /* HASH only */ #define HIFN7811_MAC_TRUNC 0x1000 /* Truncate to 12 bytes */ #define HIFN7811_MAC_RESULT 0x2000 /* Generate result */ #define HIFN7811_MAC_INSERT 0x4000 /* Insert MAC in data */ /* * Encryption Command Structure. */ struct hifn7811enc { unsigned short cmd; unsigned short hdrcnt; unsigned short srccnt; unsigned short reserved; }; #define HIFN7811_ENC_NEWKEY 0x0008 /* New key */ #define HIFN7811_ENC_NEWIV 0x0010 /* New initialization vector */ #define HIFN7811_ENC_CNTMODE 0x0020 /* Continue counting */ #define HIFN7811_ENC_DES 0x0000 /* DES encryption */ #define HIFN7811_ENC_3DES 0x0100 /* Triple DES encryption */ #define HIFN7811_ENC_RC4 0x0200 /* RC4 encryption */ #define HIFN7811_ENC_ECB 0x0000 /* ECB DES mode */ #define HIFN7811_ENC_CBC 0x0800 /* CBC DES mode */ #define HIFN7811_ENC_CFB64 0x1000 /* CFB-64 DES mode */ #define HIFN7811_ENC_OFB 0x1800 /* CFB DES mode */ #define HIFN7811_ENC_CLEAR 0x4000 /* Clear context */ /* * Base Result Structure. */ struct hifn7811res { unsigned long cmd; unsigned short srccnt; unsigned short dstcnt; }; #define HIFN7811_RES_SES HIFN7811_CMD_SES #define HIFN7811_RES_DSTOVERRUN 0x0002000 /* Destination overrun */ /* * Compression Result Structure. */ struct hifn7811compres { unsigned short cmd; unsigned short crc; }; #define HIFN7811_COMPRES_NZERO 0x0100 /* Source count non-zero */ #define HIFN7811_COMPRES_LZSEND 0x0200 /* LZS reached end marker */ #define HIFN7811_COMPRES_RSTART 0x0400 /* MPPC restart */ #define HIFN7811_COMPRES_LCBMSK 0x00ff /* LCB check byte mask */ /* * MAC Result Structure. */ struct hifn7811macres { unsigned long cmd; /* unsigned char hash[20]; */ }; #define HIFN7811_MACRES_NZERO 0x01000000 /* Source count non-zero */ #define HIFN7811_MACRES_MISCMP 0x02000000 /* Mis-compare result */ /* * Encryption Result Structure. */ struct hifn7811encres { unsigned long cmd; }; #define HIFN7811_ENCRES_NZERO 0x01000000 /* Source count non-zero */ /****************************************************************************/ #endif /* _HIFN7811_H_ */ 头文件2#ifndef __IF_CRYPTO_H #define __IF_CRYPTO_H #include <openssl/rc4.h> #include <linux/des_locl.h> #include <linux/malloc.h> typedef struct RC4_KEY_HW { unsigned char raw[16]; /* Raw key */ int len; /* Key len */ } RC4_KEY_HW; typedef unsigned short crypto_cmd_t; struct crypto_engine_def; struct crypto_request { char *inbuf; /* Input buffer */ char *outbuf; /* Output buffer */ int inlen; /* Length of input buffer */ int outlen; /* On input, max size. On Output, real size of output */ unsigned int flags; struct crypto_engine_def *engine; /* Engine to use. If NULL, use best one */ struct crypto_operation { crypto_cmd_t cmd; /* Operation to perform */ int offset; /* Offset, from inbuf, to start operation */ int len; /* Length of operation */ union { struct CRYPTO_RC4 { struct RC4_KEY_HW *key; } rc4; struct CRYPTO_DES { des_cblock key[3]; /* For DES, key[0] only is used */ des_cblock *ivec; /* NULL if no ivec */ } des; struct CRYPTO_HASH { unsigned char hmac_key[64]; unsigned char hmac_key_len; unsigned char result[20]; /* On output, contains the hash result */ unsigned char reslen; /* Contains the result len */ } hash; } u; struct crypto_operation *next; /* If non-NULL, pointer to next operation to perform on buffer * Users are responsable for memory allocated for *next */ } op; void (*callback)(struct crypto_request *); /* function to call when done request. This struct * is passed as argument. */ void *priv; /* Private to requester */ }; /* Commands */ #define CRYPT_NO_OP 0x00 #define CRYPT_ENCODE 0x00 #define CRYPT_DECODE 0x80 #define CRYPT_RC4 0x01 #define CRYPT_DES 0x02 /* Should not be used... insecure (key space too small) */ #define CRYPT_3DES 0x04 # define CRYPT_ECB 0x08 /* Meaningful only for [3]DES */ # define CRYPT_CBC 0x10 /* Meaningful only for [3]DES */ #define CRYPT_MD5 0x20 #define CRYPT_SHA 0x40 # define CRYPT_HMAC 0x08 /* Meaningful only for MD5|SHA */ # define CRYPT_96 0x10 /* Meaningful only for MD5|SHA */ # define CRYPT_APPEND 0x100 /* Meaningful only for MD5|SHA, append hash to output */ #define CRYPT_RANDOM 0x200 /* Get some random bytes in outbuf */ /* Flags */ #define CRYPT_SYNC 0x1 /* Must wait for completion */ #define CRYPT_HIGH_PRIORITY 0x2 /* Process in priority (insert at end of queue) */ #define CRYPT_DATA 0x4 /* Use to filter data from other stuff */ #define CRYPT_SOFTWARE 0x8 /* Force software, or in output, was done in Software automagically */ #define CRYPT_HARDWARE 0x10 /* Force hardware, or in output, was done in Hardware */ /* Return codes */ #define CRYPT_READY 1 #define CRYPT_OK 0 #define CRYPT_ERROR -1 #define CRYPT_NO_RESSOURCE -2 enum crypto_engine_attributes { IS_SOFTWARE =0x01, IS_HARDWARE =0x02, IS_ASYNC =0x04, /* Can return CRYPT_OK and calls back when done */ IS_SYNC =0x08 /* Can be instructed to wait until completion (BUSY LOOPING?!) */ }; /* Prototypes */ struct crypto_request *crypto_alloc_request(int flags); int crypto_execute(struct crypto_request *req); int crypto_query(crypto_cmd_t cap,unsigned int attrib); /* Returns TRUE when there is an engine that matches */ /* Optionnaly, open the engine to use and put it in req->engine */ struct crypto_engine_def *crypto_open_engine(crypto_cmd_t cap,unsigned int attrib); void crypto_close_engine(struct crypto_engine_def *eng); static inline void crypto_free_request(struct crypto_request *r) { kfree(r); } /************************************************** * * For crypto providers * ***************************************************/ struct crypto_engine_def { char *name; crypto_cmd_t capability; unsigned int attributes; int (*request_handler)(struct crypto_request *req); void (*open)(void); void (*close)(void); }; int crypto_register_engine(struct crypto_engine_def *eng); int crypto_unregister_engine(char *name); #endif |
|
|
地板#
发布于:2002-06-21 13:42
你这桶水浓度不小嘛,我得慢慢看看。。。
关于卡工作原理方面的资料有连接什么的吗?或者给我邮一个?moqingsong@sohu.com |
|
|
地下室#
发布于:2002-06-25 09:50
kao,相关资源早在第一桶水里就给出来了.这个只是把东东拿出来了而已.看来还得自已来...
|
|
|
5楼#
发布于:2002-06-25 10:12
惭愧,没好好看。。。。。
|
|
|
6楼#
发布于:2002-06-25 11:07
.cim文件用什么打开看?
哦,我好笨呀。。。 |
|
|