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