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