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