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 /*
22*10500SHai-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*10500SHai-May.Chao@Sun.COM 	entrylist_t *phardlist, entrylist_t *psoftlist,
406*10500SHai-May.Chao@Sun.COM 	entrylist_t *pfipslist)
4070Sstevel@tonic-gate {
4087968Sopensolaris@drydog.com 	boolean_t		in_kernel = B_FALSE;
4090Sstevel@tonic-gate 	crypto_get_soft_info_t	*psoft_info;
4107968Sopensolaris@drydog.com 	mechlist_t		*phead;
4117968Sopensolaris@drydog.com 	mechlist_t		*pmech;
4127968Sopensolaris@drydog.com 	mechlist_t		*pcur;
4137968Sopensolaris@drydog.com 	entry_t			*pent = NULL;
4147968Sopensolaris@drydog.com 	int			count;
4157968Sopensolaris@drydog.com 	int			fd = -1;
4167968Sopensolaris@drydog.com 	int			rc;
4177968Sopensolaris@drydog.com 	int			i;
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	if (provname == NULL) {
4200Sstevel@tonic-gate 		return (FAILURE);
4210Sstevel@tonic-gate 	}
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	if (getzoneid() == GLOBAL_ZONEID) {
4240Sstevel@tonic-gate 		/* use kcf.conf for kernel software providers in global zone */
425*10500SHai-May.Chao@Sun.COM 		if ((pent = getent_kef(provname, phardlist, psoftlist,
426*10500SHai-May.Chao@Sun.COM 		    pfipslist)) == NULL) {
4277968Sopensolaris@drydog.com 
4287968Sopensolaris@drydog.com 			/* No kcf.conf entry for this provider */
4297968Sopensolaris@drydog.com 			if (check_kernel_for_soft(provname, NULL, &in_kernel)
4307968Sopensolaris@drydog.com 			    == FAILURE) {
4317968Sopensolaris@drydog.com 				return (FAILURE);
4327968Sopensolaris@drydog.com 			} else if (in_kernel == B_FALSE) {
4337968Sopensolaris@drydog.com 				cryptoerror(LOG_STDERR,
4347968Sopensolaris@drydog.com 				    gettext("%s does not exist."), provname);
4357968Sopensolaris@drydog.com 				return (FAILURE);
4367968Sopensolaris@drydog.com 			}
4377968Sopensolaris@drydog.com 
4387968Sopensolaris@drydog.com 			/*
4397968Sopensolaris@drydog.com 			 * Set mech count to 1.  It will be reset to the
4407968Sopensolaris@drydog.com 			 * correct value later if the setup buffer is too small.
4417968Sopensolaris@drydog.com 			 */
4427968Sopensolaris@drydog.com 			count = 1;
4437968Sopensolaris@drydog.com 		} else {
4447968Sopensolaris@drydog.com 			count = pent->sup_count;
4457968Sopensolaris@drydog.com 			free_entry(pent);
4460Sstevel@tonic-gate 		}
4470Sstevel@tonic-gate 	} else {
4480Sstevel@tonic-gate 		/*
4497968Sopensolaris@drydog.com 		 * kcf.conf not there in non-global zone: set mech count to 1.
4507968Sopensolaris@drydog.com 		 * It will be reset to the correct value later if the setup
4517968Sopensolaris@drydog.com 		 * buffer is too small.
4520Sstevel@tonic-gate 		 */
4530Sstevel@tonic-gate 		count = 1;
4540Sstevel@tonic-gate 	}
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	if ((psoft_info = setup_get_soft_info(provname, count)) == NULL) {
4570Sstevel@tonic-gate 		return (FAILURE);
4580Sstevel@tonic-gate 	}
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
4610Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
4620Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
4630Sstevel@tonic-gate 		free(psoft_info);
4640Sstevel@tonic-gate 		return (FAILURE);
4650Sstevel@tonic-gate 	}
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 	/* make GET_SOFT_INFO ioctl call */
4680Sstevel@tonic-gate 	if ((rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info)) == -1) {
4690Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed: %s",
4700Sstevel@tonic-gate 		    strerror(errno));
4710Sstevel@tonic-gate 		(void) close(fd);
4720Sstevel@tonic-gate 		free(psoft_info);
4730Sstevel@tonic-gate 		return (FAILURE);
4740Sstevel@tonic-gate 	}
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 	/* BUFFER is too small, get the number of mechanisms and retry it. */
4770Sstevel@tonic-gate 	if (psoft_info->si_return_value == CRYPTO_BUFFER_TOO_SMALL) {
4780Sstevel@tonic-gate 		count = psoft_info->si_count;
4790Sstevel@tonic-gate 		free(psoft_info);
4800Sstevel@tonic-gate 		if ((psoft_info = setup_get_soft_info(provname, count))
4810Sstevel@tonic-gate 		    == NULL) {
4820Sstevel@tonic-gate 			(void) close(fd);
4830Sstevel@tonic-gate 			return (FAILURE);
4840Sstevel@tonic-gate 		} else {
4850Sstevel@tonic-gate 			rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info);
4860Sstevel@tonic-gate 			if (rc == -1) {
4870Sstevel@tonic-gate 				cryptodebug("CRYPTO_GET_SOFT_INFO ioctl "
4880Sstevel@tonic-gate 				    "failed: %s", strerror(errno));
4890Sstevel@tonic-gate 				(void) close(fd);
4900Sstevel@tonic-gate 				free(psoft_info);
4910Sstevel@tonic-gate 				return (FAILURE);
4920Sstevel@tonic-gate 			}
4930Sstevel@tonic-gate 		}
4940Sstevel@tonic-gate 	}
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 	(void) close(fd);
4970Sstevel@tonic-gate 	if (psoft_info->si_return_value != CRYPTO_SUCCESS) {
4980Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed, "
4990Sstevel@tonic-gate 		    "return_value = %d", psoft_info->si_return_value);
5000Sstevel@tonic-gate 		free(psoft_info);
5010Sstevel@tonic-gate 		return (FAILURE);
5020Sstevel@tonic-gate 	}
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 
5057968Sopensolaris@drydog.com 	/* Build the mechanism linked list and return it */
5060Sstevel@tonic-gate 	rc = SUCCESS;
5070Sstevel@tonic-gate 	phead = pcur = NULL;
5080Sstevel@tonic-gate 	for (i = 0; i < psoft_info->si_count; i++) {
5090Sstevel@tonic-gate 		pmech = create_mech(&psoft_info->si_list[i][0]);
5100Sstevel@tonic-gate 		if (pmech == NULL) {
5110Sstevel@tonic-gate 			rc = FAILURE;
5120Sstevel@tonic-gate 			break;
5130Sstevel@tonic-gate 		} else {
5140Sstevel@tonic-gate 			if (phead == NULL) {
5150Sstevel@tonic-gate 				phead = pcur = pmech;
5160Sstevel@tonic-gate 			} else {
5170Sstevel@tonic-gate 				pcur->next = pmech;
5180Sstevel@tonic-gate 				pcur = pmech;
5190Sstevel@tonic-gate 			}
5200Sstevel@tonic-gate 		}
5210Sstevel@tonic-gate 	}
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 	if (rc == FAILURE) {
5240Sstevel@tonic-gate 		free_mechlist(phead);
5250Sstevel@tonic-gate 	} else {
5260Sstevel@tonic-gate 		*ppmechlist = phead;
5270Sstevel@tonic-gate 	}
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 	free(psoft_info);
5300Sstevel@tonic-gate 	return (rc);
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate /*
5350Sstevel@tonic-gate  * Get the kernel software provider list from kernel.
5360Sstevel@tonic-gate  */
5370Sstevel@tonic-gate int
5380Sstevel@tonic-gate get_soft_list(crypto_get_soft_list_t **ppsoftlist)
5390Sstevel@tonic-gate {
5400Sstevel@tonic-gate 	crypto_get_soft_list_t *psoftlist = NULL;
5417968Sopensolaris@drydog.com 	int	count = DEFAULT_SOFT_NUM;
5427968Sopensolaris@drydog.com 	int	len;
5437968Sopensolaris@drydog.com 	int	fd = -1;
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
5460Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
5470Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
5480Sstevel@tonic-gate 		return (FAILURE);
5490Sstevel@tonic-gate 	}
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	len = MAXNAMELEN * count;
5520Sstevel@tonic-gate 	psoftlist = malloc(sizeof (crypto_get_soft_list_t) + len);
5530Sstevel@tonic-gate 	if (psoftlist == NULL) {
5540Sstevel@tonic-gate 		cryptodebug("out of memory.");
5550Sstevel@tonic-gate 		(void) close(fd);
5560Sstevel@tonic-gate 		return (FAILURE);
5570Sstevel@tonic-gate 	}
5580Sstevel@tonic-gate 	psoftlist->sl_soft_names = (caddr_t)(psoftlist + 1);
5590Sstevel@tonic-gate 	psoftlist->sl_soft_count = count;
5600Sstevel@tonic-gate 	psoftlist->sl_soft_len = len;
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_GET_SOFT_LIST, psoftlist) == -1) {
5630Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed: %s",
5640Sstevel@tonic-gate 		    strerror(errno));
5650Sstevel@tonic-gate 		free(psoftlist);
5660Sstevel@tonic-gate 		(void) close(fd);
5670Sstevel@tonic-gate 		return (FAILURE);
5680Sstevel@tonic-gate 	}
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate 	/*
5710Sstevel@tonic-gate 	 * if BUFFER is too small, get the number of software providers and
5720Sstevel@tonic-gate 	 * the minimum length needed for names and length and retry it.
5730Sstevel@tonic-gate 	 */
5740Sstevel@tonic-gate 	if (psoftlist->sl_return_value == CRYPTO_BUFFER_TOO_SMALL) {
5750Sstevel@tonic-gate 		count = psoftlist->sl_soft_count;
5760Sstevel@tonic-gate 		len = psoftlist->sl_soft_len;
5770Sstevel@tonic-gate 		free(psoftlist);
5780Sstevel@tonic-gate 		psoftlist = malloc(sizeof (crypto_get_soft_list_t) + len);
5790Sstevel@tonic-gate 		if (psoftlist == NULL) {
5800Sstevel@tonic-gate 			cryptodebug("out of memory.");
5810Sstevel@tonic-gate 			(void) close(fd);
5820Sstevel@tonic-gate 			return (FAILURE);
5830Sstevel@tonic-gate 		}
5840Sstevel@tonic-gate 		psoftlist->sl_soft_names = (caddr_t)(psoftlist + 1);
5850Sstevel@tonic-gate 		psoftlist->sl_soft_count = count;
5860Sstevel@tonic-gate 		psoftlist->sl_soft_len = len;
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 		if (ioctl(fd, CRYPTO_GET_SOFT_LIST, psoftlist) == -1) {
5890Sstevel@tonic-gate 			cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed:"
5900Sstevel@tonic-gate 			    "%s", strerror(errno));
5910Sstevel@tonic-gate 			free(psoftlist);
5920Sstevel@tonic-gate 			(void) close(fd);
5930Sstevel@tonic-gate 			return (FAILURE);
5940Sstevel@tonic-gate 		}
5950Sstevel@tonic-gate 	}
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 	if (psoftlist->sl_return_value != CRYPTO_SUCCESS) {
5980Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed, "
5990Sstevel@tonic-gate 		    "return_value = %d", psoftlist->sl_return_value);
6000Sstevel@tonic-gate 		free(psoftlist);
6010Sstevel@tonic-gate 		(void) close(fd);
6020Sstevel@tonic-gate 		return (FAILURE);
6030Sstevel@tonic-gate 	}
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate 	*ppsoftlist = psoftlist;
6060Sstevel@tonic-gate 	(void) close(fd);
6070Sstevel@tonic-gate 	return (SUCCESS);
6080Sstevel@tonic-gate }
609*10500SHai-May.Chao@Sun.COM 
610*10500SHai-May.Chao@Sun.COM /*
611*10500SHai-May.Chao@Sun.COM  * Perform the FIPS related actions
612*10500SHai-May.Chao@Sun.COM  */
613*10500SHai-May.Chao@Sun.COM int
614*10500SHai-May.Chao@Sun.COM do_fips_actions(int action, int caller)
615*10500SHai-May.Chao@Sun.COM {
616*10500SHai-May.Chao@Sun.COM 
617*10500SHai-May.Chao@Sun.COM 	crypto_fips140_t	fips_info;
618*10500SHai-May.Chao@Sun.COM 	int	fd;
619*10500SHai-May.Chao@Sun.COM 	int	rc = SUCCESS;
620*10500SHai-May.Chao@Sun.COM 	int	kcf_fips_mode = 0;
621*10500SHai-May.Chao@Sun.COM 
622*10500SHai-May.Chao@Sun.COM 	/* Get FIPS-140 status from kcf.conf */
623*10500SHai-May.Chao@Sun.COM 	fips_status_kcfconf(&kcf_fips_mode);
624*10500SHai-May.Chao@Sun.COM 
625*10500SHai-May.Chao@Sun.COM 	if (action == FIPS140_STATUS) {
626*10500SHai-May.Chao@Sun.COM 		if (kcf_fips_mode == CRYPTO_FIPS_MODE_ENABLED)
627*10500SHai-May.Chao@Sun.COM 			(void) printf(gettext(
628*10500SHai-May.Chao@Sun.COM 			    "\tFIPS-140 mode is enabled.\n"));
629*10500SHai-May.Chao@Sun.COM 		else
630*10500SHai-May.Chao@Sun.COM 			(void) printf(gettext(
631*10500SHai-May.Chao@Sun.COM 			    "\tFIPS-140 mode is disabled.\n"));
632*10500SHai-May.Chao@Sun.COM 		return (SUCCESS);
633*10500SHai-May.Chao@Sun.COM 	}
634*10500SHai-May.Chao@Sun.COM 
635*10500SHai-May.Chao@Sun.COM 	if (caller == NOT_REFRESH) {
636*10500SHai-May.Chao@Sun.COM 		/* Is it a duplicate operation? */
637*10500SHai-May.Chao@Sun.COM 		if ((action == FIPS140_ENABLE) &&
638*10500SHai-May.Chao@Sun.COM 		    (kcf_fips_mode == CRYPTO_FIPS_MODE_ENABLED)) {
639*10500SHai-May.Chao@Sun.COM 			cryptoerror(LOG_STDERR,
640*10500SHai-May.Chao@Sun.COM 			    gettext("FIPS-140 mode has already "
641*10500SHai-May.Chao@Sun.COM 			    "been enabled.\n"));
642*10500SHai-May.Chao@Sun.COM 			return (FAILURE);
643*10500SHai-May.Chao@Sun.COM 		}
644*10500SHai-May.Chao@Sun.COM 
645*10500SHai-May.Chao@Sun.COM 		if ((action == FIPS140_DISABLE) &&
646*10500SHai-May.Chao@Sun.COM 		    (kcf_fips_mode == CRYPTO_FIPS_MODE_DISABLED)) {
647*10500SHai-May.Chao@Sun.COM 			cryptoerror(LOG_STDERR,
648*10500SHai-May.Chao@Sun.COM 			    gettext("FIPS-140 mode has already "
649*10500SHai-May.Chao@Sun.COM 			    "been disabled.\n"));
650*10500SHai-May.Chao@Sun.COM 			return (FAILURE);
651*10500SHai-May.Chao@Sun.COM 		}
652*10500SHai-May.Chao@Sun.COM 
653*10500SHai-May.Chao@Sun.COM 		if ((action == FIPS140_ENABLE) || (action == FIPS140_DISABLE)) {
654*10500SHai-May.Chao@Sun.COM 			/* Update kcf.conf */
655*10500SHai-May.Chao@Sun.COM 			if ((rc = fips_update_kcfconf(action)) != SUCCESS)
656*10500SHai-May.Chao@Sun.COM 				return (rc);
657*10500SHai-May.Chao@Sun.COM 		}
658*10500SHai-May.Chao@Sun.COM 
659*10500SHai-May.Chao@Sun.COM 		/* No need to inform kernel */
660*10500SHai-May.Chao@Sun.COM 		if (action == FIPS140_ENABLE) {
661*10500SHai-May.Chao@Sun.COM 			(void) printf(gettext(
662*10500SHai-May.Chao@Sun.COM 			    "FIPS-140 mode was enabled successfully.\n"));
663*10500SHai-May.Chao@Sun.COM 			(void) printf(gettext(
664*10500SHai-May.Chao@Sun.COM 			    "Warning: In this release, the Cryptographic "
665*10500SHai-May.Chao@Sun.COM 			    "Framework has not been FIPS 140-2 "
666*10500SHai-May.Chao@Sun.COM 			    "certified.\n\n"));
667*10500SHai-May.Chao@Sun.COM 		} else {
668*10500SHai-May.Chao@Sun.COM 			(void) printf(gettext(
669*10500SHai-May.Chao@Sun.COM 			    "FIPS-140 mode was disabled successfully.\n"));
670*10500SHai-May.Chao@Sun.COM 		}
671*10500SHai-May.Chao@Sun.COM 
672*10500SHai-May.Chao@Sun.COM 		(void) printf(gettext(
673*10500SHai-May.Chao@Sun.COM 		    "The FIPS-140 mode has changed.\n"));
674*10500SHai-May.Chao@Sun.COM 		(void) printf(gettext(
675*10500SHai-May.Chao@Sun.COM 		    "The system will require a reboot.\n\n"));
676*10500SHai-May.Chao@Sun.COM 		return (SUCCESS);
677*10500SHai-May.Chao@Sun.COM 
678*10500SHai-May.Chao@Sun.COM 	}
679*10500SHai-May.Chao@Sun.COM 
680*10500SHai-May.Chao@Sun.COM 	/* This is refresh, need to inform kernel */
681*10500SHai-May.Chao@Sun.COM 	(void) memset(&fips_info, 0, sizeof (crypto_fips140_t));
682*10500SHai-May.Chao@Sun.COM 
683*10500SHai-May.Chao@Sun.COM 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
684*10500SHai-May.Chao@Sun.COM 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
685*10500SHai-May.Chao@Sun.COM 		    ADMIN_IOCTL_DEVICE, strerror(errno));
686*10500SHai-May.Chao@Sun.COM 		return (FAILURE);
687*10500SHai-May.Chao@Sun.COM 	}
688*10500SHai-May.Chao@Sun.COM 
689*10500SHai-May.Chao@Sun.COM 	switch (action) {
690*10500SHai-May.Chao@Sun.COM 	case FIPS140_ENABLE:
691*10500SHai-May.Chao@Sun.COM 		/* make CRYPTO_FIPS_SET ioctl call */
692*10500SHai-May.Chao@Sun.COM 		fips_info.fips140_op = FIPS140_ENABLE;
693*10500SHai-May.Chao@Sun.COM 		if ((rc = ioctl(fd, CRYPTO_FIPS140_SET, &fips_info)) == -1) {
694*10500SHai-May.Chao@Sun.COM 			cryptodebug("CRYPTO_FIPS140_ENABLE ioctl failed: %s",
695*10500SHai-May.Chao@Sun.COM 			    strerror(errno));
696*10500SHai-May.Chao@Sun.COM 			rc = FAILURE;
697*10500SHai-May.Chao@Sun.COM 			goto out;
698*10500SHai-May.Chao@Sun.COM 		}
699*10500SHai-May.Chao@Sun.COM 
700*10500SHai-May.Chao@Sun.COM 		if (fips_info.fips140_return_value != CRYPTO_SUCCESS) {
701*10500SHai-May.Chao@Sun.COM 			cryptodebug("CRYPTO_FIPS140_ENABLE ioctl failed, "
702*10500SHai-May.Chao@Sun.COM 			    "return_value = %d",
703*10500SHai-May.Chao@Sun.COM 			    fips_info.fips140_return_value);
704*10500SHai-May.Chao@Sun.COM 			rc = FAILURE;
705*10500SHai-May.Chao@Sun.COM 		}
706*10500SHai-May.Chao@Sun.COM 
707*10500SHai-May.Chao@Sun.COM 		break;
708*10500SHai-May.Chao@Sun.COM 
709*10500SHai-May.Chao@Sun.COM 	case FIPS140_DISABLE:
710*10500SHai-May.Chao@Sun.COM 		/* make CRYPTO_FIPS140_SET ioctl call */
711*10500SHai-May.Chao@Sun.COM 		fips_info.fips140_op = FIPS140_DISABLE;
712*10500SHai-May.Chao@Sun.COM 		if ((rc = ioctl(fd, CRYPTO_FIPS140_SET, &fips_info)) == -1) {
713*10500SHai-May.Chao@Sun.COM 			cryptodebug("CRYPTO_FIPS140_DISABLE ioctl failed: %s",
714*10500SHai-May.Chao@Sun.COM 			    strerror(errno));
715*10500SHai-May.Chao@Sun.COM 			rc = FAILURE;
716*10500SHai-May.Chao@Sun.COM 			goto out;
717*10500SHai-May.Chao@Sun.COM 		}
718*10500SHai-May.Chao@Sun.COM 
719*10500SHai-May.Chao@Sun.COM 		if (fips_info.fips140_return_value != CRYPTO_SUCCESS) {
720*10500SHai-May.Chao@Sun.COM 			cryptodebug("CRYPTO_FIPS140_DISABLE ioctl failed, "
721*10500SHai-May.Chao@Sun.COM 			    "return_value = %d",
722*10500SHai-May.Chao@Sun.COM 			    fips_info.fips140_return_value);
723*10500SHai-May.Chao@Sun.COM 			rc = FAILURE;
724*10500SHai-May.Chao@Sun.COM 		}
725*10500SHai-May.Chao@Sun.COM 
726*10500SHai-May.Chao@Sun.COM 		break;
727*10500SHai-May.Chao@Sun.COM 
728*10500SHai-May.Chao@Sun.COM 	default:
729*10500SHai-May.Chao@Sun.COM 		rc = FAILURE;
730*10500SHai-May.Chao@Sun.COM 		break;
731*10500SHai-May.Chao@Sun.COM 	};
732*10500SHai-May.Chao@Sun.COM 
733*10500SHai-May.Chao@Sun.COM out:
734*10500SHai-May.Chao@Sun.COM 	(void) close(fd);
735*10500SHai-May.Chao@Sun.COM 	return (rc);
736*10500SHai-May.Chao@Sun.COM }
737