Home | History | Annotate | Line # | Download | only in opencrypto
cryptodev.c revision 1.44.8.2.4.1
      1  1.44.8.2.4.1      matt /*	$NetBSD: cryptodev.c,v 1.44.8.2.4.1 2011/05/20 08:11:31 matt Exp $ */
      2           1.4  jonathan /*	$FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.4.2.4 2003/06/03 00:09:02 sam Exp $	*/
      3           1.1  jonathan /*	$OpenBSD: cryptodev.c,v 1.53 2002/07/10 22:21:30 mickey Exp $	*/
      4           1.1  jonathan 
      5          1.36       tls /*-
      6          1.36       tls  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      7          1.36       tls  * All rights reserved.
      8          1.36       tls  *
      9          1.36       tls  * This code is derived from software contributed to The NetBSD Foundation
     10          1.36       tls  * by Coyote Point Systems, Inc.
     11          1.36       tls  *
     12          1.36       tls  * Redistribution and use in source and binary forms, with or without
     13          1.36       tls  * modification, are permitted provided that the following conditions
     14          1.36       tls  * are met:
     15          1.36       tls  * 1. Redistributions of source code must retain the above copyright
     16          1.36       tls  *    notice, this list of conditions and the following disclaimer.
     17          1.36       tls  * 2. Redistributions in binary form must reproduce the above copyright
     18          1.36       tls  *    notice, this list of conditions and the following disclaimer in the
     19          1.36       tls  *    documentation and/or other materials provided with the distribution.
     20          1.36       tls  *
     21          1.36       tls  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     22          1.36       tls  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23          1.36       tls  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24          1.36       tls  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     25          1.36       tls  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     26          1.36       tls  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     27          1.36       tls  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     28          1.36       tls  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     29          1.36       tls  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30          1.36       tls  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31          1.36       tls  * POSSIBILITY OF SUCH DAMAGE.
     32          1.36       tls  */
     33          1.36       tls 
     34           1.1  jonathan /*
     35           1.1  jonathan  * Copyright (c) 2001 Theo de Raadt
     36           1.1  jonathan  *
     37           1.1  jonathan  * Redistribution and use in source and binary forms, with or without
     38           1.1  jonathan  * modification, are permitted provided that the following conditions
     39           1.1  jonathan  * are met:
     40           1.1  jonathan  *
     41           1.1  jonathan  * 1. Redistributions of source code must retain the above copyright
     42           1.1  jonathan  *   notice, this list of conditions and the following disclaimer.
     43           1.1  jonathan  * 2. Redistributions in binary form must reproduce the above copyright
     44           1.1  jonathan  *   notice, this list of conditions and the following disclaimer in the
     45           1.1  jonathan  *   documentation and/or other materials provided with the distribution.
     46           1.1  jonathan  * 3. The name of the author may not be used to endorse or promote products
     47           1.1  jonathan  *   derived from this software without specific prior written permission.
     48           1.1  jonathan  *
     49           1.1  jonathan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     50           1.1  jonathan  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     51           1.1  jonathan  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     52           1.1  jonathan  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     53           1.1  jonathan  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     54           1.1  jonathan  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     55           1.1  jonathan  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     56           1.1  jonathan  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     57           1.1  jonathan  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     58           1.1  jonathan  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     59           1.1  jonathan  *
     60           1.1  jonathan  * Effort sponsored in part by the Defense Advanced Research Projects
     61           1.1  jonathan  * Agency (DARPA) and Air Force Research Laboratory, Air Force
     62           1.1  jonathan  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
     63           1.1  jonathan  *
     64           1.1  jonathan  */
     65           1.1  jonathan 
     66           1.1  jonathan #include <sys/cdefs.h>
     67  1.44.8.2.4.1      matt __KERNEL_RCSID(0, "$NetBSD: cryptodev.c,v 1.44.8.2.4.1 2011/05/20 08:11:31 matt Exp $");
     68           1.1  jonathan 
     69           1.1  jonathan #include <sys/param.h>
     70           1.1  jonathan #include <sys/systm.h>
     71          1.36       tls #include <sys/kmem.h>
     72           1.1  jonathan #include <sys/malloc.h>
     73           1.1  jonathan #include <sys/mbuf.h>
     74          1.29       tls #include <sys/pool.h>
     75           1.1  jonathan #include <sys/sysctl.h>
     76           1.1  jonathan #include <sys/file.h>
     77           1.1  jonathan #include <sys/filedesc.h>
     78           1.1  jonathan #include <sys/errno.h>
     79           1.2  jonathan #include <sys/md5.h>
     80           1.1  jonathan #include <sys/sha1.h>
     81           1.1  jonathan #include <sys/conf.h>
     82           1.1  jonathan #include <sys/device.h>
     83          1.21      elad #include <sys/kauth.h>
     84          1.36       tls #include <sys/select.h>
     85          1.36       tls #include <sys/poll.h>
     86          1.37    dogcow #include <sys/atomic.h>
     87           1.1  jonathan 
     88          1.33       tls #include "opt_ocf.h"
     89           1.1  jonathan #include <opencrypto/cryptodev.h>
     90  1.44.8.2.4.1      matt #include <opencrypto/ocryptodev.h>
     91           1.1  jonathan #include <opencrypto/xform.h>
     92           1.1  jonathan 
     93           1.1  jonathan struct csession {
     94           1.1  jonathan 	TAILQ_ENTRY(csession) next;
     95           1.1  jonathan 	u_int64_t	sid;
     96           1.1  jonathan 	u_int32_t	ses;
     97           1.1  jonathan 
     98  1.44.8.2.4.1      matt 	u_int32_t	cipher;		/* note: shares name space in crd_alg */
     99           1.1  jonathan 	struct enc_xform *txform;
    100  1.44.8.2.4.1      matt 	u_int32_t	mac;		/* note: shares name space in crd_alg */
    101           1.1  jonathan 	struct auth_hash *thash;
    102  1.44.8.2.4.1      matt 	u_int32_t	comp_alg;	/* note: shares name space in crd_alg */
    103  1.44.8.2.4.1      matt 	struct comp_algo *tcomp;
    104           1.1  jonathan 
    105          1.26  christos 	void *		key;
    106           1.1  jonathan 	int		keylen;
    107           1.1  jonathan 	u_char		tmp_iv[EALG_MAX_BLOCK_LEN];
    108           1.1  jonathan 
    109          1.26  christos 	void *		mackey;
    110           1.1  jonathan 	int		mackeylen;
    111           1.1  jonathan 	u_char		tmp_mac[CRYPTO_MAX_MAC_LEN];
    112           1.1  jonathan 
    113          1.29       tls 	struct iovec	iovec[1];	/* user requests never have more */
    114           1.1  jonathan 	struct uio	uio;
    115           1.1  jonathan 	int		error;
    116           1.1  jonathan };
    117           1.1  jonathan 
    118           1.1  jonathan struct fcrypt {
    119           1.1  jonathan 	TAILQ_HEAD(csessionlist, csession) csessions;
    120          1.36       tls 	TAILQ_HEAD(crprethead, cryptop) crp_ret_mq;
    121          1.36       tls 	TAILQ_HEAD(krprethead, cryptkop) crp_ret_mkq;
    122           1.1  jonathan 	int		sesn;
    123          1.36       tls 	struct selinfo	sinfo;
    124          1.36       tls 	u_int32_t	requestid;
    125           1.1  jonathan };
    126           1.1  jonathan 
    127          1.29       tls /* For our fixed-size allocations */
    128          1.38     rmind static struct pool fcrpl;
    129          1.38     rmind static struct pool csepl;
    130           1.1  jonathan 
    131           1.1  jonathan /* Declaration of master device (fd-cloning/ctxt-allocating) entrypoints */
    132          1.16  christos static int	cryptoopen(dev_t dev, int flag, int mode, struct lwp *l);
    133           1.1  jonathan static int	cryptoread(dev_t dev, struct uio *uio, int ioflag);
    134           1.1  jonathan static int	cryptowrite(dev_t dev, struct uio *uio, int ioflag);
    135          1.16  christos static int	cryptoselect(dev_t dev, int rw, struct lwp *l);
    136           1.1  jonathan 
    137           1.1  jonathan /* Declaration of cloned-device (per-ctxt) entrypoints */
    138          1.36       tls static int	cryptof_read(struct file *, off_t *, struct uio *,
    139          1.42  christos     kauth_cred_t, int);
    140          1.36       tls static int	cryptof_write(struct file *, off_t *, struct uio *,
    141          1.42  christos     kauth_cred_t, int);
    142          1.36       tls static int	cryptof_ioctl(struct file *, u_long, void *);
    143          1.36       tls static int	cryptof_close(struct file *);
    144          1.36       tls static int 	cryptof_poll(struct file *, int);
    145           1.1  jonathan 
    146          1.12  christos static const struct fileops cryptofops = {
    147      1.44.8.2       snj 	.fo_read = cryptof_read,
    148      1.44.8.2       snj 	.fo_write = cryptof_write,
    149      1.44.8.2       snj 	.fo_ioctl = cryptof_ioctl,
    150      1.44.8.2       snj 	.fo_fcntl = fnullop_fcntl,
    151      1.44.8.2       snj 	.fo_poll = cryptof_poll,
    152      1.44.8.2       snj 	.fo_stat = fbadop_stat,
    153      1.44.8.2       snj 	.fo_close = cryptof_close,
    154      1.44.8.2       snj 	.fo_kqfilter = fnullop_kqfilter,
    155      1.44.8.2       snj 	.fo_drain = fnullop_drain,
    156           1.1  jonathan };
    157           1.1  jonathan 
    158  1.44.8.2.4.1      matt struct csession *cryptodev_csefind(struct fcrypt *, u_int);
    159           1.1  jonathan static struct	csession *csefind(struct fcrypt *, u_int);
    160           1.1  jonathan static int	csedelete(struct fcrypt *, struct csession *);
    161           1.1  jonathan static struct	csession *cseadd(struct fcrypt *, struct csession *);
    162          1.42  christos static struct	csession *csecreate(struct fcrypt *, u_int64_t, void *,
    163  1.44.8.2.4.1      matt     u_int64_t, void *, u_int64_t, u_int32_t, u_int32_t, u_int32_t,
    164  1.44.8.2.4.1      matt     struct enc_xform *, struct auth_hash *, struct comp_algo *);
    165           1.1  jonathan static int	csefree(struct csession *);
    166           1.1  jonathan 
    167           1.1  jonathan static int	cryptodev_key(struct crypt_kop *);
    168          1.36       tls static int	cryptodev_mkey(struct fcrypt *, struct crypt_n_kop *, int);
    169          1.36       tls static int	cryptodev_msessionfin(struct fcrypt *, int, u_int32_t *);
    170           1.1  jonathan 
    171           1.1  jonathan static int	cryptodev_cb(void *);
    172           1.1  jonathan static int	cryptodevkey_cb(void *);
    173           1.1  jonathan 
    174          1.36       tls static int	cryptodev_mcb(void *);
    175          1.36       tls static int	cryptodevkey_mcb(void *);
    176          1.36       tls 
    177          1.36       tls static int 	cryptodev_getmstatus(struct fcrypt *, struct crypt_result *,
    178          1.42  christos     int);
    179          1.36       tls static int	cryptodev_getstatus(struct fcrypt *, struct crypt_result *);
    180          1.36       tls 
    181  1.44.8.2.4.1      matt extern int	ocryptof_ioctl(struct file *, u_long, void *);
    182  1.44.8.2.4.1      matt 
    183           1.9  jonathan /*
    184           1.9  jonathan  * sysctl-able control variables for /dev/crypto now defined in crypto.c:
    185           1.9  jonathan  * crypto_usercrypto, crypto_userasmcrypto, crypto_devallowsoft.
    186           1.9  jonathan  */
    187           1.1  jonathan 
    188           1.1  jonathan /* ARGSUSED */
    189           1.1  jonathan int
    190          1.35        ad cryptof_read(file_t *fp, off_t *poff,
    191          1.25  christos     struct uio *uio, kauth_cred_t cred, int flags)
    192           1.1  jonathan {
    193          1.42  christos 	return EIO;
    194           1.1  jonathan }
    195           1.1  jonathan 
    196           1.1  jonathan /* ARGSUSED */
    197           1.1  jonathan int
    198          1.35        ad cryptof_write(file_t *fp, off_t *poff,
    199          1.25  christos     struct uio *uio, kauth_cred_t cred, int flags)
    200           1.1  jonathan {
    201          1.42  christos 	return EIO;
    202           1.1  jonathan }
    203           1.1  jonathan 
    204           1.1  jonathan /* ARGSUSED */
    205           1.1  jonathan int
    206          1.36       tls cryptof_ioctl(struct file *fp, u_long cmd, void *data)
    207           1.1  jonathan {
    208          1.35        ad 	struct fcrypt *fcr = fp->f_data;
    209           1.1  jonathan 	struct csession *cse;
    210           1.1  jonathan 	struct session_op *sop;
    211          1.36       tls 	struct session_n_op *snop;
    212           1.1  jonathan 	struct crypt_op *cop;
    213          1.36       tls 	struct crypt_mop *mop;
    214          1.36       tls 	struct crypt_mkop *mkop;
    215          1.36       tls 	struct crypt_n_op *cnop;
    216          1.36       tls 	struct crypt_n_kop *knop;
    217          1.36       tls 	struct crypt_sgop *sgop;
    218          1.36       tls 	struct crypt_sfop *sfop;
    219          1.36       tls 	struct cryptret *crypt_ret;
    220          1.36       tls 	struct crypt_result *crypt_res;
    221           1.1  jonathan 	u_int32_t ses;
    222          1.36       tls 	u_int32_t *sesid;
    223           1.1  jonathan 	int error = 0;
    224          1.36       tls 	size_t count;
    225           1.1  jonathan 
    226          1.29       tls 	/* backwards compatibility */
    227          1.35        ad         file_t *criofp;
    228          1.29       tls 	struct fcrypt *criofcr;
    229          1.29       tls 	int criofd;
    230          1.29       tls 
    231          1.36       tls 	switch (cmd) {
    232          1.29       tls         case CRIOGET:   /* XXX deprecated, remove after 5.0 */
    233          1.36       tls 		if ((error = fd_allocfile(&criofp, &criofd)) != 0)
    234          1.36       tls 			return error;
    235          1.36       tls 		criofcr = pool_get(&fcrpl, PR_WAITOK);
    236          1.33       tls 		mutex_spin_enter(&crypto_mtx);
    237          1.36       tls 		TAILQ_INIT(&criofcr->csessions);
    238          1.36       tls 		TAILQ_INIT(&criofcr->crp_ret_mq);
    239          1.36       tls 		TAILQ_INIT(&criofcr->crp_ret_mkq);
    240          1.36       tls 		selinit(&criofcr->sinfo);
    241          1.36       tls 
    242          1.29       tls                 /*
    243          1.29       tls                  * Don't ever return session 0, to allow detection of
    244          1.29       tls                  * failed creation attempts with multi-create ioctl.
    245          1.29       tls                  */
    246          1.36       tls 		criofcr->sesn = 1;
    247          1.36       tls 		criofcr->requestid = 1;
    248          1.33       tls 		mutex_spin_exit(&crypto_mtx);
    249          1.36       tls 		(void)fd_clone(criofp, criofd, (FREAD|FWRITE),
    250          1.29       tls 			      &cryptofops, criofcr);
    251          1.36       tls 		*(u_int32_t *)data = criofd;
    252          1.29       tls 		return error;
    253          1.36       tls 		break;
    254           1.1  jonathan 	case CIOCGSESSION:
    255           1.1  jonathan 		sop = (struct session_op *)data;
    256          1.36       tls 		error = cryptodev_session(fcr, sop);
    257          1.36       tls 		break;
    258          1.36       tls 	case CIOCNGSESSION:
    259          1.36       tls 		sgop = (struct crypt_sgop *)data;
    260          1.36       tls 		snop = kmem_alloc((sgop->count *
    261          1.36       tls 				  sizeof(struct session_n_op)), KM_SLEEP);
    262          1.36       tls 		error = copyin(sgop->sessions, snop, sgop->count *
    263          1.36       tls 			       sizeof(struct session_n_op));
    264          1.36       tls 		if (error) {
    265          1.36       tls 			goto mbail;
    266           1.1  jonathan 		}
    267           1.1  jonathan 
    268          1.36       tls 		error = cryptodev_msession(fcr, snop, sgop->count);
    269          1.36       tls 		if (error) {
    270          1.36       tls 			goto mbail;
    271           1.1  jonathan 		}
    272           1.1  jonathan 
    273          1.36       tls 		error = copyout(snop, sgop->sessions, sgop->count *
    274          1.42  christos 		    sizeof(struct session_n_op));
    275          1.36       tls mbail:
    276          1.39       tls 		kmem_free(snop, sgop->count * sizeof(struct session_n_op));
    277           1.1  jonathan 		break;
    278           1.1  jonathan 	case CIOCFSESSION:
    279          1.33       tls 		mutex_spin_enter(&crypto_mtx);
    280           1.1  jonathan 		ses = *(u_int32_t *)data;
    281           1.1  jonathan 		cse = csefind(fcr, ses);
    282           1.1  jonathan 		if (cse == NULL)
    283          1.42  christos 			return EINVAL;
    284           1.1  jonathan 		csedelete(fcr, cse);
    285           1.1  jonathan 		error = csefree(cse);
    286          1.33       tls 		mutex_spin_exit(&crypto_mtx);
    287           1.1  jonathan 		break;
    288          1.36       tls 	case CIOCNFSESSION:
    289          1.36       tls 		sfop = (struct crypt_sfop *)data;
    290          1.36       tls 		sesid = kmem_alloc((sfop->count * sizeof(u_int32_t)),
    291          1.42  christos 		    KM_SLEEP);
    292          1.42  christos 		error = copyin(sfop->sesid, sesid,
    293          1.42  christos 		    (sfop->count * sizeof(u_int32_t)));
    294          1.36       tls 		if (!error) {
    295          1.36       tls 			error = cryptodev_msessionfin(fcr, sfop->count, sesid);
    296          1.36       tls 		}
    297          1.36       tls 		kmem_free(sesid, (sfop->count * sizeof(u_int32_t)));
    298          1.36       tls 		break;
    299           1.1  jonathan 	case CIOCCRYPT:
    300          1.33       tls 		mutex_spin_enter(&crypto_mtx);
    301           1.1  jonathan 		cop = (struct crypt_op *)data;
    302           1.1  jonathan 		cse = csefind(fcr, cop->ses);
    303          1.33       tls 		mutex_spin_exit(&crypto_mtx);
    304          1.18  christos 		if (cse == NULL) {
    305          1.18  christos 			DPRINTF(("csefind failed\n"));
    306          1.42  christos 			return EINVAL;
    307          1.18  christos 		}
    308          1.35        ad 		error = cryptodev_op(cse, cop, curlwp);
    309          1.34       tls 		DPRINTF(("cryptodev_op error = %d\n", error));
    310           1.1  jonathan 		break;
    311          1.36       tls 	case CIOCNCRYPTM:
    312          1.36       tls 		mop = (struct crypt_mop *)data;
    313          1.36       tls 		cnop = kmem_alloc((mop->count * sizeof(struct crypt_n_op)),
    314          1.42  christos 		    KM_SLEEP);
    315          1.42  christos 		error = copyin(mop->reqs, cnop,
    316          1.42  christos 		    (mop->count * sizeof(struct crypt_n_op)));
    317          1.36       tls 		if(!error) {
    318          1.42  christos 			error = cryptodev_mop(fcr, cnop, mop->count, curlwp);
    319          1.36       tls 			if (!error) {
    320          1.36       tls 				error = copyout(cnop, mop->reqs,
    321          1.42  christos 				    (mop->count * sizeof(struct crypt_n_op)));
    322          1.36       tls 			}
    323          1.36       tls 		}
    324          1.36       tls 		kmem_free(cnop, (mop->count * sizeof(struct crypt_n_op)));
    325          1.36       tls 		break;
    326           1.1  jonathan 	case CIOCKEY:
    327           1.1  jonathan 		error = cryptodev_key((struct crypt_kop *)data);
    328          1.34       tls 		DPRINTF(("cryptodev_key error = %d\n", error));
    329           1.1  jonathan 		break;
    330          1.36       tls 	case CIOCNFKEYM:
    331          1.36       tls 		mkop = (struct crypt_mkop *)data;
    332          1.36       tls 		knop = kmem_alloc((mkop->count * sizeof(struct crypt_n_kop)),
    333          1.42  christos 		    KM_SLEEP);
    334          1.36       tls 		error = copyin(mkop->reqs, knop,
    335          1.42  christos 		    (mkop->count * sizeof(struct crypt_n_kop)));
    336          1.36       tls 		if (!error) {
    337          1.36       tls 			error = cryptodev_mkey(fcr, knop, mkop->count);
    338          1.36       tls 			if (!error)
    339          1.36       tls 				error = copyout(knop, mkop->reqs,
    340          1.42  christos 				    (mkop->count * sizeof(struct crypt_n_kop)));
    341          1.36       tls 		}
    342          1.36       tls 		kmem_free(knop, (mkop->count * sizeof(struct crypt_n_kop)));
    343          1.36       tls 		break;
    344           1.1  jonathan 	case CIOCASYMFEAT:
    345           1.1  jonathan 		error = crypto_getfeat((int *)data);
    346           1.1  jonathan 		break;
    347          1.36       tls 	case CIOCNCRYPTRETM:
    348          1.36       tls 		crypt_ret = (struct cryptret *)data;
    349          1.36       tls 		count = crypt_ret->count;
    350          1.42  christos 		crypt_res = kmem_alloc((count * sizeof(struct crypt_result)),
    351          1.42  christos 		    KM_SLEEP);
    352          1.36       tls 		error = copyin(crypt_ret->results, crypt_res,
    353          1.42  christos 		    (count * sizeof(struct crypt_result)));
    354          1.36       tls 		if (error)
    355          1.36       tls 			goto reterr;
    356          1.36       tls 		crypt_ret->count = cryptodev_getmstatus(fcr, crypt_res,
    357          1.42  christos 		    crypt_ret->count);
    358          1.36       tls 		/* sanity check count */
    359          1.36       tls 		if (crypt_ret->count > count) {
    360          1.37    dogcow 			printf("%s.%d: error returned count %zd > original "
    361          1.42  christos 			    " count %zd\n",
    362          1.42  christos 			    __FILE__, __LINE__, crypt_ret->count, count);
    363          1.36       tls 			crypt_ret->count = count;
    364          1.36       tls 
    365          1.36       tls 		}
    366          1.36       tls 		error = copyout(crypt_res, crypt_ret->results,
    367          1.42  christos 		    (crypt_ret->count * sizeof(struct crypt_result)));
    368          1.36       tls reterr:
    369          1.42  christos 		kmem_free(crypt_res, (count * sizeof(struct crypt_result)));
    370          1.36       tls 		break;
    371          1.36       tls 	case CIOCNCRYPTRET:
    372          1.36       tls 		error = cryptodev_getstatus(fcr, (struct crypt_result *)data);
    373          1.36       tls 		break;
    374           1.1  jonathan 	default:
    375  1.44.8.2.4.1      matt 		/* Check for backward compatible commands */
    376  1.44.8.2.4.1      matt 		error = ocryptof_ioctl(fp, cmd, data);
    377           1.1  jonathan 	}
    378          1.42  christos 	return error;
    379           1.1  jonathan }
    380           1.1  jonathan 
    381  1.44.8.2.4.1      matt int
    382          1.25  christos cryptodev_op(struct csession *cse, struct crypt_op *cop, struct lwp *l)
    383           1.1  jonathan {
    384           1.1  jonathan 	struct cryptop *crp = NULL;
    385  1.44.8.2.4.1      matt 	struct cryptodesc *crde = NULL, *crda = NULL, *crdc = NULL;
    386          1.33       tls 	int error;
    387  1.44.8.2.4.1      matt 	int iov_len = cop->len;
    388  1.44.8.2.4.1      matt 	int flags=0;
    389  1.44.8.2.4.1      matt 	int dst_len;	/* copyout size */
    390           1.1  jonathan 
    391           1.1  jonathan 	if (cop->len > 256*1024-4)
    392          1.42  christos 		return E2BIG;
    393           1.1  jonathan 
    394          1.13  jonathan 	if (cse->txform) {
    395          1.13  jonathan 		if (cop->len == 0 || (cop->len % cse->txform->blocksize) != 0)
    396          1.42  christos 			return EINVAL;
    397          1.13  jonathan 	}
    398           1.1  jonathan 
    399  1.44.8.2.4.1      matt 	DPRINTF(("cryptodev_op[%d]: iov_len %d\n", (uint32_t)cse->sid, iov_len));
    400  1.44.8.2.4.1      matt 	if ((cse->tcomp) && cop->dst_len) {
    401  1.44.8.2.4.1      matt 		if (iov_len < cop->dst_len) {
    402  1.44.8.2.4.1      matt 			/* Need larger iov to deal with decompress */
    403  1.44.8.2.4.1      matt 			iov_len = cop->dst_len;
    404  1.44.8.2.4.1      matt 		}
    405  1.44.8.2.4.1      matt 		DPRINTF(("cryptodev_op: iov_len -> %d for decompress\n", iov_len));
    406  1.44.8.2.4.1      matt 	}
    407  1.44.8.2.4.1      matt 
    408          1.42  christos 	(void)memset(&cse->uio, 0, sizeof(cse->uio));
    409           1.1  jonathan 	cse->uio.uio_iovcnt = 1;
    410           1.1  jonathan 	cse->uio.uio_resid = 0;
    411           1.1  jonathan 	cse->uio.uio_rw = UIO_WRITE;
    412           1.1  jonathan 	cse->uio.uio_iov = cse->iovec;
    413          1.17      yamt 	UIO_SETUP_SYSSPACE(&cse->uio);
    414          1.29       tls 	memset(&cse->iovec, 0, sizeof(cse->iovec));
    415  1.44.8.2.4.1      matt 
    416  1.44.8.2.4.1      matt 	/* the iov needs to be big enough to handle the uncompressed
    417  1.44.8.2.4.1      matt 	 * data.... */
    418  1.44.8.2.4.1      matt 	cse->uio.uio_iov[0].iov_len = iov_len;
    419  1.44.8.2.4.1      matt 	cse->uio.uio_iov[0].iov_base = kmem_alloc(iov_len, KM_SLEEP);
    420          1.29       tls 	cse->uio.uio_resid = cse->uio.uio_iov[0].iov_len;
    421  1.44.8.2.4.1      matt 	DPRINTF(("cryptodev_op[%d]: uio.iov_base %p malloced %d bytes\n",
    422  1.44.8.2.4.1      matt 		(uint32_t)cse->sid, cse->uio.uio_iov[0].iov_base, iov_len));
    423           1.1  jonathan 
    424  1.44.8.2.4.1      matt 	crp = crypto_getreq((cse->tcomp != NULL) + (cse->txform != NULL) + (cse->thash != NULL));
    425           1.1  jonathan 	if (crp == NULL) {
    426           1.1  jonathan 		error = ENOMEM;
    427           1.1  jonathan 		goto bail;
    428           1.1  jonathan 	}
    429  1.44.8.2.4.1      matt 	DPRINTF(("cryptodev_op[%d]: crp %p\n", (uint32_t)cse->sid, crp));
    430  1.44.8.2.4.1      matt 
    431  1.44.8.2.4.1      matt 	/* crds are always ordered tcomp, thash, then txform */
    432  1.44.8.2.4.1      matt 	/* with optional missing links */
    433  1.44.8.2.4.1      matt 
    434  1.44.8.2.4.1      matt 	/* XXX: If we're going to compress then hash or encrypt, we need
    435  1.44.8.2.4.1      matt 	 * to be able to pass on the new size of the data.
    436  1.44.8.2.4.1      matt 	 */
    437  1.44.8.2.4.1      matt 
    438  1.44.8.2.4.1      matt 	if (cse->tcomp) {
    439  1.44.8.2.4.1      matt 		crdc = crp->crp_desc;
    440  1.44.8.2.4.1      matt 	}
    441           1.1  jonathan 
    442           1.1  jonathan 	if (cse->thash) {
    443  1.44.8.2.4.1      matt 		crda = crdc ? crdc->crd_next : crp->crp_desc;
    444          1.44  christos 		if (cse->txform && crda)
    445           1.1  jonathan 			crde = crda->crd_next;
    446           1.1  jonathan 	} else {
    447  1.44.8.2.4.1      matt 		if (cse->txform) {
    448  1.44.8.2.4.1      matt 			crde = crdc ? crdc->crd_next : crp->crp_desc;
    449  1.44.8.2.4.1      matt 		} else if (!cse->tcomp) {
    450           1.1  jonathan 			error = EINVAL;
    451           1.1  jonathan 			goto bail;
    452           1.1  jonathan 		}
    453           1.1  jonathan 	}
    454           1.1  jonathan 
    455  1.44.8.2.4.1      matt 	DPRINTF(("ocf[%d]: iov_len %d, cop->len %d\n",
    456  1.44.8.2.4.1      matt 			(uint32_t)cse->sid,
    457  1.44.8.2.4.1      matt 			cse->uio.uio_iov[0].iov_len,
    458  1.44.8.2.4.1      matt 			cop->len));
    459  1.44.8.2.4.1      matt 
    460           1.1  jonathan 	if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len)))
    461          1.36       tls 	{
    462          1.36       tls 		printf("copyin failed %s %d \n", (char *)cop->src, error);
    463           1.1  jonathan 		goto bail;
    464          1.36       tls 	}
    465           1.1  jonathan 
    466  1.44.8.2.4.1      matt 	if (crdc) {
    467  1.44.8.2.4.1      matt 		switch (cop->op) {
    468  1.44.8.2.4.1      matt 		case COP_COMP:
    469  1.44.8.2.4.1      matt 			crdc->crd_flags |= CRD_F_COMP;
    470  1.44.8.2.4.1      matt 			break;
    471  1.44.8.2.4.1      matt 		case COP_DECOMP:
    472  1.44.8.2.4.1      matt 			crdc->crd_flags &= ~CRD_F_COMP;
    473  1.44.8.2.4.1      matt 			break;
    474  1.44.8.2.4.1      matt 		default:
    475  1.44.8.2.4.1      matt 			break;
    476  1.44.8.2.4.1      matt 		}
    477  1.44.8.2.4.1      matt 		/* more data to follow? */
    478  1.44.8.2.4.1      matt 		if (cop->flags & COP_F_MORE) {
    479  1.44.8.2.4.1      matt 			flags |= CRYPTO_F_MORE;
    480  1.44.8.2.4.1      matt 		}
    481  1.44.8.2.4.1      matt 		crdc->crd_len = cop->len;
    482  1.44.8.2.4.1      matt 		crdc->crd_inject = 0;
    483  1.44.8.2.4.1      matt 
    484  1.44.8.2.4.1      matt 		crdc->crd_alg = cse->comp_alg;
    485  1.44.8.2.4.1      matt 		crdc->crd_key = NULL;
    486  1.44.8.2.4.1      matt 		crdc->crd_klen = 0;
    487  1.44.8.2.4.1      matt 		DPRINTF(("cryptodev_op[%d]: crdc setup for comp_alg %d.\n",
    488  1.44.8.2.4.1      matt 					(uint32_t)cse->sid, crdc->crd_alg));
    489  1.44.8.2.4.1      matt 	}
    490  1.44.8.2.4.1      matt 
    491           1.1  jonathan 	if (crda) {
    492           1.1  jonathan 		crda->crd_skip = 0;
    493           1.1  jonathan 		crda->crd_len = cop->len;
    494           1.1  jonathan 		crda->crd_inject = 0;	/* ??? */
    495           1.1  jonathan 
    496           1.1  jonathan 		crda->crd_alg = cse->mac;
    497           1.1  jonathan 		crda->crd_key = cse->mackey;
    498           1.1  jonathan 		crda->crd_klen = cse->mackeylen * 8;
    499  1.44.8.2.4.1      matt 		DPRINTF(("cryptodev_op: crda setup for mac %d.\n", crda->crd_alg));
    500           1.1  jonathan 	}
    501           1.1  jonathan 
    502           1.1  jonathan 	if (crde) {
    503  1.44.8.2.4.1      matt 		switch (cop->op) {
    504  1.44.8.2.4.1      matt 		case COP_ENCRYPT:
    505           1.1  jonathan 			crde->crd_flags |= CRD_F_ENCRYPT;
    506  1.44.8.2.4.1      matt 			break;
    507  1.44.8.2.4.1      matt 		case COP_DECRYPT:
    508           1.1  jonathan 			crde->crd_flags &= ~CRD_F_ENCRYPT;
    509  1.44.8.2.4.1      matt 			break;
    510  1.44.8.2.4.1      matt 		default:
    511  1.44.8.2.4.1      matt 			break;
    512  1.44.8.2.4.1      matt 		}
    513           1.1  jonathan 		crde->crd_len = cop->len;
    514           1.1  jonathan 		crde->crd_inject = 0;
    515           1.1  jonathan 
    516           1.1  jonathan 		crde->crd_alg = cse->cipher;
    517           1.1  jonathan 		crde->crd_key = cse->key;
    518           1.1  jonathan 		crde->crd_klen = cse->keylen * 8;
    519  1.44.8.2.4.1      matt 		DPRINTF(("cryptodev_op: crde setup for cipher %d.\n", crde->crd_alg));
    520           1.1  jonathan 	}
    521           1.1  jonathan 
    522  1.44.8.2.4.1      matt 
    523           1.1  jonathan 	crp->crp_ilen = cop->len;
    524      1.44.8.1       snj 	/* The reqest is flagged as CRYPTO_F_USER as long as it is running
    525      1.44.8.1       snj 	 * in the user IOCTL thread.  This flag lets us skip using the retq for
    526      1.44.8.1       snj 	 * the request if it completes immediately. If the request ends up being
    527      1.44.8.1       snj 	 * delayed or is not completed immediately the flag is removed.
    528      1.44.8.1       snj 	 */
    529  1.44.8.2.4.1      matt 	crp->crp_flags = CRYPTO_F_IOV | (cop->flags & COP_F_BATCH) | CRYPTO_F_USER |
    530  1.44.8.2.4.1      matt 			flags;
    531          1.26  christos 	crp->crp_buf = (void *)&cse->uio;
    532           1.1  jonathan 	crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
    533           1.1  jonathan 	crp->crp_sid = cse->sid;
    534           1.1  jonathan 	crp->crp_opaque = (void *)cse;
    535           1.1  jonathan 
    536           1.1  jonathan 	if (cop->iv) {
    537           1.1  jonathan 		if (crde == NULL) {
    538           1.1  jonathan 			error = EINVAL;
    539           1.1  jonathan 			goto bail;
    540           1.1  jonathan 		}
    541           1.1  jonathan 		if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
    542           1.1  jonathan 			error = EINVAL;
    543           1.1  jonathan 			goto bail;
    544           1.1  jonathan 		}
    545          1.36       tls 		if ((error = copyin(cop->iv, cse->tmp_iv,
    546          1.42  christos 		    cse->txform->blocksize)))
    547           1.1  jonathan 			goto bail;
    548          1.42  christos 		(void)memcpy(crde->crd_iv, cse->tmp_iv, cse->txform->blocksize);
    549           1.1  jonathan 		crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
    550           1.1  jonathan 		crde->crd_skip = 0;
    551           1.1  jonathan 	} else if (crde) {
    552          1.20  christos 		if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
    553          1.20  christos 			crde->crd_skip = 0;
    554          1.20  christos 		} else {
    555          1.20  christos 			crde->crd_flags |= CRD_F_IV_PRESENT;
    556          1.20  christos 			crde->crd_skip = cse->txform->blocksize;
    557          1.20  christos 			crde->crd_len -= cse->txform->blocksize;
    558          1.20  christos 		}
    559           1.1  jonathan 	}
    560           1.1  jonathan 
    561           1.1  jonathan 	if (cop->mac) {
    562           1.1  jonathan 		if (crda == NULL) {
    563           1.1  jonathan 			error = EINVAL;
    564           1.1  jonathan 			goto bail;
    565           1.1  jonathan 		}
    566           1.1  jonathan 		crp->crp_mac=cse->tmp_mac;
    567           1.1  jonathan 	}
    568           1.1  jonathan 
    569          1.33       tls 	/*
    570          1.33       tls 	 * XXX there was a comment here which said that we went to
    571          1.33       tls 	 * XXX splcrypto() but needed to only if CRYPTO_F_CBIMM,
    572          1.33       tls 	 * XXX disabled on NetBSD since 1.6O due to a race condition.
    573          1.33       tls 	 * XXX But crypto_dispatch went to splcrypto() itself!  (And
    574          1.33       tls 	 * XXX now takes the crypto_mtx mutex itself).  We do, however,
    575          1.33       tls 	 * XXX need to hold the mutex across the call to cv_wait().
    576          1.33       tls 	 * XXX     (should we arrange for crypto_dispatch to return to
    577          1.33       tls 	 * XXX      us with it held?  it seems quite ugly to do so.)
    578          1.33       tls 	 */
    579          1.36       tls #ifdef notyet
    580          1.36       tls eagain:
    581          1.36       tls #endif
    582           1.1  jonathan 	error = crypto_dispatch(crp);
    583          1.33       tls 	mutex_spin_enter(&crypto_mtx);
    584          1.36       tls 
    585      1.44.8.1       snj 	/*
    586      1.44.8.1       snj 	 * If the request was going to be completed by the
    587      1.44.8.1       snj 	 * ioctl thread then it would have been done by now.
    588  1.44.8.2.4.1      matt 	 * Remove the F_USER flag so crypto_done() is not confused
    589      1.44.8.1       snj 	 * if the crypto device calls it after this point.
    590      1.44.8.1       snj 	 */
    591      1.44.8.1       snj 	crp->crp_flags &= ~(CRYPTO_F_USER);
    592      1.44.8.1       snj 
    593          1.36       tls 	switch (error) {
    594          1.36       tls #ifdef notyet	/* don't loop forever -- but EAGAIN not possible here yet */
    595          1.36       tls 	case EAGAIN:
    596          1.36       tls 		mutex_spin_exit(&crypto_mtx);
    597          1.36       tls 		goto eagain;
    598          1.36       tls 		break;
    599          1.36       tls #endif
    600          1.36       tls 	case 0:
    601          1.36       tls 		break;
    602          1.36       tls 	default:
    603          1.33       tls 		DPRINTF(("cryptodev_op: not waiting, error.\n"));
    604          1.33       tls 		mutex_spin_exit(&crypto_mtx);
    605           1.1  jonathan 		goto bail;
    606           1.1  jonathan 	}
    607      1.44.8.1       snj 
    608          1.33       tls 	while (!(crp->crp_flags & CRYPTO_F_DONE)) {
    609  1.44.8.2.4.1      matt 		DPRINTF(("cryptodev_op[%d]: sleeping on cv %08x for crp %08x\n",
    610  1.44.8.2.4.1      matt 			(uint32_t)cse->sid, (uint32_t)&crp->crp_cv,
    611  1.44.8.2.4.1      matt 			(uint32_t)crp));
    612          1.33       tls 		cv_wait(&crp->crp_cv, &crypto_mtx);	/* XXX cv_wait_sig? */
    613          1.33       tls 	}
    614          1.33       tls 	if (crp->crp_flags & CRYPTO_F_ONRETQ) {
    615      1.44.8.1       snj 		/* XXX this should never happen now with the CRYPTO_F_USER flag
    616      1.44.8.1       snj 		 * changes.
    617      1.44.8.1       snj 		 */
    618          1.33       tls 		DPRINTF(("cryptodev_op: DONE, not woken by cryptoret.\n"));
    619          1.33       tls 		(void)crypto_ret_q_remove(crp);
    620          1.33       tls 	}
    621          1.33       tls 	mutex_spin_exit(&crypto_mtx);
    622           1.1  jonathan 
    623           1.1  jonathan 	if (crp->crp_etype != 0) {
    624          1.34       tls 		DPRINTF(("cryptodev_op: crp_etype %d\n", crp->crp_etype));
    625           1.1  jonathan 		error = crp->crp_etype;
    626           1.1  jonathan 		goto bail;
    627           1.1  jonathan 	}
    628           1.1  jonathan 
    629           1.1  jonathan 	if (cse->error) {
    630          1.34       tls 		DPRINTF(("cryptodev_op: cse->error %d\n", cse->error));
    631           1.1  jonathan 		error = cse->error;
    632           1.1  jonathan 		goto bail;
    633           1.1  jonathan 	}
    634           1.1  jonathan 
    635  1.44.8.2.4.1      matt 	dst_len = crp->crp_ilen;
    636  1.44.8.2.4.1      matt 	/* let the user know how much data was returned */
    637  1.44.8.2.4.1      matt 	if (crp->crp_olen) {
    638  1.44.8.2.4.1      matt 		dst_len = cop->dst_len = crp->crp_olen;
    639  1.44.8.2.4.1      matt 	}
    640  1.44.8.2.4.1      matt 	crp->len = dst_len;
    641  1.44.8.2.4.1      matt 
    642  1.44.8.2.4.1      matt 	if (cop->dst) {
    643  1.44.8.2.4.1      matt 		DPRINTF(("cryptodev_op: copyout %d bytes to %p\n", dst_len, cop->dst));
    644  1.44.8.2.4.1      matt 	}
    645           1.1  jonathan 	if (cop->dst &&
    646  1.44.8.2.4.1      matt 	    (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, dst_len)))
    647          1.36       tls 	{
    648          1.34       tls 		DPRINTF(("cryptodev_op: copyout error %d\n", error));
    649           1.1  jonathan 		goto bail;
    650          1.34       tls 	}
    651           1.1  jonathan 
    652           1.1  jonathan 	if (cop->mac &&
    653          1.34       tls 	    (error = copyout(crp->crp_mac, cop->mac, cse->thash->authsize))) {
    654          1.34       tls 		DPRINTF(("cryptodev_op: mac copyout error %d\n", error));
    655           1.1  jonathan 		goto bail;
    656          1.34       tls 	}
    657           1.1  jonathan 
    658  1.44.8.2.4.1      matt 
    659           1.1  jonathan bail:
    660      1.44.8.1       snj 	if (crp) {
    661           1.1  jonathan 		crypto_freereq(crp);
    662      1.44.8.1       snj 	}
    663  1.44.8.2.4.1      matt 	if (cse->uio.uio_iov[0].iov_base) {
    664  1.44.8.2.4.1      matt 		kmem_free(cse->uio.uio_iov[0].iov_base,iov_len);
    665  1.44.8.2.4.1      matt 	}
    666           1.1  jonathan 
    667          1.42  christos 	return error;
    668           1.1  jonathan }
    669           1.1  jonathan 
    670           1.1  jonathan static int
    671           1.1  jonathan cryptodev_cb(void *op)
    672           1.1  jonathan {
    673           1.1  jonathan 	struct cryptop *crp = (struct cryptop *) op;
    674           1.1  jonathan 	struct csession *cse = (struct csession *)crp->crp_opaque;
    675          1.33       tls 	int error = 0;
    676           1.1  jonathan 
    677          1.33       tls 	mutex_spin_enter(&crypto_mtx);
    678           1.1  jonathan 	cse->error = crp->crp_etype;
    679          1.33       tls 	if (crp->crp_etype == EAGAIN) {
    680          1.33       tls 		/* always drop mutex to call dispatch routine */
    681          1.33       tls 		mutex_spin_exit(&crypto_mtx);
    682          1.33       tls 		error = crypto_dispatch(crp);
    683          1.33       tls 		mutex_spin_enter(&crypto_mtx);
    684          1.33       tls 	}
    685          1.33       tls 	if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) {
    686          1.33       tls 		cv_signal(&crp->crp_cv);
    687          1.33       tls 	}
    688          1.33       tls 	mutex_spin_exit(&crypto_mtx);
    689          1.42  christos 	return 0;
    690           1.1  jonathan }
    691           1.1  jonathan 
    692           1.1  jonathan static int
    693          1.36       tls cryptodev_mcb(void *op)
    694          1.36       tls {
    695          1.36       tls 	struct cryptop *crp = (struct cryptop *) op;
    696          1.36       tls 	struct csession *cse = (struct csession *)crp->crp_opaque;
    697          1.36       tls 	int  error=0;
    698          1.36       tls 
    699          1.36       tls 	mutex_spin_enter(&crypto_mtx);
    700          1.36       tls 	cse->error = crp->crp_etype;
    701          1.36       tls 	if (crp->crp_etype == EAGAIN) {
    702          1.36       tls 		mutex_spin_exit(&crypto_mtx);
    703          1.36       tls 		error = crypto_dispatch(crp);
    704          1.36       tls 		mutex_spin_enter(&crypto_mtx);
    705          1.36       tls 	}
    706          1.36       tls 	if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) {
    707          1.36       tls 		cv_signal(&crp->crp_cv);
    708          1.36       tls 	}
    709          1.36       tls 
    710          1.36       tls 	TAILQ_INSERT_TAIL(&crp->fcrp->crp_ret_mq, crp, crp_next);
    711          1.38     rmind 	selnotify(&crp->fcrp->sinfo, 0, 0);
    712          1.36       tls 	mutex_spin_exit(&crypto_mtx);
    713          1.42  christos 	return 0;
    714          1.36       tls }
    715          1.36       tls 
    716          1.36       tls static int
    717           1.1  jonathan cryptodevkey_cb(void *op)
    718           1.1  jonathan {
    719          1.42  christos 	struct cryptkop *krp = op;
    720          1.36       tls 
    721          1.36       tls 	mutex_spin_enter(&crypto_mtx);
    722          1.36       tls 	cv_signal(&krp->krp_cv);
    723          1.36       tls 	mutex_spin_exit(&crypto_mtx);
    724          1.42  christos 	return 0;
    725          1.36       tls }
    726          1.36       tls 
    727          1.36       tls static int
    728          1.36       tls cryptodevkey_mcb(void *op)
    729          1.36       tls {
    730          1.42  christos 	struct cryptkop *krp = op;
    731           1.1  jonathan 
    732          1.33       tls 	mutex_spin_enter(&crypto_mtx);
    733          1.33       tls 	cv_signal(&krp->krp_cv);
    734          1.36       tls 	TAILQ_INSERT_TAIL(&krp->fcrp->crp_ret_mkq, krp, krp_next);
    735          1.38     rmind 	selnotify(&krp->fcrp->sinfo, 0, 0);
    736          1.33       tls 	mutex_spin_exit(&crypto_mtx);
    737          1.42  christos 	return 0;
    738           1.1  jonathan }
    739           1.1  jonathan 
    740           1.1  jonathan static int
    741           1.1  jonathan cryptodev_key(struct crypt_kop *kop)
    742           1.1  jonathan {
    743           1.1  jonathan 	struct cryptkop *krp = NULL;
    744           1.1  jonathan 	int error = EINVAL;
    745           1.1  jonathan 	int in, out, size, i;
    746           1.1  jonathan 
    747          1.42  christos 	if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM)
    748          1.42  christos 		return EFBIG;
    749           1.1  jonathan 
    750           1.1  jonathan 	in = kop->crk_iparams;
    751           1.1  jonathan 	out = kop->crk_oparams;
    752           1.1  jonathan 	switch (kop->crk_op) {
    753           1.1  jonathan 	case CRK_MOD_EXP:
    754           1.1  jonathan 		if (in == 3 && out == 1)
    755           1.1  jonathan 			break;
    756          1.42  christos 		return EINVAL;
    757           1.1  jonathan 	case CRK_MOD_EXP_CRT:
    758           1.1  jonathan 		if (in == 6 && out == 1)
    759           1.1  jonathan 			break;
    760          1.42  christos 		return EINVAL;
    761           1.1  jonathan 	case CRK_DSA_SIGN:
    762           1.1  jonathan 		if (in == 5 && out == 2)
    763           1.1  jonathan 			break;
    764          1.42  christos 		return EINVAL;
    765           1.1  jonathan 	case CRK_DSA_VERIFY:
    766           1.1  jonathan 		if (in == 7 && out == 0)
    767           1.1  jonathan 			break;
    768          1.42  christos 		return EINVAL;
    769           1.1  jonathan 	case CRK_DH_COMPUTE_KEY:
    770           1.1  jonathan 		if (in == 3 && out == 1)
    771           1.1  jonathan 			break;
    772          1.42  christos 		return EINVAL;
    773          1.27       tls 	case CRK_MOD_ADD:
    774          1.27       tls 		if (in == 3 && out == 1)
    775          1.27       tls 			break;
    776          1.42  christos 		return EINVAL;
    777          1.27       tls 	case CRK_MOD_ADDINV:
    778          1.27       tls 		if (in == 2 && out == 1)
    779          1.27       tls 			break;
    780          1.42  christos 		return EINVAL;
    781          1.27       tls 	case CRK_MOD_SUB:
    782          1.27       tls 		if (in == 3 && out == 1)
    783          1.27       tls 			break;
    784          1.42  christos 		return EINVAL;
    785          1.27       tls 	case CRK_MOD_MULT:
    786          1.27       tls 		if (in == 3 && out == 1)
    787          1.27       tls 			break;
    788          1.42  christos 		return EINVAL;
    789          1.27       tls 	case CRK_MOD_MULTINV:
    790          1.27       tls 		if (in == 2 && out == 1)
    791          1.27       tls 			break;
    792          1.42  christos 		return EINVAL;
    793          1.27       tls 	case CRK_MOD:
    794          1.27       tls 		if (in == 2 && out == 1)
    795          1.27       tls 			break;
    796          1.42  christos 		return EINVAL;
    797           1.1  jonathan 	default:
    798          1.42  christos 		return EINVAL;
    799           1.1  jonathan 	}
    800           1.1  jonathan 
    801          1.33       tls 	krp = pool_get(&cryptkop_pool, PR_WAITOK);
    802          1.42  christos 	(void)memset(krp, 0, sizeof *krp);
    803          1.33       tls 	cv_init(&krp->krp_cv, "crykdev");
    804           1.1  jonathan 	krp->krp_op = kop->crk_op;
    805           1.1  jonathan 	krp->krp_status = kop->crk_status;
    806           1.1  jonathan 	krp->krp_iparams = kop->crk_iparams;
    807           1.1  jonathan 	krp->krp_oparams = kop->crk_oparams;
    808           1.1  jonathan 	krp->krp_status = 0;
    809           1.1  jonathan 	krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
    810           1.1  jonathan 
    811           1.1  jonathan 	for (i = 0; i < CRK_MAXPARAM; i++)
    812           1.1  jonathan 		krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
    813           1.1  jonathan 	for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
    814           1.1  jonathan 		size = (krp->krp_param[i].crp_nbits + 7) / 8;
    815           1.1  jonathan 		if (size == 0)
    816           1.1  jonathan 			continue;
    817          1.36       tls 		krp->krp_param[i].crp_p = kmem_alloc(size, KM_SLEEP);
    818           1.1  jonathan 		if (i >= krp->krp_iparams)
    819           1.1  jonathan 			continue;
    820          1.42  christos 		error = copyin(kop->crk_param[i].crp_p,
    821          1.42  christos 		    krp->krp_param[i].crp_p, size);
    822           1.1  jonathan 		if (error)
    823           1.1  jonathan 			goto fail;
    824           1.1  jonathan 	}
    825           1.1  jonathan 
    826           1.1  jonathan 	error = crypto_kdispatch(krp);
    827          1.33       tls 	if (error != 0) {
    828           1.1  jonathan 		goto fail;
    829          1.33       tls 	}
    830          1.33       tls 
    831          1.33       tls 	mutex_spin_enter(&crypto_mtx);
    832          1.33       tls 	while (!(krp->krp_flags & CRYPTO_F_DONE)) {
    833          1.33       tls 		cv_wait(&krp->krp_cv, &crypto_mtx);	/* XXX cv_wait_sig? */
    834          1.33       tls 	}
    835          1.33       tls 	if (krp->krp_flags & CRYPTO_F_ONRETQ) {
    836          1.33       tls 		DPRINTF(("cryptodev_key: DONE early, not via cryptoret.\n"));
    837          1.33       tls 		(void)crypto_ret_kq_remove(krp);
    838          1.33       tls 	}
    839          1.33       tls 	mutex_spin_exit(&crypto_mtx);
    840           1.1  jonathan 
    841           1.1  jonathan 	if (krp->krp_status != 0) {
    842          1.42  christos 		DPRINTF(("cryptodev_key: krp->krp_status 0x%08x\n",
    843          1.42  christos 		    krp->krp_status));
    844           1.1  jonathan 		error = krp->krp_status;
    845           1.1  jonathan 		goto fail;
    846           1.1  jonathan 	}
    847           1.1  jonathan 
    848          1.42  christos 	for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams;
    849          1.42  christos 	    i++) {
    850           1.1  jonathan 		size = (krp->krp_param[i].crp_nbits + 7) / 8;
    851           1.1  jonathan 		if (size == 0)
    852           1.1  jonathan 			continue;
    853          1.42  christos 		error = copyout(krp->krp_param[i].crp_p,
    854          1.42  christos 		    kop->crk_param[i].crp_p, size);
    855          1.34       tls 		if (error) {
    856          1.42  christos 			DPRINTF(("cryptodev_key: copyout oparam %d failed, "
    857          1.42  christos 			    "error=%d\n", i-krp->krp_iparams, error));
    858           1.1  jonathan 			goto fail;
    859          1.34       tls 		}
    860           1.1  jonathan 	}
    861           1.1  jonathan 
    862           1.1  jonathan fail:
    863          1.43  christos 	kop->crk_status = krp->krp_status;
    864          1.43  christos 	for (i = 0; i < CRK_MAXPARAM; i++) {
    865          1.43  christos 		struct crparam *kp = &(krp->krp_param[i]);
    866          1.43  christos 		if (krp->krp_param[i].crp_p) {
    867          1.43  christos 			size = (kp->crp_nbits + 7)  / 8;
    868          1.43  christos 			KASSERT(size > 0);
    869          1.43  christos 			(void)memset(kp->crp_p, 0, size);
    870          1.43  christos 			kmem_free(kp->crp_p, size);
    871           1.1  jonathan 		}
    872           1.1  jonathan 	}
    873      1.44.8.1       snj 	cv_destroy(&krp->krp_cv);
    874          1.43  christos 	pool_put(&cryptkop_pool, krp);
    875          1.34       tls 	DPRINTF(("cryptodev_key: error=0x%08x\n", error));
    876          1.42  christos 	return error;
    877           1.1  jonathan }
    878           1.1  jonathan 
    879           1.1  jonathan /* ARGSUSED */
    880           1.1  jonathan static int
    881          1.36       tls cryptof_close(struct file *fp)
    882           1.1  jonathan {
    883          1.35        ad 	struct fcrypt *fcr = fp->f_data;
    884           1.1  jonathan 	struct csession *cse;
    885           1.1  jonathan 
    886          1.33       tls 	mutex_spin_enter(&crypto_mtx);
    887           1.1  jonathan 	while ((cse = TAILQ_FIRST(&fcr->csessions))) {
    888           1.1  jonathan 		TAILQ_REMOVE(&fcr->csessions, cse, next);
    889           1.1  jonathan 		(void)csefree(cse);
    890           1.1  jonathan 	}
    891          1.36       tls 	seldestroy(&fcr->sinfo);
    892           1.1  jonathan 	fp->f_data = NULL;
    893          1.33       tls 	mutex_spin_exit(&crypto_mtx);
    894           1.1  jonathan 
    895          1.38     rmind 	pool_put(&fcrpl, fcr);
    896           1.1  jonathan 	return 0;
    897           1.1  jonathan }
    898           1.1  jonathan 
    899  1.44.8.2.4.1      matt /* needed for compatibility module */
    900  1.44.8.2.4.1      matt struct	csession *cryptodev_csefind(struct fcrypt *fcr, u_int ses)
    901  1.44.8.2.4.1      matt {
    902  1.44.8.2.4.1      matt 	return csefind(fcr, ses);
    903  1.44.8.2.4.1      matt }
    904  1.44.8.2.4.1      matt 
    905          1.33       tls /* csefind: call with crypto_mtx held. */
    906           1.1  jonathan static struct csession *
    907           1.1  jonathan csefind(struct fcrypt *fcr, u_int ses)
    908           1.1  jonathan {
    909      1.44.8.1       snj 	struct csession *cse, *cnext, *ret = NULL;
    910           1.1  jonathan 
    911          1.33       tls 	KASSERT(mutex_owned(&crypto_mtx));
    912      1.44.8.1       snj 	TAILQ_FOREACH_SAFE(cse, &fcr->csessions, next, cnext)
    913           1.1  jonathan 		if (cse->ses == ses)
    914          1.33       tls 			ret = cse;
    915          1.36       tls 
    916          1.42  christos 	return ret;
    917           1.1  jonathan }
    918           1.1  jonathan 
    919          1.33       tls /* csedelete: call with crypto_mtx held. */
    920           1.1  jonathan static int
    921           1.1  jonathan csedelete(struct fcrypt *fcr, struct csession *cse_del)
    922           1.1  jonathan {
    923      1.44.8.1       snj 	struct csession *cse, *cnext;
    924          1.33       tls 	int ret = 0;
    925           1.1  jonathan 
    926          1.33       tls 	KASSERT(mutex_owned(&crypto_mtx));
    927      1.44.8.1       snj 	TAILQ_FOREACH_SAFE(cse, &fcr->csessions, next, cnext) {
    928           1.1  jonathan 		if (cse == cse_del) {
    929           1.1  jonathan 			TAILQ_REMOVE(&fcr->csessions, cse, next);
    930          1.33       tls 			ret = 1;
    931           1.1  jonathan 		}
    932           1.1  jonathan 	}
    933          1.42  christos 	return ret;
    934           1.1  jonathan }
    935           1.1  jonathan 
    936          1.33       tls /* cseadd: call with crypto_mtx held. */
    937           1.1  jonathan static struct csession *
    938           1.1  jonathan cseadd(struct fcrypt *fcr, struct csession *cse)
    939           1.1  jonathan {
    940          1.33       tls 	KASSERT(mutex_owned(&crypto_mtx));
    941          1.33       tls 	/* don't let session ID wrap! */
    942          1.33       tls 	if (fcr->sesn + 1 == 0) return NULL;
    943           1.1  jonathan 	TAILQ_INSERT_TAIL(&fcr->csessions, cse, next);
    944           1.1  jonathan 	cse->ses = fcr->sesn++;
    945          1.42  christos 	return cse;
    946           1.1  jonathan }
    947           1.1  jonathan 
    948          1.33       tls /* csecreate: call with crypto_mtx held. */
    949           1.1  jonathan static struct csession *
    950          1.26  christos csecreate(struct fcrypt *fcr, u_int64_t sid, void *key, u_int64_t keylen,
    951          1.26  christos     void *mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac,
    952  1.44.8.2.4.1      matt     u_int32_t comp_alg, struct enc_xform *txform, struct auth_hash *thash,
    953  1.44.8.2.4.1      matt     struct comp_algo *tcomp)
    954           1.1  jonathan {
    955           1.1  jonathan 	struct csession *cse;
    956           1.1  jonathan 
    957          1.33       tls 	KASSERT(mutex_owned(&crypto_mtx));
    958          1.29       tls 	cse = pool_get(&csepl, PR_NOWAIT);
    959           1.1  jonathan 	if (cse == NULL)
    960           1.1  jonathan 		return NULL;
    961           1.1  jonathan 	cse->key = key;
    962           1.1  jonathan 	cse->keylen = keylen/8;
    963           1.1  jonathan 	cse->mackey = mackey;
    964           1.1  jonathan 	cse->mackeylen = mackeylen/8;
    965           1.1  jonathan 	cse->sid = sid;
    966           1.1  jonathan 	cse->cipher = cipher;
    967           1.1  jonathan 	cse->mac = mac;
    968  1.44.8.2.4.1      matt 	cse->comp_alg = comp_alg;
    969           1.1  jonathan 	cse->txform = txform;
    970           1.1  jonathan 	cse->thash = thash;
    971  1.44.8.2.4.1      matt 	cse->tcomp = tcomp;
    972          1.34       tls 	cse->error = 0;
    973          1.28       tls 	if (cseadd(fcr, cse))
    974          1.42  christos 		return cse;
    975          1.28       tls 	else {
    976          1.33       tls 		pool_put(&csepl, cse);
    977          1.28       tls 		return NULL;
    978          1.28       tls 	}
    979           1.1  jonathan }
    980           1.1  jonathan 
    981          1.33       tls /* csefree: call with crypto_mtx held. */
    982           1.1  jonathan static int
    983           1.1  jonathan csefree(struct csession *cse)
    984           1.1  jonathan {
    985           1.1  jonathan 	int error;
    986           1.1  jonathan 
    987          1.33       tls 	KASSERT(mutex_owned(&crypto_mtx));
    988           1.1  jonathan 	error = crypto_freesession(cse->sid);
    989           1.1  jonathan 	if (cse->key)
    990          1.36       tls 		free(cse->key, M_XDATA);
    991           1.1  jonathan 	if (cse->mackey)
    992          1.36       tls 		free(cse->mackey, M_XDATA);
    993          1.29       tls 	pool_put(&csepl, cse);
    994          1.42  christos 	return error;
    995           1.1  jonathan }
    996           1.1  jonathan 
    997           1.1  jonathan static int
    998          1.25  christos cryptoopen(dev_t dev, int flag, int mode,
    999          1.25  christos     struct lwp *l)
   1000           1.1  jonathan {
   1001          1.35        ad 	file_t *fp;
   1002          1.29       tls         struct fcrypt *fcr;
   1003          1.29       tls         int fd, error;
   1004          1.29       tls 
   1005           1.1  jonathan 	if (crypto_usercrypto == 0)
   1006          1.42  christos 		return ENXIO;
   1007          1.29       tls 
   1008          1.35        ad 	if ((error = fd_allocfile(&fp, &fd)) != 0)
   1009          1.29       tls 		return error;
   1010          1.29       tls 
   1011          1.29       tls 	fcr = pool_get(&fcrpl, PR_WAITOK);
   1012          1.33       tls 	mutex_spin_enter(&crypto_mtx);
   1013          1.29       tls 	TAILQ_INIT(&fcr->csessions);
   1014          1.36       tls 	TAILQ_INIT(&fcr->crp_ret_mq);
   1015          1.36       tls 	TAILQ_INIT(&fcr->crp_ret_mkq);
   1016          1.36       tls 	selinit(&fcr->sinfo);
   1017          1.29       tls 	/*
   1018          1.29       tls 	 * Don't ever return session 0, to allow detection of
   1019          1.29       tls 	 * failed creation attempts with multi-create ioctl.
   1020          1.29       tls 	 */
   1021          1.29       tls 	fcr->sesn = 1;
   1022          1.36       tls 	fcr->requestid = 1;
   1023          1.33       tls 	mutex_spin_exit(&crypto_mtx);
   1024          1.35        ad 	return fd_clone(fp, fd, flag, &cryptofops, fcr);
   1025           1.1  jonathan }
   1026           1.1  jonathan 
   1027           1.1  jonathan static int
   1028          1.25  christos cryptoread(dev_t dev, struct uio *uio, int ioflag)
   1029           1.1  jonathan {
   1030          1.42  christos 	return EIO;
   1031           1.1  jonathan }
   1032           1.1  jonathan 
   1033           1.1  jonathan static int
   1034          1.25  christos cryptowrite(dev_t dev, struct uio *uio, int ioflag)
   1035           1.1  jonathan {
   1036          1.42  christos 	return EIO;
   1037           1.1  jonathan }
   1038           1.1  jonathan 
   1039           1.1  jonathan int
   1040          1.25  christos cryptoselect(dev_t dev, int rw, struct lwp *l)
   1041           1.1  jonathan {
   1042          1.42  christos 	return 0;
   1043           1.1  jonathan }
   1044           1.1  jonathan 
   1045           1.1  jonathan /*static*/
   1046           1.1  jonathan struct cdevsw crypto_cdevsw = {
   1047           1.1  jonathan 	/* open */	cryptoopen,
   1048          1.29       tls 	/* close */	noclose,
   1049           1.1  jonathan 	/* read */	cryptoread,
   1050           1.1  jonathan 	/* write */	cryptowrite,
   1051          1.29       tls 	/* ioctl */	noioctl,
   1052           1.1  jonathan 	/* ttstop?*/	nostop,
   1053           1.1  jonathan 	/* ??*/		notty,
   1054           1.1  jonathan 	/* poll */	cryptoselect /*nopoll*/,
   1055           1.1  jonathan 	/* mmap */	nommap,
   1056           1.1  jonathan 	/* kqfilter */	nokqfilter,
   1057          1.23  christos 	/* type */	D_OTHER,
   1058           1.1  jonathan };
   1059           1.1  jonathan 
   1060  1.44.8.2.4.1      matt int
   1061          1.36       tls cryptodev_mop(struct fcrypt *fcr,
   1062          1.36       tls               struct crypt_n_op * cnop,
   1063          1.36       tls               int count, struct lwp *l)
   1064          1.36       tls {
   1065          1.36       tls 	struct cryptop *crp = NULL;
   1066  1.44.8.2.4.1      matt 	struct cryptodesc *crde = NULL, *crda = NULL, *crdc = NULL;
   1067          1.36       tls 	int req, error=0;
   1068          1.36       tls 	struct csession *cse;
   1069  1.44.8.2.4.1      matt 	int flags=0;
   1070  1.44.8.2.4.1      matt 	int iov_len;
   1071          1.36       tls 
   1072          1.36       tls 	for (req = 0; req < count; req++) {
   1073          1.36       tls 		mutex_spin_enter(&crypto_mtx);
   1074          1.36       tls 		cse = csefind(fcr, cnop[req].ses);
   1075          1.36       tls 		if (cse == NULL) {
   1076          1.36       tls 			DPRINTF(("csefind failed\n"));
   1077          1.36       tls 			cnop[req].status = EINVAL;
   1078          1.36       tls 			mutex_spin_exit(&crypto_mtx);
   1079          1.36       tls 			continue;
   1080          1.36       tls 		}
   1081          1.36       tls 		mutex_spin_exit(&crypto_mtx);
   1082          1.36       tls 
   1083          1.36       tls 		if (cnop[req].len > 256*1024-4) {
   1084          1.36       tls 			DPRINTF(("length failed\n"));
   1085          1.36       tls 			cnop[req].status = EINVAL;
   1086          1.36       tls 			continue;
   1087          1.36       tls 		}
   1088          1.36       tls 		if (cse->txform) {
   1089          1.36       tls 			if (cnop[req].len == 0 ||
   1090          1.36       tls 			    (cnop[req].len % cse->txform->blocksize) != 0) {
   1091          1.36       tls 				cnop[req].status = EINVAL;
   1092          1.36       tls 				continue;
   1093          1.36       tls 			}
   1094          1.36       tls 		}
   1095          1.36       tls 
   1096          1.42  christos 		crp = crypto_getreq((cse->txform != NULL) +
   1097  1.44.8.2.4.1      matt 				    (cse->thash != NULL) +
   1098  1.44.8.2.4.1      matt 				    (cse->tcomp != NULL));
   1099          1.36       tls 		if (crp == NULL) {
   1100          1.36       tls 			cnop[req].status = ENOMEM;
   1101          1.36       tls 			goto bail;
   1102          1.36       tls 		}
   1103          1.36       tls 
   1104  1.44.8.2.4.1      matt 		iov_len = cnop[req].len;
   1105  1.44.8.2.4.1      matt 		/* got a compression/decompression max size? */
   1106  1.44.8.2.4.1      matt 		if ((cse->tcomp) && cnop[req].dst_len) {
   1107  1.44.8.2.4.1      matt 			if (iov_len < cnop[req].dst_len) {
   1108  1.44.8.2.4.1      matt 				/* Need larger iov to deal with decompress */
   1109  1.44.8.2.4.1      matt 				iov_len = cnop[req].dst_len;
   1110  1.44.8.2.4.1      matt 			}
   1111  1.44.8.2.4.1      matt 			DPRINTF(("cryptodev_mop: iov_len -> %d for decompress\n", iov_len));
   1112  1.44.8.2.4.1      matt 		}
   1113  1.44.8.2.4.1      matt 
   1114          1.42  christos 		(void)memset(&crp->uio, 0, sizeof(crp->uio));
   1115          1.36       tls 		crp->uio.uio_iovcnt = 1;
   1116          1.36       tls 		crp->uio.uio_resid = 0;
   1117          1.36       tls 		crp->uio.uio_rw = UIO_WRITE;
   1118          1.36       tls 		crp->uio.uio_iov = crp->iovec;
   1119          1.36       tls 		UIO_SETUP_SYSSPACE(&crp->uio);
   1120          1.36       tls 		memset(&crp->iovec, 0, sizeof(crp->iovec));
   1121  1.44.8.2.4.1      matt 		crp->uio.uio_iov[0].iov_len = iov_len;
   1122  1.44.8.2.4.1      matt 		DPRINTF(("cryptodev_mop: kmem_alloc(%d) for iov \n", iov_len));
   1123  1.44.8.2.4.1      matt 		crp->uio.uio_iov[0].iov_base = kmem_alloc(iov_len, KM_SLEEP);
   1124          1.36       tls 		crp->uio.uio_resid = crp->uio.uio_iov[0].iov_len;
   1125          1.36       tls 
   1126  1.44.8.2.4.1      matt 		if (cse->tcomp) {
   1127  1.44.8.2.4.1      matt 			crdc = crp->crp_desc;
   1128  1.44.8.2.4.1      matt 		}
   1129  1.44.8.2.4.1      matt 
   1130          1.36       tls 		if (cse->thash) {
   1131  1.44.8.2.4.1      matt 			crda = crdc ? crdc->crd_next : crp->crp_desc;
   1132          1.44  christos 			if (cse->txform && crda)
   1133          1.36       tls 				crde = crda->crd_next;
   1134          1.36       tls 		} else {
   1135  1.44.8.2.4.1      matt 			if (cse->txform) {
   1136  1.44.8.2.4.1      matt 				crde = crdc ? crdc->crd_next : crp->crp_desc;
   1137  1.44.8.2.4.1      matt 			} else if (!cse->tcomp) {
   1138  1.44.8.2.4.1      matt 				error = EINVAL;
   1139  1.44.8.2.4.1      matt 				goto bail;
   1140          1.36       tls 			}
   1141          1.36       tls 		}
   1142          1.36       tls 
   1143          1.36       tls 		if ((copyin(cnop[req].src,
   1144          1.36       tls 		    crp->uio.uio_iov[0].iov_base, cnop[req].len))) {
   1145          1.36       tls 			cnop[req].status = EINVAL;
   1146          1.36       tls 			goto bail;
   1147          1.36       tls 		}
   1148  1.44.8.2.4.1      matt 
   1149  1.44.8.2.4.1      matt 		if (crdc) {
   1150  1.44.8.2.4.1      matt 			switch (cnop[req].op) {
   1151  1.44.8.2.4.1      matt 			case COP_COMP:
   1152  1.44.8.2.4.1      matt 				crdc->crd_flags |= CRD_F_COMP;
   1153  1.44.8.2.4.1      matt 				break;
   1154  1.44.8.2.4.1      matt 			case COP_DECOMP:
   1155  1.44.8.2.4.1      matt 				crdc->crd_flags &= ~CRD_F_COMP;
   1156  1.44.8.2.4.1      matt 				break;
   1157  1.44.8.2.4.1      matt 			default:
   1158  1.44.8.2.4.1      matt 				break;
   1159  1.44.8.2.4.1      matt 			}
   1160  1.44.8.2.4.1      matt 			/* more data to follow? */
   1161  1.44.8.2.4.1      matt 			if (cnop[req].flags & COP_F_MORE) {
   1162  1.44.8.2.4.1      matt 				flags |= CRYPTO_F_MORE;
   1163  1.44.8.2.4.1      matt 			}
   1164  1.44.8.2.4.1      matt 			crdc->crd_len = cnop[req].len;
   1165  1.44.8.2.4.1      matt 			crdc->crd_inject = 0;
   1166  1.44.8.2.4.1      matt 
   1167  1.44.8.2.4.1      matt 			crdc->crd_alg = cse->comp_alg;
   1168  1.44.8.2.4.1      matt 			crdc->crd_key = NULL;
   1169  1.44.8.2.4.1      matt 			crdc->crd_klen = 0;
   1170  1.44.8.2.4.1      matt 			DPRINTF(("cryptodev_mop[%d]: crdc setup for comp_alg %d"
   1171  1.44.8.2.4.1      matt 				 " len %d.\n",
   1172  1.44.8.2.4.1      matt 				(uint32_t)cse->sid, crdc->crd_alg,
   1173  1.44.8.2.4.1      matt 				crdc->crd_len));
   1174  1.44.8.2.4.1      matt 		}
   1175          1.36       tls 
   1176          1.36       tls 		if (crda) {
   1177          1.36       tls 			crda->crd_skip = 0;
   1178          1.36       tls 			crda->crd_len = cnop[req].len;
   1179          1.36       tls 			crda->crd_inject = 0;	/* ??? */
   1180          1.36       tls 
   1181          1.36       tls 			crda->crd_alg = cse->mac;
   1182          1.36       tls 			crda->crd_key = cse->mackey;
   1183          1.36       tls 			crda->crd_klen = cse->mackeylen * 8;
   1184          1.36       tls 		}
   1185          1.36       tls 
   1186          1.36       tls 		if (crde) {
   1187          1.36       tls 			if (cnop[req].op == COP_ENCRYPT)
   1188          1.36       tls 				crde->crd_flags |= CRD_F_ENCRYPT;
   1189          1.36       tls 			else
   1190          1.36       tls 				crde->crd_flags &= ~CRD_F_ENCRYPT;
   1191          1.36       tls 			crde->crd_len = cnop[req].len;
   1192          1.36       tls 			crde->crd_inject = 0;
   1193          1.36       tls 
   1194          1.36       tls 			crde->crd_alg = cse->cipher;
   1195          1.36       tls #ifdef notyet		/* XXX must notify h/w driver new key, drain */
   1196          1.36       tls 			if(cnop[req].key && cnop[req].keylen) {
   1197          1.36       tls 				crde->crd_key = malloc(cnop[req].keylen,
   1198          1.36       tls 						    M_XDATA, M_WAITOK);
   1199          1.36       tls 				if((error = copyin(cnop[req].key,
   1200          1.36       tls 				    crde->crd_key, cnop[req].keylen))) {
   1201          1.36       tls 					cnop[req].status = EINVAL;
   1202          1.36       tls 					goto bail;
   1203          1.36       tls 				}
   1204          1.36       tls 				crde->crd_klen =  cnop[req].keylen * 8;
   1205          1.36       tls 			} else { ... }
   1206          1.36       tls #endif
   1207          1.36       tls 			crde->crd_key = cse->key;
   1208          1.36       tls 			crde->crd_klen = cse->keylen * 8;
   1209          1.36       tls 		}
   1210          1.36       tls 
   1211          1.36       tls 		crp->crp_ilen = cnop[req].len;
   1212          1.42  christos 		crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM |
   1213  1.44.8.2.4.1      matt 		    (cnop[req].flags & COP_F_BATCH) | flags;
   1214          1.36       tls 		crp->crp_buf = (void *)&crp->uio;
   1215          1.36       tls 		crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_mcb;
   1216          1.36       tls 		crp->crp_sid = cse->sid;
   1217          1.36       tls 		crp->crp_opaque = (void *)cse;
   1218          1.36       tls 		crp->fcrp = fcr;
   1219          1.36       tls 		crp->dst = cnop[req].dst;
   1220  1.44.8.2.4.1      matt 		crp->len = cnop[req].len; /* input len, iov may be larger */
   1221          1.36       tls 		crp->mac = cnop[req].mac;
   1222  1.44.8.2.4.1      matt 		DPRINTF(("cryptodev_mop: iov_base %p dst %p len %d mac %p\n",
   1223  1.44.8.2.4.1      matt 			    crp->uio.uio_iov[0].iov_base, crp->dst, crp->len,
   1224  1.44.8.2.4.1      matt 			    crp->mac));
   1225          1.36       tls 
   1226          1.36       tls 		if (cnop[req].iv) {
   1227          1.36       tls 			if (crde == NULL) {
   1228          1.36       tls 				cnop[req].status = EINVAL;
   1229          1.36       tls 				goto bail;
   1230          1.36       tls 			}
   1231          1.36       tls 			if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
   1232          1.36       tls 				cnop[req].status = EINVAL;
   1233          1.36       tls 				goto bail;
   1234          1.36       tls 			}
   1235          1.36       tls 			if ((error = copyin(cnop[req].iv, crp->tmp_iv,
   1236          1.36       tls 			    cse->txform->blocksize))) {
   1237          1.36       tls 				cnop[req].status = EINVAL;
   1238          1.36       tls 				goto bail;
   1239          1.36       tls 			}
   1240          1.42  christos 			(void)memcpy(crde->crd_iv, crp->tmp_iv,
   1241          1.42  christos 			    cse->txform->blocksize);
   1242          1.36       tls 			crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
   1243          1.36       tls 			crde->crd_skip = 0;
   1244          1.36       tls 		} else if (crde) {
   1245          1.36       tls 			if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
   1246          1.36       tls 				crde->crd_skip = 0;
   1247          1.36       tls 			} else {
   1248          1.36       tls 				crde->crd_flags |= CRD_F_IV_PRESENT;
   1249          1.36       tls 				crde->crd_skip = cse->txform->blocksize;
   1250          1.36       tls 				crde->crd_len -= cse->txform->blocksize;
   1251          1.36       tls 			}
   1252          1.36       tls 		}
   1253          1.36       tls 
   1254          1.36       tls 		if (cnop[req].mac) {
   1255          1.36       tls 			if (crda == NULL) {
   1256          1.36       tls 				cnop[req].status = EINVAL;
   1257          1.36       tls 				goto bail;
   1258          1.36       tls 			}
   1259          1.36       tls 			crp->crp_mac=cse->tmp_mac;
   1260          1.36       tls 		}
   1261          1.36       tls 		cnop[req].reqid = atomic_inc_32_nv(&(fcr->requestid));
   1262          1.36       tls 		crp->crp_reqid = cnop[req].reqid;
   1263          1.36       tls 		crp->crp_usropaque = cnop[req].opaque;
   1264          1.36       tls #ifdef notyet
   1265          1.36       tls eagain:
   1266          1.36       tls #endif
   1267          1.36       tls 		cnop[req].status = crypto_dispatch(crp);
   1268          1.36       tls 		mutex_spin_enter(&crypto_mtx);	/* XXX why mutex? */
   1269          1.36       tls 
   1270          1.36       tls 		switch (cnop[req].status) {
   1271          1.36       tls #ifdef notyet	/* don't loop forever -- but EAGAIN not possible here yet */
   1272          1.36       tls 		case EAGAIN:
   1273          1.36       tls 			mutex_spin_exit(&crypto_mtx);
   1274          1.36       tls 			goto eagain;
   1275          1.36       tls 			break;
   1276          1.36       tls #endif
   1277          1.36       tls 		case 0:
   1278          1.36       tls 			break;
   1279          1.36       tls 		default:
   1280          1.36       tls 			DPRINTF(("cryptodev_op: not waiting, error.\n"));
   1281          1.36       tls 			mutex_spin_exit(&crypto_mtx);
   1282          1.36       tls 			goto bail;
   1283          1.36       tls 		}
   1284          1.36       tls 
   1285          1.36       tls 		mutex_spin_exit(&crypto_mtx);
   1286          1.36       tls bail:
   1287          1.36       tls 		if (cnop[req].status) {
   1288          1.36       tls 			if (crp) {
   1289  1.44.8.2.4.1      matt 				if (crp->uio.uio_iov[0].iov_base) {
   1290  1.44.8.2.4.1      matt 					kmem_free(crp->uio.uio_iov[0].iov_base,
   1291  1.44.8.2.4.1      matt 					    crp->uio.uio_iov[0].iov_len);
   1292          1.36       tls 				}
   1293  1.44.8.2.4.1      matt 				crypto_freereq(crp);
   1294          1.36       tls 			}
   1295          1.36       tls 			error = 0;
   1296          1.36       tls 		}
   1297          1.36       tls 	}
   1298          1.42  christos 	return error;
   1299          1.36       tls }
   1300          1.36       tls 
   1301          1.36       tls static int
   1302          1.36       tls cryptodev_mkey(struct fcrypt *fcr, struct crypt_n_kop *kop, int count)
   1303          1.36       tls {
   1304          1.36       tls 	struct cryptkop *krp = NULL;
   1305          1.36       tls 	int error = EINVAL;
   1306          1.36       tls 	int in, out, size, i, req;
   1307          1.36       tls 
   1308          1.36       tls 	for (req = 0; req < count; req++) {
   1309          1.42  christos 		if (kop[req].crk_iparams + kop[req].crk_oparams > CRK_MAXPARAM)
   1310          1.42  christos 			return EFBIG;
   1311          1.36       tls 
   1312          1.36       tls 		in = kop[req].crk_iparams;
   1313          1.36       tls 		out = kop[req].crk_oparams;
   1314          1.36       tls 		switch (kop[req].crk_op) {
   1315          1.36       tls 		case CRK_MOD_EXP:
   1316          1.36       tls 			if (in == 3 && out == 1)
   1317          1.36       tls 				break;
   1318          1.36       tls 			kop[req].crk_status = EINVAL;
   1319          1.36       tls 			continue;
   1320          1.36       tls 		case CRK_MOD_EXP_CRT:
   1321          1.36       tls 			if (in == 6 && out == 1)
   1322          1.36       tls 				break;
   1323          1.36       tls 			kop[req].crk_status = EINVAL;
   1324          1.36       tls 			continue;
   1325          1.36       tls 		case CRK_DSA_SIGN:
   1326          1.36       tls 			if (in == 5 && out == 2)
   1327          1.36       tls 				break;
   1328          1.36       tls 			kop[req].crk_status = EINVAL;
   1329          1.36       tls 			continue;
   1330          1.36       tls 		case CRK_DSA_VERIFY:
   1331          1.36       tls 			if (in == 7 && out == 0)
   1332          1.36       tls 				break;
   1333          1.36       tls 			kop[req].crk_status = EINVAL;
   1334          1.36       tls 			continue;
   1335          1.36       tls 		case CRK_DH_COMPUTE_KEY:
   1336          1.36       tls 			if (in == 3 && out == 1)
   1337          1.36       tls 				break;
   1338          1.36       tls 			kop[req].crk_status = EINVAL;
   1339          1.36       tls 			continue;
   1340          1.36       tls 		case CRK_MOD_ADD:
   1341          1.36       tls 			if (in == 3 && out == 1)
   1342          1.36       tls 				break;
   1343          1.36       tls 			kop[req].crk_status = EINVAL;
   1344          1.36       tls 			continue;
   1345          1.36       tls 		case CRK_MOD_ADDINV:
   1346          1.36       tls 			if (in == 2 && out == 1)
   1347          1.36       tls 				break;
   1348          1.36       tls 			kop[req].crk_status = EINVAL;
   1349          1.36       tls 			continue;
   1350          1.36       tls 		case CRK_MOD_SUB:
   1351          1.36       tls 			if (in == 3 && out == 1)
   1352          1.36       tls 				break;
   1353          1.36       tls 			kop[req].crk_status = EINVAL;
   1354          1.36       tls 			continue;
   1355          1.36       tls 		case CRK_MOD_MULT:
   1356          1.36       tls 			if (in == 3 && out == 1)
   1357          1.36       tls 				break;
   1358          1.36       tls 			kop[req].crk_status = EINVAL;
   1359          1.36       tls 			continue;
   1360          1.36       tls 		case CRK_MOD_MULTINV:
   1361          1.36       tls 			if (in == 2 && out == 1)
   1362          1.36       tls 				break;
   1363          1.36       tls 			kop[req].crk_status = EINVAL;
   1364          1.36       tls 			continue;
   1365          1.36       tls 		case CRK_MOD:
   1366          1.36       tls 			if (in == 2 && out == 1)
   1367          1.36       tls 				break;
   1368          1.36       tls 			kop[req].crk_status = EINVAL;
   1369          1.36       tls 			continue;
   1370          1.36       tls 		default:
   1371          1.36       tls 			kop[req].crk_status = EINVAL;
   1372          1.36       tls 			continue;
   1373          1.36       tls 		}
   1374          1.36       tls 
   1375          1.36       tls 		krp = pool_get(&cryptkop_pool, PR_WAITOK);
   1376          1.42  christos 		(void)memset(krp, 0, sizeof *krp);
   1377          1.36       tls 		cv_init(&krp->krp_cv, "crykdev");
   1378          1.36       tls 		krp->krp_op = kop[req].crk_op;
   1379          1.36       tls 		krp->krp_status = kop[req].crk_status;
   1380          1.36       tls 		krp->krp_iparams = kop[req].crk_iparams;
   1381          1.36       tls 		krp->krp_oparams = kop[req].crk_oparams;
   1382          1.36       tls 		krp->krp_status = 0;
   1383          1.36       tls 		krp->krp_callback =
   1384          1.36       tls 		    (int (*) (struct cryptkop *)) cryptodevkey_mcb;
   1385          1.42  christos 		(void)memcpy(krp->crk_param, kop[req].crk_param,
   1386          1.42  christos 		    sizeof(kop[req].crk_param));
   1387          1.36       tls 
   1388          1.36       tls 		krp->krp_flags = CRYPTO_F_CBIMM;
   1389          1.36       tls 
   1390          1.36       tls 		for (i = 0; i < CRK_MAXPARAM; i++)
   1391          1.36       tls 			krp->krp_param[i].crp_nbits =
   1392          1.36       tls 			    kop[req].crk_param[i].crp_nbits;
   1393          1.36       tls 		for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
   1394          1.36       tls 			size = (krp->krp_param[i].crp_nbits + 7) / 8;
   1395          1.36       tls 			if (size == 0)
   1396          1.36       tls 				continue;
   1397          1.36       tls 			krp->krp_param[i].crp_p =
   1398          1.36       tls 			    kmem_alloc(size, KM_SLEEP);
   1399          1.36       tls 			if (i >= krp->krp_iparams)
   1400          1.36       tls 				continue;
   1401          1.42  christos 			kop[req].crk_status =
   1402          1.42  christos 			    copyin(kop[req].crk_param[i].crp_p,
   1403          1.42  christos 			    krp->krp_param[i].crp_p, size);
   1404          1.36       tls 			if (kop[req].crk_status)
   1405          1.36       tls 				goto fail;
   1406          1.36       tls 		}
   1407          1.36       tls 		krp->fcrp = fcr;
   1408          1.36       tls 
   1409          1.36       tls 		kop[req].crk_reqid = atomic_inc_32_nv(&(fcr->requestid));
   1410          1.36       tls 		krp->krp_reqid = kop[req].crk_reqid;
   1411          1.36       tls 		krp->krp_usropaque = kop[req].crk_opaque;
   1412          1.36       tls 
   1413          1.36       tls 		kop[req].crk_status = crypto_kdispatch(krp);
   1414          1.36       tls 		if (kop[req].crk_status != 0) {
   1415          1.36       tls 			goto fail;
   1416          1.36       tls 		}
   1417          1.36       tls 
   1418          1.36       tls fail:
   1419          1.36       tls 		if(kop[req].crk_status) {
   1420          1.36       tls 			if (krp) {
   1421          1.36       tls 				kop[req].crk_status = krp->krp_status;
   1422          1.36       tls 				for (i = 0; i < CRK_MAXPARAM; i++) {
   1423          1.36       tls 					struct crparam *kp =
   1424          1.36       tls 						&(krp->krp_param[i]);
   1425          1.36       tls 					if (kp->crp_p) {
   1426          1.36       tls 						size = (kp->crp_nbits + 7) / 8;
   1427          1.36       tls 						KASSERT(size > 0);
   1428          1.36       tls 						memset(kp->crp_p, 0, size);
   1429          1.36       tls 						kmem_free(kp->crp_p, size);
   1430          1.36       tls 					}
   1431          1.36       tls 				}
   1432      1.44.8.1       snj 				cv_destroy(&krp->krp_cv);
   1433          1.36       tls 				pool_put(&cryptkop_pool, krp);
   1434          1.36       tls 			}
   1435          1.36       tls 		}
   1436          1.36       tls 		error = 0;
   1437          1.36       tls 	}
   1438          1.36       tls 	DPRINTF(("cryptodev_key: error=0x%08x\n", error));
   1439          1.42  christos 	return error;
   1440          1.36       tls }
   1441          1.36       tls 
   1442  1.44.8.2.4.1      matt int
   1443      1.44.8.1       snj cryptodev_session(struct fcrypt *fcr, struct session_op *sop)
   1444      1.44.8.1       snj {
   1445          1.36       tls 	struct cryptoini cria, crie;
   1446  1.44.8.2.4.1      matt 	struct cryptoini cric;		/* compressor */
   1447  1.44.8.2.4.1      matt 	struct cryptoini *crihead = NULL;
   1448          1.36       tls 	struct enc_xform *txform = NULL;
   1449          1.36       tls 	struct auth_hash *thash = NULL;
   1450  1.44.8.2.4.1      matt 	struct comp_algo *tcomp = NULL;
   1451          1.36       tls 	struct csession *cse;
   1452          1.36       tls 	u_int64_t sid;
   1453          1.36       tls 	int error = 0;
   1454          1.36       tls 
   1455  1.44.8.2.4.1      matt 	DPRINTF(("cryptodev_session() cipher=%d, mac=%d\n", sop->cipher, sop->mac));
   1456  1.44.8.2.4.1      matt 
   1457          1.36       tls 	/* XXX there must be a way to not embed the list of xforms here */
   1458          1.36       tls 	switch (sop->cipher) {
   1459          1.36       tls 	case 0:
   1460          1.36       tls 		break;
   1461          1.36       tls 	case CRYPTO_DES_CBC:
   1462          1.36       tls 		txform = &enc_xform_des;
   1463          1.36       tls 		break;
   1464          1.36       tls 	case CRYPTO_3DES_CBC:
   1465          1.36       tls 		txform = &enc_xform_3des;
   1466          1.36       tls 		break;
   1467          1.36       tls 	case CRYPTO_BLF_CBC:
   1468          1.36       tls 		txform = &enc_xform_blf;
   1469          1.36       tls 		break;
   1470          1.36       tls 	case CRYPTO_CAST_CBC:
   1471          1.36       tls 		txform = &enc_xform_cast5;
   1472  1.44.8.2.4.1      matt 		break;
   1473          1.36       tls 	case CRYPTO_SKIPJACK_CBC:
   1474          1.36       tls 		txform = &enc_xform_skipjack;
   1475          1.36       tls 		break;
   1476          1.36       tls 	case CRYPTO_AES_CBC:
   1477          1.36       tls 		txform = &enc_xform_rijndael128;
   1478          1.36       tls 		break;
   1479          1.36       tls 	case CRYPTO_NULL_CBC:
   1480          1.36       tls 		txform = &enc_xform_null;
   1481          1.36       tls 		break;
   1482          1.36       tls 	case CRYPTO_ARC4:
   1483          1.36       tls 		txform = &enc_xform_arc4;
   1484          1.36       tls 		break;
   1485          1.36       tls 	default:
   1486          1.36       tls 		DPRINTF(("Invalid cipher %d\n", sop->cipher));
   1487          1.36       tls 		return EINVAL;
   1488          1.36       tls 	}
   1489          1.36       tls 
   1490  1.44.8.2.4.1      matt 	switch (sop->comp_alg) {
   1491  1.44.8.2.4.1      matt 	case 0:
   1492  1.44.8.2.4.1      matt 		break;
   1493  1.44.8.2.4.1      matt 	case CRYPTO_DEFLATE_COMP:
   1494  1.44.8.2.4.1      matt 		tcomp = &comp_algo_deflate;
   1495  1.44.8.2.4.1      matt 		break;
   1496  1.44.8.2.4.1      matt 	case CRYPTO_GZIP_COMP:
   1497  1.44.8.2.4.1      matt 		tcomp = &comp_algo_gzip;
   1498  1.44.8.2.4.1      matt 		DPRINTF(("cryptodev_session() tcomp for GZIP\n"));
   1499  1.44.8.2.4.1      matt 		break;
   1500  1.44.8.2.4.1      matt 	default:
   1501  1.44.8.2.4.1      matt 		DPRINTF(("Invalid compression alg %d\n", sop->comp_alg));
   1502  1.44.8.2.4.1      matt 		return EINVAL;
   1503  1.44.8.2.4.1      matt 	}
   1504  1.44.8.2.4.1      matt 
   1505          1.36       tls 	switch (sop->mac) {
   1506          1.36       tls 	case 0:
   1507          1.36       tls 		break;
   1508          1.36       tls 	case CRYPTO_MD5_HMAC:
   1509          1.36       tls 		thash = &auth_hash_hmac_md5;
   1510          1.36       tls 		break;
   1511          1.36       tls 	case CRYPTO_SHA1_HMAC:
   1512          1.36       tls 		thash = &auth_hash_hmac_sha1;
   1513          1.36       tls 		break;
   1514          1.36       tls 	case CRYPTO_MD5_HMAC_96:
   1515          1.36       tls 		thash = &auth_hash_hmac_md5_96;
   1516          1.36       tls 		break;
   1517          1.36       tls 	case CRYPTO_SHA1_HMAC_96:
   1518          1.36       tls 		thash = &auth_hash_hmac_sha1_96;
   1519          1.36       tls 		break;
   1520          1.36       tls 	case CRYPTO_SHA2_HMAC:
   1521          1.36       tls 		/* XXX switching on key length seems questionable */
   1522          1.36       tls 		if (sop->mackeylen == auth_hash_hmac_sha2_256.keysize) {
   1523          1.36       tls 			thash = &auth_hash_hmac_sha2_256;
   1524          1.36       tls 		} else if (sop->mackeylen == auth_hash_hmac_sha2_384.keysize) {
   1525          1.36       tls 			thash = &auth_hash_hmac_sha2_384;
   1526          1.36       tls 		} else if (sop->mackeylen == auth_hash_hmac_sha2_512.keysize) {
   1527          1.36       tls 			thash = &auth_hash_hmac_sha2_512;
   1528          1.36       tls 		} else {
   1529          1.36       tls 			DPRINTF(("Invalid mackeylen %d\n", sop->mackeylen));
   1530          1.36       tls 			return EINVAL;
   1531          1.36       tls 		}
   1532          1.36       tls 		break;
   1533          1.36       tls 	case CRYPTO_RIPEMD160_HMAC:
   1534          1.36       tls 		thash = &auth_hash_hmac_ripemd_160;
   1535          1.36       tls 		break;
   1536          1.36       tls 	case CRYPTO_RIPEMD160_HMAC_96:
   1537          1.36       tls 		thash = &auth_hash_hmac_ripemd_160_96;
   1538          1.36       tls 		break;
   1539          1.36       tls 	case CRYPTO_MD5:
   1540          1.36       tls 		thash = &auth_hash_md5;
   1541          1.36       tls 		break;
   1542          1.36       tls 	case CRYPTO_SHA1:
   1543          1.36       tls 		thash = &auth_hash_sha1;
   1544          1.36       tls 		break;
   1545          1.36       tls 	case CRYPTO_NULL_HMAC:
   1546          1.36       tls 		thash = &auth_hash_null;
   1547          1.36       tls 		break;
   1548          1.36       tls 	default:
   1549          1.36       tls 		DPRINTF(("Invalid mac %d\n", sop->mac));
   1550          1.42  christos 		return EINVAL;
   1551          1.36       tls 	}
   1552          1.36       tls 
   1553          1.36       tls 	memset(&crie, 0, sizeof(crie));
   1554          1.36       tls 	memset(&cria, 0, sizeof(cria));
   1555  1.44.8.2.4.1      matt 	memset(&cric, 0, sizeof(cric));
   1556  1.44.8.2.4.1      matt 
   1557  1.44.8.2.4.1      matt 	if (tcomp) {
   1558  1.44.8.2.4.1      matt 		cric.cri_alg = tcomp->type;
   1559  1.44.8.2.4.1      matt 		cric.cri_klen = 0;
   1560  1.44.8.2.4.1      matt 		DPRINTF(("tcomp->type = %d\n", tcomp->type));
   1561  1.44.8.2.4.1      matt 
   1562  1.44.8.2.4.1      matt 		crihead = &cric;
   1563  1.44.8.2.4.1      matt 		if (thash) {
   1564  1.44.8.2.4.1      matt 			cric.cri_next = &cria;
   1565  1.44.8.2.4.1      matt 		} else if (txform) {
   1566  1.44.8.2.4.1      matt 			cric.cri_next = &crie;
   1567  1.44.8.2.4.1      matt 		}
   1568  1.44.8.2.4.1      matt 	}
   1569          1.36       tls 
   1570          1.36       tls 	if (txform) {
   1571          1.36       tls 		crie.cri_alg = txform->type;
   1572          1.36       tls 		crie.cri_klen = sop->keylen * 8;
   1573          1.36       tls 		if (sop->keylen > txform->maxkey ||
   1574          1.36       tls 		    sop->keylen < txform->minkey) {
   1575          1.36       tls 			DPRINTF(("keylen %d not in [%d,%d]\n",
   1576          1.42  christos 			    sop->keylen, txform->minkey, txform->maxkey));
   1577          1.42  christos 			error = EINVAL;
   1578          1.36       tls 			goto bail;
   1579          1.36       tls 		}
   1580          1.36       tls 
   1581          1.36       tls 		crie.cri_key = malloc(crie.cri_klen / 8, M_XDATA, M_WAITOK);
   1582          1.42  christos 		if ((error = copyin(sop->key, crie.cri_key, crie.cri_klen / 8)))
   1583          1.36       tls 			goto bail;
   1584  1.44.8.2.4.1      matt 		if (!crihead) {
   1585  1.44.8.2.4.1      matt 			crihead = &crie;
   1586  1.44.8.2.4.1      matt 		}
   1587  1.44.8.2.4.1      matt 	}
   1588          1.36       tls 
   1589          1.36       tls 	if (thash) {
   1590          1.36       tls 		cria.cri_alg = thash->type;
   1591          1.36       tls 		cria.cri_klen = sop->mackeylen * 8;
   1592          1.36       tls 		if (sop->mackeylen != thash->keysize) {
   1593          1.36       tls 			DPRINTF(("mackeylen %d != keysize %d\n",
   1594          1.42  christos 			    sop->mackeylen, thash->keysize));
   1595          1.36       tls 			error = EINVAL;
   1596          1.36       tls 			goto bail;
   1597          1.36       tls 		}
   1598          1.36       tls 		if (cria.cri_klen) {
   1599          1.36       tls 			cria.cri_key = malloc(cria.cri_klen / 8, M_XDATA,
   1600          1.42  christos 			    M_WAITOK);
   1601          1.36       tls 			if ((error = copyin(sop->mackey, cria.cri_key,
   1602          1.42  christos 			    cria.cri_klen / 8))) {
   1603          1.36       tls 				goto bail;
   1604          1.36       tls 			}
   1605          1.36       tls 		}
   1606  1.44.8.2.4.1      matt 		if (txform)
   1607  1.44.8.2.4.1      matt 			cria.cri_next = &crie;	/* XXX forces enc then hash? */
   1608  1.44.8.2.4.1      matt 		if (!crihead) {
   1609  1.44.8.2.4.1      matt 			crihead = &cria;
   1610  1.44.8.2.4.1      matt 		}
   1611          1.36       tls 	}
   1612  1.44.8.2.4.1      matt 
   1613          1.36       tls 	/* crypto_newsession requires that we hold the mutex. */
   1614          1.36       tls 	mutex_spin_enter(&crypto_mtx);
   1615  1.44.8.2.4.1      matt 	error = crypto_newsession(&sid, crihead, crypto_devallowsoft);
   1616          1.36       tls 	if (!error) {
   1617  1.44.8.2.4.1      matt 		DPRINTF(("cyrptodev_session: got session %d\n", (uint32_t)sid));
   1618          1.36       tls 		cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
   1619  1.44.8.2.4.1      matt 		    cria.cri_key, cria.cri_klen, (txform ? sop->cipher : 0), sop->mac,
   1620  1.44.8.2.4.1      matt 		    (tcomp ? sop->comp_alg : 0), txform, thash, tcomp);
   1621          1.36       tls 		if (cse != NULL) {
   1622          1.36       tls 			sop->ses = cse->ses;
   1623          1.36       tls 		} else {
   1624          1.36       tls 			DPRINTF(("csecreate failed\n"));
   1625          1.36       tls 			crypto_freesession(sid);
   1626          1.36       tls 			error = EINVAL;
   1627          1.36       tls 		}
   1628          1.36       tls 	} else {
   1629          1.36       tls 		DPRINTF(("SIOCSESSION violates kernel parameters %d\n",
   1630          1.42  christos 		    error));
   1631          1.36       tls 	}
   1632          1.36       tls 	mutex_spin_exit(&crypto_mtx);
   1633          1.36       tls bail:
   1634          1.36       tls 	if (error) {
   1635          1.36       tls 		if (crie.cri_key) {
   1636          1.36       tls 			memset(crie.cri_key, 0, crie.cri_klen / 8);
   1637          1.36       tls 			free(crie.cri_key, M_XDATA);
   1638          1.36       tls 		}
   1639          1.36       tls 		if (cria.cri_key) {
   1640          1.36       tls 			memset(cria.cri_key, 0, cria.cri_klen / 8);
   1641          1.36       tls 			free(cria.cri_key, M_XDATA);
   1642          1.36       tls 		}
   1643          1.36       tls 	}
   1644          1.36       tls 	return error;
   1645          1.36       tls }
   1646          1.36       tls 
   1647  1.44.8.2.4.1      matt int
   1648          1.36       tls cryptodev_msession(struct fcrypt *fcr, struct session_n_op *sn_ops,
   1649          1.36       tls 		   int count)
   1650          1.36       tls {
   1651          1.36       tls 	int i;
   1652          1.36       tls 
   1653          1.36       tls 	for (i = 0; i < count; i++, sn_ops++) {
   1654          1.36       tls 		struct session_op s_op;
   1655          1.36       tls 		s_op.cipher =		sn_ops->cipher;
   1656          1.36       tls 		s_op.mac =		sn_ops->mac;
   1657          1.36       tls 		s_op.keylen =		sn_ops->keylen;
   1658          1.36       tls 		s_op.key =		sn_ops->key;
   1659          1.36       tls 		s_op.mackeylen =	sn_ops->mackeylen;
   1660          1.36       tls 		s_op.mackey =		sn_ops->mackey;
   1661          1.36       tls 
   1662          1.36       tls 		sn_ops->status = cryptodev_session(fcr, &s_op);
   1663          1.36       tls 		sn_ops->ses =		s_op.ses;
   1664          1.36       tls 	}
   1665          1.36       tls 
   1666          1.36       tls 	return 0;
   1667          1.36       tls }
   1668          1.36       tls 
   1669          1.36       tls static int
   1670          1.36       tls cryptodev_msessionfin(struct fcrypt *fcr, int count, u_int32_t *sesid)
   1671          1.36       tls {
   1672          1.36       tls 	struct csession *cse;
   1673          1.36       tls 	int req, error = 0;
   1674          1.36       tls 
   1675          1.36       tls 	mutex_spin_enter(&crypto_mtx);
   1676          1.36       tls 	for(req = 0; req < count; req++) {
   1677          1.36       tls 		cse = csefind(fcr, sesid[req]);
   1678          1.36       tls 		if (cse == NULL)
   1679          1.36       tls 			continue;
   1680          1.36       tls 		csedelete(fcr, cse);
   1681          1.36       tls 		error = csefree(cse);
   1682          1.36       tls 	}
   1683          1.36       tls 	mutex_spin_exit(&crypto_mtx);
   1684          1.36       tls 	return 0;
   1685          1.36       tls }
   1686          1.36       tls 
   1687          1.36       tls /*
   1688          1.42  christos  * collect as many completed requests as are availble, or count completed
   1689          1.42  christos  * requests whichever is less.
   1690          1.36       tls  * return the number of requests.
   1691          1.36       tls  */
   1692          1.36       tls static int
   1693          1.36       tls cryptodev_getmstatus(struct fcrypt *fcr, struct crypt_result *crypt_res,
   1694          1.42  christos     int count)
   1695          1.36       tls {
   1696          1.36       tls 	struct cryptop *crp = NULL;
   1697          1.36       tls 	struct cryptkop *krp = NULL;
   1698          1.36       tls 	struct csession *cse;
   1699          1.36       tls 	int i, size, req = 0;
   1700          1.36       tls 	int completed=0;
   1701          1.36       tls 
   1702  1.44.8.2.4.1      matt 	/* On queue so nobody else can grab them
   1703  1.44.8.2.4.1      matt 	 * and copyout can be delayed-- no locking */
   1704  1.44.8.2.4.1      matt 	TAILQ_HEAD(, cryptop) crp_delfree_q =
   1705  1.44.8.2.4.1      matt 		TAILQ_HEAD_INITIALIZER(crp_delfree_q);
   1706  1.44.8.2.4.1      matt 	TAILQ_HEAD(, cryptkop) krp_delfree_q =
   1707  1.44.8.2.4.1      matt 		TAILQ_HEAD_INITIALIZER(krp_delfree_q);
   1708          1.36       tls 
   1709          1.36       tls 	/* at this point we do not know which response user is requesting for
   1710          1.36       tls 	 * (symmetric or asymmetric) so we copyout one from each i.e if the
   1711          1.36       tls 	 * count is 2 then 1 from symmetric and 1 from asymmetric queue and
   1712          1.36       tls 	 * if 3 then 2 symmetric and 1 asymmetric and so on */
   1713  1.44.8.2.4.1      matt 
   1714  1.44.8.2.4.1      matt 	/* pull off a list of requests while protected from changes */
   1715  1.44.8.2.4.1      matt 	mutex_spin_enter(&crypto_mtx);
   1716  1.44.8.2.4.1      matt 	while (req < count) {
   1717          1.36       tls 		crp = TAILQ_FIRST(&fcr->crp_ret_mq);
   1718  1.44.8.2.4.1      matt 		if (crp) {
   1719  1.44.8.2.4.1      matt 			TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next);
   1720  1.44.8.2.4.1      matt 			TAILQ_INSERT_TAIL(&crp_delfree_q, crp, crp_next);
   1721          1.36       tls 			cse = (struct csession *)crp->crp_opaque;
   1722  1.44.8.2.4.1      matt 
   1723  1.44.8.2.4.1      matt 			/* see if the session is still valid */
   1724          1.36       tls 			cse = csefind(fcr, cse->ses);
   1725  1.44.8.2.4.1      matt 			if (cse != NULL) {
   1726  1.44.8.2.4.1      matt 				crypt_res[req].status = 0;
   1727  1.44.8.2.4.1      matt 			} else {
   1728          1.36       tls 				DPRINTF(("csefind failed\n"));
   1729          1.36       tls 				crypt_res[req].status = EINVAL;
   1730  1.44.8.2.4.1      matt 			}
   1731  1.44.8.2.4.1      matt 			req++;
   1732  1.44.8.2.4.1      matt 		}
   1733  1.44.8.2.4.1      matt 		if(req < count) {
   1734  1.44.8.2.4.1      matt 			crypt_res[req].status = 0;
   1735  1.44.8.2.4.1      matt 			krp = TAILQ_FIRST(&fcr->crp_ret_mkq);
   1736  1.44.8.2.4.1      matt 			if (krp) {
   1737  1.44.8.2.4.1      matt 				TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next);
   1738  1.44.8.2.4.1      matt 				TAILQ_INSERT_TAIL(&krp_delfree_q, krp, krp_next);
   1739  1.44.8.2.4.1      matt 			req++;
   1740  1.44.8.2.4.1      matt 			}
   1741  1.44.8.2.4.1      matt 		}
   1742  1.44.8.2.4.1      matt 	}
   1743  1.44.8.2.4.1      matt 	mutex_spin_exit(&crypto_mtx);
   1744  1.44.8.2.4.1      matt 
   1745  1.44.8.2.4.1      matt 	/* now do all the work outside the mutex */
   1746  1.44.8.2.4.1      matt 	for(req=0; req < count ;) {
   1747  1.44.8.2.4.1      matt 		crp = TAILQ_FIRST(&crp_delfree_q);
   1748  1.44.8.2.4.1      matt 		if (crp) {
   1749  1.44.8.2.4.1      matt 			if (crypt_res[req].status != 0) {
   1750  1.44.8.2.4.1      matt 				/* csefind failed during collection */
   1751          1.36       tls 				goto bail;
   1752          1.36       tls 			}
   1753  1.44.8.2.4.1      matt 			cse = (struct csession *)crp->crp_opaque;
   1754  1.44.8.2.4.1      matt 			crypt_res[req].reqid = crp->crp_reqid;
   1755  1.44.8.2.4.1      matt 			crypt_res[req].opaque = crp->crp_usropaque;
   1756  1.44.8.2.4.1      matt 			completed++;
   1757          1.36       tls 
   1758          1.36       tls 			if (crp->crp_etype != 0) {
   1759          1.36       tls 				crypt_res[req].status = crp->crp_etype;
   1760          1.36       tls 				goto bail;
   1761          1.36       tls 			}
   1762          1.36       tls 
   1763          1.36       tls 			if (cse->error) {
   1764          1.36       tls 				crypt_res[req].status = cse->error;
   1765          1.36       tls 				goto bail;
   1766          1.36       tls 			}
   1767          1.36       tls 
   1768          1.42  christos 			if (crp->dst && (crypt_res[req].status =
   1769          1.42  christos 			    copyout(crp->uio.uio_iov[0].iov_base, crp->dst,
   1770          1.42  christos 			    crp->len)))
   1771          1.36       tls 				goto bail;
   1772          1.36       tls 
   1773          1.42  christos 			if (crp->mac && (crypt_res[req].status =
   1774          1.42  christos 			    copyout(crp->crp_mac, crp->mac,
   1775          1.42  christos 			    cse->thash->authsize)))
   1776          1.36       tls 				goto bail;
   1777  1.44.8.2.4.1      matt 
   1778          1.36       tls bail:
   1779  1.44.8.2.4.1      matt 			TAILQ_REMOVE(&crp_delfree_q, crp, crp_next);
   1780  1.44.8.2.4.1      matt 			kmem_free(crp->uio.uio_iov[0].iov_base,
   1781  1.44.8.2.4.1      matt 			    crp->uio.uio_iov[0].iov_len);
   1782  1.44.8.2.4.1      matt 			crypto_freereq(crp);
   1783          1.36       tls 			req++;
   1784          1.36       tls 		}
   1785          1.36       tls 
   1786  1.44.8.2.4.1      matt 		if (req < count) {
   1787  1.44.8.2.4.1      matt 			krp = TAILQ_FIRST(&krp_delfree_q);
   1788          1.36       tls 			if (krp) {
   1789          1.36       tls 				crypt_res[req].reqid = krp->krp_reqid;
   1790          1.36       tls 				crypt_res[req].opaque = krp->krp_usropaque;
   1791          1.36       tls 				completed++;
   1792          1.36       tls 				if (krp->krp_status != 0) {
   1793          1.36       tls 					DPRINTF(("cryptodev_key: "
   1794          1.42  christos 					    "krp->krp_status 0x%08x\n",
   1795          1.42  christos 					    krp->krp_status));
   1796          1.42  christos 					crypt_res[req].status = krp->krp_status;
   1797          1.36       tls 					goto fail;
   1798          1.36       tls 				}
   1799          1.36       tls 
   1800          1.36       tls 				for (i = krp->krp_iparams; i < krp->krp_iparams
   1801          1.42  christos 				    + krp->krp_oparams; i++) {
   1802          1.36       tls 					size = (krp->krp_param[i].crp_nbits
   1803          1.42  christos 					    + 7) / 8;
   1804          1.36       tls 					if (size == 0)
   1805          1.36       tls 						continue;
   1806          1.36       tls 					crypt_res[req].status = copyout
   1807          1.36       tls 					    (krp->krp_param[i].crp_p,
   1808          1.36       tls 					    krp->crk_param[i].crp_p, size);
   1809          1.36       tls 					if (crypt_res[req].status) {
   1810          1.36       tls 						DPRINTF(("cryptodev_key: "
   1811          1.42  christos 						    "copyout oparam %d failed, "
   1812          1.42  christos 						    "error=%d\n",
   1813          1.42  christos 						    i - krp->krp_iparams,
   1814          1.42  christos 						    crypt_res[req].status));
   1815          1.36       tls 						goto fail;
   1816          1.36       tls 					}
   1817          1.36       tls 				}
   1818          1.36       tls fail:
   1819  1.44.8.2.4.1      matt 				TAILQ_REMOVE(&krp_delfree_q, krp, krp_next);
   1820          1.36       tls 				/* not sure what to do for this */
   1821          1.36       tls 				/* kop[req].crk_status = krp->krp_status; */
   1822  1.44.8.2.4.1      matt 				for (i = 0; i < CRK_MAXPARAM; i++) {
   1823  1.44.8.2.4.1      matt 					struct crparam *kp = &(krp->krp_param[i]);
   1824  1.44.8.2.4.1      matt 					if (kp->crp_p) {
   1825  1.44.8.2.4.1      matt 						size = (kp->crp_nbits + 7) / 8;
   1826  1.44.8.2.4.1      matt 						KASSERT(size > 0);
   1827  1.44.8.2.4.1      matt 						(void)memset(kp->crp_p, 0, size);
   1828  1.44.8.2.4.1      matt 						kmem_free(kp->crp_p, size);
   1829  1.44.8.2.4.1      matt 					}
   1830  1.44.8.2.4.1      matt 				}
   1831  1.44.8.2.4.1      matt 				cv_destroy(&krp->krp_cv);
   1832  1.44.8.2.4.1      matt 				pool_put(&cryptkop_pool, krp);
   1833  1.44.8.2.4.1      matt 				req++;
   1834          1.36       tls 			}
   1835          1.36       tls 		}
   1836          1.36       tls 	}
   1837          1.36       tls 
   1838          1.36       tls 	return completed;
   1839          1.36       tls }
   1840          1.36       tls 
   1841          1.36       tls static int
   1842          1.36       tls cryptodev_getstatus (struct fcrypt *fcr, struct crypt_result *crypt_res)
   1843          1.36       tls {
   1844      1.44.8.1       snj         struct cryptop *crp = NULL, *cnext;
   1845      1.44.8.1       snj         struct cryptkop *krp = NULL, *knext;
   1846          1.36       tls         struct csession *cse;
   1847          1.36       tls         int i, size, req = 0;
   1848          1.36       tls 
   1849          1.36       tls 	mutex_spin_enter(&crypto_mtx);
   1850          1.36       tls 	/* Here we dont know for which request the user is requesting the
   1851          1.36       tls 	 * response so checking in both the queues */
   1852      1.44.8.1       snj 	TAILQ_FOREACH_SAFE(crp, &fcr->crp_ret_mq, crp_next, cnext) {
   1853          1.36       tls 		if(crp && (crp->crp_reqid == crypt_res->reqid)) {
   1854          1.36       tls 			cse = (struct csession *)crp->crp_opaque;
   1855          1.36       tls 		        crypt_res->opaque = crp->crp_usropaque;
   1856          1.36       tls 			cse = csefind(fcr, cse->ses);
   1857          1.36       tls 			if (cse == NULL) {
   1858          1.36       tls 				DPRINTF(("csefind failed\n"));
   1859          1.36       tls 				crypt_res->status = EINVAL;
   1860          1.36       tls 				goto bail;
   1861          1.36       tls 			}
   1862          1.36       tls 
   1863          1.36       tls 			if (crp->crp_etype != 0) {
   1864          1.36       tls 				crypt_res->status = crp->crp_etype;
   1865          1.36       tls 				goto bail;
   1866          1.36       tls 			}
   1867          1.36       tls 
   1868          1.36       tls 			if (cse->error) {
   1869          1.36       tls 				crypt_res->status = cse->error;
   1870          1.36       tls 				goto bail;
   1871          1.36       tls 			}
   1872          1.36       tls 
   1873          1.42  christos 			if (crp->dst && (crypt_res->status =
   1874          1.42  christos 			    copyout(crp->uio.uio_iov[0].iov_base,
   1875          1.42  christos 			    crp->dst, crp->len)))
   1876          1.36       tls 				goto bail;
   1877          1.36       tls 
   1878          1.42  christos 			if (crp->mac && (crypt_res->status =
   1879          1.42  christos 			    copyout(crp->crp_mac, crp->mac,
   1880          1.42  christos 			    cse->thash->authsize)))
   1881          1.36       tls 				goto bail;
   1882          1.36       tls bail:
   1883          1.36       tls 			TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next);
   1884          1.36       tls 
   1885          1.36       tls 			mutex_spin_exit(&crypto_mtx);
   1886          1.36       tls 			crypto_freereq(crp);
   1887          1.36       tls 			return 0;
   1888          1.36       tls 		}
   1889          1.36       tls 	}
   1890          1.36       tls 
   1891      1.44.8.1       snj 	TAILQ_FOREACH_SAFE(krp, &fcr->crp_ret_mkq, krp_next, knext) {
   1892          1.36       tls 		if(krp && (krp->krp_reqid == crypt_res->reqid)) {
   1893          1.36       tls 			crypt_res[req].opaque = krp->krp_usropaque;
   1894          1.36       tls 			if (krp->krp_status != 0) {
   1895          1.36       tls 				DPRINTF(("cryptodev_key: "
   1896          1.42  christos 				    "krp->krp_status 0x%08x\n",
   1897          1.42  christos 				    krp->krp_status));
   1898          1.36       tls 				crypt_res[req].status = krp->krp_status;
   1899          1.36       tls 				goto fail;
   1900          1.36       tls 			}
   1901          1.36       tls 
   1902          1.42  christos 			for (i = krp->krp_iparams; i < krp->krp_iparams +
   1903          1.42  christos 			    krp->krp_oparams; i++) {
   1904          1.36       tls 				size = (krp->krp_param[i].crp_nbits + 7) / 8;
   1905          1.36       tls 				if (size == 0)
   1906          1.36       tls 					continue;
   1907          1.42  christos 				crypt_res[req].status = copyout(
   1908          1.42  christos 				    krp->krp_param[i].crp_p,
   1909          1.42  christos 				    krp->crk_param[i].crp_p, size);
   1910          1.36       tls 				if (crypt_res[req].status) {
   1911          1.36       tls 					DPRINTF(("cryptodev_key: copyout oparam"
   1912          1.42  christos 					    "%d failed, error=%d\n",
   1913          1.42  christos 					    i - krp->krp_iparams,
   1914          1.42  christos 					    crypt_res[req].status));
   1915          1.36       tls 					goto fail;
   1916          1.36       tls 				}
   1917          1.36       tls 			}
   1918          1.36       tls fail:
   1919          1.36       tls 			TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next);
   1920          1.36       tls 			mutex_spin_exit(&crypto_mtx);
   1921          1.36       tls 			/* not sure what to do for this */
   1922          1.36       tls 			/* kop[req].crk_status = krp->krp_status; */
   1923          1.36       tls 			for (i = 0; i < CRK_MAXPARAM; i++) {
   1924          1.36       tls 				struct crparam *kp = &(krp->krp_param[i]);
   1925          1.36       tls 				if (kp->crp_p) {
   1926          1.36       tls 					size = (kp->crp_nbits + 7) / 8;
   1927          1.36       tls 					KASSERT(size > 0);
   1928          1.36       tls 					memset(kp->crp_p, 0, size);
   1929          1.36       tls 					kmem_free(kp->crp_p, size);
   1930          1.36       tls 				}
   1931          1.36       tls 			}
   1932      1.44.8.1       snj 			cv_destroy(&krp->krp_cv);
   1933          1.36       tls 			pool_put(&cryptkop_pool, krp);
   1934          1.36       tls 			return 0;
   1935          1.36       tls 		}
   1936          1.36       tls 	}
   1937          1.36       tls 	mutex_spin_exit(&crypto_mtx);
   1938          1.36       tls 	return EINPROGRESS;
   1939          1.36       tls }
   1940          1.36       tls 
   1941          1.36       tls static int
   1942          1.36       tls cryptof_poll(struct file *fp, int events)
   1943          1.36       tls {
   1944          1.36       tls 	struct fcrypt *fcr = (struct fcrypt *)fp->f_data;
   1945          1.38     rmind 	int revents = 0;
   1946          1.36       tls 
   1947          1.36       tls 	if (!(events & (POLLIN | POLLRDNORM))) {
   1948          1.36       tls 		/* only support read and POLLIN */
   1949          1.36       tls 		return 0;
   1950          1.36       tls 	}
   1951          1.36       tls 
   1952          1.38     rmind 	mutex_spin_enter(&crypto_mtx);
   1953          1.36       tls 	if (TAILQ_EMPTY(&fcr->crp_ret_mq) && TAILQ_EMPTY(&fcr->crp_ret_mkq)) {
   1954          1.38     rmind 		/* no completed requests pending, save the poll for later */
   1955          1.36       tls 		selrecord(curlwp, &fcr->sinfo);
   1956          1.36       tls 	} else {
   1957          1.36       tls 		/* let the app(s) know that there are completed requests */
   1958          1.38     rmind 		revents = events & (POLLIN | POLLRDNORM);
   1959          1.36       tls 	}
   1960          1.38     rmind 	mutex_spin_exit(&crypto_mtx);
   1961          1.38     rmind 
   1962          1.38     rmind 	return revents;
   1963          1.36       tls }
   1964          1.36       tls 
   1965          1.15   thorpej /*
   1966          1.15   thorpej  * Pseudo-device initialization routine for /dev/crypto
   1967          1.15   thorpej  */
   1968          1.15   thorpej void	cryptoattach(int);
   1969          1.15   thorpej 
   1970          1.15   thorpej void
   1971          1.25  christos cryptoattach(int num)
   1972          1.15   thorpej {
   1973          1.29       tls 	pool_init(&fcrpl, sizeof(struct fcrypt), 0, 0, 0, "fcrpl",
   1974          1.42  christos 	    NULL, IPL_NET);	/* XXX IPL_NET ("splcrypto") */
   1975          1.29       tls 	pool_init(&csepl, sizeof(struct csession), 0, 0, 0, "csepl",
   1976          1.42  christos 	    NULL, IPL_NET);	/* XXX IPL_NET ("splcrypto") */
   1977          1.29       tls 
   1978          1.29       tls 	/*
   1979          1.29       tls 	 * Preallocate space for 64 users, with 5 sessions each.
   1980          1.29       tls 	 * (consider that a TLS protocol session requires at least
   1981          1.29       tls 	 * 3DES, MD5, and SHA1 (both hashes are used in the PRF) for
   1982          1.29       tls 	 * the negotiation, plus HMAC_SHA1 for the actual SSL records,
   1983          1.29       tls 	 * consuming one session here for each algorithm.
   1984          1.29       tls 	 */
   1985          1.29       tls 	pool_prime(&fcrpl, 64);
   1986          1.29       tls 	pool_prime(&csepl, 64 * 5);
   1987          1.15   thorpej }
   1988