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