tech-kern 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