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