xref: /onnv-gate/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef_ioctl.c (revision 12929:f2051cc42292)
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*12929SMisaki.Miyashita@Oracle.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate #include <fcntl.h>
260Sstevel@tonic-gate #include <stdio.h>
270Sstevel@tonic-gate #include <stdlib.h>
280Sstevel@tonic-gate #include <strings.h>
290Sstevel@tonic-gate #include <unistd.h>
300Sstevel@tonic-gate #include <locale.h>
310Sstevel@tonic-gate #include <libgen.h>
320Sstevel@tonic-gate #include <sys/types.h>
33*12929SMisaki.Miyashita@Oracle.COM #include <sys/varargs.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 
41*12929SMisaki.Miyashita@Oracle.COM #define	NUM_FIPS_SW_PROV	\
42*12929SMisaki.Miyashita@Oracle.COM 	(sizeof (fips_sw_providers) / sizeof (char *))
43*12929SMisaki.Miyashita@Oracle.COM 
44*12929SMisaki.Miyashita@Oracle.COM static char *fips_sw_providers[] = {
45*12929SMisaki.Miyashita@Oracle.COM 	"des",
46*12929SMisaki.Miyashita@Oracle.COM 	"aes",
47*12929SMisaki.Miyashita@Oracle.COM 	"ecc",
48*12929SMisaki.Miyashita@Oracle.COM 	"sha1",
49*12929SMisaki.Miyashita@Oracle.COM 	"sha2",
50*12929SMisaki.Miyashita@Oracle.COM 	"rsa",
51*12929SMisaki.Miyashita@Oracle.COM 	"swrand"
52*12929SMisaki.Miyashita@Oracle.COM };
53*12929SMisaki.Miyashita@Oracle.COM 
540Sstevel@tonic-gate static crypto_get_soft_info_t *setup_get_soft_info(char *, int);
550Sstevel@tonic-gate 
56*12929SMisaki.Miyashita@Oracle.COM static void
fips_sw_printf(const char * format,...)57*12929SMisaki.Miyashita@Oracle.COM fips_sw_printf(const char *format, ...)
58*12929SMisaki.Miyashita@Oracle.COM {
59*12929SMisaki.Miyashita@Oracle.COM 	va_list	ap;
60*12929SMisaki.Miyashita@Oracle.COM 	char	message[1024];
61*12929SMisaki.Miyashita@Oracle.COM 	int	i;
62*12929SMisaki.Miyashita@Oracle.COM 
63*12929SMisaki.Miyashita@Oracle.COM 	va_start(ap, format);
64*12929SMisaki.Miyashita@Oracle.COM 	(void) snprintf(message, sizeof (message), format, ap);
65*12929SMisaki.Miyashita@Oracle.COM 	va_end(ap);
66*12929SMisaki.Miyashita@Oracle.COM 
67*12929SMisaki.Miyashita@Oracle.COM 	(void) printf(gettext("\nUser-level providers:\n"));
68*12929SMisaki.Miyashita@Oracle.COM 	(void) printf(gettext("=====================\n"));
69*12929SMisaki.Miyashita@Oracle.COM 	(void) printf(gettext("/usr/lib/security/$ISA/pkcs11_softtoken: %s\n"),
70*12929SMisaki.Miyashita@Oracle.COM 	    message);
71*12929SMisaki.Miyashita@Oracle.COM 	(void) printf(gettext("\nKernel software providers:\n"));
72*12929SMisaki.Miyashita@Oracle.COM 	(void) printf(gettext("==========================\n"));
73*12929SMisaki.Miyashita@Oracle.COM 	for (i = 0; i < NUM_FIPS_SW_PROV; i++) {
74*12929SMisaki.Miyashita@Oracle.COM 		(void) printf(gettext("%s: %s\n"),
75*12929SMisaki.Miyashita@Oracle.COM 		    fips_sw_providers[i], message);
76*12929SMisaki.Miyashita@Oracle.COM 	}
77*12929SMisaki.Miyashita@Oracle.COM }
78*12929SMisaki.Miyashita@Oracle.COM 
790Sstevel@tonic-gate /*
800Sstevel@tonic-gate  * Prepare the argument for the LOAD_SOFT_CONFIG ioctl call for the
810Sstevel@tonic-gate  * provider pointed by pent.  Return NULL if out of memory.
820Sstevel@tonic-gate  */
830Sstevel@tonic-gate crypto_load_soft_config_t *
setup_soft_conf(entry_t * pent)840Sstevel@tonic-gate setup_soft_conf(entry_t *pent)
850Sstevel@tonic-gate {
860Sstevel@tonic-gate 	crypto_load_soft_config_t	*pload_soft_conf;
870Sstevel@tonic-gate 	mechlist_t	*plist;
887968Sopensolaris@drydog.com 	uint_t		sup_count;
897968Sopensolaris@drydog.com 	size_t		extra_mech_size = 0;
907968Sopensolaris@drydog.com 	int		i;
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 	if (pent == NULL) {
930Sstevel@tonic-gate 		return (NULL);
940Sstevel@tonic-gate 	}
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	sup_count = pent->sup_count;
970Sstevel@tonic-gate 	if (sup_count > 1) {
980Sstevel@tonic-gate 		extra_mech_size = sizeof (crypto_mech_name_t) *
990Sstevel@tonic-gate 		    (sup_count - 1);
1000Sstevel@tonic-gate 	}
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 	pload_soft_conf = malloc(sizeof (crypto_load_soft_config_t) +
1030Sstevel@tonic-gate 	    extra_mech_size);
1040Sstevel@tonic-gate 	if (pload_soft_conf == NULL) {
1050Sstevel@tonic-gate 		cryptodebug("out of memory.");
1060Sstevel@tonic-gate 		return (NULL);
1070Sstevel@tonic-gate 	}
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	(void) strlcpy(pload_soft_conf->sc_name, pent->name, MAXNAMELEN);
1100Sstevel@tonic-gate 	pload_soft_conf->sc_count = sup_count;
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	i = 0;
1130Sstevel@tonic-gate 	plist =  pent->suplist;
1140Sstevel@tonic-gate 	while (i < sup_count) {
1150Sstevel@tonic-gate 		(void) strlcpy(pload_soft_conf->sc_list[i++],
1160Sstevel@tonic-gate 		    plist->name, CRYPTO_MAX_MECH_NAME);
1170Sstevel@tonic-gate 		plist = plist->next;
1180Sstevel@tonic-gate 	}
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	return (pload_soft_conf);
1210Sstevel@tonic-gate }
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate /*
1250Sstevel@tonic-gate  * Prepare the argument for the LOAD_SOFT_DISABLED ioctl call for the
1260Sstevel@tonic-gate  * provider pointed by pent.  Return NULL if out of memory.
1270Sstevel@tonic-gate  */
1280Sstevel@tonic-gate crypto_load_soft_disabled_t *
setup_soft_dis(entry_t * pent)1290Sstevel@tonic-gate setup_soft_dis(entry_t *pent)
1300Sstevel@tonic-gate {
1317968Sopensolaris@drydog.com 	crypto_load_soft_disabled_t	*pload_soft_dis = NULL;
1327968Sopensolaris@drydog.com 	mechlist_t	*plist = NULL;
1337968Sopensolaris@drydog.com 	size_t		extra_mech_size = 0;
1347968Sopensolaris@drydog.com 	uint_t		dis_count;
1357968Sopensolaris@drydog.com 	int		i;
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 	if (pent == NULL) {
1380Sstevel@tonic-gate 		return (NULL);
1390Sstevel@tonic-gate 	}
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	dis_count = pent->dis_count;
1420Sstevel@tonic-gate 	if (dis_count > 1) {
1430Sstevel@tonic-gate 		extra_mech_size = sizeof (crypto_mech_name_t) *
1440Sstevel@tonic-gate 		    (dis_count - 1);
1450Sstevel@tonic-gate 	}
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	pload_soft_dis = malloc(sizeof (crypto_load_soft_disabled_t) +
1480Sstevel@tonic-gate 	    extra_mech_size);
1490Sstevel@tonic-gate 	if (pload_soft_dis == NULL) {
1500Sstevel@tonic-gate 		cryptodebug("out of memory.");
1510Sstevel@tonic-gate 		return (NULL);
1520Sstevel@tonic-gate 	}
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	(void) strlcpy(pload_soft_dis->sd_name, pent->name, MAXNAMELEN);
1550Sstevel@tonic-gate 	pload_soft_dis->sd_count = dis_count;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	i = 0;
1580Sstevel@tonic-gate 	plist =  pent->dislist;
1590Sstevel@tonic-gate 	while (i < dis_count) {
1600Sstevel@tonic-gate 		(void) strlcpy(pload_soft_dis->sd_list[i++],
1610Sstevel@tonic-gate 		    plist->name, CRYPTO_MAX_MECH_NAME);
1620Sstevel@tonic-gate 		plist = plist->next;
1630Sstevel@tonic-gate 	}
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	return (pload_soft_dis);
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate /*
1700Sstevel@tonic-gate  * Prepare the argument for the LOAD_DEV_DISABLED ioctl call for the
1710Sstevel@tonic-gate  * provider pointed by pent.  Return NULL if out of memory.
1720Sstevel@tonic-gate  */
1730Sstevel@tonic-gate crypto_load_dev_disabled_t *
setup_dev_dis(entry_t * pent)1740Sstevel@tonic-gate setup_dev_dis(entry_t *pent)
1750Sstevel@tonic-gate {
1767968Sopensolaris@drydog.com 	crypto_load_dev_disabled_t	*pload_dev_dis = NULL;
1777968Sopensolaris@drydog.com 	mechlist_t	*plist = NULL;
1787968Sopensolaris@drydog.com 	size_t		extra_mech_size = 0;
1797968Sopensolaris@drydog.com 	uint_t		dis_count;
1807968Sopensolaris@drydog.com 	int		i;
1817968Sopensolaris@drydog.com 	char		pname[MAXNAMELEN];
1827968Sopensolaris@drydog.com 	int		inst_num;
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	if (pent == NULL) {
1850Sstevel@tonic-gate 		return (NULL);
1860Sstevel@tonic-gate 	}
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	/* get the device name and the instance number */
1890Sstevel@tonic-gate 	if (split_hw_provname(pent->name, pname, &inst_num) == FAILURE) {
1900Sstevel@tonic-gate 		return (NULL);
1910Sstevel@tonic-gate 	}
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	/* allocate space for pload_dev_des */
1940Sstevel@tonic-gate 	dis_count = pent->dis_count;
1950Sstevel@tonic-gate 	if (dis_count > 1) {
1960Sstevel@tonic-gate 		extra_mech_size = sizeof (crypto_mech_name_t) *
1970Sstevel@tonic-gate 		    (dis_count - 1);
1980Sstevel@tonic-gate 	}
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	pload_dev_dis = malloc(sizeof (crypto_load_dev_disabled_t) +
2010Sstevel@tonic-gate 	    extra_mech_size);
2020Sstevel@tonic-gate 	if (pload_dev_dis == NULL) {
2030Sstevel@tonic-gate 		cryptodebug("out of memory.");
2040Sstevel@tonic-gate 		return (NULL);
2050Sstevel@tonic-gate 	}
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	/* set the values for pload_dev_dis */
2080Sstevel@tonic-gate 	(void) strlcpy(pload_dev_dis->dd_dev_name, pname, MAXNAMELEN);
2090Sstevel@tonic-gate 	pload_dev_dis->dd_dev_instance = inst_num;
2100Sstevel@tonic-gate 	pload_dev_dis->dd_count = dis_count;
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 	i = 0;
2130Sstevel@tonic-gate 	plist =  pent->dislist;
2140Sstevel@tonic-gate 	while (i < dis_count) {
2150Sstevel@tonic-gate 		(void) strlcpy(pload_dev_dis->dd_list[i++],
2160Sstevel@tonic-gate 		    plist->name, CRYPTO_MAX_MECH_NAME);
2170Sstevel@tonic-gate 		plist = plist->next;
2180Sstevel@tonic-gate 	}
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	return (pload_dev_dis);
2210Sstevel@tonic-gate }
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate /*
2250Sstevel@tonic-gate  * Prepare the calling argument of the UNLOAD_SOFT_MODULE ioctl call for the
2260Sstevel@tonic-gate  * provider pointed by pent.  Return NULL if out of memory.
2270Sstevel@tonic-gate  */
2280Sstevel@tonic-gate crypto_unload_soft_module_t *
setup_unload_soft(entry_t * pent)2290Sstevel@tonic-gate setup_unload_soft(entry_t *pent)
2300Sstevel@tonic-gate {
2310Sstevel@tonic-gate 	crypto_unload_soft_module_t *punload_soft;
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 	if (pent == NULL) {
2340Sstevel@tonic-gate 		return (NULL);
2350Sstevel@tonic-gate 	}
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	punload_soft = malloc(sizeof (crypto_unload_soft_module_t));
2380Sstevel@tonic-gate 	if (punload_soft == NULL) {
2390Sstevel@tonic-gate 		cryptodebug("out of memory.");
2400Sstevel@tonic-gate 		return (NULL);
2410Sstevel@tonic-gate 	}
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	(void) strlcpy(punload_soft->sm_name, pent->name, MAXNAMELEN);
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	return (punload_soft);
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate /*
2500Sstevel@tonic-gate  * Prepare the calling argument for the GET_SOFT_INFO call for the provider
2510Sstevel@tonic-gate  * with the number of mechanisms specified in the second argument.
2527968Sopensolaris@drydog.com  *
2537968Sopensolaris@drydog.com  * Called by get_soft_info().
2540Sstevel@tonic-gate  */
2550Sstevel@tonic-gate static crypto_get_soft_info_t *
setup_get_soft_info(char * provname,int count)2560Sstevel@tonic-gate setup_get_soft_info(char *provname, int count)
2570Sstevel@tonic-gate {
2587968Sopensolaris@drydog.com 	crypto_get_soft_info_t	*psoft_info;
2597968Sopensolaris@drydog.com 	size_t			extra_mech_size = 0;
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	if (provname == NULL) {
2620Sstevel@tonic-gate 		return (NULL);
2630Sstevel@tonic-gate 	}
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	if (count > 1) {
2660Sstevel@tonic-gate 		extra_mech_size = sizeof (crypto_mech_name_t) * (count - 1);
2670Sstevel@tonic-gate 	}
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	psoft_info = malloc(sizeof (crypto_get_soft_info_t) + extra_mech_size);
2700Sstevel@tonic-gate 	if (psoft_info == NULL) {
2710Sstevel@tonic-gate 		cryptodebug("out of memory.");
2720Sstevel@tonic-gate 		return (NULL);
2730Sstevel@tonic-gate 	}
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	(void) strlcpy(psoft_info->si_name, provname, MAXNAMELEN);
2760Sstevel@tonic-gate 	psoft_info->si_count = count;
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	return (psoft_info);
2790Sstevel@tonic-gate }
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate /*
2830Sstevel@tonic-gate  * Get the device list from kernel.
2840Sstevel@tonic-gate  */
2850Sstevel@tonic-gate int
get_dev_list(crypto_get_dev_list_t ** ppdevlist)2860Sstevel@tonic-gate get_dev_list(crypto_get_dev_list_t **ppdevlist)
2870Sstevel@tonic-gate {
2887968Sopensolaris@drydog.com 	crypto_get_dev_list_t	*pdevlist;
2897968Sopensolaris@drydog.com 	int			fd = -1;
2907968Sopensolaris@drydog.com 	int			count = DEFAULT_DEV_NUM;
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	pdevlist = malloc(sizeof (crypto_get_dev_list_t) +
2930Sstevel@tonic-gate 	    sizeof (crypto_dev_list_entry_t) * (count - 1));
2940Sstevel@tonic-gate 	if (pdevlist == NULL) {
2950Sstevel@tonic-gate 		cryptodebug("out of memory.");
2960Sstevel@tonic-gate 		return (FAILURE);
2970Sstevel@tonic-gate 	}
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
3000Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
3010Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
3020Sstevel@tonic-gate 		return (FAILURE);
3030Sstevel@tonic-gate 	}
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 	pdevlist->dl_dev_count = count;
3060Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_GET_DEV_LIST, pdevlist) == -1) {
3070Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s",
3080Sstevel@tonic-gate 		    strerror(errno));
3090Sstevel@tonic-gate 		free(pdevlist);
3100Sstevel@tonic-gate 		(void) close(fd);
3110Sstevel@tonic-gate 		return (FAILURE);
3120Sstevel@tonic-gate 	}
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	/* BUFFER is too small, get the number of devices and retry it. */
3150Sstevel@tonic-gate 	if (pdevlist->dl_return_value == CRYPTO_BUFFER_TOO_SMALL) {
3160Sstevel@tonic-gate 		count = pdevlist->dl_dev_count;
3170Sstevel@tonic-gate 		free(pdevlist);
3180Sstevel@tonic-gate 		pdevlist = malloc(sizeof (crypto_get_dev_list_t) +
3190Sstevel@tonic-gate 		    sizeof (crypto_dev_list_entry_t) * (count - 1));
3200Sstevel@tonic-gate 		if (pdevlist == NULL) {
3210Sstevel@tonic-gate 			cryptodebug("out of memory.");
3220Sstevel@tonic-gate 			(void) close(fd);
3230Sstevel@tonic-gate 			return (FAILURE);
3240Sstevel@tonic-gate 		}
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 		if (ioctl(fd, CRYPTO_GET_DEV_LIST, pdevlist) == -1) {
3270Sstevel@tonic-gate 			cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s",
3280Sstevel@tonic-gate 			    strerror(errno));
3290Sstevel@tonic-gate 			free(pdevlist);
3300Sstevel@tonic-gate 			(void) close(fd);
3310Sstevel@tonic-gate 			return (FAILURE);
3320Sstevel@tonic-gate 		}
3330Sstevel@tonic-gate 	}
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate 	if (pdevlist->dl_return_value != CRYPTO_SUCCESS) {
3360Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed, "
3370Sstevel@tonic-gate 		    "return_value = %d", pdevlist->dl_return_value);
3380Sstevel@tonic-gate 		free(pdevlist);
3390Sstevel@tonic-gate 		(void) close(fd);
3400Sstevel@tonic-gate 		return (FAILURE);
3410Sstevel@tonic-gate 	}
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 	*ppdevlist = pdevlist;
3440Sstevel@tonic-gate 	(void) close(fd);
3450Sstevel@tonic-gate 	return (SUCCESS);
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate /*
3500Sstevel@tonic-gate  * Get all the mechanisms supported by the hardware provider.
3510Sstevel@tonic-gate  * The result will be stored in the second argument.
3520Sstevel@tonic-gate  */
3530Sstevel@tonic-gate int
get_dev_info(char * devname,int inst_num,int count,mechlist_t ** ppmechlist)3540Sstevel@tonic-gate get_dev_info(char *devname, int inst_num, int count, mechlist_t **ppmechlist)
3550Sstevel@tonic-gate {
3567968Sopensolaris@drydog.com 	crypto_get_dev_info_t	*dev_info;
3577968Sopensolaris@drydog.com 	mechlist_t	*phead;
3587968Sopensolaris@drydog.com 	mechlist_t	*pcur;
3597968Sopensolaris@drydog.com 	mechlist_t	*pmech;
3607968Sopensolaris@drydog.com 	int		fd = -1;
3617968Sopensolaris@drydog.com 	int		i;
3627968Sopensolaris@drydog.com 	int		rc;
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 	if (devname == NULL || count < 1) {
3650Sstevel@tonic-gate 		cryptodebug("get_dev_info(): devname is NULL or bogus count");
3660Sstevel@tonic-gate 		return (FAILURE);
3670Sstevel@tonic-gate 	}
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	/* Set up the argument for the CRYPTO_GET_DEV_INFO ioctl call */
3700Sstevel@tonic-gate 	dev_info = malloc(sizeof (crypto_get_dev_info_t) +
3710Sstevel@tonic-gate 	    sizeof (crypto_mech_name_t) * (count - 1));
3720Sstevel@tonic-gate 	if (dev_info == NULL) {
3730Sstevel@tonic-gate 		cryptodebug("out of memory.");
3740Sstevel@tonic-gate 		return (FAILURE);
3750Sstevel@tonic-gate 	}
3760Sstevel@tonic-gate 	(void) strlcpy(dev_info->di_dev_name, devname, MAXNAMELEN);
3770Sstevel@tonic-gate 	dev_info->di_dev_instance = inst_num;
3780Sstevel@tonic-gate 	dev_info->di_count = count;
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	/* Open the ioctl device */
3810Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
3820Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
3830Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
3840Sstevel@tonic-gate 		free(dev_info);
3850Sstevel@tonic-gate 		return (FAILURE);
3860Sstevel@tonic-gate 	}
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_GET_DEV_INFO, dev_info) == -1) {
3890Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_DEV_INFO ioctl failed: %s",
3900Sstevel@tonic-gate 		    strerror(errno));
3910Sstevel@tonic-gate 		free(dev_info);
3920Sstevel@tonic-gate 		(void) close(fd);
3930Sstevel@tonic-gate 		return (FAILURE);
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 	if (dev_info->di_return_value != CRYPTO_SUCCESS) {
3970Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_DEV_INFO ioctl failed, "
3980Sstevel@tonic-gate 		    "return_value = %d", dev_info->di_return_value);
3990Sstevel@tonic-gate 		free(dev_info);
4000Sstevel@tonic-gate 		(void) close(fd);
4010Sstevel@tonic-gate 		return (FAILURE);
4020Sstevel@tonic-gate 	}
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	phead = pcur = NULL;
4050Sstevel@tonic-gate 	rc = SUCCESS;
4060Sstevel@tonic-gate 	for (i = 0; i < dev_info->di_count; i++) {
4070Sstevel@tonic-gate 		pmech = create_mech(&dev_info->di_list[i][0]);
4080Sstevel@tonic-gate 		if (pmech == NULL) {
4090Sstevel@tonic-gate 			rc = FAILURE;
4100Sstevel@tonic-gate 			break;
4110Sstevel@tonic-gate 		} else {
4120Sstevel@tonic-gate 			if (phead == NULL) {
4130Sstevel@tonic-gate 				phead = pcur = pmech;
4140Sstevel@tonic-gate 			} else {
4150Sstevel@tonic-gate 				pcur->next = pmech;
4160Sstevel@tonic-gate 				pcur = pmech;
4170Sstevel@tonic-gate 			}
4180Sstevel@tonic-gate 		}
4190Sstevel@tonic-gate 	}
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	if (rc == SUCCESS) {
4220Sstevel@tonic-gate 		*ppmechlist = phead;
4230Sstevel@tonic-gate 	} else {
4240Sstevel@tonic-gate 		free_mechlist(phead);
4250Sstevel@tonic-gate 	}
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate 	free(dev_info);
4280Sstevel@tonic-gate 	(void) close(fd);
4290Sstevel@tonic-gate 	return (rc);
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate /*
4340Sstevel@tonic-gate  * Get the supported mechanism list of the software provider from kernel.
4357968Sopensolaris@drydog.com  *
4367968Sopensolaris@drydog.com  * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
4377968Sopensolaris@drydog.com  * If NULL, this function calls get_kcfconf_info() internally.
4380Sstevel@tonic-gate  */
4390Sstevel@tonic-gate int
get_soft_info(char * provname,mechlist_t ** ppmechlist,entrylist_t * phardlist,entrylist_t * psoftlist)4407968Sopensolaris@drydog.com get_soft_info(char *provname, mechlist_t **ppmechlist,
44110979SHai-May.Chao@Sun.COM 	entrylist_t *phardlist, entrylist_t *psoftlist)
4420Sstevel@tonic-gate {
4437968Sopensolaris@drydog.com 	boolean_t		in_kernel = B_FALSE;
4440Sstevel@tonic-gate 	crypto_get_soft_info_t	*psoft_info;
4457968Sopensolaris@drydog.com 	mechlist_t		*phead;
4467968Sopensolaris@drydog.com 	mechlist_t		*pmech;
4477968Sopensolaris@drydog.com 	mechlist_t		*pcur;
4487968Sopensolaris@drydog.com 	entry_t			*pent = NULL;
4497968Sopensolaris@drydog.com 	int			count;
4507968Sopensolaris@drydog.com 	int			fd = -1;
4517968Sopensolaris@drydog.com 	int			rc;
4527968Sopensolaris@drydog.com 	int			i;
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 	if (provname == NULL) {
4550Sstevel@tonic-gate 		return (FAILURE);
4560Sstevel@tonic-gate 	}
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	if (getzoneid() == GLOBAL_ZONEID) {
4590Sstevel@tonic-gate 		/* use kcf.conf for kernel software providers in global zone */
46010979SHai-May.Chao@Sun.COM 		if ((pent = getent_kef(provname, phardlist, psoftlist)) ==
46110979SHai-May.Chao@Sun.COM 		    NULL) {
4627968Sopensolaris@drydog.com 
4637968Sopensolaris@drydog.com 			/* No kcf.conf entry for this provider */
4647968Sopensolaris@drydog.com 			if (check_kernel_for_soft(provname, NULL, &in_kernel)
4657968Sopensolaris@drydog.com 			    == FAILURE) {
4667968Sopensolaris@drydog.com 				return (FAILURE);
4677968Sopensolaris@drydog.com 			} else if (in_kernel == B_FALSE) {
4687968Sopensolaris@drydog.com 				cryptoerror(LOG_STDERR,
4697968Sopensolaris@drydog.com 				    gettext("%s does not exist."), provname);
4707968Sopensolaris@drydog.com 				return (FAILURE);
4717968Sopensolaris@drydog.com 			}
4727968Sopensolaris@drydog.com 
4737968Sopensolaris@drydog.com 			/*
4747968Sopensolaris@drydog.com 			 * Set mech count to 1.  It will be reset to the
4757968Sopensolaris@drydog.com 			 * correct value later if the setup buffer is too small.
4767968Sopensolaris@drydog.com 			 */
4777968Sopensolaris@drydog.com 			count = 1;
4787968Sopensolaris@drydog.com 		} else {
4797968Sopensolaris@drydog.com 			count = pent->sup_count;
4807968Sopensolaris@drydog.com 			free_entry(pent);
4810Sstevel@tonic-gate 		}
4820Sstevel@tonic-gate 	} else {
4830Sstevel@tonic-gate 		/*
4847968Sopensolaris@drydog.com 		 * kcf.conf not there in non-global zone: set mech count to 1.
4857968Sopensolaris@drydog.com 		 * It will be reset to the correct value later if the setup
4867968Sopensolaris@drydog.com 		 * buffer is too small.
4870Sstevel@tonic-gate 		 */
4880Sstevel@tonic-gate 		count = 1;
4890Sstevel@tonic-gate 	}
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	if ((psoft_info = setup_get_soft_info(provname, count)) == NULL) {
4920Sstevel@tonic-gate 		return (FAILURE);
4930Sstevel@tonic-gate 	}
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
4960Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
4970Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
4980Sstevel@tonic-gate 		free(psoft_info);
4990Sstevel@tonic-gate 		return (FAILURE);
5000Sstevel@tonic-gate 	}
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	/* make GET_SOFT_INFO ioctl call */
5030Sstevel@tonic-gate 	if ((rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info)) == -1) {
5040Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed: %s",
5050Sstevel@tonic-gate 		    strerror(errno));
5060Sstevel@tonic-gate 		(void) close(fd);
5070Sstevel@tonic-gate 		free(psoft_info);
5080Sstevel@tonic-gate 		return (FAILURE);
5090Sstevel@tonic-gate 	}
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate 	/* BUFFER is too small, get the number of mechanisms and retry it. */
5120Sstevel@tonic-gate 	if (psoft_info->si_return_value == CRYPTO_BUFFER_TOO_SMALL) {
5130Sstevel@tonic-gate 		count = psoft_info->si_count;
5140Sstevel@tonic-gate 		free(psoft_info);
5150Sstevel@tonic-gate 		if ((psoft_info = setup_get_soft_info(provname, count))
5160Sstevel@tonic-gate 		    == NULL) {
5170Sstevel@tonic-gate 			(void) close(fd);
5180Sstevel@tonic-gate 			return (FAILURE);
5190Sstevel@tonic-gate 		} else {
5200Sstevel@tonic-gate 			rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info);
5210Sstevel@tonic-gate 			if (rc == -1) {
5220Sstevel@tonic-gate 				cryptodebug("CRYPTO_GET_SOFT_INFO ioctl "
5230Sstevel@tonic-gate 				    "failed: %s", strerror(errno));
5240Sstevel@tonic-gate 				(void) close(fd);
5250Sstevel@tonic-gate 				free(psoft_info);
5260Sstevel@tonic-gate 				return (FAILURE);
5270Sstevel@tonic-gate 			}
5280Sstevel@tonic-gate 		}
5290Sstevel@tonic-gate 	}
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	(void) close(fd);
5320Sstevel@tonic-gate 	if (psoft_info->si_return_value != CRYPTO_SUCCESS) {
5330Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed, "
5340Sstevel@tonic-gate 		    "return_value = %d", psoft_info->si_return_value);
5350Sstevel@tonic-gate 		free(psoft_info);
5360Sstevel@tonic-gate 		return (FAILURE);
5370Sstevel@tonic-gate 	}
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 
5407968Sopensolaris@drydog.com 	/* Build the mechanism linked list and return it */
5410Sstevel@tonic-gate 	rc = SUCCESS;
5420Sstevel@tonic-gate 	phead = pcur = NULL;
5430Sstevel@tonic-gate 	for (i = 0; i < psoft_info->si_count; i++) {
5440Sstevel@tonic-gate 		pmech = create_mech(&psoft_info->si_list[i][0]);
5450Sstevel@tonic-gate 		if (pmech == NULL) {
5460Sstevel@tonic-gate 			rc = FAILURE;
5470Sstevel@tonic-gate 			break;
5480Sstevel@tonic-gate 		} else {
5490Sstevel@tonic-gate 			if (phead == NULL) {
5500Sstevel@tonic-gate 				phead = pcur = pmech;
5510Sstevel@tonic-gate 			} else {
5520Sstevel@tonic-gate 				pcur->next = pmech;
5530Sstevel@tonic-gate 				pcur = pmech;
5540Sstevel@tonic-gate 			}
5550Sstevel@tonic-gate 		}
5560Sstevel@tonic-gate 	}
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 	if (rc == FAILURE) {
5590Sstevel@tonic-gate 		free_mechlist(phead);
5600Sstevel@tonic-gate 	} else {
5610Sstevel@tonic-gate 		*ppmechlist = phead;
5620Sstevel@tonic-gate 	}
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate 	free(psoft_info);
5650Sstevel@tonic-gate 	return (rc);
5660Sstevel@tonic-gate }
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate /*
5700Sstevel@tonic-gate  * Get the kernel software provider list from kernel.
5710Sstevel@tonic-gate  */
5720Sstevel@tonic-gate int
get_soft_list(crypto_get_soft_list_t ** ppsoftlist)5730Sstevel@tonic-gate get_soft_list(crypto_get_soft_list_t **ppsoftlist)
5740Sstevel@tonic-gate {
5750Sstevel@tonic-gate 	crypto_get_soft_list_t *psoftlist = NULL;
5767968Sopensolaris@drydog.com 	int	count = DEFAULT_SOFT_NUM;
5777968Sopensolaris@drydog.com 	int	len;
5787968Sopensolaris@drydog.com 	int	fd = -1;
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
5810Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
5820Sstevel@tonic-gate 		    ADMIN_IOCTL_DEVICE, strerror(errno));
5830Sstevel@tonic-gate 		return (FAILURE);
5840Sstevel@tonic-gate 	}
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 	len = MAXNAMELEN * count;
5870Sstevel@tonic-gate 	psoftlist = malloc(sizeof (crypto_get_soft_list_t) + len);
5880Sstevel@tonic-gate 	if (psoftlist == NULL) {
5890Sstevel@tonic-gate 		cryptodebug("out of memory.");
5900Sstevel@tonic-gate 		(void) close(fd);
5910Sstevel@tonic-gate 		return (FAILURE);
5920Sstevel@tonic-gate 	}
5930Sstevel@tonic-gate 	psoftlist->sl_soft_names = (caddr_t)(psoftlist + 1);
5940Sstevel@tonic-gate 	psoftlist->sl_soft_count = count;
5950Sstevel@tonic-gate 	psoftlist->sl_soft_len = len;
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 	if (ioctl(fd, CRYPTO_GET_SOFT_LIST, psoftlist) == -1) {
5980Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed: %s",
5990Sstevel@tonic-gate 		    strerror(errno));
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 	/*
6060Sstevel@tonic-gate 	 * if BUFFER is too small, get the number of software providers and
6070Sstevel@tonic-gate 	 * the minimum length needed for names and length and retry it.
6080Sstevel@tonic-gate 	 */
6090Sstevel@tonic-gate 	if (psoftlist->sl_return_value == CRYPTO_BUFFER_TOO_SMALL) {
6100Sstevel@tonic-gate 		count = psoftlist->sl_soft_count;
6110Sstevel@tonic-gate 		len = psoftlist->sl_soft_len;
6120Sstevel@tonic-gate 		free(psoftlist);
6130Sstevel@tonic-gate 		psoftlist = malloc(sizeof (crypto_get_soft_list_t) + len);
6140Sstevel@tonic-gate 		if (psoftlist == NULL) {
6150Sstevel@tonic-gate 			cryptodebug("out of memory.");
6160Sstevel@tonic-gate 			(void) close(fd);
6170Sstevel@tonic-gate 			return (FAILURE);
6180Sstevel@tonic-gate 		}
6190Sstevel@tonic-gate 		psoftlist->sl_soft_names = (caddr_t)(psoftlist + 1);
6200Sstevel@tonic-gate 		psoftlist->sl_soft_count = count;
6210Sstevel@tonic-gate 		psoftlist->sl_soft_len = len;
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 		if (ioctl(fd, CRYPTO_GET_SOFT_LIST, psoftlist) == -1) {
6240Sstevel@tonic-gate 			cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed:"
6250Sstevel@tonic-gate 			    "%s", strerror(errno));
6260Sstevel@tonic-gate 			free(psoftlist);
6270Sstevel@tonic-gate 			(void) close(fd);
6280Sstevel@tonic-gate 			return (FAILURE);
6290Sstevel@tonic-gate 		}
6300Sstevel@tonic-gate 	}
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate 	if (psoftlist->sl_return_value != CRYPTO_SUCCESS) {
6330Sstevel@tonic-gate 		cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed, "
6340Sstevel@tonic-gate 		    "return_value = %d", psoftlist->sl_return_value);
6350Sstevel@tonic-gate 		free(psoftlist);
6360Sstevel@tonic-gate 		(void) close(fd);
6370Sstevel@tonic-gate 		return (FAILURE);
6380Sstevel@tonic-gate 	}
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 	*ppsoftlist = psoftlist;
6410Sstevel@tonic-gate 	(void) close(fd);
6420Sstevel@tonic-gate 	return (SUCCESS);
6430Sstevel@tonic-gate }
64410500SHai-May.Chao@Sun.COM 
64510500SHai-May.Chao@Sun.COM /*
64610500SHai-May.Chao@Sun.COM  * Perform the FIPS related actions
64710500SHai-May.Chao@Sun.COM  */
64810500SHai-May.Chao@Sun.COM int
do_fips_actions(int action,int caller)64910500SHai-May.Chao@Sun.COM do_fips_actions(int action, int caller)
65010500SHai-May.Chao@Sun.COM {
65110500SHai-May.Chao@Sun.COM 
65210500SHai-May.Chao@Sun.COM 	crypto_fips140_t	fips_info;
65310500SHai-May.Chao@Sun.COM 	int	fd;
65410500SHai-May.Chao@Sun.COM 	int	rc = SUCCESS;
65510979SHai-May.Chao@Sun.COM 	int	pkcs11_fips_mode = 0;
65610500SHai-May.Chao@Sun.COM 
65710979SHai-May.Chao@Sun.COM 	/* Get FIPS-140 status from pkcs11.conf */
65810979SHai-May.Chao@Sun.COM 	fips_status_pkcs11conf(&pkcs11_fips_mode);
65910500SHai-May.Chao@Sun.COM 
66010500SHai-May.Chao@Sun.COM 	if (action == FIPS140_STATUS) {
66110979SHai-May.Chao@Sun.COM 		if (pkcs11_fips_mode == CRYPTO_FIPS_MODE_ENABLED)
662*12929SMisaki.Miyashita@Oracle.COM 			fips_sw_printf(gettext("FIPS-140 mode is enabled."));
66310500SHai-May.Chao@Sun.COM 		else
664*12929SMisaki.Miyashita@Oracle.COM 			fips_sw_printf(gettext("FIPS-140 mode is disabled."));
66510500SHai-May.Chao@Sun.COM 		return (SUCCESS);
66610500SHai-May.Chao@Sun.COM 	}
66710500SHai-May.Chao@Sun.COM 
66810500SHai-May.Chao@Sun.COM 	if (caller == NOT_REFRESH) {
66910500SHai-May.Chao@Sun.COM 		/* Is it a duplicate operation? */
67010500SHai-May.Chao@Sun.COM 		if ((action == FIPS140_ENABLE) &&
67110979SHai-May.Chao@Sun.COM 		    (pkcs11_fips_mode == CRYPTO_FIPS_MODE_ENABLED)) {
672*12929SMisaki.Miyashita@Oracle.COM 			fips_sw_printf(gettext("FIPS-140 mode has already "
673*12929SMisaki.Miyashita@Oracle.COM 			    "been enabled."));
67410500SHai-May.Chao@Sun.COM 			return (FAILURE);
67510500SHai-May.Chao@Sun.COM 		}
67610500SHai-May.Chao@Sun.COM 
67710500SHai-May.Chao@Sun.COM 		if ((action == FIPS140_DISABLE) &&
67810979SHai-May.Chao@Sun.COM 		    (pkcs11_fips_mode == CRYPTO_FIPS_MODE_DISABLED)) {
679*12929SMisaki.Miyashita@Oracle.COM 			fips_sw_printf(gettext("FIPS-140 mode has already "
680*12929SMisaki.Miyashita@Oracle.COM 			    "been disabled."));
68110500SHai-May.Chao@Sun.COM 			return (FAILURE);
68210500SHai-May.Chao@Sun.COM 		}
68310500SHai-May.Chao@Sun.COM 
68410500SHai-May.Chao@Sun.COM 		if ((action == FIPS140_ENABLE) || (action == FIPS140_DISABLE)) {
68510979SHai-May.Chao@Sun.COM 			/* Update pkcs11.conf */
68610979SHai-May.Chao@Sun.COM 			if ((rc = fips_update_pkcs11conf(action)) != SUCCESS)
68710500SHai-May.Chao@Sun.COM 				return (rc);
68810500SHai-May.Chao@Sun.COM 		}
68910500SHai-May.Chao@Sun.COM 
69010500SHai-May.Chao@Sun.COM 		/* No need to inform kernel */
69110500SHai-May.Chao@Sun.COM 		if (action == FIPS140_ENABLE) {
692*12929SMisaki.Miyashita@Oracle.COM 			fips_sw_printf(gettext("FIPS-140 mode was enabled "
693*12929SMisaki.Miyashita@Oracle.COM 			    "successfully."));
69410500SHai-May.Chao@Sun.COM 		} else {
695*12929SMisaki.Miyashita@Oracle.COM 			fips_sw_printf(gettext("FIPS-140 mode was disabled "
696*12929SMisaki.Miyashita@Oracle.COM 			    "successfully."));
69710500SHai-May.Chao@Sun.COM 		}
69810500SHai-May.Chao@Sun.COM 
69910500SHai-May.Chao@Sun.COM 		return (SUCCESS);
70010500SHai-May.Chao@Sun.COM 
70110500SHai-May.Chao@Sun.COM 	}
70210500SHai-May.Chao@Sun.COM 
70310500SHai-May.Chao@Sun.COM 	/* This is refresh, need to inform kernel */
70410500SHai-May.Chao@Sun.COM 	(void) memset(&fips_info, 0, sizeof (crypto_fips140_t));
70510500SHai-May.Chao@Sun.COM 
70610500SHai-May.Chao@Sun.COM 	if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
70710500SHai-May.Chao@Sun.COM 		cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
70810500SHai-May.Chao@Sun.COM 		    ADMIN_IOCTL_DEVICE, strerror(errno));
70910500SHai-May.Chao@Sun.COM 		return (FAILURE);
71010500SHai-May.Chao@Sun.COM 	}
71110500SHai-May.Chao@Sun.COM 
71210500SHai-May.Chao@Sun.COM 	switch (action) {
71310500SHai-May.Chao@Sun.COM 	case FIPS140_ENABLE:
71410500SHai-May.Chao@Sun.COM 		/* make CRYPTO_FIPS_SET ioctl call */
71510500SHai-May.Chao@Sun.COM 		fips_info.fips140_op = FIPS140_ENABLE;
71610500SHai-May.Chao@Sun.COM 		if ((rc = ioctl(fd, CRYPTO_FIPS140_SET, &fips_info)) == -1) {
71710500SHai-May.Chao@Sun.COM 			cryptodebug("CRYPTO_FIPS140_ENABLE ioctl failed: %s",
71810500SHai-May.Chao@Sun.COM 			    strerror(errno));
71910500SHai-May.Chao@Sun.COM 			rc = FAILURE;
72010500SHai-May.Chao@Sun.COM 			goto out;
72110500SHai-May.Chao@Sun.COM 		}
72210500SHai-May.Chao@Sun.COM 
72310500SHai-May.Chao@Sun.COM 		if (fips_info.fips140_return_value != CRYPTO_SUCCESS) {
72410500SHai-May.Chao@Sun.COM 			cryptodebug("CRYPTO_FIPS140_ENABLE ioctl failed, "
72510500SHai-May.Chao@Sun.COM 			    "return_value = %d",
72610500SHai-May.Chao@Sun.COM 			    fips_info.fips140_return_value);
72710500SHai-May.Chao@Sun.COM 			rc = FAILURE;
72810500SHai-May.Chao@Sun.COM 		}
72910500SHai-May.Chao@Sun.COM 
73010500SHai-May.Chao@Sun.COM 		break;
73110500SHai-May.Chao@Sun.COM 
73210500SHai-May.Chao@Sun.COM 	case FIPS140_DISABLE:
73310500SHai-May.Chao@Sun.COM 		/* make CRYPTO_FIPS140_SET ioctl call */
73410500SHai-May.Chao@Sun.COM 		fips_info.fips140_op = FIPS140_DISABLE;
73510500SHai-May.Chao@Sun.COM 		if ((rc = ioctl(fd, CRYPTO_FIPS140_SET, &fips_info)) == -1) {
73610500SHai-May.Chao@Sun.COM 			cryptodebug("CRYPTO_FIPS140_DISABLE ioctl failed: %s",
73710500SHai-May.Chao@Sun.COM 			    strerror(errno));
73810500SHai-May.Chao@Sun.COM 			rc = FAILURE;
73910500SHai-May.Chao@Sun.COM 			goto out;
74010500SHai-May.Chao@Sun.COM 		}
74110500SHai-May.Chao@Sun.COM 
74210500SHai-May.Chao@Sun.COM 		if (fips_info.fips140_return_value != CRYPTO_SUCCESS) {
74310500SHai-May.Chao@Sun.COM 			cryptodebug("CRYPTO_FIPS140_DISABLE ioctl failed, "
74410500SHai-May.Chao@Sun.COM 			    "return_value = %d",
74510500SHai-May.Chao@Sun.COM 			    fips_info.fips140_return_value);
74610500SHai-May.Chao@Sun.COM 			rc = FAILURE;
74710500SHai-May.Chao@Sun.COM 		}
74810500SHai-May.Chao@Sun.COM 
74910500SHai-May.Chao@Sun.COM 		break;
75010500SHai-May.Chao@Sun.COM 
75110500SHai-May.Chao@Sun.COM 	default:
75210500SHai-May.Chao@Sun.COM 		rc = FAILURE;
75310500SHai-May.Chao@Sun.COM 		break;
75410500SHai-May.Chao@Sun.COM 	};
75510500SHai-May.Chao@Sun.COM 
75610500SHai-May.Chao@Sun.COM out:
75710500SHai-May.Chao@Sun.COM 	(void) close(fd);
75810500SHai-May.Chao@Sun.COM 	return (rc);
75910500SHai-May.Chao@Sun.COM }
760