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