1 /* $NetBSD: cryptodev.c,v 1.41 2008/04/30 14:07:14 ad 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) 2008 The NetBSD Foundation, Inc. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by Coyote Point Systems, Inc. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Copyright (c) 2001 Theo de Raadt 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. The name of the author may not be used to endorse or promote products 47 * derived from this software without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 50 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 51 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 52 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 53 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 54 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 55 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 56 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 57 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 58 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 59 * 60 * Effort sponsored in part by the Defense Advanced Research Projects 61 * Agency (DARPA) and Air Force Research Laboratory, Air Force 62 * Materiel Command, USAF, under agreement number F30602-01-2-0537. 63 * 64 */ 65 66 #include <sys/cdefs.h> 67 __KERNEL_RCSID(0, "$NetBSD: cryptodev.c,v 1.41 2008/04/30 14:07:14 ad Exp $"); 68 69 #include <sys/param.h> 70 #include <sys/systm.h> 71 #include <sys/kmem.h> 72 #include <sys/malloc.h> 73 #include <sys/mbuf.h> 74 #include <sys/pool.h> 75 #include <sys/sysctl.h> 76 #include <sys/file.h> 77 #include <sys/filedesc.h> 78 #include <sys/errno.h> 79 #include <sys/md5.h> 80 #include <sys/sha1.h> 81 #include <sys/conf.h> 82 #include <sys/device.h> 83 #include <sys/kauth.h> 84 #include <sys/select.h> 85 #include <sys/poll.h> 86 #include <sys/atomic.h> 87 88 #include "opt_ocf.h" 89 #include <opencrypto/cryptodev.h> 90 #include <opencrypto/xform.h> 91 92 struct csession { 93 TAILQ_ENTRY(csession) next; 94 u_int64_t sid; 95 u_int32_t ses; 96 97 u_int32_t cipher; 98 struct enc_xform *txform; 99 u_int32_t mac; 100 struct auth_hash *thash; 101 102 void * key; 103 int keylen; 104 u_char tmp_iv[EALG_MAX_BLOCK_LEN]; 105 106 void * mackey; 107 int mackeylen; 108 u_char tmp_mac[CRYPTO_MAX_MAC_LEN]; 109 110 struct iovec iovec[1]; /* user requests never have more */ 111 struct uio uio; 112 int error; 113 }; 114 115 struct fcrypt { 116 TAILQ_HEAD(csessionlist, csession) csessions; 117 TAILQ_HEAD(crprethead, cryptop) crp_ret_mq; 118 TAILQ_HEAD(krprethead, cryptkop) crp_ret_mkq; 119 int sesn; 120 struct selinfo sinfo; 121 u_int32_t requestid; 122 }; 123 124 /* For our fixed-size allocations */ 125 static struct pool fcrpl; 126 static struct pool csepl; 127 128 /* Declaration of master device (fd-cloning/ctxt-allocating) entrypoints */ 129 static int cryptoopen(dev_t dev, int flag, int mode, struct lwp *l); 130 static int cryptoread(dev_t dev, struct uio *uio, int ioflag); 131 static int cryptowrite(dev_t dev, struct uio *uio, int ioflag); 132 static int cryptoselect(dev_t dev, int rw, struct lwp *l); 133 134 /* Declaration of cloned-device (per-ctxt) entrypoints */ 135 static int cryptof_read(struct file *, off_t *, struct uio *, 136 kauth_cred_t, int); 137 static int cryptof_write(struct file *, off_t *, struct uio *, 138 kauth_cred_t, int); 139 static int cryptof_ioctl(struct file *, u_long, void *); 140 static int cryptof_close(struct file *); 141 static int cryptof_poll(struct file *, int); 142 143 static const struct fileops cryptofops = { 144 cryptof_read, 145 cryptof_write, 146 cryptof_ioctl, 147 fnullop_fcntl, 148 cryptof_poll, 149 fbadop_stat, 150 cryptof_close, 151 fnullop_kqfilter 152 }; 153 154 static struct csession *csefind(struct fcrypt *, u_int); 155 static int csedelete(struct fcrypt *, struct csession *); 156 static struct csession *cseadd(struct fcrypt *, struct csession *); 157 static struct csession *csecreate(struct fcrypt *, u_int64_t, void *, u_int64_t, 158 void *, u_int64_t, u_int32_t, u_int32_t, struct enc_xform *, 159 struct auth_hash *); 160 static int csefree(struct csession *); 161 162 static int cryptodev_op(struct csession *, struct crypt_op *, struct lwp *); 163 static int cryptodev_mop(struct fcrypt *, struct crypt_n_op *, int, struct 164 lwp *); 165 static int cryptodev_key(struct crypt_kop *); 166 static int cryptodev_mkey(struct fcrypt *, struct crypt_n_kop *, int); 167 static int cryptodev_session(struct fcrypt *, struct session_op *); 168 static int cryptodev_msession(struct fcrypt *, struct session_n_op *, 169 int); 170 static int cryptodev_msessionfin(struct fcrypt *, int, u_int32_t *); 171 172 static int cryptodev_cb(void *); 173 static int cryptodevkey_cb(void *); 174 175 static int cryptodev_mcb(void *); 176 static int cryptodevkey_mcb(void *); 177 178 static int cryptodev_getmstatus(struct fcrypt *, struct crypt_result *, 179 int); 180 static int cryptodev_getstatus(struct fcrypt *, struct crypt_result *); 181 182 /* 183 * sysctl-able control variables for /dev/crypto now defined in crypto.c: 184 * crypto_usercrypto, crypto_userasmcrypto, crypto_devallowsoft. 185 */ 186 187 /* ARGSUSED */ 188 int 189 cryptof_read(file_t *fp, off_t *poff, 190 struct uio *uio, kauth_cred_t cred, int flags) 191 { 192 return (EIO); 193 } 194 195 /* ARGSUSED */ 196 int 197 cryptof_write(file_t *fp, off_t *poff, 198 struct uio *uio, kauth_cred_t cred, int flags) 199 { 200 return (EIO); 201 } 202 203 /* ARGSUSED */ 204 int 205 cryptof_ioctl(struct file *fp, u_long cmd, void *data) 206 { 207 struct fcrypt *fcr = fp->f_data; 208 struct csession *cse; 209 struct session_op *sop; 210 struct session_n_op *snop; 211 struct crypt_op *cop; 212 struct crypt_mop *mop; 213 struct crypt_mkop *mkop; 214 struct crypt_n_op *cnop; 215 struct crypt_n_kop *knop; 216 struct crypt_sgop *sgop; 217 struct crypt_sfop *sfop; 218 struct cryptret *crypt_ret; 219 struct crypt_result *crypt_res; 220 u_int32_t ses; 221 u_int32_t *sesid; 222 int error = 0; 223 size_t count; 224 225 /* backwards compatibility */ 226 file_t *criofp; 227 struct fcrypt *criofcr; 228 int criofd; 229 230 switch (cmd) { 231 case CRIOGET: /* XXX deprecated, remove after 5.0 */ 232 if ((error = fd_allocfile(&criofp, &criofd)) != 0) 233 return error; 234 criofcr = pool_get(&fcrpl, PR_WAITOK); 235 mutex_spin_enter(&crypto_mtx); 236 TAILQ_INIT(&criofcr->csessions); 237 TAILQ_INIT(&criofcr->crp_ret_mq); 238 TAILQ_INIT(&criofcr->crp_ret_mkq); 239 selinit(&criofcr->sinfo); 240 241 /* 242 * Don't ever return session 0, to allow detection of 243 * failed creation attempts with multi-create ioctl. 244 */ 245 criofcr->sesn = 1; 246 criofcr->requestid = 1; 247 mutex_spin_exit(&crypto_mtx); 248 (void)fd_clone(criofp, criofd, (FREAD|FWRITE), 249 &cryptofops, criofcr); 250 *(u_int32_t *)data = criofd; 251 return error; 252 break; 253 case CIOCGSESSION: 254 sop = (struct session_op *)data; 255 error = cryptodev_session(fcr, sop); 256 break; 257 case CIOCNGSESSION: 258 sgop = (struct crypt_sgop *)data; 259 snop = kmem_alloc((sgop->count * 260 sizeof(struct session_n_op)), KM_SLEEP); 261 error = copyin(sgop->sessions, snop, sgop->count * 262 sizeof(struct session_n_op)); 263 if (error) { 264 goto mbail; 265 } 266 267 error = cryptodev_msession(fcr, snop, sgop->count); 268 if (error) { 269 goto mbail; 270 } 271 272 error = copyout(snop, sgop->sessions, sgop->count * 273 sizeof(struct session_n_op)); 274 mbail: 275 kmem_free(snop, sgop->count * sizeof(struct session_n_op)); 276 break; 277 case CIOCFSESSION: 278 mutex_spin_enter(&crypto_mtx); 279 ses = *(u_int32_t *)data; 280 cse = csefind(fcr, ses); 281 if (cse == NULL) 282 return (EINVAL); 283 csedelete(fcr, cse); 284 error = csefree(cse); 285 mutex_spin_exit(&crypto_mtx); 286 break; 287 case CIOCNFSESSION: 288 sfop = (struct crypt_sfop *)data; 289 sesid = kmem_alloc((sfop->count * sizeof(u_int32_t)), 290 KM_SLEEP); 291 error = copyin(sfop->sesid, sesid, 292 (sfop->count * sizeof(u_int32_t))); 293 if (!error) { 294 error = cryptodev_msessionfin(fcr, sfop->count, sesid); 295 } 296 kmem_free(sesid, (sfop->count * sizeof(u_int32_t))); 297 break; 298 case CIOCCRYPT: 299 mutex_spin_enter(&crypto_mtx); 300 cop = (struct crypt_op *)data; 301 cse = csefind(fcr, cop->ses); 302 mutex_spin_exit(&crypto_mtx); 303 if (cse == NULL) { 304 DPRINTF(("csefind failed\n")); 305 return (EINVAL); 306 } 307 error = cryptodev_op(cse, cop, curlwp); 308 DPRINTF(("cryptodev_op error = %d\n", error)); 309 break; 310 case CIOCNCRYPTM: 311 mop = (struct crypt_mop *)data; 312 cnop = kmem_alloc((mop->count * sizeof(struct crypt_n_op)), 313 KM_SLEEP); 314 error = copyin(mop->reqs, cnop, 315 (mop->count * sizeof(struct crypt_n_op))); 316 if(!error) { 317 error = cryptodev_mop(fcr, cnop, mop->count, 318 curlwp); 319 if (!error) { 320 error = copyout(cnop, mop->reqs, 321 (mop->count * 322 sizeof(struct crypt_n_op))); 323 } 324 } 325 kmem_free(cnop, (mop->count * sizeof(struct crypt_n_op))); 326 break; 327 case CIOCKEY: 328 error = cryptodev_key((struct crypt_kop *)data); 329 DPRINTF(("cryptodev_key error = %d\n", error)); 330 break; 331 case CIOCNFKEYM: 332 mkop = (struct crypt_mkop *)data; 333 knop = kmem_alloc((mkop->count * sizeof(struct crypt_n_kop)), 334 KM_SLEEP); 335 error = copyin(mkop->reqs, knop, 336 (mkop->count * sizeof(struct crypt_n_kop))); 337 if (!error) { 338 error = cryptodev_mkey(fcr, knop, mkop->count); 339 if (!error) 340 error = copyout(knop, mkop->reqs, 341 (mkop->count * 342 sizeof(struct crypt_n_kop))); 343 } 344 kmem_free(knop, (mkop->count * sizeof(struct crypt_n_kop))); 345 break; 346 case CIOCASYMFEAT: 347 error = crypto_getfeat((int *)data); 348 break; 349 case CIOCNCRYPTRETM: 350 crypt_ret = (struct cryptret *)data; 351 count = crypt_ret->count; 352 crypt_res = kmem_alloc((count * 353 sizeof(struct crypt_result)), 354 KM_SLEEP); 355 error = copyin(crypt_ret->results, crypt_res, 356 (count * sizeof(struct crypt_result))); 357 if (error) 358 goto reterr; 359 crypt_ret->count = cryptodev_getmstatus(fcr, crypt_res, 360 crypt_ret->count); 361 /* sanity check count */ 362 if (crypt_ret->count > count) { 363 printf("%s.%d: error returned count %zd > original " 364 " count %zd\n", 365 __FILE__, __LINE__, crypt_ret->count, count); 366 crypt_ret->count = count; 367 368 } 369 error = copyout(crypt_res, crypt_ret->results, 370 (crypt_ret->count * sizeof(struct crypt_result))); 371 reterr: 372 kmem_free(crypt_res, 373 (count * sizeof(struct crypt_result))); 374 break; 375 case CIOCNCRYPTRET: 376 error = cryptodev_getstatus(fcr, (struct crypt_result *)data); 377 break; 378 default: 379 DPRINTF(("invalid ioctl cmd %ld\n", cmd)); 380 error = EINVAL; 381 } 382 return (error); 383 } 384 385 static int 386 cryptodev_op(struct csession *cse, struct crypt_op *cop, struct lwp *l) 387 { 388 struct cryptop *crp = NULL; 389 struct cryptodesc *crde = NULL, *crda = NULL; 390 int error; 391 392 if (cop->len > 256*1024-4) 393 return (E2BIG); 394 395 if (cse->txform) { 396 if (cop->len == 0 || (cop->len % cse->txform->blocksize) != 0) 397 return (EINVAL); 398 } 399 400 bzero(&cse->uio, sizeof(cse->uio)); 401 cse->uio.uio_iovcnt = 1; 402 cse->uio.uio_resid = 0; 403 cse->uio.uio_rw = UIO_WRITE; 404 cse->uio.uio_iov = cse->iovec; 405 UIO_SETUP_SYSSPACE(&cse->uio); 406 memset(&cse->iovec, 0, sizeof(cse->iovec)); 407 cse->uio.uio_iov[0].iov_len = cop->len; 408 cse->uio.uio_iov[0].iov_base = kmem_alloc(cop->len, KM_SLEEP); 409 cse->uio.uio_resid = cse->uio.uio_iov[0].iov_len; 410 411 crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL)); 412 if (crp == NULL) { 413 error = ENOMEM; 414 goto bail; 415 } 416 417 if (cse->thash) { 418 crda = crp->crp_desc; 419 if (cse->txform) 420 crde = crda->crd_next; 421 } else { 422 if (cse->txform) 423 crde = crp->crp_desc; 424 else { 425 error = EINVAL; 426 goto bail; 427 } 428 } 429 430 if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len))) 431 { 432 printf("copyin failed %s %d \n", (char *)cop->src, error); 433 goto bail; 434 } 435 436 if (crda) { 437 crda->crd_skip = 0; 438 crda->crd_len = cop->len; 439 crda->crd_inject = 0; /* ??? */ 440 441 crda->crd_alg = cse->mac; 442 crda->crd_key = cse->mackey; 443 crda->crd_klen = cse->mackeylen * 8; 444 } 445 446 if (crde) { 447 if (cop->op == COP_ENCRYPT) 448 crde->crd_flags |= CRD_F_ENCRYPT; 449 else 450 crde->crd_flags &= ~CRD_F_ENCRYPT; 451 crde->crd_len = cop->len; 452 crde->crd_inject = 0; 453 454 crde->crd_alg = cse->cipher; 455 crde->crd_key = cse->key; 456 crde->crd_klen = cse->keylen * 8; 457 } 458 459 crp->crp_ilen = cop->len; 460 crp->crp_flags = CRYPTO_F_IOV | (cop->flags & COP_F_BATCH); 461 crp->crp_buf = (void *)&cse->uio; 462 crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb; 463 crp->crp_sid = cse->sid; 464 crp->crp_opaque = (void *)cse; 465 466 if (cop->iv) { 467 if (crde == NULL) { 468 error = EINVAL; 469 goto bail; 470 } 471 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 472 error = EINVAL; 473 goto bail; 474 } 475 if ((error = copyin(cop->iv, cse->tmp_iv, 476 cse->txform->blocksize))) 477 goto bail; 478 bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize); 479 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; 480 crde->crd_skip = 0; 481 } else if (crde) { 482 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 483 crde->crd_skip = 0; 484 } else { 485 crde->crd_flags |= CRD_F_IV_PRESENT; 486 crde->crd_skip = cse->txform->blocksize; 487 crde->crd_len -= cse->txform->blocksize; 488 } 489 } 490 491 if (cop->mac) { 492 if (crda == NULL) { 493 error = EINVAL; 494 goto bail; 495 } 496 crp->crp_mac=cse->tmp_mac; 497 } 498 499 /* 500 * XXX there was a comment here which said that we went to 501 * XXX splcrypto() but needed to only if CRYPTO_F_CBIMM, 502 * XXX disabled on NetBSD since 1.6O due to a race condition. 503 * XXX But crypto_dispatch went to splcrypto() itself! (And 504 * XXX now takes the crypto_mtx mutex itself). We do, however, 505 * XXX need to hold the mutex across the call to cv_wait(). 506 * XXX (should we arrange for crypto_dispatch to return to 507 * XXX us with it held? it seems quite ugly to do so.) 508 */ 509 #ifdef notyet 510 eagain: 511 #endif 512 error = crypto_dispatch(crp); 513 mutex_spin_enter(&crypto_mtx); 514 515 switch (error) { 516 #ifdef notyet /* don't loop forever -- but EAGAIN not possible here yet */ 517 case EAGAIN: 518 mutex_spin_exit(&crypto_mtx); 519 goto eagain; 520 break; 521 #endif 522 case 0: 523 break; 524 default: 525 DPRINTF(("cryptodev_op: not waiting, error.\n")); 526 mutex_spin_exit(&crypto_mtx); 527 goto bail; 528 } 529 530 while (!(crp->crp_flags & CRYPTO_F_DONE)) { 531 DPRINTF(("cryptodev_op: sleeping on cv %08x for crp %08x\n", \ 532 (uint32_t)&crp->crp_cv, (uint32_t)crp)); 533 cv_wait(&crp->crp_cv, &crypto_mtx); /* XXX cv_wait_sig? */ 534 } 535 if (crp->crp_flags & CRYPTO_F_ONRETQ) { 536 DPRINTF(("cryptodev_op: DONE, not woken by cryptoret.\n")); 537 (void)crypto_ret_q_remove(crp); 538 } 539 mutex_spin_exit(&crypto_mtx); 540 541 if (crp->crp_etype != 0) { 542 DPRINTF(("cryptodev_op: crp_etype %d\n", crp->crp_etype)); 543 error = crp->crp_etype; 544 goto bail; 545 } 546 547 if (cse->error) { 548 DPRINTF(("cryptodev_op: cse->error %d\n", cse->error)); 549 error = cse->error; 550 goto bail; 551 } 552 553 if (cop->dst && 554 (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, cop->len))) 555 { 556 DPRINTF(("cryptodev_op: copyout error %d\n", error)); 557 goto bail; 558 } 559 560 if (cop->mac && 561 (error = copyout(crp->crp_mac, cop->mac, cse->thash->authsize))) { 562 DPRINTF(("cryptodev_op: mac copyout error %d\n", error)); 563 goto bail; 564 } 565 566 bail: 567 if (crp) 568 crypto_freereq(crp); 569 if (cse->uio.uio_iov[0].iov_base) 570 kmem_free(cse->uio.uio_iov[0].iov_base, 571 cse->uio.uio_iov[0].iov_len); 572 573 return (error); 574 } 575 576 static int 577 cryptodev_cb(void *op) 578 { 579 struct cryptop *crp = (struct cryptop *) op; 580 struct csession *cse = (struct csession *)crp->crp_opaque; 581 int error = 0; 582 583 mutex_spin_enter(&crypto_mtx); 584 cse->error = crp->crp_etype; 585 if (crp->crp_etype == EAGAIN) { 586 /* always drop mutex to call dispatch routine */ 587 mutex_spin_exit(&crypto_mtx); 588 error = crypto_dispatch(crp); 589 mutex_spin_enter(&crypto_mtx); 590 } 591 if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) { 592 cv_signal(&crp->crp_cv); 593 } 594 mutex_spin_exit(&crypto_mtx); 595 return (0); 596 } 597 598 static int 599 cryptodev_mcb(void *op) 600 { 601 struct cryptop *crp = (struct cryptop *) op; 602 struct csession *cse = (struct csession *)crp->crp_opaque; 603 int error=0; 604 605 mutex_spin_enter(&crypto_mtx); 606 cse->error = crp->crp_etype; 607 if (crp->crp_etype == EAGAIN) { 608 mutex_spin_exit(&crypto_mtx); 609 error = crypto_dispatch(crp); 610 mutex_spin_enter(&crypto_mtx); 611 } 612 if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) { 613 cv_signal(&crp->crp_cv); 614 } 615 616 TAILQ_INSERT_TAIL(&crp->fcrp->crp_ret_mq, crp, crp_next); 617 selnotify(&crp->fcrp->sinfo, 0, 0); 618 mutex_spin_exit(&crypto_mtx); 619 return (0); 620 } 621 622 static int 623 cryptodevkey_cb(void *op) 624 { 625 struct cryptkop *krp = (struct cryptkop *) op; 626 627 mutex_spin_enter(&crypto_mtx); 628 cv_signal(&krp->krp_cv); 629 mutex_spin_exit(&crypto_mtx); 630 return (0); 631 } 632 633 static int 634 cryptodevkey_mcb(void *op) 635 { 636 struct cryptkop *krp = (struct cryptkop *) op; 637 638 mutex_spin_enter(&crypto_mtx); 639 cv_signal(&krp->krp_cv); 640 TAILQ_INSERT_TAIL(&krp->fcrp->crp_ret_mkq, krp, krp_next); 641 selnotify(&krp->fcrp->sinfo, 0, 0); 642 mutex_spin_exit(&crypto_mtx); 643 return (0); 644 } 645 646 static int 647 cryptodev_key(struct crypt_kop *kop) 648 { 649 struct cryptkop *krp = NULL; 650 int error = EINVAL; 651 int in, out, size, i; 652 653 if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) { 654 return (EFBIG); 655 } 656 657 in = kop->crk_iparams; 658 out = kop->crk_oparams; 659 switch (kop->crk_op) { 660 case CRK_MOD_EXP: 661 if (in == 3 && out == 1) 662 break; 663 return (EINVAL); 664 case CRK_MOD_EXP_CRT: 665 if (in == 6 && out == 1) 666 break; 667 return (EINVAL); 668 case CRK_DSA_SIGN: 669 if (in == 5 && out == 2) 670 break; 671 return (EINVAL); 672 case CRK_DSA_VERIFY: 673 if (in == 7 && out == 0) 674 break; 675 return (EINVAL); 676 case CRK_DH_COMPUTE_KEY: 677 if (in == 3 && out == 1) 678 break; 679 return (EINVAL); 680 case CRK_MOD_ADD: 681 if (in == 3 && out == 1) 682 break; 683 return (EINVAL); 684 case CRK_MOD_ADDINV: 685 if (in == 2 && out == 1) 686 break; 687 return (EINVAL); 688 case CRK_MOD_SUB: 689 if (in == 3 && out == 1) 690 break; 691 return (EINVAL); 692 case CRK_MOD_MULT: 693 if (in == 3 && out == 1) 694 break; 695 return (EINVAL); 696 case CRK_MOD_MULTINV: 697 if (in == 2 && out == 1) 698 break; 699 return (EINVAL); 700 case CRK_MOD: 701 if (in == 2 && out == 1) 702 break; 703 return (EINVAL); 704 default: 705 return (EINVAL); 706 } 707 708 krp = pool_get(&cryptkop_pool, PR_WAITOK); 709 bzero(krp, sizeof *krp); 710 cv_init(&krp->krp_cv, "crykdev"); 711 krp->krp_op = kop->crk_op; 712 krp->krp_status = kop->crk_status; 713 krp->krp_iparams = kop->crk_iparams; 714 krp->krp_oparams = kop->crk_oparams; 715 krp->krp_status = 0; 716 krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb; 717 718 for (i = 0; i < CRK_MAXPARAM; i++) 719 krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits; 720 for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) { 721 size = (krp->krp_param[i].crp_nbits + 7) / 8; 722 if (size == 0) 723 continue; 724 krp->krp_param[i].crp_p = kmem_alloc(size, KM_SLEEP); 725 if (i >= krp->krp_iparams) 726 continue; 727 error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size); 728 if (error) 729 goto fail; 730 } 731 732 error = crypto_kdispatch(krp); 733 if (error != 0) { 734 goto fail; 735 } 736 737 mutex_spin_enter(&crypto_mtx); 738 while (!(krp->krp_flags & CRYPTO_F_DONE)) { 739 cv_wait(&krp->krp_cv, &crypto_mtx); /* XXX cv_wait_sig? */ 740 } 741 if (krp->krp_flags & CRYPTO_F_ONRETQ) { 742 DPRINTF(("cryptodev_key: DONE early, not via cryptoret.\n")); 743 (void)crypto_ret_kq_remove(krp); 744 } 745 mutex_spin_exit(&crypto_mtx); 746 747 if (krp->krp_status != 0) { 748 DPRINTF(("cryptodev_key: krp->krp_status 0x%08x\n", krp->krp_status)); 749 error = krp->krp_status; 750 goto fail; 751 } 752 753 for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) { 754 size = (krp->krp_param[i].crp_nbits + 7) / 8; 755 if (size == 0) 756 continue; 757 error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size); 758 if (error) { 759 DPRINTF(("cryptodev_key: copyout oparam %d failed, error=%d\n", i-krp->krp_iparams, error)); 760 goto fail; 761 } 762 } 763 764 fail: 765 if (krp) { 766 kop->crk_status = krp->krp_status; 767 for (i = 0; i < CRK_MAXPARAM; i++) { 768 struct crparam *kp = &(krp->krp_param[i]); 769 if (krp->krp_param[i].crp_p) { 770 size = (kp->crp_nbits + 7) / 8; 771 KASSERT(size > 0); 772 memset(kp->crp_p, 0, size); 773 kmem_free(kp->crp_p, size); 774 } 775 } 776 pool_put(&cryptkop_pool, krp); 777 } 778 DPRINTF(("cryptodev_key: error=0x%08x\n", error)); 779 return (error); 780 } 781 782 /* ARGSUSED */ 783 static int 784 cryptof_close(struct file *fp) 785 { 786 struct fcrypt *fcr = fp->f_data; 787 struct csession *cse; 788 789 mutex_spin_enter(&crypto_mtx); 790 while ((cse = TAILQ_FIRST(&fcr->csessions))) { 791 TAILQ_REMOVE(&fcr->csessions, cse, next); 792 (void)csefree(cse); 793 } 794 seldestroy(&fcr->sinfo); 795 fp->f_data = NULL; 796 mutex_spin_exit(&crypto_mtx); 797 798 pool_put(&fcrpl, fcr); 799 return 0; 800 } 801 802 /* csefind: call with crypto_mtx held. */ 803 static struct csession * 804 csefind(struct fcrypt *fcr, u_int ses) 805 { 806 struct csession *cse, *ret = NULL; 807 808 KASSERT(mutex_owned(&crypto_mtx)); 809 TAILQ_FOREACH(cse, &fcr->csessions, next) 810 if (cse->ses == ses) 811 ret = cse; 812 813 return (ret); 814 } 815 816 /* csedelete: call with crypto_mtx held. */ 817 static int 818 csedelete(struct fcrypt *fcr, struct csession *cse_del) 819 { 820 struct csession *cse; 821 int ret = 0; 822 823 KASSERT(mutex_owned(&crypto_mtx)); 824 TAILQ_FOREACH(cse, &fcr->csessions, next) { 825 if (cse == cse_del) { 826 TAILQ_REMOVE(&fcr->csessions, cse, next); 827 ret = 1; 828 } 829 } 830 return (ret); 831 } 832 833 /* cseadd: call with crypto_mtx held. */ 834 static struct csession * 835 cseadd(struct fcrypt *fcr, struct csession *cse) 836 { 837 KASSERT(mutex_owned(&crypto_mtx)); 838 /* don't let session ID wrap! */ 839 if (fcr->sesn + 1 == 0) return NULL; 840 TAILQ_INSERT_TAIL(&fcr->csessions, cse, next); 841 cse->ses = fcr->sesn++; 842 return (cse); 843 } 844 845 /* csecreate: call with crypto_mtx held. */ 846 static struct csession * 847 csecreate(struct fcrypt *fcr, u_int64_t sid, void *key, u_int64_t keylen, 848 void *mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac, 849 struct enc_xform *txform, struct auth_hash *thash) 850 { 851 struct csession *cse; 852 853 KASSERT(mutex_owned(&crypto_mtx)); 854 cse = pool_get(&csepl, PR_NOWAIT); 855 if (cse == NULL) 856 return NULL; 857 cse->key = key; 858 cse->keylen = keylen/8; 859 cse->mackey = mackey; 860 cse->mackeylen = mackeylen/8; 861 cse->sid = sid; 862 cse->cipher = cipher; 863 cse->mac = mac; 864 cse->txform = txform; 865 cse->thash = thash; 866 cse->error = 0; 867 if (cseadd(fcr, cse)) 868 return (cse); 869 else { 870 pool_put(&csepl, cse); 871 return NULL; 872 } 873 } 874 875 /* csefree: call with crypto_mtx held. */ 876 static int 877 csefree(struct csession *cse) 878 { 879 int error; 880 881 KASSERT(mutex_owned(&crypto_mtx)); 882 error = crypto_freesession(cse->sid); 883 if (cse->key) 884 free(cse->key, M_XDATA); 885 if (cse->mackey) 886 free(cse->mackey, M_XDATA); 887 pool_put(&csepl, cse); 888 return (error); 889 } 890 891 static int 892 cryptoopen(dev_t dev, int flag, int mode, 893 struct lwp *l) 894 { 895 file_t *fp; 896 struct fcrypt *fcr; 897 int fd, error; 898 899 if (crypto_usercrypto == 0) 900 return (ENXIO); 901 902 if ((error = fd_allocfile(&fp, &fd)) != 0) 903 return error; 904 905 fcr = pool_get(&fcrpl, PR_WAITOK); 906 mutex_spin_enter(&crypto_mtx); 907 TAILQ_INIT(&fcr->csessions); 908 TAILQ_INIT(&fcr->crp_ret_mq); 909 TAILQ_INIT(&fcr->crp_ret_mkq); 910 selinit(&fcr->sinfo); 911 /* 912 * Don't ever return session 0, to allow detection of 913 * failed creation attempts with multi-create ioctl. 914 */ 915 fcr->sesn = 1; 916 fcr->requestid = 1; 917 mutex_spin_exit(&crypto_mtx); 918 return fd_clone(fp, fd, flag, &cryptofops, fcr); 919 } 920 921 static int 922 cryptoread(dev_t dev, struct uio *uio, int ioflag) 923 { 924 return (EIO); 925 } 926 927 static int 928 cryptowrite(dev_t dev, struct uio *uio, int ioflag) 929 { 930 return (EIO); 931 } 932 933 int 934 cryptoselect(dev_t dev, int rw, struct lwp *l) 935 { 936 return (0); 937 } 938 939 /*static*/ 940 struct cdevsw crypto_cdevsw = { 941 /* open */ cryptoopen, 942 /* close */ noclose, 943 /* read */ cryptoread, 944 /* write */ cryptowrite, 945 /* ioctl */ noioctl, 946 /* ttstop?*/ nostop, 947 /* ??*/ notty, 948 /* poll */ cryptoselect /*nopoll*/, 949 /* mmap */ nommap, 950 /* kqfilter */ nokqfilter, 951 /* type */ D_OTHER, 952 }; 953 954 static int 955 cryptodev_mop(struct fcrypt *fcr, 956 struct crypt_n_op * cnop, 957 int count, struct lwp *l) 958 { 959 struct cryptop *crp = NULL; 960 struct cryptodesc *crde = NULL, *crda = NULL; 961 int req, error=0; 962 struct csession *cse; 963 964 for (req = 0; req < count; req++) { 965 mutex_spin_enter(&crypto_mtx); 966 cse = csefind(fcr, cnop[req].ses); 967 if (cse == NULL) { 968 DPRINTF(("csefind failed\n")); 969 cnop[req].status = EINVAL; 970 mutex_spin_exit(&crypto_mtx); 971 continue; 972 } 973 mutex_spin_exit(&crypto_mtx); 974 975 if (cnop[req].len > 256*1024-4) { 976 DPRINTF(("length failed\n")); 977 cnop[req].status = EINVAL; 978 continue; 979 } 980 if (cse->txform) { 981 if (cnop[req].len == 0 || 982 (cnop[req].len % cse->txform->blocksize) != 0) { 983 cnop[req].status = EINVAL; 984 continue; 985 } 986 } 987 988 crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL)); 989 if (crp == NULL) { 990 cnop[req].status = ENOMEM; 991 goto bail; 992 } 993 994 bzero(&crp->uio, sizeof(crp->uio)); 995 crp->uio.uio_iovcnt = 1; 996 crp->uio.uio_resid = 0; 997 crp->uio.uio_rw = UIO_WRITE; 998 crp->uio.uio_iov = crp->iovec; 999 UIO_SETUP_SYSSPACE(&crp->uio); 1000 memset(&crp->iovec, 0, sizeof(crp->iovec)); 1001 crp->uio.uio_iov[0].iov_len = cnop[req].len; 1002 crp->uio.uio_iov[0].iov_base = kmem_alloc(cnop[req].len, 1003 KM_SLEEP); 1004 crp->uio.uio_resid = crp->uio.uio_iov[0].iov_len; 1005 1006 if (cse->thash) { 1007 crda = crp->crp_desc; 1008 if (cse->txform) 1009 crde = crda->crd_next; 1010 } else { 1011 if (cse->txform) 1012 crde = crp->crp_desc; 1013 else { 1014 cnop[req].status = EINVAL; 1015 goto bail; 1016 } 1017 } 1018 1019 if ((copyin(cnop[req].src, 1020 crp->uio.uio_iov[0].iov_base, cnop[req].len))) { 1021 cnop[req].status = EINVAL; 1022 goto bail; 1023 } 1024 1025 if (crda) { 1026 crda->crd_skip = 0; 1027 crda->crd_len = cnop[req].len; 1028 crda->crd_inject = 0; /* ??? */ 1029 1030 crda->crd_alg = cse->mac; 1031 crda->crd_key = cse->mackey; 1032 crda->crd_klen = cse->mackeylen * 8; 1033 } 1034 1035 if (crde) { 1036 if (cnop[req].op == COP_ENCRYPT) 1037 crde->crd_flags |= CRD_F_ENCRYPT; 1038 else 1039 crde->crd_flags &= ~CRD_F_ENCRYPT; 1040 crde->crd_len = cnop[req].len; 1041 crde->crd_inject = 0; 1042 1043 crde->crd_alg = cse->cipher; 1044 #ifdef notyet /* XXX must notify h/w driver new key, drain */ 1045 if(cnop[req].key && cnop[req].keylen) { 1046 crde->crd_key = malloc(cnop[req].keylen, 1047 M_XDATA, M_WAITOK); 1048 if((error = copyin(cnop[req].key, 1049 crde->crd_key, cnop[req].keylen))) { 1050 cnop[req].status = EINVAL; 1051 goto bail; 1052 } 1053 crde->crd_klen = cnop[req].keylen * 8; 1054 } else { ... } 1055 #endif 1056 crde->crd_key = cse->key; 1057 crde->crd_klen = cse->keylen * 8; 1058 } 1059 1060 crp->crp_ilen = cnop[req].len; 1061 crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM 1062 | (cnop[req].flags & COP_F_BATCH); 1063 crp->crp_buf = (void *)&crp->uio; 1064 crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_mcb; 1065 crp->crp_sid = cse->sid; 1066 crp->crp_opaque = (void *)cse; 1067 crp->fcrp = fcr; 1068 crp->dst = cnop[req].dst; 1069 /* we can use the crp_ilen in cryptop(crp) for this */ 1070 crp->len = cnop[req].len; 1071 crp->mac = cnop[req].mac; 1072 1073 if (cnop[req].iv) { 1074 if (crde == NULL) { 1075 cnop[req].status = EINVAL; 1076 goto bail; 1077 } 1078 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 1079 cnop[req].status = EINVAL; 1080 goto bail; 1081 } 1082 if ((error = copyin(cnop[req].iv, crp->tmp_iv, 1083 cse->txform->blocksize))) { 1084 cnop[req].status = EINVAL; 1085 goto bail; 1086 } 1087 bcopy(crp->tmp_iv, crde->crd_iv, cse->txform->blocksize); 1088 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; 1089 crde->crd_skip = 0; 1090 } else if (crde) { 1091 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 1092 crde->crd_skip = 0; 1093 } else { 1094 crde->crd_flags |= CRD_F_IV_PRESENT; 1095 crde->crd_skip = cse->txform->blocksize; 1096 crde->crd_len -= cse->txform->blocksize; 1097 } 1098 } 1099 1100 if (cnop[req].mac) { 1101 if (crda == NULL) { 1102 cnop[req].status = EINVAL; 1103 goto bail; 1104 } 1105 crp->crp_mac=cse->tmp_mac; 1106 } 1107 cnop[req].reqid = atomic_inc_32_nv(&(fcr->requestid)); 1108 crp->crp_reqid = cnop[req].reqid; 1109 crp->crp_usropaque = cnop[req].opaque; 1110 #ifdef notyet 1111 eagain: 1112 #endif 1113 cnop[req].status = crypto_dispatch(crp); 1114 mutex_spin_enter(&crypto_mtx); /* XXX why mutex? */ 1115 1116 switch (cnop[req].status) { 1117 #ifdef notyet /* don't loop forever -- but EAGAIN not possible here yet */ 1118 case EAGAIN: 1119 mutex_spin_exit(&crypto_mtx); 1120 goto eagain; 1121 break; 1122 #endif 1123 case 0: 1124 break; 1125 default: 1126 DPRINTF(("cryptodev_op: not waiting, error.\n")); 1127 mutex_spin_exit(&crypto_mtx); 1128 goto bail; 1129 } 1130 1131 mutex_spin_exit(&crypto_mtx); 1132 bail: 1133 if (cnop[req].status) { 1134 if (crp) { 1135 crypto_freereq(crp); 1136 if(cse->uio.uio_iov[0].iov_base) { 1137 kmem_free(cse->uio.uio_iov[0].iov_base, 1138 cse->uio.uio_iov[0].iov_len); 1139 } 1140 } 1141 error = 0; 1142 } 1143 } 1144 return (error); 1145 } 1146 1147 static int 1148 cryptodev_mkey(struct fcrypt *fcr, struct crypt_n_kop *kop, int count) 1149 { 1150 struct cryptkop *krp = NULL; 1151 int error = EINVAL; 1152 int in, out, size, i, req; 1153 1154 for (req = 0; req < count; req++) { 1155 if (kop[req].crk_iparams + kop[req].crk_oparams > CRK_MAXPARAM) { 1156 return (EFBIG); 1157 } 1158 1159 in = kop[req].crk_iparams; 1160 out = kop[req].crk_oparams; 1161 switch (kop[req].crk_op) { 1162 case CRK_MOD_EXP: 1163 if (in == 3 && out == 1) 1164 break; 1165 kop[req].crk_status = EINVAL; 1166 continue; 1167 case CRK_MOD_EXP_CRT: 1168 if (in == 6 && out == 1) 1169 break; 1170 kop[req].crk_status = EINVAL; 1171 continue; 1172 case CRK_DSA_SIGN: 1173 if (in == 5 && out == 2) 1174 break; 1175 kop[req].crk_status = EINVAL; 1176 continue; 1177 case CRK_DSA_VERIFY: 1178 if (in == 7 && out == 0) 1179 break; 1180 kop[req].crk_status = EINVAL; 1181 continue; 1182 case CRK_DH_COMPUTE_KEY: 1183 if (in == 3 && out == 1) 1184 break; 1185 kop[req].crk_status = EINVAL; 1186 continue; 1187 case CRK_MOD_ADD: 1188 if (in == 3 && out == 1) 1189 break; 1190 kop[req].crk_status = EINVAL; 1191 continue; 1192 case CRK_MOD_ADDINV: 1193 if (in == 2 && out == 1) 1194 break; 1195 kop[req].crk_status = EINVAL; 1196 continue; 1197 case CRK_MOD_SUB: 1198 if (in == 3 && out == 1) 1199 break; 1200 kop[req].crk_status = EINVAL; 1201 continue; 1202 case CRK_MOD_MULT: 1203 if (in == 3 && out == 1) 1204 break; 1205 kop[req].crk_status = EINVAL; 1206 continue; 1207 case CRK_MOD_MULTINV: 1208 if (in == 2 && out == 1) 1209 break; 1210 kop[req].crk_status = EINVAL; 1211 continue; 1212 case CRK_MOD: 1213 if (in == 2 && out == 1) 1214 break; 1215 kop[req].crk_status = EINVAL; 1216 continue; 1217 default: 1218 kop[req].crk_status = EINVAL; 1219 continue; 1220 } 1221 1222 krp = pool_get(&cryptkop_pool, PR_WAITOK); 1223 bzero(krp, sizeof *krp); 1224 cv_init(&krp->krp_cv, "crykdev"); 1225 krp->krp_op = kop[req].crk_op; 1226 krp->krp_status = kop[req].crk_status; 1227 krp->krp_iparams = kop[req].crk_iparams; 1228 krp->krp_oparams = kop[req].crk_oparams; 1229 krp->krp_status = 0; 1230 krp->krp_callback = 1231 (int (*) (struct cryptkop *)) cryptodevkey_mcb; 1232 bcopy(kop[req].crk_param, 1233 krp->crk_param, 1234 sizeof(kop[req].crk_param)); 1235 1236 krp->krp_flags = CRYPTO_F_CBIMM; 1237 1238 for (i = 0; i < CRK_MAXPARAM; i++) 1239 krp->krp_param[i].crp_nbits = 1240 kop[req].crk_param[i].crp_nbits; 1241 for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) { 1242 size = (krp->krp_param[i].crp_nbits + 7) / 8; 1243 if (size == 0) 1244 continue; 1245 krp->krp_param[i].crp_p = 1246 kmem_alloc(size, KM_SLEEP); 1247 if (i >= krp->krp_iparams) 1248 continue; 1249 kop[req].crk_status = copyin(kop[req].crk_param[i].crp_p, 1250 krp->krp_param[i].crp_p, size); 1251 if (kop[req].crk_status) 1252 goto fail; 1253 } 1254 krp->fcrp = fcr; 1255 1256 kop[req].crk_reqid = atomic_inc_32_nv(&(fcr->requestid)); 1257 krp->krp_reqid = kop[req].crk_reqid; 1258 krp->krp_usropaque = kop[req].crk_opaque; 1259 1260 kop[req].crk_status = crypto_kdispatch(krp); 1261 if (kop[req].crk_status != 0) { 1262 goto fail; 1263 } 1264 1265 fail: 1266 if(kop[req].crk_status) { 1267 if (krp) { 1268 kop[req].crk_status = krp->krp_status; 1269 for (i = 0; i < CRK_MAXPARAM; i++) { 1270 struct crparam *kp = 1271 &(krp->krp_param[i]); 1272 if (kp->crp_p) { 1273 size = (kp->crp_nbits + 7) / 8; 1274 KASSERT(size > 0); 1275 memset(kp->crp_p, 0, size); 1276 kmem_free(kp->crp_p, size); 1277 } 1278 } 1279 pool_put(&cryptkop_pool, krp); 1280 } 1281 } 1282 error = 0; 1283 } 1284 DPRINTF(("cryptodev_key: error=0x%08x\n", error)); 1285 return (error); 1286 } 1287 1288 static int 1289 cryptodev_session(struct fcrypt *fcr, struct session_op *sop) { 1290 struct cryptoini cria, crie; 1291 struct enc_xform *txform = NULL; 1292 struct auth_hash *thash = NULL; 1293 struct csession *cse; 1294 u_int64_t sid; 1295 int error = 0; 1296 1297 /* XXX there must be a way to not embed the list of xforms here */ 1298 switch (sop->cipher) { 1299 case 0: 1300 break; 1301 case CRYPTO_DES_CBC: 1302 txform = &enc_xform_des; 1303 break; 1304 case CRYPTO_3DES_CBC: 1305 txform = &enc_xform_3des; 1306 break; 1307 case CRYPTO_BLF_CBC: 1308 txform = &enc_xform_blf; 1309 break; 1310 case CRYPTO_CAST_CBC: 1311 txform = &enc_xform_cast5; 1312 case CRYPTO_SKIPJACK_CBC: 1313 txform = &enc_xform_skipjack; 1314 break; 1315 case CRYPTO_AES_CBC: 1316 txform = &enc_xform_rijndael128; 1317 break; 1318 case CRYPTO_NULL_CBC: 1319 txform = &enc_xform_null; 1320 break; 1321 case CRYPTO_ARC4: 1322 txform = &enc_xform_arc4; 1323 break; 1324 default: 1325 DPRINTF(("Invalid cipher %d\n", sop->cipher)); 1326 return EINVAL; 1327 } 1328 1329 switch (sop->mac) { 1330 case 0: 1331 break; 1332 case CRYPTO_MD5_HMAC: 1333 thash = &auth_hash_hmac_md5; 1334 break; 1335 case CRYPTO_SHA1_HMAC: 1336 thash = &auth_hash_hmac_sha1; 1337 break; 1338 case CRYPTO_MD5_HMAC_96: 1339 thash = &auth_hash_hmac_md5_96; 1340 break; 1341 case CRYPTO_SHA1_HMAC_96: 1342 thash = &auth_hash_hmac_sha1_96; 1343 break; 1344 case CRYPTO_SHA2_HMAC: 1345 /* XXX switching on key length seems questionable */ 1346 if (sop->mackeylen == auth_hash_hmac_sha2_256.keysize) { 1347 thash = &auth_hash_hmac_sha2_256; 1348 } else if (sop->mackeylen == auth_hash_hmac_sha2_384.keysize) { 1349 thash = &auth_hash_hmac_sha2_384; 1350 } else if (sop->mackeylen == auth_hash_hmac_sha2_512.keysize) { 1351 thash = &auth_hash_hmac_sha2_512; 1352 } else { 1353 DPRINTF(("Invalid mackeylen %d\n", sop->mackeylen)); 1354 return EINVAL; 1355 } 1356 break; 1357 case CRYPTO_RIPEMD160_HMAC: 1358 thash = &auth_hash_hmac_ripemd_160; 1359 break; 1360 case CRYPTO_RIPEMD160_HMAC_96: 1361 thash = &auth_hash_hmac_ripemd_160_96; 1362 break; 1363 case CRYPTO_MD5: 1364 thash = &auth_hash_md5; 1365 break; 1366 case CRYPTO_SHA1: 1367 thash = &auth_hash_sha1; 1368 break; 1369 case CRYPTO_NULL_HMAC: 1370 thash = &auth_hash_null; 1371 break; 1372 default: 1373 DPRINTF(("Invalid mac %d\n", sop->mac)); 1374 return (EINVAL); 1375 } 1376 1377 memset(&crie, 0, sizeof(crie)); 1378 memset(&cria, 0, sizeof(cria)); 1379 1380 if (txform) { 1381 crie.cri_alg = txform->type; 1382 crie.cri_klen = sop->keylen * 8; 1383 if (sop->keylen > txform->maxkey || 1384 sop->keylen < txform->minkey) { 1385 DPRINTF(("keylen %d not in [%d,%d]\n", 1386 sop->keylen, txform->minkey, 1387 txform->maxkey)); 1388 error = EINVAL ; 1389 goto bail; 1390 } 1391 1392 crie.cri_key = malloc(crie.cri_klen / 8, M_XDATA, M_WAITOK); 1393 if ((error = copyin(sop->key, crie.cri_key, 1394 crie.cri_klen / 8))) { 1395 goto bail; 1396 } 1397 if (thash) { 1398 crie.cri_next = &cria; /* XXX forces enc then hash? */ 1399 } 1400 } 1401 1402 if (thash) { 1403 cria.cri_alg = thash->type; 1404 cria.cri_klen = sop->mackeylen * 8; 1405 if (sop->mackeylen != thash->keysize) { 1406 DPRINTF(("mackeylen %d != keysize %d\n", 1407 sop->mackeylen, thash->keysize)); 1408 error = EINVAL; 1409 goto bail; 1410 } 1411 if (cria.cri_klen) { 1412 cria.cri_key = malloc(cria.cri_klen / 8, M_XDATA, 1413 M_WAITOK); 1414 if ((error = copyin(sop->mackey, cria.cri_key, 1415 cria.cri_klen / 8))) { 1416 goto bail; 1417 } 1418 } 1419 } 1420 /* crypto_newsession requires that we hold the mutex. */ 1421 mutex_spin_enter(&crypto_mtx); 1422 error = crypto_newsession(&sid, (txform ? &crie : &cria), 1423 crypto_devallowsoft); 1424 if (!error) { 1425 cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen, 1426 cria.cri_key, cria.cri_klen, sop->cipher, 1427 sop->mac, txform, thash); 1428 if (cse != NULL) { 1429 sop->ses = cse->ses; 1430 } else { 1431 DPRINTF(("csecreate failed\n")); 1432 crypto_freesession(sid); 1433 error = EINVAL; 1434 } 1435 } else { 1436 DPRINTF(("SIOCSESSION violates kernel parameters %d\n", 1437 error)); 1438 } 1439 mutex_spin_exit(&crypto_mtx); 1440 bail: 1441 if (error) { 1442 if (crie.cri_key) { 1443 memset(crie.cri_key, 0, crie.cri_klen / 8); 1444 free(crie.cri_key, M_XDATA); 1445 } 1446 if (cria.cri_key) { 1447 memset(cria.cri_key, 0, cria.cri_klen / 8); 1448 free(cria.cri_key, M_XDATA); 1449 } 1450 } 1451 return error; 1452 } 1453 1454 static int 1455 cryptodev_msession(struct fcrypt *fcr, struct session_n_op *sn_ops, 1456 int count) 1457 { 1458 int i; 1459 1460 for (i = 0; i < count; i++, sn_ops++) { 1461 struct session_op s_op; 1462 s_op.cipher = sn_ops->cipher; 1463 s_op.mac = sn_ops->mac; 1464 s_op.keylen = sn_ops->keylen; 1465 s_op.key = sn_ops->key; 1466 s_op.mackeylen = sn_ops->mackeylen; 1467 s_op.mackey = sn_ops->mackey; 1468 1469 sn_ops->status = cryptodev_session(fcr, &s_op); 1470 sn_ops->ses = s_op.ses; 1471 } 1472 1473 return 0; 1474 } 1475 1476 static int 1477 cryptodev_msessionfin(struct fcrypt *fcr, int count, u_int32_t *sesid) 1478 { 1479 struct csession *cse; 1480 int req, error = 0; 1481 1482 mutex_spin_enter(&crypto_mtx); 1483 for(req = 0; req < count; req++) { 1484 cse = csefind(fcr, sesid[req]); 1485 if (cse == NULL) 1486 continue; 1487 csedelete(fcr, cse); 1488 error = csefree(cse); 1489 } 1490 mutex_spin_exit(&crypto_mtx); 1491 return 0; 1492 } 1493 1494 /* 1495 * collect as many completed requests as are availble, or count completed requests 1496 * whichever is less. 1497 * return the number of requests. 1498 */ 1499 static int 1500 cryptodev_getmstatus(struct fcrypt *fcr, struct crypt_result *crypt_res, 1501 int count) 1502 { 1503 struct cryptop *crp = NULL; 1504 struct cryptkop *krp = NULL; 1505 struct csession *cse; 1506 int i, size, req = 0; 1507 int completed=0; 1508 1509 /* On stack so nobody else can grab them -- no locking */ 1510 SLIST_HEAD(, cryptop) crp_delfree_l = 1511 SLIST_HEAD_INITIALIZER(crp_delfree_l); 1512 SLIST_HEAD(, cryptkop) krp_delfree_l = 1513 SLIST_HEAD_INITIALIZER(krp_delfree_l); 1514 1515 mutex_spin_enter(&crypto_mtx); 1516 1517 /* at this point we do not know which response user is requesting for 1518 * (symmetric or asymmetric) so we copyout one from each i.e if the 1519 * count is 2 then 1 from symmetric and 1 from asymmetric queue and 1520 * if 3 then 2 symmetric and 1 asymmetric and so on */ 1521 for(; req < count ;) { 1522 crp = TAILQ_FIRST(&fcr->crp_ret_mq); 1523 if(crp) { 1524 cse = (struct csession *)crp->crp_opaque; 1525 crypt_res[req].reqid = crp->crp_reqid; 1526 crypt_res[req].opaque = crp->crp_usropaque; 1527 completed++; 1528 cse = csefind(fcr, cse->ses); 1529 if (cse == NULL) { 1530 DPRINTF(("csefind failed\n")); 1531 crypt_res[req].status = EINVAL; 1532 goto bail; 1533 } 1534 1535 if (crp->crp_etype != 0) { 1536 crypt_res[req].status = crp->crp_etype; 1537 goto bail; 1538 } 1539 1540 if (cse->error) { 1541 crypt_res[req].status = cse->error; 1542 goto bail; 1543 } 1544 1545 if (crp->dst && 1546 (crypt_res[req].status = copyout 1547 (crp->uio.uio_iov[0].iov_base, 1548 crp->dst, crp->len))) 1549 goto bail; 1550 1551 if (crp->mac && 1552 (crypt_res[req].status = copyout 1553 (crp->crp_mac, crp->mac, 1554 cse->thash->authsize))) 1555 goto bail; 1556 bail: 1557 TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next); 1558 SLIST_INSERT_HEAD(&crp_delfree_l, crp, 1559 crp_qun.crp_lnext); 1560 req++; 1561 } 1562 1563 if(req < count) { 1564 krp = TAILQ_FIRST(&fcr->crp_ret_mkq); 1565 if (krp) { 1566 crypt_res[req].reqid = krp->krp_reqid; 1567 crypt_res[req].opaque = krp->krp_usropaque; 1568 completed++; 1569 if (krp->krp_status != 0) { 1570 DPRINTF(("cryptodev_key: " 1571 "krp->krp_status" 1572 "0x%08x\n", krp->krp_status)); 1573 crypt_res[req].status = 1574 krp->krp_status; 1575 goto fail; 1576 } 1577 1578 for (i = krp->krp_iparams; i < krp->krp_iparams 1579 + krp->krp_oparams; i++) { 1580 size = (krp->krp_param[i].crp_nbits 1581 + 7) / 8; 1582 if (size == 0) 1583 continue; 1584 crypt_res[req].status = copyout 1585 (krp->krp_param[i].crp_p, 1586 krp->crk_param[i].crp_p, size); 1587 if (crypt_res[req].status) { 1588 DPRINTF(("cryptodev_key: " 1589 "copyout oparam " 1590 "%d failed, " 1591 "error=%d\n", 1592 i-krp->krp_iparams, 1593 crypt_res[req].status)); 1594 goto fail; 1595 } 1596 } 1597 fail: 1598 TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next); 1599 /* not sure what to do for this */ 1600 /* kop[req].crk_status = krp->krp_status; */ 1601 SLIST_INSERT_HEAD(&krp_delfree_l, krp, 1602 krp_qun.krp_lnext); 1603 } 1604 req++; 1605 } 1606 } 1607 mutex_spin_exit(&crypto_mtx); 1608 1609 while(!SLIST_EMPTY(&crp_delfree_l)) { 1610 crp = SLIST_FIRST(&crp_delfree_l); 1611 SLIST_REMOVE_HEAD(&crp_delfree_l, crp_qun.crp_lnext); 1612 kmem_free(crp->uio.uio_iov[0].iov_base, 1613 crp->uio.uio_iov[0].iov_len); 1614 crypto_freereq(crp); 1615 } 1616 1617 while(!SLIST_EMPTY(&krp_delfree_l)) { 1618 krp = SLIST_FIRST(&krp_delfree_l); 1619 for (i = 0; i < CRK_MAXPARAM; i++) { 1620 struct crparam *kp = &(krp->krp_param[i]); 1621 if (kp->crp_p) { 1622 size = (kp->crp_nbits + 7) / 8; 1623 KASSERT(size > 0); 1624 memset(kp->crp_p, 0, size); 1625 kmem_free(kp->crp_p, size); 1626 } 1627 } 1628 SLIST_REMOVE_HEAD(&krp_delfree_l, krp_qun.krp_lnext); 1629 pool_put(&cryptkop_pool, krp); 1630 } 1631 return completed; 1632 } 1633 1634 static int 1635 cryptodev_getstatus (struct fcrypt *fcr, struct crypt_result *crypt_res) 1636 { 1637 struct cryptop *crp = NULL; 1638 struct cryptkop *krp = NULL; 1639 struct csession *cse; 1640 int i, size, req = 0; 1641 1642 mutex_spin_enter(&crypto_mtx); 1643 /* Here we dont know for which request the user is requesting the 1644 * response so checking in both the queues */ 1645 TAILQ_FOREACH(crp, &fcr->crp_ret_mq, crp_next) { 1646 if(crp && (crp->crp_reqid == crypt_res->reqid)) { 1647 cse = (struct csession *)crp->crp_opaque; 1648 crypt_res->opaque = crp->crp_usropaque; 1649 cse = csefind(fcr, cse->ses); 1650 if (cse == NULL) { 1651 DPRINTF(("csefind failed\n")); 1652 crypt_res->status = EINVAL; 1653 goto bail; 1654 } 1655 1656 if (crp->crp_etype != 0) { 1657 crypt_res->status = crp->crp_etype; 1658 goto bail; 1659 } 1660 1661 if (cse->error) { 1662 crypt_res->status = cse->error; 1663 goto bail; 1664 } 1665 1666 if (crp->dst && 1667 (crypt_res->status = copyout 1668 (crp->uio.uio_iov[0].iov_base, 1669 crp->dst, crp->len))) 1670 goto bail; 1671 1672 if (crp->mac && 1673 (crypt_res->status = copyout(crp->crp_mac, 1674 crp->mac, cse->thash->authsize))) 1675 goto bail; 1676 bail: 1677 TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next); 1678 1679 mutex_spin_exit(&crypto_mtx); 1680 crypto_freereq(crp); 1681 return 0; 1682 } 1683 } 1684 1685 TAILQ_FOREACH(krp, &fcr->crp_ret_mkq, krp_next) { 1686 if(krp && (krp->krp_reqid == crypt_res->reqid)) { 1687 crypt_res[req].opaque = krp->krp_usropaque; 1688 if (krp->krp_status != 0) { 1689 DPRINTF(("cryptodev_key: " 1690 "krp->krp_status 0x%08x\n", 1691 krp->krp_status)); 1692 crypt_res[req].status = krp->krp_status; 1693 goto fail; 1694 } 1695 1696 for (i = krp->krp_iparams; i < krp->krp_iparams 1697 + krp->krp_oparams; i++) { 1698 size = (krp->krp_param[i].crp_nbits + 7) / 8; 1699 if (size == 0) 1700 continue; 1701 crypt_res[req].status = copyout 1702 (krp->krp_param[i].crp_p, 1703 krp->crk_param[i].crp_p, size); 1704 if (crypt_res[req].status) { 1705 DPRINTF(("cryptodev_key: copyout oparam" 1706 "%d failed, error=%d\n", 1707 i-krp->krp_iparams, 1708 crypt_res[req].status)); 1709 goto fail; 1710 } 1711 } 1712 fail: 1713 TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next); 1714 mutex_spin_exit(&crypto_mtx); 1715 /* not sure what to do for this */ 1716 /* kop[req].crk_status = krp->krp_status; */ 1717 for (i = 0; i < CRK_MAXPARAM; i++) { 1718 struct crparam *kp = &(krp->krp_param[i]); 1719 if (kp->crp_p) { 1720 size = (kp->crp_nbits + 7) / 8; 1721 KASSERT(size > 0); 1722 memset(kp->crp_p, 0, size); 1723 kmem_free(kp->crp_p, size); 1724 } 1725 } 1726 pool_put(&cryptkop_pool, krp); 1727 return 0; 1728 } 1729 } 1730 mutex_spin_exit(&crypto_mtx); 1731 return EINPROGRESS; 1732 } 1733 1734 static int 1735 cryptof_poll(struct file *fp, int events) 1736 { 1737 struct fcrypt *fcr = (struct fcrypt *)fp->f_data; 1738 int revents = 0; 1739 1740 if (!(events & (POLLIN | POLLRDNORM))) { 1741 /* only support read and POLLIN */ 1742 return 0; 1743 } 1744 1745 mutex_spin_enter(&crypto_mtx); 1746 if (TAILQ_EMPTY(&fcr->crp_ret_mq) && TAILQ_EMPTY(&fcr->crp_ret_mkq)) { 1747 /* no completed requests pending, save the poll for later */ 1748 selrecord(curlwp, &fcr->sinfo); 1749 } else { 1750 /* let the app(s) know that there are completed requests */ 1751 revents = events & (POLLIN | POLLRDNORM); 1752 } 1753 mutex_spin_exit(&crypto_mtx); 1754 1755 return revents; 1756 } 1757 1758 /* 1759 * Pseudo-device initialization routine for /dev/crypto 1760 */ 1761 void cryptoattach(int); 1762 1763 void 1764 cryptoattach(int num) 1765 { 1766 pool_init(&fcrpl, sizeof(struct fcrypt), 0, 0, 0, "fcrpl", 1767 NULL, IPL_NET); /* XXX IPL_NET ("splcrypto") */ 1768 pool_init(&csepl, sizeof(struct csession), 0, 0, 0, "csepl", 1769 NULL, IPL_NET); /* XXX IPL_NET ("splcrypto") */ 1770 1771 /* 1772 * Preallocate space for 64 users, with 5 sessions each. 1773 * (consider that a TLS protocol session requires at least 1774 * 3DES, MD5, and SHA1 (both hashes are used in the PRF) for 1775 * the negotiation, plus HMAC_SHA1 for the actual SSL records, 1776 * consuming one session here for each algorithm. 1777 */ 1778 pool_prime(&fcrpl, 64); 1779 pool_prime(&csepl, 64 * 5); 1780 } 1781