tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

patch: multiple-request, async-request support for /dev/crypto



The attached patch adds ioctls for multiple request submission and
retrieval in a single system call, and for asynchronous operation via
select()/poll() to /dev/crypto. It was written for a slightly older
NetBSD-current and I've hastily adapted it to Andrew's recent file
descriptor allocation changes, which I hope I got right -- it's well
tested before that adaptation but untested with it (caveat emptor).
With this patch and a slightly clever multithreaded application that
batches requests when pushing them to /dev/crypto we can do 84,000
trivial asymmetric operations/sec (32 bit modular math ops) to a
rather old crypto accellerator card, with a Core 2 Duo as the host.
I think it's worth the added complexity. Even simpler applications
can benefit -- a lot -- from async operation and retrieving multiple
requests at once when poll() fires.
There is some duplicated code here in the multiple-request ioctls that
could be shared with the single-request ioctls. It'd be a moderate pain
to clean up and I'd prefer to do that after commit so I can get this
in the tree while I have time to focus on it. Also, there is a large
comment here describing the new ioctls and parameters which text I'll
reproduce in or move to the manual page.
I will revise the openssl engine to work as efficiently as possible with
the new ioctls added here once I sort out some issues about updating
OpenSSL itself in our tree and feeding changes back to the OpenSSL project
in an effective way.
Comments?
-- 
Thor Lancelot Simon
Coyote Point Systems, Inc. <tls%coyotepoint.com@localhost>
Millerton, NY, USA
diff -r -u -p opencrypto.o/crypto.c opencrypto/crypto.c
--- opencrypto.o/crypto.c 2008年02月05日 07:26:13.000000000 -0500
+++ opencrypto/crypto.c 2008年03月27日 01:32:44.000000000 -0400
@@ -2,6 +2,42 @@
 /* $FreeBSD: src/sys/opencrypto/crypto.c,v 1.4.2.5 2003年02月26日 00:14:05 sam 
Exp $ */
 /* $OpenBSD: crypto.c,v 1.41 2002年07月17日 23:52:38 art Exp $ */
 
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Coyote Point Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
 /*
 * The author of this code is Angelos D. Keromytis 
(angelos%cis.upenn.edu@localhost)
 *
@@ -984,6 +1020,9 @@ crypto_done(struct cryptop *crp)
 if (crypto_timing)
 crypto_tstat(&cryptostats.cs_done, &crp->crp_tstamp);
 #endif
+
+ crp->crp_flags |= CRYPTO_F_DONE;
+
 /*
 * Normal case; queue the callback for the thread.
 *
@@ -992,17 +1031,39 @@ crypto_done(struct cryptop *crp)
 * back to mark operations completed. Thus we need
 * to mask both while manipulating the return queue.
 */
- mutex_spin_enter(&crypto_mtx);
- wasempty = TAILQ_EMPTY(&crp_ret_q);
- DPRINTF(("crypto_done: queueing %08x\n", (uint32_t)crp));
- crp->crp_flags |= CRYPTO_F_ONRETQ|CRYPTO_F_DONE;
- TAILQ_INSERT_TAIL(&crp_ret_q, crp, crp_next);
- if (wasempty) {
- DPRINTF(("crypto_done: waking cryptoret, %08x " \
- "hit empty queue\n.", (uint32_t)crp));
- cv_signal(&cryptoret_cv);
+ if (crp->crp_flags & CRYPTO_F_CBIMM) {
+ /*
+ * Do the callback directly. This is ok when the
+ * callback routine does very little (e.g. the
+ * /dev/crypto callback method just does a wakeup).
+ */
+#ifdef CRYPTO_TIMING
+ if (crypto_timing) {
+ /*
+ * NB: We must copy the timestamp before
+ * doing the callback as the cryptop is
+ * likely to be reclaimed.
+ */
+ struct timespec t = crp->crp_tstamp;
+ crypto_tstat(&cryptostats.cs_cb, &t);
+ crp->crp_callback(crp);
+ crypto_tstat(&cryptostats.cs_finis, &t);
+ } else
+#endif
+ crp->crp_callback(crp);
+ } else {
+ mutex_spin_enter(&crypto_mtx);
+ wasempty = TAILQ_EMPTY(&crp_ret_q);
+ DPRINTF(("crypto_done: queueing %08x\n", (uint32_t)crp));
+ crp->crp_flags |= CRYPTO_F_ONRETQ;
+ TAILQ_INSERT_TAIL(&crp_ret_q, crp, crp_next);
+ if (wasempty) {
+ DPRINTF(("crypto_done: waking cryptoret, %08x " \
+ "hit empty queue\n.", (uint32_t)crp));
+ cv_signal(&cryptoret_cv);
+ }
+ mutex_spin_exit(&crypto_mtx);
 }
- mutex_spin_exit(&crypto_mtx);
 }
 
 /*
@@ -1015,19 +1076,26 @@ crypto_kdone(struct cryptkop *krp)
 
 if (krp->krp_status != 0)
 cryptostats.cs_kerrs++;
+ 
+ krp->krp_flags |= CRYPTO_F_DONE;
+
 /*
 * The return queue is manipulated by the swi thread
 * and, potentially, by crypto device drivers calling
 * back to mark operations completed. Thus we need
 * to mask both while manipulating the return queue.
 */
- mutex_spin_enter(&crypto_mtx);
- wasempty = TAILQ_EMPTY(&crp_ret_kq);
- krp->krp_flags |= CRYPTO_F_ONRETQ|CRYPTO_F_DONE;
- TAILQ_INSERT_TAIL(&crp_ret_kq, krp, krp_next);
- if (wasempty)
- cv_signal(&cryptoret_cv);
- mutex_spin_exit(&crypto_mtx);
+ if (krp->krp_flags & CRYPTO_F_CBIMM) {
+ krp->krp_callback(krp);
+ } else {
+ mutex_spin_enter(&crypto_mtx);
+ wasempty = TAILQ_EMPTY(&crp_ret_kq);
+ krp->krp_flags |= CRYPTO_F_ONRETQ;
+ TAILQ_INSERT_TAIL(&crp_ret_kq, krp, krp_next);
+ if (wasempty)
+ cv_signal(&cryptoret_cv);
+ mutex_spin_exit(&crypto_mtx);
+ }
 }
 
 int
diff -r -u -p opencrypto.o/cryptodev.c opencrypto/cryptodev.c
--- opencrypto.o/cryptodev.c 2008年03月21日 17:55:01.000000000 -0400
+++ opencrypto/cryptodev.c 2008年03月27日 01:53:34.000000000 -0400
@@ -2,6 +2,42 @@
 /* $FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.4.2.4 2003年06月03日 00:09:02 
sam Exp $ */
 /* $OpenBSD: cryptodev.c,v 1.53 2002年07月10日 22:21:30 mickey Exp $ */
 
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Coyote Point Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
 /*
 * Copyright (c) 2001 Theo de Raadt
 *
@@ -39,6 +75,7 @@ __KERNEL_RCSID(0, "$NetBSD: cryptodev.c,
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/kmem.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/pool.h>
@@ -51,6 +88,8 @@ __KERNEL_RCSID(0, "$NetBSD: cryptodev.c,
 #include <sys/conf.h>
 #include <sys/device.h>
 #include <sys/kauth.h>
+#include <sys/select.h>
+#include <sys/poll.h>
 
 #include "opt_ocf.h"
 #include <opencrypto/cryptodev.h>
@@ -81,7 +120,11 @@ struct csession {
 
 struct fcrypt {
 TAILQ_HEAD(csessionlist, csession) csessions;
+ TAILQ_HEAD(crprethead, cryptop) crp_ret_mq;
+ TAILQ_HEAD(krprethead, cryptkop) crp_ret_mkq;
 int sesn;
+ struct selinfo sinfo;
+ u_int32_t requestid;
 };
 
 /* For our fixed-size allocations */
