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
fips_sw_printf(const char * format,...)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 *
setup_soft_conf(entry_t * pent)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 *
setup_soft_dis(entry_t * pent)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 *
setup_dev_dis(entry_t * pent)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 *
setup_unload_soft(entry_t * pent)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 *
setup_get_soft_info(char * provname,int count)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
get_dev_list(crypto_get_dev_list_t ** ppdevlist)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
get_dev_info(char * devname,int inst_num,int count,mechlist_t ** ppmechlist)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
get_soft_info(char * provname,mechlist_t ** ppmechlist,entrylist_t * phardlist,entrylist_t * psoftlist)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
get_soft_list(crypto_get_soft_list_t ** ppsoftlist)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
do_fips_actions(int action,int caller)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