1 /* $FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.41 2009/09/04 09:48:18 pjd Exp $ */ 2 /* $OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt Exp $ */ 3 4 /*- 5 * Copyright (c) 2001 Theo de Raadt 6 * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting 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 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/malloc.h> 39 #include <sys/device.h> 40 #include <sys/mbuf.h> 41 #include <sys/lock.h> 42 #include <sys/sysctl.h> 43 #include <sys/file.h> 44 #include <sys/filedesc.h> 45 #include <sys/errno.h> 46 #include <sys/uio.h> 47 #include <sys/random.h> 48 #include <sys/conf.h> 49 #include <sys/module.h> 50 #include <sys/kernel.h> 51 #include <sys/fcntl.h> 52 #include <sys/proc.h> 53 54 #include <sys/file2.h> 55 56 #include <opencrypto/cryptodev.h> 57 #include <opencrypto/xform.h> 58 59 struct csession { 60 TAILQ_ENTRY(csession) next; 61 u_int64_t sid; 62 u_int32_t ses; 63 struct lock lock; 64 65 u_int32_t cipher; 66 struct enc_xform *txform; 67 u_int32_t mac; 68 struct auth_hash *thash; 69 70 caddr_t key; 71 int keylen; 72 u_char tmp_iv[EALG_MAX_BLOCK_LEN]; 73 74 caddr_t mackey; 75 int mackeylen; 76 77 struct iovec iovec; 78 struct uio uio; 79 int error; 80 uint32_t busy; 81 }; 82 83 struct fcrypt { 84 TAILQ_HEAD(csessionlist, csession) csessions; 85 int sesn; 86 }; 87 88 static int cryptof_rw(struct file *fp, struct uio *uio, 89 struct ucred *cred, int flags); 90 static int cryptof_ioctl(struct file *, u_long, caddr_t, 91 struct ucred *, struct sysmsg *); 92 static int cryptof_kqfilter(struct file *, struct knote *); 93 static int cryptof_stat(struct file *, struct stat *, struct ucred *); 94 static int cryptof_close(struct file *); 95 96 static struct fileops cryptofops = { 97 .fo_read = cryptof_rw, 98 .fo_write = cryptof_rw, 99 .fo_ioctl = cryptof_ioctl, 100 .fo_kqfilter = cryptof_kqfilter, 101 .fo_stat = cryptof_stat, 102 .fo_close = cryptof_close, 103 .fo_shutdown = nofo_shutdown 104 }; 105 106 static struct csession *csefind(struct fcrypt *, u_int, int *); 107 static void csedrop(struct csession *); 108 static int csedelete(struct fcrypt *, struct csession *); 109 static struct csession *cseadd(struct fcrypt *, struct csession *); 110 static struct csession *csecreate(struct fcrypt *, u_int64_t, caddr_t, 111 u_int64_t, caddr_t, u_int64_t, u_int32_t, u_int32_t, struct enc_xform *, 112 struct auth_hash *); 113 static int csefree(struct csession *); 114 115 static int cryptodev_op(struct csession *, struct crypt_op *, struct ucred *); 116 static int cryptodev_key(struct crypt_kop *); 117 static int cryptodev_find(struct crypt_find_op *); 118 119 static struct lock cryptodev_lock = LOCK_INITIALIZER("cryptodev", 0, 0); 120 121 static int 122 cryptof_rw( 123 struct file *fp, 124 struct uio *uio, 125 struct ucred *active_cred, 126 int flags) 127 { 128 return (EIO); 129 } 130 131 /* 132 * Check a crypto identifier to see if it requested 133 * a software device/driver. This can be done either 134 * by device name/class or through search constraints. 135 */ 136 static int 137 checkforsoftware(int crid) 138 { 139 if (crid & CRYPTOCAP_F_SOFTWARE) 140 return EINVAL; /* XXX */ 141 if ((crid & CRYPTOCAP_F_HARDWARE) == 0 && 142 (crypto_getcaps(crid) & CRYPTOCAP_F_HARDWARE) == 0) 143 return EINVAL; /* XXX */ 144 return 0; 145 } 146 147 /* ARGSUSED */ 148 static int 149 cryptof_ioctl(struct file *fp, u_long cmd, caddr_t data, 150 struct ucred *cred, struct sysmsg *msg) 151 { 152 #define SES2(p) ((struct session2_op *)p) 153 struct cryptoini cria, crie; 154 struct fcrypt *fcr = fp->f_data; 155 struct csession *cse; 156 struct session_op *sop; 157 struct crypt_op *cop; 158 struct enc_xform *txform = NULL; 159 struct auth_hash *thash = NULL; 160 struct crypt_kop *kop; 161 u_int64_t sid; 162 u_int32_t ses; 163 int error = 0, crid; 164 165 switch (cmd) { 166 case CIOCGSESSION: 167 case CIOCGSESSION2: 168 sop = (struct session_op *)data; 169 switch (sop->cipher) { 170 case 0: 171 break; 172 case CRYPTO_DES_CBC: 173 txform = &enc_xform_des; 174 break; 175 case CRYPTO_3DES_CBC: 176 txform = &enc_xform_3des; 177 break; 178 case CRYPTO_BLF_CBC: 179 txform = &enc_xform_blf; 180 break; 181 case CRYPTO_CAST_CBC: 182 txform = &enc_xform_cast5; 183 break; 184 case CRYPTO_SKIPJACK_CBC: 185 txform = &enc_xform_skipjack; 186 break; 187 case CRYPTO_AES_CBC: 188 txform = &enc_xform_rijndael128; 189 break; 190 case CRYPTO_AES_XTS: 191 txform = &enc_xform_aes_xts; 192 break; 193 case CRYPTO_AES_CTR: 194 txform = &enc_xform_aes_ctr; 195 break; 196 case CRYPTO_NULL_CBC: 197 txform = &enc_xform_null; 198 break; 199 case CRYPTO_ARC4: 200 txform = &enc_xform_arc4; 201 break; 202 case CRYPTO_CAMELLIA_CBC: 203 txform = &enc_xform_camellia; 204 break; 205 case CRYPTO_TWOFISH_CBC: 206 txform = &enc_xform_twofish; 207 break; 208 case CRYPTO_SERPENT_CBC: 209 txform = &enc_xform_serpent; 210 break; 211 case CRYPTO_TWOFISH_XTS: 212 txform = &enc_xform_twofish_xts; 213 break; 214 case CRYPTO_SERPENT_XTS: 215 txform = &enc_xform_serpent_xts; 216 break; 217 default: 218 return (EINVAL); 219 } 220 221 switch (sop->mac) { 222 case 0: 223 break; 224 case CRYPTO_MD5_HMAC: 225 thash = &auth_hash_hmac_md5; 226 break; 227 case CRYPTO_SHA1_HMAC: 228 thash = &auth_hash_hmac_sha1; 229 break; 230 case CRYPTO_SHA2_256_HMAC: 231 thash = &auth_hash_hmac_sha2_256; 232 break; 233 case CRYPTO_SHA2_384_HMAC: 234 thash = &auth_hash_hmac_sha2_384; 235 break; 236 case CRYPTO_SHA2_512_HMAC: 237 thash = &auth_hash_hmac_sha2_512; 238 break; 239 case CRYPTO_RIPEMD160_HMAC: 240 thash = &auth_hash_hmac_ripemd_160; 241 break; 242 #ifdef notdef 243 case CRYPTO_MD5: 244 thash = &auth_hash_md5; 245 break; 246 case CRYPTO_SHA1: 247 thash = &auth_hash_sha1; 248 break; 249 #endif 250 case CRYPTO_NULL_HMAC: 251 thash = &auth_hash_null; 252 break; 253 default: 254 return (EINVAL); 255 } 256 257 bzero(&crie, sizeof(crie)); 258 bzero(&cria, sizeof(cria)); 259 260 if (txform) { 261 crie.cri_alg = txform->type; 262 crie.cri_klen = sop->keylen * 8; 263 if (sop->keylen > txform->maxkey || 264 sop->keylen < txform->minkey) { 265 error = EINVAL; 266 goto bail; 267 } 268 269 crie.cri_key = kmalloc(crie.cri_klen / 8, 270 M_XDATA, M_WAITOK); 271 if ((error = copyin(sop->key, crie.cri_key, 272 crie.cri_klen / 8))) 273 goto bail; 274 if (thash) 275 crie.cri_next = &cria; 276 } 277 278 if (thash) { 279 cria.cri_alg = thash->type; 280 cria.cri_klen = sop->mackeylen * 8; 281 if (sop->mackeylen != thash->keysize) { 282 error = EINVAL; 283 goto bail; 284 } 285 286 if (cria.cri_klen) { 287 cria.cri_key = kmalloc(cria.cri_klen / 8, 288 M_XDATA, M_WAITOK); 289 if ((error = copyin(sop->mackey, cria.cri_key, 290 cria.cri_klen / 8))) 291 goto bail; 292 } 293 } 294 295 /* NB: CIOGSESSION2 has the crid */ 296 if (cmd == CIOCGSESSION2) { 297 crid = SES2(sop)->crid; 298 error = checkforsoftware(crid); 299 if (error) 300 goto bail; 301 } else { 302 crid = CRYPTOCAP_F_HARDWARE; 303 if (crypto_devallowsoft) 304 crid |= CRYPTOCAP_F_SOFTWARE; 305 } 306 error = crypto_newsession(&sid, (txform ? &crie : &cria), crid); 307 if (error) 308 goto bail; 309 310 lockmgr(&cryptodev_lock, LK_EXCLUSIVE); 311 cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen, 312 cria.cri_key, cria.cri_klen, sop->cipher, 313 sop->mac, txform, thash); 314 lockmgr(&cryptodev_lock, LK_RELEASE); 315 316 if (cse == NULL) { 317 crypto_freesession(sid); 318 error = EINVAL; 319 goto bail; 320 } 321 sop->ses = cse->ses; 322 if (cmd == CIOCGSESSION2) { 323 /* return hardware/driver id */ 324 SES2(sop)->crid = CRYPTO_SESID2HID(cse->sid); 325 } 326 bail: 327 if (error) { 328 if (crie.cri_key) { 329 bzero(crie.cri_key, crie.cri_klen / 8); 330 kfree(crie.cri_key, M_XDATA); 331 } 332 if (cria.cri_key) { 333 bzero(cria.cri_key, cria.cri_klen / 8); 334 kfree(cria.cri_key, M_XDATA); 335 } 336 } 337 break; 338 case CIOCFSESSION: 339 lockmgr(&cryptodev_lock, LK_EXCLUSIVE); 340 ses = *(u_int32_t *)data; 341 cse = csefind(fcr, ses, &error); 342 if (cse) { 343 csedelete(fcr, cse); 344 error = csefree(cse); 345 } 346 lockmgr(&cryptodev_lock, LK_RELEASE); 347 break; 348 case CIOCCRYPT: 349 cop = (struct crypt_op *)data; 350 lockmgr(&cryptodev_lock, LK_EXCLUSIVE); 351 cse = csefind(fcr, cop->ses, &error); 352 lockmgr(&cryptodev_lock, LK_RELEASE); 353 if (cse) { 354 error = cryptodev_op(cse, cop, cred); 355 csedrop(cse); 356 } 357 break; 358 case CIOCKEY: 359 case CIOCKEY2: 360 if (!crypto_userasymcrypto) 361 return (EPERM); /* XXX compat? */ 362 lockmgr(&cryptodev_lock, LK_EXCLUSIVE); 363 kop = (struct crypt_kop *)data; 364 if (cmd == CIOCKEY) { 365 /* NB: crypto core enforces s/w driver use */ 366 kop->crk_crid = 367 CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE; 368 } 369 error = cryptodev_key(kop); 370 lockmgr(&cryptodev_lock, LK_RELEASE); 371 break; 372 case CIOCASYMFEAT: 373 if (!crypto_userasymcrypto) { 374 /* 375 * NB: if user asym crypto operations are 376 * not permitted return "no algorithms" 377 * so well-behaved applications will just 378 * fallback to doing them in software. 379 */ 380 *(int *)data = 0; 381 } else { 382 error = crypto_getfeat((int *)data); 383 } 384 break; 385 case CIOCFINDDEV: 386 error = cryptodev_find((struct crypt_find_op *)data); 387 break; 388 default: 389 error = EINVAL; 390 break; 391 } 392 return (error); 393 #undef SES2 394 } 395 396 static int cryptodev_cb(void *); 397 398 static int 399 cryptodev_op(struct csession *cse, struct crypt_op *cop, 400 struct ucred *active_cred) 401 { 402 struct cryptop *crp = NULL; 403 struct cryptodesc *crde = NULL, *crda = NULL; 404 int error; 405 406 if (cop->len > 256*1024-4) 407 return (E2BIG); 408 409 if (cse->txform) { 410 if (cop->len == 0 || (cop->len % cse->txform->blocksize) != 0) 411 return (EINVAL); 412 } 413 414 bzero(&cse->uio, sizeof(cse->uio)); 415 cse->uio.uio_iov = &cse->iovec; 416 cse->uio.uio_iovcnt = 1; 417 cse->uio.uio_offset = 0; 418 cse->uio.uio_resid = cop->len; 419 cse->uio.uio_segflg = UIO_SYSSPACE; 420 cse->uio.uio_rw = UIO_WRITE; 421 /* XXX: not sure, was td, now curthread? */ 422 cse->uio.uio_td = curthread; 423 cse->uio.uio_iov[0].iov_len = cop->len; 424 if (cse->thash) { 425 cse->uio.uio_iov[0].iov_len += cse->thash->hashsize; 426 cse->uio.uio_resid += cse->thash->hashsize; 427 } 428 cse->uio.uio_iov[0].iov_base = kmalloc(cse->uio.uio_iov[0].iov_len, 429 M_XDATA, M_WAITOK); 430 431 crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL)); 432 if (crp == NULL) { 433 error = ENOMEM; 434 goto bail; 435 } 436 437 if (cse->thash) { 438 crda = crp->crp_desc; 439 if (cse->txform) 440 crde = crda->crd_next; 441 } else { 442 if (cse->txform) 443 crde = crp->crp_desc; 444 else { 445 error = EINVAL; 446 goto bail; 447 } 448 } 449 450 if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len))) 451 goto bail; 452 453 if (crda) { 454 crda->crd_skip = 0; 455 crda->crd_len = cop->len; 456 crda->crd_inject = cop->len; 457 458 crda->crd_alg = cse->mac; 459 crda->crd_key = cse->mackey; 460 crda->crd_klen = cse->mackeylen * 8; 461 } 462 463 if (crde) { 464 if (cop->op == COP_ENCRYPT) 465 crde->crd_flags |= CRD_F_ENCRYPT; 466 else 467 crde->crd_flags &= ~CRD_F_ENCRYPT; 468 crde->crd_len = cop->len; 469 crde->crd_inject = 0; 470 471 crde->crd_alg = cse->cipher; 472 crde->crd_key = cse->key; 473 crde->crd_klen = cse->keylen * 8; 474 } 475 476 crp->crp_ilen = cop->len; 477 crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM 478 | (cop->flags & COP_F_BATCH); 479 crp->crp_buf = (caddr_t)&cse->uio; 480 crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb; 481 crp->crp_sid = cse->sid; 482 crp->crp_opaque = (void *)cse; 483 484 if (cop->iv) { 485 if (crde == NULL) { 486 error = EINVAL; 487 goto bail; 488 } 489 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 490 error = EINVAL; 491 goto bail; 492 } 493 if ((error = copyin(cop->iv, cse->tmp_iv, cse->txform->blocksize))) 494 goto bail; 495 bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize); 496 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; 497 crde->crd_skip = 0; 498 } else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 499 crde->crd_skip = 0; 500 } else if (crde) { 501 crde->crd_flags |= CRD_F_IV_PRESENT; 502 crde->crd_skip = cse->txform->blocksize; 503 crde->crd_len -= cse->txform->blocksize; 504 } 505 506 if (cop->mac && crda == NULL) { 507 error = EINVAL; 508 goto bail; 509 } 510 511 again: 512 /* 513 * Let the dispatch run unlocked, then, interlock against the 514 * callback before checking if the operation completed and going 515 * to sleep. This insures drivers don't inherit our lock which 516 * results in a lock order reversal between crypto_dispatch forced 517 * entry and the crypto_done callback into us. 518 */ 519 error = crypto_dispatch(crp); 520 lockmgr(&cse->lock, LK_EXCLUSIVE); 521 if (error == 0 && (crp->crp_flags & CRYPTO_F_DONE) == 0) 522 error = lksleep(crp, &cse->lock, 0, "crydev", 0); 523 lockmgr(&cse->lock, LK_RELEASE); 524 525 if (error != 0) 526 goto bail; 527 528 if (crp->crp_etype == EAGAIN) { 529 crp->crp_etype = 0; 530 crp->crp_flags &= ~CRYPTO_F_DONE; 531 goto again; 532 } 533 534 if (crp->crp_etype != 0) { 535 error = crp->crp_etype; 536 goto bail; 537 } 538 539 if (cse->error) { 540 error = cse->error; 541 goto bail; 542 } 543 544 if (cop->dst && 545 (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, cop->len))) 546 goto bail; 547 548 if (cop->mac && 549 (error = copyout((caddr_t)cse->uio.uio_iov[0].iov_base + cop->len, 550 cop->mac, cse->thash->hashsize))) 551 goto bail; 552 553 bail: 554 if (crp) 555 crypto_freereq(crp); 556 if (cse->uio.uio_iov[0].iov_base) 557 kfree(cse->uio.uio_iov[0].iov_base, M_XDATA); 558 559 return (error); 560 } 561 562 static int 563 cryptodev_cb(void *op) 564 { 565 struct cryptop *crp = (struct cryptop *) op; 566 struct csession *cse = (struct csession *)crp->crp_opaque; 567 568 lockmgr(&cse->lock, LK_EXCLUSIVE); 569 cse->error = crp->crp_etype; 570 wakeup_one(crp); 571 lockmgr(&cse->lock, LK_RELEASE); 572 return (0); 573 } 574 575 static int 576 cryptodevkey_cb(void *op) 577 { 578 struct cryptkop *krp = (struct cryptkop *) op; 579 580 wakeup_one(krp); 581 return (0); 582 } 583 584 static int 585 cryptodev_key(struct crypt_kop *kop) 586 { 587 struct cryptkop *krp = NULL; 588 int error = EINVAL; 589 int in, out, size, i; 590 591 if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) { 592 return (EFBIG); 593 } 594 595 in = kop->crk_iparams; 596 out = kop->crk_oparams; 597 switch (kop->crk_op) { 598 case CRK_MOD_EXP: 599 if (in == 3 && out == 1) 600 break; 601 return (EINVAL); 602 case CRK_MOD_EXP_CRT: 603 if (in == 6 && out == 1) 604 break; 605 return (EINVAL); 606 case CRK_DSA_SIGN: 607 if (in == 5 && out == 2) 608 break; 609 return (EINVAL); 610 case CRK_DSA_VERIFY: 611 if (in == 7 && out == 0) 612 break; 613 return (EINVAL); 614 case CRK_DH_COMPUTE_KEY: 615 if (in == 3 && out == 1) 616 break; 617 return (EINVAL); 618 default: 619 return (EINVAL); 620 } 621 622 krp = (struct cryptkop *)kmalloc(sizeof *krp, M_XDATA, M_WAITOK | M_ZERO); 623 krp->krp_op = kop->crk_op; 624 krp->krp_status = kop->crk_status; 625 krp->krp_iparams = kop->crk_iparams; 626 krp->krp_oparams = kop->crk_oparams; 627 krp->krp_crid = kop->crk_crid; 628 krp->krp_status = 0; 629 krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb; 630 631 for (i = 0; i < CRK_MAXPARAM; i++) { 632 if (kop->crk_param[i].crp_nbits > 65536) 633 /* Limit is the same as in OpenBSD */ 634 goto fail; 635 krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits; 636 } 637 for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) { 638 size = (krp->krp_param[i].crp_nbits + 7) / 8; 639 if (size == 0) 640 continue; 641 krp->krp_param[i].crp_p = kmalloc(size, M_XDATA, M_WAITOK); 642 if (i >= krp->krp_iparams) 643 continue; 644 error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size); 645 if (error) 646 goto fail; 647 } 648 649 error = crypto_kdispatch(krp); 650 if (error) 651 goto fail; 652 error = tsleep(krp, 0, "crydev", 0); 653 if (error) { 654 /* XXX can this happen? if so, how do we recover? */ 655 goto fail; 656 } 657 658 kop->crk_crid = krp->krp_crid; /* device that did the work */ 659 if (krp->krp_status != 0) { 660 error = krp->krp_status; 661 goto fail; 662 } 663 664 for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) { 665 size = (krp->krp_param[i].crp_nbits + 7) / 8; 666 if (size == 0) 667 continue; 668 error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size); 669 if (error) 670 goto fail; 671 } 672 673 fail: 674 if (krp) { 675 kop->crk_status = krp->krp_status; 676 for (i = 0; i < CRK_MAXPARAM; i++) { 677 if (krp->krp_param[i].crp_p) { 678 bzero(krp->krp_param[i].crp_p, 679 (krp->krp_param[i].crp_nbits + 7) / 8); 680 kfree(krp->krp_param[i].crp_p, M_XDATA); 681 } 682 } 683 kfree(krp, M_XDATA); 684 } 685 return (error); 686 } 687 688 static int 689 cryptodev_find(struct crypt_find_op *find) 690 { 691 device_t dev; 692 693 if (find->crid != -1) { 694 dev = crypto_find_device_byhid(find->crid); 695 if (dev == NULL) 696 return (ENOENT); 697 strlcpy(find->name, device_get_nameunit(dev), 698 sizeof(find->name)); 699 } else { 700 find->crid = crypto_find_driver(find->name); 701 if (find->crid == -1) 702 return (ENOENT); 703 } 704 return (0); 705 } 706 707 /* 708 * MPSAFE 709 */ 710 static int 711 cryptof_kqfilter(struct file *fp, struct knote *kn) 712 { 713 714 return (0); 715 } 716 717 /* 718 * MPSAFE 719 */ 720 static int 721 cryptof_stat(struct file *fp, struct stat *sb, struct ucred *cred) 722 { 723 return (EOPNOTSUPP); 724 } 725 726 static int 727 cryptof_close(struct file *fp) 728 { 729 struct fcrypt *fcr = fp->f_data; 730 struct csession *cse; 731 732 lockmgr(&cryptodev_lock, LK_EXCLUSIVE); 733 fcr = (struct fcrypt *)fp->f_data; 734 while ((cse = TAILQ_FIRST(&fcr->csessions))) { 735 TAILQ_REMOVE(&fcr->csessions, cse, next); 736 (void)csefree(cse); 737 } 738 fp->f_data = NULL; 739 lockmgr(&cryptodev_lock, LK_RELEASE); 740 741 kfree(fcr, M_XDATA); 742 return (0); 743 } 744 745 static struct csession * 746 csefind(struct fcrypt *fcr, u_int ses, int *errorp) 747 { 748 struct csession *cse; 749 750 TAILQ_FOREACH(cse, &fcr->csessions, next) { 751 if (cse->ses == ses) { 752 if (cse->busy) { 753 kprintf("csefind: cse %p BUSY\n", cse); 754 *errorp = EBUSY; 755 return NULL; 756 } 757 cse->busy = 1; 758 return (cse); 759 } 760 } 761 *errorp = EINVAL; 762 return (NULL); 763 } 764 765 static void 766 csedrop(struct csession *cse) 767 { 768 cse->busy = 0; 769 } 770 771 static int 772 csedelete(struct fcrypt *fcr, struct csession *cse_del) 773 { 774 struct csession *cse; 775 776 TAILQ_FOREACH(cse, &fcr->csessions, next) { 777 if (cse == cse_del) { 778 TAILQ_REMOVE(&fcr->csessions, cse, next); 779 return (1); 780 } 781 } 782 return (0); 783 } 784 785 static struct csession * 786 cseadd(struct fcrypt *fcr, struct csession *cse) 787 { 788 TAILQ_INSERT_TAIL(&fcr->csessions, cse, next); 789 cse->ses = fcr->sesn++; 790 return (cse); 791 } 792 793 struct csession * 794 csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen, 795 caddr_t mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac, 796 struct enc_xform *txform, struct auth_hash *thash) 797 { 798 struct csession *cse; 799 800 cse = kmalloc(sizeof(struct csession), M_XDATA, M_WAITOK | M_ZERO); 801 lockinit(&cse->lock, "cryptodev", 0, LK_CANRECURSE); 802 cse->key = key; 803 cse->keylen = keylen/8; 804 cse->mackey = mackey; 805 cse->mackeylen = mackeylen/8; 806 cse->sid = sid; 807 cse->cipher = cipher; 808 cse->mac = mac; 809 cse->txform = txform; 810 cse->thash = thash; 811 cseadd(fcr, cse); 812 return (cse); 813 } 814 815 static int 816 csefree(struct csession *cse) 817 { 818 int error; 819 820 error = crypto_freesession(cse->sid); 821 lockuninit(&cse->lock); 822 if (cse->key) 823 kfree(cse->key, M_XDATA); 824 if (cse->mackey) 825 kfree(cse->mackey, M_XDATA); 826 kfree(cse, M_XDATA); 827 return (error); 828 } 829 830 static int 831 cryptoopen(struct dev_open_args *ap) 832 { 833 return (0); 834 } 835 836 static int 837 cryptoread(struct dev_read_args *ap) 838 { 839 return (EIO); 840 } 841 842 static int 843 cryptowrite(struct dev_write_args *ap) 844 { 845 return (EIO); 846 } 847 848 static int 849 cryptoioctl(struct dev_ioctl_args *ap) 850 { 851 struct thread *td = curthread; 852 struct file *f; 853 struct fcrypt *fcr; 854 int fd, error; 855 856 switch (ap->a_cmd) { 857 case CRIOGET: 858 fcr = kmalloc(sizeof(struct fcrypt), M_XDATA, M_WAITOK); 859 TAILQ_INIT(&fcr->csessions); 860 fcr->sesn = 0; 861 862 KKASSERT(td->td_lwp); 863 error = falloc(td->td_lwp, &f, &fd); 864 865 if (error) { 866 kfree(fcr, M_XDATA); 867 return (error); 868 } 869 /* falloc automatically provides an extra reference to 'f'. */ 870 f->f_flag = FREAD | FWRITE; 871 f->f_type = DTYPE_CRYPTO; 872 f->f_ops = &cryptofops; 873 f->f_data = fcr; 874 fsetfd(td->td_proc->p_fd, f, fd); 875 *(u_int32_t *)ap->a_data = fd; 876 fdrop(f); 877 878 break; 879 case CRIOFINDDEV: 880 error = cryptodev_find((struct crypt_find_op *)ap->a_data); 881 break; 882 case CRIOASYMFEAT: 883 error = crypto_getfeat((int *)ap->a_data); 884 break; 885 default: 886 error = EINVAL; 887 break; 888 } 889 return (error); 890 } 891 892 static struct dev_ops crypto_ops = { 893 { "crypto", 0, D_MPSAFE }, 894 .d_open = cryptoopen, 895 .d_read = cryptoread, 896 .d_write = cryptowrite, 897 .d_ioctl = cryptoioctl, 898 }; 899 900 /* 901 * Initialization code, both for static and dynamic loading. 902 */ 903 static int 904 cryptodev_modevent(module_t mod, int type, void *unused) 905 { 906 switch (type) { 907 case MOD_LOAD: 908 if (bootverbose) 909 kprintf("crypto: <crypto device>\n"); 910 make_dev(&crypto_ops, 0, UID_ROOT, GID_WHEEL, 911 0666, "crypto"); 912 return 0; 913 case MOD_UNLOAD: 914 /*XXX disallow if active sessions */ 915 //dev_ops_remove(&crypto_ops, 0, 0); 916 dev_ops_remove_all(&crypto_ops); 917 return 0; 918 } 919 return EINVAL; 920 } 921 922 static moduledata_t cryptodev_mod = { 923 "cryptodev", 924 cryptodev_modevent, 925 0 926 }; 927 MODULE_VERSION(cryptodev, 1); 928 DECLARE_MODULE(cryptodev, cryptodev_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 929 MODULE_DEPEND(cryptodev, crypto, 1, 1, 1); 930