@@ -97,15 +140,16 @@ static int cryptoselect(dev_t dev, int r
 /* Declaration of cloned-device (per-ctxt) entrypoints */
 static int cryptof_read(file_t *, off_t *, struct uio *, kauth_cred_t, 
int);
 static int cryptof_write(file_t *, off_t *, struct uio *, kauth_cred_t, 
int);
-static int cryptof_ioctl(file_t *, u_long, void *);
-static int cryptof_close(file_t *);
+static int cryptof_ioctl(file_t *, u_long, void*, struct lwp *l);
+static int cryptof_close(file_t *, struct lwp *);
+static int cryptof_poll(file_t *, int , struct lwp *);
 
 static const struct fileops cryptofops = {
 cryptof_read,
 cryptof_write,
 cryptof_ioctl,
 fnullop_fcntl,
- fnullop_poll,
+ cryptof_poll,
 fbadop_stat,
 cryptof_close,
 fnullop_kqfilter
@@ -120,12 +164,20 @@ static struct csession *csecreate(struct
 static int csefree(struct csession *);
 
 static int cryptodev_op(struct csession *, struct crypt_op *, struct lwp 
*);
+static int cryptodev_mop(struct fcrypt *, struct crypt_n_op *, int, struct 
lwp *); 
 static int cryptodev_key(struct crypt_kop *);
+static int cryptodev_mkey(struct fcrypt *, struct crypt_n_kop *, int);
 int cryptodev_dokey(struct crypt_kop *kop, struct crparam kvp[]);
+static int crypto_sessionfin(struct fcrypt *, int, u_int32_t *);
 
 static int cryptodev_cb(void *);
 static int cryptodevkey_cb(void *);
 
+static int cryptodev_mcb(void *);
+static int cryptodevkey_mcb(void *);
+
+static int crypto_getmstatus(struct fcrypt *, struct crypt_result_t *, 
int);
+static int crypto_getstatus(struct fcrypt *, struct crypt_result_t *);
 /*
 * sysctl-able control variables for /dev/crypto now defined in crypto.c:
 * crypto_usercrypto, crypto_userasmcrypto, crypto_devallowsoft.
@@ -155,36 +207,56 @@ cryptof_ioctl(file_t *fp, u_long cmd, vo
 struct fcrypt *fcr = fp->f_data;
 struct csession *cse;
 struct session_op *sop;
+ struct session_n_op snop, *psnop;
 struct crypt_op *cop;
+ struct crypto_mop *mop;
+ struct crypto_mkop *mkop;
+ struct crypt_n_op *cnop;
+ struct crypt_n_kop *knop;
+ struct crypt_fnop *fnop;
+ struct cryptret_t *cryptret;
+ struct crypt_result_t *crypt_result;
 struct enc_xform *txform = NULL;
 struct auth_hash *thash = NULL;
 u_int64_t sid;
 u_int32_t ses;
+ u_int32_t *sesid;
 int error = 0;
+ int first = 1;
+ size_t count;
 
 /* backwards compatibility */
 file_t *criofp;
 struct fcrypt *criofcr;
 int criofd;
 
- switch (cmd) {
+ switch (cmd) {
 case CRIOGET: /* XXX deprecated, remove after 5.0 */
- if ((error = fd_allocfile(&criofp, &criofd)) != 0)
- return error;
- criofcr = pool_get(&fcrpl, PR_WAITOK);
+ if ((error = fd_allocfile(&criofp, &criofd)) != 0)
+ return error;
+ criofcr = pool_get(&fcrpl, PR_WAITOK);
+ if (criofcr == NULL) {
+ fd_abort(curproc, criofp, &criofd);
+ return ENOMEM;
+ }
 mutex_spin_enter(&crypto_mtx);
- TAILQ_INIT(&criofcr->csessions);
+ TAILQ_INIT(&criofcr->csessions);
+ TAILQ_INIT(&criofcr->crp_ret_mq);
+ TAILQ_INIT(&criofcr->crp_ret_mkq);
+ selinit(&criofcr->sinfo);
+
 /*
 * Don't ever return session 0, to allow detection of
 * failed creation attempts with multi-create ioctl.
 */
- criofcr->sesn = 1;
+ criofcr->sesn = 1;
+ criofcr->requestid = 1;
 mutex_spin_exit(&crypto_mtx);
- (void)fd_clone(criofp, criofd, (FREAD|FWRITE),
+ (void)fd_clone(criofp, criofd, (FREAD|FWRITE),
 &cryptofops, criofcr);
- *(u_int32_t *)data = criofd;
+ *(u_int32_t *)data = criofd;
 return error;
- break;
+ break;
 case CIOCGSESSION:
 sop = (struct session_op *)data;
 switch (sop->cipher) {
@@ -248,6 +320,9 @@ cryptof_ioctl(file_t *fp, u_long cmd, vo
 }
 break;
 case CRYPTO_RIPEMD160_HMAC:
+ thash = &auth_hash_hmac_ripemd_160;
+ break;
+ case CRYPTO_RIPEMD160_HMAC_96:
 thash = &auth_hash_hmac_ripemd_160_96;
 break;
 case CRYPTO_MD5:
@@ -328,12 +403,193 @@ cryptof_ioctl(file_t *fp, u_long cmd, vo
 mutex_spin_exit(&crypto_mtx);
 bail:
 if (error) {
- if (crie.cri_key)
- FREE(crie.cri_key, M_XDATA);
- if (cria.cri_key)
- FREE(cria.cri_key, M_XDATA);
+ if (crie.cri_key) {
+ memset(crie.cri_key, 0, crie.cri_klen / 8);
+ free(crie.cri_key, M_XDATA);
+ }
+ if (cria.cri_key) {
+ memset(cria.cri_key, 0, cria.cri_klen / 8);
+ free(cria.cri_key, M_XDATA);
+ }
 }
 break;
+ case CIOCNSESSION:
+ psnop = (struct session_n_op *)data;
+ bcopy(data, (void *)&snop, sizeof(struct session_n_op));
+ do {
+ switch (snop.cipher) {
+ case 0:
+ break;
+ case CRYPTO_DES_CBC:
+ txform = &enc_xform_des;
+ break;
+ case CRYPTO_3DES_CBC:
+ txform = &enc_xform_3des;
+ break;
+ case CRYPTO_BLF_CBC:
+ txform = &enc_xform_blf;
+ break;
+ case CRYPTO_CAST_CBC:
+ txform = &enc_xform_cast5;
+ break;
+ case CRYPTO_SKIPJACK_CBC:
+ txform = &enc_xform_skipjack;
+ break;
+ case CRYPTO_AES_CBC:
+ txform = &enc_xform_rijndael128;
+ break;
+ case CRYPTO_NULL_CBC:
+ txform = &enc_xform_null;
+ break;
+ case CRYPTO_ARC4:
+ txform = &enc_xform_arc4;
+ break;
+ default:
+ DPRINTF(("Invalid cipher %d\n", snop.cipher));
+ snop.status = EINVAL;
+ goto mbail;
+ }
+
+ switch (snop.mac) {
+ case 0:
+ break;
+ case CRYPTO_MD5_HMAC:
+ thash = &auth_hash_hmac_md5;
+ break;
+ case CRYPTO_SHA1_HMAC:
+ thash = &auth_hash_hmac_sha1;
+ break;
+ case CRYPTO_MD5_HMAC_96:
+ thash = &auth_hash_hmac_md5_96;
+ break;
+ case CRYPTO_SHA1_HMAC_96:
+ thash = &auth_hash_hmac_sha1_96;
+ break;
+ case CRYPTO_SHA2_HMAC:
+ if (snop.mackeylen == 
auth_hash_hmac_sha2_256.keysize)
+ thash = &auth_hash_hmac_sha2_256;
+ else if (snop.mackeylen == 
auth_hash_hmac_sha2_384.keysize)
+ thash = &auth_hash_hmac_sha2_384;
+ else if (snop.mackeylen == 
auth_hash_hmac_sha2_512.keysize)
+ thash = &auth_hash_hmac_sha2_512;
+ else {
+ DPRINTF(("Invalid mackeylen %d\n",
+ snop.mackeylen));
+ snop.status = EINVAL;
+ }
+ break;
+ case CRYPTO_RIPEMD160_HMAC:
+ thash = &auth_hash_hmac_ripemd_160;
+ break;
+ case CRYPTO_RIPEMD160_HMAC_96:
+ thash = &auth_hash_hmac_ripemd_160_96;
+ break;
+ case CRYPTO_MD5:
+ thash = &auth_hash_md5;
+ break;
+ case CRYPTO_SHA1:
+ thash = &auth_hash_sha1;
+ break;
+ case CRYPTO_NULL_HMAC:
+ thash = &auth_hash_null;
+ break;
+ default: 
+ DPRINTF(("Invalid mac %d\n", snop.mac));
+ snop.status = EINVAL;
+ goto mbail; 
+ }
+
+ bzero(&crie, sizeof(crie));
+ bzero(&cria, sizeof(cria));
+
+ if (txform) {
+ crie.cri_alg = txform->type;
+ crie.cri_klen = snop.keylen * 8;
+ if (snop.keylen > txform->maxkey ||
+ snop.keylen < txform->minkey) {
+ DPRINTF(("keylen %d not in [%d,%d]\n",
+ snop.keylen, txform->minkey,
+ txform->maxkey));
+ snop.status = EINVAL;
+ goto mbail;
+ }
+
+ crie.cri_key = malloc(crie.cri_klen / 8, 
+ M_XDATA, M_WAITOK);
+ if((snop.status = copyin(snop.key, 
+ crie.cri_key, crie.cri_klen / 8)))
+ goto mbail;
+ if (thash)
+ crie.cri_next = &cria;
+ }
+
+ if (thash) {
+ cria.cri_alg = thash->type;
+ cria.cri_klen = snop.mackeylen * 8;
+ if (snop.mackeylen != thash->keysize) {
+ DPRINTF(("mackeylen %d != keysize %d\n",
+ snop.mackeylen, thash->keysize));
+ snop.status = EINVAL;
+ goto mbail;
+ }
+
+ if (cria.cri_klen) {
+ cria.cri_key = malloc(cria.cri_klen / 8,
+ M_XDATA, M_WAITOK);
+ if((snop.status = copyin(snop.mackey, 
+ cria.cri_key, cria.cri_klen / 8)))
+ goto mbail;
+ }
+ }
+ mutex_spin_enter(&crypto_mtx);
+ snop.status = crypto_newsession(&sid, 
+ (txform ? &crie : &cria), 
+ crypto_devallowsoft);
+ if (!snop.status) {
+ cse = csecreate(fcr, sid, crie.cri_key, 
+ crie.cri_klen, cria.cri_key, 
+ cria.cri_klen, snop.cipher, 
+ snop.mac, txform, thash);
+ if (cse != NULL) {
+ snop.ses = cse->ses;
+ } else {
+ DPRINTF(("csecreate failed\n"));
+ crypto_freesession(sid);
+ snop.status = EINVAL;
+ }
+ } else {
+ DPRINTF(("SIOCSESSION violates kernel 
parameters %d\n",
+ snop.status));
+ }
+ mutex_spin_exit(&crypto_mtx);
+mbail:
+ if(snop.status) {
+ snop.ses = 0;
+ if (crie.cri_key)
+ memset(crie.cri_key, 0, crie.cri_klen / 
8);
+ free(crie.cri_key, M_XDATA);
+ if (cria.cri_key)
+ memset(cria.cri_key, 0, cria.cri_klen / 
8);
+ free(cria.cri_key, M_XDATA);
+ }
+ 
+ if(first) {
+ bcopy(&snop, psnop,
+ sizeof(struct session_n_op));
+ first = 0;
+ } else {
+ error = copyout(&snop, psnop, 
+ sizeof(struct session_n_op));
+ }
+
+ psnop = snop.next;
+
+ if (psnop) {
+ copyin(psnop, &snop,
+ sizeof(struct session_n_op));
+ }
+ } while (psnop && !error);
+ break; 
 case CIOCFSESSION:
 mutex_spin_enter(&crypto_mtx);
 ses = *(u_int32_t *)data;
@@ -344,6 +600,19 @@ bail:
 error = csefree(cse);
 mutex_spin_exit(&crypto_mtx);
 break;
+ case CIOCFNSESSION:
+ fnop = (struct crypt_fnop *)data;
+ sesid = kmem_alloc((fnop->count * sizeof(u_int32_t)), 
+ KM_SLEEP);
+ if (!sesid)
+ return (EINVAL);
+ error = copyin(fnop->sesid, sesid, 
+ (fnop->count * sizeof(u_int32_t)));
+ if (!error) {
+ error = crypto_sessionfin(fcr, fnop->count, sesid);
+ }
+ kmem_free(sesid, (fnop->count * sizeof(u_int32_t)));
+ break;
 case CIOCCRYPT:
 mutex_spin_enter(&crypto_mtx);
 cop = (struct crypt_op *)data;
@@ -356,13 +625,80 @@ bail:
 error = cryptodev_op(cse, cop, curlwp);
 DPRINTF(("cryptodev_op error = %d\n", error));
 break;
+ case CIOCNCRYPTM:
+ mop = (struct crypto_mop *)data;
+ cnop = kmem_alloc((mop->count * sizeof(struct crypt_n_op)),
+ KM_SLEEP);
+ if(!cnop) {
+ return(EINVAL);
+ }
+ error = copyin(mop->reqs, cnop, 
+ (mop->count * sizeof(struct crypt_n_op)));
+ if(!error) {
+ error = cryptodev_mop(fcr, cnop, mop->count, l);
+ if (!error) {
+ error = copyout(cnop, mop->reqs, 
+ (mop->count *
+ sizeof(struct crypt_n_op)));
+ }
+ }
+ kmem_free(cnop, (mop->count * sizeof(struct crypt_n_op)));
+ break; 
 case CIOCKEY:
 error = cryptodev_key((struct crypt_kop *)data);
 DPRINTF(("cryptodev_key error = %d\n", error));
 break;
+ case CIOCNFKEYM:
+ mkop = (struct crypto_mkop *)data;
+ knop = kmem_alloc((mkop->count * sizeof(struct crypt_n_kop)),
+ KM_SLEEP);
+ if (!knop) {
+ return(EINVAL);
+ }
+ error = copyin(mkop->reqs, knop,
+ (mkop->count * sizeof(struct crypt_n_kop)));
+ if (!error) {
+ error = cryptodev_mkey(fcr, knop, mkop->count);
+ if (!error)
+ error = copyout(knop, mkop->reqs,
+ (mkop->count *
+ sizeof(struct crypt_n_kop)));
+ }
+ kmem_free(knop, (mkop->count * sizeof(struct crypt_n_kop)));
+ break;
 case CIOCASYMFEAT:
 error = crypto_getfeat((int *)data);
 break;
+ case CIOCNCRYPTRETM:
+ cryptret = (struct cryptret_t *)data;
+ count = cryptret->count;
+ crypt_result = kmem_alloc((count * 
+ sizeof(struct crypt_result_t)), 
+ KM_SLEEP);
+ if(!crypt_result)
+ return(EINVAL);
+ error = copyin(cryptret->results, crypt_result,
+ (count * sizeof(struct crypt_result_t)));
+ if (error)
+ goto reterr;
+ cryptret->count = crypto_getmstatus(fcr, crypt_result,
+ cryptret->count);
+ /* sanity check count */
+ if (cryptret->count > count) {
+ printf("%s.%d: error returned count %d > original count 
%d\n",
+ __FILE__, __LINE__, cryptret->count, 
count);
+ cryptret->count = count;
+
+ }
+ error = copyout(crypt_result, cryptret->results,
+ (cryptret->count * sizeof(struct crypt_result_t)));
+reterr:
+ kmem_free(crypt_result,
+ (count * sizeof(struct crypt_result_t)));
+ break;
+ case CIOCNCRYPTRET:
+ error = crypto_getstatus(fcr, (struct crypt_result_t *)data); 
+ break;
 default:
 DPRINTF(("invalid ioctl cmd %ld\n", cmd));
 error = EINVAL;
@@ -393,7 +729,7 @@ cryptodev_op(struct csession *cse, struc
 UIO_SETUP_SYSSPACE(&cse->uio);
 memset(&cse->iovec, 0, sizeof(cse->iovec));
 cse->uio.uio_iov[0].iov_len = cop->len;
- cse->uio.uio_iov[0].iov_base = malloc(cop->len, M_XDATA, M_WAITOK);
+ cse->uio.uio_iov[0].iov_base = kmem_alloc(cop->len, KM_SLEEP);
 cse->uio.uio_resid = cse->uio.uio_iov[0].iov_len;
 
 crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL));
@@ -416,7 +752,10 @@ cryptodev_op(struct csession *cse, struc
 }
 
 if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len)))
+ {
+ printf("copyin failed %s %d \n", (char *)cop->src, error);
 goto bail;
+ }
 
 if (crda) {
 crda->crd_skip = 0;
@@ -442,8 +781,7 @@ cryptodev_op(struct csession *cse, struc
 }
 
 crp->crp_ilen = cop->len;
- crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
- | (cop->flags & COP_F_BATCH);
+ crp->crp_flags = CRYPTO_F_IOV | (cop->flags & COP_F_BATCH);
 crp->crp_buf = (void *)&cse->uio;
 crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
 crp->crp_sid = cse->sid;
@@ -458,7 +796,8 @@ cryptodev_op(struct csession *cse, struc
 error = EINVAL;
 goto bail;
 }
- if ((error = copyin(cop->iv, cse->tmp_iv, 
cse->txform->blocksize)))
+ if ((error = copyin(cop->iv, cse->tmp_iv,
+ cse->txform->blocksize)))
 goto bail;
 bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize);
 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
@@ -491,13 +830,27 @@ cryptodev_op(struct csession *cse, struc
 * XXX (should we arrange for crypto_dispatch to return to
 * XXX us with it held? it seems quite ugly to do so.)
 */
+#ifdef notyet
+eagain:
+#endif
 error = crypto_dispatch(crp);
 mutex_spin_enter(&crypto_mtx);
- if (error != 0) {
+
+ switch (error) {
+#ifdef notyet /* don't loop forever -- but EAGAIN not possible here yet */
+ case EAGAIN:
+ mutex_spin_exit(&crypto_mtx);
+ goto eagain;
+ break;
+#endif
+ case 0:
+ break;
+ default:
 DPRINTF(("cryptodev_op: not waiting, error.\n"));
 mutex_spin_exit(&crypto_mtx);
 goto bail;
 }
+ 
 while (!(crp->crp_flags & CRYPTO_F_DONE)) {
 DPRINTF(("cryptodev_op: sleeping on cv %08x for crp %08x\n", \
 (uint32_t)&crp->crp_cv, (uint32_t)crp));
@@ -522,7 +875,8 @@ cryptodev_op(struct csession *cse, struc
 }
 
 if (cop->dst &&
- (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, 
cop->len))) {
+ (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, cop->len)))
+ {
 DPRINTF(("cryptodev_op: copyout error %d\n", error));
 goto bail;
 }
@@ -537,7 +891,8 @@ bail:
 if (crp)
 crypto_freereq(crp);
 if (cse->uio.uio_iov[0].iov_base)
- free(cse->uio.uio_iov[0].iov_base, M_XDATA);
+ kmem_free(cse->uio.uio_iov[0].iov_base,
+ cse->uio.uio_iov[0].iov_len);
 
 return (error);
 }
@@ -565,13 +920,50 @@ cryptodev_cb(void *op)
 }
 
 static int
+cryptodev_mcb(void *op)
+{
+ struct cryptop *crp = (struct cryptop *) op;
+ struct csession *cse = (struct csession *)crp->crp_opaque;
+ int error=0;
+
+ mutex_spin_enter(&crypto_mtx);
+ cse->error = crp->crp_etype;
+ if (crp->crp_etype == EAGAIN) {
+ mutex_spin_exit(&crypto_mtx);
+ error = crypto_dispatch(crp);
+ mutex_spin_enter(&crypto_mtx);
+ }
+ if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) {
+ cv_signal(&crp->crp_cv);
+ }
+
+ TAILQ_INSERT_TAIL(&crp->fcrp->crp_ret_mq, crp, crp_next);
+ mutex_spin_exit(&crypto_mtx);
+ selnotify(&crp->fcrp->sinfo, 0, 0);
+ return (0);
+}
+
+static int
 cryptodevkey_cb(void *op)
 {
 struct cryptkop *krp = (struct cryptkop *) op;
+ 
+ mutex_spin_enter(&crypto_mtx);
+ cv_signal(&krp->krp_cv);
+ mutex_spin_exit(&crypto_mtx);
+ return (0);
+}
+
+static int
+cryptodevkey_mcb(void *op)
+{
+ struct cryptkop *krp = (struct cryptkop *) op;
 
 mutex_spin_enter(&crypto_mtx);
 cv_signal(&krp->krp_cv);
+ TAILQ_INSERT_TAIL(&krp->fcrp->crp_ret_mkq, krp, krp_next);
 mutex_spin_exit(&crypto_mtx);
+ selnotify(&krp->fcrp->sinfo,0);
 return (0);
 }
 
@@ -655,7 +1047,7 @@ cryptodev_key(struct crypt_kop *kop)
 size = (krp->krp_param[i].crp_nbits + 7) / 8;
 if (size == 0)
 continue;
- krp->krp_param[i].crp_p = malloc(size, M_XDATA, M_WAITOK);
+ krp->krp_param[i].crp_p = kmem_alloc(size, KM_SLEEP);
 if (i >= krp->krp_iparams)
 continue;
 error = copyin(kop->crk_param[i].crp_p, 
krp->krp_param[i].crp_p, size);
@@ -699,8 +1091,13 @@ fail:
 if (krp) {
 kop->crk_status = krp->krp_status;
 for (i = 0; i < CRK_MAXPARAM; i++) {
- if (krp->krp_param[i].crp_p)
- FREE(krp->krp_param[i].crp_p, M_XDATA);
+ struct crparam *kp = &(krp->krp_param[i]);
+ if (krp->krp_param[i].crp_p) {
+ size = (kp->crp_nbits + 7) / 8;
+ KASSERT(size > 0);
+ memset(kp->crp_p, 0, size);
+ kmem_free(kp->crp_p, size);
+ }
 }
 pool_put(&cryptkop_pool, krp);
 }
@@ -720,6 +1117,7 @@ cryptof_close(file_t *fp)
 TAILQ_REMOVE(&fcr->csessions, cse, next);
 (void)csefree(cse);
 }
+ seldestroy(&fcr->sinfo);
 pool_put(&fcrpl, fcr);
 
 fp->f_data = NULL;
@@ -738,6 +1136,7 @@ csefind(struct fcrypt *fcr, u_int ses)
 TAILQ_FOREACH(cse, &fcr->csessions, next)
 if (cse->ses == ses)
 ret = cse;
+ 
 return (ret);
 }
 
