xref: /netbsd-src/sys/opencrypto/cryptodev.c (revision cac8e449158efc7261bebc8657cbb0125a2cfdde)
1 /*	$NetBSD: cryptodev.c,v 1.44 2008/05/24 16:42:00 christos 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.44 2008/05/24 16:42:00 christos 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 *,
158     u_int64_t, 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 *,
163     struct lwp *);
164 static int	cryptodev_mop(struct fcrypt *, struct crypt_n_op *, int,
165     struct lwp *);
166 static int	cryptodev_key(struct crypt_kop *);
167 static int	cryptodev_mkey(struct fcrypt *, struct crypt_n_kop *, int);
168 static int	cryptodev_session(struct fcrypt *, struct session_op *);
169 static int	cryptodev_msession(struct fcrypt *, struct session_n_op *, 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, curlwp);
318 			if (!error) {
319 				error = copyout(cnop, mop->reqs,
320 				    (mop->count * sizeof(struct crypt_n_op)));
321 			}
322 		}
323 		kmem_free(cnop, (mop->count * sizeof(struct crypt_n_op)));
324 		break;
325 	case CIOCKEY:
326 		error = cryptodev_key((struct crypt_kop *)data);
327 		DPRINTF(("cryptodev_key error = %d\n", error));
328 		break;
329 	case CIOCNFKEYM:
330 		mkop = (struct crypt_mkop *)data;
331 		knop = kmem_alloc((mkop->count * sizeof(struct crypt_n_kop)),
332 		    KM_SLEEP);
333 		error = copyin(mkop->reqs, knop,
334 		    (mkop->count * sizeof(struct crypt_n_kop)));
335 		if (!error) {
336 			error = cryptodev_mkey(fcr, knop, mkop->count);
337 			if (!error)
338 				error = copyout(knop, mkop->reqs,
339 				    (mkop->count * sizeof(struct crypt_n_kop)));
340 		}
341 		kmem_free(knop, (mkop->count * sizeof(struct crypt_n_kop)));
342 		break;
343 	case CIOCASYMFEAT:
344 		error = crypto_getfeat((int *)data);
345 		break;
346 	case CIOCNCRYPTRETM:
347 		crypt_ret = (struct cryptret *)data;
348 		count = crypt_ret->count;
349 		crypt_res = kmem_alloc((count * sizeof(struct crypt_result)),
350 		    KM_SLEEP);
351 		error = copyin(crypt_ret->results, crypt_res,
352 		    (count * sizeof(struct crypt_result)));
353 		if (error)
354 			goto reterr;
355 		crypt_ret->count = cryptodev_getmstatus(fcr, crypt_res,
356 		    crypt_ret->count);
357 		/* sanity check count */
358 		if (crypt_ret->count > count) {
359 			printf("%s.%d: error returned count %zd > original "
360 			    " count %zd\n",
361 			    __FILE__, __LINE__, crypt_ret->count, count);
362 			crypt_ret->count = count;
363 
364 		}
365 		error = copyout(crypt_res, crypt_ret->results,
366 		    (crypt_ret->count * sizeof(struct crypt_result)));
367 reterr:
368 		kmem_free(crypt_res, (count * sizeof(struct crypt_result)));
369 		break;
370 	case CIOCNCRYPTRET:
371 		error = cryptodev_getstatus(fcr, (struct crypt_result *)data);
372 		break;
373 	default:
374 		DPRINTF(("invalid ioctl cmd %ld\n", cmd));
375 		error = EINVAL;
376 	}
377 	return error;
378 }
379 
380 static int
381 cryptodev_op(struct csession *cse, struct crypt_op *cop, struct lwp *l)
382 {
383 	struct cryptop *crp = NULL;
384 	struct cryptodesc *crde = NULL, *crda = NULL;
385 	int error;
386 
387 	if (cop->len > 256*1024-4)
388 		return E2BIG;
389 
390 	if (cse->txform) {
391 		if (cop->len == 0 || (cop->len % cse->txform->blocksize) != 0)
392 			return EINVAL;
393 	}
394 
395 	(void)memset(&cse->uio, 0, sizeof(cse->uio));
396 	cse->uio.uio_iovcnt = 1;
397 	cse->uio.uio_resid = 0;
398 	cse->uio.uio_rw = UIO_WRITE;
399 	cse->uio.uio_iov = cse->iovec;
400 	UIO_SETUP_SYSSPACE(&cse->uio);
401 	memset(&cse->iovec, 0, sizeof(cse->iovec));
402 	cse->uio.uio_iov[0].iov_len = cop->len;
403 	cse->uio.uio_iov[0].iov_base = kmem_alloc(cop->len, KM_SLEEP);
404 	cse->uio.uio_resid = cse->uio.uio_iov[0].iov_len;
405 
406 	crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL));
407 	if (crp == NULL) {
408 		error = ENOMEM;
409 		goto bail;
410 	}
411 
412 	if (cse->thash) {
413 		crda = crp->crp_desc;
414 		if (cse->txform && crda)
415 			crde = crda->crd_next;
416 	} else {
417 		if (cse->txform)
418 			crde = crp->crp_desc;
419 		else {
420 			error = EINVAL;
421 			goto bail;
422 		}
423 	}
424 
425 	if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len)))
426 	{
427 		printf("copyin failed %s %d \n", (char *)cop->src, error);
428 		goto bail;
429 	}
430 
431 	if (crda) {
432 		crda->crd_skip = 0;
433 		crda->crd_len = cop->len;
434 		crda->crd_inject = 0;	/* ??? */
435 
436 		crda->crd_alg = cse->mac;
437 		crda->crd_key = cse->mackey;
438 		crda->crd_klen = cse->mackeylen * 8;
439 	}
440 
441 	if (crde) {
442 		if (cop->op == COP_ENCRYPT)
443 			crde->crd_flags |= CRD_F_ENCRYPT;
444 		else
445 			crde->crd_flags &= ~CRD_F_ENCRYPT;
446 		crde->crd_len = cop->len;
447 		crde->crd_inject = 0;
448 
449 		crde->crd_alg = cse->cipher;
450 		crde->crd_key = cse->key;
451 		crde->crd_klen = cse->keylen * 8;
452 	}
453 
454 	crp->crp_ilen = cop->len;
455 	crp->crp_flags = CRYPTO_F_IOV | (cop->flags & COP_F_BATCH);
456 	crp->crp_buf = (void *)&cse->uio;
457 	crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
458 	crp->crp_sid = cse->sid;
459 	crp->crp_opaque = (void *)cse;
460 
461 	if (cop->iv) {
462 		if (crde == NULL) {
463 			error = EINVAL;
464 			goto bail;
465 		}
466 		if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
467 			error = EINVAL;
468 			goto bail;
469 		}
470 		if ((error = copyin(cop->iv, cse->tmp_iv,
471 		    cse->txform->blocksize)))
472 			goto bail;
473 		(void)memcpy(crde->crd_iv, cse->tmp_iv, cse->txform->blocksize);
474 		crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
475 		crde->crd_skip = 0;
476 	} else if (crde) {
477 		if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
478 			crde->crd_skip = 0;
479 		} else {
480 			crde->crd_flags |= CRD_F_IV_PRESENT;
481 			crde->crd_skip = cse->txform->blocksize;
482 			crde->crd_len -= cse->txform->blocksize;
483 		}
484 	}
485 
486 	if (cop->mac) {
487 		if (crda == NULL) {
488 			error = EINVAL;
489 			goto bail;
490 		}
491 		crp->crp_mac=cse->tmp_mac;
492 	}
493 
494 	/*
495 	 * XXX there was a comment here which said that we went to
496 	 * XXX splcrypto() but needed to only if CRYPTO_F_CBIMM,
497 	 * XXX disabled on NetBSD since 1.6O due to a race condition.
498 	 * XXX But crypto_dispatch went to splcrypto() itself!  (And
499 	 * XXX now takes the crypto_mtx mutex itself).  We do, however,
500 	 * XXX need to hold the mutex across the call to cv_wait().
501 	 * XXX     (should we arrange for crypto_dispatch to return to
502 	 * XXX      us with it held?  it seems quite ugly to do so.)
503 	 */
504 #ifdef notyet
505 eagain:
506 #endif
507 	error = crypto_dispatch(crp);
508 	mutex_spin_enter(&crypto_mtx);
509 
510 	switch (error) {
511 #ifdef notyet	/* don't loop forever -- but EAGAIN not possible here yet */
512 	case EAGAIN:
513 		mutex_spin_exit(&crypto_mtx);
514 		goto eagain;
515 		break;
516 #endif
517 	case 0:
518 		break;
519 	default:
520 		DPRINTF(("cryptodev_op: not waiting, error.\n"));
521 		mutex_spin_exit(&crypto_mtx);
522 		goto bail;
523 	}
524 
525 	while (!(crp->crp_flags & CRYPTO_F_DONE)) {
526 		DPRINTF(("cryptodev_op: sleeping on cv %08x for crp %08x\n", \
527 		    (uint32_t)&crp->crp_cv, (uint32_t)crp));
528 		cv_wait(&crp->crp_cv, &crypto_mtx);	/* XXX cv_wait_sig? */
529 	}
530 	if (crp->crp_flags & CRYPTO_F_ONRETQ) {
531 		DPRINTF(("cryptodev_op: DONE, not woken by cryptoret.\n"));
532 		(void)crypto_ret_q_remove(crp);
533 	}
534 	mutex_spin_exit(&crypto_mtx);
535 
536 	if (crp->crp_etype != 0) {
537 		DPRINTF(("cryptodev_op: crp_etype %d\n", crp->crp_etype));
538 		error = crp->crp_etype;
539 		goto bail;
540 	}
541 
542 	if (cse->error) {
543 		DPRINTF(("cryptodev_op: cse->error %d\n", cse->error));
544 		error = cse->error;
545 		goto bail;
546 	}
547 
548 	if (cop->dst &&
549 	    (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, cop->len)))
550 	{
551 		DPRINTF(("cryptodev_op: copyout error %d\n", error));
552 		goto bail;
553 	}
554 
555 	if (cop->mac &&
556 	    (error = copyout(crp->crp_mac, cop->mac, cse->thash->authsize))) {
557 		DPRINTF(("cryptodev_op: mac copyout error %d\n", error));
558 		goto bail;
559 	}
560 
561 bail:
562 	if (crp)
563 		crypto_freereq(crp);
564 	if (cse->uio.uio_iov[0].iov_base)
565 		kmem_free(cse->uio.uio_iov[0].iov_base,
566 		    cse->uio.uio_iov[0].iov_len);
567 
568 	return error;
569 }
570 
571 static int
572 cryptodev_cb(void *op)
573 {
574 	struct cryptop *crp = (struct cryptop *) op;
575 	struct csession *cse = (struct csession *)crp->crp_opaque;
576 	int error = 0;
577 
578 	mutex_spin_enter(&crypto_mtx);
579 	cse->error = crp->crp_etype;
580 	if (crp->crp_etype == EAGAIN) {
581 		/* always drop mutex to call dispatch routine */
582 		mutex_spin_exit(&crypto_mtx);
583 		error = crypto_dispatch(crp);
584 		mutex_spin_enter(&crypto_mtx);
585 	}
586 	if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) {
587 		cv_signal(&crp->crp_cv);
588 	}
589 	mutex_spin_exit(&crypto_mtx);
590 	return 0;
591 }
592 
593 static int
594 cryptodev_mcb(void *op)
595 {
596 	struct cryptop *crp = (struct cryptop *) op;
597 	struct csession *cse = (struct csession *)crp->crp_opaque;
598 	int  error=0;
599 
600 	mutex_spin_enter(&crypto_mtx);
601 	cse->error = crp->crp_etype;
602 	if (crp->crp_etype == EAGAIN) {
603 		mutex_spin_exit(&crypto_mtx);
604 		error = crypto_dispatch(crp);
605 		mutex_spin_enter(&crypto_mtx);
606 	}
607 	if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) {
608 		cv_signal(&crp->crp_cv);
609 	}
610 
611 	TAILQ_INSERT_TAIL(&crp->fcrp->crp_ret_mq, crp, crp_next);
612 	selnotify(&crp->fcrp->sinfo, 0, 0);
613 	mutex_spin_exit(&crypto_mtx);
614 	return 0;
615 }
616 
617 static int
618 cryptodevkey_cb(void *op)
619 {
620 	struct cryptkop *krp = op;
621 
622 	mutex_spin_enter(&crypto_mtx);
623 	cv_signal(&krp->krp_cv);
624 	mutex_spin_exit(&crypto_mtx);
625 	return 0;
626 }
627 
628 static int
629 cryptodevkey_mcb(void *op)
630 {
631 	struct cryptkop *krp = op;
632 
633 	mutex_spin_enter(&crypto_mtx);
634 	cv_signal(&krp->krp_cv);
635 	TAILQ_INSERT_TAIL(&krp->fcrp->crp_ret_mkq, krp, krp_next);
636 	selnotify(&krp->fcrp->sinfo, 0, 0);
637 	mutex_spin_exit(&crypto_mtx);
638 	return 0;
639 }
640 
641 static int
642 cryptodev_key(struct crypt_kop *kop)
643 {
644 	struct cryptkop *krp = NULL;
645 	int error = EINVAL;
646 	int in, out, size, i;
647 
648 	if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM)
649 		return EFBIG;
650 
651 	in = kop->crk_iparams;
652 	out = kop->crk_oparams;
653 	switch (kop->crk_op) {
654 	case CRK_MOD_EXP:
655 		if (in == 3 && out == 1)
656 			break;
657 		return EINVAL;
658 	case CRK_MOD_EXP_CRT:
659 		if (in == 6 && out == 1)
660 			break;
661 		return EINVAL;
662 	case CRK_DSA_SIGN:
663 		if (in == 5 && out == 2)
664 			break;
665 		return EINVAL;
666 	case CRK_DSA_VERIFY:
667 		if (in == 7 && out == 0)
668 			break;
669 		return EINVAL;
670 	case CRK_DH_COMPUTE_KEY:
671 		if (in == 3 && out == 1)
672 			break;
673 		return EINVAL;
674 	case CRK_MOD_ADD:
675 		if (in == 3 && out == 1)
676 			break;
677 		return EINVAL;
678 	case CRK_MOD_ADDINV:
679 		if (in == 2 && out == 1)
680 			break;
681 		return EINVAL;
682 	case CRK_MOD_SUB:
683 		if (in == 3 && out == 1)
684 			break;
685 		return EINVAL;
686 	case CRK_MOD_MULT:
687 		if (in == 3 && out == 1)
688 			break;
689 		return EINVAL;
690 	case CRK_MOD_MULTINV:
691 		if (in == 2 && out == 1)
692 			break;
693 		return EINVAL;
694 	case CRK_MOD:
695 		if (in == 2 && out == 1)
696 			break;
697 		return EINVAL;
698 	default:
699 		return EINVAL;
700 	}
701 
702 	krp = pool_get(&cryptkop_pool, PR_WAITOK);
703 	(void)memset(krp, 0, sizeof *krp);
704 	cv_init(&krp->krp_cv, "crykdev");
705 	krp->krp_op = kop->crk_op;
706 	krp->krp_status = kop->crk_status;
707 	krp->krp_iparams = kop->crk_iparams;
708 	krp->krp_oparams = kop->crk_oparams;
709 	krp->krp_status = 0;
710 	krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
711 
712 	for (i = 0; i < CRK_MAXPARAM; i++)
713 		krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
714 	for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
715 		size = (krp->krp_param[i].crp_nbits + 7) / 8;
716 		if (size == 0)
717 			continue;
718 		krp->krp_param[i].crp_p = kmem_alloc(size, KM_SLEEP);
719 		if (i >= krp->krp_iparams)
720 			continue;
721 		error = copyin(kop->crk_param[i].crp_p,
722 		    krp->krp_param[i].crp_p, size);
723 		if (error)
724 			goto fail;
725 	}
726 
727 	error = crypto_kdispatch(krp);
728 	if (error != 0) {
729 		goto fail;
730 	}
731 
732 	mutex_spin_enter(&crypto_mtx);
733 	while (!(krp->krp_flags & CRYPTO_F_DONE)) {
734 		cv_wait(&krp->krp_cv, &crypto_mtx);	/* XXX cv_wait_sig? */
735 	}
736 	if (krp->krp_flags & CRYPTO_F_ONRETQ) {
737 		DPRINTF(("cryptodev_key: DONE early, not via cryptoret.\n"));
738 		(void)crypto_ret_kq_remove(krp);
739 	}
740 	mutex_spin_exit(&crypto_mtx);
741 
742 	if (krp->krp_status != 0) {
743 		DPRINTF(("cryptodev_key: krp->krp_status 0x%08x\n",
744 		    krp->krp_status));
745 		error = krp->krp_status;
746 		goto fail;
747 	}
748 
749 	for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams;
750 	    i++) {
751 		size = (krp->krp_param[i].crp_nbits + 7) / 8;
752 		if (size == 0)
753 			continue;
754 		error = copyout(krp->krp_param[i].crp_p,
755 		    kop->crk_param[i].crp_p, size);
756 		if (error) {
757 			DPRINTF(("cryptodev_key: copyout oparam %d failed, "
758 			    "error=%d\n", i-krp->krp_iparams, error));
759 			goto fail;
760 		}
761 	}
762 
763 fail:
764 	kop->crk_status = krp->krp_status;
765 	for (i = 0; i < CRK_MAXPARAM; i++) {
766 		struct crparam *kp = &(krp->krp_param[i]);
767 		if (krp->krp_param[i].crp_p) {
768 			size = (kp->crp_nbits + 7)  / 8;
769 			KASSERT(size > 0);
770 			(void)memset(kp->crp_p, 0, size);
771 			kmem_free(kp->crp_p, size);
772 		}
773 	}
774 	pool_put(&cryptkop_pool, krp);
775 	DPRINTF(("cryptodev_key: error=0x%08x\n", error));
776 	return error;
777 }
778 
779 /* ARGSUSED */
780 static int
781 cryptof_close(struct file *fp)
782 {
783 	struct fcrypt *fcr = fp->f_data;
784 	struct csession *cse;
785 
786 	mutex_spin_enter(&crypto_mtx);
787 	while ((cse = TAILQ_FIRST(&fcr->csessions))) {
788 		TAILQ_REMOVE(&fcr->csessions, cse, next);
789 		(void)csefree(cse);
790 	}
791 	seldestroy(&fcr->sinfo);
792 	fp->f_data = NULL;
793 	mutex_spin_exit(&crypto_mtx);
794 
795 	pool_put(&fcrpl, fcr);
796 	return 0;
797 }
798 
799 /* csefind: call with crypto_mtx held. */
800 static struct csession *
801 csefind(struct fcrypt *fcr, u_int ses)
802 {
803 	struct csession *cse, *ret = NULL;
804 
805 	KASSERT(mutex_owned(&crypto_mtx));
806 	TAILQ_FOREACH(cse, &fcr->csessions, next)
807 		if (cse->ses == ses)
808 			ret = cse;
809 
810 	return ret;
811 }
812 
813 /* csedelete: call with crypto_mtx held. */
814 static int
815 csedelete(struct fcrypt *fcr, struct csession *cse_del)
816 {
817 	struct csession *cse;
818 	int ret = 0;
819 
820 	KASSERT(mutex_owned(&crypto_mtx));
821 	TAILQ_FOREACH(cse, &fcr->csessions, next) {
822 		if (cse == cse_del) {
823 			TAILQ_REMOVE(&fcr->csessions, cse, next);
824 			ret = 1;
825 		}
826 	}
827 	return ret;
828 }
829 
830 /* cseadd: call with crypto_mtx held. */
831 static struct csession *
832 cseadd(struct fcrypt *fcr, struct csession *cse)
833 {
834 	KASSERT(mutex_owned(&crypto_mtx));
835 	/* don't let session ID wrap! */
836 	if (fcr->sesn + 1 == 0) return NULL;
837 	TAILQ_INSERT_TAIL(&fcr->csessions, cse, next);
838 	cse->ses = fcr->sesn++;
839 	return cse;
840 }
841 
842 /* csecreate: call with crypto_mtx held. */
843 static struct csession *
844 csecreate(struct fcrypt *fcr, u_int64_t sid, void *key, u_int64_t keylen,
845     void *mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac,
846     struct enc_xform *txform, struct auth_hash *thash)
847 {
848 	struct csession *cse;
849 
850 	KASSERT(mutex_owned(&crypto_mtx));
851 	cse = pool_get(&csepl, PR_NOWAIT);
852 	if (cse == NULL)
853 		return NULL;
854 	cse->key = key;
855 	cse->keylen = keylen/8;
856 	cse->mackey = mackey;
857 	cse->mackeylen = mackeylen/8;
858 	cse->sid = sid;
859 	cse->cipher = cipher;
860 	cse->mac = mac;
861 	cse->txform = txform;
862 	cse->thash = thash;
863 	cse->error = 0;
864 	if (cseadd(fcr, cse))
865 		return cse;
866 	else {
867 		pool_put(&csepl, cse);
868 		return NULL;
869 	}
870 }
871 
872 /* csefree: call with crypto_mtx held. */
873 static int
874 csefree(struct csession *cse)
875 {
876 	int error;
877 
878 	KASSERT(mutex_owned(&crypto_mtx));
879 	error = crypto_freesession(cse->sid);
880 	if (cse->key)
881 		free(cse->key, M_XDATA);
882 	if (cse->mackey)
883 		free(cse->mackey, M_XDATA);
884 	pool_put(&csepl, cse);
885 	return error;
886 }
887 
888 static int
889 cryptoopen(dev_t dev, int flag, int mode,
890     struct lwp *l)
891 {
892 	file_t *fp;
893         struct fcrypt *fcr;
894         int fd, error;
895 
896 	if (crypto_usercrypto == 0)
897 		return ENXIO;
898 
899 	if ((error = fd_allocfile(&fp, &fd)) != 0)
900 		return error;
901 
902 	fcr = pool_get(&fcrpl, PR_WAITOK);
903 	mutex_spin_enter(&crypto_mtx);
904 	TAILQ_INIT(&fcr->csessions);
905 	TAILQ_INIT(&fcr->crp_ret_mq);
906 	TAILQ_INIT(&fcr->crp_ret_mkq);
907 	selinit(&fcr->sinfo);
908 	/*
909 	 * Don't ever return session 0, to allow detection of
910 	 * failed creation attempts with multi-create ioctl.
911 	 */
912 	fcr->sesn = 1;
913 	fcr->requestid = 1;
914 	mutex_spin_exit(&crypto_mtx);
915 	return fd_clone(fp, fd, flag, &cryptofops, fcr);
916 }
917 
918 static int
919 cryptoread(dev_t dev, struct uio *uio, int ioflag)
920 {
921 	return EIO;
922 }
923 
924 static int
925 cryptowrite(dev_t dev, struct uio *uio, int ioflag)
926 {
927 	return EIO;
928 }
929 
930 int
931 cryptoselect(dev_t dev, int rw, struct lwp *l)
932 {
933 	return 0;
934 }
935 
936 /*static*/
937 struct cdevsw crypto_cdevsw = {
938 	/* open */	cryptoopen,
939 	/* close */	noclose,
940 	/* read */	cryptoread,
941 	/* write */	cryptowrite,
942 	/* ioctl */	noioctl,
943 	/* ttstop?*/	nostop,
944 	/* ??*/		notty,
945 	/* poll */	cryptoselect /*nopoll*/,
946 	/* mmap */	nommap,
947 	/* kqfilter */	nokqfilter,
948 	/* type */	D_OTHER,
949 };
950 
951 static int
952 cryptodev_mop(struct fcrypt *fcr,
953               struct crypt_n_op * cnop,
954               int count, struct lwp *l)
955 {
956 	struct cryptop *crp = NULL;
957 	struct cryptodesc *crde = NULL, *crda = NULL;
958 	int req, error=0;
959 	struct csession *cse;
960 
961 	for (req = 0; req < count; req++) {
962 		mutex_spin_enter(&crypto_mtx);
963 		cse = csefind(fcr, cnop[req].ses);
964 		if (cse == NULL) {
965 			DPRINTF(("csefind failed\n"));
966 			cnop[req].status = EINVAL;
967 			mutex_spin_exit(&crypto_mtx);
968 			continue;
969 		}
970 		mutex_spin_exit(&crypto_mtx);
971 
972 		if (cnop[req].len > 256*1024-4) {
973 			DPRINTF(("length failed\n"));
974 			cnop[req].status = EINVAL;
975 			continue;
976 		}
977 		if (cse->txform) {
978 			if (cnop[req].len == 0 ||
979 			    (cnop[req].len % cse->txform->blocksize) != 0) {
980 				cnop[req].status = EINVAL;
981 				continue;
982 			}
983 		}
984 
985 		crp = crypto_getreq((cse->txform != NULL) +
986 		    (cse->thash != NULL));
987 		if (crp == NULL) {
988 			cnop[req].status = ENOMEM;
989 			goto bail;
990 		}
991 
992 		(void)memset(&crp->uio, 0, sizeof(crp->uio));
993 		crp->uio.uio_iovcnt = 1;
994 		crp->uio.uio_resid = 0;
995 		crp->uio.uio_rw = UIO_WRITE;
996 		crp->uio.uio_iov = crp->iovec;
997 		UIO_SETUP_SYSSPACE(&crp->uio);
998 		memset(&crp->iovec, 0, sizeof(crp->iovec));
999 		crp->uio.uio_iov[0].iov_len = cnop[req].len;
1000 		crp->uio.uio_iov[0].iov_base = kmem_alloc(cnop[req].len,
1001 		    KM_SLEEP);
1002 		crp->uio.uio_resid = crp->uio.uio_iov[0].iov_len;
1003 
1004 		if (cse->thash) {
1005 			crda = crp->crp_desc;
1006 			if (cse->txform && crda)
1007 				crde = crda->crd_next;
1008 		} else {
1009 			if (cse->txform)
1010 				crde = crp->crp_desc;
1011 			else {
1012 				cnop[req].status = EINVAL;
1013 				goto bail;
1014 			}
1015 		}
1016 
1017 		if ((copyin(cnop[req].src,
1018 		    crp->uio.uio_iov[0].iov_base, cnop[req].len))) {
1019 			cnop[req].status = EINVAL;
1020 			goto bail;
1021 		}
1022 
1023 		if (crda) {
1024 			crda->crd_skip = 0;
1025 			crda->crd_len = cnop[req].len;
1026 			crda->crd_inject = 0;	/* ??? */
1027 
1028 			crda->crd_alg = cse->mac;
1029 			crda->crd_key = cse->mackey;
1030 			crda->crd_klen = cse->mackeylen * 8;
1031 		}
1032 
1033 		if (crde) {
1034 			if (cnop[req].op == COP_ENCRYPT)
1035 				crde->crd_flags |= CRD_F_ENCRYPT;
1036 			else
1037 				crde->crd_flags &= ~CRD_F_ENCRYPT;
1038 			crde->crd_len = cnop[req].len;
1039 			crde->crd_inject = 0;
1040 
1041 			crde->crd_alg = cse->cipher;
1042 #ifdef notyet		/* XXX must notify h/w driver new key, drain */
1043 			if(cnop[req].key && cnop[req].keylen) {
1044 				crde->crd_key = malloc(cnop[req].keylen,
1045 						    M_XDATA, M_WAITOK);
1046 				if((error = copyin(cnop[req].key,
1047 				    crde->crd_key, cnop[req].keylen))) {
1048 					cnop[req].status = EINVAL;
1049 					goto bail;
1050 				}
1051 				crde->crd_klen =  cnop[req].keylen * 8;
1052 			} else { ... }
1053 #endif
1054 			crde->crd_key = cse->key;
1055 			crde->crd_klen = cse->keylen * 8;
1056 		}
1057 
1058 		crp->crp_ilen = cnop[req].len;
1059 		crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM |
1060 		    (cnop[req].flags & COP_F_BATCH);
1061 		crp->crp_buf = (void *)&crp->uio;
1062 		crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_mcb;
1063 		crp->crp_sid = cse->sid;
1064 		crp->crp_opaque = (void *)cse;
1065 		crp->fcrp = fcr;
1066 		crp->dst = cnop[req].dst;
1067 		/* we can use the crp_ilen in cryptop(crp) for this */
1068 		crp->len = cnop[req].len;
1069 		crp->mac = cnop[req].mac;
1070 
1071 		if (cnop[req].iv) {
1072 			if (crde == NULL) {
1073 				cnop[req].status = EINVAL;
1074 				goto bail;
1075 			}
1076 			if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
1077 				cnop[req].status = EINVAL;
1078 				goto bail;
1079 			}
1080 			if ((error = copyin(cnop[req].iv, crp->tmp_iv,
1081 			    cse->txform->blocksize))) {
1082 				cnop[req].status = EINVAL;
1083 				goto bail;
1084 			}
1085 			(void)memcpy(crde->crd_iv, crp->tmp_iv,
1086 			    cse->txform->blocksize);
1087 			crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
1088 			crde->crd_skip = 0;
1089 		} else if (crde) {
1090 			if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
1091 				crde->crd_skip = 0;
1092 			} else {
1093 				crde->crd_flags |= CRD_F_IV_PRESENT;
1094 				crde->crd_skip = cse->txform->blocksize;
1095 				crde->crd_len -= cse->txform->blocksize;
1096 			}
1097 		}
1098 
1099 		if (cnop[req].mac) {
1100 			if (crda == NULL) {
1101 				cnop[req].status = EINVAL;
1102 				goto bail;
1103 			}
1104 			crp->crp_mac=cse->tmp_mac;
1105 		}
1106 		cnop[req].reqid = atomic_inc_32_nv(&(fcr->requestid));
1107 		crp->crp_reqid = cnop[req].reqid;
1108 		crp->crp_usropaque = cnop[req].opaque;
1109 #ifdef notyet
1110 eagain:
1111 #endif
1112 		cnop[req].status = crypto_dispatch(crp);
1113 		mutex_spin_enter(&crypto_mtx);	/* XXX why mutex? */
1114 
1115 		switch (cnop[req].status) {
1116 #ifdef notyet	/* don't loop forever -- but EAGAIN not possible here yet */
1117 		case EAGAIN:
1118 			mutex_spin_exit(&crypto_mtx);
1119 			goto eagain;
1120 			break;
1121 #endif
1122 		case 0:
1123 			break;
1124 		default:
1125 			DPRINTF(("cryptodev_op: not waiting, error.\n"));
1126 			mutex_spin_exit(&crypto_mtx);
1127 			goto bail;
1128 		}
1129 
1130 		mutex_spin_exit(&crypto_mtx);
1131 bail:
1132 		if (cnop[req].status) {
1133 			if (crp) {
1134 				crypto_freereq(crp);
1135 				if(cse->uio.uio_iov[0].iov_base) {
1136 					kmem_free(cse->uio.uio_iov[0].iov_base,
1137 					    cse->uio.uio_iov[0].iov_len);
1138 				}
1139 			}
1140 			error = 0;
1141 		}
1142 	}
1143 	return error;
1144 }
1145 
1146 static int
1147 cryptodev_mkey(struct fcrypt *fcr, struct crypt_n_kop *kop, int count)
1148 {
1149 	struct cryptkop *krp = NULL;
1150 	int error = EINVAL;
1151 	int in, out, size, i, req;
1152 
1153 	for (req = 0; req < count; req++) {
1154 		if (kop[req].crk_iparams + kop[req].crk_oparams > CRK_MAXPARAM)
1155 			return EFBIG;
1156 
1157 		in = kop[req].crk_iparams;
1158 		out = kop[req].crk_oparams;
1159 		switch (kop[req].crk_op) {
1160 		case CRK_MOD_EXP:
1161 			if (in == 3 && out == 1)
1162 				break;
1163 			kop[req].crk_status = EINVAL;
1164 			continue;
1165 		case CRK_MOD_EXP_CRT:
1166 			if (in == 6 && out == 1)
1167 				break;
1168 			kop[req].crk_status = EINVAL;
1169 			continue;
1170 		case CRK_DSA_SIGN:
1171 			if (in == 5 && out == 2)
1172 				break;
1173 			kop[req].crk_status = EINVAL;
1174 			continue;
1175 		case CRK_DSA_VERIFY:
1176 			if (in == 7 && out == 0)
1177 				break;
1178 			kop[req].crk_status = EINVAL;
1179 			continue;
1180 		case CRK_DH_COMPUTE_KEY:
1181 			if (in == 3 && out == 1)
1182 				break;
1183 			kop[req].crk_status = EINVAL;
1184 			continue;
1185 		case CRK_MOD_ADD:
1186 			if (in == 3 && out == 1)
1187 				break;
1188 			kop[req].crk_status = EINVAL;
1189 			continue;
1190 		case CRK_MOD_ADDINV:
1191 			if (in == 2 && out == 1)
1192 				break;
1193 			kop[req].crk_status = EINVAL;
1194 			continue;
1195 		case CRK_MOD_SUB:
1196 			if (in == 3 && out == 1)
1197 				break;
1198 			kop[req].crk_status = EINVAL;
1199 			continue;
1200 		case CRK_MOD_MULT:
1201 			if (in == 3 && out == 1)
1202 				break;
1203 			kop[req].crk_status = EINVAL;
1204 			continue;
1205 		case CRK_MOD_MULTINV:
1206 			if (in == 2 && out == 1)
1207 				break;
1208 			kop[req].crk_status = EINVAL;
1209 			continue;
1210 		case CRK_MOD:
1211 			if (in == 2 && out == 1)
1212 				break;
1213 			kop[req].crk_status = EINVAL;
1214 			continue;
1215 		default:
1216 			kop[req].crk_status = EINVAL;
1217 			continue;
1218 		}
1219 
1220 		krp = pool_get(&cryptkop_pool, PR_WAITOK);
1221 		(void)memset(krp, 0, sizeof *krp);
1222 		cv_init(&krp->krp_cv, "crykdev");
1223 		krp->krp_op = kop[req].crk_op;
1224 		krp->krp_status = kop[req].crk_status;
1225 		krp->krp_iparams = kop[req].crk_iparams;
1226 		krp->krp_oparams = kop[req].crk_oparams;
1227 		krp->krp_status = 0;
1228 		krp->krp_callback =
1229 		    (int (*) (struct cryptkop *)) cryptodevkey_mcb;
1230 		(void)memcpy(krp->crk_param, kop[req].crk_param,
1231 		    sizeof(kop[req].crk_param));
1232 
1233 		krp->krp_flags = CRYPTO_F_CBIMM;
1234 
1235 		for (i = 0; i < CRK_MAXPARAM; i++)
1236 			krp->krp_param[i].crp_nbits =
1237 			    kop[req].crk_param[i].crp_nbits;
1238 		for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
1239 			size = (krp->krp_param[i].crp_nbits + 7) / 8;
1240 			if (size == 0)
1241 				continue;
1242 			krp->krp_param[i].crp_p =
1243 			    kmem_alloc(size, KM_SLEEP);
1244 			if (i >= krp->krp_iparams)
1245 				continue;
1246 			kop[req].crk_status =
1247 			    copyin(kop[req].crk_param[i].crp_p,
1248 			    krp->krp_param[i].crp_p, size);
1249 			if (kop[req].crk_status)
1250 				goto fail;
1251 		}
1252 		krp->fcrp = fcr;
1253 
1254 		kop[req].crk_reqid = atomic_inc_32_nv(&(fcr->requestid));
1255 		krp->krp_reqid = kop[req].crk_reqid;
1256 		krp->krp_usropaque = kop[req].crk_opaque;
1257 
1258 		kop[req].crk_status = crypto_kdispatch(krp);
1259 		if (kop[req].crk_status != 0) {
1260 			goto fail;
1261 		}
1262 
1263 fail:
1264 		if(kop[req].crk_status) {
1265 			if (krp) {
1266 				kop[req].crk_status = krp->krp_status;
1267 				for (i = 0; i < CRK_MAXPARAM; i++) {
1268 					struct crparam *kp =
1269 						&(krp->krp_param[i]);
1270 					if (kp->crp_p) {
1271 						size = (kp->crp_nbits + 7) / 8;
1272 						KASSERT(size > 0);
1273 						memset(kp->crp_p, 0, size);
1274 						kmem_free(kp->crp_p, size);
1275 					}
1276 				}
1277 				pool_put(&cryptkop_pool, krp);
1278 			}
1279 		}
1280 		error = 0;
1281 	}
1282 	DPRINTF(("cryptodev_key: error=0x%08x\n", error));
1283 	return error;
1284 }
1285 
1286 static int
1287 cryptodev_session(struct fcrypt *fcr, struct session_op *sop) {
1288 	struct cryptoini cria, crie;
1289 	struct enc_xform *txform = NULL;
1290 	struct auth_hash *thash = NULL;
1291 	struct csession *cse;
1292 	u_int64_t sid;
1293 	int error = 0;
1294 
1295 	/* XXX there must be a way to not embed the list of xforms here */
1296 	switch (sop->cipher) {
1297 	case 0:
1298 		break;
1299 	case CRYPTO_DES_CBC:
1300 		txform = &enc_xform_des;
1301 		break;
1302 	case CRYPTO_3DES_CBC:
1303 		txform = &enc_xform_3des;
1304 		break;
1305 	case CRYPTO_BLF_CBC:
1306 		txform = &enc_xform_blf;
1307 		break;
1308 	case CRYPTO_CAST_CBC:
1309 		txform = &enc_xform_cast5;
1310 	case CRYPTO_SKIPJACK_CBC:
1311 		txform = &enc_xform_skipjack;
1312 		break;
1313 	case CRYPTO_AES_CBC:
1314 		txform = &enc_xform_rijndael128;
1315 		break;
1316 	case CRYPTO_NULL_CBC:
1317 		txform = &enc_xform_null;
1318 		break;
1319 	case CRYPTO_ARC4:
1320 		txform = &enc_xform_arc4;
1321 		break;
1322 	default:
1323 		DPRINTF(("Invalid cipher %d\n", sop->cipher));
1324 		return EINVAL;
1325 	}
1326 
1327 	switch (sop->mac) {
1328 	case 0:
1329 		break;
1330 	case CRYPTO_MD5_HMAC:
1331 		thash = &auth_hash_hmac_md5;
1332 		break;
1333 	case CRYPTO_SHA1_HMAC:
1334 		thash = &auth_hash_hmac_sha1;
1335 		break;
1336 	case CRYPTO_MD5_HMAC_96:
1337 		thash = &auth_hash_hmac_md5_96;
1338 		break;
1339 	case CRYPTO_SHA1_HMAC_96:
1340 		thash = &auth_hash_hmac_sha1_96;
1341 		break;
1342 	case CRYPTO_SHA2_HMAC:
1343 		/* XXX switching on key length seems questionable */
1344 		if (sop->mackeylen == auth_hash_hmac_sha2_256.keysize) {
1345 			thash = &auth_hash_hmac_sha2_256;
1346 		} else if (sop->mackeylen == auth_hash_hmac_sha2_384.keysize) {
1347 			thash = &auth_hash_hmac_sha2_384;
1348 		} else if (sop->mackeylen == auth_hash_hmac_sha2_512.keysize) {
1349 			thash = &auth_hash_hmac_sha2_512;
1350 		} else {
1351 			DPRINTF(("Invalid mackeylen %d\n", sop->mackeylen));
1352 			return EINVAL;
1353 		}
1354 		break;
1355 	case CRYPTO_RIPEMD160_HMAC:
1356 		thash = &auth_hash_hmac_ripemd_160;
1357 		break;
1358 	case CRYPTO_RIPEMD160_HMAC_96:
1359 		thash = &auth_hash_hmac_ripemd_160_96;
1360 		break;
1361 	case CRYPTO_MD5:
1362 		thash = &auth_hash_md5;
1363 		break;
1364 	case CRYPTO_SHA1:
1365 		thash = &auth_hash_sha1;
1366 		break;
1367 	case CRYPTO_NULL_HMAC:
1368 		thash = &auth_hash_null;
1369 		break;
1370 	default:
1371 		DPRINTF(("Invalid mac %d\n", sop->mac));
1372 		return EINVAL;
1373 	}
1374 
1375 	memset(&crie, 0, sizeof(crie));
1376 	memset(&cria, 0, sizeof(cria));
1377 
1378 	if (txform) {
1379 		crie.cri_alg = txform->type;
1380 		crie.cri_klen = sop->keylen * 8;
1381 		if (sop->keylen > txform->maxkey ||
1382 		    sop->keylen < txform->minkey) {
1383 			DPRINTF(("keylen %d not in [%d,%d]\n",
1384 			    sop->keylen, txform->minkey, txform->maxkey));
1385 			error = EINVAL;
1386 			goto bail;
1387 		}
1388 
1389 		crie.cri_key = malloc(crie.cri_klen / 8, M_XDATA, M_WAITOK);
1390 		if ((error = copyin(sop->key, crie.cri_key, crie.cri_klen / 8)))
1391 			goto bail;
1392 		if (thash)
1393 			crie.cri_next = &cria;	/* XXX forces enc then hash? */
1394 	}
1395 
1396 	if (thash) {
1397 		cria.cri_alg = thash->type;
1398 		cria.cri_klen = sop->mackeylen * 8;
1399 		if (sop->mackeylen != thash->keysize) {
1400 			DPRINTF(("mackeylen %d != keysize %d\n",
1401 			    sop->mackeylen, thash->keysize));
1402 			error = EINVAL;
1403 			goto bail;
1404 		}
1405 		if (cria.cri_klen) {
1406 			cria.cri_key = malloc(cria.cri_klen / 8, M_XDATA,
1407 			    M_WAITOK);
1408 			if ((error = copyin(sop->mackey, cria.cri_key,
1409 			    cria.cri_klen / 8))) {
1410 				goto bail;
1411 			}
1412 		}
1413 	}
1414 	/* crypto_newsession requires that we hold the mutex. */
1415 	mutex_spin_enter(&crypto_mtx);
1416 	error = crypto_newsession(&sid, (txform ? &crie : &cria),
1417 	    crypto_devallowsoft);
1418 	if (!error) {
1419 		cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
1420 		    cria.cri_key, cria.cri_klen, sop->cipher, sop->mac,
1421 		    txform, thash);
1422 		if (cse != NULL) {
1423 			sop->ses = cse->ses;
1424 		} else {
1425 			DPRINTF(("csecreate failed\n"));
1426 			crypto_freesession(sid);
1427 			error = EINVAL;
1428 		}
1429 	} else {
1430 		DPRINTF(("SIOCSESSION violates kernel parameters %d\n",
1431 		    error));
1432 	}
1433 	mutex_spin_exit(&crypto_mtx);
1434 bail:
1435 	if (error) {
1436 		if (crie.cri_key) {
1437 			memset(crie.cri_key, 0, crie.cri_klen / 8);
1438 			free(crie.cri_key, M_XDATA);
1439 		}
1440 		if (cria.cri_key) {
1441 			memset(cria.cri_key, 0, cria.cri_klen / 8);
1442 			free(cria.cri_key, M_XDATA);
1443 		}
1444 	}
1445 	return error;
1446 }
1447 
1448 static int
1449 cryptodev_msession(struct fcrypt *fcr, struct session_n_op *sn_ops,
1450 		   int count)
1451 {
1452 	int i;
1453 
1454 	for (i = 0; i < count; i++, sn_ops++) {
1455 		struct session_op s_op;
1456 		s_op.cipher =		sn_ops->cipher;
1457 		s_op.mac =		sn_ops->mac;
1458 		s_op.keylen =		sn_ops->keylen;
1459 		s_op.key =		sn_ops->key;
1460 		s_op.mackeylen =	sn_ops->mackeylen;
1461 		s_op.mackey =		sn_ops->mackey;
1462 
1463 		sn_ops->status = cryptodev_session(fcr, &s_op);
1464 		sn_ops->ses =		s_op.ses;
1465 	}
1466 
1467 	return 0;
1468 }
1469 
1470 static int
1471 cryptodev_msessionfin(struct fcrypt *fcr, int count, u_int32_t *sesid)
1472 {
1473 	struct csession *cse;
1474 	int req, error = 0;
1475 
1476 	mutex_spin_enter(&crypto_mtx);
1477 	for(req = 0; req < count; req++) {
1478 		cse = csefind(fcr, sesid[req]);
1479 		if (cse == NULL)
1480 			continue;
1481 		csedelete(fcr, cse);
1482 		error = csefree(cse);
1483 	}
1484 	mutex_spin_exit(&crypto_mtx);
1485 	return 0;
1486 }
1487 
1488 /*
1489  * collect as many completed requests as are availble, or count completed
1490  * requests whichever is less.
1491  * return the number of requests.
1492  */
1493 static int
1494 cryptodev_getmstatus(struct fcrypt *fcr, struct crypt_result *crypt_res,
1495     int count)
1496 {
1497 	struct cryptop *crp = NULL;
1498 	struct cryptkop *krp = NULL;
1499 	struct csession *cse;
1500 	int i, size, req = 0;
1501 	int completed=0;
1502 
1503 	/* On stack so nobody else can grab them -- no locking */
1504 	SLIST_HEAD(, cryptop) crp_delfree_l =
1505 	    SLIST_HEAD_INITIALIZER(crp_delfree_l);
1506 	SLIST_HEAD(, cryptkop) krp_delfree_l =
1507 	    SLIST_HEAD_INITIALIZER(krp_delfree_l);
1508 
1509 	mutex_spin_enter(&crypto_mtx);
1510 
1511 	/* at this point we do not know which response user is requesting for
1512 	 * (symmetric or asymmetric) so we copyout one from each i.e if the
1513 	 * count is 2 then 1 from symmetric and 1 from asymmetric queue and
1514 	 * if 3 then 2 symmetric and 1 asymmetric and so on */
1515 	for(; req < count ;) {
1516 		crp = TAILQ_FIRST(&fcr->crp_ret_mq);
1517 		if(crp) {
1518 			cse = (struct csession *)crp->crp_opaque;
1519 			crypt_res[req].reqid = crp->crp_reqid;
1520 			crypt_res[req].opaque = crp->crp_usropaque;
1521 			completed++;
1522 			cse = csefind(fcr, cse->ses);
1523 			if (cse == NULL) {
1524 				DPRINTF(("csefind failed\n"));
1525 				crypt_res[req].status = EINVAL;
1526 				goto bail;
1527 			}
1528 
1529 			if (crp->crp_etype != 0) {
1530 				crypt_res[req].status = crp->crp_etype;
1531 				goto bail;
1532 			}
1533 
1534 			if (cse->error) {
1535 				crypt_res[req].status = cse->error;
1536 				goto bail;
1537 			}
1538 
1539 			if (crp->dst && (crypt_res[req].status =
1540 			    copyout(crp->uio.uio_iov[0].iov_base, crp->dst,
1541 			    crp->len)))
1542 				goto bail;
1543 
1544 			if (crp->mac && (crypt_res[req].status =
1545 			    copyout(crp->crp_mac, crp->mac,
1546 			    cse->thash->authsize)))
1547 				goto bail;
1548 bail:
1549 			TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next);
1550 			SLIST_INSERT_HEAD(&crp_delfree_l, crp,
1551 			    crp_qun.crp_lnext);
1552 			req++;
1553 		}
1554 
1555 		if(req < count) {
1556 			krp = TAILQ_FIRST(&fcr->crp_ret_mkq);
1557 			if (krp) {
1558 				crypt_res[req].reqid = krp->krp_reqid;
1559 				crypt_res[req].opaque = krp->krp_usropaque;
1560 				completed++;
1561 				if (krp->krp_status != 0) {
1562 					DPRINTF(("cryptodev_key: "
1563 					    "krp->krp_status 0x%08x\n",
1564 					    krp->krp_status));
1565 					crypt_res[req].status = krp->krp_status;
1566 					goto fail;
1567 				}
1568 
1569 				for (i = krp->krp_iparams; i < krp->krp_iparams
1570 				    + krp->krp_oparams; i++) {
1571 					size = (krp->krp_param[i].crp_nbits
1572 					    + 7) / 8;
1573 					if (size == 0)
1574 						continue;
1575 					crypt_res[req].status = copyout
1576 					    (krp->krp_param[i].crp_p,
1577 					    krp->crk_param[i].crp_p, size);
1578 					if (crypt_res[req].status) {
1579 						DPRINTF(("cryptodev_key: "
1580 						    "copyout oparam %d failed, "
1581 						    "error=%d\n",
1582 						    i - krp->krp_iparams,
1583 						    crypt_res[req].status));
1584 						goto fail;
1585 					}
1586 				}
1587 fail:
1588 				TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next);
1589 				/* not sure what to do for this */
1590 				/* kop[req].crk_status = krp->krp_status; */
1591 				SLIST_INSERT_HEAD(&krp_delfree_l, krp,
1592 				    krp_qun.krp_lnext);
1593 			}
1594 			req++;
1595 		}
1596 	}
1597 	mutex_spin_exit(&crypto_mtx);
1598 
1599 	while(!SLIST_EMPTY(&crp_delfree_l)) {
1600 		crp = SLIST_FIRST(&crp_delfree_l);
1601 		SLIST_REMOVE_HEAD(&crp_delfree_l, crp_qun.crp_lnext);
1602 		kmem_free(crp->uio.uio_iov[0].iov_base,
1603 		    crp->uio.uio_iov[0].iov_len);
1604 		crypto_freereq(crp);
1605 	}
1606 
1607 	while(!SLIST_EMPTY(&krp_delfree_l)) {
1608 		krp = SLIST_FIRST(&krp_delfree_l);
1609 		for (i = 0; i < CRK_MAXPARAM; i++) {
1610 			struct crparam *kp = &(krp->krp_param[i]);
1611 			if (kp->crp_p) {
1612 				size = (kp->crp_nbits + 7) / 8;
1613 				KASSERT(size > 0);
1614 				(void)memset(kp->crp_p, 0, size);
1615 				kmem_free(kp->crp_p, size);
1616 			}
1617 		}
1618 		SLIST_REMOVE_HEAD(&krp_delfree_l, krp_qun.krp_lnext);
1619 		pool_put(&cryptkop_pool, krp);
1620 	}
1621 	return completed;
1622 }
1623 
1624 static int
1625 cryptodev_getstatus (struct fcrypt *fcr, struct crypt_result *crypt_res)
1626 {
1627         struct cryptop *crp = NULL;
1628         struct cryptkop *krp = NULL;
1629         struct csession *cse;
1630         int i, size, req = 0;
1631 
1632 	mutex_spin_enter(&crypto_mtx);
1633 	/* Here we dont know for which request the user is requesting the
1634 	 * response so checking in both the queues */
1635 	TAILQ_FOREACH(crp, &fcr->crp_ret_mq, crp_next) {
1636 		if(crp && (crp->crp_reqid == crypt_res->reqid)) {
1637 			cse = (struct csession *)crp->crp_opaque;
1638 		        crypt_res->opaque = crp->crp_usropaque;
1639 			cse = csefind(fcr, cse->ses);
1640 			if (cse == NULL) {
1641 				DPRINTF(("csefind failed\n"));
1642 				crypt_res->status = EINVAL;
1643 				goto bail;
1644 			}
1645 
1646 			if (crp->crp_etype != 0) {
1647 				crypt_res->status = crp->crp_etype;
1648 				goto bail;
1649 			}
1650 
1651 			if (cse->error) {
1652 				crypt_res->status = cse->error;
1653 				goto bail;
1654 			}
1655 
1656 			if (crp->dst && (crypt_res->status =
1657 			    copyout(crp->uio.uio_iov[0].iov_base,
1658 			    crp->dst, crp->len)))
1659 				goto bail;
1660 
1661 			if (crp->mac && (crypt_res->status =
1662 			    copyout(crp->crp_mac, crp->mac,
1663 			    cse->thash->authsize)))
1664 				goto bail;
1665 bail:
1666 			TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next);
1667 
1668 			mutex_spin_exit(&crypto_mtx);
1669 			crypto_freereq(crp);
1670 			return 0;
1671 		}
1672 	}
1673 
1674 	TAILQ_FOREACH(krp, &fcr->crp_ret_mkq, krp_next) {
1675 		if(krp && (krp->krp_reqid == crypt_res->reqid)) {
1676 			crypt_res[req].opaque = krp->krp_usropaque;
1677 			if (krp->krp_status != 0) {
1678 				DPRINTF(("cryptodev_key: "
1679 				    "krp->krp_status 0x%08x\n",
1680 				    krp->krp_status));
1681 				crypt_res[req].status = krp->krp_status;
1682 				goto fail;
1683 			}
1684 
1685 			for (i = krp->krp_iparams; i < krp->krp_iparams +
1686 			    krp->krp_oparams; i++) {
1687 				size = (krp->krp_param[i].crp_nbits + 7) / 8;
1688 				if (size == 0)
1689 					continue;
1690 				crypt_res[req].status = copyout(
1691 				    krp->krp_param[i].crp_p,
1692 				    krp->crk_param[i].crp_p, size);
1693 				if (crypt_res[req].status) {
1694 					DPRINTF(("cryptodev_key: copyout oparam"
1695 					    "%d failed, error=%d\n",
1696 					    i - krp->krp_iparams,
1697 					    crypt_res[req].status));
1698 					goto fail;
1699 				}
1700 			}
1701 fail:
1702 			TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next);
1703 			mutex_spin_exit(&crypto_mtx);
1704 			/* not sure what to do for this */
1705 			/* kop[req].crk_status = krp->krp_status; */
1706 			for (i = 0; i < CRK_MAXPARAM; i++) {
1707 				struct crparam *kp = &(krp->krp_param[i]);
1708 				if (kp->crp_p) {
1709 					size = (kp->crp_nbits + 7) / 8;
1710 					KASSERT(size > 0);
1711 					memset(kp->crp_p, 0, size);
1712 					kmem_free(kp->crp_p, size);
1713 				}
1714 			}
1715 			pool_put(&cryptkop_pool, krp);
1716 			return 0;
1717 		}
1718 	}
1719 	mutex_spin_exit(&crypto_mtx);
1720 	return EINPROGRESS;
1721 }
1722 
1723 static int
1724 cryptof_poll(struct file *fp, int events)
1725 {
1726 	struct fcrypt *fcr = (struct fcrypt *)fp->f_data;
1727 	int revents = 0;
1728 
1729 	if (!(events & (POLLIN | POLLRDNORM))) {
1730 		/* only support read and POLLIN */
1731 		return 0;
1732 	}
1733 
1734 	mutex_spin_enter(&crypto_mtx);
1735 	if (TAILQ_EMPTY(&fcr->crp_ret_mq) && TAILQ_EMPTY(&fcr->crp_ret_mkq)) {
1736 		/* no completed requests pending, save the poll for later */
1737 		selrecord(curlwp, &fcr->sinfo);
1738 	} else {
1739 		/* let the app(s) know that there are completed requests */
1740 		revents = events & (POLLIN | POLLRDNORM);
1741 	}
1742 	mutex_spin_exit(&crypto_mtx);
1743 
1744 	return revents;
1745 }
1746 
1747 /*
1748  * Pseudo-device initialization routine for /dev/crypto
1749  */
1750 void	cryptoattach(int);
1751 
1752 void
1753 cryptoattach(int num)
1754 {
1755 	pool_init(&fcrpl, sizeof(struct fcrypt), 0, 0, 0, "fcrpl",
1756 	    NULL, IPL_NET);	/* XXX IPL_NET ("splcrypto") */
1757 	pool_init(&csepl, sizeof(struct csession), 0, 0, 0, "csepl",
1758 	    NULL, IPL_NET);	/* XXX IPL_NET ("splcrypto") */
1759 
1760 	/*
1761 	 * Preallocate space for 64 users, with 5 sessions each.
1762 	 * (consider that a TLS protocol session requires at least
1763 	 * 3DES, MD5, and SHA1 (both hashes are used in the PRF) for
1764 	 * the negotiation, plus HMAC_SHA1 for the actual SSL records,
1765 	 * consuming one session here for each algorithm.
1766 	 */
1767 	pool_prime(&fcrpl, 64);
1768 	pool_prime(&csepl, 64 * 5);
1769 }
1770