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 */ 56static int cryptoadm_attach(dev_info_t *, ddi_attach_cmd_t); 57static int cryptoadm_detach(dev_info_t *, ddi_detach_cmd_t); 58static int cryptoadm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 59static int cryptoadm_open(dev_t *, int, int, cred_t *); 60static int cryptoadm_close(dev_t, int, int, cred_t *); 61static int cryptoadm_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 62 63extern void audit_cryptoadm(int, char *, crypto_mech_name_t *, uint_t, 64 uint_t, uint32_t, int); 65 66/* 67 * Module linkage. 68 */ 69static 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 90static 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 105static struct modldrv modldrv = { 106 &mod_driverops, /* drv_modops */ 107 "Cryptographic Administrative Interface", /* drv_linkinfo */ 108 &devops, 109}; 110 111static struct modlinkage modlinkage = { 112 MODREV_1, /* ml_rev */ 113 &modldrv, /* ml_linkage */ 114 NULL 115}; 116 117static dev_info_t *cryptoadm_dip = NULL; 118 119/* 120 * DDI entry points. 121 */ 122int 123_init(void) 124{ 125 return (mod_install(&modlinkage)); 126} 127 128int 129_fini(void) 130{ 131 return (mod_remove(&modlinkage)); 132} 133 134int 135_info(struct modinfo *modinfop) 136{ 137 return (mod_info(&modlinkage, modinfop)); 138} 139 140/* ARGSUSED */ 141static int 142cryptoadm_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 156static int 157cryptoadm_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 mutex_init(&fips140_mode_lock, NULL, MUTEX_DEFAULT, NULL); 176 cryptoadm_dip = dip; 177 178 return (DDI_SUCCESS); 179} 180 181static int 182cryptoadm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 183{ 184 if (cmd != DDI_DETACH) 185 return (DDI_FAILURE); 186 187 cryptoadm_dip = NULL; 188 ddi_remove_minor_node(dip, NULL); 189 190 return (DDI_SUCCESS); 191} 192 193/* ARGSUSED */ 194static int 195cryptoadm_open(dev_t *devp, int flag, int otyp, cred_t *credp) 196{ 197 if (otyp != OTYP_CHR || cryptoadm_dip == NULL) 198 return (ENXIO); 199 200 /* exclusive opens are not supported */ 201 if (flag & FEXCL) 202 return (ENOTSUP); 203 204 *devp = makedevice(getmajor(*devp), 0); 205 206 kcf_sched_start(); 207 208 return (0); 209} 210 211/* ARGSUSED */ 212static int 213cryptoadm_close(dev_t dev, int flag, int otyp, cred_t *credp) 214{ 215 return (0); 216} 217 218/* 219 * Returns TRUE if array of size MAXNAMELEN contains a '\0' 220 * termination character, otherwise, it returns FALSE. 221 */ 222static boolean_t 223null_terminated(char *array) 224{ 225 int i; 226 227 for (i = 0; i < MAXNAMELEN; i++) 228 if (array[i] == '\0') 229 return (B_TRUE); 230 231 return (B_FALSE); 232} 233 234/* 235 * This ioctl returns an array of hardware providers. Each entry 236 * contains a device name, device instance, and number of 237 * supported mechanisms. 238 */ 239/* ARGSUSED */ 240static int 241get_dev_list(dev_t dev, caddr_t arg, int mode, int *rval) 242{ 243 crypto_get_dev_list_t dev_list; 244 crypto_dev_list_entry_t *entries; 245 size_t copyout_size; 246 uint_t count; 247 ulong_t offset; 248 249 if (copyin(arg, &dev_list, sizeof (dev_list)) != 0) 250 return (EFAULT); 251 252 /* get the list from the core module */ 253 if (crypto_get_dev_list(&count, &entries) != 0) { 254 dev_list.dl_return_value = CRYPTO_FAILED; 255 if (copyout(&dev_list, arg, sizeof (dev_list)) != 0) { 256 return (EFAULT); 257 } 258 return (0); 259 } 260 261 /* check if buffer is too small */ 262 if (count > dev_list.dl_dev_count) { 263 dev_list.dl_dev_count = count; 264 dev_list.dl_return_value = CRYPTO_BUFFER_TOO_SMALL; 265 crypto_free_dev_list(entries, count); 266 if (copyout(&dev_list, arg, sizeof (dev_list)) != 0) { 267 return (EFAULT); 268 } 269 return (0); 270 } 271 272 dev_list.dl_dev_count = count; 273 dev_list.dl_return_value = CRYPTO_SUCCESS; 274 275 copyout_size = count * sizeof (crypto_dev_list_entry_t); 276 277 /* copyout the first stuff */ 278 if (copyout(&dev_list, arg, sizeof (dev_list)) != 0) { 279 crypto_free_dev_list(entries, count); 280 return (EFAULT); 281 } 282 283 /* copyout entries */ 284 offset = offsetof(crypto_get_dev_list_t, dl_devs); 285 if (count > 0 && copyout(entries, arg + offset, copyout_size) != 0) { 286 crypto_free_dev_list(entries, count); 287 return (EFAULT); 288 } 289 crypto_free_dev_list(entries, count); 290 return (0); 291} 292 293/* 294 * This ioctl returns a buffer containing the null terminated names 295 * of software providers. 296 */ 297/* ARGSUSED */ 298static int 299get_soft_list(dev_t dev, caddr_t arg, int mode, int *rval) 300{ 301 STRUCT_DECL(crypto_get_soft_list, soft_list); 302 char *names; 303 size_t len; 304 uint_t count; 305 306 STRUCT_INIT(soft_list, mode); 307 308 if (copyin(arg, STRUCT_BUF(soft_list), STRUCT_SIZE(soft_list)) != 0) 309 return (EFAULT); 310 311 /* get the list from the core module */ 312 if (crypto_get_soft_list(&count, &names, &len) != 0) { 313 STRUCT_FSET(soft_list, sl_return_value, CRYPTO_FAILED); 314 if (copyout(STRUCT_BUF(soft_list), arg, 315 STRUCT_SIZE(soft_list)) != 0) { 316 return (EFAULT); 317 } 318 return (0); 319 } 320 321 /* check if buffer is too small */ 322 if (len > STRUCT_FGET(soft_list, sl_soft_len)) { 323 STRUCT_FSET(soft_list, sl_soft_count, count); 324 STRUCT_FSET(soft_list, sl_soft_len, len); 325 STRUCT_FSET(soft_list, sl_return_value, 326 CRYPTO_BUFFER_TOO_SMALL); 327 kmem_free(names, len); 328 if (copyout(STRUCT_BUF(soft_list), arg, 329 STRUCT_SIZE(soft_list)) != 0) { 330 return (EFAULT); 331 } 332 return (0); 333 } 334 335 STRUCT_FSET(soft_list, sl_soft_count, count); 336 STRUCT_FSET(soft_list, sl_soft_len, len); 337 STRUCT_FSET(soft_list, sl_return_value, CRYPTO_SUCCESS); 338 339 if (count > 0 && copyout(names, 340 STRUCT_FGETP(soft_list, sl_soft_names), len) != 0) { 341 kmem_free(names, len); 342 return (EFAULT); 343 } 344 kmem_free(names, len); 345 346 if (copyout(STRUCT_BUF(soft_list), arg, STRUCT_SIZE(soft_list)) != 0) { 347 return (EFAULT); 348 } 349 350 return (0); 351} 352 353/* 354 * This ioctl returns an array of mechanisms supported by the 355 * specified device. 356 */ 357/* ARGSUSED */ 358static int 359get_dev_info(dev_t dev, caddr_t arg, int mode, int *rval) 360{ 361 crypto_get_dev_info_t dev_info; 362 crypto_mech_name_t *entries; 363 size_t copyout_size; 364 uint_t count; 365 ulong_t offset; 366 char *dev_name; 367 int rv; 368 369 if (copyin(arg, &dev_info, sizeof (dev_info)) != 0) 370 return (EFAULT); 371 372 dev_name = dev_info.di_dev_name; 373 /* make sure the device name is null terminated */ 374 if (!null_terminated(dev_name)) { 375 dev_info.di_return_value = CRYPTO_ARGUMENTS_BAD; 376 if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) { 377 return (EFAULT); 378 } 379 return (0); 380 } 381 382 /* get mechanism names from the core module */ 383 if ((rv = crypto_get_dev_info(dev_name, dev_info.di_dev_instance, 384 &count, &entries)) != CRYPTO_SUCCESS) { 385 dev_info.di_return_value = rv; 386 if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) { 387 return (EFAULT); 388 } 389 return (0); 390 } 391 392 /* check if buffer is too small */ 393 if (count > dev_info.di_count) { 394 dev_info.di_count = count; 395 dev_info.di_return_value = CRYPTO_BUFFER_TOO_SMALL; 396 crypto_free_mech_list(entries, count); 397 if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) { 398 return (EFAULT); 399 } 400 return (0); 401 } 402 403 dev_info.di_count = count; 404 dev_info.di_return_value = CRYPTO_SUCCESS; 405 406 copyout_size = count * sizeof (crypto_mech_name_t); 407 408 /* copyout the first stuff */ 409 if (copyout(&dev_info, arg, sizeof (dev_info)) != 0) { 410 crypto_free_mech_list(entries, count); 411 return (EFAULT); 412 } 413 414 /* copyout entries */ 415 offset = offsetof(crypto_get_dev_info_t, di_list); 416 if (copyout(entries, arg + offset, copyout_size) != 0) { 417 crypto_free_mech_list(entries, count); 418 return (EFAULT); 419 } 420 crypto_free_mech_list(entries, count); 421 return (0); 422} 423 424/* 425 * This ioctl returns an array of mechanisms supported by the 426 * specified cryptographic module. 427 */ 428/* ARGSUSED */ 429static int 430get_soft_info(dev_t dev, caddr_t arg, int mode, int *rval) 431{ 432 crypto_get_soft_info_t soft_info; 433 crypto_mech_name_t *entries; 434 size_t copyout_size; 435 uint_t count; 436 ulong_t offset; 437 char *name; 438 439 if (copyin(arg, &soft_info, sizeof (soft_info)) != 0) 440 return (EFAULT); 441 442 name = soft_info.si_name; 443 /* make sure the provider name is null terminated */ 444 if (!null_terminated(name)) { 445 soft_info.si_return_value = CRYPTO_ARGUMENTS_BAD; 446 if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) { 447 return (EFAULT); 448 } 449 return (0); 450 } 451 452 /* get mechanism names from the core module */ 453 if (crypto_get_soft_info(name, &count, &entries) != 0) { 454 soft_info.si_return_value = CRYPTO_FAILED; 455 if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) { 456 return (EFAULT); 457 } 458 return (0); 459 } 460 461 /* check if buffer is too small */ 462 if (count > soft_info.si_count) { 463 soft_info.si_count = count; 464 soft_info.si_return_value = CRYPTO_BUFFER_TOO_SMALL; 465 crypto_free_mech_list(entries, count); 466 if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) { 467 return (EFAULT); 468 } 469 return (0); 470 } 471 472 soft_info.si_count = count; 473 soft_info.si_return_value = CRYPTO_SUCCESS; 474 copyout_size = count * sizeof (crypto_mech_name_t); 475 476 /* copyout the first stuff */ 477 if (copyout(&soft_info, arg, sizeof (soft_info)) != 0) { 478 crypto_free_mech_list(entries, count); 479 return (EFAULT); 480 } 481 482 /* copyout entries */ 483 offset = offsetof(crypto_get_soft_info_t, si_list); 484 if (copyout(entries, arg + offset, copyout_size) != 0) { 485 crypto_free_mech_list(entries, count); 486 return (EFAULT); 487 } 488 crypto_free_mech_list(entries, count); 489 return (0); 490} 491 492/* 493 * This ioctl disables mechanisms supported by the specified device. 494 */ 495/* ARGSUSED */ 496static int 497load_dev_disabled(dev_t dev, caddr_t arg, int mode, int *rval) 498{ 499 crypto_load_dev_disabled_t dev_disabled; 500 crypto_mech_name_t *entries; 501 size_t size; 502 ulong_t offset; 503 uint_t count; 504 uint_t instance; 505 char *dev_name; 506 uint32_t rv; 507 int error = 0; 508 509 if (copyin(arg, &dev_disabled, sizeof (dev_disabled)) != 0) { 510 error = EFAULT; 511 goto out2; 512 } 513 514 dev_name = dev_disabled.dd_dev_name; 515 /* make sure the device name is null terminated */ 516 if (!null_terminated(dev_name)) { 517 rv = CRYPTO_ARGUMENTS_BAD; 518 goto out; 519 } 520 521 count = dev_disabled.dd_count; 522 instance = dev_disabled.dd_dev_instance; 523 if (count == 0) { 524 /* remove the entry */ 525 if (crypto_load_dev_disabled(dev_name, instance, 0, NULL) != 0) 526 rv = CRYPTO_FAILED; 527 else 528 rv = CRYPTO_SUCCESS; 529 goto out; 530 } 531 532 if (count > KCF_MAXMECHS) { 533 rv = CRYPTO_ARGUMENTS_BAD; 534 goto out; 535 } 536 537 size = count * sizeof (crypto_mech_name_t); 538 entries = kmem_alloc(size, KM_SLEEP); 539 540 offset = offsetof(crypto_load_dev_disabled_t, dd_list); 541 if (copyin(arg + offset, entries, size) != 0) { 542 kmem_free(entries, size); 543 error = EFAULT; 544 goto out2; 545 } 546 547 /* 'entries' consumed (but not freed) by crypto_load_dev_disabled() */ 548 if (crypto_load_dev_disabled(dev_name, instance, count, entries) != 0) { 549 kmem_free(entries, size); 550 rv = CRYPTO_FAILED; 551 goto out; 552 } 553 rv = CRYPTO_SUCCESS; 554out: 555 dev_disabled.dd_return_value = rv; 556 557 if (copyout(&dev_disabled, arg, sizeof (dev_disabled)) != 0) { 558 error = EFAULT; 559 } 560out2: 561 if (AU_AUDITING()) 562 audit_cryptoadm(CRYPTO_LOAD_DEV_DISABLED, dev_name, entries, 563 count, instance, rv, error); 564 return (error); 565} 566 567/* 568 * This ioctl disables mechanisms supported by the specified 569 * cryptographic module. 570 */ 571/* ARGSUSED */ 572static int 573load_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; 632out: 633 soft_disabled.sd_return_value = rv; 634 635 if (copyout(&soft_disabled, arg, sizeof (soft_disabled)) != 0) { 636 error = EFAULT; 637 } 638out2: 639 if (AU_AUDITING()) 640 audit_cryptoadm(CRYPTO_LOAD_SOFT_DISABLED, name, entries, 641 count, 0, rv, error); 642 return (error); 643} 644 645/* 646 * This ioctl loads the supported mechanisms of the specfied cryptographic 647 * module. This is so, at boot time, all software providers do not 648 * have to be opened in order to cause them to register their 649 * supported mechanisms. 650 */ 651/* ARGSUSED */ 652static int 653load_soft_config(dev_t dev, caddr_t arg, int mode, int *rval) 654{ 655 crypto_load_soft_config_t soft_config; 656 crypto_mech_name_t *entries; 657 size_t size; 658 uint_t count; 659 ulong_t offset; 660 char *name; 661 uint32_t rv; 662 int error = 0; 663 664 if (copyin(arg, &soft_config, sizeof (soft_config)) != 0) { 665 error = EFAULT; 666 goto out2; 667 } 668 669 name = soft_config.sc_name; 670 /* make sure the name is null terminated */ 671 if (!null_terminated(name)) { 672 soft_config.sc_return_value = CRYPTO_ARGUMENTS_BAD; 673 if (copyout(&soft_config, arg, sizeof (soft_config)) != 0) { 674 return (EFAULT); 675 } 676 return (0); 677 } 678 679 count = soft_config.sc_count; 680 if (count == 0) { 681 if (crypto_load_soft_config(name, 0, NULL) != 0) { 682 rv = CRYPTO_FAILED; 683 } else { 684 rv = CRYPTO_SUCCESS; 685 } 686 goto out; 687 } 688 689 if (count > KCF_MAXMECHS) { 690 rv = CRYPTO_ARGUMENTS_BAD; 691 goto out; 692 } 693 694 size = count * sizeof (crypto_mech_name_t); 695 entries = kmem_alloc(size, KM_SLEEP); 696 697 offset = offsetof(crypto_load_soft_config_t, sc_list); 698 if (copyin(arg + offset, entries, size) != 0) { 699 kmem_free(entries, size); 700 error = EFAULT; 701 goto out2; 702 } 703 704 /* 705 * 'entries' is consumed (but not freed) by 706 * crypto_load_soft_config() 707 */ 708 if (crypto_load_soft_config(name, count, entries) != 0) { 709 kmem_free(entries, size); 710 rv = CRYPTO_FAILED; 711 goto out; 712 } 713 rv = CRYPTO_SUCCESS; 714out: 715 soft_config.sc_return_value = rv; 716 717 if (copyout(&soft_config, arg, sizeof (soft_config)) != 0) { 718 error = EFAULT; 719 } 720out2: 721 if (AU_AUDITING()) 722 audit_cryptoadm(CRYPTO_LOAD_SOFT_CONFIG, name, entries, count, 723 0, rv, error); 724 return (error); 725} 726 727/* 728 * This ioctl unloads the specfied cryptographic module and removes 729 * its table of supported mechanisms. 730 */ 731/* ARGSUSED */ 732static int 733unload_soft_module(dev_t dev, caddr_t arg, int mode, int *rval) 734{ 735 crypto_unload_soft_module_t unload_soft_module; 736 char *name; 737 uint32_t rv; 738 int error = 0; 739 740 if (copyin(arg, &unload_soft_module, 741 sizeof (unload_soft_module)) != 0) { 742 error = EFAULT; 743 goto out2; 744 } 745 746 name = unload_soft_module.sm_name; 747 /* make sure the name is null terminated */ 748 if (!null_terminated(name)) { 749 unload_soft_module.sm_return_value = CRYPTO_ARGUMENTS_BAD; 750 if (copyout(&unload_soft_module, arg, 751 sizeof (unload_soft_module)) != 0) { 752 return (EFAULT); 753 } 754 return (0); 755 } 756 757 rv = crypto_unload_soft_module(name); 758out: 759 unload_soft_module.sm_return_value = rv; 760 761 if (copyout(&unload_soft_module, arg, 762 sizeof (unload_soft_module)) != 0) { 763 error = EFAULT; 764 } 765out2: 766 if (AU_AUDITING()) 767 audit_cryptoadm(CRYPTO_UNLOAD_SOFT_MODULE, name, NULL, 0, 0, 768 rv, error); 769 770 return (error); 771} 772 773/* 774 * This ioctl loads a door descriptor into the kernel. The descriptor 775 * is used for module verification. 776 */ 777/* ARGSUSED */ 778static int 779load_door(dev_t dev, caddr_t arg, int mode, int *rval) 780{ 781 crypto_load_door_t load_door; 782 uint32_t rv; 783 int error = 0; 784 785 if (copyin(arg, &load_door, sizeof (crypto_load_door_t)) != 0) { 786 error = EFAULT; 787 goto out2; 788 } 789 790 if (crypto_load_door(load_door.ld_did) != 0) { 791 rv = CRYPTO_FAILED; 792 goto out; 793 } 794 rv = CRYPTO_SUCCESS; 795out: 796 load_door.ld_return_value = rv; 797 798 if (copyout(&load_door, arg, sizeof (crypto_load_door_t)) != 0) 799 error = EFAULT; 800 801out2: 802 if (AU_AUDITING()) 803 audit_cryptoadm(CRYPTO_LOAD_DOOR, NULL, NULL, 804 0, 0, rv, error); 805 return (error); 806} 807 808/* 809 * This function enables/disables FIPS140 mode or gets the current 810 * FIPS 140 mode status. 811 * 812 * CRYPTO_FIPS140_STATUS: Returns back the value of global_fips140_mode. 813 * CRYPTO_FIPS140_SET: Recognizes 2 operations from userland: 814 * FIPS140_ENABLE or FIPS140_DISABLE. These can only be 815 * called when global_fips140_mode is FIPS140_MODE_UNSET 816 * as they are only operations that can be performed at 817 * bootup. 818 */ 819/* ARGSUSED */ 820static int 821fips140_actions(dev_t dev, caddr_t arg, int mode, int *rval, int cmd) 822{ 823 crypto_fips140_t fips140_info; 824 uint32_t rv = CRYPTO_SUCCESS; 825 int error = 0; 826 827 if (copyin(arg, &fips140_info, sizeof (crypto_fips140_t)) != 0) 828 return (EFAULT); 829 830 switch (cmd) { 831 case CRYPTO_FIPS140_STATUS: 832 fips140_info.fips140_status = global_fips140_mode; 833 break; 834 case CRYPTO_FIPS140_SET: 835 /* If the mode has been determined, there is nothing to set */ 836 mutex_enter(&fips140_mode_lock); 837 838 if (fips140_info.fips140_op == FIPS140_ENABLE && 839 global_fips140_mode == FIPS140_MODE_UNSET) { 840 /* 841 * If FIPS 140 is enabled, all approriate modules 842 * must be loaded and validated. This can be done in 843 * the background as the rest of the OS comes up. 844 */ 845 global_fips140_mode = FIPS140_MODE_VALIDATING; 846 (void) thread_create(NULL, 0, kcf_fips140_validate, 847 NULL, 0, &p0, TS_RUN, MAXCLSYSPRI); 848 cv_signal(&cv_fips140); 849 850 } else if (fips140_info.fips140_op == FIPS140_DISABLE && 851 global_fips140_mode == FIPS140_MODE_UNSET) { 852 /* 853 * If FIPS 140 is not enabled, any modules that are 854 * waiting for validation must be released so they 855 * can be verified. 856 */ 857 global_fips140_mode = FIPS140_MODE_DISABLED; 858 kcf_activate(); 859 cv_signal(&cv_fips140); 860 861 } else if (fips140_info.fips140_op != FIPS140_DISABLE && 862 fips140_info.fips140_op != FIPS140_ENABLE) { 863 rv = CRYPTO_ARGUMENTS_BAD; 864 } 865 866 mutex_exit(&fips140_mode_lock); 867 break; 868 869 default: 870 rv = CRYPTO_ARGUMENTS_BAD; 871 } 872 873 fips140_info.fips140_return_value = rv; 874 875 if (copyout(&fips140_info, arg, sizeof (crypto_fips140_t)) != 0) 876 error = EFAULT; 877 878 return (error); 879} 880 881static int 882cryptoadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, 883 int *rval) 884{ 885 uint32_t auditing = AU_AUDITING(); 886 int error; 887#define ARG ((caddr_t)arg) 888 889 switch (cmd) { 890 case CRYPTO_LOAD_DEV_DISABLED: 891 case CRYPTO_LOAD_SOFT_DISABLED: 892 case CRYPTO_LOAD_SOFT_CONFIG: 893 case CRYPTO_UNLOAD_SOFT_MODULE: 894 case CRYPTO_POOL_CREATE: 895 case CRYPTO_POOL_WAIT: 896 case CRYPTO_POOL_RUN: 897 case CRYPTO_LOAD_DOOR: 898 case CRYPTO_FIPS140_SET: 899 if ((error = drv_priv(c)) != 0) 900 return (error); 901 default: 902 break; 903 } 904 905 switch (cmd) { 906 case CRYPTO_GET_DEV_LIST: 907 return (get_dev_list(dev, ARG, mode, rval)); 908 909 case CRYPTO_GET_DEV_INFO: 910 return (get_dev_info(dev, ARG, mode, rval)); 911 912 case CRYPTO_GET_SOFT_LIST: 913 return (get_soft_list(dev, ARG, mode, rval)); 914 915 case CRYPTO_GET_SOFT_INFO: 916 return (get_soft_info(dev, ARG, mode, rval)); 917 918 case CRYPTO_LOAD_DEV_DISABLED: 919 return (load_dev_disabled(dev, ARG, mode, rval)); 920 921 case CRYPTO_LOAD_SOFT_DISABLED: 922 return (load_soft_disabled(dev, ARG, mode, rval)); 923 924 case CRYPTO_LOAD_SOFT_CONFIG: 925 return (load_soft_config(dev, ARG, mode, rval)); 926 927 case CRYPTO_UNLOAD_SOFT_MODULE: 928 return (unload_soft_module(dev, ARG, mode, rval)); 929 930 case CRYPTO_POOL_CREATE: 931 /* 932 * The framework allocates and initializes the pool. 933 * So, this is a no op. We are keeping this ioctl around 934 * to be used for any future threadpool related work. 935 */ 936 if (auditing) 937 audit_cryptoadm(CRYPTO_POOL_CREATE, NULL, NULL, 938 0, 0, 0, 0); 939 return (0); 940 941 case CRYPTO_POOL_WAIT: { 942 int nthrs = 0, err; 943 944 if ((err = kcf_svc_wait(&nthrs)) == 0) { 945 if (copyout((caddr_t)&nthrs, ARG, sizeof (int)) 946 == -1) 947 err = EFAULT; 948 } 949 if (auditing) 950 audit_cryptoadm(CRYPTO_POOL_WAIT, NULL, NULL, 951 0, 0, 0, err); 952 return (err); 953 } 954 955 case CRYPTO_POOL_RUN: { 956 int err; 957 958 err = kcf_svc_do_run(); 959 if (auditing) 960 audit_cryptoadm(CRYPTO_POOL_RUN, NULL, NULL, 961 0, 0, 0, err); 962 return (err); 963 } 964 965 case CRYPTO_LOAD_DOOR: 966 return (load_door(dev, ARG, mode, rval)); 967 case CRYPTO_FIPS140_STATUS: 968 return (fips140_actions(dev, ARG, mode, rval, cmd)); 969 case CRYPTO_FIPS140_SET: { 970 int err; 971 972 err = fips140_actions(dev, ARG, mode, rval, cmd); 973 if (auditing) 974 audit_cryptoadm(CRYPTO_FIPS140_SET, NULL, NULL, 975 0, 0, 0, err); 976 return (err); 977 } 978 } 979 980 return (EINVAL); 981} 982