@@ -809,9 +1208,9 @@ csefree(struct csession *cse)
 KASSERT(mutex_owned(&crypto_mtx));
 error = crypto_freesession(cse->sid);
 if (cse->key)
- FREE(cse->key, M_XDATA);
+ free(cse->key, M_XDATA);
 if (cse->mackey)
- FREE(cse->mackey, M_XDATA);
+ free(cse->mackey, M_XDATA);
 pool_put(&csepl, cse);
 return (error);
 }
@@ -831,13 +1230,21 @@ cryptoopen(dev_t dev, int flag, int mode
 return error;
 
 fcr = pool_get(&fcrpl, PR_WAITOK);
+ if (fcr == NULL) {
+ fdrelease(l, fd);
+ return ENOMEM;
+ }
 mutex_spin_enter(&crypto_mtx);
 TAILQ_INIT(&fcr->csessions);
+ TAILQ_INIT(&fcr->crp_ret_mq);
+ TAILQ_INIT(&fcr->crp_ret_mkq);
+ selinit(&fcr->sinfo);
 /*
 * Don't ever return session 0, to allow detection of
 * failed creation attempts with multi-create ioctl.
 */
 fcr->sesn = 1;
+ fcr->requestid = 1;
 mutex_spin_exit(&crypto_mtx);
 return fd_clone(fp, fd, flag, &cryptofops, fcr);
 }
