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