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