@@ -875,6 +1282,622 @@ struct cdevsw crypto_cdevsw = {
 /* type */ D_OTHER,
 };
 
+static int 
+cryptodev_mop(struct fcrypt *fcr, 
+ struct crypt_n_op * cnop,
+ int count,
+ struct lwp *l)
+{
+ struct cryptop *crp = NULL;
+ struct cryptodesc *crde = NULL, *crda = NULL;
+ int req, error=0;
+ struct csession *cse;
+
+ for (req = 0; req < count; req++) {
+ mutex_spin_enter(&crypto_mtx);
+ cse = csefind(fcr, cnop[req].ses);
+ if (cse == NULL) {
+ DPRINTF(("csefind failed\n"));
+ cnop[req].status = EINVAL;
+ mutex_spin_exit(&crypto_mtx);
+ continue;
+ }
+ mutex_spin_exit(&crypto_mtx);
+ 
+ if (cnop[req].len > 256*1024-4) {
+ DPRINTF(("length failed\n"));
+ cnop[req].status = EINVAL;
+ continue;
+ }
+ if (cse->txform) {
+ if (cnop[req].len == 0 || 
+ (cnop[req].len % cse->txform->blocksize) != 0) { 
+ cnop[req].status = EINVAL;
+ continue;
+ }
+ }
+
+ crp = crypto_getreq((cse->txform != NULL) + (cse->thash != 
NULL));
+ if (crp == NULL) {
+ cnop[req].status = ENOMEM;
+ goto bail;
+ }
+
+ bzero(&crp->uio, sizeof(crp->uio));
+ crp->uio.uio_iovcnt = 1;
+ crp->uio.uio_resid = 0;
+ crp->uio.uio_rw = UIO_WRITE;
+ crp->uio.uio_iov = crp->iovec;
+ UIO_SETUP_SYSSPACE(&crp->uio);
+ memset(&crp->iovec, 0, sizeof(crp->iovec));
+ crp->uio.uio_iov[0].iov_len = cnop[req].len;
+ crp->uio.uio_iov[0].iov_base = kmem_alloc(cnop[req].len,
+ KM_SLEEP);
+ crp->uio.uio_resid = crp->uio.uio_iov[0].iov_len;
+
+ if (cse->thash) {
+ crda = crp->crp_desc;
+ if (cse->txform)
+ crde = crda->crd_next;
+ } else {
+ if (cse->txform)
+ crde = crp->crp_desc;
+ else {
+ cnop[req].status = EINVAL;
+ goto bail; 
+ }
+ }
+
+ if ((copyin(cnop[req].src, 
+ crp->uio.uio_iov[0].iov_base, cnop[req].len))) {
+ cnop[req].status = EINVAL;
+ goto bail;
+ }
+ 
+ if (crda) {
+ crda->crd_skip = 0;
+ crda->crd_len = cnop[req].len;
+ crda->crd_inject = 0; /* ??? */
+
+ crda->crd_alg = cse->mac;
+ crda->crd_key = cse->mackey;
+ crda->crd_klen = cse->mackeylen * 8;
+ }
+
+ if (crde) {
+ if (cnop[req].op == COP_ENCRYPT)
+ crde->crd_flags |= CRD_F_ENCRYPT;
+ else
+ crde->crd_flags &= ~CRD_F_ENCRYPT;
+ crde->crd_len = cnop[req].len;
+ crde->crd_inject = 0;
+
+ crde->crd_alg = cse->cipher;
+ if(cnop[req].key && cnop[req].keylen) {
+ crde->crd_key = malloc(cnop[req].keylen,
+ M_XDATA, M_WAITOK);
+ if((error = copyin(cnop[req].key, 
+ crde->crd_key, cnop[req].keylen))) {
+ cnop[req].status = EINVAL;
+ goto bail;
+ }
+ crde->crd_klen = cnop[req].keylen * 8;
+ } else {
+ crde->crd_key = cse->key;
+ crde->crd_klen = cse->keylen * 8;
+ }
+ }
+
+ crp->crp_ilen = cnop[req].len;
+ crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM
+ | (cnop[req].flags & COP_F_BATCH);
+ crp->crp_buf = (void *)&crp->uio;
+ crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_mcb;
+ crp->crp_sid = cse->sid;
+ crp->crp_opaque = (void *)cse;
+ crp->fcrp = fcr;
+ crp->dst = cnop[req].dst;
+ /* we can use the crp_ilen in cryptop(crp) for this */
+ crp->len = cnop[req].len;
+ crp->mac = cnop[req].mac;
+
+ if (cnop[req].iv) {
+ if (crde == NULL) {
+ cnop[req].status = EINVAL;
+ goto bail;
+ }
+ if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
+ cnop[req].status = EINVAL;
+ goto bail;
+ }
+ if ((error = copyin(cnop[req].iv, crp->tmp_iv,
+ cse->txform->blocksize))) {
+ cnop[req].status = EINVAL;
+ goto bail;
+ }
+ bcopy(crp->tmp_iv, crde->crd_iv, 
cse->txform->blocksize);
+ crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
+ crde->crd_skip = 0;
+ } else if (crde) {
+ if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
+ crde->crd_skip = 0;
+ } else {
+ crde->crd_flags |= CRD_F_IV_PRESENT;
+ crde->crd_skip = cse->txform->blocksize;
+ crde->crd_len -= cse->txform->blocksize;
+ }
+ }
+ 
+ if (cnop[req].mac) {
+ if (crda == NULL) {
+ cnop[req].status = EINVAL;
+ goto bail;
+ }
+ crp->crp_mac=cse->tmp_mac;
+ }
+ cnop[req].reqid = atomic_inc_32_nv(&(fcr->requestid));
+ crp->crp_reqid = cnop[req].reqid;
+ crp->crp_usropaque = cnop[req].opaque;
+#ifdef notyet
+eagain:
+#endif
+ cnop[req].status = crypto_dispatch(crp);
+ mutex_spin_enter(&crypto_mtx); /* XXX why mutex? */
+
+ switch (cnop[req].status) {
+#ifdef notyet /* don't loop forever -- but EAGAIN not possible here yet */
+ case EAGAIN:
+ mutex_spin_exit(&crypto_mtx);
+ goto eagain;
+ break;
+#endif
+ case 0:
+ break;
+ default:
+ DPRINTF(("cryptodev_op: not waiting, error.\n"));
+ mutex_spin_exit(&crypto_mtx);
+ goto bail;
+ }
+
+ mutex_spin_exit(&crypto_mtx);
+bail:
+ if (cnop[req].status) {
+ if (crp) {
+ crypto_freereq(crp);
+ if(cse->uio.uio_iov[0].iov_base) {
+ kmem_free(cse->uio.uio_iov[0].iov_base,
+ cse->uio.uio_iov[0].iov_len);
+ }
+ }
+ error = 0;
+ }
+ }
+ return (error);
+}
+
+static int
+cryptodev_mkey(struct fcrypt *fcr, struct crypt_n_kop *kop, int count)
+{
+ struct cryptkop *krp = NULL;
+ int error = EINVAL;
+ int in, out, size, i, req;
+
+ for (req = 0; req < count; req++) {
+ if (kop[req].crk_iparams + kop[req].crk_oparams > CRK_MAXPARAM) 
{
+ return (EFBIG);
+ }
+
+ in = kop[req].crk_iparams;
+ out = kop[req].crk_oparams;
+ switch (kop[req].crk_op) {
+ case CRK_MOD_EXP:
+ if (in == 3 && out == 1)
+ break;
+ kop[req].status = EINVAL;
+ continue;
+ case CRK_MOD_EXP_CRT:
+ if (in == 6 && out == 1)
+ break;
+ kop[req].status = EINVAL;
+ continue;
+ case CRK_DSA_SIGN:
+ if (in == 5 && out == 2)
+ break;
+ kop[req].status = EINVAL;
+ continue;
+ case CRK_DSA_VERIFY:
+ if (in == 7 && out == 0)
+ break;
+ kop[req].status = EINVAL;
+ continue;
+ case CRK_DH_COMPUTE_KEY:
+ if (in == 3 && out == 1)
+ break;
+ kop[req].status = EINVAL;
+ continue;
+ case CRK_MOD_ADD:
+ if (in == 3 && out == 1)
+ break;
+ kop[req].status = EINVAL;
+ continue;
+ case CRK_MOD_ADDINV:
+ if (in == 2 && out == 1)
+ break;
+ kop[req].status = EINVAL;
+ continue;
+ case CRK_MOD_SUB:
+ if (in == 3 && out == 1)
+ break;
+ kop[req].status = EINVAL;
+ continue;
+ case CRK_MOD_MULT:
+ if (in == 3 && out == 1)
+ break; 
+ kop[req].status = EINVAL;
+ continue;
+ case CRK_MOD_MULTINV:
+ if (in == 2 && out == 1)
+ break;
+ kop[req].status = EINVAL;
+ continue;
+ case CRK_MOD:
+ if (in == 2 && out == 1)
+ break;
+ kop[req].status = EINVAL;
+ continue;
+ default:
+ kop[req].status = EINVAL;
+ continue;
+ }
+
+ krp = pool_get(&cryptkop_pool, PR_WAITOK);
+ if (!krp) {
+ kop[req].status = ENOMEM;
+ goto fail;
+ }
+ bzero(krp, sizeof *krp);
+ cv_init(&krp->krp_cv, "crykdev");
+ krp->krp_op = kop[req].crk_op;
+ krp->krp_status = kop[req].crk_status;
+ krp->krp_iparams = kop[req].crk_iparams;
+ krp->krp_oparams = kop[req].crk_oparams;
+ krp->krp_status = 0;
+ krp->krp_callback =
+ (int (*) (struct cryptkop *)) cryptodevkey_mcb;
+ bcopy(kop[req].crk_param,
+ krp->crk_param,
+ sizeof(kop[req].crk_param));
+
+ krp->krp_flags = CRYPTO_F_CBIMM;
+
+ for (i = 0; i < CRK_MAXPARAM; i++)
+ krp->krp_param[i].crp_nbits =
+ kop[req].crk_param[i].crp_nbits;
+ for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
+ size = (krp->krp_param[i].crp_nbits + 7) / 8;
+ if (size == 0)
+ continue;
+ krp->krp_param[i].crp_p =
+ kmem_alloc(size, KM_SLEEP);
+ if (i >= krp->krp_iparams)
+ continue;
+ kop[req].status = copyin(kop[req].crk_param[i].crp_p,
+ krp->krp_param[i].crp_p, size);
+ if (kop[req].status)
+ goto fail;
+ }
+ krp->fcrp = fcr;
+
+ kop[req].reqid = atomic_inc_32_nv(&(fcr->requestid));
+ krp->krp_reqid = kop[req].reqid;
+ krp->krp_usropaque = kop[req].crk_opaque;
+
+ kop[req].status = crypto_kdispatch(krp);
+ if (kop[req].status != 0) {
+ goto fail;
+ }
+
+fail:
+ if(kop[req].status) {
+ if (krp) {
+ kop[req].crk_status = krp->krp_status;
+ for (i = 0; i < CRK_MAXPARAM; i++) {
+ struct crparam *kp =
+ &(krp->krp_param[i]);
+ if (kp->crp_p) {
+ size = (kp->crp_nbits + 7) / 8;
+ KASSERT(size > 0);
+ memset(kp->crp_p, 0, size);
+ kmem_free(kp->crp_p, size);
+ }
+ }
+ pool_put(&cryptkop_pool, krp);
+ }
+ }
+ error = 0;
+ }
+ DPRINTF(("cryptodev_key: error=0x%08x\n", error));
+ return (error);
+}
+
+static int
+crypto_sessionfin(struct fcrypt *fcr, int count, u_int32_t *sesid)
+{
+ struct csession *cse;
+ int req, error = 0;
+
+ mutex_spin_enter(&crypto_mtx);
+ for(req = 0; req < count; req++) {
+ cse = csefind(fcr, sesid[req]);
+ if (cse == NULL)
+ continue;
+ csedelete(fcr, cse);
+ error = csefree(cse);
+ }
+ mutex_spin_exit(&crypto_mtx);
+ return 0;
+}
+
+/*
+ * collect as many completed requests as are availble, or count completed 
requests
+ * whichever is less.
+ * return the number of requests.
+ */
+static int
+crypto_getmstatus(struct fcrypt *fcr, struct crypt_result_t *crypt_result, int 
count)
+{
+ struct cryptop *crp = NULL;
+ struct cryptkop *krp = NULL;
+ struct csession *cse;
+ int i, size, req = 0;
+ int completed=0;
+
+ /* On stack so nobody else can grab them -- no locking */
+ SLIST_HEAD(, cryptop) crp_delfree_l =
+ SLIST_HEAD_INITIALIZER(crp_delfree_l);
+ SLIST_HEAD(, cryptkop) krp_delfree_l =
+ SLIST_HEAD_INITIALIZER(krp_delfree_l);
+
+ mutex_spin_enter(&crypto_mtx);
+
+ /* at this point we do not know which response user is requesting for 
+ * (symmetric or asymmetric) so we copyout one from each i.e if the 
+ * count is 2 then 1 from symmetric and 1 from asymmetric queue and 
+ * if 3 then 2 symmetric and 1 asymmetric and so on */
+ for(; req < count ;) {
+ crp = TAILQ_FIRST(&fcr->crp_ret_mq);
+ if(crp) {
+ cse = (struct csession *)crp->crp_opaque;
+ crypt_result[req].rid = crp->crp_reqid;
+ crypt_result[req].opaque = crp->crp_usropaque;
+ completed++;
+ cse = csefind(fcr, cse->ses);
+ if (cse == NULL) {
+ DPRINTF(("csefind failed\n"));
+ crypt_result[req].status = EINVAL;
+ goto bail;
+ }
+ 
+ if (crp->crp_etype != 0) {
+ crypt_result[req].status = crp->crp_etype;
+ goto bail;
+ }
+
+ if (cse->error) {
+ crypt_result[req].status = cse->error;
+ goto bail;
+ }
+
+ if (crp->dst &&
+ (crypt_result[req].status = copyout
+ (crp->uio.uio_iov[0].iov_base,
+ crp->dst, crp->len)))
+ goto bail;
+
+ if (crp->mac &&
+ (crypt_result[req].status = copyout
+ (crp->crp_mac, crp->mac,
+ cse->thash->authsize)))
+ goto bail;
+bail:
+ TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next);
+ SLIST_INSERT_HEAD(&crp_delfree_l, crp,
+ crp_qun.crp_lnext);
+ req++;
+ }
+
+ if(req < count) {
+ krp = TAILQ_FIRST(&fcr->crp_ret_mkq);
+ if (krp) {
+ crypt_result[req].rid = krp->krp_reqid;
+ crypt_result[req].opaque = krp->krp_usropaque;
+ completed++;
+ if (krp->krp_status != 0) {
+ DPRINTF(("cryptodev_key: "
+ "krp->krp_status"
+ "0x%08x\n", krp->krp_status));
+ crypt_result[req].status =
+ krp->krp_status;
+ goto fail;
+ }
+
+ for (i = krp->krp_iparams; i < krp->krp_iparams
+ + krp->krp_oparams; i++) {
+ size = (krp->krp_param[i].crp_nbits
+ + 7) / 8;
+ if (size == 0)
+ continue;
+ crypt_result[req].status = copyout
+ (krp->krp_param[i].crp_p,
+ krp->crk_param[i].crp_p, size);
+ if (crypt_result[req].status) {
+ DPRINTF(("cryptodev_key: "
+ "copyout oparam "
+ "%d failed, "
+ "error=%d\n",
+ i-krp->krp_iparams, 
+ crypt_result[req].status));
+ goto fail;
+ }
+ }
+fail:
+ TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next);
+ /* not sure what to do for this */
+ /* kop[req].crk_status = krp->krp_status; */ 
+ SLIST_INSERT_HEAD(&krp_delfree_l, krp,
+ krp_qun.krp_lnext);
+ }
+ req++;
+ }
+ }
+ mutex_spin_exit(&crypto_mtx);
+
+ while(!SLIST_EMPTY(&crp_delfree_l)) {
+ crp = SLIST_FIRST(&crp_delfree_l);
+ SLIST_REMOVE_HEAD(&crp_delfree_l, crp_qun.crp_lnext);
+ kmem_free(crp->uio.uio_iov[0].iov_base,
+ crp->uio.uio_iov[0].iov_len);
+ crypto_freereq(crp);
+ }
+ 
+ while(!SLIST_EMPTY(&krp_delfree_l)) {
+ krp = SLIST_FIRST(&krp_delfree_l);
+ for (i = 0; i < CRK_MAXPARAM; i++) {
+ struct crparam *kp = &(krp->krp_param[i]);
+ if (kp->crp_p) {
+ size = (kp->crp_nbits + 7) / 8;
+ KASSERT(size > 0);
+ memset(kp->crp_p, 0, size);
+ kmem_free(kp->crp_p, size);
+ }
+ }
+ SLIST_REMOVE_HEAD(&krp_delfree_l, krp_qun.krp_lnext);
+ pool_put(&cryptkop_pool, krp);
+ }
+ return completed; 
+}
+
+static int
+crypto_getstatus (struct fcrypt *fcr, struct crypt_result_t *crypt_result)
+{
+ struct cryptop *crp = NULL;
+ struct cryptkop *krp = NULL;
+ struct csession *cse;
+ int i, size, req = 0;
+
+ mutex_spin_enter(&crypto_mtx); 
+ /* Here we dont know for which request the user is requesting the 
+ * response so checking in both the queues */
+ TAILQ_FOREACH(crp, &fcr->crp_ret_mq, crp_next) {
+ if(crp && (crp->crp_reqid == crypt_result->rid)) {
+ cse = (struct csession *)crp->crp_opaque;
+ crypt_result->opaque = crp->crp_usropaque;
+ cse = csefind(fcr, cse->ses);
+ if (cse == NULL) {
+ DPRINTF(("csefind failed\n"));
+ crypt_result->status = EINVAL;
+ goto bail;
+ }
+
+ if (crp->crp_etype != 0) {
+ crypt_result->status = crp->crp_etype;
+ goto bail;
+ }
+
+ if (cse->error) {
+ crypt_result->status = cse->error;
+ goto bail;
+ }
+
+ if (crp->dst &&
+ (crypt_result->status = copyout
+ (crp->uio.uio_iov[0].iov_base, 
+ crp->dst, crp->len)))
+ goto bail;
+ 
+ if (crp->mac &&
+ (crypt_result->status = copyout(crp->crp_mac, 
+ crp->mac, cse->thash->authsize)))
+ goto bail;
+bail:
+ TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next);
+
+ mutex_spin_exit(&crypto_mtx);
+ crypto_freereq(crp);
+ return 0;
+ }
+ }
+
+ TAILQ_FOREACH(krp, &fcr->crp_ret_mkq, krp_next) {
+ if(krp && (krp->krp_reqid == crypt_result->rid)) {
+ crypt_result[req].opaque = krp->krp_usropaque;
+ if (krp->krp_status != 0) {
+ DPRINTF(("cryptodev_key: "
+ "krp->krp_status 0x%08x\n", 
+ krp->krp_status));
+ crypt_result[req].status = krp->krp_status;
+ goto fail;
+ }
+
+ for (i = krp->krp_iparams; i < krp->krp_iparams 
+ + krp->krp_oparams; i++) {
+ size = (krp->krp_param[i].crp_nbits + 7) / 8;
+ if (size == 0)
+ continue;
+ crypt_result[req].status = copyout
+ (krp->krp_param[i].crp_p, 
+ krp->crk_param[i].crp_p, size);
+ if (crypt_result[req].status) {
+ DPRINTF(("cryptodev_key: copyout oparam"
+ "%d failed, error=%d\n", 
+ i-krp->krp_iparams, 
+ crypt_result[req].status));
+ goto fail;
+ }
+ }
+fail:
+ TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next);
+ mutex_spin_exit(&crypto_mtx);
+ /* not sure what to do for this */
+ /* kop[req].crk_status = krp->krp_status; */ 
+ for (i = 0; i < CRK_MAXPARAM; i++) {
+ struct crparam *kp = &(krp->krp_param[i]);
+ if (kp->crp_p) {
+ size = (kp->crp_nbits + 7) / 8;
+ KASSERT(size > 0);
+ memset(kp->crp_p, 0, size);
+ kmem_free(kp->crp_p, size);
+ }
+ }
+ pool_put(&cryptkop_pool, krp);
+ return 0;
+ }
+ }
+ mutex_spin_exit(&crypto_mtx);
+ return EINPROGRESS; 
+}
+
+static int 
+cryptof_poll(file_t *fp, int events, struct lwp *l)
+{
+ struct fcrypt *fcr = (struct fcrypt *)fp->f_data;
+
+ if (!(events & (POLLIN | POLLRDNORM))) {
+ /* only support read and POLLIN */
+ return 0;
+ }
+
+ if (TAILQ_EMPTY(&fcr->crp_ret_mq) && TAILQ_EMPTY(&fcr->crp_ret_mkq)) {
+ /* no completed requests pending,
+ * save the poll for later (for selnotify()). */
+ selrecord(l, &fcr->sinfo);
+ return 0;
+ } else {
+ /* let the app(s) know that there are completed requests */
+ return events & (POLLIN | POLLRDNORM);
+ }
+}
+
 /*
 * Pseudo-device initialization routine for /dev/crypto
 */
