1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * The ioctl interface for administrative commands. 30 */ 31 32 #include <sys/types.h> 33 #include <sys/modctl.h> 34 #include <sys/conf.h> 35 #include <sys/stat.h> 36 #include <sys/ddi.h> 37 #include <sys/sunddi.h> 38 #include <sys/kmem.h> 39 #include <sys/errno.h> 40 #include <sys/ksynch.h> 41 #include <sys/file.h> 42 #include <sys/open.h> 43 #include <sys/cred.h> 44 #include <sys/model.h> 45 #include <sys/sysmacros.h> 46 #include <sys/crypto/common.h> 47 #include <sys/crypto/api.h> 48 #include <sys/crypto/impl.h> 49 #include <sys/crypto/sched_impl.h> 50 #include <sys/crypto/ioctladmin.h> 51 #include <c2/audit.h> 52 53 /* 54 * DDI entry points. 55 */ 56 static int cryptoadm_attach(dev_info_t *, ddi_attach_cmd_t); 57 static int cryptoadm_detach(dev_info_t *, ddi_detach_cmd_t); 58 static int cryptoadm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 59 static int cryptoadm_open(dev_t *, int, int, cred_t *); 60 static int cryptoadm_close(dev_t, int, int, cred_t *); 61 static int cryptoadm_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 62 63 extern void audit_cryptoadm(int, char *, crypto_mech_name_t *, uint_t, 64 uint_t, uint32_t, int); 65 /* 66 * Module linkage. 67 */ 68 static struct cb_ops cbops = { 69 cryptoadm_open, /* cb_open */ 70 cryptoadm_close, /* cb_close */ 71 nodev, /* cb_strategy */ 72 nodev, /* cb_print */ 73 nodev, /* cb_dump */ 74 nodev, /* cb_read */ 75 nodev, /* cb_write */ 76 cryptoadm_ioctl, /* cb_ioctl */ 77 nodev, /* cb_devmap */ 78 nodev, /* cb_mmap */ 79 nodev, /* cb_segmap */ 80 nochpoll, /* cb_chpoll */ 81 ddi_prop_op, /* cb_prop_op */ 82 NULL, /* cb_streamtab */ 83 D_MP, /* cb_flag */ 84 CB_REV, /* cb_rev */ 85 nodev, /* cb_aread */ 86 nodev, /* cb_awrite */ 87 }; 88 89 static struct dev_ops devops = { 90 DEVO_REV, /* devo_rev */ 91 0, /* devo_refcnt */ 92 cryptoadm_getinfo, /* devo_getinfo */ 93 nulldev, /* devo_identify */ 94 nulldev, /* devo_probe */ 95 cryptoadm_attach, /* devo_attach */ 96 cryptoadm_detach, /* devo_detach */ 97 nodev, /* devo_reset */ 98 &cbops, /* devo_cb_ops */ 99 NULL, /* devo_bus_ops */ 100 NULL, /* devo_power */ 101 }; 102 103 static struct modldrv modldrv = { 104 &mod_driverops, /* drv_modops */ 105 "Cryptographic Administrative Interface", /* drv_linkinfo */ 106 &devops, 107 }; 108 109 static struct modlinkage modlinkage = { 110 MODREV_1, /* ml_rev */ 111 &modldrv, /* ml_linkage */ 112 NULL 113 }; 114 115 static dev_info_t *cryptoadm_dip = NULL; 116 117 /* 118 * DDI entry points. 119 */ 120 int 121 _init(void) 122 { 123 return (mod_install(&modlinkage)); 124 } 125 126 int 127 _fini(void) 128 { 129 return (mod_remove(&modlinkage)); 130 } 131 132 int 133 _info(struct modinfo *modinfop) 134 { 135 return (mod_info(&modlinkage, modinfop)); 136 } 137 138 /* ARGSUSED */ 139 static int 140 cryptoadm_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 141 { 142 switch (cmd) { 143 case DDI_INFO_DEVT2DEVINFO: 144 *result = (void *)cryptoadm_dip; 145 return (DDI_SUCCESS); 146 147 case DDI_INFO_DEVT2INSTANCE: 148 *result = (void *)0; 149 return (DDI_SUCCESS); 150 } 151 return (DDI_FAILURE); 152 } 153 154 static int 155 cryptoadm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 156 { 157 if (cmd != DDI_ATTACH) { 158 return (DDI_FAILURE); 159 } 160 if (ddi_get_instance(dip) != 0) { 161 /* we only allow instance 0 to attach */ 162 return (DDI_FAILURE); 163 } 164 165 /* create the minor node */ 166 if (ddi_create_minor_node(dip, "cryptoadm", S_IFCHR, 0, 167 DDI_PSEUDO, 0) != DDI_SUCCESS) { 168 cmn_err(CE_WARN, "cryptoadm: failed creating minor node"); 169 ddi_remove_minor_node(dip, NULL); 170 return (DDI_FAILURE); 171 } 172 173 cryptoadm_dip = dip; 174 175 return (DDI_SUCCESS); 176 } 177 178 static int 179 cryptoadm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 180 { 181 if (cmd != DDI_DETACH) 182 return (DDI_FAILURE); 183 184 cryptoadm_dip = NULL; 185 ddi_remove_minor_node(dip, NULL); 186 187 return (DDI_SUCCESS); 188 } 189 190 /* ARGSUSED */ 191 static int 192 cryptoadm_open(dev_t *devp, int flag, int otyp, cred_t *credp) 193 { 194 if (otyp != OTYP_CHR || cryptoadm_dip == NULL) 195 return (ENXIO); 196 197 /* exclusive opens are not supported */ 198 if (flag & FEXCL) 199 return (ENOTSUP); 200 201 *devp = makedevice(getmajor(*devp), 0); 202 203 kcf_sched_start(); 204 205 return (0); 206 } 207 208 /* ARGSUSED */ 209 static int 210 cryptoadm_close(dev_t dev, int flag, int otyp, cred_t *credp) 211 { 212 return (0); 213 } 214 215 /* 216 * Returns TRUE if array of size MAXNAMELEN contains a '\0' 217 * termination character, otherwise, it returns FALSE. 218 */ 219 static boolean_t 220 null_terminated(char *array) 221 { 222 int i; 223 224 for (i = 0; i < MAXNAMELEN; i++) 225 if (array[i] == '\0') 226 return (B_TRUE); 227 228 return (B_FALSE); 229 } 230 231 /* 232 * This ioctl returns an array of hardware providers. Each entry 233 * contains a device name, device instance, and number of 234 * supported mechanisms. 235 */ 236 /* ARGSUSED */ 237 static int 238 get_dev_list(dev_t dev, caddr_t arg, int mode, int *rval) 239 { 240 crypto_get_dev_list_t dev_list; 241 crypto_dev_list_entry_t *entries; 242 size_t copyout_size; 243 uint_t count; 244 ulong_t offset; 245 246 if (copyin(arg, &dev_list, sizeof (dev_list)) != 0) 247 return (EFAULT); 248 249 /* get the list from the core module */ 250 if (crypto_get_dev_list(&count, &entries) != 0) { 251 dev_list.dl_return_value = CRYPTO_FAILED; 252 if (copyout(&dev_list, arg, sizeof (dev_list)) != 0) { 253 return (EFAULT); 254 } 255 return (0); 256 } 257 258 /* check if buffer is too small */ 259 if (count > dev_list.dl_dev_count) { 260 dev_list.dl_dev_count = count; 261 dev_list.dl_return_value = CRYPTO_BUFFER_TOO_SMALL; 262 crypto_free_dev_list(entries, count); 263 if (copyout(&dev_list, arg, sizeof (dev_list)) != 0) { 264 return (EFAULT); 265 } 266 return (0); 267 } 268 269 dev_list.dl_dev_count = count; 270 dev_list.dl_return_value = CRYPTO_SUCCESS; 271 272 copyout_size = count * sizeof (crypto_dev_list_entry_t); 273 274 /* copyout the first stuff */ 275 if (copyout(&dev_list, arg, sizeof (dev_list)) != 0) { 276 crypto_free_dev_list(entries, count); 277 return (EFAULT); 278 } 279 280 /* copyout entries */ 281 offset = offsetof(crypto_get_dev_list_t, dl_devs); 282 if (count > 0 && copyout(entries, arg + offset, copyout_size) != 0) { 283 crypto_free_dev_list(entries, count); 284 return (EFAULT); 285 } 286 crypto_free_dev_list(entries, count); 287 return (0); 288 } 289 290 /* 291 * This ioctl returns a buffer containing the null terminated names 292 * of software providers. 293 */ 294 /* ARGSUSED */ 295 static int 296 get_soft_list(dev_t dev, caddr_t arg, int mode, int *rval) 297 { 298 STRUCT_DECL(crypto_get_soft_list, soft_list); 299 char *names; 300 size_t len; 301 uint_t count; 302 303 STRUCT_INIT(soft_list, mode); 304 305 if (copyin(arg, STRUCT_BUF(soft_list), STRUCT_SIZE(soft_list)) != 0) 306 return (EFAULT); 307 308 /* get the list from the core module */ 309 if (crypto_get_soft_list(&count, &names, &len) != 0) { 310 STRUCT_FSET(soft_list, sl_return_value, CRYPTO_FAILED); 311 if (copyout(STRUCT_BUF(soft_list), arg, 312 STRUCT_SIZE(soft_list)) != 0) { 313 return (EFAULT); 314 } 315 return (0); 316 } 317 318 /* check if buffer is too small */ 319 if (len > STRUCT_FGET(soft_list, sl_soft_len)) { 320 STRUCT_FSET(soft_list, sl_soft_count, count); 321 STRUCT_FSET(soft_list, sl_soft_len, len); 322 STRUCT_FSET(soft_list, sl_return_value, 323 CRYPTO_BUFFER_TOO_SMALL); 324 kmem_free(names, len); 325 if (copyout(STRUCT_BUF(soft_list), arg, 326 STRUCT_SIZE(soft_list)) != 0) { 327 return (EFAULT); 328 } 329 return (0); 330 } 331 332 STRUCT_FSET(soft_list, sl_soft_count, count); 333 STRUCT_FSET(soft_list, sl_soft_len, len); 334 STRUCT_FSET(soft_list, sl_return_value, CRYPTO_SUCCESS); 335 336 if (count > 0 && copyout(names, 337 STRUCT_FGETP(soft_list, sl_soft_names), len) != 0) { 338 kmem_free(names, len); 339 return (EFAULT); 340 } 341 kmem_free(names, len); 342 343 if (copyout(STRUCT_BUF(soft_list), arg, STRUCT_SIZE(soft_list)) != 0) { 344 return (EFAULT); 345 } 346 347 return (0); 348 } 349 350 /* 351 * This ioctl returns an array of mechanisms supported by the 352 * specified device. 353 */ 354 /* ARGSUSED */ 355 static int 356 get_dev_info(dev_t dev, caddr_t arg, int mode, int *rval) 357 { 358 crypto_get_dev_info_t dev_info; 359 crypto_mech_name_t *entries; 360 size_t copyout_size; 361 uint_t count; 362 ulong_t offset; 363 char *dev_name; 364 int rv; 365 366 if (copyin(arg, &dev_info, sizeof (dev_info)) != 0) 367 return (EFAULT); 368 369 dev_name = dev_info.di_dev_name; 370 /* make sure the device name is null terminated */ 371 if (!null_terminated(dev_name)) { 372 dev_info.di_return_value = CRYPTO_ARGUMENTS_BAD; 373 if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) { 374 return (EFAULT); 375 } 376 return (0); 377 } 378 379 /* get mechanism names from the core module */ 380 if ((rv = crypto_get_dev_info(dev_name, dev_info.di_dev_instance, 381 &count, &entries)) != CRYPTO_SUCCESS) { 382 dev_info.di_return_value = rv; 383 if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) { 384 return (EFAULT); 385 } 386 return (0); 387 } 388 389 /* check if buffer is too small */ 390 if (count > dev_info.di_count) { 391 dev_info.di_count = count; 392 dev_info.di_return_value = CRYPTO_BUFFER_TOO_SMALL; 393 crypto_free_mech_list(entries, count); 394 if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) { 395 return (EFAULT); 396 } 397 return (0); 398 } 399 400 dev_info.di_count = count; 401 dev_info.di_return_value = CRYPTO_SUCCESS; 402 403 copyout_size = count * sizeof (crypto_mech_name_t); 404 405 /* copyout the first stuff */ 406 if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) { 407 crypto_free_mech_list(entries, count); 408 return (EFAULT); 409 } 410 411 /* copyout entries */ 412 offset = offsetof(crypto_get_dev_info_t, di_list); 413 if (copyout(entries, arg + offset, copyout_size) != 0) { 414 crypto_free_mech_list(entries, count); 415 return (EFAULT); 416 } 417 crypto_free_mech_list(entries, count); 418 return (0); 419 } 420 421 /* 422 * This ioctl returns an array of mechanisms supported by the 423 * specified cryptographic module. 424 */ 425 /* ARGSUSED */ 426 static int 427 get_soft_info(dev_t dev, caddr_t arg, int mode, int *rval) 428 { 429 crypto_get_soft_info_t soft_info; 430 crypto_mech_name_t *entries; 431 size_t copyout_size; 432 uint_t count; 433 ulong_t offset; 434 char *name; 435 436 if (copyin(arg, &soft_info, sizeof (soft_info)) != 0) 437 return (EFAULT); 438 439 name = soft_info.si_name; 440 /* make sure the provider name is null terminated */ 441 if (!null_terminated(name)) { 442 soft_info.si_return_value = CRYPTO_ARGUMENTS_BAD; 443 if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) { 444 return (EFAULT); 445 } 446 return (0); 447 } 448 449 /* get mechanism names from the core module */ 450 if (crypto_get_soft_info(name, &count, &entries) != 0) { 451 soft_info.si_return_value = CRYPTO_FAILED; 452 if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) { 453 return (EFAULT); 454 } 455 return (0); 456 } 457 458 /* check if buffer is too small */ 459 if (count > soft_info.si_count) { 460 soft_info.si_count = count; 461 soft_info.si_return_value = CRYPTO_BUFFER_TOO_SMALL; 462 crypto_free_mech_list(entries, count); 463 if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) { 464 return (EFAULT); 465 } 466 return (0); 467 } 468 469 soft_info.si_count = count; 470 soft_info.si_return_value = CRYPTO_SUCCESS; 471 copyout_size = count * sizeof (crypto_mech_name_t); 472 473 /* copyout the first stuff */ 474 if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) { 475 crypto_free_mech_list(entries, count); 476 return (EFAULT); 477 } 478 479 /* copyout entries */ 480 offset = offsetof(crypto_get_soft_info_t, si_list); 481 if (copyout(entries, arg + offset, copyout_size) != 0) { 482 crypto_free_mech_list(entries, count); 483 return (EFAULT); 484 } 485 crypto_free_mech_list(entries, count); 486 return (0); 487 } 488 489 /* 490 * This ioctl disables mechanisms supported by the specified device. 491 */ 492 /* ARGSUSED */ 493 static int 494 load_dev_disabled(dev_t dev, caddr_t arg, int mode, int *rval) 495 { 496 crypto_load_dev_disabled_t dev_disabled; 497 crypto_mech_name_t *entries; 498 size_t size; 499 ulong_t offset; 500 uint_t count; 501 uint_t instance; 502 char *dev_name; 503 uint32_t rv; 504 int error = 0; 505 506 if (copyin(arg, &dev_disabled, sizeof (dev_disabled)) != 0) { 507 error = EFAULT; 508 goto out2; 509 } 510 511 dev_name = dev_disabled.dd_dev_name; 512 /* make sure the device name is null terminated */ 513 if (!null_terminated(dev_name)) { 514 rv = CRYPTO_ARGUMENTS_BAD; 515 goto out; 516 } 517 518 count = dev_disabled.dd_count; 519 instance = dev_disabled.dd_dev_instance; 520 if (count == 0) { 521 /* remove the entry */ 522 if (crypto_load_dev_disabled(dev_name, instance, 0, NULL) != 0) 523 rv = CRYPTO_FAILED; 524 else 525 rv = CRYPTO_SUCCESS; 526 goto out; 527 } 528 529 if (count > KCF_MAXMECHS) { 530 rv = CRYPTO_ARGUMENTS_BAD; 531 goto out; 532 } 533 534 size = count * sizeof (crypto_mech_name_t); 535 entries = kmem_alloc(size, KM_SLEEP); 536 537 offset = offsetof(crypto_load_dev_disabled_t, dd_list); 538 if (copyin(arg + offset, entries, size) != 0) { 539 kmem_free(entries, size); 540 error = EFAULT; 541 goto out2; 542 } 543 544 /* 'entries' consumed (but not freed) by crypto_load_dev_disabled() */ 545 if (crypto_load_dev_disabled(dev_name, instance, count, entries) != 0) { 546 kmem_free(entries, size); 547 rv = CRYPTO_FAILED; 548 goto out; 549 } 550 rv = CRYPTO_SUCCESS; 551 out: 552 dev_disabled.dd_return_value = rv; 553 554 if (copyout(&dev_disabled, arg, sizeof (dev_disabled)) != 0) { 555 error = EFAULT; 556 } 557 out2: 558 #ifdef C2_AUDIT 559 if (audit_active) 560 audit_cryptoadm(CRYPTO_LOAD_DEV_DISABLED, dev_name, entries, 561 count, instance, rv, error); 562 #endif 563 return (error); 564 } 565 566 /* 567 * This ioctl disables mechanisms supported by the specified 568 * cryptographic module. 569 */ 570 /* ARGSUSED */ 571 static int 572 load_soft_disabled(dev_t dev, caddr_t arg, int mode, int *rval) 573 { 574 crypto_load_soft_disabled_t soft_disabled; 575 crypto_mech_name_t *entries; 576 size_t size; 577 uint_t count; 578 ulong_t offset; 579 char *name; 580 uint32_t rv; 581 int error = 0; 582 583 if (copyin(arg, &soft_disabled, sizeof (soft_disabled)) != 0) { 584 error = EFAULT; 585 goto out2; 586 } 587 588 name = soft_disabled.sd_name; 589 /* make sure the name is null terminated */ 590 if (!null_terminated(name)) { 591 soft_disabled.sd_return_value = CRYPTO_ARGUMENTS_BAD; 592 if (copyout(&soft_disabled, arg, sizeof (soft_disabled)) != 0) { 593 return (EFAULT); 594 } 595 return (0); 596 } 597 598 count = soft_disabled.sd_count; 599 if (count == 0) { 600 /* remove the entry */ 601 if (crypto_load_soft_disabled(name, 0, NULL) != 0) { 602 rv = CRYPTO_FAILED; 603 } else { 604 rv = CRYPTO_SUCCESS; 605 } 606 goto out; 607 } 608 609 if (count > KCF_MAXMECHS) { 610 rv = CRYPTO_ARGUMENTS_BAD; 611 goto out; 612 } 613 614 size = count * sizeof (crypto_mech_name_t); 615 entries = kmem_alloc(size, KM_SLEEP); 616 617 offset = offsetof(crypto_load_soft_disabled_t, sd_list); 618 if (copyin(arg + offset, entries, size) != 0) { 619 kmem_free(entries, size); 620 error = EFAULT; 621 goto out2; 622 } 623 624 /* 'entries' is consumed by crypto_load_soft_disabled() */ 625 if (crypto_load_soft_disabled(name, count, entries) != 0) { 626 kmem_free(entries, size); 627 rv = CRYPTO_FAILED; 628 goto out; 629 } 630 rv = CRYPTO_SUCCESS; 631 out: 632 soft_disabled.sd_return_value = rv; 633 634 if (copyout(&soft_disabled, arg, sizeof (soft_disabled)) != 0) { 635 error = EFAULT; 636 } 637 out2: 638 #ifdef C2_AUDIT 639 if (audit_active) 640 audit_cryptoadm(CRYPTO_LOAD_SOFT_DISABLED, name, entries, 641 count, 0, rv, error); 642 #endif 643 return (error); 644 } 645 646 /* 647 * This ioctl loads the supported mechanisms of the specfied cryptographic 648 * module. This is so, at boot time, all software providers do not 649 * have to be opened in order to cause them to register their 650 * supported mechanisms. 651 */ 652 /* ARGSUSED */ 653 static int 654 load_soft_config(dev_t dev, caddr_t arg, int mode, int *rval) 655 { 656 crypto_load_soft_config_t soft_config; 657 crypto_mech_name_t *entries; 658 size_t size; 659 uint_t count; 660 ulong_t offset; 661 char *name; 662 uint32_t rv; 663 int error = 0; 664 665 if (copyin(arg, &soft_config, sizeof (soft_config)) != 0) { 666 error = EFAULT; 667 goto out2; 668 } 669 670 name = soft_config.sc_name; 671 /* make sure the name is null terminated */ 672 if (!null_terminated(name)) { 673 soft_config.sc_return_value = CRYPTO_ARGUMENTS_BAD; 674 if (copyout(&soft_config, arg, sizeof (soft_config)) != 0) { 675 return (EFAULT); 676 } 677 return (0); 678 } 679 680 count = soft_config.sc_count; 681 if (count == 0) { 682 if (crypto_load_soft_config(name, 0, NULL) != 0) { 683 rv = CRYPTO_FAILED; 684 } else { 685 rv = CRYPTO_SUCCESS; 686 } 687 goto out; 688 } 689 690 if (count > KCF_MAXMECHS) { 691 rv = CRYPTO_ARGUMENTS_BAD; 692 goto out; 693 } 694 695 size = count * sizeof (crypto_mech_name_t); 696 entries = kmem_alloc(size, KM_SLEEP); 697 698 offset = offsetof(crypto_load_soft_config_t, sc_list); 699 if (copyin(arg + offset, entries, size) != 0) { 700 kmem_free(entries, size); 701 error = EFAULT; 702 goto out2; 703 } 704 705 /* 706 * 'entries' is consumed (but not freed) by 707 * crypto_load_soft_config() 708 */ 709 if (crypto_load_soft_config(name, count, entries) != 0) { 710 kmem_free(entries, size); 711 rv = CRYPTO_FAILED; 712 goto out; 713 } 714 rv = CRYPTO_SUCCESS; 715 out: 716 soft_config.sc_return_value = rv; 717 718 if (copyout(&soft_config, arg, sizeof (soft_config)) != 0) { 719 error = EFAULT; 720 } 721 out2: 722 #ifdef C2_AUDIT 723 if (audit_active) 724 audit_cryptoadm(CRYPTO_LOAD_SOFT_CONFIG, name, entries, count, 725 0, rv, error); 726 #endif 727 return (error); 728 } 729 730 /* 731 * This ioctl unloads the specfied cryptographic module and removes 732 * its table of supported mechanisms. 733 */ 734 /* ARGSUSED */ 735 static int 736 unload_soft_module(dev_t dev, caddr_t arg, int mode, int *rval) 737 { 738 crypto_unload_soft_module_t unload_soft_module; 739 char *name; 740 uint32_t rv; 741 int error = 0; 742 743 if (copyin(arg, &unload_soft_module, 744 sizeof (unload_soft_module)) != 0) { 745 error = EFAULT; 746 goto out2; 747 } 748 749 name = unload_soft_module.sm_name; 750 /* make sure the name is null terminated */ 751 if (!null_terminated(name)) { 752 unload_soft_module.sm_return_value = CRYPTO_ARGUMENTS_BAD; 753 if (copyout(&unload_soft_module, arg, 754 sizeof (unload_soft_module)) != 0) { 755 return (EFAULT); 756 } 757 return (0); 758 } 759 760 rv = crypto_unload_soft_module(name); 761 out: 762 unload_soft_module.sm_return_value = rv; 763 764 if (copyout(&unload_soft_module, arg, 765 sizeof (unload_soft_module)) != 0) { 766 error = EFAULT; 767 } 768 out2: 769 #ifdef C2_AUDIT 770 if (audit_active) 771 audit_cryptoadm(CRYPTO_UNLOAD_SOFT_MODULE, name, NULL, 0, 0, 772 rv, error); 773 #endif 774 775 return (error); 776 } 777 778 /* 779 * This ioctl loads a door descriptor into the kernel. The descriptor 780 * is used for module verification. 781 */ 782 /* ARGSUSED */ 783 static int 784 load_door(dev_t dev, caddr_t arg, int mode, int *rval) 785 { 786 crypto_load_door_t load_door; 787 uint32_t rv; 788 int error = 0; 789 790 if (copyin(arg, &load_door, sizeof (crypto_load_door_t)) != 0) { 791 error = EFAULT; 792 goto out2; 793 } 794 795 if (crypto_load_door(load_door.ld_did) != 0) { 796 rv = CRYPTO_FAILED; 797 goto out; 798 } 799 rv = CRYPTO_SUCCESS; 800 out: 801 load_door.ld_return_value = rv; 802 803 if (copyout(&load_door, arg, sizeof (crypto_load_door_t)) != 0) 804 error = EFAULT; 805 806 out2: 807 #ifdef C2_AUDIT 808 if (audit_active) 809 audit_cryptoadm(CRYPTO_LOAD_DOOR, NULL, NULL, 810 0, 0, rv, error); 811 #endif 812 return (error); 813 } 814 815 static int 816 cryptoadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, 817 int *rval) 818 { 819 int error; 820 #define ARG ((caddr_t)arg) 821 822 switch (cmd) { 823 case CRYPTO_LOAD_DEV_DISABLED: 824 case CRYPTO_LOAD_SOFT_DISABLED: 825 case CRYPTO_LOAD_SOFT_CONFIG: 826 case CRYPTO_UNLOAD_SOFT_MODULE: 827 case CRYPTO_POOL_CREATE: 828 case CRYPTO_POOL_WAIT: 829 case CRYPTO_POOL_RUN: 830 case CRYPTO_LOAD_DOOR: 831 if ((error = drv_priv(c)) != 0) 832 return (error); 833 default: 834 break; 835 } 836 837 switch (cmd) { 838 case CRYPTO_GET_DEV_LIST: 839 return (get_dev_list(dev, ARG, mode, rval)); 840 841 case CRYPTO_GET_DEV_INFO: 842 return (get_dev_info(dev, ARG, mode, rval)); 843 844 case CRYPTO_GET_SOFT_LIST: 845 return (get_soft_list(dev, ARG, mode, rval)); 846 847 case CRYPTO_GET_SOFT_INFO: 848 return (get_soft_info(dev, ARG, mode, rval)); 849 850 case CRYPTO_LOAD_DEV_DISABLED: 851 return (load_dev_disabled(dev, ARG, mode, rval)); 852 853 case CRYPTO_LOAD_SOFT_DISABLED: 854 return (load_soft_disabled(dev, ARG, mode, rval)); 855 856 case CRYPTO_LOAD_SOFT_CONFIG: 857 return (load_soft_config(dev, ARG, mode, rval)); 858 859 case CRYPTO_UNLOAD_SOFT_MODULE: 860 return (unload_soft_module(dev, ARG, mode, rval)); 861 862 case CRYPTO_POOL_CREATE: 863 /* 864 * The framework allocates and initializes the pool. 865 * So, this is a no op. We are keeping this ioctl around 866 * to be used for any future threadpool related work. 867 */ 868 #ifdef C2_AUDIT 869 if (audit_active) 870 audit_cryptoadm(CRYPTO_POOL_CREATE, NULL, NULL, 871 0, 0, 0, 0); 872 #endif 873 return (0); 874 875 case CRYPTO_POOL_WAIT: { 876 int nthrs = 0, err; 877 878 if ((err = kcf_svc_wait(&nthrs)) == 0) { 879 if (copyout((caddr_t)&nthrs, ARG, sizeof (int)) 880 == -1) 881 err = EFAULT; 882 } 883 #ifdef C2_AUDIT 884 if (audit_active) 885 audit_cryptoadm(CRYPTO_POOL_WAIT, NULL, NULL, 886 0, 0, 0, err); 887 #endif 888 return (err); 889 } 890 891 case CRYPTO_POOL_RUN: { 892 int err; 893 894 err = kcf_svc_do_run(); 895 #ifdef C2_AUDIT 896 if (audit_active) 897 audit_cryptoadm(CRYPTO_POOL_RUN, NULL, NULL, 898 0, 0, 0, err); 899 #endif 900 return (err); 901 } 902 903 case CRYPTO_LOAD_DOOR: 904 return (load_door(dev, ARG, mode, rval)); 905 } 906 return (EINVAL); 907 } 908