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

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

1.1     ! nbrk        1: /*     $OpenBSD: crypto.c,v 1.48 2006/05/31 23:01:44 tedu Exp $        */
        !             2: /*
        !             3:  * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
        !             4:  *
        !             5:  * This code was written by Angelos D. Keromytis in Athens, Greece, in
        !             6:  * February 2000. Network Security Technologies Inc. (NSTI) kindly
        !             7:  * supported the development of this code.
        !             8:  *
        !             9:  * Copyright (c) 2000, 2001 Angelos D. Keromytis
        !            10:  *
        !            11:  * Permission to use, copy, and modify this software with or without fee
        !            12:  * is hereby granted, provided that this entire notice is included in
        !            13:  * all source code copies of any software which is or includes a copy or
        !            14:  * modification of this software.
        !            15:  *
        !            16:  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
        !            17:  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
        !            18:  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
        !            19:  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
        !            20:  * PURPOSE.
        !            21:  */
        !            22:
        !            23: #include <sys/param.h>
        !            24: #include <sys/systm.h>
        !            25: #include <sys/malloc.h>
        !            26: #include <sys/proc.h>
        !            27: #include <sys/pool.h>
        !            28: #include <crypto/cryptodev.h>
        !            29:
        !            30: struct cryptocap *crypto_drivers = NULL;
        !            31: int crypto_drivers_num = 0;
        !            32:
        !            33: struct pool cryptop_pool;
        !            34: struct pool cryptodesc_pool;
        !            35: int crypto_pool_initialized = 0;
        !            36:
        !            37: struct cryptop *crp_req_queue = NULL;
        !            38: struct cryptop **crp_req_queue_tail = NULL;
        !            39:
        !            40: struct cryptkop *krp_req_queue = NULL;
        !            41: struct cryptkop **krp_req_queue_tail = NULL;
        !            42:
        !            43: /*
        !            44:  * Create a new session.
        !            45:  */
        !            46: int
        !            47: crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int hard)
        !            48: {
        !            49:        u_int32_t hid, lid, hid2 = -1;
        !            50:        struct cryptocap *cpc;
        !            51:        struct cryptoini *cr;
        !            52:        int err, s, turn = 0;
        !            53:
        !            54:        if (crypto_drivers == NULL)
        !            55:                return EINVAL;
        !            56:
        !            57:        s = splvm();
        !            58:
        !            59:        /*
        !            60:         * The algorithm we use here is pretty stupid; just use the
        !            61:         * first driver that supports all the algorithms we need. Do
        !            62:         * a double-pass over all the drivers, ignoring software ones
        !            63:         * at first, to deal with cases of drivers that register after
        !            64:         * the software one(s) --- e.g., PCMCIA crypto cards.
        !            65:         *
        !            66:         * XXX We need more smarts here (in real life too, but that's
        !            67:         * XXX another story altogether).
        !            68:         */
        !            69:        do {
        !            70:                for (hid = 0; hid < crypto_drivers_num; hid++) {
        !            71:                        cpc = &crypto_drivers[hid];
        !            72:
        !            73:                        /*
        !            74:                         * If it's not initialized or has remaining sessions
        !            75:                         * referencing it, skip.
        !            76:                         */
        !            77:                        if (cpc->cc_newsession == NULL ||
        !            78:                            (cpc->cc_flags & CRYPTOCAP_F_CLEANUP))
        !            79:                                continue;
        !            80:
        !            81:                        if (cpc->cc_flags & CRYPTOCAP_F_SOFTWARE) {
        !            82:                                /*
        !            83:                                 * First round of search, ignore
        !            84:                                 * software drivers.
        !            85:                                 */
        !            86:                                if (turn == 0)
        !            87:                                        continue;
        !            88:                        } else { /* !CRYPTOCAP_F_SOFTWARE */
        !            89:                                /* Second round of search, only software. */
        !            90:                                if (turn == 1)
        !            91:                                        continue;
        !            92:                        }
        !            93:
        !            94:                        /* See if all the algorithms are supported. */
        !            95:                        for (cr = cri; cr; cr = cr->cri_next) {
        !            96:                                if (cpc->cc_alg[cr->cri_alg] == 0)
        !            97:                                        break;
        !            98:                        }
        !            99:
        !           100:                        /*
        !           101:                         * If even one algorithm is not supported,
        !           102:                         * keep searching.
        !           103:                         */
        !           104:                        if (cr != NULL)
        !           105:                                continue;
        !           106:
        !           107:                        /*
        !           108:                         * If we had a previous match, see how it compares
        !           109:                         * to this one. Keep "remembering" whichever is
        !           110:                         * the best of the two.
        !           111:                         */
        !           112:                        if (hid2 != -1) {
        !           113:                                /*
        !           114:                                 * Compare session numbers, pick the one
        !           115:                                 * with the lowest.
        !           116:                                 * XXX Need better metrics, this will
        !           117:                                 * XXX just do un-weighted round-robin.
        !           118:                                 */
        !           119:                                if (crypto_drivers[hid].cc_sessions <=
        !           120:                                    crypto_drivers[hid2].cc_sessions)
        !           121:                                        hid2 = hid;
        !           122:                        } else {
        !           123:                                /*
        !           124:                                 * Remember this one, for future
        !           125:                                  * comparisons.
        !           126:                                 */
        !           127:                                hid2 = hid;
        !           128:                        }
        !           129:                }
        !           130:
        !           131:                /*
        !           132:                 * If we found something worth remembering, leave. The
        !           133:                 * side-effect is that we will always prefer a hardware
        !           134:                 * driver over the software one.
        !           135:                 */
        !           136:                if (hid2 != -1)
        !           137:                        break;
        !           138:
        !           139:                turn++;
        !           140:
        !           141:                /* If we only want hardware drivers, don't do second pass. */
        !           142:        } while (turn <= 2 && hard == 0);
        !           143:
        !           144:        hid = hid2;
        !           145:
        !           146:        /*
        !           147:         * Can't do everything in one session.
        !           148:         *
        !           149:         * XXX Fix this. We need to inject a "virtual" session
        !           150:         * XXX layer right about here.
        !           151:         */
        !           152:
        !           153:        if (hid == -1) {
        !           154:                splx(s);
        !           155:                return EINVAL;
        !           156:        }
        !           157:
        !           158:        /* Call the driver initialization routine. */
        !           159:        lid = hid; /* Pass the driver ID. */
        !           160:        err = crypto_drivers[hid].cc_newsession(&lid, cri);
        !           161:        if (err == 0) {
        !           162:                (*sid) = hid;
        !           163:                (*sid) <<= 32;
        !           164:                (*sid) |= (lid & 0xffffffff);
        !           165:                crypto_drivers[hid].cc_sessions++;
        !           166:        }
        !           167:
        !           168:        splx(s);
        !           169:        return err;
        !           170: }
        !           171:
        !           172: /*
        !           173:  * Delete an existing session (or a reserved session on an unregistered
        !           174:  * driver).
        !           175:  */
        !           176: int
        !           177: crypto_freesession(u_int64_t sid)
        !           178: {
        !           179:        int err = 0, s;
        !           180:        u_int32_t hid;
        !           181:
        !           182:        if (crypto_drivers == NULL)
        !           183:                return EINVAL;
        !           184:
        !           185:        /* Determine two IDs. */
        !           186:        hid = (sid >> 32) & 0xffffffff;
        !           187:
        !           188:        if (hid >= crypto_drivers_num)
        !           189:                return ENOENT;
        !           190:
        !           191:        s = splvm();
        !           192:
        !           193:        if (crypto_drivers[hid].cc_sessions)
        !           194:                crypto_drivers[hid].cc_sessions--;
        !           195:
        !           196:        /* Call the driver cleanup routine, if available. */
        !           197:        if (crypto_drivers[hid].cc_freesession)
        !           198:                err = crypto_drivers[hid].cc_freesession(sid);
        !           199:
        !           200:        /*
        !           201:         * If this was the last session of a driver marked as invalid,
        !           202:         * make the entry available for reuse.
        !           203:         */
        !           204:        if ((crypto_drivers[hid].cc_flags & CRYPTOCAP_F_CLEANUP) &&
        !           205:            crypto_drivers[hid].cc_sessions == 0)
        !           206:                bzero(&crypto_drivers[hid], sizeof(struct cryptocap));
        !           207:
        !           208:        splx(s);
        !           209:        return err;
        !           210: }
        !           211:
        !           212: /*
        !           213:  * Find an empty slot.
        !           214:  */
        !           215: int32_t
        !           216: crypto_get_driverid(u_int8_t flags)
        !           217: {
        !           218:        struct cryptocap *newdrv;
        !           219:        int i, s;
        !           220:
        !           221:        s = splvm();
        !           222:
        !           223:        if (crypto_drivers_num == 0) {
        !           224:                crypto_drivers_num = CRYPTO_DRIVERS_INITIAL;
        !           225:                crypto_drivers = malloc(crypto_drivers_num *
        !           226:                    sizeof(struct cryptocap), M_CRYPTO_DATA, M_NOWAIT);
        !           227:                if (crypto_drivers == NULL) {
        !           228:                        crypto_drivers_num = 0;
        !           229:                        splx(s);
        !           230:                        return -1;
        !           231:                }
        !           232:
        !           233:                bzero(crypto_drivers, crypto_drivers_num *
        !           234:                    sizeof(struct cryptocap));
        !           235:        }
        !           236:
        !           237:        for (i = 0; i < crypto_drivers_num; i++) {
        !           238:                if (crypto_drivers[i].cc_process == NULL &&
        !           239:                    !(crypto_drivers[i].cc_flags & CRYPTOCAP_F_CLEANUP) &&
        !           240:                    crypto_drivers[i].cc_sessions == 0) {
        !           241:                        crypto_drivers[i].cc_sessions = 1; /* Mark */
        !           242:                        crypto_drivers[i].cc_flags = flags;
        !           243:                        splx(s);
        !           244:                        return i;
        !           245:                }
        !           246:        }
        !           247:
        !           248:        /* Out of entries, allocate some more. */
        !           249:        if (i == crypto_drivers_num) {
        !           250:                /* Be careful about wrap-around. */
        !           251:                if (2 * crypto_drivers_num <= crypto_drivers_num) {
        !           252:                        splx(s);
        !           253:                        return -1;
        !           254:                }
        !           255:
        !           256:                newdrv = malloc(2 * crypto_drivers_num *
        !           257:                    sizeof(struct cryptocap), M_CRYPTO_DATA, M_NOWAIT);
        !           258:                if (newdrv == NULL) {
        !           259:                        splx(s);
        !           260:                        return -1;
        !           261:                }
        !           262:
        !           263:                bcopy(crypto_drivers, newdrv,
        !           264:                    crypto_drivers_num * sizeof(struct cryptocap));
        !           265:                bzero(&newdrv[crypto_drivers_num],
        !           266:                    crypto_drivers_num * sizeof(struct cryptocap));
        !           267:
        !           268:                newdrv[i].cc_sessions = 1; /* Mark */
        !           269:                newdrv[i].cc_flags = flags;
        !           270:                crypto_drivers_num *= 2;
        !           271:
        !           272:                free(crypto_drivers, M_CRYPTO_DATA);
        !           273:                crypto_drivers = newdrv;
        !           274:                splx(s);
        !           275:                return i;
        !           276:        }
        !           277:
        !           278:        /* Shouldn't really get here... */
        !           279:        splx(s);
        !           280:        return -1;
        !           281: }
        !           282:
        !           283: /*
        !           284:  * Register a crypto driver. It should be called once for each algorithm
        !           285:  * supported by the driver.
        !           286:  */
        !           287: int
        !           288: crypto_kregister(u_int32_t driverid, int *kalg,
        !           289:     int (*kprocess)(struct cryptkop *))
        !           290: {
        !           291:        int s, i;
        !           292:
        !           293:        if (driverid >= crypto_drivers_num || kalg  == NULL ||
        !           294:            crypto_drivers == NULL)
        !           295:                return EINVAL;
        !           296:
        !           297:        s = splvm();
        !           298:
        !           299:        for (i = 0; i < CRK_ALGORITHM_MAX; i++) {
        !           300:                /*
        !           301:                 * XXX Do some performance testing to determine
        !           302:                 * placing.  We probably need an auxiliary data
        !           303:                 * structure that describes relative performances.
        !           304:                 */
        !           305:
        !           306:                crypto_drivers[driverid].cc_kalg[i] = kalg[i];
        !           307:        }
        !           308:
        !           309:        crypto_drivers[driverid].cc_kprocess = kprocess;
        !           310:
        !           311:        splx(s);
        !           312:        return 0;
        !           313: }
        !           314:
        !           315: /* Register a crypto driver. */
        !           316: int
        !           317: crypto_register(u_int32_t driverid, int *alg,
        !           318:     int (*newses)(u_int32_t *, struct cryptoini *),
        !           319:     int (*freeses)(u_int64_t), int (*process)(struct cryptop *))
        !           320: {
        !           321:        int s, i;
        !           322:
        !           323:
        !           324:        if (driverid >= crypto_drivers_num || alg == NULL ||
        !           325:            crypto_drivers == NULL)
        !           326:                return EINVAL;
        !           327:
        !           328:        s = splvm();
        !           329:
        !           330:        for (i = 0; i < CRYPTO_ALGORITHM_ALL; i++) {
        !           331:                /*
        !           332:                 * XXX Do some performance testing to determine
        !           333:                 * placing.  We probably need an auxiliary data
        !           334:                 * structure that describes relative performances.
        !           335:                 */
        !           336:
        !           337:                crypto_drivers[driverid].cc_alg[i] = alg[i];
        !           338:        }
        !           339:
        !           340:
        !           341:        crypto_drivers[driverid].cc_newsession = newses;
        !           342:        crypto_drivers[driverid].cc_process = process;
        !           343:        crypto_drivers[driverid].cc_freesession = freeses;
        !           344:        crypto_drivers[driverid].cc_sessions = 0; /* Unmark */
        !           345:
        !           346:        splx(s);
        !           347:
        !           348:        return 0;
        !           349: }
        !           350:
        !           351: /*
        !           352:  * Unregister a crypto driver. If there are pending sessions using it,
        !           353:  * leave enough information around so that subsequent calls using those
        !           354:  * sessions will correctly detect the driver being unregistered and reroute
        !           355:  * the request.
        !           356:  */
        !           357: int
        !           358: crypto_unregister(u_int32_t driverid, int alg)
        !           359: {
        !           360:        int i = CRYPTO_ALGORITHM_MAX + 1, s;
        !           361:        u_int32_t ses;
        !           362:
        !           363:        s = splvm();
        !           364:
        !           365:        /* Sanity checks. */
        !           366:        if (driverid >= crypto_drivers_num || crypto_drivers == NULL ||
        !           367:            ((alg <= 0 || alg > CRYPTO_ALGORITHM_MAX) &&
        !           368:                alg != CRYPTO_ALGORITHM_ALL) ||
        !           369:            crypto_drivers[driverid].cc_alg[alg] == 0) {
        !           370:                splx(s);
        !           371:                return EINVAL;
        !           372:        }
        !           373:
        !           374:        if (alg != CRYPTO_ALGORITHM_ALL) {
        !           375:                crypto_drivers[driverid].cc_alg[alg] = 0;
        !           376:
        !           377:                /* Was this the last algorithm ? */
        !           378:                for (i = 1; i <= CRYPTO_ALGORITHM_MAX; i++)
        !           379:                        if (crypto_drivers[driverid].cc_alg[i] != 0)
        !           380:                                break;
        !           381:        }
        !           382:
        !           383:        /*
        !           384:         * If a driver unregistered its last algorithm or all of them
        !           385:         * (alg == CRYPTO_ALGORITHM_ALL), cleanup its entry.
        !           386:         */
        !           387:        if (i == CRYPTO_ALGORITHM_MAX + 1 || alg == CRYPTO_ALGORITHM_ALL) {
        !           388:                ses = crypto_drivers[driverid].cc_sessions;
        !           389:                bzero(&crypto_drivers[driverid], sizeof(struct cryptocap));
        !           390:                if (ses != 0) {
        !           391:                        /*
        !           392:                         * If there are pending sessions, just mark as invalid.
        !           393:                         */
        !           394:                        crypto_drivers[driverid].cc_flags |= CRYPTOCAP_F_CLEANUP;
        !           395:                        crypto_drivers[driverid].cc_sessions = ses;
        !           396:                }
        !           397:        }
        !           398:        splx(s);
        !           399:        return 0;
        !           400: }
        !           401:
        !           402: /*
        !           403:  * Add crypto request to a queue, to be processed by a kernel thread.
        !           404:  */
        !           405: int
        !           406: crypto_dispatch(struct cryptop *crp)
        !           407: {
        !           408:        int s;
        !           409:        u_int32_t hid;
        !           410:
        !           411:        s = splvm();
        !           412:        /*
        !           413:         * Keep track of ops per driver, for coallescing purposes. If
        !           414:         * we have been given an invalid hid, we'll deal with in the
        !           415:         * crypto_invoke(), through session migration.
        !           416:         */
        !           417:        hid = (crp->crp_sid >> 32) & 0xffffffff;
        !           418:        if (hid < crypto_drivers_num)
        !           419:                crypto_drivers[hid].cc_queued++;
        !           420:
        !           421:        crp->crp_next = NULL;
        !           422:        if (crp_req_queue == NULL) {
        !           423:                crp_req_queue = crp;
        !           424:                crp_req_queue_tail = &(crp->crp_next);
        !           425:                splx(s);
        !           426:                wakeup(&crp_req_queue); /* Shared wait channel. */
        !           427:        } else {
        !           428:                *crp_req_queue_tail = crp;
        !           429:                crp_req_queue_tail = &(crp->crp_next);
        !           430:                splx(s);
        !           431:        }
        !           432:        return 0;
        !           433: }
        !           434:
        !           435: int
        !           436: crypto_kdispatch(struct cryptkop *krp)
        !           437: {
        !           438:        int s;
        !           439:
        !           440:        s = splvm();
        !           441:
        !           442:        krp->krp_next = NULL;
        !           443:        if (krp_req_queue == NULL) {
        !           444:                krp_req_queue = krp;
        !           445:                krp_req_queue_tail = &(krp->krp_next);
        !           446:                splx(s);
        !           447:                wakeup(&crp_req_queue); /* Shared wait channel. */
        !           448:        } else {
        !           449:                *krp_req_queue_tail = krp;
        !           450:                krp_req_queue_tail = &(krp->krp_next);
        !           451:                splx(s);
        !           452:        }
        !           453:        return 0;
        !           454: }
        !           455:
        !           456: /*
        !           457:  * Dispatch an asymmetric crypto request to the appropriate crypto devices.
        !           458:  */
        !           459: int
        !           460: crypto_kinvoke(struct cryptkop *krp)
        !           461: {
        !           462:        extern int cryptodevallowsoft;
        !           463:        u_int32_t hid;
        !           464:        int error;
        !           465:
        !           466:        /* Sanity checks. */
        !           467:        if (krp == NULL || krp->krp_callback == NULL)
        !           468:                return (EINVAL);
        !           469:
        !           470:        for (hid = 0; hid < crypto_drivers_num; hid++) {
        !           471:                if ((crypto_drivers[hid].cc_flags & CRYPTOCAP_F_SOFTWARE) &&
        !           472:                    cryptodevallowsoft == 0)
        !           473:                        continue;
        !           474:                if (crypto_drivers[hid].cc_kprocess == NULL)
        !           475:                        continue;
        !           476:                if ((crypto_drivers[hid].cc_kalg[krp->krp_op] &
        !           477:                    CRYPTO_ALG_FLAG_SUPPORTED) == 0)
        !           478:                        continue;
        !           479:                break;
        !           480:        }
        !           481:
        !           482:        if (hid == crypto_drivers_num) {
        !           483:                krp->krp_status = ENODEV;
        !           484:                crypto_kdone(krp);
        !           485:                return (0);
        !           486:        }
        !           487:
        !           488:        krp->krp_hid = hid;
        !           489:
        !           490:        crypto_drivers[hid].cc_koperations++;
        !           491:
        !           492:        error = crypto_drivers[hid].cc_kprocess(krp);
        !           493:        if (error) {
        !           494:                krp->krp_status = error;
        !           495:                crypto_kdone(krp);
        !           496:        }
        !           497:        return (0);
        !           498: }
        !           499:
        !           500: /*
        !           501:  * Dispatch a crypto request to the appropriate crypto devices.
        !           502:  */
        !           503: int
        !           504: crypto_invoke(struct cryptop *crp)
        !           505: {
        !           506:        struct cryptodesc *crd;
        !           507:        u_int64_t nid;
        !           508:        u_int32_t hid;
        !           509:        int error;
        !           510:
        !           511:        /* Sanity checks. */
        !           512:        if (crp == NULL || crp->crp_callback == NULL)
        !           513:                return EINVAL;
        !           514:
        !           515:        if (crp->crp_desc == NULL || crypto_drivers == NULL) {
        !           516:                crp->crp_etype = EINVAL;
        !           517:                crypto_done(crp);
        !           518:                return 0;
        !           519:        }
        !           520:
        !           521:        hid = (crp->crp_sid >> 32) & 0xffffffff;
        !           522:        if (hid >= crypto_drivers_num)
        !           523:                goto migrate;
        !           524:
        !           525:        crypto_drivers[hid].cc_queued--;
        !           526:
        !           527:        if (crypto_drivers[hid].cc_flags & CRYPTOCAP_F_CLEANUP) {
        !           528:                crypto_freesession(crp->crp_sid);
        !           529:                goto migrate;
        !           530:        }
        !           531:
        !           532:        if (crypto_drivers[hid].cc_process == NULL)
        !           533:                goto migrate;
        !           534:
        !           535:        crypto_drivers[hid].cc_operations++;
        !           536:        crypto_drivers[hid].cc_bytes += crp->crp_ilen;
        !           537:
        !           538:        error = crypto_drivers[hid].cc_process(crp);
        !           539:        if (error) {
        !           540:                if (error == ERESTART) {
        !           541:                        /* Unregister driver and migrate session. */
        !           542:                        crypto_unregister(hid, CRYPTO_ALGORITHM_ALL);
        !           543:                        goto migrate;
        !           544:                } else {
        !           545:                        crp->crp_etype = error;
        !           546:                        crypto_done(crp);
        !           547:                }
        !           548:        }
        !           549:
        !           550:        return 0;
        !           551:
        !           552:  migrate:
        !           553:        /* Migrate session. */
        !           554:        for (crd = crp->crp_desc; crd->crd_next; crd = crd->crd_next)
        !           555:                crd->CRD_INI.cri_next = &(crd->crd_next->CRD_INI);
        !           556:
        !           557:        if (crypto_newsession(&nid, &(crp->crp_desc->CRD_INI), 0) == 0)
        !           558:                crp->crp_sid = nid;
        !           559:
        !           560:        crp->crp_etype = EAGAIN;
        !           561:        crypto_done(crp);
        !           562:        return 0;
        !           563: }
        !           564:
        !           565: /*
        !           566:  * Release a set of crypto descriptors.
        !           567:  */
        !           568: void
        !           569: crypto_freereq(struct cryptop *crp)
        !           570: {
        !           571:        struct cryptodesc *crd;
        !           572:        int s;
        !           573:
        !           574:        if (crp == NULL)
        !           575:                return;
        !           576:
        !           577:        s = splvm();
        !           578:
        !           579:        while ((crd = crp->crp_desc) != NULL) {
        !           580:                crp->crp_desc = crd->crd_next;
        !           581:                pool_put(&cryptodesc_pool, crd);
        !           582:        }
        !           583:
        !           584:        pool_put(&cryptop_pool, crp);
        !           585:        splx(s);
        !           586: }
        !           587:
        !           588: /*
        !           589:  * Acquire a set of crypto descriptors.
        !           590:  */
        !           591: struct cryptop *
        !           592: crypto_getreq(int num)
        !           593: {
        !           594:        struct cryptodesc *crd;
        !           595:        struct cryptop *crp;
        !           596:        int s;
        !           597:
        !           598:        s = splvm();
        !           599:
        !           600:        if (crypto_pool_initialized == 0) {
        !           601:                pool_init(&cryptop_pool, sizeof(struct cryptop), 0, 0,
        !           602:                    0, "cryptop", NULL);
        !           603:                pool_init(&cryptodesc_pool, sizeof(struct cryptodesc), 0, 0,
        !           604:                    0, "cryptodesc", NULL);
        !           605:                crypto_pool_initialized = 1;
        !           606:        }
        !           607:
        !           608:        crp = pool_get(&cryptop_pool, PR_NOWAIT);
        !           609:        if (crp == NULL) {
        !           610:                splx(s);
        !           611:                return NULL;
        !           612:        }
        !           613:        bzero(crp, sizeof(struct cryptop));
        !           614:
        !           615:        while (num--) {
        !           616:                crd = pool_get(&cryptodesc_pool, PR_NOWAIT);
        !           617:                if (crd == NULL) {
        !           618:                        splx(s);
        !           619:                        crypto_freereq(crp);
        !           620:                        return NULL;
        !           621:                }
        !           622:
        !           623:                bzero(crd, sizeof(struct cryptodesc));
        !           624:                crd->crd_next = crp->crp_desc;
        !           625:                crp->crp_desc = crd;
        !           626:        }
        !           627:
        !           628:        splx(s);
        !           629:        return crp;
        !           630: }
        !           631:
        !           632: /*
        !           633:  * Crypto thread, runs as a kernel thread to process crypto requests.
        !           634:  */
        !           635: void
        !           636: crypto_thread(void)
        !           637: {
        !           638:        struct cryptop *crp;
        !           639:        struct cryptkop *krp;
        !           640:        int s;
        !           641:
        !           642:        s = splvm();
        !           643:
        !           644:        for (;;) {
        !           645:                crp = crp_req_queue;
        !           646:                krp = krp_req_queue;
        !           647:                if (crp == NULL && krp == NULL) {
        !           648:                        (void)tsleep(&crp_req_queue, PLOCK, "crypto_wait", 0);
        !           649:                        continue;
        !           650:                }
        !           651:
        !           652:                if (crp) {
        !           653:                        /* Remove from the queue. */
        !           654:                        crp_req_queue = crp->crp_next;
        !           655:                        crypto_invoke(crp);
        !           656:                }
        !           657:                if (krp) {
        !           658:                        /* Remove from the queue. */
        !           659:                        krp_req_queue = krp->krp_next;
        !           660:                        crypto_kinvoke(krp);
        !           661:                }
        !           662:        }
        !           663: }
        !           664:
        !           665: /*
        !           666:  * Invoke the callback on behalf of the driver.
        !           667:  */
        !           668: void
        !           669: crypto_done(struct cryptop *crp)
        !           670: {
        !           671:        crp->crp_flags |= CRYPTO_F_DONE;
        !           672:        crp->crp_callback(crp);
        !           673: }
        !           674:
        !           675: /*
        !           676:  * Invoke the callback on behalf of the driver.
        !           677:  */
        !           678: void
        !           679: crypto_kdone(struct cryptkop *krp)
        !           680: {
        !           681:        krp->krp_callback(krp);
        !           682: }
        !           683:
        !           684: int
        !           685: crypto_getfeat(int *featp)
        !           686: {
        !           687:        extern int cryptodevallowsoft, userasymcrypto;
        !           688:        int hid, kalg, feat = 0;
        !           689:
        !           690:        if (userasymcrypto == 0)
        !           691:                goto out;
        !           692:        for (hid = 0; hid < crypto_drivers_num; hid++) {
        !           693:                if ((crypto_drivers[hid].cc_flags & CRYPTOCAP_F_SOFTWARE) &&
        !           694:                    cryptodevallowsoft == 0) {
        !           695:                        continue;
        !           696:                }
        !           697:                if (crypto_drivers[hid].cc_kprocess == NULL)
        !           698:                        continue;
        !           699:                for (kalg = 0; kalg < CRK_ALGORITHM_MAX; kalg++)
        !           700:                        if ((crypto_drivers[hid].cc_kalg[kalg] &
        !           701:                            CRYPTO_ALG_FLAG_SUPPORTED) != 0)
        !           702:                                feat |=  1 << kalg;
        !           703:        }
        !           704: out:
        !           705:        *featp = feat;
        !           706:        return (0);
        !           707: }

CVSweb