1 /* $NetBSD: cryptodev.c,v 1.44 2008/05/24 16:42:00 christos 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.44 2008/05/24 16:42:00 christos 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 *, 158 u_int64_t, 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 *, 163 struct lwp *); 164 static int cryptodev_mop(struct fcrypt *, struct crypt_n_op *, int, 165 struct lwp *); 166 static int cryptodev_key(struct crypt_kop *); 167 static int cryptodev_mkey(struct fcrypt *, struct crypt_n_kop *, int); 168 static int cryptodev_session(struct fcrypt *, struct session_op *); 169 static int cryptodev_msession(struct fcrypt *, struct session_n_op *, 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, curlwp); 318 if (!error) { 319 error = copyout(cnop, mop->reqs, 320 (mop->count * sizeof(struct crypt_n_op))); 321 } 322 } 323 kmem_free(cnop, (mop->count * sizeof(struct crypt_n_op))); 324 break; 325 case CIOCKEY: 326 error = cryptodev_key((struct crypt_kop *)data); 327 DPRINTF(("cryptodev_key error = %d\n", error)); 328 break; 329 case CIOCNFKEYM: 330 mkop = (struct crypt_mkop *)data; 331 knop = kmem_alloc((mkop->count * sizeof(struct crypt_n_kop)), 332 KM_SLEEP); 333 error = copyin(mkop->reqs, knop, 334 (mkop->count * sizeof(struct crypt_n_kop))); 335 if (!error) { 336 error = cryptodev_mkey(fcr, knop, mkop->count); 337 if (!error) 338 error = copyout(knop, mkop->reqs, 339 (mkop->count * sizeof(struct crypt_n_kop))); 340 } 341 kmem_free(knop, (mkop->count * sizeof(struct crypt_n_kop))); 342 break; 343 case CIOCASYMFEAT: 344 error = crypto_getfeat((int *)data); 345 break; 346 case CIOCNCRYPTRETM: 347 crypt_ret = (struct cryptret *)data; 348 count = crypt_ret->count; 349 crypt_res = kmem_alloc((count * sizeof(struct crypt_result)), 350 KM_SLEEP); 351 error = copyin(crypt_ret->results, crypt_res, 352 (count * sizeof(struct crypt_result))); 353 if (error) 354 goto reterr; 355 crypt_ret->count = cryptodev_getmstatus(fcr, crypt_res, 356 crypt_ret->count); 357 /* sanity check count */ 358 if (crypt_ret->count > count) { 359 printf("%s.%d: error returned count %zd > original " 360 " count %zd\n", 361 __FILE__, __LINE__, crypt_ret->count, count); 362 crypt_ret->count = count; 363 364 } 365 error = copyout(crypt_res, crypt_ret->results, 366 (crypt_ret->count * sizeof(struct crypt_result))); 367 reterr: 368 kmem_free(crypt_res, (count * sizeof(struct crypt_result))); 369 break; 370 case CIOCNCRYPTRET: 371 error = cryptodev_getstatus(fcr, (struct crypt_result *)data); 372 break; 373 default: 374 DPRINTF(("invalid ioctl cmd %ld\n", cmd)); 375 error = EINVAL; 376 } 377 return error; 378 } 379 380 static int 381 cryptodev_op(struct csession *cse, struct crypt_op *cop, struct lwp *l) 382 { 383 struct cryptop *crp = NULL; 384 struct cryptodesc *crde = NULL, *crda = NULL; 385 int error; 386 387 if (cop->len > 256*1024-4) 388 return E2BIG; 389 390 if (cse->txform) { 391 if (cop->len == 0 || (cop->len % cse->txform->blocksize) != 0) 392 return EINVAL; 393 } 394 395 (void)memset(&cse->uio, 0, sizeof(cse->uio)); 396 cse->uio.uio_iovcnt = 1; 397 cse->uio.uio_resid = 0; 398 cse->uio.uio_rw = UIO_WRITE; 399 cse->uio.uio_iov = cse->iovec; 400 UIO_SETUP_SYSSPACE(&cse->uio); 401 memset(&cse->iovec, 0, sizeof(cse->iovec)); 402 cse->uio.uio_iov[0].iov_len = cop->len; 403 cse->uio.uio_iov[0].iov_base = kmem_alloc(cop->len, KM_SLEEP); 404 cse->uio.uio_resid = cse->uio.uio_iov[0].iov_len; 405 406 crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL)); 407 if (crp == NULL) { 408 error = ENOMEM; 409 goto bail; 410 } 411 412 if (cse->thash) { 413 crda = crp->crp_desc; 414 if (cse->txform && crda) 415 crde = crda->crd_next; 416 } else { 417 if (cse->txform) 418 crde = crp->crp_desc; 419 else { 420 error = EINVAL; 421 goto bail; 422 } 423 } 424 425 if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len))) 426 { 427 printf("copyin failed %s %d \n", (char *)cop->src, error); 428 goto bail; 429 } 430 431 if (crda) { 432 crda->crd_skip = 0; 433 crda->crd_len = cop->len; 434 crda->crd_inject = 0; /* ??? */ 435 436 crda->crd_alg = cse->mac; 437 crda->crd_key = cse->mackey; 438 crda->crd_klen = cse->mackeylen * 8; 439 } 440 441 if (crde) { 442 if (cop->op == COP_ENCRYPT) 443 crde->crd_flags |= CRD_F_ENCRYPT; 444 else 445 crde->crd_flags &= ~CRD_F_ENCRYPT; 446 crde->crd_len = cop->len; 447 crde->crd_inject = 0; 448 449 crde->crd_alg = cse->cipher; 450 crde->crd_key = cse->key; 451 crde->crd_klen = cse->keylen * 8; 452 } 453 454 crp->crp_ilen = cop->len; 455 crp->crp_flags = CRYPTO_F_IOV | (cop->flags & COP_F_BATCH); 456 crp->crp_buf = (void *)&cse->uio; 457 crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb; 458 crp->crp_sid = cse->sid; 459 crp->crp_opaque = (void *)cse; 460 461 if (cop->iv) { 462 if (crde == NULL) { 463 error = EINVAL; 464 goto bail; 465 } 466 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 467 error = EINVAL; 468 goto bail; 469 } 470 if ((error = copyin(cop->iv, cse->tmp_iv, 471 cse->txform->blocksize))) 472 goto bail; 473 (void)memcpy(crde->crd_iv, cse->tmp_iv, cse->txform->blocksize); 474 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; 475 crde->crd_skip = 0; 476 } else if (crde) { 477 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 478 crde->crd_skip = 0; 479 } else { 480 crde->crd_flags |= CRD_F_IV_PRESENT; 481 crde->crd_skip = cse->txform->blocksize; 482 crde->crd_len -= cse->txform->blocksize; 483 } 484 } 485 486 if (cop->mac) { 487 if (crda == NULL) { 488 error = EINVAL; 489 goto bail; 490 } 491 crp->crp_mac=cse->tmp_mac; 492 } 493 494 /* 495 * XXX there was a comment here which said that we went to 496 * XXX splcrypto() but needed to only if CRYPTO_F_CBIMM, 497 * XXX disabled on NetBSD since 1.6O due to a race condition. 498 * XXX But crypto_dispatch went to splcrypto() itself! (And 499 * XXX now takes the crypto_mtx mutex itself). We do, however, 500 * XXX need to hold the mutex across the call to cv_wait(). 501 * XXX (should we arrange for crypto_dispatch to return to 502 * XXX us with it held? it seems quite ugly to do so.) 503 */ 504 #ifdef notyet 505 eagain: 506 #endif 507 error = crypto_dispatch(crp); 508 mutex_spin_enter(&crypto_mtx); 509 510 switch (error) { 511 #ifdef notyet /* don't loop forever -- but EAGAIN not possible here yet */ 512 case EAGAIN: 513 mutex_spin_exit(&crypto_mtx); 514 goto eagain; 515 break; 516 #endif 517 case 0: 518 break; 519 default: 520 DPRINTF(("cryptodev_op: not waiting, error.\n")); 521 mutex_spin_exit(&crypto_mtx); 522 goto bail; 523 } 524 525 while (!(crp->crp_flags & CRYPTO_F_DONE)) { 526 DPRINTF(("cryptodev_op: sleeping on cv %08x for crp %08x\n", \ 527 (uint32_t)&crp->crp_cv, (uint32_t)crp)); 528 cv_wait(&crp->crp_cv, &crypto_mtx); /* XXX cv_wait_sig? */ 529 } 530 if (crp->crp_flags & CRYPTO_F_ONRETQ) { 531 DPRINTF(("cryptodev_op: DONE, not woken by cryptoret.\n")); 532 (void)crypto_ret_q_remove(crp); 533 } 534 mutex_spin_exit(&crypto_mtx); 535 536 if (crp->crp_etype != 0) { 537 DPRINTF(("cryptodev_op: crp_etype %d\n", crp->crp_etype)); 538 error = crp->crp_etype; 539 goto bail; 540 } 541 542 if (cse->error) { 543 DPRINTF(("cryptodev_op: cse->error %d\n", cse->error)); 544 error = cse->error; 545 goto bail; 546 } 547 548 if (cop->dst && 549 (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, cop->len))) 550 { 551 DPRINTF(("cryptodev_op: copyout error %d\n", error)); 552 goto bail; 553 } 554 555 if (cop->mac && 556 (error = copyout(crp->crp_mac, cop->mac, cse->thash->authsize))) { 557 DPRINTF(("cryptodev_op: mac copyout error %d\n", error)); 558 goto bail; 559 } 560 561 bail: 562 if (crp) 563 crypto_freereq(crp); 564 if (cse->uio.uio_iov[0].iov_base) 565 kmem_free(cse->uio.uio_iov[0].iov_base, 566 cse->uio.uio_iov[0].iov_len); 567 568 return error; 569 } 570 571 static int 572 cryptodev_cb(void *op) 573 { 574 struct cryptop *crp = (struct cryptop *) op; 575 struct csession *cse = (struct csession *)crp->crp_opaque; 576 int error = 0; 577 578 mutex_spin_enter(&crypto_mtx); 579 cse->error = crp->crp_etype; 580 if (crp->crp_etype == EAGAIN) { 581 /* always drop mutex to call dispatch routine */ 582 mutex_spin_exit(&crypto_mtx); 583 error = crypto_dispatch(crp); 584 mutex_spin_enter(&crypto_mtx); 585 } 586 if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) { 587 cv_signal(&crp->crp_cv); 588 } 589 mutex_spin_exit(&crypto_mtx); 590 return 0; 591 } 592 593 static int 594 cryptodev_mcb(void *op) 595 { 596 struct cryptop *crp = (struct cryptop *) op; 597 struct csession *cse = (struct csession *)crp->crp_opaque; 598 int error=0; 599 600 mutex_spin_enter(&crypto_mtx); 601 cse->error = crp->crp_etype; 602 if (crp->crp_etype == EAGAIN) { 603 mutex_spin_exit(&crypto_mtx); 604 error = crypto_dispatch(crp); 605 mutex_spin_enter(&crypto_mtx); 606 } 607 if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) { 608 cv_signal(&crp->crp_cv); 609 } 610 611 TAILQ_INSERT_TAIL(&crp->fcrp->crp_ret_mq, crp, crp_next); 612 selnotify(&crp->fcrp->sinfo, 0, 0); 613 mutex_spin_exit(&crypto_mtx); 614 return 0; 615 } 616 617 static int 618 cryptodevkey_cb(void *op) 619 { 620 struct cryptkop *krp = op; 621 622 mutex_spin_enter(&crypto_mtx); 623 cv_signal(&krp->krp_cv); 624 mutex_spin_exit(&crypto_mtx); 625 return 0; 626 } 627 628 static int 629 cryptodevkey_mcb(void *op) 630 { 631 struct cryptkop *krp = op; 632 633 mutex_spin_enter(&crypto_mtx); 634 cv_signal(&krp->krp_cv); 635 TAILQ_INSERT_TAIL(&krp->fcrp->crp_ret_mkq, krp, krp_next); 636 selnotify(&krp->fcrp->sinfo, 0, 0); 637 mutex_spin_exit(&crypto_mtx); 638 return 0; 639 } 640 641 static int 642 cryptodev_key(struct crypt_kop *kop) 643 { 644 struct cryptkop *krp = NULL; 645 int error = EINVAL; 646 int in, out, size, i; 647 648 if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) 649 return EFBIG; 650 651 in = kop->crk_iparams; 652 out = kop->crk_oparams; 653 switch (kop->crk_op) { 654 case CRK_MOD_EXP: 655 if (in == 3 && out == 1) 656 break; 657 return EINVAL; 658 case CRK_MOD_EXP_CRT: 659 if (in == 6 && out == 1) 660 break; 661 return EINVAL; 662 case CRK_DSA_SIGN: 663 if (in == 5 && out == 2) 664 break; 665 return EINVAL; 666 case CRK_DSA_VERIFY: 667 if (in == 7 && out == 0) 668 break; 669 return EINVAL; 670 case CRK_DH_COMPUTE_KEY: 671 if (in == 3 && out == 1) 672 break; 673 return EINVAL; 674 case CRK_MOD_ADD: 675 if (in == 3 && out == 1) 676 break; 677 return EINVAL; 678 case CRK_MOD_ADDINV: 679 if (in == 2 && out == 1) 680 break; 681 return EINVAL; 682 case CRK_MOD_SUB: 683 if (in == 3 && out == 1) 684 break; 685 return EINVAL; 686 case CRK_MOD_MULT: 687 if (in == 3 && out == 1) 688 break; 689 return EINVAL; 690 case CRK_MOD_MULTINV: 691 if (in == 2 && out == 1) 692 break; 693 return EINVAL; 694 case CRK_MOD: 695 if (in == 2 && out == 1) 696 break; 697 return EINVAL; 698 default: 699 return EINVAL; 700 } 701 702 krp = pool_get(&cryptkop_pool, PR_WAITOK); 703 (void)memset(krp, 0, sizeof *krp); 704 cv_init(&krp->krp_cv, "crykdev"); 705 krp->krp_op = kop->crk_op; 706 krp->krp_status = kop->crk_status; 707 krp->krp_iparams = kop->crk_iparams; 708 krp->krp_oparams = kop->crk_oparams; 709 krp->krp_status = 0; 710 krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb; 711 712 for (i = 0; i < CRK_MAXPARAM; i++) 713 krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits; 714 for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) { 715 size = (krp->krp_param[i].crp_nbits + 7) / 8; 716 if (size == 0) 717 continue; 718 krp->krp_param[i].crp_p = kmem_alloc(size, KM_SLEEP); 719 if (i >= krp->krp_iparams) 720 continue; 721 error = copyin(kop->crk_param[i].crp_p, 722 krp->krp_param[i].crp_p, size); 723 if (error) 724 goto fail; 725 } 726 727 error = crypto_kdispatch(krp); 728 if (error != 0) { 729 goto fail; 730 } 731 732 mutex_spin_enter(&crypto_mtx); 733 while (!(krp->krp_flags & CRYPTO_F_DONE)) { 734 cv_wait(&krp->krp_cv, &crypto_mtx); /* XXX cv_wait_sig? */ 735 } 736 if (krp->krp_flags & CRYPTO_F_ONRETQ) { 737 DPRINTF(("cryptodev_key: DONE early, not via cryptoret.\n")); 738 (void)crypto_ret_kq_remove(krp); 739 } 740 mutex_spin_exit(&crypto_mtx); 741 742 if (krp->krp_status != 0) { 743 DPRINTF(("cryptodev_key: krp->krp_status 0x%08x\n", 744 krp->krp_status)); 745 error = krp->krp_status; 746 goto fail; 747 } 748 749 for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; 750 i++) { 751 size = (krp->krp_param[i].crp_nbits + 7) / 8; 752 if (size == 0) 753 continue; 754 error = copyout(krp->krp_param[i].crp_p, 755 kop->crk_param[i].crp_p, size); 756 if (error) { 757 DPRINTF(("cryptodev_key: copyout oparam %d failed, " 758 "error=%d\n", i-krp->krp_iparams, error)); 759 goto fail; 760 } 761 } 762 763 fail: 764 kop->crk_status = krp->krp_status; 765 for (i = 0; i < CRK_MAXPARAM; i++) { 766 struct crparam *kp = &(krp->krp_param[i]); 767 if (krp->krp_param[i].crp_p) { 768 size = (kp->crp_nbits + 7) / 8; 769 KASSERT(size > 0); 770 (void)memset(kp->crp_p, 0, size); 771 kmem_free(kp->crp_p, size); 772 } 773 } 774 pool_put(&cryptkop_pool, krp); 775 DPRINTF(("cryptodev_key: error=0x%08x\n", error)); 776 return error; 777 } 778 779 /* ARGSUSED */ 780 static int 781 cryptof_close(struct file *fp) 782 { 783 struct fcrypt *fcr = fp->f_data; 784 struct csession *cse; 785 786 mutex_spin_enter(&crypto_mtx); 787 while ((cse = TAILQ_FIRST(&fcr->csessions))) { 788 TAILQ_REMOVE(&fcr->csessions, cse, next); 789 (void)csefree(cse); 790 } 791 seldestroy(&fcr->sinfo); 792 fp->f_data = NULL; 793 mutex_spin_exit(&crypto_mtx); 794 795 pool_put(&fcrpl, fcr); 796 return 0; 797 } 798 799 /* csefind: call with crypto_mtx held. */ 800 static struct csession * 801 csefind(struct fcrypt *fcr, u_int ses) 802 { 803 struct csession *cse, *ret = NULL; 804 805 KASSERT(mutex_owned(&crypto_mtx)); 806 TAILQ_FOREACH(cse, &fcr->csessions, next) 807 if (cse->ses == ses) 808 ret = cse; 809 810 return ret; 811 } 812 813 /* csedelete: call with crypto_mtx held. */ 814 static int 815 csedelete(struct fcrypt *fcr, struct csession *cse_del) 816 { 817 struct csession *cse; 818 int ret = 0; 819 820 KASSERT(mutex_owned(&crypto_mtx)); 821 TAILQ_FOREACH(cse, &fcr->csessions, next) { 822 if (cse == cse_del) { 823 TAILQ_REMOVE(&fcr->csessions, cse, next); 824 ret = 1; 825 } 826 } 827 return ret; 828 } 829 830 /* cseadd: call with crypto_mtx held. */ 831 static struct csession * 832 cseadd(struct fcrypt *fcr, struct csession *cse) 833 { 834 KASSERT(mutex_owned(&crypto_mtx)); 835 /* don't let session ID wrap! */ 836 if (fcr->sesn + 1 == 0) return NULL; 837 TAILQ_INSERT_TAIL(&fcr->csessions, cse, next); 838 cse->ses = fcr->sesn++; 839 return cse; 840 } 841 842 /* csecreate: call with crypto_mtx held. */ 843 static struct csession * 844 csecreate(struct fcrypt *fcr, u_int64_t sid, void *key, u_int64_t keylen, 845 void *mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac, 846 struct enc_xform *txform, struct auth_hash *thash) 847 { 848 struct csession *cse; 849 850 KASSERT(mutex_owned(&crypto_mtx)); 851 cse = pool_get(&csepl, PR_NOWAIT); 852 if (cse == NULL) 853 return NULL; 854 cse->key = key; 855 cse->keylen = keylen/8; 856 cse->mackey = mackey; 857 cse->mackeylen = mackeylen/8; 858 cse->sid = sid; 859 cse->cipher = cipher; 860 cse->mac = mac; 861 cse->txform = txform; 862 cse->thash = thash; 863 cse->error = 0; 864 if (cseadd(fcr, cse)) 865 return cse; 866 else { 867 pool_put(&csepl, cse); 868 return NULL; 869 } 870 } 871 872 /* csefree: call with crypto_mtx held. */ 873 static int 874 csefree(struct csession *cse) 875 { 876 int error; 877 878 KASSERT(mutex_owned(&crypto_mtx)); 879 error = crypto_freesession(cse->sid); 880 if (cse->key) 881 free(cse->key, M_XDATA); 882 if (cse->mackey) 883 free(cse->mackey, M_XDATA); 884 pool_put(&csepl, cse); 885 return error; 886 } 887 888 static int 889 cryptoopen(dev_t dev, int flag, int mode, 890 struct lwp *l) 891 { 892 file_t *fp; 893 struct fcrypt *fcr; 894 int fd, error; 895 896 if (crypto_usercrypto == 0) 897 return ENXIO; 898 899 if ((error = fd_allocfile(&fp, &fd)) != 0) 900 return error; 901 902 fcr = pool_get(&fcrpl, PR_WAITOK); 903 mutex_spin_enter(&crypto_mtx); 904 TAILQ_INIT(&fcr->csessions); 905 TAILQ_INIT(&fcr->crp_ret_mq); 906 TAILQ_INIT(&fcr->crp_ret_mkq); 907 selinit(&fcr->sinfo); 908 /* 909 * Don't ever return session 0, to allow detection of 910 * failed creation attempts with multi-create ioctl. 911 */ 912 fcr->sesn = 1; 913 fcr->requestid = 1; 914 mutex_spin_exit(&crypto_mtx); 915 return fd_clone(fp, fd, flag, &cryptofops, fcr); 916 } 917 918 static int 919 cryptoread(dev_t dev, struct uio *uio, int ioflag) 920 { 921 return EIO; 922 } 923 924 static int 925 cryptowrite(dev_t dev, struct uio *uio, int ioflag) 926 { 927 return EIO; 928 } 929 930 int 931 cryptoselect(dev_t dev, int rw, struct lwp *l) 932 { 933 return 0; 934 } 935 936 /*static*/ 937 struct cdevsw crypto_cdevsw = { 938 /* open */ cryptoopen, 939 /* close */ noclose, 940 /* read */ cryptoread, 941 /* write */ cryptowrite, 942 /* ioctl */ noioctl, 943 /* ttstop?*/ nostop, 944 /* ??*/ notty, 945 /* poll */ cryptoselect /*nopoll*/, 946 /* mmap */ nommap, 947 /* kqfilter */ nokqfilter, 948 /* type */ D_OTHER, 949 }; 950 951 static int 952 cryptodev_mop(struct fcrypt *fcr, 953 struct crypt_n_op * cnop, 954 int count, struct lwp *l) 955 { 956 struct cryptop *crp = NULL; 957 struct cryptodesc *crde = NULL, *crda = NULL; 958 int req, error=0; 959 struct csession *cse; 960 961 for (req = 0; req < count; req++) { 962 mutex_spin_enter(&crypto_mtx); 963 cse = csefind(fcr, cnop[req].ses); 964 if (cse == NULL) { 965 DPRINTF(("csefind failed\n")); 966 cnop[req].status = EINVAL; 967 mutex_spin_exit(&crypto_mtx); 968 continue; 969 } 970 mutex_spin_exit(&crypto_mtx); 971 972 if (cnop[req].len > 256*1024-4) { 973 DPRINTF(("length failed\n")); 974 cnop[req].status = EINVAL; 975 continue; 976 } 977 if (cse->txform) { 978 if (cnop[req].len == 0 || 979 (cnop[req].len % cse->txform->blocksize) != 0) { 980 cnop[req].status = EINVAL; 981 continue; 982 } 983 } 984 985 crp = crypto_getreq((cse->txform != NULL) + 986 (cse->thash != NULL)); 987 if (crp == NULL) { 988 cnop[req].status = ENOMEM; 989 goto bail; 990 } 991 992 (void)memset(&crp->uio, 0, sizeof(crp->uio)); 993 crp->uio.uio_iovcnt = 1; 994 crp->uio.uio_resid = 0; 995 crp->uio.uio_rw = UIO_WRITE; 996 crp->uio.uio_iov = crp->iovec; 997 UIO_SETUP_SYSSPACE(&crp->uio); 998 memset(&crp->iovec, 0, sizeof(crp->iovec)); 999 crp->uio.uio_iov[0].iov_len = cnop[req].len; 1000 crp->uio.uio_iov[0].iov_base = kmem_alloc(cnop[req].len, 1001 KM_SLEEP); 1002 crp->uio.uio_resid = crp->uio.uio_iov[0].iov_len; 1003 1004 if (cse->thash) { 1005 crda = crp->crp_desc; 1006 if (cse->txform && crda) 1007 crde = crda->crd_next; 1008 } else { 1009 if (cse->txform) 1010 crde = crp->crp_desc; 1011 else { 1012 cnop[req].status = EINVAL; 1013 goto bail; 1014 } 1015 } 1016 1017 if ((copyin(cnop[req].src, 1018 crp->uio.uio_iov[0].iov_base, cnop[req].len))) { 1019 cnop[req].status = EINVAL; 1020 goto bail; 1021 } 1022 1023 if (crda) { 1024 crda->crd_skip = 0; 1025 crda->crd_len = cnop[req].len; 1026 crda->crd_inject = 0; /* ??? */ 1027 1028 crda->crd_alg = cse->mac; 1029 crda->crd_key = cse->mackey; 1030 crda->crd_klen = cse->mackeylen * 8; 1031 } 1032 1033 if (crde) { 1034 if (cnop[req].op == COP_ENCRYPT) 1035 crde->crd_flags |= CRD_F_ENCRYPT; 1036 else 1037 crde->crd_flags &= ~CRD_F_ENCRYPT; 1038 crde->crd_len = cnop[req].len; 1039 crde->crd_inject = 0; 1040 1041 crde->crd_alg = cse->cipher; 1042 #ifdef notyet /* XXX must notify h/w driver new key, drain */ 1043 if(cnop[req].key && cnop[req].keylen) { 1044 crde->crd_key = malloc(cnop[req].keylen, 1045 M_XDATA, M_WAITOK); 1046 if((error = copyin(cnop[req].key, 1047 crde->crd_key, cnop[req].keylen))) { 1048 cnop[req].status = EINVAL; 1049 goto bail; 1050 } 1051 crde->crd_klen = cnop[req].keylen * 8; 1052 } else { ... } 1053 #endif 1054 crde->crd_key = cse->key; 1055 crde->crd_klen = cse->keylen * 8; 1056 } 1057 1058 crp->crp_ilen = cnop[req].len; 1059 crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM | 1060 (cnop[req].flags & COP_F_BATCH); 1061 crp->crp_buf = (void *)&crp->uio; 1062 crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_mcb; 1063 crp->crp_sid = cse->sid; 1064 crp->crp_opaque = (void *)cse; 1065 crp->fcrp = fcr; 1066 crp->dst = cnop[req].dst; 1067 /* we can use the crp_ilen in cryptop(crp) for this */ 1068 crp->len = cnop[req].len; 1069 crp->mac = cnop[req].mac; 1070 1071 if (cnop[req].iv) { 1072 if (crde == NULL) { 1073 cnop[req].status = EINVAL; 1074 goto bail; 1075 } 1076 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 1077 cnop[req].status = EINVAL; 1078 goto bail; 1079 } 1080 if ((error = copyin(cnop[req].iv, crp->tmp_iv, 1081 cse->txform->blocksize))) { 1082 cnop[req].status = EINVAL; 1083 goto bail; 1084 } 1085 (void)memcpy(crde->crd_iv, crp->tmp_iv, 1086 cse->txform->blocksize); 1087 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; 1088 crde->crd_skip = 0; 1089 } else if (crde) { 1090 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 1091 crde->crd_skip = 0; 1092 } else { 1093 crde->crd_flags |= CRD_F_IV_PRESENT; 1094 crde->crd_skip = cse->txform->blocksize; 1095 crde->crd_len -= cse->txform->blocksize; 1096 } 1097 } 1098 1099 if (cnop[req].mac) { 1100 if (crda == NULL) { 1101 cnop[req].status = EINVAL; 1102 goto bail; 1103 } 1104 crp->crp_mac=cse->tmp_mac; 1105 } 1106 cnop[req].reqid = atomic_inc_32_nv(&(fcr->requestid)); 1107 crp->crp_reqid = cnop[req].reqid; 1108 crp->crp_usropaque = cnop[req].opaque; 1109 #ifdef notyet 1110 eagain: 1111 #endif 1112 cnop[req].status = crypto_dispatch(crp); 1113 mutex_spin_enter(&crypto_mtx); /* XXX why mutex? */ 1114 1115 switch (cnop[req].status) { 1116 #ifdef notyet /* don't loop forever -- but EAGAIN not possible here yet */ 1117 case EAGAIN: 1118 mutex_spin_exit(&crypto_mtx); 1119 goto eagain; 1120 break; 1121 #endif 1122 case 0: 1123 break; 1124 default: 1125 DPRINTF(("cryptodev_op: not waiting, error.\n")); 1126 mutex_spin_exit(&crypto_mtx); 1127 goto bail; 1128 } 1129 1130 mutex_spin_exit(&crypto_mtx); 1131 bail: 1132 if (cnop[req].status) { 1133 if (crp) { 1134 crypto_freereq(crp); 1135 if(cse->uio.uio_iov[0].iov_base) { 1136 kmem_free(cse->uio.uio_iov[0].iov_base, 1137 cse->uio.uio_iov[0].iov_len); 1138 } 1139 } 1140 error = 0; 1141 } 1142 } 1143 return error; 1144 } 1145 1146 static int 1147 cryptodev_mkey(struct fcrypt *fcr, struct crypt_n_kop *kop, int count) 1148 { 1149 struct cryptkop *krp = NULL; 1150 int error = EINVAL; 1151 int in, out, size, i, req; 1152 1153 for (req = 0; req < count; req++) { 1154 if (kop[req].crk_iparams + kop[req].crk_oparams > CRK_MAXPARAM) 1155 return EFBIG; 1156 1157 in = kop[req].crk_iparams; 1158 out = kop[req].crk_oparams; 1159 switch (kop[req].crk_op) { 1160 case CRK_MOD_EXP: 1161 if (in == 3 && out == 1) 1162 break; 1163 kop[req].crk_status = EINVAL; 1164 continue; 1165 case CRK_MOD_EXP_CRT: 1166 if (in == 6 && out == 1) 1167 break; 1168 kop[req].crk_status = EINVAL; 1169 continue; 1170 case CRK_DSA_SIGN: 1171 if (in == 5 && out == 2) 1172 break; 1173 kop[req].crk_status = EINVAL; 1174 continue; 1175 case CRK_DSA_VERIFY: 1176 if (in == 7 && out == 0) 1177 break; 1178 kop[req].crk_status = EINVAL; 1179 continue; 1180 case CRK_DH_COMPUTE_KEY: 1181 if (in == 3 && out == 1) 1182 break; 1183 kop[req].crk_status = EINVAL; 1184 continue; 1185 case CRK_MOD_ADD: 1186 if (in == 3 && out == 1) 1187 break; 1188 kop[req].crk_status = EINVAL; 1189 continue; 1190 case CRK_MOD_ADDINV: 1191 if (in == 2 && out == 1) 1192 break; 1193 kop[req].crk_status = EINVAL; 1194 continue; 1195 case CRK_MOD_SUB: 1196 if (in == 3 && out == 1) 1197 break; 1198 kop[req].crk_status = EINVAL; 1199 continue; 1200 case CRK_MOD_MULT: 1201 if (in == 3 && out == 1) 1202 break; 1203 kop[req].crk_status = EINVAL; 1204 continue; 1205 case CRK_MOD_MULTINV: 1206 if (in == 2 && out == 1) 1207 break; 1208 kop[req].crk_status = EINVAL; 1209 continue; 1210 case CRK_MOD: 1211 if (in == 2 && out == 1) 1212 break; 1213 kop[req].crk_status = EINVAL; 1214 continue; 1215 default: 1216 kop[req].crk_status = EINVAL; 1217 continue; 1218 } 1219 1220 krp = pool_get(&cryptkop_pool, PR_WAITOK); 1221 (void)memset(krp, 0, sizeof *krp); 1222 cv_init(&krp->krp_cv, "crykdev"); 1223 krp->krp_op = kop[req].crk_op; 1224 krp->krp_status = kop[req].crk_status; 1225 krp->krp_iparams = kop[req].crk_iparams; 1226 krp->krp_oparams = kop[req].crk_oparams; 1227 krp->krp_status = 0; 1228 krp->krp_callback = 1229 (int (*) (struct cryptkop *)) cryptodevkey_mcb; 1230 (void)memcpy(krp->crk_param, kop[req].crk_param, 1231 sizeof(kop[req].crk_param)); 1232 1233 krp->krp_flags = CRYPTO_F_CBIMM; 1234 1235 for (i = 0; i < CRK_MAXPARAM; i++) 1236 krp->krp_param[i].crp_nbits = 1237 kop[req].crk_param[i].crp_nbits; 1238 for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) { 1239 size = (krp->krp_param[i].crp_nbits + 7) / 8; 1240 if (size == 0) 1241 continue; 1242 krp->krp_param[i].crp_p = 1243 kmem_alloc(size, KM_SLEEP); 1244 if (i >= krp->krp_iparams) 1245 continue; 1246 kop[req].crk_status = 1247 copyin(kop[req].crk_param[i].crp_p, 1248 krp->krp_param[i].crp_p, size); 1249 if (kop[req].crk_status) 1250 goto fail; 1251 } 1252 krp->fcrp = fcr; 1253 1254 kop[req].crk_reqid = atomic_inc_32_nv(&(fcr->requestid)); 1255 krp->krp_reqid = kop[req].crk_reqid; 1256 krp->krp_usropaque = kop[req].crk_opaque; 1257 1258 kop[req].crk_status = crypto_kdispatch(krp); 1259 if (kop[req].crk_status != 0) { 1260 goto fail; 1261 } 1262 1263 fail: 1264 if(kop[req].crk_status) { 1265 if (krp) { 1266 kop[req].crk_status = krp->krp_status; 1267 for (i = 0; i < CRK_MAXPARAM; i++) { 1268 struct crparam *kp = 1269 &(krp->krp_param[i]); 1270 if (kp->crp_p) { 1271 size = (kp->crp_nbits + 7) / 8; 1272 KASSERT(size > 0); 1273 memset(kp->crp_p, 0, size); 1274 kmem_free(kp->crp_p, size); 1275 } 1276 } 1277 pool_put(&cryptkop_pool, krp); 1278 } 1279 } 1280 error = 0; 1281 } 1282 DPRINTF(("cryptodev_key: error=0x%08x\n", error)); 1283 return error; 1284 } 1285 1286 static int 1287 cryptodev_session(struct fcrypt *fcr, struct session_op *sop) { 1288 struct cryptoini cria, crie; 1289 struct enc_xform *txform = NULL; 1290 struct auth_hash *thash = NULL; 1291 struct csession *cse; 1292 u_int64_t sid; 1293 int error = 0; 1294 1295 /* XXX there must be a way to not embed the list of xforms here */ 1296 switch (sop->cipher) { 1297 case 0: 1298 break; 1299 case CRYPTO_DES_CBC: 1300 txform = &enc_xform_des; 1301 break; 1302 case CRYPTO_3DES_CBC: 1303 txform = &enc_xform_3des; 1304 break; 1305 case CRYPTO_BLF_CBC: 1306 txform = &enc_xform_blf; 1307 break; 1308 case CRYPTO_CAST_CBC: 1309 txform = &enc_xform_cast5; 1310 case CRYPTO_SKIPJACK_CBC: 1311 txform = &enc_xform_skipjack; 1312 break; 1313 case CRYPTO_AES_CBC: 1314 txform = &enc_xform_rijndael128; 1315 break; 1316 case CRYPTO_NULL_CBC: 1317 txform = &enc_xform_null; 1318 break; 1319 case CRYPTO_ARC4: 1320 txform = &enc_xform_arc4; 1321 break; 1322 default: 1323 DPRINTF(("Invalid cipher %d\n", sop->cipher)); 1324 return EINVAL; 1325 } 1326 1327 switch (sop->mac) { 1328 case 0: 1329 break; 1330 case CRYPTO_MD5_HMAC: 1331 thash = &auth_hash_hmac_md5; 1332 break; 1333 case CRYPTO_SHA1_HMAC: 1334 thash = &auth_hash_hmac_sha1; 1335 break; 1336 case CRYPTO_MD5_HMAC_96: 1337 thash = &auth_hash_hmac_md5_96; 1338 break; 1339 case CRYPTO_SHA1_HMAC_96: 1340 thash = &auth_hash_hmac_sha1_96; 1341 break; 1342 case CRYPTO_SHA2_HMAC: 1343 /* XXX switching on key length seems questionable */ 1344 if (sop->mackeylen == auth_hash_hmac_sha2_256.keysize) { 1345 thash = &auth_hash_hmac_sha2_256; 1346 } else if (sop->mackeylen == auth_hash_hmac_sha2_384.keysize) { 1347 thash = &auth_hash_hmac_sha2_384; 1348 } else if (sop->mackeylen == auth_hash_hmac_sha2_512.keysize) { 1349 thash = &auth_hash_hmac_sha2_512; 1350 } else { 1351 DPRINTF(("Invalid mackeylen %d\n", sop->mackeylen)); 1352 return EINVAL; 1353 } 1354 break; 1355 case CRYPTO_RIPEMD160_HMAC: 1356 thash = &auth_hash_hmac_ripemd_160; 1357 break; 1358 case CRYPTO_RIPEMD160_HMAC_96: 1359 thash = &auth_hash_hmac_ripemd_160_96; 1360 break; 1361 case CRYPTO_MD5: 1362 thash = &auth_hash_md5; 1363 break; 1364 case CRYPTO_SHA1: 1365 thash = &auth_hash_sha1; 1366 break; 1367 case CRYPTO_NULL_HMAC: 1368 thash = &auth_hash_null; 1369 break; 1370 default: 1371 DPRINTF(("Invalid mac %d\n", sop->mac)); 1372 return EINVAL; 1373 } 1374 1375 memset(&crie, 0, sizeof(crie)); 1376 memset(&cria, 0, sizeof(cria)); 1377 1378 if (txform) { 1379 crie.cri_alg = txform->type; 1380 crie.cri_klen = sop->keylen * 8; 1381 if (sop->keylen > txform->maxkey || 1382 sop->keylen < txform->minkey) { 1383 DPRINTF(("keylen %d not in [%d,%d]\n", 1384 sop->keylen, txform->minkey, txform->maxkey)); 1385 error = EINVAL; 1386 goto bail; 1387 } 1388 1389 crie.cri_key = malloc(crie.cri_klen / 8, M_XDATA, M_WAITOK); 1390 if ((error = copyin(sop->key, crie.cri_key, crie.cri_klen / 8))) 1391 goto bail; 1392 if (thash) 1393 crie.cri_next = &cria; /* XXX forces enc then hash? */ 1394 } 1395 1396 if (thash) { 1397 cria.cri_alg = thash->type; 1398 cria.cri_klen = sop->mackeylen * 8; 1399 if (sop->mackeylen != thash->keysize) { 1400 DPRINTF(("mackeylen %d != keysize %d\n", 1401 sop->mackeylen, thash->keysize)); 1402 error = EINVAL; 1403 goto bail; 1404 } 1405 if (cria.cri_klen) { 1406 cria.cri_key = malloc(cria.cri_klen / 8, M_XDATA, 1407 M_WAITOK); 1408 if ((error = copyin(sop->mackey, cria.cri_key, 1409 cria.cri_klen / 8))) { 1410 goto bail; 1411 } 1412 } 1413 } 1414 /* crypto_newsession requires that we hold the mutex. */ 1415 mutex_spin_enter(&crypto_mtx); 1416 error = crypto_newsession(&sid, (txform ? &crie : &cria), 1417 crypto_devallowsoft); 1418 if (!error) { 1419 cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen, 1420 cria.cri_key, cria.cri_klen, sop->cipher, sop->mac, 1421 txform, thash); 1422 if (cse != NULL) { 1423 sop->ses = cse->ses; 1424 } else { 1425 DPRINTF(("csecreate failed\n")); 1426 crypto_freesession(sid); 1427 error = EINVAL; 1428 } 1429 } else { 1430 DPRINTF(("SIOCSESSION violates kernel parameters %d\n", 1431 error)); 1432 } 1433 mutex_spin_exit(&crypto_mtx); 1434 bail: 1435 if (error) { 1436 if (crie.cri_key) { 1437 memset(crie.cri_key, 0, crie.cri_klen / 8); 1438 free(crie.cri_key, M_XDATA); 1439 } 1440 if (cria.cri_key) { 1441 memset(cria.cri_key, 0, cria.cri_klen / 8); 1442 free(cria.cri_key, M_XDATA); 1443 } 1444 } 1445 return error; 1446 } 1447 1448 static int 1449 cryptodev_msession(struct fcrypt *fcr, struct session_n_op *sn_ops, 1450 int count) 1451 { 1452 int i; 1453 1454 for (i = 0; i < count; i++, sn_ops++) { 1455 struct session_op s_op; 1456 s_op.cipher = sn_ops->cipher; 1457 s_op.mac = sn_ops->mac; 1458 s_op.keylen = sn_ops->keylen; 1459 s_op.key = sn_ops->key; 1460 s_op.mackeylen = sn_ops->mackeylen; 1461 s_op.mackey = sn_ops->mackey; 1462 1463 sn_ops->status = cryptodev_session(fcr, &s_op); 1464 sn_ops->ses = s_op.ses; 1465 } 1466 1467 return 0; 1468 } 1469 1470 static int 1471 cryptodev_msessionfin(struct fcrypt *fcr, int count, u_int32_t *sesid) 1472 { 1473 struct csession *cse; 1474 int req, error = 0; 1475 1476 mutex_spin_enter(&crypto_mtx); 1477 for(req = 0; req < count; req++) { 1478 cse = csefind(fcr, sesid[req]); 1479 if (cse == NULL) 1480 continue; 1481 csedelete(fcr, cse); 1482 error = csefree(cse); 1483 } 1484 mutex_spin_exit(&crypto_mtx); 1485 return 0; 1486 } 1487 1488 /* 1489 * collect as many completed requests as are availble, or count completed 1490 * requests whichever is less. 1491 * return the number of requests. 1492 */ 1493 static int 1494 cryptodev_getmstatus(struct fcrypt *fcr, struct crypt_result *crypt_res, 1495 int count) 1496 { 1497 struct cryptop *crp = NULL; 1498 struct cryptkop *krp = NULL; 1499 struct csession *cse; 1500 int i, size, req = 0; 1501 int completed=0; 1502 1503 /* On stack so nobody else can grab them -- no locking */ 1504 SLIST_HEAD(, cryptop) crp_delfree_l = 1505 SLIST_HEAD_INITIALIZER(crp_delfree_l); 1506 SLIST_HEAD(, cryptkop) krp_delfree_l = 1507 SLIST_HEAD_INITIALIZER(krp_delfree_l); 1508 1509 mutex_spin_enter(&crypto_mtx); 1510 1511 /* at this point we do not know which response user is requesting for 1512 * (symmetric or asymmetric) so we copyout one from each i.e if the 1513 * count is 2 then 1 from symmetric and 1 from asymmetric queue and 1514 * if 3 then 2 symmetric and 1 asymmetric and so on */ 1515 for(; req < count ;) { 1516 crp = TAILQ_FIRST(&fcr->crp_ret_mq); 1517 if(crp) { 1518 cse = (struct csession *)crp->crp_opaque; 1519 crypt_res[req].reqid = crp->crp_reqid; 1520 crypt_res[req].opaque = crp->crp_usropaque; 1521 completed++; 1522 cse = csefind(fcr, cse->ses); 1523 if (cse == NULL) { 1524 DPRINTF(("csefind failed\n")); 1525 crypt_res[req].status = EINVAL; 1526 goto bail; 1527 } 1528 1529 if (crp->crp_etype != 0) { 1530 crypt_res[req].status = crp->crp_etype; 1531 goto bail; 1532 } 1533 1534 if (cse->error) { 1535 crypt_res[req].status = cse->error; 1536 goto bail; 1537 } 1538 1539 if (crp->dst && (crypt_res[req].status = 1540 copyout(crp->uio.uio_iov[0].iov_base, crp->dst, 1541 crp->len))) 1542 goto bail; 1543 1544 if (crp->mac && (crypt_res[req].status = 1545 copyout(crp->crp_mac, crp->mac, 1546 cse->thash->authsize))) 1547 goto bail; 1548 bail: 1549 TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next); 1550 SLIST_INSERT_HEAD(&crp_delfree_l, crp, 1551 crp_qun.crp_lnext); 1552 req++; 1553 } 1554 1555 if(req < count) { 1556 krp = TAILQ_FIRST(&fcr->crp_ret_mkq); 1557 if (krp) { 1558 crypt_res[req].reqid = krp->krp_reqid; 1559 crypt_res[req].opaque = krp->krp_usropaque; 1560 completed++; 1561 if (krp->krp_status != 0) { 1562 DPRINTF(("cryptodev_key: " 1563 "krp->krp_status 0x%08x\n", 1564 krp->krp_status)); 1565 crypt_res[req].status = krp->krp_status; 1566 goto fail; 1567 } 1568 1569 for (i = krp->krp_iparams; i < krp->krp_iparams 1570 + krp->krp_oparams; i++) { 1571 size = (krp->krp_param[i].crp_nbits 1572 + 7) / 8; 1573 if (size == 0) 1574 continue; 1575 crypt_res[req].status = copyout 1576 (krp->krp_param[i].crp_p, 1577 krp->crk_param[i].crp_p, size); 1578 if (crypt_res[req].status) { 1579 DPRINTF(("cryptodev_key: " 1580 "copyout oparam %d failed, " 1581 "error=%d\n", 1582 i - krp->krp_iparams, 1583 crypt_res[req].status)); 1584 goto fail; 1585 } 1586 } 1587 fail: 1588 TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next); 1589 /* not sure what to do for this */ 1590 /* kop[req].crk_status = krp->krp_status; */ 1591 SLIST_INSERT_HEAD(&krp_delfree_l, krp, 1592 krp_qun.krp_lnext); 1593 } 1594 req++; 1595 } 1596 } 1597 mutex_spin_exit(&crypto_mtx); 1598 1599 while(!SLIST_EMPTY(&crp_delfree_l)) { 1600 crp = SLIST_FIRST(&crp_delfree_l); 1601 SLIST_REMOVE_HEAD(&crp_delfree_l, crp_qun.crp_lnext); 1602 kmem_free(crp->uio.uio_iov[0].iov_base, 1603 crp->uio.uio_iov[0].iov_len); 1604 crypto_freereq(crp); 1605 } 1606 1607 while(!SLIST_EMPTY(&krp_delfree_l)) { 1608 krp = SLIST_FIRST(&krp_delfree_l); 1609 for (i = 0; i < CRK_MAXPARAM; i++) { 1610 struct crparam *kp = &(krp->krp_param[i]); 1611 if (kp->crp_p) { 1612 size = (kp->crp_nbits + 7) / 8; 1613 KASSERT(size > 0); 1614 (void)memset(kp->crp_p, 0, size); 1615 kmem_free(kp->crp_p, size); 1616 } 1617 } 1618 SLIST_REMOVE_HEAD(&krp_delfree_l, krp_qun.krp_lnext); 1619 pool_put(&cryptkop_pool, krp); 1620 } 1621 return completed; 1622 } 1623 1624 static int 1625 cryptodev_getstatus (struct fcrypt *fcr, struct crypt_result *crypt_res) 1626 { 1627 struct cryptop *crp = NULL; 1628 struct cryptkop *krp = NULL; 1629 struct csession *cse; 1630 int i, size, req = 0; 1631 1632 mutex_spin_enter(&crypto_mtx); 1633 /* Here we dont know for which request the user is requesting the 1634 * response so checking in both the queues */ 1635 TAILQ_FOREACH(crp, &fcr->crp_ret_mq, crp_next) { 1636 if(crp && (crp->crp_reqid == crypt_res->reqid)) { 1637 cse = (struct csession *)crp->crp_opaque; 1638 crypt_res->opaque = crp->crp_usropaque; 1639 cse = csefind(fcr, cse->ses); 1640 if (cse == NULL) { 1641 DPRINTF(("csefind failed\n")); 1642 crypt_res->status = EINVAL; 1643 goto bail; 1644 } 1645 1646 if (crp->crp_etype != 0) { 1647 crypt_res->status = crp->crp_etype; 1648 goto bail; 1649 } 1650 1651 if (cse->error) { 1652 crypt_res->status = cse->error; 1653 goto bail; 1654 } 1655 1656 if (crp->dst && (crypt_res->status = 1657 copyout(crp->uio.uio_iov[0].iov_base, 1658 crp->dst, crp->len))) 1659 goto bail; 1660 1661 if (crp->mac && (crypt_res->status = 1662 copyout(crp->crp_mac, crp->mac, 1663 cse->thash->authsize))) 1664 goto bail; 1665 bail: 1666 TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next); 1667 1668 mutex_spin_exit(&crypto_mtx); 1669 crypto_freereq(crp); 1670 return 0; 1671 } 1672 } 1673 1674 TAILQ_FOREACH(krp, &fcr->crp_ret_mkq, krp_next) { 1675 if(krp && (krp->krp_reqid == crypt_res->reqid)) { 1676 crypt_res[req].opaque = krp->krp_usropaque; 1677 if (krp->krp_status != 0) { 1678 DPRINTF(("cryptodev_key: " 1679 "krp->krp_status 0x%08x\n", 1680 krp->krp_status)); 1681 crypt_res[req].status = krp->krp_status; 1682 goto fail; 1683 } 1684 1685 for (i = krp->krp_iparams; i < krp->krp_iparams + 1686 krp->krp_oparams; i++) { 1687 size = (krp->krp_param[i].crp_nbits + 7) / 8; 1688 if (size == 0) 1689 continue; 1690 crypt_res[req].status = copyout( 1691 krp->krp_param[i].crp_p, 1692 krp->crk_param[i].crp_p, size); 1693 if (crypt_res[req].status) { 1694 DPRINTF(("cryptodev_key: copyout oparam" 1695 "%d failed, error=%d\n", 1696 i - krp->krp_iparams, 1697 crypt_res[req].status)); 1698 goto fail; 1699 } 1700 } 1701 fail: 1702 TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next); 1703 mutex_spin_exit(&crypto_mtx); 1704 /* not sure what to do for this */ 1705 /* kop[req].crk_status = krp->krp_status; */ 1706 for (i = 0; i < CRK_MAXPARAM; i++) { 1707 struct crparam *kp = &(krp->krp_param[i]); 1708 if (kp->crp_p) { 1709 size = (kp->crp_nbits + 7) / 8; 1710 KASSERT(size > 0); 1711 memset(kp->crp_p, 0, size); 1712 kmem_free(kp->crp_p, size); 1713 } 1714 } 1715 pool_put(&cryptkop_pool, krp); 1716 return 0; 1717 } 1718 } 1719 mutex_spin_exit(&crypto_mtx); 1720 return EINPROGRESS; 1721 } 1722 1723 static int 1724 cryptof_poll(struct file *fp, int events) 1725 { 1726 struct fcrypt *fcr = (struct fcrypt *)fp->f_data; 1727 int revents = 0; 1728 1729 if (!(events & (POLLIN | POLLRDNORM))) { 1730 /* only support read and POLLIN */ 1731 return 0; 1732 } 1733 1734 mutex_spin_enter(&crypto_mtx); 1735 if (TAILQ_EMPTY(&fcr->crp_ret_mq) && TAILQ_EMPTY(&fcr->crp_ret_mkq)) { 1736 /* no completed requests pending, save the poll for later */ 1737 selrecord(curlwp, &fcr->sinfo); 1738 } else { 1739 /* let the app(s) know that there are completed requests */ 1740 revents = events & (POLLIN | POLLRDNORM); 1741 } 1742 mutex_spin_exit(&crypto_mtx); 1743 1744 return revents; 1745 } 1746 1747 /* 1748 * Pseudo-device initialization routine for /dev/crypto 1749 */ 1750 void cryptoattach(int); 1751 1752 void 1753 cryptoattach(int num) 1754 { 1755 pool_init(&fcrpl, sizeof(struct fcrypt), 0, 0, 0, "fcrpl", 1756 NULL, IPL_NET); /* XXX IPL_NET ("splcrypto") */ 1757 pool_init(&csepl, sizeof(struct csession), 0, 0, 0, "csepl", 1758 NULL, IPL_NET); /* XXX IPL_NET ("splcrypto") */ 1759 1760 /* 1761 * Preallocate space for 64 users, with 5 sessions each. 1762 * (consider that a TLS protocol session requires at least 1763 * 3DES, MD5, and SHA1 (both hashes are used in the PRF) for 1764 * the negotiation, plus HMAC_SHA1 for the actual SSL records, 1765 * consuming one session here for each algorithm. 1766 */ 1767 pool_prime(&fcrpl, 64); 1768 pool_prime(&csepl, 64 * 5); 1769 } 1770