1 /* $NetBSD: cryptodev.c,v 1.56 2011/05/06 21:48:46 drochner 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.56 2011/05/06 21:48:46 drochner 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 #include <sys/stat.h> 88 89 #include "opt_ocf.h" 90 #include "opt_compat_netbsd.h" 91 #include <opencrypto/cryptodev.h> 92 #include <opencrypto/cryptodev_internal.h> 93 #include <opencrypto/xform.h> 94 95 struct csession { 96 TAILQ_ENTRY(csession) next; 97 u_int64_t sid; 98 u_int32_t ses; 99 100 u_int32_t cipher; /* note: shares name space in crd_alg */ 101 const struct enc_xform *txform; 102 u_int32_t mac; /* note: shares name space in crd_alg */ 103 const struct auth_hash *thash; 104 u_int32_t comp_alg; /* note: shares name space in crd_alg */ 105 const struct comp_algo *tcomp; 106 107 void * key; 108 int keylen; 109 u_char tmp_iv[EALG_MAX_BLOCK_LEN]; 110 111 void * mackey; 112 int mackeylen; 113 u_char tmp_mac[CRYPTO_MAX_MAC_LEN]; 114 115 struct iovec iovec[1]; /* user requests never have more */ 116 struct uio uio; 117 int error; 118 }; 119 120 struct fcrypt { 121 TAILQ_HEAD(csessionlist, csession) csessions; 122 TAILQ_HEAD(crprethead, cryptop) crp_ret_mq; 123 TAILQ_HEAD(krprethead, cryptkop) crp_ret_mkq; 124 int sesn; 125 struct selinfo sinfo; 126 u_int32_t requestid; 127 struct timespec atime; 128 struct timespec mtime; 129 struct timespec btime; 130 }; 131 132 /* For our fixed-size allocations */ 133 static struct pool fcrpl; 134 static struct pool csepl; 135 136 /* Declaration of master device (fd-cloning/ctxt-allocating) entrypoints */ 137 static int cryptoopen(dev_t dev, int flag, int mode, struct lwp *l); 138 static int cryptoread(dev_t dev, struct uio *uio, int ioflag); 139 static int cryptowrite(dev_t dev, struct uio *uio, int ioflag); 140 static int cryptoselect(dev_t dev, int rw, struct lwp *l); 141 142 /* Declaration of cloned-device (per-ctxt) entrypoints */ 143 static int cryptof_read(struct file *, off_t *, struct uio *, 144 kauth_cred_t, int); 145 static int cryptof_write(struct file *, off_t *, struct uio *, 146 kauth_cred_t, int); 147 static int cryptof_ioctl(struct file *, u_long, void *); 148 static int cryptof_close(struct file *); 149 static int cryptof_poll(struct file *, int); 150 static int cryptof_stat(struct file *, struct stat *); 151 152 static const struct fileops cryptofops = { 153 .fo_read = cryptof_read, 154 .fo_write = cryptof_write, 155 .fo_ioctl = cryptof_ioctl, 156 .fo_fcntl = fnullop_fcntl, 157 .fo_poll = cryptof_poll, 158 .fo_stat = cryptof_stat, 159 .fo_close = cryptof_close, 160 .fo_kqfilter = fnullop_kqfilter, 161 .fo_restart = fnullop_restart, 162 }; 163 164 struct csession *cryptodev_csefind(struct fcrypt *, u_int); 165 static struct csession *csefind(struct fcrypt *, u_int); 166 static int csedelete(struct fcrypt *, struct csession *); 167 static struct csession *cseadd(struct fcrypt *, struct csession *); 168 static struct csession *csecreate(struct fcrypt *, u_int64_t, void *, 169 u_int64_t, void *, u_int64_t, u_int32_t, u_int32_t, u_int32_t, 170 const struct enc_xform *, const struct auth_hash *, 171 const struct comp_algo *); 172 static int csefree(struct csession *); 173 174 static int cryptodev_key(struct crypt_kop *); 175 static int cryptodev_mkey(struct fcrypt *, struct crypt_n_kop *, int); 176 static int cryptodev_msessionfin(struct fcrypt *, int, u_int32_t *); 177 178 static int cryptodev_cb(void *); 179 static int cryptodevkey_cb(void *); 180 181 static int cryptodev_mcb(void *); 182 static int cryptodevkey_mcb(void *); 183 184 static int cryptodev_getmstatus(struct fcrypt *, struct crypt_result *, 185 int); 186 static int cryptodev_getstatus(struct fcrypt *, struct crypt_result *); 187 188 #ifdef COMPAT_50 189 extern int ocryptof_ioctl(struct file *, u_long, void *); 190 #endif 191 192 /* 193 * sysctl-able control variables for /dev/crypto now defined in crypto.c: 194 * crypto_usercrypto, crypto_userasmcrypto, crypto_devallowsoft. 195 */ 196 197 /* ARGSUSED */ 198 int 199 cryptof_read(file_t *fp, off_t *poff, 200 struct uio *uio, kauth_cred_t cred, int flags) 201 { 202 return EIO; 203 } 204 205 /* ARGSUSED */ 206 int 207 cryptof_write(file_t *fp, off_t *poff, 208 struct uio *uio, kauth_cred_t cred, int flags) 209 { 210 return EIO; 211 } 212 213 /* ARGSUSED */ 214 int 215 cryptof_ioctl(struct file *fp, u_long cmd, void *data) 216 { 217 struct fcrypt *fcr = fp->f_data; 218 struct csession *cse; 219 struct session_op *sop; 220 struct session_n_op *snop; 221 struct crypt_op *cop; 222 struct crypt_mop *mop; 223 struct crypt_mkop *mkop; 224 struct crypt_n_op *cnop; 225 struct crypt_n_kop *knop; 226 struct crypt_sgop *sgop; 227 struct crypt_sfop *sfop; 228 struct cryptret *crypt_ret; 229 struct crypt_result *crypt_res; 230 u_int32_t ses; 231 u_int32_t *sesid; 232 int error = 0; 233 size_t count; 234 235 /* backwards compatibility */ 236 file_t *criofp; 237 struct fcrypt *criofcr; 238 int criofd; 239 240 mutex_spin_enter(&crypto_mtx); 241 getnanotime(&fcr->atime); 242 mutex_spin_exit(&crypto_mtx); 243 244 switch (cmd) { 245 case CRIOGET: /* XXX deprecated, remove after 5.0 */ 246 if ((error = fd_allocfile(&criofp, &criofd)) != 0) 247 return error; 248 criofcr = pool_get(&fcrpl, PR_WAITOK); 249 mutex_spin_enter(&crypto_mtx); 250 TAILQ_INIT(&criofcr->csessions); 251 TAILQ_INIT(&criofcr->crp_ret_mq); 252 TAILQ_INIT(&criofcr->crp_ret_mkq); 253 selinit(&criofcr->sinfo); 254 255 /* 256 * Don't ever return session 0, to allow detection of 257 * failed creation attempts with multi-create ioctl. 258 */ 259 criofcr->sesn = 1; 260 criofcr->requestid = 1; 261 mutex_spin_exit(&crypto_mtx); 262 (void)fd_clone(criofp, criofd, (FREAD|FWRITE), 263 &cryptofops, criofcr); 264 *(u_int32_t *)data = criofd; 265 return error; 266 break; 267 case CIOCGSESSION: 268 sop = (struct session_op *)data; 269 error = cryptodev_session(fcr, sop); 270 break; 271 case CIOCNGSESSION: 272 sgop = (struct crypt_sgop *)data; 273 snop = kmem_alloc((sgop->count * 274 sizeof(struct session_n_op)), KM_SLEEP); 275 error = copyin(sgop->sessions, snop, sgop->count * 276 sizeof(struct session_n_op)); 277 if (error) { 278 goto mbail; 279 } 280 281 mutex_spin_enter(&crypto_mtx); 282 fcr->mtime = fcr->atime; 283 mutex_spin_exit(&crypto_mtx); 284 error = cryptodev_msession(fcr, snop, sgop->count); 285 if (error) { 286 goto mbail; 287 } 288 289 error = copyout(snop, sgop->sessions, sgop->count * 290 sizeof(struct session_n_op)); 291 mbail: 292 kmem_free(snop, sgop->count * sizeof(struct session_n_op)); 293 break; 294 case CIOCFSESSION: 295 mutex_spin_enter(&crypto_mtx); 296 fcr->mtime = fcr->atime; 297 ses = *(u_int32_t *)data; 298 cse = csefind(fcr, ses); 299 if (cse == NULL) { 300 mutex_spin_exit(&crypto_mtx); 301 return EINVAL; 302 } 303 csedelete(fcr, cse); 304 mutex_spin_exit(&crypto_mtx); 305 error = csefree(cse); 306 break; 307 case CIOCNFSESSION: 308 mutex_spin_enter(&crypto_mtx); 309 fcr->mtime = fcr->atime; 310 mutex_spin_exit(&crypto_mtx); 311 sfop = (struct crypt_sfop *)data; 312 sesid = kmem_alloc((sfop->count * sizeof(u_int32_t)), 313 KM_SLEEP); 314 error = copyin(sfop->sesid, sesid, 315 (sfop->count * sizeof(u_int32_t))); 316 if (!error) { 317 error = cryptodev_msessionfin(fcr, sfop->count, sesid); 318 } 319 kmem_free(sesid, (sfop->count * sizeof(u_int32_t))); 320 break; 321 case CIOCCRYPT: 322 mutex_spin_enter(&crypto_mtx); 323 fcr->mtime = fcr->atime; 324 cop = (struct crypt_op *)data; 325 cse = csefind(fcr, cop->ses); 326 mutex_spin_exit(&crypto_mtx); 327 if (cse == NULL) { 328 DPRINTF(("csefind failed\n")); 329 return EINVAL; 330 } 331 error = cryptodev_op(cse, cop, curlwp); 332 DPRINTF(("cryptodev_op error = %d\n", error)); 333 break; 334 case CIOCNCRYPTM: 335 mutex_spin_enter(&crypto_mtx); 336 fcr->mtime = fcr->atime; 337 mutex_spin_exit(&crypto_mtx); 338 mop = (struct crypt_mop *)data; 339 cnop = kmem_alloc((mop->count * sizeof(struct crypt_n_op)), 340 KM_SLEEP); 341 error = copyin(mop->reqs, cnop, 342 (mop->count * sizeof(struct crypt_n_op))); 343 if(!error) { 344 error = cryptodev_mop(fcr, cnop, mop->count, curlwp); 345 if (!error) { 346 error = copyout(cnop, mop->reqs, 347 (mop->count * sizeof(struct crypt_n_op))); 348 } 349 } 350 kmem_free(cnop, (mop->count * sizeof(struct crypt_n_op))); 351 break; 352 case CIOCKEY: 353 error = cryptodev_key((struct crypt_kop *)data); 354 DPRINTF(("cryptodev_key error = %d\n", error)); 355 break; 356 case CIOCNFKEYM: 357 mutex_spin_enter(&crypto_mtx); 358 fcr->mtime = fcr->atime; 359 mutex_spin_exit(&crypto_mtx); 360 mkop = (struct crypt_mkop *)data; 361 knop = kmem_alloc((mkop->count * sizeof(struct crypt_n_kop)), 362 KM_SLEEP); 363 error = copyin(mkop->reqs, knop, 364 (mkop->count * sizeof(struct crypt_n_kop))); 365 if (!error) { 366 error = cryptodev_mkey(fcr, knop, mkop->count); 367 if (!error) 368 error = copyout(knop, mkop->reqs, 369 (mkop->count * sizeof(struct crypt_n_kop))); 370 } 371 kmem_free(knop, (mkop->count * sizeof(struct crypt_n_kop))); 372 break; 373 case CIOCASYMFEAT: 374 error = crypto_getfeat((int *)data); 375 break; 376 case CIOCNCRYPTRETM: 377 mutex_spin_enter(&crypto_mtx); 378 fcr->mtime = fcr->atime; 379 mutex_spin_exit(&crypto_mtx); 380 crypt_ret = (struct cryptret *)data; 381 count = crypt_ret->count; 382 crypt_res = kmem_alloc((count * sizeof(struct crypt_result)), 383 KM_SLEEP); 384 error = copyin(crypt_ret->results, crypt_res, 385 (count * sizeof(struct crypt_result))); 386 if (error) 387 goto reterr; 388 crypt_ret->count = cryptodev_getmstatus(fcr, crypt_res, 389 crypt_ret->count); 390 /* sanity check count */ 391 if (crypt_ret->count > count) { 392 printf("%s.%d: error returned count %zd > original " 393 " count %zd\n", 394 __FILE__, __LINE__, crypt_ret->count, count); 395 crypt_ret->count = count; 396 397 } 398 error = copyout(crypt_res, crypt_ret->results, 399 (crypt_ret->count * sizeof(struct crypt_result))); 400 reterr: 401 kmem_free(crypt_res, (count * sizeof(struct crypt_result))); 402 break; 403 case CIOCNCRYPTRET: 404 error = cryptodev_getstatus(fcr, (struct crypt_result *)data); 405 break; 406 default: 407 #ifdef COMPAT_50 408 /* Check for backward compatible commands */ 409 error = ocryptof_ioctl(fp, cmd, data); 410 #else 411 return EINVAL; 412 #endif 413 } 414 return error; 415 } 416 417 int 418 cryptodev_op(struct csession *cse, struct crypt_op *cop, struct lwp *l) 419 { 420 struct cryptop *crp = NULL; 421 struct cryptodesc *crde = NULL, *crda = NULL, *crdc = NULL; 422 int error; 423 int iov_len = cop->len; 424 int flags=0; 425 int dst_len; /* copyout size */ 426 427 if (cop->len > 256*1024-4) 428 return E2BIG; 429 430 if (cse->txform) { 431 if (cop->len == 0 || (cop->len % cse->txform->blocksize) != 0) 432 return EINVAL; 433 } 434 435 DPRINTF(("cryptodev_op[%u]: iov_len %d\n", 436 CRYPTO_SESID2LID(cse->sid), iov_len)); 437 if ((cse->tcomp) && cop->dst_len) { 438 if (iov_len < cop->dst_len) { 439 /* Need larger iov to deal with decompress */ 440 iov_len = cop->dst_len; 441 } 442 DPRINTF(("cryptodev_op: iov_len -> %d for decompress\n", iov_len)); 443 } 444 445 (void)memset(&cse->uio, 0, sizeof(cse->uio)); 446 cse->uio.uio_iovcnt = 1; 447 cse->uio.uio_resid = 0; 448 cse->uio.uio_rw = UIO_WRITE; 449 cse->uio.uio_iov = cse->iovec; 450 UIO_SETUP_SYSSPACE(&cse->uio); 451 memset(&cse->iovec, 0, sizeof(cse->iovec)); 452 453 /* the iov needs to be big enough to handle the uncompressed 454 * data.... */ 455 cse->uio.uio_iov[0].iov_len = iov_len; 456 cse->uio.uio_iov[0].iov_base = kmem_alloc(iov_len, KM_SLEEP); 457 cse->uio.uio_resid = cse->uio.uio_iov[0].iov_len; 458 DPRINTF(("cryptodev_op[%u]: uio.iov_base %p malloced %d bytes\n", 459 CRYPTO_SESID2LID(cse->sid), 460 cse->uio.uio_iov[0].iov_base, iov_len)); 461 462 crp = crypto_getreq((cse->tcomp != NULL) + (cse->txform != NULL) + (cse->thash != NULL)); 463 if (crp == NULL) { 464 error = ENOMEM; 465 goto bail; 466 } 467 DPRINTF(("cryptodev_op[%u]: crp %p\n", 468 CRYPTO_SESID2LID(cse->sid), crp)); 469 470 /* crds are always ordered tcomp, thash, then txform */ 471 /* with optional missing links */ 472 473 /* XXX: If we're going to compress then hash or encrypt, we need 474 * to be able to pass on the new size of the data. 475 */ 476 477 if (cse->tcomp) { 478 crdc = crp->crp_desc; 479 } 480 481 if (cse->thash) { 482 crda = crdc ? crdc->crd_next : crp->crp_desc; 483 if (cse->txform && crda) 484 crde = crda->crd_next; 485 } else { 486 if (cse->txform) { 487 crde = crdc ? crdc->crd_next : crp->crp_desc; 488 } else if (!cse->tcomp) { 489 error = EINVAL; 490 goto bail; 491 } 492 } 493 494 DPRINTF(("ocf[%u]: iov_len %zu, cop->len %u\n", 495 CRYPTO_SESID2LID(cse->sid), 496 cse->uio.uio_iov[0].iov_len, 497 cop->len)); 498 499 if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len))) 500 { 501 printf("copyin failed %s %d \n", (char *)cop->src, error); 502 goto bail; 503 } 504 505 if (crdc) { 506 switch (cop->op) { 507 case COP_COMP: 508 crdc->crd_flags |= CRD_F_COMP; 509 break; 510 case COP_DECOMP: 511 crdc->crd_flags &= ~CRD_F_COMP; 512 break; 513 default: 514 break; 515 } 516 /* more data to follow? */ 517 if (cop->flags & COP_F_MORE) { 518 flags |= CRYPTO_F_MORE; 519 } 520 crdc->crd_len = cop->len; 521 crdc->crd_inject = 0; 522 523 crdc->crd_alg = cse->comp_alg; 524 crdc->crd_key = NULL; 525 crdc->crd_klen = 0; 526 DPRINTF(("cryptodev_op[%u]: crdc setup for comp_alg %d.\n", 527 CRYPTO_SESID2LID(cse->sid), crdc->crd_alg)); 528 } 529 530 if (crda) { 531 crda->crd_skip = 0; 532 crda->crd_len = cop->len; 533 crda->crd_inject = 0; /* ??? */ 534 535 crda->crd_alg = cse->mac; 536 crda->crd_key = cse->mackey; 537 crda->crd_klen = cse->mackeylen * 8; 538 DPRINTF(("cryptodev_op: crda setup for mac %d.\n", crda->crd_alg)); 539 } 540 541 if (crde) { 542 switch (cop->op) { 543 case COP_ENCRYPT: 544 crde->crd_flags |= CRD_F_ENCRYPT; 545 break; 546 case COP_DECRYPT: 547 crde->crd_flags &= ~CRD_F_ENCRYPT; 548 break; 549 default: 550 break; 551 } 552 crde->crd_len = cop->len; 553 crde->crd_inject = 0; 554 555 crde->crd_alg = cse->cipher; 556 crde->crd_key = cse->key; 557 crde->crd_klen = cse->keylen * 8; 558 DPRINTF(("cryptodev_op: crde setup for cipher %d.\n", crde->crd_alg)); 559 } 560 561 562 crp->crp_ilen = cop->len; 563 /* The reqest is flagged as CRYPTO_F_USER as long as it is running 564 * in the user IOCTL thread. This flag lets us skip using the retq for 565 * the request if it completes immediately. If the request ends up being 566 * delayed or is not completed immediately the flag is removed. 567 */ 568 crp->crp_flags = CRYPTO_F_IOV | (cop->flags & COP_F_BATCH) | CRYPTO_F_USER | 569 flags; 570 crp->crp_buf = (void *)&cse->uio; 571 crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb; 572 crp->crp_sid = cse->sid; 573 crp->crp_opaque = (void *)cse; 574 575 if (cop->iv) { 576 if (crde == NULL) { 577 error = EINVAL; 578 goto bail; 579 } 580 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 581 error = EINVAL; 582 goto bail; 583 } 584 if ((error = copyin(cop->iv, cse->tmp_iv, 585 cse->txform->blocksize))) 586 goto bail; 587 (void)memcpy(crde->crd_iv, cse->tmp_iv, cse->txform->blocksize); 588 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; 589 crde->crd_skip = 0; 590 } else if (crde) { 591 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 592 crde->crd_skip = 0; 593 } else { 594 crde->crd_flags |= CRD_F_IV_PRESENT; 595 crde->crd_skip = cse->txform->blocksize; 596 crde->crd_len -= cse->txform->blocksize; 597 } 598 } 599 600 if (cop->mac) { 601 if (crda == NULL) { 602 error = EINVAL; 603 goto bail; 604 } 605 crp->crp_mac=cse->tmp_mac; 606 } 607 608 /* 609 * XXX there was a comment here which said that we went to 610 * XXX splcrypto() but needed to only if CRYPTO_F_CBIMM, 611 * XXX disabled on NetBSD since 1.6O due to a race condition. 612 * XXX But crypto_dispatch went to splcrypto() itself! (And 613 * XXX now takes the crypto_mtx mutex itself). We do, however, 614 * XXX need to hold the mutex across the call to cv_wait(). 615 * XXX (should we arrange for crypto_dispatch to return to 616 * XXX us with it held? it seems quite ugly to do so.) 617 */ 618 #ifdef notyet 619 eagain: 620 #endif 621 error = crypto_dispatch(crp); 622 mutex_spin_enter(&crypto_mtx); 623 624 /* 625 * If the request was going to be completed by the 626 * ioctl thread then it would have been done by now. 627 * Remove the F_USER flag so crypto_done() is not confused 628 * if the crypto device calls it after this point. 629 */ 630 crp->crp_flags &= ~(CRYPTO_F_USER); 631 632 switch (error) { 633 #ifdef notyet /* don't loop forever -- but EAGAIN not possible here yet */ 634 case EAGAIN: 635 mutex_spin_exit(&crypto_mtx); 636 goto eagain; 637 break; 638 #endif 639 case 0: 640 break; 641 default: 642 DPRINTF(("cryptodev_op: not waiting, error.\n")); 643 mutex_spin_exit(&crypto_mtx); 644 goto bail; 645 } 646 647 while (!(crp->crp_flags & CRYPTO_F_DONE)) { 648 DPRINTF(("cryptodev_op[%d]: sleeping on cv %p for crp %p\n", 649 (uint32_t)cse->sid, &crp->crp_cv, crp)); 650 cv_wait(&crp->crp_cv, &crypto_mtx); /* XXX cv_wait_sig? */ 651 } 652 if (crp->crp_flags & CRYPTO_F_ONRETQ) { 653 /* XXX this should never happen now with the CRYPTO_F_USER flag 654 * changes. 655 */ 656 DPRINTF(("cryptodev_op: DONE, not woken by cryptoret.\n")); 657 (void)crypto_ret_q_remove(crp); 658 } 659 mutex_spin_exit(&crypto_mtx); 660 661 if (crp->crp_etype != 0) { 662 DPRINTF(("cryptodev_op: crp_etype %d\n", crp->crp_etype)); 663 error = crp->crp_etype; 664 goto bail; 665 } 666 667 if (cse->error) { 668 DPRINTF(("cryptodev_op: cse->error %d\n", cse->error)); 669 error = cse->error; 670 goto bail; 671 } 672 673 dst_len = crp->crp_ilen; 674 /* let the user know how much data was returned */ 675 if (crp->crp_olen) { 676 dst_len = cop->dst_len = crp->crp_olen; 677 } 678 crp->len = dst_len; 679 680 if (cop->dst) { 681 DPRINTF(("cryptodev_op: copyout %d bytes to %p\n", dst_len, cop->dst)); 682 } 683 if (cop->dst && 684 (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, dst_len))) 685 { 686 DPRINTF(("cryptodev_op: copyout error %d\n", error)); 687 goto bail; 688 } 689 690 if (cop->mac && 691 (error = copyout(crp->crp_mac, cop->mac, cse->thash->authsize))) { 692 DPRINTF(("cryptodev_op: mac copyout error %d\n", error)); 693 goto bail; 694 } 695 696 697 bail: 698 if (crp) { 699 crypto_freereq(crp); 700 } 701 if (cse->uio.uio_iov[0].iov_base) { 702 kmem_free(cse->uio.uio_iov[0].iov_base,iov_len); 703 } 704 705 return error; 706 } 707 708 static int 709 cryptodev_cb(void *op) 710 { 711 struct cryptop *crp = (struct cryptop *) op; 712 struct csession *cse = (struct csession *)crp->crp_opaque; 713 int error = 0; 714 715 mutex_spin_enter(&crypto_mtx); 716 cse->error = crp->crp_etype; 717 if (crp->crp_etype == EAGAIN) { 718 /* always drop mutex to call dispatch routine */ 719 mutex_spin_exit(&crypto_mtx); 720 error = crypto_dispatch(crp); 721 mutex_spin_enter(&crypto_mtx); 722 } 723 if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) { 724 cv_signal(&crp->crp_cv); 725 } 726 mutex_spin_exit(&crypto_mtx); 727 return 0; 728 } 729 730 static int 731 cryptodev_mcb(void *op) 732 { 733 struct cryptop *crp = (struct cryptop *) op; 734 struct csession *cse = (struct csession *)crp->crp_opaque; 735 int error=0; 736 737 mutex_spin_enter(&crypto_mtx); 738 cse->error = crp->crp_etype; 739 if (crp->crp_etype == EAGAIN) { 740 mutex_spin_exit(&crypto_mtx); 741 error = crypto_dispatch(crp); 742 mutex_spin_enter(&crypto_mtx); 743 } 744 if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) { 745 cv_signal(&crp->crp_cv); 746 } 747 748 TAILQ_INSERT_TAIL(&crp->fcrp->crp_ret_mq, crp, crp_next); 749 selnotify(&crp->fcrp->sinfo, 0, 0); 750 mutex_spin_exit(&crypto_mtx); 751 return 0; 752 } 753 754 static int 755 cryptodevkey_cb(void *op) 756 { 757 struct cryptkop *krp = op; 758 759 mutex_spin_enter(&crypto_mtx); 760 cv_signal(&krp->krp_cv); 761 mutex_spin_exit(&crypto_mtx); 762 return 0; 763 } 764 765 static int 766 cryptodevkey_mcb(void *op) 767 { 768 struct cryptkop *krp = op; 769 770 mutex_spin_enter(&crypto_mtx); 771 cv_signal(&krp->krp_cv); 772 TAILQ_INSERT_TAIL(&krp->fcrp->crp_ret_mkq, krp, krp_next); 773 selnotify(&krp->fcrp->sinfo, 0, 0); 774 mutex_spin_exit(&crypto_mtx); 775 return 0; 776 } 777 778 static int 779 cryptodev_key(struct crypt_kop *kop) 780 { 781 struct cryptkop *krp = NULL; 782 int error = EINVAL; 783 int in, out, size, i; 784 785 if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) 786 return EFBIG; 787 788 in = kop->crk_iparams; 789 out = kop->crk_oparams; 790 switch (kop->crk_op) { 791 case CRK_MOD_EXP: 792 if (in == 3 && out == 1) 793 break; 794 return EINVAL; 795 case CRK_MOD_EXP_CRT: 796 if (in == 6 && out == 1) 797 break; 798 return EINVAL; 799 case CRK_DSA_SIGN: 800 if (in == 5 && out == 2) 801 break; 802 return EINVAL; 803 case CRK_DSA_VERIFY: 804 if (in == 7 && out == 0) 805 break; 806 return EINVAL; 807 case CRK_DH_COMPUTE_KEY: 808 if (in == 3 && out == 1) 809 break; 810 return EINVAL; 811 case CRK_MOD_ADD: 812 if (in == 3 && out == 1) 813 break; 814 return EINVAL; 815 case CRK_MOD_ADDINV: 816 if (in == 2 && out == 1) 817 break; 818 return EINVAL; 819 case CRK_MOD_SUB: 820 if (in == 3 && out == 1) 821 break; 822 return EINVAL; 823 case CRK_MOD_MULT: 824 if (in == 3 && out == 1) 825 break; 826 return EINVAL; 827 case CRK_MOD_MULTINV: 828 if (in == 2 && out == 1) 829 break; 830 return EINVAL; 831 case CRK_MOD: 832 if (in == 2 && out == 1) 833 break; 834 return EINVAL; 835 default: 836 return EINVAL; 837 } 838 839 krp = pool_get(&cryptkop_pool, PR_WAITOK); 840 (void)memset(krp, 0, sizeof *krp); 841 cv_init(&krp->krp_cv, "crykdev"); 842 krp->krp_op = kop->crk_op; 843 krp->krp_status = kop->crk_status; 844 krp->krp_iparams = kop->crk_iparams; 845 krp->krp_oparams = kop->crk_oparams; 846 krp->krp_status = 0; 847 krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb; 848 849 for (i = 0; i < CRK_MAXPARAM; i++) 850 krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits; 851 for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) { 852 size = (krp->krp_param[i].crp_nbits + 7) / 8; 853 if (size == 0) 854 continue; 855 krp->krp_param[i].crp_p = kmem_alloc(size, KM_SLEEP); 856 if (i >= krp->krp_iparams) 857 continue; 858 error = copyin(kop->crk_param[i].crp_p, 859 krp->krp_param[i].crp_p, size); 860 if (error) 861 goto fail; 862 } 863 864 error = crypto_kdispatch(krp); 865 if (error != 0) { 866 goto fail; 867 } 868 869 mutex_spin_enter(&crypto_mtx); 870 while (!(krp->krp_flags & CRYPTO_F_DONE)) { 871 cv_wait(&krp->krp_cv, &crypto_mtx); /* XXX cv_wait_sig? */ 872 } 873 if (krp->krp_flags & CRYPTO_F_ONRETQ) { 874 DPRINTF(("cryptodev_key: DONE early, not via cryptoret.\n")); 875 (void)crypto_ret_kq_remove(krp); 876 } 877 mutex_spin_exit(&crypto_mtx); 878 879 if (krp->krp_status != 0) { 880 DPRINTF(("cryptodev_key: krp->krp_status 0x%08x\n", 881 krp->krp_status)); 882 error = krp->krp_status; 883 goto fail; 884 } 885 886 for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; 887 i++) { 888 size = (krp->krp_param[i].crp_nbits + 7) / 8; 889 if (size == 0) 890 continue; 891 error = copyout(krp->krp_param[i].crp_p, 892 kop->crk_param[i].crp_p, size); 893 if (error) { 894 DPRINTF(("cryptodev_key: copyout oparam %d failed, " 895 "error=%d\n", i-krp->krp_iparams, error)); 896 goto fail; 897 } 898 } 899 900 fail: 901 kop->crk_status = krp->krp_status; 902 for (i = 0; i < CRK_MAXPARAM; i++) { 903 struct crparam *kp = &(krp->krp_param[i]); 904 if (krp->krp_param[i].crp_p) { 905 size = (kp->crp_nbits + 7) / 8; 906 KASSERT(size > 0); 907 (void)memset(kp->crp_p, 0, size); 908 kmem_free(kp->crp_p, size); 909 } 910 } 911 cv_destroy(&krp->krp_cv); 912 pool_put(&cryptkop_pool, krp); 913 DPRINTF(("cryptodev_key: error=0x%08x\n", error)); 914 return error; 915 } 916 917 /* ARGSUSED */ 918 static int 919 cryptof_close(struct file *fp) 920 { 921 struct fcrypt *fcr = fp->f_data; 922 struct csession *cse; 923 924 mutex_spin_enter(&crypto_mtx); 925 while ((cse = TAILQ_FIRST(&fcr->csessions))) { 926 TAILQ_REMOVE(&fcr->csessions, cse, next); 927 mutex_spin_exit(&crypto_mtx); 928 (void)csefree(cse); 929 mutex_spin_enter(&crypto_mtx); 930 } 931 seldestroy(&fcr->sinfo); 932 fp->f_data = NULL; 933 mutex_spin_exit(&crypto_mtx); 934 935 pool_put(&fcrpl, fcr); 936 return 0; 937 } 938 939 /* needed for compatibility module */ 940 struct csession *cryptodev_csefind(struct fcrypt *fcr, u_int ses) 941 { 942 return csefind(fcr, ses); 943 } 944 945 /* csefind: call with crypto_mtx held. */ 946 static struct csession * 947 csefind(struct fcrypt *fcr, u_int ses) 948 { 949 struct csession *cse, *cnext, *ret = NULL; 950 951 KASSERT(mutex_owned(&crypto_mtx)); 952 TAILQ_FOREACH_SAFE(cse, &fcr->csessions, next, cnext) 953 if (cse->ses == ses) 954 ret = cse; 955 956 return ret; 957 } 958 959 /* csedelete: call with crypto_mtx held. */ 960 static int 961 csedelete(struct fcrypt *fcr, struct csession *cse_del) 962 { 963 struct csession *cse, *cnext; 964 int ret = 0; 965 966 KASSERT(mutex_owned(&crypto_mtx)); 967 TAILQ_FOREACH_SAFE(cse, &fcr->csessions, next, cnext) { 968 if (cse == cse_del) { 969 TAILQ_REMOVE(&fcr->csessions, cse, next); 970 ret = 1; 971 } 972 } 973 return ret; 974 } 975 976 static struct csession * 977 cseadd(struct fcrypt *fcr, struct csession *cse) 978 { 979 mutex_spin_enter(&crypto_mtx); 980 /* don't let session ID wrap! */ 981 if (fcr->sesn + 1 == 0) return NULL; 982 TAILQ_INSERT_TAIL(&fcr->csessions, cse, next); 983 cse->ses = fcr->sesn++; 984 mutex_spin_exit(&crypto_mtx); 985 return cse; 986 } 987 988 static struct csession * 989 csecreate(struct fcrypt *fcr, u_int64_t sid, void *key, u_int64_t keylen, 990 void *mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac, 991 u_int32_t comp_alg, const struct enc_xform *txform, 992 const struct auth_hash *thash, const struct comp_algo *tcomp) 993 { 994 struct csession *cse; 995 996 cse = pool_get(&csepl, PR_NOWAIT); 997 if (cse == NULL) 998 return NULL; 999 cse->key = key; 1000 cse->keylen = keylen/8; 1001 cse->mackey = mackey; 1002 cse->mackeylen = mackeylen/8; 1003 cse->sid = sid; 1004 cse->cipher = cipher; 1005 cse->mac = mac; 1006 cse->comp_alg = comp_alg; 1007 cse->txform = txform; 1008 cse->thash = thash; 1009 cse->tcomp = tcomp; 1010 cse->error = 0; 1011 if (cseadd(fcr, cse)) 1012 return cse; 1013 else { 1014 pool_put(&csepl, cse); 1015 return NULL; 1016 } 1017 } 1018 1019 /* csefree: call with crypto_mtx held. */ 1020 static int 1021 csefree(struct csession *cse) 1022 { 1023 int error; 1024 1025 error = crypto_freesession(cse->sid); 1026 if (cse->key) 1027 free(cse->key, M_XDATA); 1028 if (cse->mackey) 1029 free(cse->mackey, M_XDATA); 1030 pool_put(&csepl, cse); 1031 return error; 1032 } 1033 1034 static int 1035 cryptoopen(dev_t dev, int flag, int mode, 1036 struct lwp *l) 1037 { 1038 file_t *fp; 1039 struct fcrypt *fcr; 1040 int fd, error; 1041 1042 if (crypto_usercrypto == 0) 1043 return ENXIO; 1044 1045 if ((error = fd_allocfile(&fp, &fd)) != 0) 1046 return error; 1047 1048 fcr = pool_get(&fcrpl, PR_WAITOK); 1049 getnanotime(&fcr->btime); 1050 fcr->atime = fcr->mtime = fcr->btime; 1051 mutex_spin_enter(&crypto_mtx); 1052 TAILQ_INIT(&fcr->csessions); 1053 TAILQ_INIT(&fcr->crp_ret_mq); 1054 TAILQ_INIT(&fcr->crp_ret_mkq); 1055 selinit(&fcr->sinfo); 1056 /* 1057 * Don't ever return session 0, to allow detection of 1058 * failed creation attempts with multi-create ioctl. 1059 */ 1060 fcr->sesn = 1; 1061 fcr->requestid = 1; 1062 mutex_spin_exit(&crypto_mtx); 1063 return fd_clone(fp, fd, flag, &cryptofops, fcr); 1064 } 1065 1066 static int 1067 cryptoread(dev_t dev, struct uio *uio, int ioflag) 1068 { 1069 return EIO; 1070 } 1071 1072 static int 1073 cryptowrite(dev_t dev, struct uio *uio, int ioflag) 1074 { 1075 return EIO; 1076 } 1077 1078 int 1079 cryptoselect(dev_t dev, int rw, struct lwp *l) 1080 { 1081 return 0; 1082 } 1083 1084 /*static*/ 1085 struct cdevsw crypto_cdevsw = { 1086 /* open */ cryptoopen, 1087 /* close */ noclose, 1088 /* read */ cryptoread, 1089 /* write */ cryptowrite, 1090 /* ioctl */ noioctl, 1091 /* ttstop?*/ nostop, 1092 /* ??*/ notty, 1093 /* poll */ cryptoselect /*nopoll*/, 1094 /* mmap */ nommap, 1095 /* kqfilter */ nokqfilter, 1096 /* type */ D_OTHER, 1097 }; 1098 1099 int 1100 cryptodev_mop(struct fcrypt *fcr, 1101 struct crypt_n_op * cnop, 1102 int count, struct lwp *l) 1103 { 1104 struct cryptop *crp = NULL; 1105 struct cryptodesc *crde = NULL, *crda = NULL, *crdc = NULL; 1106 int req, error=0; 1107 struct csession *cse; 1108 int flags=0; 1109 int iov_len; 1110 1111 for (req = 0; req < count; req++) { 1112 mutex_spin_enter(&crypto_mtx); 1113 cse = csefind(fcr, cnop[req].ses); 1114 if (cse == NULL) { 1115 DPRINTF(("csefind failed\n")); 1116 cnop[req].status = EINVAL; 1117 mutex_spin_exit(&crypto_mtx); 1118 continue; 1119 } 1120 mutex_spin_exit(&crypto_mtx); 1121 1122 if (cnop[req].len > 256*1024-4) { 1123 DPRINTF(("length failed\n")); 1124 cnop[req].status = EINVAL; 1125 continue; 1126 } 1127 if (cse->txform) { 1128 if (cnop[req].len == 0 || 1129 (cnop[req].len % cse->txform->blocksize) != 0) { 1130 cnop[req].status = EINVAL; 1131 continue; 1132 } 1133 } 1134 1135 crp = crypto_getreq((cse->txform != NULL) + 1136 (cse->thash != NULL) + 1137 (cse->tcomp != NULL)); 1138 if (crp == NULL) { 1139 cnop[req].status = ENOMEM; 1140 goto bail; 1141 } 1142 1143 iov_len = cnop[req].len; 1144 /* got a compression/decompression max size? */ 1145 if ((cse->tcomp) && cnop[req].dst_len) { 1146 if (iov_len < cnop[req].dst_len) { 1147 /* Need larger iov to deal with decompress */ 1148 iov_len = cnop[req].dst_len; 1149 } 1150 DPRINTF(("cryptodev_mop: iov_len -> %d for decompress\n", iov_len)); 1151 } 1152 1153 (void)memset(&crp->uio, 0, sizeof(crp->uio)); 1154 crp->uio.uio_iovcnt = 1; 1155 crp->uio.uio_resid = 0; 1156 crp->uio.uio_rw = UIO_WRITE; 1157 crp->uio.uio_iov = crp->iovec; 1158 UIO_SETUP_SYSSPACE(&crp->uio); 1159 memset(&crp->iovec, 0, sizeof(crp->iovec)); 1160 crp->uio.uio_iov[0].iov_len = iov_len; 1161 DPRINTF(("cryptodev_mop: kmem_alloc(%d) for iov \n", iov_len)); 1162 crp->uio.uio_iov[0].iov_base = kmem_alloc(iov_len, KM_SLEEP); 1163 crp->uio.uio_resid = crp->uio.uio_iov[0].iov_len; 1164 1165 if (cse->tcomp) { 1166 crdc = crp->crp_desc; 1167 } 1168 1169 if (cse->thash) { 1170 crda = crdc ? crdc->crd_next : crp->crp_desc; 1171 if (cse->txform && crda) 1172 crde = crda->crd_next; 1173 } else { 1174 if (cse->txform) { 1175 crde = crdc ? crdc->crd_next : crp->crp_desc; 1176 } else if (!cse->tcomp) { 1177 error = EINVAL; 1178 goto bail; 1179 } 1180 } 1181 1182 if ((copyin(cnop[req].src, 1183 crp->uio.uio_iov[0].iov_base, cnop[req].len))) { 1184 cnop[req].status = EINVAL; 1185 goto bail; 1186 } 1187 1188 if (crdc) { 1189 switch (cnop[req].op) { 1190 case COP_COMP: 1191 crdc->crd_flags |= CRD_F_COMP; 1192 break; 1193 case COP_DECOMP: 1194 crdc->crd_flags &= ~CRD_F_COMP; 1195 break; 1196 default: 1197 break; 1198 } 1199 /* more data to follow? */ 1200 if (cnop[req].flags & COP_F_MORE) { 1201 flags |= CRYPTO_F_MORE; 1202 } 1203 crdc->crd_len = cnop[req].len; 1204 crdc->crd_inject = 0; 1205 1206 crdc->crd_alg = cse->comp_alg; 1207 crdc->crd_key = NULL; 1208 crdc->crd_klen = 0; 1209 DPRINTF(("cryptodev_mop[%d]: crdc setup for comp_alg %d" 1210 " len %d.\n", 1211 (uint32_t)cse->sid, crdc->crd_alg, 1212 crdc->crd_len)); 1213 } 1214 1215 if (crda) { 1216 crda->crd_skip = 0; 1217 crda->crd_len = cnop[req].len; 1218 crda->crd_inject = 0; /* ??? */ 1219 1220 crda->crd_alg = cse->mac; 1221 crda->crd_key = cse->mackey; 1222 crda->crd_klen = cse->mackeylen * 8; 1223 } 1224 1225 if (crde) { 1226 if (cnop[req].op == COP_ENCRYPT) 1227 crde->crd_flags |= CRD_F_ENCRYPT; 1228 else 1229 crde->crd_flags &= ~CRD_F_ENCRYPT; 1230 crde->crd_len = cnop[req].len; 1231 crde->crd_inject = 0; 1232 1233 crde->crd_alg = cse->cipher; 1234 #ifdef notyet /* XXX must notify h/w driver new key, drain */ 1235 if(cnop[req].key && cnop[req].keylen) { 1236 crde->crd_key = malloc(cnop[req].keylen, 1237 M_XDATA, M_WAITOK); 1238 if((error = copyin(cnop[req].key, 1239 crde->crd_key, cnop[req].keylen))) { 1240 cnop[req].status = EINVAL; 1241 goto bail; 1242 } 1243 crde->crd_klen = cnop[req].keylen * 8; 1244 } else { ... } 1245 #endif 1246 crde->crd_key = cse->key; 1247 crde->crd_klen = cse->keylen * 8; 1248 } 1249 1250 crp->crp_ilen = cnop[req].len; 1251 crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIMM | 1252 (cnop[req].flags & COP_F_BATCH) | flags; 1253 crp->crp_buf = (void *)&crp->uio; 1254 crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_mcb; 1255 crp->crp_sid = cse->sid; 1256 crp->crp_opaque = (void *)cse; 1257 crp->fcrp = fcr; 1258 crp->dst = cnop[req].dst; 1259 crp->len = cnop[req].len; /* input len, iov may be larger */ 1260 crp->mac = cnop[req].mac; 1261 DPRINTF(("cryptodev_mop: iov_base %p dst %p len %d mac %p\n", 1262 crp->uio.uio_iov[0].iov_base, crp->dst, crp->len, 1263 crp->mac)); 1264 1265 if (cnop[req].iv) { 1266 if (crde == NULL) { 1267 cnop[req].status = EINVAL; 1268 goto bail; 1269 } 1270 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 1271 cnop[req].status = EINVAL; 1272 goto bail; 1273 } 1274 if ((error = copyin(cnop[req].iv, crp->tmp_iv, 1275 cse->txform->blocksize))) { 1276 cnop[req].status = EINVAL; 1277 goto bail; 1278 } 1279 (void)memcpy(crde->crd_iv, crp->tmp_iv, 1280 cse->txform->blocksize); 1281 crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; 1282 crde->crd_skip = 0; 1283 } else if (crde) { 1284 if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 1285 crde->crd_skip = 0; 1286 } else { 1287 crde->crd_flags |= CRD_F_IV_PRESENT; 1288 crde->crd_skip = cse->txform->blocksize; 1289 crde->crd_len -= cse->txform->blocksize; 1290 } 1291 } 1292 1293 if (cnop[req].mac) { 1294 if (crda == NULL) { 1295 cnop[req].status = EINVAL; 1296 goto bail; 1297 } 1298 crp->crp_mac=cse->tmp_mac; 1299 } 1300 cnop[req].reqid = atomic_inc_32_nv(&(fcr->requestid)); 1301 crp->crp_reqid = cnop[req].reqid; 1302 crp->crp_usropaque = cnop[req].opaque; 1303 #ifdef notyet 1304 eagain: 1305 #endif 1306 cnop[req].status = crypto_dispatch(crp); 1307 mutex_spin_enter(&crypto_mtx); /* XXX why mutex? */ 1308 1309 switch (cnop[req].status) { 1310 #ifdef notyet /* don't loop forever -- but EAGAIN not possible here yet */ 1311 case EAGAIN: 1312 mutex_spin_exit(&crypto_mtx); 1313 goto eagain; 1314 break; 1315 #endif 1316 case 0: 1317 break; 1318 default: 1319 DPRINTF(("cryptodev_op: not waiting, error.\n")); 1320 mutex_spin_exit(&crypto_mtx); 1321 goto bail; 1322 } 1323 1324 mutex_spin_exit(&crypto_mtx); 1325 bail: 1326 if (cnop[req].status) { 1327 if (crp) { 1328 if (crp->uio.uio_iov[0].iov_base) { 1329 kmem_free(crp->uio.uio_iov[0].iov_base, 1330 crp->uio.uio_iov[0].iov_len); 1331 } 1332 crypto_freereq(crp); 1333 } 1334 error = 0; 1335 } 1336 } 1337 return error; 1338 } 1339 1340 static int 1341 cryptodev_mkey(struct fcrypt *fcr, struct crypt_n_kop *kop, int count) 1342 { 1343 struct cryptkop *krp = NULL; 1344 int error = EINVAL; 1345 int in, out, size, i, req; 1346 1347 for (req = 0; req < count; req++) { 1348 if (kop[req].crk_iparams + kop[req].crk_oparams > CRK_MAXPARAM) 1349 return EFBIG; 1350 1351 in = kop[req].crk_iparams; 1352 out = kop[req].crk_oparams; 1353 switch (kop[req].crk_op) { 1354 case CRK_MOD_EXP: 1355 if (in == 3 && out == 1) 1356 break; 1357 kop[req].crk_status = EINVAL; 1358 continue; 1359 case CRK_MOD_EXP_CRT: 1360 if (in == 6 && out == 1) 1361 break; 1362 kop[req].crk_status = EINVAL; 1363 continue; 1364 case CRK_DSA_SIGN: 1365 if (in == 5 && out == 2) 1366 break; 1367 kop[req].crk_status = EINVAL; 1368 continue; 1369 case CRK_DSA_VERIFY: 1370 if (in == 7 && out == 0) 1371 break; 1372 kop[req].crk_status = EINVAL; 1373 continue; 1374 case CRK_DH_COMPUTE_KEY: 1375 if (in == 3 && out == 1) 1376 break; 1377 kop[req].crk_status = EINVAL; 1378 continue; 1379 case CRK_MOD_ADD: 1380 if (in == 3 && out == 1) 1381 break; 1382 kop[req].crk_status = EINVAL; 1383 continue; 1384 case CRK_MOD_ADDINV: 1385 if (in == 2 && out == 1) 1386 break; 1387 kop[req].crk_status = EINVAL; 1388 continue; 1389 case CRK_MOD_SUB: 1390 if (in == 3 && out == 1) 1391 break; 1392 kop[req].crk_status = EINVAL; 1393 continue; 1394 case CRK_MOD_MULT: 1395 if (in == 3 && out == 1) 1396 break; 1397 kop[req].crk_status = EINVAL; 1398 continue; 1399 case CRK_MOD_MULTINV: 1400 if (in == 2 && out == 1) 1401 break; 1402 kop[req].crk_status = EINVAL; 1403 continue; 1404 case CRK_MOD: 1405 if (in == 2 && out == 1) 1406 break; 1407 kop[req].crk_status = EINVAL; 1408 continue; 1409 default: 1410 kop[req].crk_status = EINVAL; 1411 continue; 1412 } 1413 1414 krp = pool_get(&cryptkop_pool, PR_WAITOK); 1415 (void)memset(krp, 0, sizeof *krp); 1416 cv_init(&krp->krp_cv, "crykdev"); 1417 krp->krp_op = kop[req].crk_op; 1418 krp->krp_status = kop[req].crk_status; 1419 krp->krp_iparams = kop[req].crk_iparams; 1420 krp->krp_oparams = kop[req].crk_oparams; 1421 krp->krp_status = 0; 1422 krp->krp_callback = 1423 (int (*) (struct cryptkop *)) cryptodevkey_mcb; 1424 (void)memcpy(krp->crk_param, kop[req].crk_param, 1425 sizeof(kop[req].crk_param)); 1426 1427 krp->krp_flags = CRYPTO_F_CBIMM; 1428 1429 for (i = 0; i < CRK_MAXPARAM; i++) 1430 krp->krp_param[i].crp_nbits = 1431 kop[req].crk_param[i].crp_nbits; 1432 for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) { 1433 size = (krp->krp_param[i].crp_nbits + 7) / 8; 1434 if (size == 0) 1435 continue; 1436 krp->krp_param[i].crp_p = 1437 kmem_alloc(size, KM_SLEEP); 1438 if (i >= krp->krp_iparams) 1439 continue; 1440 kop[req].crk_status = 1441 copyin(kop[req].crk_param[i].crp_p, 1442 krp->krp_param[i].crp_p, size); 1443 if (kop[req].crk_status) 1444 goto fail; 1445 } 1446 krp->fcrp = fcr; 1447 1448 kop[req].crk_reqid = atomic_inc_32_nv(&(fcr->requestid)); 1449 krp->krp_reqid = kop[req].crk_reqid; 1450 krp->krp_usropaque = kop[req].crk_opaque; 1451 1452 kop[req].crk_status = crypto_kdispatch(krp); 1453 if (kop[req].crk_status != 0) { 1454 goto fail; 1455 } 1456 1457 fail: 1458 if(kop[req].crk_status) { 1459 if (krp) { 1460 kop[req].crk_status = krp->krp_status; 1461 for (i = 0; i < CRK_MAXPARAM; i++) { 1462 struct crparam *kp = 1463 &(krp->krp_param[i]); 1464 if (kp->crp_p) { 1465 size = (kp->crp_nbits + 7) / 8; 1466 KASSERT(size > 0); 1467 memset(kp->crp_p, 0, size); 1468 kmem_free(kp->crp_p, size); 1469 } 1470 } 1471 cv_destroy(&krp->krp_cv); 1472 pool_put(&cryptkop_pool, krp); 1473 } 1474 } 1475 error = 0; 1476 } 1477 DPRINTF(("cryptodev_key: error=0x%08x\n", error)); 1478 return error; 1479 } 1480 1481 int 1482 cryptodev_session(struct fcrypt *fcr, struct session_op *sop) 1483 { 1484 struct cryptoini cria, crie; 1485 struct cryptoini cric; /* compressor */ 1486 struct cryptoini *crihead = NULL; 1487 const struct enc_xform *txform = NULL; 1488 const struct auth_hash *thash = NULL; 1489 const struct comp_algo *tcomp = NULL; 1490 struct csession *cse; 1491 u_int64_t sid; 1492 int error = 0; 1493 1494 DPRINTF(("cryptodev_session() cipher=%d, mac=%d\n", sop->cipher, sop->mac)); 1495 1496 /* XXX there must be a way to not embed the list of xforms here */ 1497 switch (sop->cipher) { 1498 case 0: 1499 break; 1500 case CRYPTO_DES_CBC: 1501 txform = &enc_xform_des; 1502 break; 1503 case CRYPTO_3DES_CBC: 1504 txform = &enc_xform_3des; 1505 break; 1506 case CRYPTO_BLF_CBC: 1507 txform = &enc_xform_blf; 1508 break; 1509 case CRYPTO_CAST_CBC: 1510 txform = &enc_xform_cast5; 1511 break; 1512 case CRYPTO_SKIPJACK_CBC: 1513 txform = &enc_xform_skipjack; 1514 break; 1515 case CRYPTO_AES_CBC: 1516 txform = &enc_xform_rijndael128; 1517 break; 1518 case CRYPTO_NULL_CBC: 1519 txform = &enc_xform_null; 1520 break; 1521 case CRYPTO_ARC4: 1522 txform = &enc_xform_arc4; 1523 break; 1524 default: 1525 DPRINTF(("Invalid cipher %d\n", sop->cipher)); 1526 return EINVAL; 1527 } 1528 1529 switch (sop->comp_alg) { 1530 case 0: 1531 break; 1532 case CRYPTO_DEFLATE_COMP: 1533 tcomp = &comp_algo_deflate; 1534 break; 1535 case CRYPTO_GZIP_COMP: 1536 tcomp = &comp_algo_gzip; 1537 DPRINTF(("cryptodev_session() tcomp for GZIP\n")); 1538 break; 1539 default: 1540 DPRINTF(("Invalid compression alg %d\n", sop->comp_alg)); 1541 return EINVAL; 1542 } 1543 1544 switch (sop->mac) { 1545 case 0: 1546 break; 1547 case CRYPTO_MD5_HMAC: 1548 thash = &auth_hash_hmac_md5; 1549 break; 1550 case CRYPTO_SHA1_HMAC: 1551 thash = &auth_hash_hmac_sha1; 1552 break; 1553 case CRYPTO_MD5_HMAC_96: 1554 thash = &auth_hash_hmac_md5_96; 1555 break; 1556 case CRYPTO_SHA1_HMAC_96: 1557 thash = &auth_hash_hmac_sha1_96; 1558 break; 1559 case CRYPTO_SHA2_HMAC: 1560 /* XXX switching on key length seems questionable */ 1561 if (sop->mackeylen == auth_hash_hmac_sha2_256.keysize) { 1562 thash = &auth_hash_hmac_sha2_256; 1563 } else if (sop->mackeylen == auth_hash_hmac_sha2_384.keysize) { 1564 thash = &auth_hash_hmac_sha2_384; 1565 } else if (sop->mackeylen == auth_hash_hmac_sha2_512.keysize) { 1566 thash = &auth_hash_hmac_sha2_512; 1567 } else { 1568 DPRINTF(("Invalid mackeylen %d\n", sop->mackeylen)); 1569 return EINVAL; 1570 } 1571 break; 1572 case CRYPTO_RIPEMD160_HMAC: 1573 thash = &auth_hash_hmac_ripemd_160; 1574 break; 1575 case CRYPTO_RIPEMD160_HMAC_96: 1576 thash = &auth_hash_hmac_ripemd_160_96; 1577 break; 1578 case CRYPTO_MD5: 1579 thash = &auth_hash_md5; 1580 break; 1581 case CRYPTO_SHA1: 1582 thash = &auth_hash_sha1; 1583 break; 1584 case CRYPTO_NULL_HMAC: 1585 thash = &auth_hash_null; 1586 break; 1587 default: 1588 DPRINTF(("Invalid mac %d\n", sop->mac)); 1589 return EINVAL; 1590 } 1591 1592 memset(&crie, 0, sizeof(crie)); 1593 memset(&cria, 0, sizeof(cria)); 1594 memset(&cric, 0, sizeof(cric)); 1595 1596 if (tcomp) { 1597 cric.cri_alg = tcomp->type; 1598 cric.cri_klen = 0; 1599 DPRINTF(("tcomp->type = %d\n", tcomp->type)); 1600 1601 crihead = &cric; 1602 if (thash) { 1603 cric.cri_next = &cria; 1604 } else if (txform) { 1605 cric.cri_next = &crie; 1606 } 1607 } 1608 1609 if (txform) { 1610 crie.cri_alg = txform->type; 1611 crie.cri_klen = sop->keylen * 8; 1612 if (sop->keylen > txform->maxkey || 1613 sop->keylen < txform->minkey) { 1614 DPRINTF(("keylen %d not in [%d,%d]\n", 1615 sop->keylen, txform->minkey, txform->maxkey)); 1616 error = EINVAL; 1617 goto bail; 1618 } 1619 1620 crie.cri_key = malloc(crie.cri_klen / 8, M_XDATA, M_WAITOK); 1621 if ((error = copyin(sop->key, crie.cri_key, crie.cri_klen / 8))) 1622 goto bail; 1623 if (!crihead) { 1624 crihead = &crie; 1625 } 1626 } 1627 1628 if (thash) { 1629 cria.cri_alg = thash->type; 1630 cria.cri_klen = sop->mackeylen * 8; 1631 if (sop->mackeylen != thash->keysize) { 1632 DPRINTF(("mackeylen %d != keysize %d\n", 1633 sop->mackeylen, thash->keysize)); 1634 error = EINVAL; 1635 goto bail; 1636 } 1637 if (cria.cri_klen) { 1638 cria.cri_key = malloc(cria.cri_klen / 8, M_XDATA, 1639 M_WAITOK); 1640 if ((error = copyin(sop->mackey, cria.cri_key, 1641 cria.cri_klen / 8))) { 1642 goto bail; 1643 } 1644 } 1645 if (txform) 1646 cria.cri_next = &crie; /* XXX forces enc then hash? */ 1647 if (!crihead) { 1648 crihead = &cria; 1649 } 1650 } 1651 1652 error = crypto_newsession(&sid, crihead, crypto_devallowsoft); 1653 if (!error) { 1654 DPRINTF(("cyrptodev_session: got session %d\n", (uint32_t)sid)); 1655 cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen, 1656 cria.cri_key, cria.cri_klen, (txform ? sop->cipher : 0), sop->mac, 1657 (tcomp ? sop->comp_alg : 0), txform, thash, tcomp); 1658 if (cse != NULL) { 1659 sop->ses = cse->ses; 1660 } else { 1661 DPRINTF(("csecreate failed\n")); 1662 crypto_freesession(sid); 1663 error = EINVAL; 1664 } 1665 } else { 1666 DPRINTF(("SIOCSESSION violates kernel parameters %d\n", 1667 error)); 1668 } 1669 bail: 1670 if (error) { 1671 if (crie.cri_key) { 1672 memset(crie.cri_key, 0, crie.cri_klen / 8); 1673 free(crie.cri_key, M_XDATA); 1674 } 1675 if (cria.cri_key) { 1676 memset(cria.cri_key, 0, cria.cri_klen / 8); 1677 free(cria.cri_key, M_XDATA); 1678 } 1679 } 1680 return error; 1681 } 1682 1683 int 1684 cryptodev_msession(struct fcrypt *fcr, struct session_n_op *sn_ops, 1685 int count) 1686 { 1687 int i; 1688 1689 for (i = 0; i < count; i++, sn_ops++) { 1690 struct session_op s_op; 1691 s_op.cipher = sn_ops->cipher; 1692 s_op.mac = sn_ops->mac; 1693 s_op.keylen = sn_ops->keylen; 1694 s_op.key = sn_ops->key; 1695 s_op.mackeylen = sn_ops->mackeylen; 1696 s_op.mackey = sn_ops->mackey; 1697 1698 sn_ops->status = cryptodev_session(fcr, &s_op); 1699 sn_ops->ses = s_op.ses; 1700 } 1701 1702 return 0; 1703 } 1704 1705 static int 1706 cryptodev_msessionfin(struct fcrypt *fcr, int count, u_int32_t *sesid) 1707 { 1708 struct csession *cse; 1709 int req, error = 0; 1710 1711 mutex_spin_enter(&crypto_mtx); 1712 for(req = 0; req < count; req++) { 1713 cse = csefind(fcr, sesid[req]); 1714 if (cse == NULL) 1715 continue; 1716 csedelete(fcr, cse); 1717 mutex_spin_exit(&crypto_mtx); 1718 error = csefree(cse); 1719 mutex_spin_enter(&crypto_mtx); 1720 } 1721 mutex_spin_exit(&crypto_mtx); 1722 return 0; 1723 } 1724 1725 /* 1726 * collect as many completed requests as are availble, or count completed 1727 * requests whichever is less. 1728 * return the number of requests. 1729 */ 1730 static int 1731 cryptodev_getmstatus(struct fcrypt *fcr, struct crypt_result *crypt_res, 1732 int count) 1733 { 1734 struct cryptop *crp = NULL; 1735 struct cryptkop *krp = NULL; 1736 struct csession *cse; 1737 int i, size, req = 0; 1738 int completed=0; 1739 1740 /* On queue so nobody else can grab them 1741 * and copyout can be delayed-- no locking */ 1742 TAILQ_HEAD(, cryptop) crp_delfree_q = 1743 TAILQ_HEAD_INITIALIZER(crp_delfree_q); 1744 TAILQ_HEAD(, cryptkop) krp_delfree_q = 1745 TAILQ_HEAD_INITIALIZER(krp_delfree_q); 1746 1747 /* at this point we do not know which response user is requesting for 1748 * (symmetric or asymmetric) so we copyout one from each i.e if the 1749 * count is 2 then 1 from symmetric and 1 from asymmetric queue and 1750 * if 3 then 2 symmetric and 1 asymmetric and so on */ 1751 1752 /* pull off a list of requests while protected from changes */ 1753 mutex_spin_enter(&crypto_mtx); 1754 while (req < count) { 1755 crp = TAILQ_FIRST(&fcr->crp_ret_mq); 1756 if (crp) { 1757 TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next); 1758 TAILQ_INSERT_TAIL(&crp_delfree_q, crp, crp_next); 1759 cse = (struct csession *)crp->crp_opaque; 1760 1761 /* see if the session is still valid */ 1762 cse = csefind(fcr, cse->ses); 1763 if (cse != NULL) { 1764 crypt_res[req].status = 0; 1765 } else { 1766 DPRINTF(("csefind failed\n")); 1767 crypt_res[req].status = EINVAL; 1768 } 1769 req++; 1770 } 1771 if(req < count) { 1772 crypt_res[req].status = 0; 1773 krp = TAILQ_FIRST(&fcr->crp_ret_mkq); 1774 if (krp) { 1775 TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next); 1776 TAILQ_INSERT_TAIL(&krp_delfree_q, krp, krp_next); 1777 req++; 1778 } 1779 } 1780 } 1781 mutex_spin_exit(&crypto_mtx); 1782 1783 /* now do all the work outside the mutex */ 1784 for(req=0; req < count ;) { 1785 crp = TAILQ_FIRST(&crp_delfree_q); 1786 if (crp) { 1787 if (crypt_res[req].status != 0) { 1788 /* csefind failed during collection */ 1789 goto bail; 1790 } 1791 cse = (struct csession *)crp->crp_opaque; 1792 crypt_res[req].reqid = crp->crp_reqid; 1793 crypt_res[req].opaque = crp->crp_usropaque; 1794 completed++; 1795 1796 if (crp->crp_etype != 0) { 1797 crypt_res[req].status = crp->crp_etype; 1798 goto bail; 1799 } 1800 1801 if (cse->error) { 1802 crypt_res[req].status = cse->error; 1803 goto bail; 1804 } 1805 1806 if (crp->dst && (crypt_res[req].status = 1807 copyout(crp->uio.uio_iov[0].iov_base, crp->dst, 1808 crp->len))) 1809 goto bail; 1810 1811 if (crp->mac && (crypt_res[req].status = 1812 copyout(crp->crp_mac, crp->mac, 1813 cse->thash->authsize))) 1814 goto bail; 1815 1816 bail: 1817 TAILQ_REMOVE(&crp_delfree_q, crp, crp_next); 1818 kmem_free(crp->uio.uio_iov[0].iov_base, 1819 crp->uio.uio_iov[0].iov_len); 1820 crypto_freereq(crp); 1821 req++; 1822 } 1823 1824 if (req < count) { 1825 krp = TAILQ_FIRST(&krp_delfree_q); 1826 if (krp) { 1827 crypt_res[req].reqid = krp->krp_reqid; 1828 crypt_res[req].opaque = krp->krp_usropaque; 1829 completed++; 1830 if (krp->krp_status != 0) { 1831 DPRINTF(("cryptodev_key: " 1832 "krp->krp_status 0x%08x\n", 1833 krp->krp_status)); 1834 crypt_res[req].status = krp->krp_status; 1835 goto fail; 1836 } 1837 1838 for (i = krp->krp_iparams; i < krp->krp_iparams 1839 + krp->krp_oparams; i++) { 1840 size = (krp->krp_param[i].crp_nbits 1841 + 7) / 8; 1842 if (size == 0) 1843 continue; 1844 crypt_res[req].status = copyout 1845 (krp->krp_param[i].crp_p, 1846 krp->crk_param[i].crp_p, size); 1847 if (crypt_res[req].status) { 1848 DPRINTF(("cryptodev_key: " 1849 "copyout oparam %d failed, " 1850 "error=%d\n", 1851 i - krp->krp_iparams, 1852 crypt_res[req].status)); 1853 goto fail; 1854 } 1855 } 1856 fail: 1857 TAILQ_REMOVE(&krp_delfree_q, krp, krp_next); 1858 /* not sure what to do for this */ 1859 /* kop[req].crk_status = krp->krp_status; */ 1860 for (i = 0; i < CRK_MAXPARAM; i++) { 1861 struct crparam *kp = &(krp->krp_param[i]); 1862 if (kp->crp_p) { 1863 size = (kp->crp_nbits + 7) / 8; 1864 KASSERT(size > 0); 1865 (void)memset(kp->crp_p, 0, size); 1866 kmem_free(kp->crp_p, size); 1867 } 1868 } 1869 cv_destroy(&krp->krp_cv); 1870 pool_put(&cryptkop_pool, krp); 1871 req++; 1872 } 1873 } 1874 } 1875 1876 return completed; 1877 } 1878 1879 static int 1880 cryptodev_getstatus (struct fcrypt *fcr, struct crypt_result *crypt_res) 1881 { 1882 struct cryptop *crp = NULL, *cnext; 1883 struct cryptkop *krp = NULL, *knext; 1884 struct csession *cse; 1885 int i, size, req = 0; 1886 1887 mutex_spin_enter(&crypto_mtx); 1888 /* Here we dont know for which request the user is requesting the 1889 * response so checking in both the queues */ 1890 TAILQ_FOREACH_SAFE(crp, &fcr->crp_ret_mq, crp_next, cnext) { 1891 if(crp && (crp->crp_reqid == crypt_res->reqid)) { 1892 cse = (struct csession *)crp->crp_opaque; 1893 crypt_res->opaque = crp->crp_usropaque; 1894 cse = csefind(fcr, cse->ses); 1895 if (cse == NULL) { 1896 DPRINTF(("csefind failed\n")); 1897 crypt_res->status = EINVAL; 1898 goto bail; 1899 } 1900 1901 if (crp->crp_etype != 0) { 1902 crypt_res->status = crp->crp_etype; 1903 goto bail; 1904 } 1905 1906 if (cse->error) { 1907 crypt_res->status = cse->error; 1908 goto bail; 1909 } 1910 1911 if (crp->dst && (crypt_res->status = 1912 copyout(crp->uio.uio_iov[0].iov_base, 1913 crp->dst, crp->len))) 1914 goto bail; 1915 1916 if (crp->mac && (crypt_res->status = 1917 copyout(crp->crp_mac, crp->mac, 1918 cse->thash->authsize))) 1919 goto bail; 1920 bail: 1921 TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next); 1922 1923 mutex_spin_exit(&crypto_mtx); 1924 crypto_freereq(crp); 1925 return 0; 1926 } 1927 } 1928 1929 TAILQ_FOREACH_SAFE(krp, &fcr->crp_ret_mkq, krp_next, knext) { 1930 if(krp && (krp->krp_reqid == crypt_res->reqid)) { 1931 crypt_res[req].opaque = krp->krp_usropaque; 1932 if (krp->krp_status != 0) { 1933 DPRINTF(("cryptodev_key: " 1934 "krp->krp_status 0x%08x\n", 1935 krp->krp_status)); 1936 crypt_res[req].status = krp->krp_status; 1937 goto fail; 1938 } 1939 1940 for (i = krp->krp_iparams; i < krp->krp_iparams + 1941 krp->krp_oparams; i++) { 1942 size = (krp->krp_param[i].crp_nbits + 7) / 8; 1943 if (size == 0) 1944 continue; 1945 crypt_res[req].status = copyout( 1946 krp->krp_param[i].crp_p, 1947 krp->crk_param[i].crp_p, size); 1948 if (crypt_res[req].status) { 1949 DPRINTF(("cryptodev_key: copyout oparam" 1950 "%d failed, error=%d\n", 1951 i - krp->krp_iparams, 1952 crypt_res[req].status)); 1953 goto fail; 1954 } 1955 } 1956 fail: 1957 TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next); 1958 mutex_spin_exit(&crypto_mtx); 1959 /* not sure what to do for this */ 1960 /* kop[req].crk_status = krp->krp_status; */ 1961 for (i = 0; i < CRK_MAXPARAM; i++) { 1962 struct crparam *kp = &(krp->krp_param[i]); 1963 if (kp->crp_p) { 1964 size = (kp->crp_nbits + 7) / 8; 1965 KASSERT(size > 0); 1966 memset(kp->crp_p, 0, size); 1967 kmem_free(kp->crp_p, size); 1968 } 1969 } 1970 cv_destroy(&krp->krp_cv); 1971 pool_put(&cryptkop_pool, krp); 1972 return 0; 1973 } 1974 } 1975 mutex_spin_exit(&crypto_mtx); 1976 return EINPROGRESS; 1977 } 1978 1979 static int 1980 cryptof_stat(struct file *fp, struct stat *st) 1981 { 1982 struct fcrypt *fcr = fp->f_data; 1983 1984 (void)memset(st, 0, sizeof(st)); 1985 1986 mutex_spin_enter(&crypto_mtx); 1987 st->st_dev = makedev(cdevsw_lookup_major(&crypto_cdevsw), fcr->sesn); 1988 st->st_atimespec = fcr->atime; 1989 st->st_mtimespec = fcr->mtime; 1990 st->st_ctimespec = st->st_birthtimespec = fcr->btime; 1991 st->st_uid = kauth_cred_geteuid(fp->f_cred); 1992 st->st_gid = kauth_cred_getegid(fp->f_cred); 1993 mutex_spin_exit(&crypto_mtx); 1994 1995 return 0; 1996 } 1997 1998 static int 1999 cryptof_poll(struct file *fp, int events) 2000 { 2001 struct fcrypt *fcr = (struct fcrypt *)fp->f_data; 2002 int revents = 0; 2003 2004 if (!(events & (POLLIN | POLLRDNORM))) { 2005 /* only support read and POLLIN */ 2006 return 0; 2007 } 2008 2009 mutex_spin_enter(&crypto_mtx); 2010 if (TAILQ_EMPTY(&fcr->crp_ret_mq) && TAILQ_EMPTY(&fcr->crp_ret_mkq)) { 2011 /* no completed requests pending, save the poll for later */ 2012 selrecord(curlwp, &fcr->sinfo); 2013 } else { 2014 /* let the app(s) know that there are completed requests */ 2015 revents = events & (POLLIN | POLLRDNORM); 2016 } 2017 mutex_spin_exit(&crypto_mtx); 2018 2019 return revents; 2020 } 2021 2022 /* 2023 * Pseudo-device initialization routine for /dev/crypto 2024 */ 2025 void cryptoattach(int); 2026 2027 void 2028 cryptoattach(int num) 2029 { 2030 pool_init(&fcrpl, sizeof(struct fcrypt), 0, 0, 0, "fcrpl", 2031 NULL, IPL_NET); /* XXX IPL_NET ("splcrypto") */ 2032 pool_init(&csepl, sizeof(struct csession), 0, 0, 0, "csepl", 2033 NULL, IPL_NET); /* XXX IPL_NET ("splcrypto") */ 2034 2035 /* 2036 * Preallocate space for 64 users, with 5 sessions each. 2037 * (consider that a TLS protocol session requires at least 2038 * 3DES, MD5, and SHA1 (both hashes are used in the PRF) for 2039 * the negotiation, plus HMAC_SHA1 for the actual SSL records, 2040 * consuming one session here for each algorithm. 2041 */ 2042 pool_prime(&fcrpl, 64); 2043 pool_prime(&csepl, 64 * 5); 2044 } 2045