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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <fcntl.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <strings.h> 29 #include <unistd.h> 30 #include <locale.h> 31 #include <libgen.h> 32 #include <sys/types.h> 33 #include <sys/varargs.h> 34 #include <zone.h> 35 #include <sys/crypto/ioctladmin.h> 36 #include "cryptoadm.h" 37 38 #define DEFAULT_DEV_NUM 5 39 #define DEFAULT_SOFT_NUM 10 40 41 #define NUM_FIPS_SW_PROV \ 42 (sizeof (fips_sw_providers) / sizeof (char *)) 43 44 static char *fips_sw_providers[] = { 45 "des", 46 "aes", 47 "ecc", 48 "sha1", 49 "sha2", 50 "rsa", 51 "swrand" 52 }; 53 54 static crypto_get_soft_info_t *setup_get_soft_info(char *, int); 55 56 static void 57 fips_sw_printf(const char *format, ...) 58 { 59 va_list ap; 60 char message[1024]; 61 int i; 62 63 va_start(ap, format); 64 (void) snprintf(message, sizeof (message), format, ap); 65 va_end(ap); 66 67 (void) printf(gettext("\nUser-level providers:\n")); 68 (void) printf(gettext("=====================\n")); 69 (void) printf(gettext("/usr/lib/security/$ISA/pkcs11_softtoken: %s\n"), 70 message); 71 (void) printf(gettext("\nKernel software providers:\n")); 72 (void) printf(gettext("==========================\n")); 73 for (i = 0; i < NUM_FIPS_SW_PROV; i++) { 74 (void) printf(gettext("%s: %s\n"), 75 fips_sw_providers[i], message); 76 } 77 } 78 79 /* 80 * Prepare the argument for the LOAD_SOFT_CONFIG ioctl call for the 81 * provider pointed by pent. Return NULL if out of memory. 82 */ 83 crypto_load_soft_config_t * 84 setup_soft_conf(entry_t *pent) 85 { 86 crypto_load_soft_config_t *pload_soft_conf; 87 mechlist_t *plist; 88 uint_t sup_count; 89 size_t extra_mech_size = 0; 90 int i; 91 92 if (pent == NULL) { 93 return (NULL); 94 } 95 96 sup_count = pent->sup_count; 97 if (sup_count > 1) { 98 extra_mech_size = sizeof (crypto_mech_name_t) * 99 (sup_count - 1); 100 } 101 102 pload_soft_conf = malloc(sizeof (crypto_load_soft_config_t) + 103 extra_mech_size); 104 if (pload_soft_conf == NULL) { 105 cryptodebug("out of memory."); 106 return (NULL); 107 } 108 109 (void) strlcpy(pload_soft_conf->sc_name, pent->name, MAXNAMELEN); 110 pload_soft_conf->sc_count = sup_count; 111 112 i = 0; 113 plist = pent->suplist; 114 while (i < sup_count) { 115 (void) strlcpy(pload_soft_conf->sc_list[i++], 116 plist->name, CRYPTO_MAX_MECH_NAME); 117 plist = plist->next; 118 } 119 120 return (pload_soft_conf); 121 } 122 123 124 /* 125 * Prepare the argument for the LOAD_SOFT_DISABLED ioctl call for the 126 * provider pointed by pent. Return NULL if out of memory. 127 */ 128 crypto_load_soft_disabled_t * 129 setup_soft_dis(entry_t *pent) 130 { 131 crypto_load_soft_disabled_t *pload_soft_dis = NULL; 132 mechlist_t *plist = NULL; 133 size_t extra_mech_size = 0; 134 uint_t dis_count; 135 int i; 136 137 if (pent == NULL) { 138 return (NULL); 139 } 140 141 dis_count = pent->dis_count; 142 if (dis_count > 1) { 143 extra_mech_size = sizeof (crypto_mech_name_t) * 144 (dis_count - 1); 145 } 146 147 pload_soft_dis = malloc(sizeof (crypto_load_soft_disabled_t) + 148 extra_mech_size); 149 if (pload_soft_dis == NULL) { 150 cryptodebug("out of memory."); 151 return (NULL); 152 } 153 154 (void) strlcpy(pload_soft_dis->sd_name, pent->name, MAXNAMELEN); 155 pload_soft_dis->sd_count = dis_count; 156 157 i = 0; 158 plist = pent->dislist; 159 while (i < dis_count) { 160 (void) strlcpy(pload_soft_dis->sd_list[i++], 161 plist->name, CRYPTO_MAX_MECH_NAME); 162 plist = plist->next; 163 } 164 165 return (pload_soft_dis); 166 } 167 168 169 /* 170 * Prepare the argument for the LOAD_DEV_DISABLED ioctl call for the 171 * provider pointed by pent. Return NULL if out of memory. 172 */ 173 crypto_load_dev_disabled_t * 174 setup_dev_dis(entry_t *pent) 175 { 176 crypto_load_dev_disabled_t *pload_dev_dis = NULL; 177 mechlist_t *plist = NULL; 178 size_t extra_mech_size = 0; 179 uint_t dis_count; 180 int i; 181 char pname[MAXNAMELEN]; 182 int inst_num; 183 184 if (pent == NULL) { 185 return (NULL); 186 } 187 188 /* get the device name and the instance number */ 189 if (split_hw_provname(pent->name, pname, &inst_num) == FAILURE) { 190 return (NULL); 191 } 192 193 /* allocate space for pload_dev_des */ 194 dis_count = pent->dis_count; 195 if (dis_count > 1) { 196 extra_mech_size = sizeof (crypto_mech_name_t) * 197 (dis_count - 1); 198 } 199 200 pload_dev_dis = malloc(sizeof (crypto_load_dev_disabled_t) + 201 extra_mech_size); 202 if (pload_dev_dis == NULL) { 203 cryptodebug("out of memory."); 204 return (NULL); 205 } 206 207 /* set the values for pload_dev_dis */ 208 (void) strlcpy(pload_dev_dis->dd_dev_name, pname, MAXNAMELEN); 209 pload_dev_dis->dd_dev_instance = inst_num; 210 pload_dev_dis->dd_count = dis_count; 211 212 i = 0; 213 plist = pent->dislist; 214 while (i < dis_count) { 215 (void) strlcpy(pload_dev_dis->dd_list[i++], 216 plist->name, CRYPTO_MAX_MECH_NAME); 217 plist = plist->next; 218 } 219 220 return (pload_dev_dis); 221 } 222 223 224 /* 225 * Prepare the calling argument of the UNLOAD_SOFT_MODULE ioctl call for the 226 * provider pointed by pent. Return NULL if out of memory. 227 */ 228 crypto_unload_soft_module_t * 229 setup_unload_soft(entry_t *pent) 230 { 231 crypto_unload_soft_module_t *punload_soft; 232 233 if (pent == NULL) { 234 return (NULL); 235 } 236 237 punload_soft = malloc(sizeof (crypto_unload_soft_module_t)); 238 if (punload_soft == NULL) { 239 cryptodebug("out of memory."); 240 return (NULL); 241 } 242 243 (void) strlcpy(punload_soft->sm_name, pent->name, MAXNAMELEN); 244 245 return (punload_soft); 246 } 247 248 249 /* 250 * Prepare the calling argument for the GET_SOFT_INFO call for the provider 251 * with the number of mechanisms specified in the second argument. 252 * 253 * Called by get_soft_info(). 254 */ 255 static crypto_get_soft_info_t * 256 setup_get_soft_info(char *provname, int count) 257 { 258 crypto_get_soft_info_t *psoft_info; 259 size_t extra_mech_size = 0; 260 261 if (provname == NULL) { 262 return (NULL); 263 } 264 265 if (count > 1) { 266 extra_mech_size = sizeof (crypto_mech_name_t) * (count - 1); 267 } 268 269 psoft_info = malloc(sizeof (crypto_get_soft_info_t) + extra_mech_size); 270 if (psoft_info == NULL) { 271 cryptodebug("out of memory."); 272 return (NULL); 273 } 274 275 (void) strlcpy(psoft_info->si_name, provname, MAXNAMELEN); 276 psoft_info->si_count = count; 277 278 return (psoft_info); 279 } 280 281 282 /* 283 * Get the device list from kernel. 284 */ 285 int 286 get_dev_list(crypto_get_dev_list_t **ppdevlist) 287 { 288 crypto_get_dev_list_t *pdevlist; 289 int fd = -1; 290 int count = DEFAULT_DEV_NUM; 291 292 pdevlist = malloc(sizeof (crypto_get_dev_list_t) + 293 sizeof (crypto_dev_list_entry_t) * (count - 1)); 294 if (pdevlist == NULL) { 295 cryptodebug("out of memory."); 296 return (FAILURE); 297 } 298 299 if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) { 300 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 301 ADMIN_IOCTL_DEVICE, strerror(errno)); 302 return (FAILURE); 303 } 304 305 pdevlist->dl_dev_count = count; 306 if (ioctl(fd, CRYPTO_GET_DEV_LIST, pdevlist) == -1) { 307 cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s", 308 strerror(errno)); 309 free(pdevlist); 310 (void) close(fd); 311 return (FAILURE); 312 } 313 314 /* BUFFER is too small, get the number of devices and retry it. */ 315 if (pdevlist->dl_return_value == CRYPTO_BUFFER_TOO_SMALL) { 316 count = pdevlist->dl_dev_count; 317 free(pdevlist); 318 pdevlist = malloc(sizeof (crypto_get_dev_list_t) + 319 sizeof (crypto_dev_list_entry_t) * (count - 1)); 320 if (pdevlist == NULL) { 321 cryptodebug("out of memory."); 322 (void) close(fd); 323 return (FAILURE); 324 } 325 326 if (ioctl(fd, CRYPTO_GET_DEV_LIST, pdevlist) == -1) { 327 cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s", 328 strerror(errno)); 329 free(pdevlist); 330 (void) close(fd); 331 return (FAILURE); 332 } 333 } 334 335 if (pdevlist->dl_return_value != CRYPTO_SUCCESS) { 336 cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed, " 337 "return_value = %d", pdevlist->dl_return_value); 338 free(pdevlist); 339 (void) close(fd); 340 return (FAILURE); 341 } 342 343 *ppdevlist = pdevlist; 344 (void) close(fd); 345 return (SUCCESS); 346 } 347 348 349 /* 350 * Get all the mechanisms supported by the hardware provider. 351 * The result will be stored in the second argument. 352 */ 353 int 354 get_dev_info(char *devname, int inst_num, int count, mechlist_t **ppmechlist) 355 { 356 crypto_get_dev_info_t *dev_info; 357 mechlist_t *phead; 358 mechlist_t *pcur; 359 mechlist_t *pmech; 360 int fd = -1; 361 int i; 362 int rc; 363 364 if (devname == NULL || count < 1) { 365 cryptodebug("get_dev_info(): devname is NULL or bogus count"); 366 return (FAILURE); 367 } 368 369 /* Set up the argument for the CRYPTO_GET_DEV_INFO ioctl call */ 370 dev_info = malloc(sizeof (crypto_get_dev_info_t) + 371 sizeof (crypto_mech_name_t) * (count - 1)); 372 if (dev_info == NULL) { 373 cryptodebug("out of memory."); 374 return (FAILURE); 375 } 376 (void) strlcpy(dev_info->di_dev_name, devname, MAXNAMELEN); 377 dev_info->di_dev_instance = inst_num; 378 dev_info->di_count = count; 379 380 /* Open the ioctl device */ 381 if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) { 382 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 383 ADMIN_IOCTL_DEVICE, strerror(errno)); 384 free(dev_info); 385 return (FAILURE); 386 } 387 388 if (ioctl(fd, CRYPTO_GET_DEV_INFO, dev_info) == -1) { 389 cryptodebug("CRYPTO_GET_DEV_INFO ioctl failed: %s", 390 strerror(errno)); 391 free(dev_info); 392 (void) close(fd); 393 return (FAILURE); 394 } 395 396 if (dev_info->di_return_value != CRYPTO_SUCCESS) { 397 cryptodebug("CRYPTO_GET_DEV_INFO ioctl failed, " 398 "return_value = %d", dev_info->di_return_value); 399 free(dev_info); 400 (void) close(fd); 401 return (FAILURE); 402 } 403 404 phead = pcur = NULL; 405 rc = SUCCESS; 406 for (i = 0; i < dev_info->di_count; i++) { 407 pmech = create_mech(&dev_info->di_list[i][0]); 408 if (pmech == NULL) { 409 rc = FAILURE; 410 break; 411 } else { 412 if (phead == NULL) { 413 phead = pcur = pmech; 414 } else { 415 pcur->next = pmech; 416 pcur = pmech; 417 } 418 } 419 } 420 421 if (rc == SUCCESS) { 422 *ppmechlist = phead; 423 } else { 424 free_mechlist(phead); 425 } 426 427 free(dev_info); 428 (void) close(fd); 429 return (rc); 430 } 431 432 433 /* 434 * Get the supported mechanism list of the software provider from kernel. 435 * 436 * Parameters phardlist and psoftlist are supplied by get_kcfconf_info(). 437 * If NULL, this function calls get_kcfconf_info() internally. 438 */ 439 int 440 get_soft_info(char *provname, mechlist_t **ppmechlist, 441 entrylist_t *phardlist, entrylist_t *psoftlist) 442 { 443 boolean_t in_kernel = B_FALSE; 444 crypto_get_soft_info_t *psoft_info; 445 mechlist_t *phead; 446 mechlist_t *pmech; 447 mechlist_t *pcur; 448 entry_t *pent = NULL; 449 int count; 450 int fd = -1; 451 int rc; 452 int i; 453 454 if (provname == NULL) { 455 return (FAILURE); 456 } 457 458 if (getzoneid() == GLOBAL_ZONEID) { 459 /* use kcf.conf for kernel software providers in global zone */ 460 if ((pent = getent_kef(provname, phardlist, psoftlist)) == 461 NULL) { 462 463 /* No kcf.conf entry for this provider */ 464 if (check_kernel_for_soft(provname, NULL, &in_kernel) 465 == FAILURE) { 466 return (FAILURE); 467 } else if (in_kernel == B_FALSE) { 468 cryptoerror(LOG_STDERR, 469 gettext("%s does not exist."), provname); 470 return (FAILURE); 471 } 472 473 /* 474 * Set mech count to 1. It will be reset to the 475 * correct value later if the setup buffer is too small. 476 */ 477 count = 1; 478 } else { 479 count = pent->sup_count; 480 free_entry(pent); 481 } 482 } else { 483 /* 484 * kcf.conf not there in non-global zone: set mech count to 1. 485 * It will be reset to the correct value later if the setup 486 * buffer is too small. 487 */ 488 count = 1; 489 } 490 491 if ((psoft_info = setup_get_soft_info(provname, count)) == NULL) { 492 return (FAILURE); 493 } 494 495 if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) { 496 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 497 ADMIN_IOCTL_DEVICE, strerror(errno)); 498 free(psoft_info); 499 return (FAILURE); 500 } 501 502 /* make GET_SOFT_INFO ioctl call */ 503 if ((rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info)) == -1) { 504 cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed: %s", 505 strerror(errno)); 506 (void) close(fd); 507 free(psoft_info); 508 return (FAILURE); 509 } 510 511 /* BUFFER is too small, get the number of mechanisms and retry it. */ 512 if (psoft_info->si_return_value == CRYPTO_BUFFER_TOO_SMALL) { 513 count = psoft_info->si_count; 514 free(psoft_info); 515 if ((psoft_info = setup_get_soft_info(provname, count)) 516 == NULL) { 517 (void) close(fd); 518 return (FAILURE); 519 } else { 520 rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info); 521 if (rc == -1) { 522 cryptodebug("CRYPTO_GET_SOFT_INFO ioctl " 523 "failed: %s", strerror(errno)); 524 (void) close(fd); 525 free(psoft_info); 526 return (FAILURE); 527 } 528 } 529 } 530 531 (void) close(fd); 532 if (psoft_info->si_return_value != CRYPTO_SUCCESS) { 533 cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed, " 534 "return_value = %d", psoft_info->si_return_value); 535 free(psoft_info); 536 return (FAILURE); 537 } 538 539 540 /* Build the mechanism linked list and return it */ 541 rc = SUCCESS; 542 phead = pcur = NULL; 543 for (i = 0; i < psoft_info->si_count; i++) { 544 pmech = create_mech(&psoft_info->si_list[i][0]); 545 if (pmech == NULL) { 546 rc = FAILURE; 547 break; 548 } else { 549 if (phead == NULL) { 550 phead = pcur = pmech; 551 } else { 552 pcur->next = pmech; 553 pcur = pmech; 554 } 555 } 556 } 557 558 if (rc == FAILURE) { 559 free_mechlist(phead); 560 } else { 561 *ppmechlist = phead; 562 } 563 564 free(psoft_info); 565 return (rc); 566 } 567 568 569 /* 570 * Get the kernel software provider list from kernel. 571 */ 572 int 573 get_soft_list(crypto_get_soft_list_t **ppsoftlist) 574 { 575 crypto_get_soft_list_t *psoftlist = NULL; 576 int count = DEFAULT_SOFT_NUM; 577 int len; 578 int fd = -1; 579 580 if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) { 581 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 582 ADMIN_IOCTL_DEVICE, strerror(errno)); 583 return (FAILURE); 584 } 585 586 len = MAXNAMELEN * count; 587 psoftlist = malloc(sizeof (crypto_get_soft_list_t) + len); 588 if (psoftlist == NULL) { 589 cryptodebug("out of memory."); 590 (void) close(fd); 591 return (FAILURE); 592 } 593 psoftlist->sl_soft_names = (caddr_t)(psoftlist + 1); 594 psoftlist->sl_soft_count = count; 595 psoftlist->sl_soft_len = len; 596 597 if (ioctl(fd, CRYPTO_GET_SOFT_LIST, psoftlist) == -1) { 598 cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed: %s", 599 strerror(errno)); 600 free(psoftlist); 601 (void) close(fd); 602 return (FAILURE); 603 } 604 605 /* 606 * if BUFFER is too small, get the number of software providers and 607 * the minimum length needed for names and length and retry it. 608 */ 609 if (psoftlist->sl_return_value == CRYPTO_BUFFER_TOO_SMALL) { 610 count = psoftlist->sl_soft_count; 611 len = psoftlist->sl_soft_len; 612 free(psoftlist); 613 psoftlist = malloc(sizeof (crypto_get_soft_list_t) + len); 614 if (psoftlist == NULL) { 615 cryptodebug("out of memory."); 616 (void) close(fd); 617 return (FAILURE); 618 } 619 psoftlist->sl_soft_names = (caddr_t)(psoftlist + 1); 620 psoftlist->sl_soft_count = count; 621 psoftlist->sl_soft_len = len; 622 623 if (ioctl(fd, CRYPTO_GET_SOFT_LIST, psoftlist) == -1) { 624 cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed:" 625 "%s", strerror(errno)); 626 free(psoftlist); 627 (void) close(fd); 628 return (FAILURE); 629 } 630 } 631 632 if (psoftlist->sl_return_value != CRYPTO_SUCCESS) { 633 cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed, " 634 "return_value = %d", psoftlist->sl_return_value); 635 free(psoftlist); 636 (void) close(fd); 637 return (FAILURE); 638 } 639 640 *ppsoftlist = psoftlist; 641 (void) close(fd); 642 return (SUCCESS); 643 } 644 645 /* 646 * Perform the FIPS related actions 647 */ 648 int 649 do_fips_actions(int action, int caller) 650 { 651 652 crypto_fips140_t fips_info; 653 int fd; 654 int rc = SUCCESS; 655 int pkcs11_fips_mode = 0; 656 657 /* Get FIPS-140 status from pkcs11.conf */ 658 fips_status_pkcs11conf(&pkcs11_fips_mode); 659 660 if (action == FIPS140_STATUS) { 661 if (pkcs11_fips_mode == CRYPTO_FIPS_MODE_ENABLED) 662 fips_sw_printf(gettext("FIPS-140 mode is enabled.")); 663 else 664 fips_sw_printf(gettext("FIPS-140 mode is disabled.")); 665 return (SUCCESS); 666 } 667 668 if (caller == NOT_REFRESH) { 669 /* Is it a duplicate operation? */ 670 if ((action == FIPS140_ENABLE) && 671 (pkcs11_fips_mode == CRYPTO_FIPS_MODE_ENABLED)) { 672 fips_sw_printf(gettext("FIPS-140 mode has already " 673 "been enabled.")); 674 return (FAILURE); 675 } 676 677 if ((action == FIPS140_DISABLE) && 678 (pkcs11_fips_mode == CRYPTO_FIPS_MODE_DISABLED)) { 679 fips_sw_printf(gettext("FIPS-140 mode has already " 680 "been disabled.")); 681 return (FAILURE); 682 } 683 684 if ((action == FIPS140_ENABLE) || (action == FIPS140_DISABLE)) { 685 /* Update pkcs11.conf */ 686 if ((rc = fips_update_pkcs11conf(action)) != SUCCESS) 687 return (rc); 688 } 689 690 /* No need to inform kernel */ 691 if (action == FIPS140_ENABLE) { 692 fips_sw_printf(gettext("FIPS-140 mode was enabled " 693 "successfully.")); 694 } else { 695 fips_sw_printf(gettext("FIPS-140 mode was disabled " 696 "successfully.")); 697 } 698 699 return (SUCCESS); 700 701 } 702 703 /* This is refresh, need to inform kernel */ 704 (void) memset(&fips_info, 0, sizeof (crypto_fips140_t)); 705 706 if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) { 707 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 708 ADMIN_IOCTL_DEVICE, strerror(errno)); 709 return (FAILURE); 710 } 711 712 switch (action) { 713 case FIPS140_ENABLE: 714 /* make CRYPTO_FIPS_SET ioctl call */ 715 fips_info.fips140_op = FIPS140_ENABLE; 716 if ((rc = ioctl(fd, CRYPTO_FIPS140_SET, &fips_info)) == -1) { 717 cryptodebug("CRYPTO_FIPS140_ENABLE ioctl failed: %s", 718 strerror(errno)); 719 rc = FAILURE; 720 goto out; 721 } 722 723 if (fips_info.fips140_return_value != CRYPTO_SUCCESS) { 724 cryptodebug("CRYPTO_FIPS140_ENABLE ioctl failed, " 725 "return_value = %d", 726 fips_info.fips140_return_value); 727 rc = FAILURE; 728 } 729 730 break; 731 732 case FIPS140_DISABLE: 733 /* make CRYPTO_FIPS140_SET ioctl call */ 734 fips_info.fips140_op = FIPS140_DISABLE; 735 if ((rc = ioctl(fd, CRYPTO_FIPS140_SET, &fips_info)) == -1) { 736 cryptodebug("CRYPTO_FIPS140_DISABLE ioctl failed: %s", 737 strerror(errno)); 738 rc = FAILURE; 739 goto out; 740 } 741 742 if (fips_info.fips140_return_value != CRYPTO_SUCCESS) { 743 cryptodebug("CRYPTO_FIPS140_DISABLE ioctl failed, " 744 "return_value = %d", 745 fips_info.fips140_return_value); 746 rc = FAILURE; 747 } 748 749 break; 750 751 default: 752 rc = FAILURE; 753 break; 754 }; 755 756 out: 757 (void) close(fd); 758 return (rc); 759 } 760