The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/opencrypto/cryptodev.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: eec2750237eb3a9c53efa733f81775e5


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.