diff -r -u -p opencrypto.o/cryptodev.h opencrypto/cryptodev.h
--- opencrypto.o/cryptodev.h 2008年02月03日 19:35:34.000000000 -0500
+++ opencrypto/cryptodev.h 2008年03月27日 01:32:44.000000000 -0400
@@ -2,6 +2,42 @@
 /* $FreeBSD: src/sys/opencrypto/cryptodev.h,v 1.2.2.6 2003年07月02日 17:04:50 
sam Exp $ */
 /* $OpenBSD: cryptodev.h,v 1.33 2002年07月17日 23:52:39 art Exp $ */
 
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Coyote Point Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
 /*
 * The author of this code is Angelos D. Keromytis 
(angelos%cis.upenn.edu@localhost)
 *
@@ -121,6 +157,22 @@ struct session_op {
 u_int32_t ses; /* returns: session # */
 };
 
+/* to support multiple session creation */
+
+struct session_n_op {
+ u_int32_t cipher; /* ie. CRYPTO_DES_CBC */
+ u_int32_t mac; /* ie. CRYPTO_MD5_HMAC */
+
+ u_int32_t keylen; /* cipher key */
+ void * key;
+ int mackeylen; /* mac key */
+ void * mackey;
+
+ u_int32_t ses; /* returns: session # */
+ int status;
+ struct session_n_op * next; /* next pointer for multiple session */
+};
+
 struct crypt_op {
 u_int32_t ses;
 u_int16_t op; /* i.e. COP_ENCRYPT */
@@ -134,6 +186,57 @@ struct crypt_op {
 void * iv;
 };
 
+/* to support multiple session creation */
+/*
+ *
+ * The reqid field is filled when the operation has 
+ * been accepted and started, and can be used to later retrieve
+ * the operation results via CIOCNCRYPTRET or identify the 
+ * request in the completion list returned by CIOCNCRYPTRETM.
+ *
+ * The opaque pointer can be set arbitrarily by the user
+ * and it is passed back in the crypt_result_t structure
+ * when the request completes. This field can be used for example
+ * to track context for the request and avoid lookups in the
+ * user application.
+ */
+
+struct crypt_n_op {
+ u_int32_t ses;
+ u_int16_t op; /* i.e. COP_ENCRYPT */
+#define COP_ENCRYPT 1
+#define COP_DECRYPT 2
+ u_int16_t flags;
+#define COP_F_BATCH 0x0008 /* Dispatch as quickly as possible */
+ u_int len;
+
+ u_int32_t reqid; /* request id */
+ int status; /* status of request -accepted or not 
*/ 
+ void *opaque; /* opaque pointer returned to user */
+ u_int32_t keylen; /* cipher key - optional */
+ void * key;
+
+ void * src, *dst; /* become iov[] inside kernel */
+ void * mac; /* must be big enough for chosen MAC */
+ void * iv;
+};
+
+/* CIOCNCRYPTM ioctl argument, supporting one or more asynchronous
+ * crypto_n_op operations.
+ * Each crypo_n_op will receive a request id which can be used to check its
+ * status via CIOCNCRYPTRET, or to watch for its completion in the list
+ * obtained via CIOCNCRYPTRETM.
+ */
+struct crypto_mop {
+ size_t count; /* how many */
+ struct crypt_n_op * reqs; /* where to get them */
+};
+
+struct crypt_fnop {
+ size_t count;
+ u_int32_t *sesid;
+}; 
+
 #define CRYPTO_MAX_MAC_LEN 20
 
 /* bignum parameter, in packed bytes, ... */
@@ -152,6 +255,53 @@ struct crypt_kop {
 u_int crk_pad1;
 struct crparam crk_param[CRK_MAXPARAM];
 };
+
+/*
+ * Used with the CIOCNFKEYM ioctl.
+ *
+ * This structure allows the OCF to return a request id
+ * for each of the kop operations specified in the CIOCNFKEYM call.
+ * 
+ * The crk_opaque pointer can be arbitrarily set by the user
+ * and it is passed back in the crypt_result_t structure
+ * when the request completes. This field can be used for example
+ * to track context for the request and avoid lookups in the
+ * user application.
+ */
+struct crypt_n_kop {
+ u_int crk_op; /* ie. CRK_MOD_EXP or other */
+ u_int crk_status; /* return status */
+ u_short crk_iparams; /* # of input parameters */
+ u_short crk_oparams; /* # of output parameters */
+ u_int crk_pad1;
+ struct crparam crk_param[CRK_MAXPARAM];
+ u_int32_t reqid; /* request id */
+ int status; /* status of request -accepted or not */
+ void *crk_opaque; /* opaque pointer returned to user */
+};
+
+struct crypto_mkop {
+ size_t count; /* how many */
+ struct crypt_n_kop * reqs; /* where to get them */
+};
+
+/* Asynchronous key or crypto result.
+ * Note that the status will be set in the crypt_result_t structure,
+ * not in the original crypt_kop structure (crk_status).
+ */
+struct crypt_result_t {
+ u_int32_t rid; /* request id */
+ u_int32_t status; /* status of request: 0 if successful */
+ void * opaque; /* Opaque pointer from the user, passed 
along */
+};
+
+struct cryptret_t {
+ size_t count; /* space for how many */
+ struct crypt_result_t * results; /* where to put them */
+}; 
+
+
+/* Assymetric key operations */
 #define CRK_ALGORITM_MIN 0
 #define CRK_MOD_EXP 0
 #define CRK_MOD_EXP_CRT 1
@@ -178,6 +328,146 @@ struct crypt_kop {
 #define CRF_MOD_MULTINV (1 << CRK_MOD_MULTINV)
 #define CRF_MOD (1 << CRK_MOD)
 
+/**********************************************************************
+ 
+ IOCTL Request descriptions
+ 
+ CRIOGET int *fd
+ Clone the fd argument to ioctl(4), yielding a new file descrip-
+ tor which can be used to create crypto sessions and request
+ crypto operations.
+
+ CIOCGSESSION struct session_op *sessp
+ Persistently bind a file descriptor returned by a previous
+ CRIOGET to a session: that is, to the chosen privacy algorithm,
+ integrity algorithm, and keys specified in sessp. The special
+ value 0 for either privacy or integrity is reserved to indicate
+ that the indicated operation (privacy or integrity) is not
+ desired for this session.
+
+ For non-zero symmetric-key privacy algorithms, the privacy
+ algorithm must be specified in sess->cipher, the key length in
+ sessp->keylen, and the key value in the octets addressed by
+ sessp->key.
+
+ For keyed one-way hash algorithms, the one-way hash must be
+ specified in sessp->mac, the key length in sessp->mackey, and
+ the key value in the octets addressed by sessp->mackeylen.
+
+ Support for a specific combination of fused privacy and
+ integrity-check algorithms depends on whether the underlying
+ hardware supports that combination. Not all combinations are
+ supported by all hardware, even if the hardware supports each
+ operation as a stand-alone non-fused operation.
+
+ CIOCCRYPT struct crypt_op *cr_op
+ Request a symmetric-key (or unkeyed hash) operation. The file
+ descriptor argument to ioctl(4) must have been bound to a valid
+ session. To encrypt, set cr_op->op to COP_ENCRYPT. To
+ decrypt, set cr_op->op to COP_DECRYPT. The field cr_op->len
+ supplies the length of the input buffer; the fields cr_op->src,
+ cr_op->dst, cr_op->mac, cr_op->iv supply the addresses of the
+ input buffer, output buffer, one-way hash, and initialization
+ vector, respectively.
+
+ CIOCNCRYPTM struct crypto_mop *cr_mop
+ This is the asynchronous version of CIOCCRYPT, which allows 
+ multiple symmetric-key (or unkeyed hash) operations to be
+ started (see CIOCRYPT above for the details for each operation).
+ The cr_mop->count field specifies the number of operations
+ provided in the cr_mop->reqs array.
+
+ Each operation is assigned a unique request id returned in the
+ cr_mop->reqs[n].reqid field.
+
+ Each operation can accept an opaque value from the user to
+ be passed back to the user when the operation completes 
+ (e.g. to track context for the request). The opaque field
+ is cr_mop->reqs[n].opaque.
+
+ If a problem occurs with starting any of the operations then
+ that operation's cr_mop->reqs[n].status field is filled with
+ the error code. The failure of an operation does not prevent
+ the other operations from being started.
+
+
+ CIOCFSESSION u_int32_t *session
+ Destroys the specified /dev/crypto session associated with the
+ file-descriptor argument.
+
+ CIOCFNSESSION struct crypt_fnop *cr_fnop
+ Destroys the cr_fnop->count /dev/crypto sessions specified by
+ the crypt_fnop array of session identifiers.
+
+ Asymmetric-key commands
+ CIOCASSYMFEAT int *feature_mask
+ Returns a bitmask of supported asymmetric-key operations. Each
+ of the above-listed asymmetric operations is present if and
+ only if the bit position numbered by the code for that opera-
+ tion is set. For example, CRK_MOD_EXP is available if and only
+ if the bit (1 << CRK_MOD_EX) is set.
+
+ CIOCFKEY struct crypt_kop *kop
+ Performs an asymmetric-key operation from the list above. The
+ specific operation is supplied in kop->crk_op; final status for
+ the operation is returned in kop->crk_status. The number of
+ input arguments and the number of output arguments is specified
+ in kop->crk_iparams and kop->crk_iparams, respectively. The
+ field crk_param[] must be filled in with exactly
+ kop->crk_iparams + kop->crk_oparams arguments, each encoded as
+ a struct crparam (address, bitlength) pair.
+
+ CIOCNFKEYM struct crypt_mkop *mkop
+ This is the asynchronous version of CIOCKEY, which starts one 
+ or more key operations.
+ mkop->count specifies the number of key operations in the
+ mkop->reqs array.
+
+ Each operation is assigned a unique request id returned in the
+ mkop->reqs[n].reqid field.
+
+ Each operation accepts an opaque value from the user to
+ be passed back to the user when the operation completes 
+ (e.g. to track context for the request). The opaque field
+ is mkop->reqs[n].crk_opaque.
+
+ If a problem occurs with starting any of the operations then
+ that operation's mkop->reqs[n].status field is filled with
+ the error code. The failure of an operation does not prevent
+ the other operations from being started.
+
+ Asynchronous status commands
+ select() or poll() can be used to determine when /dev/crypto has completed
+ operations ready to be retrieved.
+
+ CIOCNCRYPTRET struct crypt_result_t *cres
+ Check for the status of the request specified by cres->rid.
+
+ The cres->status field is set as follows:
+ 0 - the request has completed, and its results have been 
+ copied out to the original crypt_op or crypt_kop structure
+ used to start the request. The copyout takes place during
+ this ioctl, so the calling process must be the process that
+ started the request.
+
+ EINPROGRESS - the request has not yet completed.
+
+ EINVAL - the request was not found.
+
+ Other values indicate a problem during the processing of 
+ the request.
+
+ CIOCNCRYPTRETM struct cryptret_t *cret
+ Retreive a number of completed requests. This ioctl accepts
+ a count and an array, and fills the array with up to count
+ completed requests. The array entries are described above
+ in the CIONCRYPTRET ioctl.
+
+ The cret->results[n].rid fields filled by this ioctl call.
+ The results may be mixed crypt_op and crypt_kop operations.
+
+**********************************************************************/
+
 /*
 * done against open of /dev/crypto, to get a cloned descriptor.
 * Please use F_SETFD against the cloned descriptor.
@@ -189,6 +479,12 @@ struct crypt_kop {
 #define CIOCFSESSION _IOW('c', 102, u_int32_t)
 #define CIOCCRYPT _IOWR('c', 103, struct crypt_op)
 #define CIOCKEY _IOWR('c', 104, struct crypt_kop)
+#define CIOCNSESSION _IOWR('c', 106, struct session_n_op)
+#define CIOCNCRYPTM _IOWR('c', 107, struct crypto_mop)
+#define CIOCNFKEYM _IOWR('c', 108, struct crypto_mkop)
+#define CIOCFNSESSION _IOW('c', 109, struct crypt_fnop)
+#define CIOCNCRYPTRETM _IOWR('c', 110, struct cryptret_t)
+#define CIOCNCRYPTRET _IOWR('c', 111, struct crypt_result_t)
 
 #define CIOCASYMFEAT _IOR('c', 105, u_int32_t)
 
@@ -257,9 +553,16 @@ struct cryptodesc {
 
 /* Structure describing complete operation */
 struct cryptop {
- TAILQ_ENTRY(cryptop) crp_next;
-
+ union {
+ TAILQ_ENTRY(cryptop) crp_tnext;
+ SLIST_ENTRY(cryptop) crp_lnext;
+ } crp_qun;
+#define crp_next crp_qun.crp_tnext /* XXX compat */
 u_int64_t crp_sid; /* Session ID */
+ 
+ u_int32_t crp_reqid; /* request id */
+ void * crp_usropaque; /* Opaque pointer from user, passed 
along */
+
 int crp_ilen; /* Input data total length */
 int crp_olen; /* Result total length */
 
@@ -293,6 +596,15 @@ struct cryptop {
 void * crp_mac;
 struct timespec crp_tstamp; /* performance time stamp */
 kcondvar_t crp_cv;
+ struct fcrypt *fcrp;
+ void * dst;
+ void * mac;
+ u_int len;
+ u_char tmp_iv[EALG_MAX_BLOCK_LEN];
+ u_char tmp_mac[CRYPTO_MAX_MAC_LEN];
+ 
+ struct iovec iovec[1];
+ struct uio uio;
 };
 
 #define CRYPTO_BUF_CONTIG 0x0
@@ -308,7 +620,14 @@ struct cryptop {
 #define CRYPTO_HINT_MORE 0x1 /* more ops coming shortly */
 
 struct cryptkop {
- TAILQ_ENTRY(cryptkop) krp_next;
+ union {
+ TAILQ_ENTRY(cryptkop) krp_tnext;
+ SLIST_ENTRY(cryptkop) krp_lnext;
+ } krp_qun;
+#define krp_next krp_qun.krp_tnext /* XXX compat */
+
+ u_int32_t krp_reqid; /* request id */
+ void * krp_usropaque; /* Opaque pointer from user, passed 
along */
 
 u_int krp_op; /* ie. CRK_MOD_EXP or other */
 u_int krp_status; /* return status */
@@ -319,6 +638,8 @@ struct cryptkop {
 int (*krp_callback)(struct cryptkop *);
 int krp_flags; /* same values as crp_flags */
 kcondvar_t krp_cv;
+ struct fcrypt *fcrp;
+ struct crparam crk_param[CRK_MAXPARAM];
 };
 
 /* Crypto capabilities structure */


Home | Main Index | Thread Index | Old Index

AltStyle によって変換されたページ (->オリジナル) /