10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57968Sopensolaris@drydog.com  * Common Development and Distribution License (the "License").
67968Sopensolaris@drydog.com  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
2210500SHai-May.Chao@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <fcntl.h>
270Sstevel@tonic-gate #include <stdio.h>
280Sstevel@tonic-gate #include <stdlib.h>
290Sstevel@tonic-gate #include <strings.h>
300Sstevel@tonic-gate #include <unistd.h>
310Sstevel@tonic-gate #include <locale.h>
320Sstevel@tonic-gate #include <libgen.h>
330Sstevel@tonic-gate #include <sys/types.h>
340Sstevel@tonic-gate #include <zone.h>
350Sstevel@tonic-gate #include <sys/crypto/ioctladmin.h>
360Sstevel@tonic-gate #include "cryptoadm.h"
370Sstevel@tonic-gate 
380Sstevel@tonic-gate #define	DEFAULT_DEV_NUM 5
390Sstevel@tonic-gate #define	DEFAULT_SOFT_NUM 10
400Sstevel@tonic-gate 
410Sstevel@tonic-gate static crypto_get_soft_info_t *setup_get_soft_info(char *, int);
420Sstevel@tonic-gate 
430Sstevel@tonic-gate /*
440Sstevel@tonic-gate  * Prepare the argument for the LOAD_SOFT_CONFIG ioctl call for the
450Sstevel@tonic-gate  * provider pointed by pent.  Return NULL if out of memory.
460Sstevel@tonic-gate  */
470Sstevel@tonic-gate crypto_load_soft_config_t *
480Sstevel@tonic-gate setup_soft_conf(entry_t *pent)
490Sstevel@tonic-gate {
500Sstevel@tonic-gate 	crypto_load_soft_config_t	*pload_soft_conf;
510Sstevel@tonic-gate 	mechlist_t	*plist;
527968Sopensolaris@drydog.com 	uint_t		sup_count;
537968Sopensolaris@drydog.com 	size_t		extra_mech_size = 0;
547968Sopensolaris@drydog.com 	int		i;
550Sstevel@tonic-gate 
560Sstevel@tonic-gate 	if (pent == NULL) {
570Sstevel@tonic-gate 		return (NULL);
580Sstevel@tonic-gate 	}
590Sstevel@tonic-gate 
600Sstevel@tonic-gate 	sup_count = pent->sup_count;
610Sstevel@tonic-gate 	if (sup_count > 1) {
620Sstevel@tonic-gate 		extra_mech_size = sizeof (crypto_mech_name_t) *
630Sstevel@tonic-gate 		    (sup_count - 1);
640Sstevel@tonic-gate 	}
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 	pload_soft_conf = malloc(sizeof (crypto_load_soft_config_t) +
670Sstevel@tonic-gate 	    extra_mech_size);
680Sstevel@tonic-gate 	if (pload_soft_conf == NULL) {
690Sstevel@tonic-gate 		cryptodebug("out of memory.");
700Sstevel@tonic-gate 		return (NULL);
710Sstevel@tonic-gate 	}
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 	(void) strlcpy(pload_soft_conf->sc_name, pent->name, MAXNAMELEN);
740Sstevel@tonic-gate 	pload_soft_conf->sc_count = sup_count;
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	i = 0;
770Sstevel@tonic-gate 	plist =  pent->suplist;
780Sstevel@tonic-gate 	while (i < sup_count) {
790Sstevel@tonic-gate 		(void) strlcpy(pload_soft_conf->sc_list[i++],
800Sstevel@tonic-gate 		    plist->name, CRYPTO_MAX_MECH_NAME);
810Sstevel@tonic-gate 		plist = plist->next;
820Sstevel@tonic-gate 	}
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 	return (pload_soft_conf);
850Sstevel@tonic-gate }
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 
880Sstevel@tonic-gate /*
890Sstevel@tonic-gate  * Prepare the argument for the LOAD_SOFT_DISABLED ioctl call for the
900Sstevel@tonic-gate  * provider pointed by pent.  Return NULL if out of memory.
910Sstevel@tonic-gate  */
920Sstevel@tonic-gate crypto_load_soft_disabled_t *
930Sstevel@tonic-gate setup_soft_dis(entry_t *pent)
940Sstevel@tonic-gate {
957968Sopensolaris@drydog.com 	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
967968Sopensolaris@drydog.com 	mechlist_t	*plist = NULL;
977968Sopensolaris@drydog.com 	size_t		extra_mech_size = 0;
987968Sopensolaris@drydog.com 	uint_t		dis_count;
997968Sopensolaris@drydog.com 	int		i;
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate 	if (pent == NULL) {
1020Sstevel@tonic-gate 		return (NULL);
1030Sstevel@tonic-gate 	}
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate 	dis_count = pent->dis_count;
1060Sstevel@tonic-gate 	if (dis_count > 1) {
1070Sstevel@tonic-gate 		extra_mech_size = sizeof (crypto_mech_name_t) *
1080Sstevel@tonic-gate 		    (dis_count - 1);
1090Sstevel@tonic-gate 	}
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 	pload_soft_dis = malloc(sizeof (crypto_load_soft_disabled_t) +
1120Sstevel@tonic-gate 	    extra_mech_size);
1130Sstevel@tonic-gate 	if (pload_soft_dis == NULL) {
1140Sstevel@tonic-gate 		cryptodebug("out of memory.");
1150Sstevel@tonic-gate 		return (NULL);
1160Sstevel@tonic-gate 	}
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 	(void) strlcpy(pload_soft_dis->sd_name, pent->name, MAXNAMELEN);
1190Sstevel@tonic-gate 	pload_soft_dis->sd_count = dis_count;
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 	i = 0;
1220Sstevel@tonic-gate 	plist =  pent->dislist;
1230Sstevel@tonic-gate 	while (i < dis_count) {
1240Sstevel@tonic-gate 		(void) strlcpy(pload_soft_dis->sd_list[i++],
1250Sstevel@tonic-gate 		    plist->name, CRYPTO_MAX_MECH_NAME);
1260Sstevel@tonic-gate 		plist = plist->next;
1270Sstevel@tonic-gate 	}
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	return (pload_soft_dis);
1300Sstevel@tonic-gate }
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate /*
1340Sstevel@tonic-gate  * Prepare the argument for the LOAD_DEV_DISABLED ioctl call for the
1350Sstevel@tonic-gate  * provider pointed by pent.  Return NULL if out of memory.
1360Sstevel@tonic-gate  */
1370Sstevel@tonic-gate crypto_load_dev_disabled_t *
1380Sstevel@tonic-gate setup_dev_dis(entry_t *pent)
1390Sstevel@tonic-gate {
1407968Sopensolaris@drydog.com 	crypto_load_dev_disabled_t	*pload_dev_dis = NULL;
1417968Sopensolaris@drydog.com 	mechlist_t	*plist = NULL;
1427968Sopensolaris@drydog.com 	size_t		extra_mech_size = 0;
1437968Sopensolaris@drydog.com 	uint_t		dis_count;
1447968Sopensolaris@drydog.com 	int		i;
1457968Sopensolaris@drydog.com 	char		pname[MAXNAMELEN];
1467968Sopensolaris@drydog.com 	int		inst_num;
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	if (pent == NULL) {
1490Sstevel@tonic-gate 		return (NULL);
1500Sstevel@tonic-gate 	}
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 	/* get the device name and the instance number */
1530Sstevel@tonic-gate 	if (split_hw_provname(pent->name, pname, &inst_num) == FAILURE) {
1540Sstevel@tonic-gate 		return (NULL);
1550Sstevel@tonic-gate 	}
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	/* allocate space for pload_dev_des */
1580Sstevel@tonic-gate 	dis_count = pent->dis_count;
1590Sstevel@tonic-gate 	if (dis_count > 1) {
1600Sstevel@tonic-gate 		extra_mech_size = sizeof (crypto_mech_name_t) *
1610Sstevel@tonic-gate 		    (dis_count - 1);
1620Sstevel@tonic-gate 	}
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	pload_dev_dis = malloc(sizeof (crypto_load_dev_disabled_t) +
1650Sstevel@tonic-gate 	    extra_mech_size);
1660Sstevel@tonic-gate 	if (pload_dev_dis == NULL) {
1670Sstevel@tonic-gate 		cryptodebug("out of memory.");
1680Sstevel@tonic-gate 		return (NULL);
1690Sstevel@tonic-gate 	}
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 	/* set the values for pload_dev_dis */
1720Sstevel@tonic-gate 	(void) strlcpy(pload_dev_dis->dd_dev_name, pname, MAXNAMELEN);
1730Sstevel@tonic-gate 	pload_dev_dis->dd_dev_instance = inst_num;
1740Sstevel@tonic-gate 	pload_dev_dis->dd_count = dis_count;
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	i = 0;
1770Sstevel@tonic-gate 	plist =  pent->dislist;
1780Sstevel@tonic-gate 	while (i < dis_count) {
1790Sstevel@tonic-gate 		(void) strlcpy(pload_dev_dis->dd_list[i++],
1800Sstevel@tonic-gate 		    plist->name, CRYPTO_MAX_MECH_NAME);
1810Sstevel@tonic-gate 		plist = plist->next;
1820Sstevel@tonic-gate 	}
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	return (pload_dev_dis);
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate /*
1890Sstevel@tonic-gate  * Prepare the calling argument of the UNLOAD_SOFT_MODULE ioctl call for the
1900Sstevel@tonic-gate  * provider pointed by pent.  Return NULL if out of memory.
1910Sstevel@tonic-gate  */
1920Sstevel@tonic-gate crypto_unload_soft_module_t *
1930Sstevel@tonic-gate setup_unload_soft(entry_t *pent)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate 	crypto_unload_soft_module_t *punload_soft;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	if (pent == NULL) {
1980Sstevel@tonic-gate 		return (NULL);
1990Sstevel@tonic-gate 	}
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	punload_soft = malloc(sizeof (crypto_unload_soft_module_t));
2020Sstevel@tonic-gate 	if (punload_soft == NULL) {
2030Sstevel@tonic-gate 		cryptodebug("out of memory.");
2040Sstevel@tonic-gate 		return (NULL);
2050Sstevel@tonic-gate 	}
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	(void) strlcpy(punload_soft->sm_name, pent->name, MAXNAMELEN);
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	return (punload_soft);
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate /*
2140Sstevel@tonic-gate  * Prepare the calling argument for the GET_SOFT_INFO call for the provider
2150Sstevel@tonic-gate  * with the number of mechanisms specified in the second argument.
2167968Sopensolaris@drydog.com  *
2177968Sopensolaris@drydog.com  * Called by get_soft_info().
2180Sstevel@tonic-gate  */
2190Sstevel@tonic-gate static crypto_get_soft_info_t *
2200Sstevel@tonic-gate setup_get_soft_info(char *provname, int count)
2210Sstevel@tonic-gate {
2227968Sopensolaris@drydog.com 	crypto_get_soft_info_t	*psoft_info;
2237968Sopensolaris@drydog.com 	size_t			extra_mech_size = 0;
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	if (provname == NULL) {
2260Sstevel@tonic-gate 		return (NULL);
2270Sstevel@tonic-gate 	}
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 	if (count > 1) {
2300Sstevel@tonic-gate 		extra_mech_size = sizeof (crypto_mech_name_t) * (count - 1);
2310Sstevel@tonic-gate 	}
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 	psoft_info = malloc(sizeof (crypto_get_soft_info_t) + extra_mech_size);
2340Sstevel@tonic-gate 	if (psoft_info == NULL) {
2350Sstevel@tonic-gate 		cryptodebug("out of memory.");
2360Sstevel@tonic-gate 		return (NULL);
2370Sstevel@tonic-gate 	}
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 	(void) strlcpy(psoft_info->si_name, provname, MAXNAMELEN);
2400Sstevel@tonic-gate 	psoft_info->si_count = count;
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	return (psoft_info);
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate /*
2470Sstevel@tonic-gate  * Get the device list from kernel.
2480Sstevel@tonic-gate  */
2490Sstevel@tonic-gate int
2500Sstevel@tonic-gate get_dev_list(crypto_get_dev_list_t **ppdevlist)
2510Sstevel@tonic-gate {
2527968Sopensolaris@drydog.com 	crypto_get_dev_list_t	*pdevlist;
2537968Sopensolaris@drydog.com 	int			fd = -1;
2547968Sopensolaris@drydog.com 	int			count = DEFAULT_DEV_NUM;
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	pdevlist = malloc(sizeof (crypto_get_dev_list_t) +
2570Sstevel@tonic-gate 	    sizeof (crypto_dev_list_entry_t) * (count - 1));
2580Sstevel@tonic-gate 	if (pdevlist == NULL) {
2590Sstevel@tonic-gate 		cryptodebug("out of memory.");
2600Sstevel@tonic-gate 		return (FAILURE);
2610Sstevel@tonic-gate 	}
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
2640Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
2650Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
2660Sstevel@tonic-gate 		return (FAILURE);
2670Sstevel@tonic-gate 	}
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	pdevlist->dl_dev_count = count;
2700Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_GET_DEV_LIST, pdevlist) == -1) {
2710Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s",
2720Sstevel@tonic-gate 		    strerror(errno));
2730Sstevel@tonic-gate 		free(pdevlist);
2740Sstevel@tonic-gate 		(void) close(fd);
2750Sstevel@tonic-gate 		return (FAILURE);
2760Sstevel@tonic-gate 	}
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	/* BUFFER is too small, get the number of devices and retry it. */
2790Sstevel@tonic-gate 	if (pdevlist->dl_return_value == CRYPTO_BUFFER_TOO_SMALL) {
2800Sstevel@tonic-gate 		count = pdevlist->dl_dev_count;
2810Sstevel@tonic-gate 		free(pdevlist);
2820Sstevel@tonic-gate 		pdevlist = malloc(sizeof (crypto_get_dev_list_t) +
2830Sstevel@tonic-gate 		    sizeof (crypto_dev_list_entry_t) * (count - 1));
2840Sstevel@tonic-gate 		if (pdevlist == NULL) {
2850Sstevel@tonic-gate 			cryptodebug("out of memory.");
2860Sstevel@tonic-gate 			(void) close(fd);
2870Sstevel@tonic-gate 			return (FAILURE);
2880Sstevel@tonic-gate 		}
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 		if (ioctl(fd, CRYPTO_GET_DEV_LIST, pdevlist) == -1) {
2910Sstevel@tonic-gate 			cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s",
2920Sstevel@tonic-gate 			    strerror(errno));
2930Sstevel@tonic-gate 			free(pdevlist);
2940Sstevel@tonic-gate 			(void) close(fd);
2950Sstevel@tonic-gate 			return (FAILURE);
2960Sstevel@tonic-gate 		}
2970Sstevel@tonic-gate 	}
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	if (pdevlist->dl_return_value != CRYPTO_SUCCESS) {
3000Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed, "
3010Sstevel@tonic-gate 		    "return_value = %d", pdevlist->dl_return_value);
3020Sstevel@tonic-gate 		free(pdevlist);
3030Sstevel@tonic-gate 		(void) close(fd);
3040Sstevel@tonic-gate 		return (FAILURE);
3050Sstevel@tonic-gate 	}
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate 	*ppdevlist = pdevlist;
3080Sstevel@tonic-gate 	(void) close(fd);
3090Sstevel@tonic-gate 	return (SUCCESS);
3100Sstevel@tonic-gate }
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate /*
3140Sstevel@tonic-gate  * Get all the mechanisms supported by the hardware provider.
3150Sstevel@tonic-gate  * The result will be stored in the second argument.
3160Sstevel@tonic-gate  */
3170Sstevel@tonic-gate int
3180Sstevel@tonic-gate get_dev_info(char *devname, int inst_num, int count, mechlist_t **ppmechlist)
3190Sstevel@tonic-gate {
3207968Sopensolaris@drydog.com 	crypto_get_dev_info_t	*dev_info;
3217968Sopensolaris@drydog.com 	mechlist_t	*phead;
3227968Sopensolaris@drydog.com 	mechlist_t	*pcur;
3237968Sopensolaris@drydog.com 	mechlist_t	*pmech;
3247968Sopensolaris@drydog.com 	int		fd = -1;
3257968Sopensolaris@drydog.com 	int		i;
3267968Sopensolaris@drydog.com 	int		rc;
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	if (devname == NULL || count < 1) {
3290Sstevel@tonic-gate 		cryptodebug("get_dev_info(): devname is NULL or bogus count");
3300Sstevel@tonic-gate 		return (FAILURE);
3310Sstevel@tonic-gate 	}
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	/* Set up the argument for the CRYPTO_GET_DEV_INFO ioctl call */
3340Sstevel@tonic-gate 	dev_info = malloc(sizeof (crypto_get_dev_info_t) +
3350Sstevel@tonic-gate 	    sizeof (crypto_mech_name_t) * (count - 1));
3360Sstevel@tonic-gate 	if (dev_info == NULL) {
3370Sstevel@tonic-gate 		cryptodebug("out of memory.");
3380Sstevel@tonic-gate 		return (FAILURE);
3390Sstevel@tonic-gate 	}
3400Sstevel@tonic-gate 	(void) strlcpy(dev_info->di_dev_name, devname, MAXNAMELEN);
3410Sstevel@tonic-gate 	dev_info->di_dev_instance = inst_num;
3420Sstevel@tonic-gate 	dev_info->di_count = count;
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 	/* Open the ioctl device */
3450Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
3460Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
3470Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
3480Sstevel@tonic-gate 		free(dev_info);
3490Sstevel@tonic-gate 		return (FAILURE);
3500Sstevel@tonic-gate 	}
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_GET_DEV_INFO, dev_info) == -1) {
3530Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_DEV_INFO ioctl failed: %s",
3540Sstevel@tonic-gate 		    strerror(errno));
3550Sstevel@tonic-gate 		free(dev_info);
3560Sstevel@tonic-gate 		(void) close(fd);
3570Sstevel@tonic-gate 		return (FAILURE);
3580Sstevel@tonic-gate 	}
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	if (dev_info->di_return_value != CRYPTO_SUCCESS) {
3610Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_DEV_INFO ioctl failed, "
3620Sstevel@tonic-gate 		    "return_value = %d", dev_info->di_return_value);
3630Sstevel@tonic-gate 		free(dev_info);
3640Sstevel@tonic-gate 		(void) close(fd);
3650Sstevel@tonic-gate 		return (FAILURE);
3660Sstevel@tonic-gate 	}
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 	phead = pcur = NULL;
3690Sstevel@tonic-gate 	rc = SUCCESS;
3700Sstevel@tonic-gate 	for (i = 0; i < dev_info->di_count; i++) {
3710Sstevel@tonic-gate 		pmech = create_mech(&dev_info->di_list[i][0]);
3720Sstevel@tonic-gate 		if (pmech == NULL) {
3730Sstevel@tonic-gate 			rc = FAILURE;
3740Sstevel@tonic-gate 			break;
3750Sstevel@tonic-gate 		} else {
3760Sstevel@tonic-gate 			if (phead == NULL) {
3770Sstevel@tonic-gate 				phead = pcur = pmech;
3780Sstevel@tonic-gate 			} else {
3790Sstevel@tonic-gate 				pcur->next = pmech;
3800Sstevel@tonic-gate 				pcur = pmech;
3810Sstevel@tonic-gate 			}
3820Sstevel@tonic-gate 		}
3830Sstevel@tonic-gate 	}
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	if (rc == SUCCESS) {
3860Sstevel@tonic-gate 		*ppmechlist = phead;
3870Sstevel@tonic-gate 	} else {
3880Sstevel@tonic-gate 		free_mechlist(phead);
3890Sstevel@tonic-gate 	}
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 	free(dev_info);
3920Sstevel@tonic-gate 	(void) close(fd);
3930Sstevel@tonic-gate 	return (rc);
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate /*
3980Sstevel@tonic-gate  * Get the supported mechanism list of the software provider from kernel.
3997968Sopensolaris@drydog.com  *
4007968Sopensolaris@drydog.com  * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
4017968Sopensolaris@drydog.com  * If NULL, this function calls get_kcfconf_info() internally.
4020Sstevel@tonic-gate  */
4030Sstevel@tonic-gate int
4047968Sopensolaris@drydog.com get_soft_info(char *provname, mechlist_t **ppmechlist,
405*10979SHai-May.Chao@Sun.COM 	entrylist_t *phardlist, entrylist_t *psoftlist)
4060Sstevel@tonic-gate {
4077968Sopensolaris@drydog.com 	boolean_t		in_kernel = B_FALSE;
4080Sstevel@tonic-gate 	crypto_get_soft_info_t	*psoft_info;
4097968Sopensolaris@drydog.com 	mechlist_t		*phead;
4107968Sopensolaris@drydog.com 	mechlist_t		*pmech;
4117968Sopensolaris@drydog.com 	mechlist_t		*pcur;
4127968Sopensolaris@drydog.com 	entry_t			*pent = NULL;
4137968Sopensolaris@drydog.com 	int			count;
4147968Sopensolaris@drydog.com 	int			fd = -1;
4157968Sopensolaris@drydog.com 	int			rc;
4167968Sopensolaris@drydog.com 	int			i;
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	if (provname == NULL) {
4190Sstevel@tonic-gate 		return (FAILURE);
4200Sstevel@tonic-gate 	}
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 	if (getzoneid() == GLOBAL_ZONEID) {
4230Sstevel@tonic-gate 		/* use kcf.conf for kernel software providers in global zone */
424*10979SHai-May.Chao@Sun.COM 		if ((pent = getent_kef(provname, phardlist, psoftlist)) ==
425*10979SHai-May.Chao@Sun.COM 		    NULL) {
4267968Sopensolaris@drydog.com 
4277968Sopensolaris@drydog.com 			/* No kcf.conf entry for this provider */
4287968Sopensolaris@drydog.com 			if (check_kernel_for_soft(provname, NULL, &in_kernel)
4297968Sopensolaris@drydog.com 			    == FAILURE) {
4307968Sopensolaris@drydog.com 				return (FAILURE);
4317968Sopensolaris@drydog.com 			} else if (in_kernel == B_FALSE) {
4327968Sopensolaris@drydog.com 				cryptoerror(LOG_STDERR,
4337968Sopensolaris@drydog.com 				    gettext("%s does not exist."), provname);
4347968Sopensolaris@drydog.com 				return (FAILURE);
4357968Sopensolaris@drydog.com 			}
4367968Sopensolaris@drydog.com 
4377968Sopensolaris@drydog.com 			/*
4387968Sopensolaris@drydog.com 			 * Set mech count to 1.  It will be reset to the
4397968Sopensolaris@drydog.com 			 * correct value later if the setup buffer is too small.
4407968Sopensolaris@drydog.com 			 */
4417968Sopensolaris@drydog.com 			count = 1;
4427968Sopensolaris@drydog.com 		} else {
4437968Sopensolaris@drydog.com 			count = pent->sup_count;
4447968Sopensolaris@drydog.com 			free_entry(pent);
4450Sstevel@tonic-gate 		}
4460Sstevel@tonic-gate 	} else {
4470Sstevel@tonic-gate 		/*
4487968Sopensolaris@drydog.com 		 * kcf.conf not there in non-global zone: set mech count to 1.
4497968Sopensolaris@drydog.com 		 * It will be reset to the correct value later if the setup
4507968Sopensolaris@drydog.com 		 * buffer is too small.
4510Sstevel@tonic-gate 		 */
4520Sstevel@tonic-gate 		count = 1;
4530Sstevel@tonic-gate 	}
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate 	if ((psoft_info = setup_get_soft_info(provname, count)) == NULL) {
4560Sstevel@tonic-gate 		return (FAILURE);
4570Sstevel@tonic-gate 	}
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
4600Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
4610Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
4620Sstevel@tonic-gate 		free(psoft_info);
4630Sstevel@tonic-gate 		return (FAILURE);
4640Sstevel@tonic-gate 	}
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 	/* make GET_SOFT_INFO ioctl call */
4670Sstevel@tonic-gate 	if ((rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info)) == -1) {
4680Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed: %s",
4690Sstevel@tonic-gate 		    strerror(errno));
4700Sstevel@tonic-gate 		(void) close(fd);
4710Sstevel@tonic-gate 		free(psoft_info);
4720Sstevel@tonic-gate 		return (FAILURE);
4730Sstevel@tonic-gate 	}
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 	/* BUFFER is too small, get the number of mechanisms and retry it. */
4760Sstevel@tonic-gate 	if (psoft_info->si_return_value == CRYPTO_BUFFER_TOO_SMALL) {
4770Sstevel@tonic-gate 		count = psoft_info->si_count;
4780Sstevel@tonic-gate 		free(psoft_info);
4790Sstevel@tonic-gate 		if ((psoft_info = setup_get_soft_info(provname, count))
4800Sstevel@tonic-gate 		    == NULL) {
4810Sstevel@tonic-gate 			(void) close(fd);
4820Sstevel@tonic-gate 			return (FAILURE);
4830Sstevel@tonic-gate 		} else {
4840Sstevel@tonic-gate 			rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info);
4850Sstevel@tonic-gate 			if (rc == -1) {
4860Sstevel@tonic-gate 				cryptodebug("CRYPTO_GET_SOFT_INFO ioctl "
4870Sstevel@tonic-gate 				    "failed: %s", strerror(errno));
4880Sstevel@tonic-gate 				(void) close(fd);
4890Sstevel@tonic-gate 				free(psoft_info);
4900Sstevel@tonic-gate 				return (FAILURE);
4910Sstevel@tonic-gate 			}
4920Sstevel@tonic-gate 		}
4930Sstevel@tonic-gate 	}
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 	(void) close(fd);
4960Sstevel@tonic-gate 	if (psoft_info->si_return_value != CRYPTO_SUCCESS) {
4970Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed, "
4980Sstevel@tonic-gate 		    "return_value = %d", psoft_info->si_return_value);
4990Sstevel@tonic-gate 		free(psoft_info);
5000Sstevel@tonic-gate 		return (FAILURE);
5010Sstevel@tonic-gate 	}
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 
5047968Sopensolaris@drydog.com 	/* Build the mechanism linked list and return it */
5050Sstevel@tonic-gate 	rc = SUCCESS;
5060Sstevel@tonic-gate 	phead = pcur = NULL;
5070Sstevel@tonic-gate 	for (i = 0; i < psoft_info->si_count; i++) {
5080Sstevel@tonic-gate 		pmech = create_mech(&psoft_info->si_list[i][0]);
5090Sstevel@tonic-gate 		if (pmech == NULL) {
5100Sstevel@tonic-gate 			rc = FAILURE;
5110Sstevel@tonic-gate 			break;
5120Sstevel@tonic-gate 		} else {
5130Sstevel@tonic-gate 			if (phead == NULL) {
5140Sstevel@tonic-gate 				phead = pcur = pmech;
5150Sstevel@tonic-gate 			} else {
5160Sstevel@tonic-gate 				pcur->next = pmech;
5170Sstevel@tonic-gate 				pcur = pmech;
5180Sstevel@tonic-gate 			}
5190Sstevel@tonic-gate 		}
5200Sstevel@tonic-gate 	}
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	if (rc == FAILURE) {
5230Sstevel@tonic-gate 		free_mechlist(phead);
5240Sstevel@tonic-gate 	} else {
5250Sstevel@tonic-gate 		*ppmechlist = phead;
5260Sstevel@tonic-gate 	}
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 	free(psoft_info);
5290Sstevel@tonic-gate 	return (rc);
5300Sstevel@tonic-gate }
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate /*
5340Sstevel@tonic-gate  * Get the kernel software provider list from kernel.
5350Sstevel@tonic-gate  */
5360Sstevel@tonic-gate int
5370Sstevel@tonic-gate get_soft_list(crypto_get_soft_list_t **ppsoftlist)
5380Sstevel@tonic-gate {
5390Sstevel@tonic-gate 	crypto_get_soft_list_t *psoftlist = NULL;
5407968Sopensolaris@drydog.com 	int	count = DEFAULT_SOFT_NUM;
5417968Sopensolaris@drydog.com 	int	len;
5427968Sopensolaris@drydog.com 	int	fd = -1;
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
5450Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
5460Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
5470Sstevel@tonic-gate 		return (FAILURE);
5480Sstevel@tonic-gate 	}
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 	len = MAXNAMELEN * count;
5510Sstevel@tonic-gate 	psoftlist = malloc(sizeof (crypto_get_soft_list_t) + len);
5520Sstevel@tonic-gate 	if (psoftlist == NULL) {
5530Sstevel@tonic-gate 		cryptodebug("out of memory.");
5540Sstevel@tonic-gate 		(void) close(fd);
5550Sstevel@tonic-gate 		return (FAILURE);
5560Sstevel@tonic-gate 	}
5570Sstevel@tonic-gate 	psoftlist->sl_soft_names = (caddr_t)(psoftlist + 1);
5580Sstevel@tonic-gate 	psoftlist->sl_soft_count = count;
5590Sstevel@tonic-gate 	psoftlist->sl_soft_len = len;
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_GET_SOFT_LIST, psoftlist) == -1) {
5620Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed: %s",
5630Sstevel@tonic-gate 		    strerror(errno));
5640Sstevel@tonic-gate 		free(psoftlist);
5650Sstevel@tonic-gate 		(void) close(fd);
5660Sstevel@tonic-gate 		return (FAILURE);
5670Sstevel@tonic-gate 	}
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate 	/*
5700Sstevel@tonic-gate 	 * if BUFFER is too small, get the number of software providers and
5710Sstevel@tonic-gate 	 * the minimum length needed for names and length and retry it.
5720Sstevel@tonic-gate 	 */
5730Sstevel@tonic-gate 	if (psoftlist->sl_return_value == CRYPTO_BUFFER_TOO_SMALL) {
5740Sstevel@tonic-gate 		count = psoftlist->sl_soft_count;
5750Sstevel@tonic-gate 		len = psoftlist->sl_soft_len;
5760Sstevel@tonic-gate 		free(psoftlist);
5770Sstevel@tonic-gate 		psoftlist = malloc(sizeof (crypto_get_soft_list_t) + len);
5780Sstevel@tonic-gate 		if (psoftlist == NULL) {
5790Sstevel@tonic-gate 			cryptodebug("out of memory.");
5800Sstevel@tonic-gate 			(void) close(fd);
5810Sstevel@tonic-gate 			return (FAILURE);
5820Sstevel@tonic-gate 		}
5830Sstevel@tonic-gate 		psoftlist->sl_soft_names = (caddr_t)(psoftlist + 1);
5840Sstevel@tonic-gate 		psoftlist->sl_soft_count = count;
5850Sstevel@tonic-gate 		psoftlist->sl_soft_len = len;
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 		if (ioctl(fd, CRYPTO_GET_SOFT_LIST, psoftlist) == -1) {
5880Sstevel@tonic-gate 			cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed:"
5890Sstevel@tonic-gate 			    "%s", strerror(errno));
5900Sstevel@tonic-gate 			free(psoftlist);
5910Sstevel@tonic-gate 			(void) close(fd);
5920Sstevel@tonic-gate 			return (FAILURE);
5930Sstevel@tonic-gate 		}
5940Sstevel@tonic-gate 	}
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 	if (psoftlist->sl_return_value != CRYPTO_SUCCESS) {
5970Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed, "
5980Sstevel@tonic-gate 		    "return_value = %d", psoftlist->sl_return_value);
5990Sstevel@tonic-gate 		free(psoftlist);
6000Sstevel@tonic-gate 		(void) close(fd);
6010Sstevel@tonic-gate 		return (FAILURE);
6020Sstevel@tonic-gate 	}
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 	*ppsoftlist = psoftlist;
6050Sstevel@tonic-gate 	(void) close(fd);
6060Sstevel@tonic-gate 	return (SUCCESS);
6070Sstevel@tonic-gate }
60810500SHai-May.Chao@Sun.COM 
60910500SHai-May.Chao@Sun.COM /*
61010500SHai-May.Chao@Sun.COM  * Perform the FIPS related actions
61110500SHai-May.Chao@Sun.COM  */
61210500SHai-May.Chao@Sun.COM int
61310500SHai-May.Chao@Sun.COM do_fips_actions(int action, int caller)
61410500SHai-May.Chao@Sun.COM {
61510500SHai-May.Chao@Sun.COM 
61610500SHai-May.Chao@Sun.COM 	crypto_fips140_t	fips_info;
61710500SHai-May.Chao@Sun.COM 	int	fd;
61810500SHai-May.Chao@Sun.COM 	int	rc = SUCCESS;
619*10979SHai-May.Chao@Sun.COM 	int	pkcs11_fips_mode = 0;
62010500SHai-May.Chao@Sun.COM 
621*10979SHai-May.Chao@Sun.COM 	/* Get FIPS-140 status from pkcs11.conf */
622*10979SHai-May.Chao@Sun.COM 	fips_status_pkcs11conf(&pkcs11_fips_mode);
62310500SHai-May.Chao@Sun.COM 
62410500SHai-May.Chao@Sun.COM 	if (action == FIPS140_STATUS) {
625*10979SHai-May.Chao@Sun.COM 		if (pkcs11_fips_mode == CRYPTO_FIPS_MODE_ENABLED)
62610500SHai-May.Chao@Sun.COM 			(void) printf(gettext(
62710500SHai-May.Chao@Sun.COM 			    "\tFIPS-140 mode is enabled.\n"));
62810500SHai-May.Chao@Sun.COM 		else
62910500SHai-May.Chao@Sun.COM 			(void) printf(gettext(
63010500SHai-May.Chao@Sun.COM 			    "\tFIPS-140 mode is disabled.\n"));
63110500SHai-May.Chao@Sun.COM 		return (SUCCESS);
63210500SHai-May.Chao@Sun.COM 	}
63310500SHai-May.Chao@Sun.COM 
63410500SHai-May.Chao@Sun.COM 	if (caller == NOT_REFRESH) {
63510500SHai-May.Chao@Sun.COM 		/* Is it a duplicate operation? */
63610500SHai-May.Chao@Sun.COM 		if ((action == FIPS140_ENABLE) &&
637*10979SHai-May.Chao@Sun.COM 		    (pkcs11_fips_mode == CRYPTO_FIPS_MODE_ENABLED)) {
63810500SHai-May.Chao@Sun.COM 			cryptoerror(LOG_STDERR,
63910500SHai-May.Chao@Sun.COM 			    gettext("FIPS-140 mode has already "
64010500SHai-May.Chao@Sun.COM 			    "been enabled.\n"));
64110500SHai-May.Chao@Sun.COM 			return (FAILURE);
64210500SHai-May.Chao@Sun.COM 		}
64310500SHai-May.Chao@Sun.COM 
64410500SHai-May.Chao@Sun.COM 		if ((action == FIPS140_DISABLE) &&
645*10979SHai-May.Chao@Sun.COM 		    (pkcs11_fips_mode == CRYPTO_FIPS_MODE_DISABLED)) {
64610500SHai-May.Chao@Sun.COM 			cryptoerror(LOG_STDERR,
64710500SHai-May.Chao@Sun.COM 			    gettext("FIPS-140 mode has already "
64810500SHai-May.Chao@Sun.COM 			    "been disabled.\n"));
64910500SHai-May.Chao@Sun.COM 			return (FAILURE);
65010500SHai-May.Chao@Sun.COM 		}
65110500SHai-May.Chao@Sun.COM 
65210500SHai-May.Chao@Sun.COM 		if ((action == FIPS140_ENABLE) || (action == FIPS140_DISABLE)) {
653*10979SHai-May.Chao@Sun.COM 			/* Update pkcs11.conf */
654*10979SHai-May.Chao@Sun.COM 			if ((rc = fips_update_pkcs11conf(action)) != SUCCESS)
65510500SHai-May.Chao@Sun.COM 				return (rc);
65610500SHai-May.Chao@Sun.COM 		}
65710500SHai-May.Chao@Sun.COM 
65810500SHai-May.Chao@Sun.COM 		/* No need to inform kernel */
65910500SHai-May.Chao@Sun.COM 		if (action == FIPS140_ENABLE) {
66010500SHai-May.Chao@Sun.COM 			(void) printf(gettext(
66110500SHai-May.Chao@Sun.COM 			    "FIPS-140 mode was enabled successfully.\n"));
66210500SHai-May.Chao@Sun.COM 			(void) printf(gettext(
66310500SHai-May.Chao@Sun.COM 			    "Warning: In this release, the Cryptographic "
66410500SHai-May.Chao@Sun.COM 			    "Framework has not been FIPS 140-2 "
66510500SHai-May.Chao@Sun.COM 			    "certified.\n\n"));
66610500SHai-May.Chao@Sun.COM 		} else {
66710500SHai-May.Chao@Sun.COM 			(void) printf(gettext(
66810500SHai-May.Chao@Sun.COM 			    "FIPS-140 mode was disabled successfully.\n"));
66910500SHai-May.Chao@Sun.COM 		}
67010500SHai-May.Chao@Sun.COM 
67110500SHai-May.Chao@Sun.COM 		(void) printf(gettext(
67210500SHai-May.Chao@Sun.COM 		    "The FIPS-140 mode has changed.\n"));
67310500SHai-May.Chao@Sun.COM 		(void) printf(gettext(
67410500SHai-May.Chao@Sun.COM 		    "The system will require a reboot.\n\n"));
67510500SHai-May.Chao@Sun.COM 		return (SUCCESS);
67610500SHai-May.Chao@Sun.COM 
67710500SHai-May.Chao@Sun.COM 	}
67810500SHai-May.Chao@Sun.COM 
67910500SHai-May.Chao@Sun.COM 	/* This is refresh, need to inform kernel */
68010500SHai-May.Chao@Sun.COM 	(void) memset(&fips_info, 0, sizeof (crypto_fips140_t));
68110500SHai-May.Chao@Sun.COM 
68210500SHai-May.Chao@Sun.COM 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
68310500SHai-May.Chao@Sun.COM 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
68410500SHai-May.Chao@Sun.COM 		    ADMIN_IOCTL_DEVICE, strerror(errno));
68510500SHai-May.Chao@Sun.COM 		return (FAILURE);
68610500SHai-May.Chao@Sun.COM 	}
68710500SHai-May.Chao@Sun.COM 
68810500SHai-May.Chao@Sun.COM 	switch (action) {
68910500SHai-May.Chao@Sun.COM 	case FIPS140_ENABLE:
69010500SHai-May.Chao@Sun.COM 		/* make CRYPTO_FIPS_SET ioctl call */
69110500SHai-May.Chao@Sun.COM 		fips_info.fips140_op = FIPS140_ENABLE;
69210500SHai-May.Chao@Sun.COM 		if ((rc = ioctl(fd, CRYPTO_FIPS140_SET, &fips_info)) == -1) {
69310500SHai-May.Chao@Sun.COM 			cryptodebug("CRYPTO_FIPS140_ENABLE ioctl failed: %s",
69410500SHai-May.Chao@Sun.COM 			    strerror(errno));
69510500SHai-May.Chao@Sun.COM 			rc = FAILURE;
69610500SHai-May.Chao@Sun.COM 			goto out;
69710500SHai-May.Chao@Sun.COM 		}
69810500SHai-May.Chao@Sun.COM 
69910500SHai-May.Chao@Sun.COM 		if (fips_info.fips140_return_value != CRYPTO_SUCCESS) {
70010500SHai-May.Chao@Sun.COM 			cryptodebug("CRYPTO_FIPS140_ENABLE ioctl failed, "
70110500SHai-May.Chao@Sun.COM 			    "return_value = %d",
70210500SHai-May.Chao@Sun.COM 			    fips_info.fips140_return_value);
70310500SHai-May.Chao@Sun.COM 			rc = FAILURE;
70410500SHai-May.Chao@Sun.COM 		}
70510500SHai-May.Chao@Sun.COM 
70610500SHai-May.Chao@Sun.COM 		break;
70710500SHai-May.Chao@Sun.COM 
70810500SHai-May.Chao@Sun.COM 	case FIPS140_DISABLE:
70910500SHai-May.Chao@Sun.COM 		/* make CRYPTO_FIPS140_SET ioctl call */
71010500SHai-May.Chao@Sun.COM 		fips_info.fips140_op = FIPS140_DISABLE;
71110500SHai-May.Chao@Sun.COM 		if ((rc = ioctl(fd, CRYPTO_FIPS140_SET, &fips_info)) == -1) {
71210500SHai-May.Chao@Sun.COM 			cryptodebug("CRYPTO_FIPS140_DISABLE ioctl failed: %s",
71310500SHai-May.Chao@Sun.COM 			    strerror(errno));
71410500SHai-May.Chao@Sun.COM 			rc = FAILURE;
71510500SHai-May.Chao@Sun.COM 			goto out;
71610500SHai-May.Chao@Sun.COM 		}
71710500SHai-May.Chao@Sun.COM 
71810500SHai-May.Chao@Sun.COM 		if (fips_info.fips140_return_value != CRYPTO_SUCCESS) {
71910500SHai-May.Chao@Sun.COM 			cryptodebug("CRYPTO_FIPS140_DISABLE ioctl failed, "
72010500SHai-May.Chao@Sun.COM 			    "return_value = %d",
72110500SHai-May.Chao@Sun.COM 			    fips_info.fips140_return_value);
72210500SHai-May.Chao@Sun.COM 			rc = FAILURE;
72310500SHai-May.Chao@Sun.COM 		}
72410500SHai-May.Chao@Sun.COM 
72510500SHai-May.Chao@Sun.COM 		break;
72610500SHai-May.Chao@Sun.COM 
72710500SHai-May.Chao@Sun.COM 	default:
72810500SHai-May.Chao@Sun.COM 		rc = FAILURE;
72910500SHai-May.Chao@Sun.COM 		break;
73010500SHai-May.Chao@Sun.COM 	};
73110500SHai-May.Chao@Sun.COM 
73210500SHai-May.Chao@Sun.COM out:
73310500SHai-May.Chao@Sun.COM 	(void) close(fd);
73410500SHai-May.Chao@Sun.COM 	return (rc);
73510500SHai-May.Chao@Sun.COM }
736