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

📄 crypto.c

📁 linux下基于加密芯片的加密设备
💻 C
📖 第 1 页 / 共 3 页
字号:
	if ((crp->crp_flags & CRYPTO_F_DONE) != 0)		printk("crypto: crypto_done op already done, flags 0x%x",				crp->crp_flags);	crp->crp_flags |= CRYPTO_F_DONE;	if (crp->crp_etype != 0)		cryptostats.cs_errs++;	/*	 * CBIMM means unconditionally do the callback immediately;	 * CBIFSYNC means do the callback immediately only if the	 * operation was done synchronously.  Both are used to avoid	 * doing extraneous context switches; the latter is mostly	 * used with the software crypto driver.	 */	if ((crp->crp_flags & CRYPTO_F_CBIMM) ||	    ((crp->crp_flags & CRYPTO_F_CBIFSYNC) &&	     (CRYPTO_SESID2CAPS(crp->crp_sid) & CRYPTOCAP_F_SYNC))) {		/*		 * Do the callback directly.  This is ok when the		 * callback routine does very little (e.g. the		 * /dev/crypto callback method just does a wakeup).		 */		crp->crp_callback(crp);	} else {		int wasempty, r_flags;		/*		 * Normal case; queue the callback for the thread.		 */		CRYPTO_RETQ_LOCK();		wasempty = list_empty(&crp_ret_q);		list_add_tail(&crp->crp_list, &crp_ret_q);		if (wasempty)			wake_up_interruptible(&cryptoretproc_wait);	/*shared wait channel */		CRYPTO_RETQ_UNLOCK();	}}/* * Invoke the callback on behalf of the driver. */voidcrypto_kdone(struct cryptkop *krp){	int wasempty, r_flags;	if (krp->krp_status != 0)		cryptostats.cs_kerrs++;	CRYPTO_RETQ_LOCK();	wasempty = list_empty(&crp_ret_kq);	list_add_tail(&krp->krp_list, &crp_ret_kq);	if (wasempty)		wake_up_interruptible(&cryptoretproc_wait);	/* shared wait channel */	CRYPTO_RETQ_UNLOCK();}intcrypto_getfeat(int *featp){	int hid, kalg, feat = 0, d_flags;	if (!crypto_userasymcrypto)		goto out;	  	CRYPTO_DRIVER_LOCK();	for (hid = 0; hid < crypto_drivers_num; hid++) {		if ((crypto_drivers[hid].cc_flags & CRYPTOCAP_F_SOFTWARE) &&		    !crypto_devallowsoft) {			continue;		}		if (crypto_drivers[hid].cc_kprocess == NULL)			continue;		for (kalg = 0; kalg < CRK_ALGORITHM_MAX; kalg++)			if ((crypto_drivers[hid].cc_kalg[kalg] &			    CRYPTO_ALG_FLAG_SUPPORTED) != 0)				feat |=  1 << kalg;	}	CRYPTO_DRIVER_UNLOCK();out:	*featp = feat;	return (0);}/* * Crypto thread, dispatches crypto requests. */static intcrypto_proc(void *arg){	struct cryptop *crp, *submit;	struct cryptkop *krp, *krpp;	struct cryptocap *cap;	int result, hint, q_flags;	daemonize();	spin_lock_irq(&current->sigmask_lock);	sigemptyset(&current->blocked);	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);	sprintf(current->comm, "crypto");	CRYPTO_Q_LOCK();	for (;;) {		/*		 * Find the first element in the queue that can be		 * processed and look-ahead to see if multiple ops		 * are ready for the same driver.		 */		submit = NULL;		hint = 0;		list_for_each_entry(crp, &crp_q, crp_list) {			u_int32_t hid = CRYPTO_SESID2HID(crp->crp_sid);			cap = crypto_checkdriver(hid);			if (cap == NULL || cap->cc_process == NULL) {				/* Op needs to be migrated, process it. */				if (submit == NULL)					submit = crp;				break;			}			if (!cap->cc_qblocked) {				if (submit != NULL) {					/*					 * We stop on finding another op,					 * regardless whether its for the same					 * driver or not.  We could keep					 * searching the queue but it might be					 * better to just use a per-driver					 * queue instead.					 */					if (CRYPTO_SESID2HID(submit->crp_sid) == hid)						hint = CRYPTO_HINT_MORE;					break;				} else {					submit = crp;					if ((submit->crp_flags & CRYPTO_F_BATCH) == 0)						break;					/* keep scanning for more are q'd */				}			}		}		if (submit != NULL) {			list_del(&submit->crp_list);			result = crypto_invoke(submit, hint);			if (result == ERESTART) {				/*				 * The driver ran out of resources, mark the				 * driver ``blocked'' for cryptop's and put				 * the request back in the queue.  It would				 * best to put the request back where we got				 * it but that's hard so for now we put it				 * at the front.  This should be ok; putting				 * it at the end does not work.				 */				/* XXX validate sid again? */				crypto_drivers[CRYPTO_SESID2HID(submit->crp_sid)].cc_qblocked = 1;				list_add(&submit->crp_list, &crp_q);				cryptostats.cs_blocks++;			}		}		/* As above, but for key ops */		krp = NULL;		list_for_each_entry(krpp, &crp_kq, krp_list) {			cap = crypto_checkdriver(krpp->krp_hid);			if (cap == NULL || cap->cc_kprocess == NULL) {				/* Op needs to be migrated, process it. */				krp = krpp;				break;			}			if (!cap->cc_kqblocked) {				krp = krpp;				break;			}		}		if (krp != NULL) {			list_del(&krp->krp_list);			result = crypto_kinvoke(krp, 0);			if (result == ERESTART) {				/*				 * The driver ran out of resources, mark the				 * driver ``blocked'' for cryptkop's and put				 * the request back in the queue.  It would				 * best to put the request back where we got				 * it but that's hard so for now we put it				 * at the front.  This should be ok; putting				 * it at the end does not work.				 */				/* XXX validate sid again? */				crypto_drivers[krp->krp_hid].cc_kqblocked = 1;				list_add(&krp->krp_list, &crp_kq);				cryptostats.cs_kblocks++;			}		}		if (submit == NULL && krp == NULL) {			/*			 * Nothing more to be processed.  Sleep until we're			 * woken because there are more ops to process.			 * This happens either by submission or by a driver			 * becoming unblocked and notifying us through			 * crypto_unblock.  Note that when we wakeup we			 * start processing each queue again from the			 * front. It's not clear that it's important to			 * preserve this ordering since ops may finish			 * out of order if dispatched to different devices			 * and some become blocked while others do not.			 */			dprintk("%s - sleeping\n", __FUNCTION__);			CRYPTO_Q_UNLOCK();			wait_event_interruptible(cryptoproc_wait,					cryptoproc == (pid_t) -1 ||					!list_empty(&crp_q) ||					!list_empty(&crp_kq));			if (signal_pending (current)) {				spin_lock_irq(&current->sigmask_lock);				flush_signals(current);				spin_unlock_irq(&current->sigmask_lock);			}			CRYPTO_Q_LOCK();			dprintk("%s - awake\n", __FUNCTION__);			if (cryptoproc == (pid_t) -1)				break;			cryptostats.cs_intrs++;		}	}	CRYPTO_Q_UNLOCK();	complete_and_exit(&cryptoproc_exited, 0);}/* * Crypto returns thread, does callbacks for processed crypto requests. * Callbacks are done here, rather than in the crypto drivers, because * callbacks typically are expensive and would slow interrupt handling. */static intcrypto_ret_proc(void *arg){	struct cryptop *crpt;	struct cryptkop *krpt;	int r_flags;	daemonize();	spin_lock_irq(&current->sigmask_lock);	sigemptyset(&current->blocked);	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);	sprintf(current->comm, "crypto_ret");	CRYPTO_RETQ_LOCK();	for (;;) {		/* Harvest return q's for completed ops */		crpt = NULL;		if (!list_empty(&crp_ret_q))			crpt = list_entry(crp_ret_q.next, typeof(*crpt), crp_list);		if (crpt != NULL)			list_del(&crpt->crp_list);		krpt = NULL;		if (!list_empty(&crp_ret_kq))			krpt = list_entry(crp_ret_kq.next, typeof(*krpt), krp_list);		if (krpt != NULL)			list_del(&krpt->krp_list);		if (crpt != NULL || krpt != NULL) {			CRYPTO_RETQ_UNLOCK();			/*			 * Run callbacks unlocked.			 */			if (crpt != NULL)				crpt->crp_callback(crpt);			if (krpt != NULL)				krpt->krp_callback(krpt);			CRYPTO_RETQ_LOCK();		} else {			/*			 * Nothing more to be processed.  Sleep until we're			 * woken because there are more returns to process.			 */			dprintk("%s - sleeping\n", __FUNCTION__);			CRYPTO_RETQ_UNLOCK();			wait_event_interruptible(cryptoretproc_wait,					cryptoretproc == (pid_t) -1 ||					!list_empty(&crp_ret_q) ||					!list_empty(&crp_ret_kq));			if (signal_pending (current)) {				spin_lock_irq(&current->sigmask_lock);				flush_signals(current);				spin_unlock_irq(&current->sigmask_lock);			}			CRYPTO_RETQ_LOCK();			dprintk("%s - awake\n", __FUNCTION__);			if (cryptoretproc == (pid_t) -1)				break;			cryptostats.cs_rets++;		}	}	CRYPTO_RETQ_UNLOCK();	complete_and_exit(&cryptoretproc_exited, 0);}static intcrypto_init(void){	int error;	dprintk("%s(0x%x)\n", __FUNCTION__, (int) crypto_init);	if (crypto_initted)		return 0;	crypto_initted = 1;	spin_lock_init(&crypto_drivers_lock);	spin_lock_init(&crypto_q_lock);	spin_lock_init(&crypto_ret_q_lock);	cryptop_zone = kmem_cache_create("cryptop", sizeof(struct cryptop),				       0, SLAB_HWCACHE_ALIGN, NULL, NULL);	cryptodesc_zone = kmem_cache_create("cryptodesc", sizeof(struct cryptodesc),				       0, SLAB_HWCACHE_ALIGN, NULL, NULL);	if (cryptodesc_zone == NULL || cryptop_zone == NULL) {		printk("crypto: crypto_init cannot setup crypto zones\n");		error = ENOMEM;		goto bad;	}	crypto_drivers_num = CRYPTO_DRIVERS_INITIAL;	crypto_drivers = kmalloc(crypto_drivers_num * sizeof(struct cryptocap),			GFP_KERNEL);	if (crypto_drivers == NULL) {		printk("crypto: crypto_init cannot setup crypto drivers\n");		error = ENOMEM;		goto bad;	}	memset(crypto_drivers, 0, crypto_drivers_num * sizeof(struct cryptocap));	init_completion(&cryptoproc_exited);	init_completion(&cryptoretproc_exited);	cryptoproc = kernel_thread(crypto_proc, NULL, CLONE_FS|CLONE_FILES);	if (cryptoproc < 0) {		error = cryptoproc;		printk("crypto: crypto_init cannot start crypto thread; error %d",			error);		goto bad;	}	cryptoretproc = kernel_thread(crypto_ret_proc, NULL, CLONE_FS|CLONE_FILES);	if (cryptoretproc < 0) {		error = cryptoretproc;		printk("crypto: crypto_init cannot start cryptoret thread; error %d",				error);		goto bad;	}	return 0;bad:	crypto_exit();	return error;}static voidcrypto_exit(void){	pid_t p;	int d_flags;	dprintk("%s()\n", __FUNCTION__);	/*	 * Terminate any crypto threads.	 */	CRYPTO_DRIVER_LOCK();	p = cryptoproc;	cryptoproc = (pid_t) -1;	kill_proc(p, SIGTERM, 1);	wake_up_interruptible(&cryptoproc_wait);	wait_for_completion(&cryptoproc_exited);	p = cryptoretproc;	cryptoretproc = (pid_t) -1;	kill_proc(p, SIGTERM, 1);	wake_up_interruptible(&cryptoretproc_wait);	wait_for_completion(&cryptoretproc_exited);	CRYPTO_DRIVER_UNLOCK();	/* XXX flush queues??? */	/* 	 * Reclaim dynamically allocated resources.	 */	if (crypto_drivers != NULL)		kfree(crypto_drivers);	if (cryptodesc_zone != NULL)		kmem_cache_destroy(cryptodesc_zone);	if (cryptop_zone != NULL)		kmem_cache_destroy(cryptop_zone);}EXPORT_SYMBOL(crypto_newsession);EXPORT_SYMBOL(crypto_freesession);EXPORT_SYMBOL(crypto_get_driverid);EXPORT_SYMBOL(crypto_kregister);EXPORT_SYMBOL(crypto_register);EXPORT_SYMBOL(crypto_unregister);EXPORT_SYMBOL(crypto_unregister_all);EXPORT_SYMBOL(crypto_unblock);EXPORT_SYMBOL(crypto_dispatch);EXPORT_SYMBOL(crypto_kdispatch);EXPORT_SYMBOL(crypto_freereq);EXPORT_SYMBOL(crypto_getreq);EXPORT_SYMBOL(crypto_done);EXPORT_SYMBOL(crypto_kdone);EXPORT_SYMBOL(crypto_getfeat);module_init(crypto_init);module_exit(crypto_exit);MODULE_LICENSE("BSD");MODULE_AUTHOR("davidm@snapgear.com");MODULE_DESCRIPTION("OCF (OpenBSD Cryptographic Framework)");

⌨️ 快捷键说明

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