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

📄 cryptodev.c

📁 linux下基于加密芯片的加密设备
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	$OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt Exp $	*//* * The linux port of this code done by David McCullough <davidm@snapgear.com> * The license and original author are listed below. * Copyright (C) 2004 David McCullough <davidm@snapgear.com> * * Copyright (c) 2001 Theo de Raadt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *   notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *   notice, this list of conditions and the following disclaimer in the *   documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products *   derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Effort sponsored in part by the Defense Advanced Research Projects * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F30602-01-2-0537. */static int errno = -1;#define __KERNEL_SYSCALLS__ 1#include <linux/config.h>#include <linux/types.h>#include <linux/time.h>#include <linux/list.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/unistd.h>#include <linux/module.h>#include <linux/wait.h>#include <linux/slab.h>#include <linux/fs.h>#include <linux/file.h>#include <linux/miscdevice.h>#include <asm/uaccess.h>#include <cryptodev.h>#include <uio.h>static int debug = 0;MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug,	   "Enable debug");static int crypto_devsel = 0;MODULE_PARM(crypto_devsel, "i");MODULE_PARM_DESC(crypto_devsel,	   "Select cryptodev drivers: -1=software only, 1=HW only, 0=any");struct csession_info {	u_int16_t	blocksize;	u_int16_t	minkey, maxkey;	u_int16_t	keysize;	/* u_int16_t	hashsize;  */	u_int16_t	authsize;	/* u_int16_t	ctxsize; */};struct csession {	struct list_head	list;	u_int64_t	sid;	u_int32_t	ses;	wait_queue_head_t waitq;	u_int32_t	cipher;	u_int32_t	mac;	caddr_t		key;	int		keylen;	u_char		tmp_iv[EALG_MAX_BLOCK_LEN];	caddr_t		mackey;	int		mackeylen;	u_char		tmp_mac[CRYPTO_MAX_MAC_LEN];	struct csession_info info;	struct iovec	iovec;	struct uio	uio;	int		error;};struct fcrypt {	struct list_head	csessions;	int		sesn;};static struct csession *csefind(struct fcrypt *, u_int);static int csedelete(struct fcrypt *, struct csession *);static struct csession *cseadd(struct fcrypt *, struct csession *);static struct csession *csecreate(struct fcrypt *, u_int64_t,		struct cryptoini *crie, struct cryptoini *cria, struct csession_info *);static int csefree(struct csession *);static	int cryptodev_op(struct csession *, struct crypt_op *);static	int cryptodev_key(struct crypt_kop *);static int cryptodev_cb(void *);static intcryptodev_op(struct csession *cse, struct crypt_op *cop){	struct cryptop *crp = NULL;	struct cryptodesc *crde = NULL, *crda = NULL;	int error;	dprintk("%s()\n", __FUNCTION__);	if (cop->len > 256*1024-4) {		dprintk("%s: %d > 256k\n", __FUNCTION__, cop->len);		return (E2BIG);	}	if (cse->info.blocksize && (cop->len % cse->info.blocksize) != 0) {		dprintk("%s: blocksize=%d len=%d\n", __FUNCTION__, cse->info.blocksize,				cop->len);		return (EINVAL);	}	cse->uio.uio_iov = &cse->iovec;	cse->uio.uio_iovcnt = 1;	cse->uio.uio_offset = 0;#if 0	cse->uio.uio_resid = cop->len;	cse->uio.uio_segflg = UIO_SYSSPACE;	cse->uio.uio_rw = UIO_WRITE;	cse->uio.uio_td = td;#endif	cse->uio.uio_iov[0].iov_len = cop->len;	cse->uio.uio_iov[0].iov_base = kmalloc(cop->len, GFP_KERNEL);	crp = crypto_getreq((cse->info.blocksize != 0) + (cse->info.authsize != 0));	if (crp == NULL) {		dprintk("%s: ENOMEM\n", __FUNCTION__);		error = ENOMEM;		goto bail;	}	if (cse->info.authsize) {		crda = crp->crp_desc;		if (cse->info.blocksize)			crde = crda->crd_next;	} else {		if (cse->info.blocksize)			crde = crp->crp_desc;		else {			dprintk("%s: bad request\n", __FUNCTION__);			error = EINVAL;			goto bail;		}	}	if ((error = copy_from_user(cse->uio.uio_iov[0].iov_base, cop->src,					cop->len))) {		dprintk("%s: bad copy\n", __FUNCTION__);		goto bail;	}	if (crda) {		crda->crd_skip = 0;		crda->crd_len = cop->len;		crda->crd_inject = 0;	/* ??? */		crda->crd_alg = cse->mac;		crda->crd_key = cse->mackey;		crda->crd_klen = cse->mackeylen * 8;	}	if (crde) {		if (cop->op == COP_ENCRYPT)			crde->crd_flags |= CRD_F_ENCRYPT;		else			crde->crd_flags &= ~CRD_F_ENCRYPT;		crde->crd_len = cop->len;		crde->crd_inject = 0;		crde->crd_alg = cse->cipher;		crde->crd_key = cse->key;		crde->crd_klen = cse->keylen * 8;	}	crp->crp_ilen = cop->len;	crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM		       | (cop->flags & COP_F_BATCH);	crp->crp_buf = (caddr_t)&cse->uio;	crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;	crp->crp_sid = cse->sid;	crp->crp_opaque = (void *)cse;	if (cop->iv) {		if (crde == NULL) {			error = EINVAL;			dprintk("%s no crde\n", __FUNCTION__);			goto bail;		}		if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */			error = EINVAL;			dprintk("%s arc4 with IV\n", __FUNCTION__);			goto bail;		}		if ((error = copy_from_user(cse->tmp_iv, cop->iv,						cse->info.blocksize))) {			dprintk("%s bad iv copy\n", __FUNCTION__);			goto bail;		}		memcpy(crde->crd_iv, cse->tmp_iv, cse->info.blocksize);		crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;		crde->crd_skip = 0;	} else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */		crde->crd_skip = 0;	} else if (crde) {		crde->crd_flags |= CRD_F_IV_PRESENT;		crde->crd_skip = cse->info.blocksize;		crde->crd_len -= cse->info.blocksize;	}	if (cop->mac) {		if (crda == NULL) {			error = EINVAL;			dprintk("%s no crda\n", __FUNCTION__);			goto bail;		}		crp->crp_mac=cse->tmp_mac;	}	/*	 * Let the dispatch run unlocked, then, interlock against the	 * callback before checking if the operation completed and going	 * to sleep.  This insures drivers don't inherit our lock which	 * results in a lock order reversal between crypto_dispatch forced	 * entry and the crypto_done callback into us.	 */	error = crypto_dispatch(crp);	if (error == 0) {		dprintk("%s about to WAIT\n", __FUNCTION__);		/*		 * we really need to wait for driver to complete to maintain		 * state,  luckily interrupts will be remembered		 */		do {			error = wait_event_interruptible(crp->crp_waitq,					((crp->crp_flags & CRYPTO_F_DONE) != 0));			error = -error;		} while ((crp->crp_flags & CRYPTO_F_DONE) == 0);		dprintk("%s finished WAITING error=%d\n", __FUNCTION__, error);	}	if (crp->crp_etype != 0) {		error = crp->crp_etype;		dprintk("%s error in crp processing\n", __FUNCTION__);		goto bail;	}	if (cse->error) {		error = cse->error;		dprintk("%s error in cse processing\n", __FUNCTION__);		goto bail;	}	if (cop->dst && (error = copy_to_user(cop->dst,					cse->uio.uio_iov[0].iov_base, cop->len))) {		dprintk("%s bad dst copy\n", __FUNCTION__);		goto bail;	}	if (cop->mac && (error=copy_to_user(cop->mac, crp->crp_mac,					cse->info.authsize))) {		dprintk("%s bad mac copy\n", __FUNCTION__);		goto bail;	}bail:	if (crp)		crypto_freereq(crp);	if (cse->uio.uio_iov[0].iov_base)		kfree(cse->uio.uio_iov[0].iov_base);	return (error);}static intcryptodev_cb(void *op){	struct cryptop *crp = (struct cryptop *) op;	struct csession *cse = (struct csession *)crp->crp_opaque;	dprintk("%s()\n", __FUNCTION__);	cse->error = crp->crp_etype;	if (crp->crp_etype == EAGAIN) {		crp->crp_flags &= ~CRYPTO_F_DONE;#ifdef NOTYET		/*		 * DAVIDM I am fairly sure that we should turn this into a batch		 * request to stop bad karma/lockup, revisit		 */		crp->crp_flags |= CRYPTO_F_BATCH;#endif		return crypto_dispatch(crp);	}	wake_up_interruptible(&crp->crp_waitq);	return (0);}static intcryptodevkey_cb(void *op){	struct cryptkop *krp = (struct cryptkop *) op;	dprintk("%s()\n", __FUNCTION__);	wake_up_interruptible(&krp->krp_waitq);	return (0);}static intcryptodev_key(struct crypt_kop *kop){	struct cryptkop *krp = NULL;	int error = EINVAL;	int in, out, size, i;	dprintk("%s()\n", __FUNCTION__);	if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {		dprintk("%s params too big\n", __FUNCTION__);		return (EFBIG);	}	in = kop->crk_iparams;	out = kop->crk_oparams;	switch (kop->crk_op) {	case CRK_MOD_EXP:		if (in == 3 && out == 1)			break;		return (EINVAL);	case CRK_MOD_EXP_CRT:		if (in == 6 && out == 1)			break;		return (EINVAL);	case CRK_DSA_SIGN:		if (in == 5 && out == 2)			break;		return (EINVAL);	case CRK_DSA_VERIFY:		if (in == 7 && out == 0)			break;		return (EINVAL);	case CRK_DH_COMPUTE_KEY:		if (in == 3 && out == 1)			break;		return (EINVAL);	default:		return (EINVAL);	}	krp = (struct cryptkop *)kmalloc(sizeof *krp, GFP_KERNEL);	if (!krp)		return (ENOMEM);	memset(krp, 0, sizeof *krp);	krp->krp_op = kop->crk_op;	krp->krp_status = kop->crk_status;	krp->krp_iparams = kop->crk_iparams;	krp->krp_oparams = kop->crk_oparams;	krp->krp_status = 0;	krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;	init_waitqueue_head(&krp->krp_waitq);	for (i = 0; i < CRK_MAXPARAM; i++)		krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;	for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {		size = (krp->krp_param[i].crp_nbits + 7) / 8;		if (size == 0)			continue;		krp->krp_param[i].crp_p = (caddr_t) kmalloc(size, GFP_KERNEL);		if (i >= krp->krp_iparams)			continue;		error = copy_from_user(krp->krp_param[i].crp_p,				kop->crk_param[i].crp_p, size);		if (error)			goto fail;	}	error = crypto_kdispatch(krp);	if (error)		goto fail;	interruptible_sleep_on(&krp->krp_waitq);		if (krp->krp_status != 0) {		error = krp->krp_status;		goto fail;	}	for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {		size = (krp->krp_param[i].crp_nbits + 7) / 8;		if (size == 0)			continue;		error = copy_to_user(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p,				size);		if (error)

⌨️ 快捷键说明

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