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

📄 crypto.c

📁 linux下基于加密芯片的加密设备
💻 C
📖 第 1 页 / 共 3 页
字号:
	    (CRYPTO_ALGORITHM_MIN <= alg && alg <= CRYPTO_ALGORITHM_MAX)) {		/*		 * XXX Do some performance testing to determine placing.		 * XXX We probably need an auxiliary data structure that		 * XXX describes relative performances.		 */		cap->cc_alg[alg] = flags | CRYPTO_ALG_FLAG_SUPPORTED;		cap->cc_max_op_len[alg] = maxoplen;		if (crypto_verbose)			printk("crypto: driver %u registers alg %u flags %u maxoplen %u\n"				, driverid				, alg				, flags				, maxoplen			);		if (cap->cc_process == NULL) {			cap->cc_arg = arg;			cap->cc_newsession = newses;			cap->cc_process = process;			cap->cc_freesession = freeses;			cap->cc_sessions = 0;		/* Unmark */		}		err = 0;	} else		err = EINVAL;	CRYPTO_DRIVER_UNLOCK();	return err;}/* * Unregister a crypto driver. If there are pending sessions using it, * leave enough information around so that subsequent calls using those * sessions will correctly detect the driver has been unregistered and * reroute requests. */intcrypto_unregister(u_int32_t driverid, int alg){	int i, err, d_flags;	u_int32_t ses;	struct cryptocap *cap;	dprintk("%s()\n", __FUNCTION__);	CRYPTO_DRIVER_LOCK();	cap = crypto_checkdriver(driverid);	if (cap != NULL &&	    (CRYPTO_ALGORITHM_MIN <= alg && alg <= CRYPTO_ALGORITHM_MAX) &&	    cap->cc_alg[alg] != 0) {		cap->cc_alg[alg] = 0;		cap->cc_max_op_len[alg] = 0;		/* Was this the last algorithm ? */		for (i = 1; i <= CRYPTO_ALGORITHM_MAX; i++)			if (cap->cc_alg[i] != 0)				break;		if (i == CRYPTO_ALGORITHM_MAX + 1) {			ses = cap->cc_sessions;			memset(cap, 0, sizeof(struct cryptocap));			if (ses != 0) {				/*				 * If there are pending sessions, just mark as invalid.				 */				cap->cc_flags |= CRYPTOCAP_F_CLEANUP;				cap->cc_sessions = ses;			}		}		err = 0;	} else		err = EINVAL;	CRYPTO_DRIVER_UNLOCK();	return err;}/* * Unregister all algorithms associated with a crypto driver. * If there are pending sessions using it, leave enough information * around so that subsequent calls using those sessions will * correctly detect the driver has been unregistered and reroute * requests. */intcrypto_unregister_all(u_int32_t driverid){	int i, err, d_flags;	u_int32_t ses;	struct cryptocap *cap;	dprintk("%s()\n", __FUNCTION__);	CRYPTO_DRIVER_LOCK();	cap = crypto_checkdriver(driverid);	if (cap != NULL) {		for (i = CRYPTO_ALGORITHM_MIN; i <= CRYPTO_ALGORITHM_MAX; i++) {			cap->cc_alg[i] = 0;			cap->cc_max_op_len[i] = 0;		}		ses = cap->cc_sessions;		memset(cap, 0, sizeof(struct cryptocap));		if (ses != 0) {			/*			 * If there are pending sessions, just mark as invalid.			 */			cap->cc_flags |= CRYPTOCAP_F_CLEANUP;			cap->cc_sessions = ses;		}		err = 0;	} else		err = EINVAL;	CRYPTO_DRIVER_UNLOCK();	return err;}/* * Clear blockage on a driver.  The what parameter indicates whether * the driver is now ready for cryptop's and/or cryptokop's. */intcrypto_unblock(u_int32_t driverid, int what){	struct cryptocap *cap;	int needwakeup, err, q_flags;	dprintk("%s()\n", __FUNCTION__);	CRYPTO_Q_LOCK();	cap = crypto_checkdriver(driverid);	if (cap != NULL) {		needwakeup = 0;		if (what & CRYPTO_SYMQ) {			needwakeup |= cap->cc_qblocked;			cap->cc_qblocked = 0;		}		if (what & CRYPTO_ASYMQ) {			needwakeup |= cap->cc_kqblocked;			cap->cc_kqblocked = 0;		}		if (needwakeup)			wake_up_interruptible(&cryptoproc_wait);		err = 0;	} else		err = EINVAL;	CRYPTO_Q_UNLOCK();	return err;}/* * Add a crypto request to a queue, to be processed by the kernel thread. */intcrypto_dispatch(struct cryptop *crp){	u_int32_t hid = CRYPTO_SESID2HID(crp->crp_sid);	int result, q_flags;	dprintk("%s()\n", __FUNCTION__);	cryptostats.cs_ops++;	CRYPTO_Q_LOCK();	if ((crp->crp_flags & CRYPTO_F_BATCH) == 0) {		struct cryptocap *cap;		/*		 * Caller marked the request to be processed		 * immediately; dispatch it directly to the		 * driver unless the driver is currently blocked.		 */		cap = crypto_checkdriver(hid);		if (cap && !cap->cc_qblocked) {			result = crypto_invoke(crp, 0);			if (result == ERESTART) {				/*				 * The driver ran out of resources, mark the				 * driver ``blocked'' for cryptop's and put				 * the request on the queue.				 *				 * XXX ops are placed at the tail so their				 * order is preserved but this can place them				 * behind batch'd ops.				 */				crypto_drivers[hid].cc_qblocked = 1;				list_add_tail(&crp->crp_list, &crp_q);				cryptostats.cs_blocks++;				result = 0;			}		} else {			/*			 * The driver is blocked, just queue the op until			 * it unblocks and the kernel thread gets kicked.			 */			list_add_tail(&crp->crp_list, &crp_q);			result = 0;		}	} else {		int wasempty;		/*		 * Caller marked the request as ``ok to delay'';		 * queue it for the dispatch thread.  This is desirable		 * when the operation is low priority and/or suitable		 * for batching.		 */		wasempty = list_empty(&crp_q);		list_add_tail(&crp->crp_list, &crp_q);		if (wasempty)			wake_up_interruptible(&cryptoproc_wait);		result = 0;	}	CRYPTO_Q_UNLOCK();	return result;}/* * Add an asymetric crypto request to a queue, * to be processed by the kernel thread. */intcrypto_kdispatch(struct cryptkop *krp){	struct cryptocap *cap;	int result, q_flags;	dprintk("%s()\n", __FUNCTION__);	cryptostats.cs_kops++;	CRYPTO_Q_LOCK();	cap = crypto_checkdriver(krp->krp_hid);	if (cap && !cap->cc_kqblocked) {		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.			 */			crypto_drivers[krp->krp_hid].cc_kqblocked = 1;			list_add_tail(&krp->krp_list, &crp_kq);			cryptostats.cs_kblocks++;		}	} else {		/*		 * The driver is blocked, just queue the op until		 * it unblocks and the kernel thread gets kicked.		 */		list_add_tail(&krp->krp_list, &crp_kq);		result = 0;	}	CRYPTO_Q_UNLOCK();	return result;}/* * Dispatch an assymetric crypto request to the appropriate crypto devices. */static intcrypto_kinvoke(struct cryptkop *krp, int hint){	u_int32_t hid;	int error;	dprintk("%s()\n", __FUNCTION__);	if (!crypto_q_locked)		printk("crypto: crypto_kinvoke called without lock!\n");	/* Sanity checks. */	if (krp == NULL) {		dprintk("%s,%d: null krp\n", __FILE__, __LINE__);		return EINVAL;	}	if (krp->krp_callback == NULL) {		dprintk("%s,%d: null krp_callback\n", __FILE__, __LINE__);		kfree(krp);		/* XXX allocated in cryptodev */		return EINVAL;	}	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;		if ((crypto_drivers[hid].cc_kalg[krp->krp_op] &		    CRYPTO_ALG_FLAG_SUPPORTED) == 0)			continue;		break;	}	if (hid < crypto_drivers_num) {		krp->krp_hid = hid;		error = crypto_drivers[hid].cc_kprocess(				crypto_drivers[hid].cc_karg, krp, hint);	} else {		dprintk("%s,%d: ENODEV\n", __FILE__, __LINE__);		error = ENODEV;	}	if (error) {		krp->krp_status = error;		crypto_kdone(krp);	}	return 0;}/* * Dispatch a crypto request to the appropriate crypto devices. */static intcrypto_invoke(struct cryptop *crp, int hint){	u_int32_t hid;	int (*process)(void*, struct cryptop *, int);	dprintk("%s()\n", __FUNCTION__);	if (crypto_q_locked == 0)		printk("crypto: crypto_invoke called without lock!\n");	/* Sanity checks. */	if (crp == NULL)		return EINVAL;	if (crp->crp_callback == NULL) {		crypto_freereq(crp);		return EINVAL;	}	if (crp->crp_desc == NULL) {		crp->crp_etype = EINVAL;		crypto_done(crp);		return 0;	}	hid = CRYPTO_SESID2HID(crp->crp_sid);	if (hid < crypto_drivers_num) {		if (crypto_drivers[hid].cc_flags & CRYPTOCAP_F_CLEANUP)			crypto_freesession(crp->crp_sid);		process = crypto_drivers[hid].cc_process;	} else {		process = NULL;	}	if (process == NULL) {		struct cryptodesc *crd;		u_int64_t nid;		/*		 * Driver has unregistered; migrate the session and return		 * an error to the caller so they'll resubmit the op.		 */		for (crd = crp->crp_desc; crd->crd_next; crd = crd->crd_next)			crd->CRD_INI.cri_next = &(crd->crd_next->CRD_INI);		if (crypto_newsession(&nid, &(crp->crp_desc->CRD_INI), 0) == 0)			crp->crp_sid = nid;		crp->crp_etype = EAGAIN;		crypto_done(crp);		return 0;	} else {		/*		 * Invoke the driver to process the request.		 */		return (*process)(crypto_drivers[hid].cc_arg, crp, hint);	}}/* * Release a set of crypto descriptors. */voidcrypto_freereq(struct cryptop *crp){	struct cryptodesc *crd;	if (crp == NULL)		return;	while ((crd = crp->crp_desc) != NULL) {		crp->crp_desc = crd->crd_next;		kmem_cache_free(cryptodesc_zone, crd);	}	kmem_cache_free(cryptop_zone, crp);}/* * Acquire a set of crypto descriptors. */struct cryptop *crypto_getreq(int num){	struct cryptodesc *crd;	struct cryptop *crp;	crp = kmem_cache_alloc(cryptop_zone, SLAB_ATOMIC);	if (crp != NULL) {		memset(crp, 0, sizeof(*crp));		INIT_LIST_HEAD(&crp->crp_list);		init_waitqueue_head(&crp->crp_waitq);		while (num--) {			crd = kmem_cache_alloc(cryptodesc_zone, SLAB_ATOMIC);			if (crd == NULL) {				crypto_freereq(crp);				return NULL;			}			memset(crd, 0, sizeof(*crd));			crd->crd_next = crp->crp_desc;			crp->crp_desc = crd;		}	}	return crp;}/* * Invoke the callback on behalf of the driver. */voidcrypto_done(struct cryptop *crp){

⌨️ 快捷键说明

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