[BACK]Return to cryptodev.c CVS log [TXT][DIR] Up to [local] / sys / crypto

Annotation of sys/crypto/cryptodev.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: cryptodev.c,v 1.66 2006/10/25 15:10:25 tedu Exp $     */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2001 Theo de Raadt
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms, with or without
        !             7:  * modification, are permitted provided that the following conditions
        !             8:  * are met:
        !             9:  *
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *   notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *   notice, this list of conditions and the following disclaimer in the
        !            14:  *   documentation and/or other materials provided with the distribution.
        !            15:  *
        !            16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            26:  *
        !            27:  * Effort sponsored in part by the Defense Advanced Research Projects
        !            28:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
        !            29:  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
        !            30:  *
        !            31:  */
        !            32:
        !            33: #include <sys/param.h>
        !            34: #include <sys/systm.h>
        !            35: #include <sys/malloc.h>
        !            36: #include <sys/mbuf.h>
        !            37: #include <sys/sysctl.h>
        !            38: #include <sys/file.h>
        !            39: #include <sys/filedesc.h>
        !            40: #include <sys/errno.h>
        !            41: #include <dev/rndvar.h>
        !            42: #include <sys/conf.h>
        !            43: #include <sys/device.h>
        !            44: #include <crypto/md5.h>
        !            45: #include <crypto/sha1.h>
        !            46: #include <crypto/rmd160.h>
        !            47: #include <crypto/cast.h>
        !            48: #include <crypto/skipjack.h>
        !            49: #include <crypto/blf.h>
        !            50: #include <crypto/cryptodev.h>
        !            51: #include <crypto/xform.h>
        !            52:
        !            53: extern struct cryptocap *crypto_drivers;
        !            54: extern int crypto_drivers_num;
        !            55:
        !            56: struct csession {
        !            57:        TAILQ_ENTRY(csession) next;
        !            58:        u_int64_t       sid;
        !            59:        u_int32_t       ses;
        !            60:
        !            61:        u_int32_t       cipher;
        !            62:        struct enc_xform *txform;
        !            63:        u_int32_t       mac;
        !            64:        struct auth_hash *thash;
        !            65:
        !            66:        caddr_t         key;
        !            67:        int             keylen;
        !            68:        u_char          tmp_iv[EALG_MAX_BLOCK_LEN];
        !            69:
        !            70:        caddr_t         mackey;
        !            71:        int             mackeylen;
        !            72:        u_char          tmp_mac[CRYPTO_MAX_MAC_LEN];
        !            73:
        !            74:        struct iovec    iovec[IOV_MAX];
        !            75:        struct uio      uio;
        !            76:        int             error;
        !            77: };
        !            78:
        !            79: struct fcrypt {
        !            80:        TAILQ_HEAD(csessionlist, csession) csessions;
        !            81:        int             sesn;
        !            82: };
        !            83:
        !            84: void   cryptoattach(int);
        !            85:
        !            86: int    cryptof_read(struct file *, off_t *, struct uio *, struct ucred *);
        !            87: int    cryptof_write(struct file *, off_t *, struct uio *, struct ucred *);
        !            88: int    cryptof_ioctl(struct file *, u_long, caddr_t, struct proc *p);
        !            89: int    cryptof_poll(struct file *, int, struct proc *);
        !            90: int    cryptof_kqfilter(struct file *, struct knote *);
        !            91: int    cryptof_stat(struct file *, struct stat *, struct proc *);
        !            92: int    cryptof_close(struct file *, struct proc *);
        !            93:
        !            94: static struct fileops cryptofops = {
        !            95:     cryptof_read,
        !            96:     cryptof_write,
        !            97:     cryptof_ioctl,
        !            98:     cryptof_poll,
        !            99:     cryptof_kqfilter,
        !           100:     cryptof_stat,
        !           101:     cryptof_close
        !           102: };
        !           103:
        !           104: struct csession *csefind(struct fcrypt *, u_int);
        !           105: int    csedelete(struct fcrypt *, struct csession *);
        !           106: struct csession *cseadd(struct fcrypt *, struct csession *);
        !           107: struct csession *csecreate(struct fcrypt *, u_int64_t, caddr_t, u_int64_t,
        !           108:     caddr_t, u_int64_t, u_int32_t, u_int32_t, struct enc_xform *,
        !           109:     struct auth_hash *);
        !           110: int    csefree(struct csession *);
        !           111:
        !           112: int    cryptodev_op(struct csession *, struct crypt_op *, struct proc *);
        !           113: int    cryptodev_key(struct crypt_kop *);
        !           114: int    cryptodev_dokey(struct crypt_kop *kop, struct crparam kvp[]);
        !           115:
        !           116: int    cryptodev_cb(struct cryptop *);
        !           117: int    cryptodevkey_cb(struct cryptkop *);
        !           118:
        !           119: int    usercrypto = 1;         /* userland may do crypto requests */
        !           120: int    userasymcrypto = 1;     /* userland may do asymmetric crypto reqs */
        !           121: int    cryptodevallowsoft = 0; /* only use hardware crypto */
        !           122:
        !           123: /* ARGSUSED */
        !           124: int
        !           125: cryptof_read(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
        !           126: {
        !           127:        return (EIO);
        !           128: }
        !           129:
        !           130: /* ARGSUSED */
        !           131: int
        !           132: cryptof_write(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
        !           133: {
        !           134:        return (EIO);
        !           135: }
        !           136:
        !           137: /* ARGSUSED */
        !           138: int
        !           139: cryptof_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
        !           140: {
        !           141:        struct cryptoini cria, crie;
        !           142:        struct fcrypt *fcr = fp->f_data;
        !           143:        struct csession *cse;
        !           144:        struct session_op *sop;
        !           145:        struct crypt_op *cop;
        !           146:        struct enc_xform *txform = NULL;
        !           147:        struct auth_hash *thash = NULL;
        !           148:        u_int64_t sid;
        !           149:        u_int32_t ses;
        !           150:        int error = 0;
        !           151:
        !           152:        switch (cmd) {
        !           153:        case CIOCGSESSION:
        !           154:                sop = (struct session_op *)data;
        !           155:                switch (sop->cipher) {
        !           156:                case 0:
        !           157:                        break;
        !           158:                case CRYPTO_DES_CBC:
        !           159:                        txform = &enc_xform_des;
        !           160:                        break;
        !           161:                case CRYPTO_3DES_CBC:
        !           162:                        txform = &enc_xform_3des;
        !           163:                        break;
        !           164:                case CRYPTO_BLF_CBC:
        !           165:                        txform = &enc_xform_blf;
        !           166:                        break;
        !           167:                case CRYPTO_CAST_CBC:
        !           168:                        txform = &enc_xform_cast5;
        !           169:                        break;
        !           170:                case CRYPTO_SKIPJACK_CBC:
        !           171:                        txform = &enc_xform_skipjack;
        !           172:                        break;
        !           173:                case CRYPTO_AES_CBC:
        !           174:                        txform = &enc_xform_rijndael128;
        !           175:                        break;
        !           176:                case CRYPTO_AES_CTR:
        !           177:                        txform = &enc_xform_aes_ctr;
        !           178:                        break;
        !           179:                case CRYPTO_ARC4:
        !           180:                        txform = &enc_xform_arc4;
        !           181:                        break;
        !           182:                case CRYPTO_NULL:
        !           183:                        txform = &enc_xform_null;
        !           184:                        break;
        !           185:                default:
        !           186:                        return (EINVAL);
        !           187:                }
        !           188:
        !           189:                switch (sop->mac) {
        !           190:                case 0:
        !           191:                        break;
        !           192: #if 0
        !           193:                case CRYPTO_MD5_HMAC:
        !           194:                        thash = &auth_hash_hmac_md5_96;
        !           195:                        break;
        !           196:                case CRYPTO_SHA1_HMAC:
        !           197:                        thash = &auth_hash_hmac_sha1_96;
        !           198:                        break;
        !           199:                case CRYPTO_RIPEMD160_HMAC:
        !           200:                        thash = &auth_hash_hmac_ripemd_160_96;
        !           201:                        break;
        !           202:                case CRYPTO_MD5:
        !           203:                        thash = &auth_hash_md5;
        !           204:                        break;
        !           205:                case CRYPTO_SHA1:
        !           206:                        thash = &auth_hash_sha1;
        !           207:                        break;
        !           208: #endif
        !           209:                default:
        !           210:                        return (EINVAL);
        !           211:                }
        !           212:
        !           213:                bzero(&crie, sizeof(crie));
        !           214:                bzero(&cria, sizeof(cria));
        !           215:
        !           216:                if (txform) {
        !           217:                        crie.cri_alg = txform->type;
        !           218:                        crie.cri_klen = sop->keylen * 8;
        !           219:                        if (sop->keylen > txform->maxkey ||
        !           220:                            sop->keylen < txform->minkey) {
        !           221:                                error = EINVAL;
        !           222:                                goto bail;
        !           223:                        }
        !           224:
        !           225:                        MALLOC(crie.cri_key, u_int8_t *,
        !           226:                            crie.cri_klen / 8, M_XDATA, M_WAITOK);
        !           227:                        if ((error = copyin(sop->key, crie.cri_key,
        !           228:                            crie.cri_klen / 8)))
        !           229:                                goto bail;
        !           230:                        if (thash)
        !           231:                                crie.cri_next = &cria;
        !           232:                }
        !           233:
        !           234:                if (thash) {
        !           235:                        cria.cri_alg = thash->type;
        !           236:                        cria.cri_klen = sop->mackeylen * 8;
        !           237:                        if (sop->mackeylen != thash->keysize) {
        !           238:                                error = EINVAL;
        !           239:                                goto bail;
        !           240:                        }
        !           241:
        !           242:                        if (cria.cri_klen) {
        !           243:                                MALLOC(cria.cri_key, u_int8_t *,
        !           244:                                    cria.cri_klen / 8, M_XDATA, M_WAITOK);
        !           245:                                if ((error = copyin(sop->mackey, cria.cri_key,
        !           246:                                    cria.cri_klen / 8)))
        !           247:                                        goto bail;
        !           248:                        }
        !           249:                }
        !           250:
        !           251:                error = crypto_newsession(&sid, (txform ? &crie : &cria),
        !           252:                    !cryptodevallowsoft);
        !           253:
        !           254:                if (error)
        !           255:                        goto bail;
        !           256:
        !           257:                cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
        !           258:                    cria.cri_key, cria.cri_klen, sop->cipher, sop->mac, txform,
        !           259:                    thash);
        !           260:
        !           261:                if (cse == NULL) {
        !           262:                        crypto_freesession(sid);
        !           263:                        error = EINVAL;
        !           264:                        goto bail;
        !           265:                }
        !           266:                sop->ses = cse->ses;
        !           267:
        !           268: bail:
        !           269:                if (error) {
        !           270:                        if (crie.cri_key)
        !           271:                                FREE(crie.cri_key, M_XDATA);
        !           272:                        if (cria.cri_key)
        !           273:                                FREE(cria.cri_key, M_XDATA);
        !           274:                }
        !           275:                break;
        !           276:        case CIOCFSESSION:
        !           277:                ses = *(u_int32_t *)data;
        !           278:                cse = csefind(fcr, ses);
        !           279:                if (cse == NULL)
        !           280:                        return (EINVAL);
        !           281:                csedelete(fcr, cse);
        !           282:                error = csefree(cse);
        !           283:                break;
        !           284:        case CIOCCRYPT:
        !           285:                cop = (struct crypt_op *)data;
        !           286:                cse = csefind(fcr, cop->ses);
        !           287:                if (cse == NULL)
        !           288:                        return (EINVAL);
        !           289:                error = cryptodev_op(cse, cop, p);
        !           290:                break;
        !           291:        case CIOCKEY:
        !           292:                error = cryptodev_key((struct crypt_kop *)data);
        !           293:                break;
        !           294:        case CIOCASYMFEAT:
        !           295:                error = crypto_getfeat((int *)data);
        !           296:                break;
        !           297:        default:
        !           298:                error = EINVAL;
        !           299:        }
        !           300:        return (error);
        !           301: }
        !           302:
        !           303: int
        !           304: cryptodev_op(struct csession *cse, struct crypt_op *cop, struct proc *p)
        !           305: {
        !           306:        struct cryptop *crp = NULL;
        !           307:        struct cryptodesc *crde = NULL, *crda = NULL;
        !           308:        int i, s, error;
        !           309:        u_int32_t hid;
        !           310:
        !           311:        if (cop->len > 64*1024-4)
        !           312:                return (E2BIG);
        !           313:
        !           314:        if (cse->txform) {
        !           315:                if (cop->len == 0 || (cop->len % cse->txform->blocksize) != 0)
        !           316:                        return (EINVAL);
        !           317:        }
        !           318:
        !           319:        bzero(&cse->uio, sizeof(cse->uio));
        !           320:        cse->uio.uio_iovcnt = 1;
        !           321:        cse->uio.uio_resid = 0;
        !           322:        cse->uio.uio_segflg = UIO_SYSSPACE;
        !           323:        cse->uio.uio_rw = UIO_WRITE;
        !           324:        cse->uio.uio_procp = p;
        !           325:        cse->uio.uio_iov = cse->iovec;
        !           326:        bzero(&cse->iovec, sizeof(cse->iovec));
        !           327:        cse->uio.uio_iov[0].iov_len = cop->len;
        !           328:        cse->uio.uio_iov[0].iov_base = malloc(cop->len, M_XDATA, M_WAITOK);
        !           329:        for (i = 0; i < cse->uio.uio_iovcnt; i++)
        !           330:                cse->uio.uio_resid += cse->uio.uio_iov[0].iov_len;
        !           331:
        !           332:        /* number of requests, not logical and */
        !           333:        crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL));
        !           334:        if (crp == NULL) {
        !           335:                error = ENOMEM;
        !           336:                goto bail;
        !           337:        }
        !           338:
        !           339:        if (cse->thash) {
        !           340:                crda = crp->crp_desc;
        !           341:                if (cse->txform)
        !           342:                        crde = crda->crd_next;
        !           343:        } else {
        !           344:                if (cse->txform)
        !           345:                        crde = crp->crp_desc;
        !           346:                else {
        !           347:                        error = EINVAL;
        !           348:                        goto bail;
        !           349:                }
        !           350:        }
        !           351:
        !           352:        if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len)))
        !           353:                goto bail;
        !           354:
        !           355:        if (crda) {
        !           356:                crda->crd_skip = 0;
        !           357:                crda->crd_len = cop->len;
        !           358:                crda->crd_inject = 0;   /* ??? */
        !           359:
        !           360:                crda->crd_alg = cse->mac;
        !           361:                crda->crd_key = cse->mackey;
        !           362:                crda->crd_klen = cse->mackeylen * 8;
        !           363:        }
        !           364:
        !           365:        if (crde) {
        !           366:                if (cop->op == COP_ENCRYPT)
        !           367:                        crde->crd_flags |= CRD_F_ENCRYPT;
        !           368:                else
        !           369:                        crde->crd_flags &= ~CRD_F_ENCRYPT;
        !           370:                crde->crd_len = cop->len;
        !           371:                crde->crd_inject = 0;
        !           372:
        !           373:                crde->crd_alg = cse->cipher;
        !           374:                crde->crd_key = cse->key;
        !           375:                crde->crd_klen = cse->keylen * 8;
        !           376:        }
        !           377:
        !           378:        crp->crp_ilen = cop->len;
        !           379:        crp->crp_buf = (caddr_t)&cse->uio;
        !           380:        crp->crp_callback = cryptodev_cb;
        !           381:        crp->crp_sid = cse->sid;
        !           382:        crp->crp_opaque = cse;
        !           383:
        !           384:        if (cop->iv) {
        !           385:                if (crde == NULL) {
        !           386:                        error = EINVAL;
        !           387:                        goto bail;
        !           388:                }
        !           389:                if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
        !           390:                        error = EINVAL;
        !           391:                        goto bail;
        !           392:                }
        !           393:                if ((error = copyin(cop->iv, cse->tmp_iv, cse->txform->blocksize)))
        !           394:                        goto bail;
        !           395:                bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize);
        !           396:                crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
        !           397:                crde->crd_skip = 0;
        !           398:        } else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
        !           399:                crde->crd_skip = 0;
        !           400:        } else if (crde) {
        !           401:                crde->crd_flags |= CRD_F_IV_PRESENT;
        !           402:                crde->crd_skip = cse->txform->blocksize;
        !           403:                crde->crd_len -= cse->txform->blocksize;
        !           404:        }
        !           405:
        !           406:        if (cop->mac) {
        !           407:                if (crda == NULL) {
        !           408:                        error = EINVAL;
        !           409:                        goto bail;
        !           410:                }
        !           411:                crp->crp_mac = cse->tmp_mac;
        !           412:        }
        !           413:
        !           414:        /* try the fast path first */
        !           415:        crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_NOQUEUE;
        !           416:        hid = (crp->crp_sid >> 32) & 0xffffffff;
        !           417:        if (hid >= crypto_drivers_num)
        !           418:                goto dispatch;
        !           419:        if (crypto_drivers[hid].cc_flags & CRYPTOCAP_F_SOFTWARE)
        !           420:                goto dispatch;
        !           421:        if (crypto_drivers[hid].cc_process == NULL)
        !           422:                goto dispatch;
        !           423:        error = crypto_drivers[hid].cc_process(crp);
        !           424:        if (error) {
        !           425:                /* clear error */
        !           426:                crp->crp_etype = 0;
        !           427:                goto dispatch;
        !           428:        }
        !           429:        goto processed;
        !           430:  dispatch:
        !           431:        crp->crp_flags = CRYPTO_F_IOV;
        !           432:        crypto_dispatch(crp);
        !           433:  processed:
        !           434:        s = splnet();
        !           435:        while (!(crp->crp_flags & CRYPTO_F_DONE)) {
        !           436:                error = tsleep(cse, PSOCK, "crydev", 0);
        !           437:        }
        !           438:        splx(s);
        !           439:        if (error) {
        !           440:                /* XXX can this happen?  if so, how do we recover? */
        !           441:                goto bail;
        !           442:        }
        !           443:
        !           444:        if (cse->error) {
        !           445:                error = cse->error;
        !           446:                goto bail;
        !           447:        }
        !           448:        if (crp->crp_etype != 0) {
        !           449:                error = crp->crp_etype;
        !           450:                goto bail;
        !           451:        }
        !           452:
        !           453:
        !           454:        if (cop->dst &&
        !           455:            (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, cop->len)))
        !           456:                goto bail;
        !           457:
        !           458:        if (cop->mac &&
        !           459:            (error = copyout(crp->crp_mac, cop->mac, cse->thash->authsize)))
        !           460:                goto bail;
        !           461:
        !           462: bail:
        !           463:        if (crp)
        !           464:                crypto_freereq(crp);
        !           465:        if (cse->uio.uio_iov[0].iov_base)
        !           466:                free(cse->uio.uio_iov[0].iov_base, M_XDATA);
        !           467:
        !           468:        return (error);
        !           469: }
        !           470:
        !           471: int
        !           472: cryptodev_cb(struct cryptop *crp)
        !           473: {
        !           474:        struct csession *cse = crp->crp_opaque;
        !           475:
        !           476:        cse->error = crp->crp_etype;
        !           477:        if (crp->crp_etype == EAGAIN) {
        !           478:                crp->crp_flags = CRYPTO_F_IOV;
        !           479:                return crypto_dispatch(crp);
        !           480:        }
        !           481:        wakeup(cse);
        !           482:        return (0);
        !           483: }
        !           484:
        !           485: int
        !           486: cryptodevkey_cb(struct cryptkop *krp)
        !           487: {
        !           488:
        !           489:        wakeup(krp);
        !           490:        return (0);
        !           491: }
        !           492:
        !           493: int
        !           494: cryptodev_key(struct crypt_kop *kop)
        !           495: {
        !           496:        struct cryptkop *krp = NULL;
        !           497:        int error = EINVAL;
        !           498:        int in, out, size, i;
        !           499:
        !           500:        if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
        !           501:                return (EFBIG);
        !           502:        }
        !           503:
        !           504:        in = kop->crk_iparams;
        !           505:        out = kop->crk_oparams;
        !           506:        switch (kop->crk_op) {
        !           507:        case CRK_MOD_EXP:
        !           508:                if (in == 3 && out == 1)
        !           509:                        break;
        !           510:                return (EINVAL);
        !           511:        case CRK_MOD_EXP_CRT:
        !           512:                if (in == 6 && out == 1)
        !           513:                        break;
        !           514:                return (EINVAL);
        !           515:        case CRK_DSA_SIGN:
        !           516:                if (in == 5 && out == 2)
        !           517:                        break;
        !           518:                return (EINVAL);
        !           519:        case CRK_DSA_VERIFY:
        !           520:                if (in == 7 && out == 0)
        !           521:                        break;
        !           522:                return (EINVAL);
        !           523:        case CRK_DH_COMPUTE_KEY:
        !           524:                if (in == 3 && out == 1)
        !           525:                        break;
        !           526:                return (EINVAL);
        !           527:        default:
        !           528:                return (EINVAL);
        !           529:        }
        !           530:
        !           531:        krp = malloc(sizeof *krp, M_XDATA, M_WAITOK);
        !           532:        bzero(krp, sizeof *krp);
        !           533:        krp->krp_op = kop->crk_op;
        !           534:        krp->krp_status = kop->crk_status;
        !           535:        krp->krp_iparams = kop->crk_iparams;
        !           536:        krp->krp_oparams = kop->crk_oparams;
        !           537:        krp->krp_status = 0;
        !           538:        krp->krp_callback = cryptodevkey_cb;
        !           539:
        !           540:        for (i = 0; i < CRK_MAXPARAM; i++) {
        !           541:                krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
        !           542:                if (kop->crk_param[i].crp_nbits > 65536) {
        !           543:                        /* XXX how big do we need to support? */
        !           544:                        goto fail;
        !           545:                }
        !           546:        }
        !           547:        for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
        !           548:                size = (krp->krp_param[i].crp_nbits + 7) / 8;
        !           549:                if (size == 0)
        !           550:                        continue;
        !           551:                krp->krp_param[i].crp_p = malloc(size, M_XDATA, M_WAITOK);
        !           552:                if (i >= krp->krp_iparams)
        !           553:                        continue;
        !           554:                error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size);
        !           555:                if (error)
        !           556:                        goto fail;
        !           557:        }
        !           558:
        !           559:        error = crypto_kdispatch(krp);
        !           560:        if (error)
        !           561:                goto fail;
        !           562:        error = tsleep(krp, PSOCK, "crydev", 0);
        !           563:        if (error) {
        !           564:                /* XXX can this happen?  if so, how do we recover? */
        !           565:                goto fail;
        !           566:        }
        !           567:
        !           568:        if (krp->krp_status != 0) {
        !           569:                error = krp->krp_status;
        !           570:                goto fail;
        !           571:        }
        !           572:
        !           573:        for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
        !           574:                size = (krp->krp_param[i].crp_nbits + 7) / 8;
        !           575:                if (size == 0)
        !           576:                        continue;
        !           577:                error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size);
        !           578:                if (error)
        !           579:                        goto fail;
        !           580:        }
        !           581:
        !           582: fail:
        !           583:        if (krp) {
        !           584:                kop->crk_status = krp->krp_status;
        !           585:                for (i = 0; i < CRK_MAXPARAM; i++) {
        !           586:                        if (krp->krp_param[i].crp_p)
        !           587:                                free(krp->krp_param[i].crp_p, M_XDATA);
        !           588:                }
        !           589:                free(krp, M_XDATA);
        !           590:        }
        !           591:        return (error);
        !           592: }
        !           593:
        !           594: /* ARGSUSED */
        !           595: int
        !           596: cryptof_poll(struct file *fp, int events, struct proc *p)
        !           597: {
        !           598:        return (0);
        !           599: }
        !           600:
        !           601: /* ARGSUSED */
        !           602: int
        !           603: cryptof_kqfilter(struct file *fp, struct knote *kn)
        !           604: {
        !           605:        return (0);
        !           606: }
        !           607:
        !           608: /* ARGSUSED */
        !           609: int
        !           610: cryptof_stat(struct file *fp, struct stat *sb, struct proc *p)
        !           611: {
        !           612:        return (EOPNOTSUPP);
        !           613: }
        !           614:
        !           615: /* ARGSUSED */
        !           616: int
        !           617: cryptof_close(struct file *fp, struct proc *p)
        !           618: {
        !           619:        struct fcrypt *fcr = fp->f_data;
        !           620:        struct csession *cse;
        !           621:
        !           622:        while ((cse = TAILQ_FIRST(&fcr->csessions))) {
        !           623:                TAILQ_REMOVE(&fcr->csessions, cse, next);
        !           624:                (void)csefree(cse);
        !           625:        }
        !           626:        FREE(fcr, M_XDATA);
        !           627:        fp->f_data = NULL;
        !           628:        return 0;
        !           629: }
        !           630:
        !           631: void
        !           632: cryptoattach(int n)
        !           633: {
        !           634: }
        !           635:
        !           636: int
        !           637: cryptoopen(dev_t dev, int flag, int mode, struct proc *p)
        !           638: {
        !           639:        if (usercrypto == 0)
        !           640:                return (ENXIO);
        !           641: #ifdef CRYPTO
        !           642:        return (0);
        !           643: #else
        !           644:        return (ENXIO);
        !           645: #endif
        !           646: }
        !           647:
        !           648: int
        !           649: cryptoclose(dev_t dev, int flag, int mode, struct proc *p)
        !           650: {
        !           651:        return (0);
        !           652: }
        !           653:
        !           654: int
        !           655: cryptoread(dev_t dev, struct uio *uio, int ioflag)
        !           656: {
        !           657:        return (EIO);
        !           658: }
        !           659:
        !           660: int
        !           661: cryptowrite(dev_t dev, struct uio *uio, int ioflag)
        !           662: {
        !           663:        return (EIO);
        !           664: }
        !           665:
        !           666: int
        !           667: cryptoioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
        !           668: {
        !           669:        struct file *f;
        !           670:        struct fcrypt *fcr;
        !           671:        int fd, error;
        !           672:
        !           673:        switch (cmd) {
        !           674:        case CRIOGET:
        !           675:                MALLOC(fcr, struct fcrypt *,
        !           676:                    sizeof(struct fcrypt), M_XDATA, M_WAITOK);
        !           677:                TAILQ_INIT(&fcr->csessions);
        !           678:                fcr->sesn = 0;
        !           679:
        !           680:                error = falloc(p, &f, &fd);
        !           681:                if (error) {
        !           682:                        FREE(fcr, M_XDATA);
        !           683:                        return (error);
        !           684:                }
        !           685:                f->f_flag = FREAD | FWRITE;
        !           686:                f->f_type = DTYPE_CRYPTO;
        !           687:                f->f_ops = &cryptofops;
        !           688:                f->f_data = fcr;
        !           689:                *(u_int32_t *)data = fd;
        !           690:                FILE_SET_MATURE(f);
        !           691:                break;
        !           692:        default:
        !           693:                error = EINVAL;
        !           694:                break;
        !           695:        }
        !           696:        return (error);
        !           697: }
        !           698:
        !           699: int
        !           700: cryptopoll(dev_t dev, int events, struct proc *p)
        !           701: {
        !           702:        return (seltrue(dev, events, p));
        !           703: }
        !           704:
        !           705: struct csession *
        !           706: csefind(struct fcrypt *fcr, u_int ses)
        !           707: {
        !           708:        struct csession *cse;
        !           709:
        !           710:        TAILQ_FOREACH(cse, &fcr->csessions, next)
        !           711:                if (cse->ses == ses)
        !           712:                        return (cse);
        !           713:        return (NULL);
        !           714: }
        !           715:
        !           716: int
        !           717: csedelete(struct fcrypt *fcr, struct csession *cse_del)
        !           718: {
        !           719:        struct csession *cse;
        !           720:
        !           721:        TAILQ_FOREACH(cse, &fcr->csessions, next) {
        !           722:                if (cse == cse_del) {
        !           723:                        TAILQ_REMOVE(&fcr->csessions, cse, next);
        !           724:                        return (1);
        !           725:                }
        !           726:        }
        !           727:        return (0);
        !           728: }
        !           729:
        !           730: struct csession *
        !           731: cseadd(struct fcrypt *fcr, struct csession *cse)
        !           732: {
        !           733:        TAILQ_INSERT_TAIL(&fcr->csessions, cse, next);
        !           734:        cse->ses = fcr->sesn++;
        !           735:        return (cse);
        !           736: }
        !           737:
        !           738: struct csession *
        !           739: csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen,
        !           740:     caddr_t mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac,
        !           741:     struct enc_xform *txform, struct auth_hash *thash)
        !           742: {
        !           743:        struct csession *cse;
        !           744:
        !           745:        MALLOC(cse, struct csession *, sizeof(struct csession),
        !           746:            M_XDATA, M_NOWAIT);
        !           747:        if (cse == NULL)
        !           748:                return NULL;
        !           749:        cse->key = key;
        !           750:        cse->keylen = keylen/8;
        !           751:        cse->mackey = mackey;
        !           752:        cse->mackeylen = mackeylen/8;
        !           753:        cse->sid = sid;
        !           754:        cse->cipher = cipher;
        !           755:        cse->mac = mac;
        !           756:        cse->txform = txform;
        !           757:        cse->thash = thash;
        !           758:        cseadd(fcr, cse);
        !           759:        return (cse);
        !           760: }
        !           761:
        !           762: int
        !           763: csefree(struct csession *cse)
        !           764: {
        !           765:        int error;
        !           766:
        !           767:        error = crypto_freesession(cse->sid);
        !           768:        if (cse->key)
        !           769:                FREE(cse->key, M_XDATA);
        !           770:        if (cse->mackey)
        !           771:                FREE(cse->mackey, M_XDATA);
        !           772:        FREE(cse, M_XDATA);
        !           773:        return (error);
        !           774: }

CVSweb