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 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 * 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 * 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 * 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 * 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 * 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 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 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 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 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 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