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