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