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 51971Skrishna * Common Development and Distribution License (the "License"). 61971Skrishna * 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 <sys/stat.h> 350Sstevel@tonic-gate #include <sys/crypto/ioctladmin.h> 360Sstevel@tonic-gate #include <signal.h> 370Sstevel@tonic-gate #include <sys/crypto/elfsign.h> 380Sstevel@tonic-gate #include "cryptoadm.h" 390Sstevel@tonic-gate 400Sstevel@tonic-gate static int check_hardware_provider(char *, char *, int *, int *); 410Sstevel@tonic-gate 420Sstevel@tonic-gate /* 430Sstevel@tonic-gate * Display the mechanism list for a kernel software provider. 447968Sopensolaris@drydog.com * This implements part of the "cryptoadm list -m" command. 457968Sopensolaris@drydog.com * 46*10500SHai-May.Chao@Sun.COM * Parameters phardlist, psoftlist and pfipslist are supplied by 47*10500SHai-May.Chao@Sun.COM * get_soft_info(). 48*10500SHai-May.Chao@Sun.COM * If NULL, this function obtains it by calling getent_kef() and 49*10500SHai-May.Chao@Sun.COM * then get_kcfconf_info() via get_soft_info() internally. 500Sstevel@tonic-gate */ 510Sstevel@tonic-gate int 527968Sopensolaris@drydog.com list_mechlist_for_soft(char *provname, 53*10500SHai-May.Chao@Sun.COM entrylist_t *phardlist, entrylist_t *psoftlist, 54*10500SHai-May.Chao@Sun.COM entrylist_t *pfipslist) 550Sstevel@tonic-gate { 567968Sopensolaris@drydog.com mechlist_t *pmechlist = NULL; 577968Sopensolaris@drydog.com int rc; 580Sstevel@tonic-gate 590Sstevel@tonic-gate if (provname == NULL) { 600Sstevel@tonic-gate return (FAILURE); 610Sstevel@tonic-gate } 620Sstevel@tonic-gate 63*10500SHai-May.Chao@Sun.COM rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist, 64*10500SHai-May.Chao@Sun.COM pfipslist); 650Sstevel@tonic-gate if (rc == SUCCESS) { 660Sstevel@tonic-gate (void) filter_mechlist(&pmechlist, RANDOM); 670Sstevel@tonic-gate print_mechlist(provname, pmechlist); 680Sstevel@tonic-gate free_mechlist(pmechlist); 690Sstevel@tonic-gate } else { 700Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 710Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 720Sstevel@tonic-gate provname); 730Sstevel@tonic-gate } 740Sstevel@tonic-gate 750Sstevel@tonic-gate return (rc); 760Sstevel@tonic-gate } 770Sstevel@tonic-gate 780Sstevel@tonic-gate /* 790Sstevel@tonic-gate * Display the mechanism list for a kernel hardware provider. 807968Sopensolaris@drydog.com * This implements part of the "cryptoadm list -m" command. 810Sstevel@tonic-gate */ 820Sstevel@tonic-gate int 830Sstevel@tonic-gate list_mechlist_for_hard(char *provname) 840Sstevel@tonic-gate { 857968Sopensolaris@drydog.com mechlist_t *pmechlist = NULL; 867968Sopensolaris@drydog.com char devname[MAXNAMELEN]; 877968Sopensolaris@drydog.com int inst_num; 887968Sopensolaris@drydog.com int count; 897968Sopensolaris@drydog.com int rc = SUCCESS; 900Sstevel@tonic-gate 910Sstevel@tonic-gate if (provname == NULL) { 920Sstevel@tonic-gate return (FAILURE); 930Sstevel@tonic-gate } 940Sstevel@tonic-gate 950Sstevel@tonic-gate /* 960Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 970Sstevel@tonic-gate * mechanisms also. 980Sstevel@tonic-gate */ 990Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) == 1000Sstevel@tonic-gate FAILURE) { 1010Sstevel@tonic-gate return (FAILURE); 1020Sstevel@tonic-gate } 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 1050Sstevel@tonic-gate if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) == 1060Sstevel@tonic-gate SUCCESS) { 1070Sstevel@tonic-gate (void) filter_mechlist(&pmechlist, RANDOM); 1080Sstevel@tonic-gate print_mechlist(provname, pmechlist); 1090Sstevel@tonic-gate free_mechlist(pmechlist); 1100Sstevel@tonic-gate } 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate return (rc); 1130Sstevel@tonic-gate } 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate /* 1170Sstevel@tonic-gate * Display the policy information for a kernel software provider. 1187968Sopensolaris@drydog.com * This implements part of the "cryptoadm list -p" command. 1197968Sopensolaris@drydog.com * 120*10500SHai-May.Chao@Sun.COM * Parameters phardlist, psoftlist and pfipslist are supplied by 121*10500SHai-May.Chao@Sun.COM * getent_kef(). 122*10500SHai-May.Chao@Sun.COM * If NULL, this function obtains it by calling get_kcfconf_info() 123*10500SHai-May.Chao@Sun.COM * via getent_kef() internally. 1240Sstevel@tonic-gate */ 1250Sstevel@tonic-gate int 1267968Sopensolaris@drydog.com list_policy_for_soft(char *provname, 127*10500SHai-May.Chao@Sun.COM entrylist_t *phardlist, entrylist_t *psoftlist, 128*10500SHai-May.Chao@Sun.COM entrylist_t *pfipslist) 1290Sstevel@tonic-gate { 1307968Sopensolaris@drydog.com int rc; 1317968Sopensolaris@drydog.com entry_t *pent = NULL; 1327968Sopensolaris@drydog.com mechlist_t *pmechlist = NULL; 1337968Sopensolaris@drydog.com boolean_t has_random = B_FALSE; 1347968Sopensolaris@drydog.com boolean_t has_mechs = B_FALSE; 1357968Sopensolaris@drydog.com boolean_t in_kernel = B_FALSE; 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate if (provname == NULL) { 1380Sstevel@tonic-gate return (FAILURE); 1390Sstevel@tonic-gate } 1400Sstevel@tonic-gate 1417968Sopensolaris@drydog.com if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) { 1427968Sopensolaris@drydog.com return (FAILURE); 1437968Sopensolaris@drydog.com } else if (in_kernel == B_FALSE) { 1440Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s does not exist."), 1450Sstevel@tonic-gate provname); 1460Sstevel@tonic-gate return (FAILURE); 1470Sstevel@tonic-gate } 148*10500SHai-May.Chao@Sun.COM pent = getent_kef(provname, phardlist, psoftlist, 149*10500SHai-May.Chao@Sun.COM pfipslist); 1500Sstevel@tonic-gate 151*10500SHai-May.Chao@Sun.COM rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist, 152*10500SHai-May.Chao@Sun.COM pfipslist); 1530Sstevel@tonic-gate if (rc == SUCCESS) { 1540Sstevel@tonic-gate has_random = filter_mechlist(&pmechlist, RANDOM); 1550Sstevel@tonic-gate if (pmechlist != NULL) { 1560Sstevel@tonic-gate has_mechs = B_TRUE; 1570Sstevel@tonic-gate free_mechlist(pmechlist); 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate } else { 1600Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 1610Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 1620Sstevel@tonic-gate provname); 1630Sstevel@tonic-gate return (rc); 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 1667968Sopensolaris@drydog.com print_kef_policy(provname, pent, has_random, has_mechs); 1670Sstevel@tonic-gate free_entry(pent); 1680Sstevel@tonic-gate return (SUCCESS); 1690Sstevel@tonic-gate } 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate /* 1740Sstevel@tonic-gate * Display the policy information for a kernel hardware provider. 1757968Sopensolaris@drydog.com * This implements part of the "cryptoadm list -p" command. 1767968Sopensolaris@drydog.com * 177*10500SHai-May.Chao@Sun.COM * Parameters phardlist, psoftlist and pfipslist are supplied by getent_kef(). 178*10500SHai-May.Chao@Sun.COM * If NULL, this function obtains it by calling get_kcfconf_info() via 179*10500SHai-May.Chao@Sun.COM * getent_kef() internally. 180*10500SHai-May.Chao@Sun.COM * Parameter pdevlist is supplied by check_kernel_for_hard(). 181*10500SHai-May.Chao@Sun.COM * If NULL, this function obtains it by calling get_dev_list() via 182*10500SHai-May.Chao@Sun.COM * check_kernel_for_hard() internally. 1830Sstevel@tonic-gate */ 1840Sstevel@tonic-gate int 1857968Sopensolaris@drydog.com list_policy_for_hard(char *provname, 1867968Sopensolaris@drydog.com entrylist_t *phardlist, entrylist_t *psoftlist, 187*10500SHai-May.Chao@Sun.COM entrylist_t *pfipslist, crypto_get_dev_list_t *pdevlist) 1880Sstevel@tonic-gate { 1897968Sopensolaris@drydog.com entry_t *pent = NULL; 1907968Sopensolaris@drydog.com boolean_t in_kernel; 1917968Sopensolaris@drydog.com mechlist_t *pmechlist = NULL; 1927968Sopensolaris@drydog.com char devname[MAXNAMELEN]; 1937968Sopensolaris@drydog.com int inst_num; 1947968Sopensolaris@drydog.com int count; 1957968Sopensolaris@drydog.com int rc = SUCCESS; 1967968Sopensolaris@drydog.com boolean_t has_random = B_FALSE; 1977968Sopensolaris@drydog.com boolean_t has_mechs = B_FALSE; 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate if (provname == NULL) { 2000Sstevel@tonic-gate return (FAILURE); 2010Sstevel@tonic-gate } 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate /* 2040Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 2050Sstevel@tonic-gate * mechanisms also. 2060Sstevel@tonic-gate */ 2070Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) == 2080Sstevel@tonic-gate FAILURE) { 2090Sstevel@tonic-gate return (FAILURE); 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 2130Sstevel@tonic-gate if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) == 2140Sstevel@tonic-gate SUCCESS) { 2150Sstevel@tonic-gate has_random = filter_mechlist(&pmechlist, RANDOM); 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate if (pmechlist != NULL) { 2180Sstevel@tonic-gate has_mechs = B_TRUE; 2190Sstevel@tonic-gate free_mechlist(pmechlist); 2200Sstevel@tonic-gate } 2210Sstevel@tonic-gate } else { 2220Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 2230Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 2240Sstevel@tonic-gate devname); 2250Sstevel@tonic-gate return (rc); 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate /* 2290Sstevel@tonic-gate * If the hardware provider has an entry in the kcf.conf file, 2300Sstevel@tonic-gate * some of its mechanisms must have been disabled. Print out 2310Sstevel@tonic-gate * the disabled list from the config file entry. Otherwise, 2320Sstevel@tonic-gate * if it is active, then all the mechanisms for it are enabled. 2330Sstevel@tonic-gate */ 234*10500SHai-May.Chao@Sun.COM if ((pent = getent_kef(provname, phardlist, psoftlist, 235*10500SHai-May.Chao@Sun.COM pfipslist)) != NULL) { 2367968Sopensolaris@drydog.com print_kef_policy(provname, pent, has_random, has_mechs); 2370Sstevel@tonic-gate free_entry(pent); 2380Sstevel@tonic-gate return (SUCCESS); 2390Sstevel@tonic-gate } else { 2407968Sopensolaris@drydog.com if (check_kernel_for_hard(provname, pdevlist, 2417968Sopensolaris@drydog.com &in_kernel) == FAILURE) { 2420Sstevel@tonic-gate return (FAILURE); 2437968Sopensolaris@drydog.com } else if (in_kernel == B_TRUE) { 2440Sstevel@tonic-gate (void) printf(gettext( 2450Sstevel@tonic-gate "%s: all mechanisms are enabled."), provname); 2460Sstevel@tonic-gate if (has_random) 2470Sstevel@tonic-gate /* 2487334SDaniel.Anderson@Sun.COM * TRANSLATION_NOTE 2490Sstevel@tonic-gate * "random" is a keyword and not to be 2500Sstevel@tonic-gate * translated. 2510Sstevel@tonic-gate */ 2520Sstevel@tonic-gate (void) printf(gettext(" %s is enabled.\n"), 2530Sstevel@tonic-gate "random"); 2540Sstevel@tonic-gate else 2550Sstevel@tonic-gate (void) printf("\n"); 2560Sstevel@tonic-gate return (SUCCESS); 2570Sstevel@tonic-gate } else { 2580Sstevel@tonic-gate cryptoerror(LOG_STDERR, 2590Sstevel@tonic-gate gettext("%s does not exist."), provname); 2600Sstevel@tonic-gate return (FAILURE); 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate } 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate 2667968Sopensolaris@drydog.com /* 2677968Sopensolaris@drydog.com * Disable a kernel hardware provider. 2687968Sopensolaris@drydog.com * This implements the "cryptoadm disable" command for 2697968Sopensolaris@drydog.com * kernel hardware providers. 2707968Sopensolaris@drydog.com */ 2710Sstevel@tonic-gate int 2720Sstevel@tonic-gate disable_kef_hardware(char *provname, boolean_t rndflag, boolean_t allflag, 2730Sstevel@tonic-gate mechlist_t *dislist) 2740Sstevel@tonic-gate { 2757968Sopensolaris@drydog.com crypto_load_dev_disabled_t *pload_dev_dis = NULL; 2767968Sopensolaris@drydog.com mechlist_t *infolist = NULL; 2777968Sopensolaris@drydog.com entry_t *pent = NULL; 2787968Sopensolaris@drydog.com boolean_t new_dev_entry = B_FALSE; 2797968Sopensolaris@drydog.com char devname[MAXNAMELEN]; 2807968Sopensolaris@drydog.com int inst_num; 2817968Sopensolaris@drydog.com int count; 2827968Sopensolaris@drydog.com int fd = -1; 2837968Sopensolaris@drydog.com int rc = SUCCESS; 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate if (provname == NULL) { 2860Sstevel@tonic-gate return (FAILURE); 2870Sstevel@tonic-gate } 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate /* 2900Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 2910Sstevel@tonic-gate * mechanisms also. 2920Sstevel@tonic-gate */ 2930Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) 2940Sstevel@tonic-gate == FAILURE) { 2950Sstevel@tonic-gate return (FAILURE); 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 2990Sstevel@tonic-gate if (get_dev_info(devname, inst_num, count, &infolist) == FAILURE) { 3000Sstevel@tonic-gate return (FAILURE); 3010Sstevel@tonic-gate } 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate /* 3040Sstevel@tonic-gate * Get the entry of this hardware provider from the config file. 3050Sstevel@tonic-gate * If there is no entry yet, create one for it. 3060Sstevel@tonic-gate */ 307*10500SHai-May.Chao@Sun.COM if ((pent = getent_kef(provname, NULL, NULL, NULL)) == NULL) { 3087968Sopensolaris@drydog.com if ((pent = create_entry(provname)) == NULL) { 3090Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("out of memory.")); 3100Sstevel@tonic-gate free_mechlist(infolist); 3110Sstevel@tonic-gate return (FAILURE); 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate new_dev_entry = B_TRUE; 3140Sstevel@tonic-gate } 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate /* 3170Sstevel@tonic-gate * kCF treats random as an internal mechanism. So, we need to 3180Sstevel@tonic-gate * filter it from the mechanism list here, if we are NOT disabling 3190Sstevel@tonic-gate * or enabling the random feature. Note that we map random feature at 3200Sstevel@tonic-gate * cryptoadm(1M) level to the "random" mechanism in kCF. 3210Sstevel@tonic-gate */ 3220Sstevel@tonic-gate if (!rndflag) { 3232860Smcpowers (void) filter_mechlist(&dislist, RANDOM); 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate /* Calculate the new disabled list */ 3270Sstevel@tonic-gate if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) { 3282860Smcpowers free_mechlist(infolist); 3290Sstevel@tonic-gate free_entry(pent); 3300Sstevel@tonic-gate return (FAILURE); 3310Sstevel@tonic-gate } 3322860Smcpowers free_mechlist(infolist); 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate /* If no mechanisms are to be disabled, return */ 3350Sstevel@tonic-gate if (pent->dis_count == 0) { 3360Sstevel@tonic-gate free_entry(pent); 3370Sstevel@tonic-gate return (SUCCESS); 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate /* Update the config file with the new entry or the updated entry */ 3410Sstevel@tonic-gate if (new_dev_entry) { 3420Sstevel@tonic-gate rc = update_kcfconf(pent, ADD_MODE); 3430Sstevel@tonic-gate } else { 3440Sstevel@tonic-gate rc = update_kcfconf(pent, MODIFY_MODE); 3450Sstevel@tonic-gate } 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate if (rc == FAILURE) { 3480Sstevel@tonic-gate free_entry(pent); 3490Sstevel@tonic-gate return (FAILURE); 3500Sstevel@tonic-gate } 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate /* Inform kernel about the new disabled mechanism list */ 3530Sstevel@tonic-gate if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) { 3540Sstevel@tonic-gate free_entry(pent); 3550Sstevel@tonic-gate return (FAILURE); 3560Sstevel@tonic-gate } 3570Sstevel@tonic-gate free_entry(pent); 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 3600Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 3610Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 3620Sstevel@tonic-gate free(pload_dev_dis); 3630Sstevel@tonic-gate return (FAILURE); 3640Sstevel@tonic-gate } 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) { 3670Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: %s", 3680Sstevel@tonic-gate strerror(errno)); 3690Sstevel@tonic-gate free(pload_dev_dis); 3700Sstevel@tonic-gate (void) close(fd); 3710Sstevel@tonic-gate return (FAILURE); 3720Sstevel@tonic-gate } 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 3750Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl return_value = " 3760Sstevel@tonic-gate "%d", pload_dev_dis->dd_return_value); 3770Sstevel@tonic-gate free(pload_dev_dis); 3780Sstevel@tonic-gate (void) close(fd); 3790Sstevel@tonic-gate return (FAILURE); 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate free(pload_dev_dis); 3830Sstevel@tonic-gate (void) close(fd); 3840Sstevel@tonic-gate return (SUCCESS); 3850Sstevel@tonic-gate } 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate 3887968Sopensolaris@drydog.com /* 3897968Sopensolaris@drydog.com * Disable a kernel software provider. 3907968Sopensolaris@drydog.com * This implements the "cryptoadm disable" command for 3917968Sopensolaris@drydog.com * kernel software providers. 3927968Sopensolaris@drydog.com */ 3930Sstevel@tonic-gate int 3940Sstevel@tonic-gate disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag, 3950Sstevel@tonic-gate mechlist_t *dislist) 3960Sstevel@tonic-gate { 3970Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 3987968Sopensolaris@drydog.com mechlist_t *infolist = NULL; 3997968Sopensolaris@drydog.com entry_t *pent = NULL; 4007968Sopensolaris@drydog.com entrylist_t *phardlist = NULL; 4017968Sopensolaris@drydog.com entrylist_t *psoftlist = NULL; 402*10500SHai-May.Chao@Sun.COM entrylist_t *pfipslist = NULL; 4037968Sopensolaris@drydog.com boolean_t in_kernel = B_FALSE; 4047968Sopensolaris@drydog.com int fd = -1; 4057968Sopensolaris@drydog.com int rc = SUCCESS; 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate if (provname == NULL) { 4080Sstevel@tonic-gate return (FAILURE); 4090Sstevel@tonic-gate } 4100Sstevel@tonic-gate 4110Sstevel@tonic-gate /* 4120Sstevel@tonic-gate * Check if the kernel software provider is currently unloaded. 4130Sstevel@tonic-gate * If it is unloaded, return FAILURE, because the disable subcommand 4140Sstevel@tonic-gate * can not perform on inactive (unloaded) providers. 4150Sstevel@tonic-gate */ 416*10500SHai-May.Chao@Sun.COM if (check_kernel_for_soft(provname, NULL, &in_kernel) == 417*10500SHai-May.Chao@Sun.COM FAILURE) { 4187968Sopensolaris@drydog.com return (FAILURE); 4197968Sopensolaris@drydog.com } else if (in_kernel == B_FALSE) { 4207968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, 4217968Sopensolaris@drydog.com gettext("%s is not loaded or does not exist."), 4227968Sopensolaris@drydog.com provname); 4230Sstevel@tonic-gate return (FAILURE); 4247968Sopensolaris@drydog.com } 4257968Sopensolaris@drydog.com 426*10500SHai-May.Chao@Sun.COM if (get_kcfconf_info(&phardlist, &psoftlist, &pfipslist) == 427*10500SHai-May.Chao@Sun.COM FAILURE) { 4287968Sopensolaris@drydog.com cryptoerror(LOG_ERR, 4297968Sopensolaris@drydog.com "failed to retrieve the providers' " 4307968Sopensolaris@drydog.com "information from the configuration file - %s.", 4317968Sopensolaris@drydog.com _PATH_KCF_CONF); 4320Sstevel@tonic-gate return (FAILURE); 4330Sstevel@tonic-gate } 4340Sstevel@tonic-gate 4357968Sopensolaris@drydog.com /* 4367968Sopensolaris@drydog.com * Get the entry of this provider from the kcf.conf file, if any. 4377968Sopensolaris@drydog.com * Otherwise, create a new kcf.conf entry for writing back to the file. 4387968Sopensolaris@drydog.com */ 439*10500SHai-May.Chao@Sun.COM pent = getent_kef(provname, phardlist, psoftlist, pfipslist); 4407968Sopensolaris@drydog.com if (pent == NULL) { /* create a new entry */ 4417968Sopensolaris@drydog.com pent = create_entry(provname); 4427968Sopensolaris@drydog.com if (pent == NULL) { 4437968Sopensolaris@drydog.com cryptodebug("out of memory."); 4447968Sopensolaris@drydog.com rc = FAILURE; 4457968Sopensolaris@drydog.com goto out; 4467968Sopensolaris@drydog.com } 4470Sstevel@tonic-gate } 4480Sstevel@tonic-gate 4497968Sopensolaris@drydog.com /* Get the mechanism list for the software provider from the kernel */ 450*10500SHai-May.Chao@Sun.COM if (get_soft_info(provname, &infolist, phardlist, psoftlist, 451*10500SHai-May.Chao@Sun.COM pfipslist) == FAILURE) { 4527968Sopensolaris@drydog.com rc = FAILURE; 4537968Sopensolaris@drydog.com goto out; 4547968Sopensolaris@drydog.com } 4557968Sopensolaris@drydog.com 4567968Sopensolaris@drydog.com if ((infolist != NULL) && (infolist->name[0] != '\0')) { 4577968Sopensolaris@drydog.com /* 4587968Sopensolaris@drydog.com * Replace the supportedlist from kcf.conf with possibly 4597968Sopensolaris@drydog.com * more-up-to-date list from the kernel. This is the case 4607968Sopensolaris@drydog.com * for default software providers that had more mechanisms 4617968Sopensolaris@drydog.com * added in the current version of the kernel. 4627968Sopensolaris@drydog.com */ 4637968Sopensolaris@drydog.com free_mechlist(pent->suplist); 4647968Sopensolaris@drydog.com pent->suplist = infolist; 4657968Sopensolaris@drydog.com } 4667968Sopensolaris@drydog.com 4677968Sopensolaris@drydog.com /* 4687968Sopensolaris@drydog.com * kCF treats random as an internal mechanism. So, we need to 4697968Sopensolaris@drydog.com * filter it from the mechanism list here, if we are NOT disabling 4707968Sopensolaris@drydog.com * or enabling the random feature. Note that we map random feature at 4717968Sopensolaris@drydog.com * cryptoadm(1M) level to the "random" mechanism in kCF. 4727968Sopensolaris@drydog.com */ 4730Sstevel@tonic-gate if (!rndflag) { 4740Sstevel@tonic-gate (void) filter_mechlist(&infolist, RANDOM); 4750Sstevel@tonic-gate } 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate /* Calculate the new disabled list */ 4780Sstevel@tonic-gate if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) { 4797968Sopensolaris@drydog.com rc = FAILURE; 4807968Sopensolaris@drydog.com goto out; 4810Sstevel@tonic-gate } 4820Sstevel@tonic-gate 4830Sstevel@tonic-gate /* Update the kcf.conf file with the updated entry */ 4840Sstevel@tonic-gate if (update_kcfconf(pent, MODIFY_MODE) == FAILURE) { 4857968Sopensolaris@drydog.com rc = FAILURE; 4867968Sopensolaris@drydog.com goto out; 4870Sstevel@tonic-gate } 4880Sstevel@tonic-gate 4897968Sopensolaris@drydog.com /* Setup argument to inform kernel about the new disabled list. */ 4900Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 4917968Sopensolaris@drydog.com rc = FAILURE; 4927968Sopensolaris@drydog.com goto out; 4930Sstevel@tonic-gate } 4940Sstevel@tonic-gate 4950Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 4960Sstevel@tonic-gate cryptoerror(LOG_STDERR, 4970Sstevel@tonic-gate gettext("failed to open %s for RW: %s"), 4980Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 4997968Sopensolaris@drydog.com rc = FAILURE; 5007968Sopensolaris@drydog.com goto out; 5010Sstevel@tonic-gate } 5020Sstevel@tonic-gate 5037968Sopensolaris@drydog.com /* Inform kernel about the new disabled list. */ 5040Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) { 5050Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s", 5060Sstevel@tonic-gate strerror(errno)); 5077968Sopensolaris@drydog.com rc = FAILURE; 5087968Sopensolaris@drydog.com goto out; 5090Sstevel@tonic-gate } 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 5120Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = " 5130Sstevel@tonic-gate "%d", pload_soft_dis->sd_return_value); 5147968Sopensolaris@drydog.com rc = FAILURE; 5157968Sopensolaris@drydog.com goto out; 5160Sstevel@tonic-gate } 5170Sstevel@tonic-gate 5187968Sopensolaris@drydog.com out: 5197968Sopensolaris@drydog.com free_entrylist(phardlist); 5207968Sopensolaris@drydog.com free_entrylist(psoftlist); 5217968Sopensolaris@drydog.com free_mechlist(infolist); 5227968Sopensolaris@drydog.com free_entry(pent); 5230Sstevel@tonic-gate free(pload_soft_dis); 5247968Sopensolaris@drydog.com if (fd != -1) 5257968Sopensolaris@drydog.com (void) close(fd); 5267968Sopensolaris@drydog.com return (rc); 5270Sstevel@tonic-gate } 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate 5307968Sopensolaris@drydog.com /* 5317968Sopensolaris@drydog.com * Enable a kernel software or hardware provider. 5327968Sopensolaris@drydog.com * This implements the "cryptoadm enable" command for kernel providers. 5337968Sopensolaris@drydog.com */ 5340Sstevel@tonic-gate int 5350Sstevel@tonic-gate enable_kef(char *provname, boolean_t rndflag, boolean_t allflag, 5360Sstevel@tonic-gate mechlist_t *mlist) 5370Sstevel@tonic-gate { 5380Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 5390Sstevel@tonic-gate crypto_load_dev_disabled_t *pload_dev_dis = NULL; 5407968Sopensolaris@drydog.com entry_t *pent = NULL; 5417968Sopensolaris@drydog.com boolean_t redo_flag = B_FALSE; 5427968Sopensolaris@drydog.com boolean_t in_kernel = B_FALSE; 5437968Sopensolaris@drydog.com int fd = -1; 5447968Sopensolaris@drydog.com int rc = SUCCESS; 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate 5477968Sopensolaris@drydog.com /* Get the entry of this provider from the kcf.conf file, if any. */ 548*10500SHai-May.Chao@Sun.COM pent = getent_kef(provname, NULL, NULL, NULL); 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate if (is_device(provname)) { 5510Sstevel@tonic-gate if (pent == NULL) { 5520Sstevel@tonic-gate /* 5530Sstevel@tonic-gate * This device doesn't have an entry in the config 5540Sstevel@tonic-gate * file, therefore nothing is disabled. 5550Sstevel@tonic-gate */ 5560Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 5570Sstevel@tonic-gate "all mechanisms are enabled already for %s."), 5580Sstevel@tonic-gate provname); 5597968Sopensolaris@drydog.com free_entry(pent); 5600Sstevel@tonic-gate return (SUCCESS); 5610Sstevel@tonic-gate } 5620Sstevel@tonic-gate } else { /* a software module */ 5637968Sopensolaris@drydog.com if (check_kernel_for_soft(provname, NULL, &in_kernel) == 5647968Sopensolaris@drydog.com FAILURE) { 5657968Sopensolaris@drydog.com free_entry(pent); 5660Sstevel@tonic-gate return (FAILURE); 5677968Sopensolaris@drydog.com } else if (in_kernel == B_FALSE) { 5687968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext("%s does not exist."), 5697968Sopensolaris@drydog.com provname); 5707968Sopensolaris@drydog.com free_entry(pent); 5717968Sopensolaris@drydog.com return (FAILURE); 5727968Sopensolaris@drydog.com } else if ((pent == NULL) || (pent->dis_count == 0)) { 5730Sstevel@tonic-gate /* nothing to be enabled. */ 5740Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 5750Sstevel@tonic-gate "all mechanisms are enabled already for %s."), 5760Sstevel@tonic-gate provname); 5770Sstevel@tonic-gate free_entry(pent); 5780Sstevel@tonic-gate return (SUCCESS); 5790Sstevel@tonic-gate } 5800Sstevel@tonic-gate } 5810Sstevel@tonic-gate 5827968Sopensolaris@drydog.com /* 5837968Sopensolaris@drydog.com * kCF treats random as an internal mechanism. So, we need to 5847968Sopensolaris@drydog.com * filter it from the mechanism list here, if we are NOT disabling 5857968Sopensolaris@drydog.com * or enabling the random feature. Note that we map random feature at 5867968Sopensolaris@drydog.com * cryptoadm(1M) level to the "random" mechanism in kCF. 5877968Sopensolaris@drydog.com */ 5880Sstevel@tonic-gate if (!rndflag) { 5890Sstevel@tonic-gate redo_flag = filter_mechlist(&pent->dislist, RANDOM); 5900Sstevel@tonic-gate if (redo_flag) 5910Sstevel@tonic-gate pent->dis_count--; 5920Sstevel@tonic-gate } 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate /* Update the entry by enabling mechanisms for this provider */ 5950Sstevel@tonic-gate if ((rc = enable_mechs(&pent, allflag, mlist)) != SUCCESS) { 5960Sstevel@tonic-gate free_entry(pent); 5970Sstevel@tonic-gate return (rc); 5980Sstevel@tonic-gate } 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate if (redo_flag) { 6010Sstevel@tonic-gate mechlist_t *tmp; 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate if ((tmp = create_mech(RANDOM)) == NULL) { 6040Sstevel@tonic-gate free_entry(pent); 6050Sstevel@tonic-gate return (FAILURE); 6060Sstevel@tonic-gate } 6070Sstevel@tonic-gate tmp->next = pent->dislist; 6080Sstevel@tonic-gate pent->dislist = tmp; 6090Sstevel@tonic-gate pent->dis_count++; 6100Sstevel@tonic-gate } 6110Sstevel@tonic-gate 6120Sstevel@tonic-gate /* 6137968Sopensolaris@drydog.com * Update the kcf.conf file with the updated entry. 6140Sstevel@tonic-gate * For a hardware provider, if there is no more disabled mechanism, 6157968Sopensolaris@drydog.com * remove the entire kcf.conf entry. 6160Sstevel@tonic-gate */ 6170Sstevel@tonic-gate if (is_device(pent->name) && (pent->dis_count == 0)) { 6180Sstevel@tonic-gate rc = update_kcfconf(pent, DELETE_MODE); 6190Sstevel@tonic-gate } else { 6200Sstevel@tonic-gate rc = update_kcfconf(pent, MODIFY_MODE); 6210Sstevel@tonic-gate } 6220Sstevel@tonic-gate 6230Sstevel@tonic-gate if (rc == FAILURE) { 6240Sstevel@tonic-gate free_entry(pent); 6250Sstevel@tonic-gate return (FAILURE); 6260Sstevel@tonic-gate } 6270Sstevel@tonic-gate 6280Sstevel@tonic-gate 6290Sstevel@tonic-gate /* Inform Kernel about the policy change */ 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 6320Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 6330Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 6347968Sopensolaris@drydog.com free_entry(pent); 6350Sstevel@tonic-gate return (FAILURE); 6360Sstevel@tonic-gate } 6370Sstevel@tonic-gate 6380Sstevel@tonic-gate if (is_device(provname)) { 6390Sstevel@tonic-gate /* LOAD_DEV_DISABLED */ 6400Sstevel@tonic-gate if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) { 6417968Sopensolaris@drydog.com free_entry(pent); 6420Sstevel@tonic-gate return (FAILURE); 6430Sstevel@tonic-gate } 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) { 6460Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: " 6470Sstevel@tonic-gate "%s", strerror(errno)); 6487968Sopensolaris@drydog.com free_entry(pent); 6490Sstevel@tonic-gate free(pload_dev_dis); 6500Sstevel@tonic-gate (void) close(fd); 6510Sstevel@tonic-gate return (FAILURE); 6520Sstevel@tonic-gate } 6530Sstevel@tonic-gate 6540Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 6550Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 6560Sstevel@tonic-gate "return_value = %d", 6570Sstevel@tonic-gate pload_dev_dis->dd_return_value); 6587968Sopensolaris@drydog.com free_entry(pent); 6590Sstevel@tonic-gate free(pload_dev_dis); 6600Sstevel@tonic-gate (void) close(fd); 6610Sstevel@tonic-gate return (FAILURE); 6620Sstevel@tonic-gate } 6630Sstevel@tonic-gate 6647968Sopensolaris@drydog.com } else { /* a software module */ 6650Sstevel@tonic-gate /* LOAD_SOFT_DISABLED */ 6660Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 6677968Sopensolaris@drydog.com free_entry(pent); 6680Sstevel@tonic-gate return (FAILURE); 6690Sstevel@tonic-gate } 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) 6720Sstevel@tonic-gate == -1) { 6730Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: " 6740Sstevel@tonic-gate "%s", strerror(errno)); 6757968Sopensolaris@drydog.com free_entry(pent); 6760Sstevel@tonic-gate free(pload_soft_dis); 6770Sstevel@tonic-gate (void) close(fd); 6780Sstevel@tonic-gate return (FAILURE); 6790Sstevel@tonic-gate } 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 6820Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 6830Sstevel@tonic-gate "return_value = %d", 6840Sstevel@tonic-gate pload_soft_dis->sd_return_value); 6857968Sopensolaris@drydog.com free_entry(pent); 6860Sstevel@tonic-gate free(pload_soft_dis); 6870Sstevel@tonic-gate (void) close(fd); 6880Sstevel@tonic-gate return (FAILURE); 6890Sstevel@tonic-gate } 6900Sstevel@tonic-gate } 6910Sstevel@tonic-gate 6927968Sopensolaris@drydog.com free_entry(pent); 6937968Sopensolaris@drydog.com free(pload_soft_dis); 6940Sstevel@tonic-gate (void) close(fd); 6950Sstevel@tonic-gate return (SUCCESS); 6960Sstevel@tonic-gate } 6970Sstevel@tonic-gate 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate /* 7000Sstevel@tonic-gate * Install a software module with the specified mechanism list into the system. 7010Sstevel@tonic-gate * This routine adds an entry into the config file for this software module 7020Sstevel@tonic-gate * first, then makes a CRYPTO_LOAD_SOFT_CONFIG ioctl call to inform kernel 7030Sstevel@tonic-gate * about the new addition. 7040Sstevel@tonic-gate */ 7050Sstevel@tonic-gate int 7060Sstevel@tonic-gate install_kef(char *provname, mechlist_t *mlist) 7070Sstevel@tonic-gate { 7080Sstevel@tonic-gate crypto_load_soft_config_t *pload_soft_conf = NULL; 7097968Sopensolaris@drydog.com boolean_t found; 7107968Sopensolaris@drydog.com entry_t *pent = NULL; 7117968Sopensolaris@drydog.com FILE *pfile = NULL; 7127968Sopensolaris@drydog.com FILE *pfile_tmp = NULL; 7137968Sopensolaris@drydog.com char tmpfile_name[MAXPATHLEN]; 7147968Sopensolaris@drydog.com char *ptr; 7157968Sopensolaris@drydog.com char *str; 7167968Sopensolaris@drydog.com char *name; 7177968Sopensolaris@drydog.com char buffer[BUFSIZ]; 7187968Sopensolaris@drydog.com char buffer2[BUFSIZ]; 7197968Sopensolaris@drydog.com int found_count; 7207968Sopensolaris@drydog.com int fd = -1; 7217968Sopensolaris@drydog.com int rc = SUCCESS; 7227968Sopensolaris@drydog.com int err; 7230Sstevel@tonic-gate 7240Sstevel@tonic-gate if ((provname == NULL) || (mlist == NULL)) { 7250Sstevel@tonic-gate return (FAILURE); 7260Sstevel@tonic-gate } 7270Sstevel@tonic-gate 7280Sstevel@tonic-gate /* Check if the provider already exists */ 729*10500SHai-May.Chao@Sun.COM if ((pent = getent_kef(provname, NULL, NULL, NULL)) != NULL) { 7300Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s exists already."), 7310Sstevel@tonic-gate provname); 7320Sstevel@tonic-gate free_entry(pent); 7330Sstevel@tonic-gate return (FAILURE); 7340Sstevel@tonic-gate } 7350Sstevel@tonic-gate 7360Sstevel@tonic-gate /* Create an entry with provname and mlist. */ 7377968Sopensolaris@drydog.com if ((pent = create_entry(provname)) == NULL) { 7380Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("out of memory.")); 7390Sstevel@tonic-gate return (FAILURE); 7400Sstevel@tonic-gate } 7410Sstevel@tonic-gate pent->sup_count = get_mech_count(mlist); 7420Sstevel@tonic-gate pent->suplist = mlist; 7430Sstevel@tonic-gate 7440Sstevel@tonic-gate /* Append an entry for this software module to the kcf.conf file. */ 7450Sstevel@tonic-gate if ((str = ent2str(pent)) == NULL) { 7460Sstevel@tonic-gate free_entry(pent); 7470Sstevel@tonic-gate return (FAILURE); 7480Sstevel@tonic-gate } 7490Sstevel@tonic-gate 7500Sstevel@tonic-gate if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) { 7510Sstevel@tonic-gate err = errno; 7520Sstevel@tonic-gate cryptoerror(LOG_STDERR, 7530Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 7540Sstevel@tonic-gate strerror(err)); 7550Sstevel@tonic-gate cryptodebug("failed to open %s for write.", _PATH_KCF_CONF); 7560Sstevel@tonic-gate free_entry(pent); 7570Sstevel@tonic-gate return (FAILURE); 7580Sstevel@tonic-gate } 7590Sstevel@tonic-gate 7600Sstevel@tonic-gate if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 7610Sstevel@tonic-gate err = errno; 7620Sstevel@tonic-gate cryptoerror(LOG_STDERR, 7630Sstevel@tonic-gate gettext("failed to lock the configuration - %s"), 7640Sstevel@tonic-gate strerror(err)); 7650Sstevel@tonic-gate free_entry(pent); 7660Sstevel@tonic-gate (void) fclose(pfile); 7670Sstevel@tonic-gate return (FAILURE); 7680Sstevel@tonic-gate } 7690Sstevel@tonic-gate 7700Sstevel@tonic-gate /* 7710Sstevel@tonic-gate * Create a temporary file in the /etc/crypto directory. 7720Sstevel@tonic-gate */ 7730Sstevel@tonic-gate (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 7740Sstevel@tonic-gate if (mkstemp(tmpfile_name) == -1) { 7750Sstevel@tonic-gate err = errno; 7760Sstevel@tonic-gate cryptoerror(LOG_STDERR, 7770Sstevel@tonic-gate gettext("failed to create a temporary file - %s"), 7780Sstevel@tonic-gate strerror(err)); 7790Sstevel@tonic-gate free_entry(pent); 7800Sstevel@tonic-gate (void) fclose(pfile); 7810Sstevel@tonic-gate return (FAILURE); 7820Sstevel@tonic-gate } 7830Sstevel@tonic-gate 7840Sstevel@tonic-gate if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 7850Sstevel@tonic-gate err = errno; 7860Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 7870Sstevel@tonic-gate tmpfile_name, strerror(err)); 7880Sstevel@tonic-gate free_entry(pent); 7890Sstevel@tonic-gate (void) fclose(pfile); 7900Sstevel@tonic-gate return (FAILURE); 7910Sstevel@tonic-gate } 7920Sstevel@tonic-gate 7930Sstevel@tonic-gate 7940Sstevel@tonic-gate /* 7950Sstevel@tonic-gate * Loop thru the config file. If the provider was reserved within a 7960Sstevel@tonic-gate * package bracket, just uncomment it. Otherwise, append it at 7970Sstevel@tonic-gate * the end. The resulting file will be saved in the temp file first. 7980Sstevel@tonic-gate */ 7990Sstevel@tonic-gate found_count = 0; 8000Sstevel@tonic-gate rc = SUCCESS; 8010Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) { 8020Sstevel@tonic-gate found = B_FALSE; 8030Sstevel@tonic-gate if (buffer[0] == '#') { 8040Sstevel@tonic-gate (void) strlcpy(buffer2, buffer, BUFSIZ); 8050Sstevel@tonic-gate ptr = buffer2; 8060Sstevel@tonic-gate ptr++; 8070Sstevel@tonic-gate if ((name = strtok(ptr, SEP_COLON)) == NULL) { 8080Sstevel@tonic-gate rc = FAILURE; 8090Sstevel@tonic-gate break; 8100Sstevel@tonic-gate } else if (strcmp(provname, name) == 0) { 8110Sstevel@tonic-gate found = B_TRUE; 8120Sstevel@tonic-gate found_count++; 8130Sstevel@tonic-gate } 8140Sstevel@tonic-gate } 8150Sstevel@tonic-gate 8160Sstevel@tonic-gate if (found == B_FALSE) { 8170Sstevel@tonic-gate if (fputs(buffer, pfile_tmp) == EOF) { 8180Sstevel@tonic-gate rc = FAILURE; 8190Sstevel@tonic-gate } 8200Sstevel@tonic-gate } else { 8210Sstevel@tonic-gate if (found_count == 1) { 8220Sstevel@tonic-gate if (fputs(str, pfile_tmp) == EOF) { 8230Sstevel@tonic-gate rc = FAILURE; 8240Sstevel@tonic-gate } 8250Sstevel@tonic-gate } else { 8260Sstevel@tonic-gate /* 8270Sstevel@tonic-gate * Found a second entry with #libname. 8287968Sopensolaris@drydog.com * Should not happen. The kcf.conf file 8290Sstevel@tonic-gate * is corrupted. Give a warning and skip 8300Sstevel@tonic-gate * this entry. 8310Sstevel@tonic-gate */ 8320Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8330Sstevel@tonic-gate "(Warning) Found an additional reserved " 8340Sstevel@tonic-gate "entry for %s."), provname); 8350Sstevel@tonic-gate } 8360Sstevel@tonic-gate } 8370Sstevel@tonic-gate 8380Sstevel@tonic-gate if (rc == FAILURE) { 8390Sstevel@tonic-gate break; 8400Sstevel@tonic-gate } 8410Sstevel@tonic-gate } 8420Sstevel@tonic-gate (void) fclose(pfile); 8430Sstevel@tonic-gate 8440Sstevel@tonic-gate if (rc == FAILURE) { 8450Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("write error.")); 8460Sstevel@tonic-gate (void) fclose(pfile_tmp); 8470Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 8480Sstevel@tonic-gate err = errno; 8490Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8500Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), tmpfile_name, 8510Sstevel@tonic-gate strerror(err)); 8520Sstevel@tonic-gate } 8530Sstevel@tonic-gate free_entry(pent); 8540Sstevel@tonic-gate return (FAILURE); 8550Sstevel@tonic-gate } 8560Sstevel@tonic-gate 8570Sstevel@tonic-gate if (found_count == 0) { 8580Sstevel@tonic-gate /* 8590Sstevel@tonic-gate * This libname was not in package before, append it to the 8600Sstevel@tonic-gate * end of the temp file. 8610Sstevel@tonic-gate */ 8620Sstevel@tonic-gate if (fputs(str, pfile_tmp) == EOF) { 8630Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8640Sstevel@tonic-gate "failed to write to %s: %s"), tmpfile_name, 8650Sstevel@tonic-gate strerror(errno)); 8660Sstevel@tonic-gate (void) fclose(pfile_tmp); 8670Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 8680Sstevel@tonic-gate err = errno; 8690Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8700Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 8710Sstevel@tonic-gate tmpfile_name, strerror(err)); 8720Sstevel@tonic-gate } 8730Sstevel@tonic-gate free_entry(pent); 8740Sstevel@tonic-gate return (FAILURE); 8750Sstevel@tonic-gate } 8760Sstevel@tonic-gate } 8770Sstevel@tonic-gate 8780Sstevel@tonic-gate if (fclose(pfile_tmp) != 0) { 8790Sstevel@tonic-gate err = errno; 8800Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8810Sstevel@tonic-gate gettext("failed to close %s: %s"), tmpfile_name, 8820Sstevel@tonic-gate strerror(err)); 8837968Sopensolaris@drydog.com free_entry(pent); 8840Sstevel@tonic-gate return (FAILURE); 8850Sstevel@tonic-gate } 8860Sstevel@tonic-gate 8870Sstevel@tonic-gate if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) { 8880Sstevel@tonic-gate err = errno; 8890Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8900Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 8917968Sopensolaris@drydog.com strerror(err)); 8920Sstevel@tonic-gate cryptodebug("failed to rename %s to %s: %s", tmpfile_name, 8930Sstevel@tonic-gate _PATH_KCF_CONF, strerror(err)); 8940Sstevel@tonic-gate rc = FAILURE; 8950Sstevel@tonic-gate } else if (chmod(_PATH_KCF_CONF, 8960Sstevel@tonic-gate S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 8970Sstevel@tonic-gate err = errno; 8980Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8990Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 9000Sstevel@tonic-gate strerror(err)); 9010Sstevel@tonic-gate cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF, 9020Sstevel@tonic-gate strerror(err)); 9030Sstevel@tonic-gate rc = FAILURE; 9040Sstevel@tonic-gate } else { 9050Sstevel@tonic-gate rc = SUCCESS; 9060Sstevel@tonic-gate } 9070Sstevel@tonic-gate 9080Sstevel@tonic-gate if (rc == FAILURE) { 9090Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 9100Sstevel@tonic-gate err = errno; 9110Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 9120Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 9130Sstevel@tonic-gate tmpfile_name, strerror(err)); 9140Sstevel@tonic-gate } 9157968Sopensolaris@drydog.com free_entry(pent); 9160Sstevel@tonic-gate return (FAILURE); 9170Sstevel@tonic-gate } 9180Sstevel@tonic-gate 9190Sstevel@tonic-gate 9200Sstevel@tonic-gate /* Inform kernel of this new software module. */ 9210Sstevel@tonic-gate 9220Sstevel@tonic-gate if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) { 9230Sstevel@tonic-gate free_entry(pent); 9240Sstevel@tonic-gate return (FAILURE); 9250Sstevel@tonic-gate } 9260Sstevel@tonic-gate 9270Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 9280Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 9290Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 9300Sstevel@tonic-gate free_entry(pent); 9310Sstevel@tonic-gate free(pload_soft_conf); 9320Sstevel@tonic-gate return (FAILURE); 9330Sstevel@tonic-gate } 9340Sstevel@tonic-gate 9350Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) { 9360Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 9370Sstevel@tonic-gate strerror(errno)); 9380Sstevel@tonic-gate free_entry(pent); 9390Sstevel@tonic-gate free(pload_soft_conf); 9400Sstevel@tonic-gate (void) close(fd); 9410Sstevel@tonic-gate return (FAILURE); 9420Sstevel@tonic-gate } 9430Sstevel@tonic-gate 9440Sstevel@tonic-gate if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 9450Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed, " 9460Sstevel@tonic-gate "return_value = %d", pload_soft_conf->sc_return_value); 9470Sstevel@tonic-gate free_entry(pent); 9480Sstevel@tonic-gate free(pload_soft_conf); 9490Sstevel@tonic-gate (void) close(fd); 9500Sstevel@tonic-gate return (FAILURE); 9510Sstevel@tonic-gate } 9520Sstevel@tonic-gate 9530Sstevel@tonic-gate free_entry(pent); 9540Sstevel@tonic-gate free(pload_soft_conf); 9550Sstevel@tonic-gate (void) close(fd); 9560Sstevel@tonic-gate return (SUCCESS); 9570Sstevel@tonic-gate } 9580Sstevel@tonic-gate 9590Sstevel@tonic-gate /* 9600Sstevel@tonic-gate * Uninstall the software module. This routine first unloads the software 9610Sstevel@tonic-gate * module with 3 ioctl calls, then deletes its entry from the config file. 9620Sstevel@tonic-gate * Removing an entry from the config file needs to be done last to ensure 9630Sstevel@tonic-gate * that there is still an entry if the earlier unload failed for any reason. 9640Sstevel@tonic-gate */ 9650Sstevel@tonic-gate int 9660Sstevel@tonic-gate uninstall_kef(char *provname) 9670Sstevel@tonic-gate { 9687968Sopensolaris@drydog.com entry_t *pent = NULL; 9697968Sopensolaris@drydog.com int rc = SUCCESS; 9707968Sopensolaris@drydog.com boolean_t in_kernel = B_FALSE; 9717968Sopensolaris@drydog.com boolean_t in_kcfconf = B_FALSE; 9727968Sopensolaris@drydog.com int fd = -1; 9737968Sopensolaris@drydog.com crypto_load_soft_config_t *pload_soft_conf = NULL; 9740Sstevel@tonic-gate 9757968Sopensolaris@drydog.com /* Check to see if the provider exists first. */ 9767968Sopensolaris@drydog.com if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) { 9770Sstevel@tonic-gate return (FAILURE); 9787968Sopensolaris@drydog.com } else if (in_kernel == B_FALSE) { 9797968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext("%s does not exist."), 9807968Sopensolaris@drydog.com provname); 9810Sstevel@tonic-gate return (FAILURE); 9820Sstevel@tonic-gate } 9830Sstevel@tonic-gate 9840Sstevel@tonic-gate /* 9857968Sopensolaris@drydog.com * If it is loaded, unload it first. This does 2 ioctl calls: 9867968Sopensolaris@drydog.com * CRYPTO_UNLOAD_SOFT_MODULE and CRYPTO_LOAD_SOFT_DISABLED. 9870Sstevel@tonic-gate */ 9887968Sopensolaris@drydog.com if (unload_kef_soft(provname) == FAILURE) { 9890Sstevel@tonic-gate cryptoerror(LOG_STDERR, 9907968Sopensolaris@drydog.com gettext("failed to unload %s during uninstall.\n"), 9917968Sopensolaris@drydog.com provname); 9920Sstevel@tonic-gate return (FAILURE); 9930Sstevel@tonic-gate } 9940Sstevel@tonic-gate 9950Sstevel@tonic-gate /* 9967968Sopensolaris@drydog.com * Inform kernel to remove the configuration of this software module. 9970Sstevel@tonic-gate */ 9980Sstevel@tonic-gate 9997968Sopensolaris@drydog.com /* Setup ioctl() parameter */ 1000*10500SHai-May.Chao@Sun.COM pent = getent_kef(provname, NULL, NULL, NULL); 10017968Sopensolaris@drydog.com if (pent != NULL) { /* in kcf.conf */ 10027968Sopensolaris@drydog.com in_kcfconf = B_TRUE; 10037968Sopensolaris@drydog.com free_mechlist(pent->suplist); 10047968Sopensolaris@drydog.com pent->suplist = NULL; 10057968Sopensolaris@drydog.com pent->sup_count = 0; 10067968Sopensolaris@drydog.com } else if ((pent = create_entry(provname)) == NULL) { 10077968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext("out of memory.")); 10087968Sopensolaris@drydog.com return (FAILURE); 10097968Sopensolaris@drydog.com } 10107968Sopensolaris@drydog.com if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) { 10117968Sopensolaris@drydog.com free_entry(pent); 10127968Sopensolaris@drydog.com return (FAILURE); 10130Sstevel@tonic-gate } 10140Sstevel@tonic-gate 10157968Sopensolaris@drydog.com /* Open the /dev/cryptoadm device */ 10167968Sopensolaris@drydog.com if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 10177968Sopensolaris@drydog.com int err = errno; 10187968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 10197968Sopensolaris@drydog.com ADMIN_IOCTL_DEVICE, strerror(err)); 10207968Sopensolaris@drydog.com free_entry(pent); 10217968Sopensolaris@drydog.com free(pload_soft_conf); 10227968Sopensolaris@drydog.com return (FAILURE); 10237968Sopensolaris@drydog.com } 10247968Sopensolaris@drydog.com 10257968Sopensolaris@drydog.com if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, 10267968Sopensolaris@drydog.com pload_soft_conf) == -1) { 10277968Sopensolaris@drydog.com cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 10287968Sopensolaris@drydog.com strerror(errno)); 10297968Sopensolaris@drydog.com free_entry(pent); 10307968Sopensolaris@drydog.com free(pload_soft_conf); 10317968Sopensolaris@drydog.com (void) close(fd); 10320Sstevel@tonic-gate return (FAILURE); 10330Sstevel@tonic-gate } 10340Sstevel@tonic-gate 10357968Sopensolaris@drydog.com if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 10367968Sopensolaris@drydog.com cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl = return_value = %d", 10377968Sopensolaris@drydog.com pload_soft_conf->sc_return_value); 10387968Sopensolaris@drydog.com free_entry(pent); 10397968Sopensolaris@drydog.com free(pload_soft_conf); 10407968Sopensolaris@drydog.com (void) close(fd); 10410Sstevel@tonic-gate return (FAILURE); 10420Sstevel@tonic-gate } 10430Sstevel@tonic-gate 10447968Sopensolaris@drydog.com /* ioctl cleanup */ 10457968Sopensolaris@drydog.com free(pload_soft_conf); 10467968Sopensolaris@drydog.com (void) close(fd); 10477968Sopensolaris@drydog.com 10487968Sopensolaris@drydog.com 10497968Sopensolaris@drydog.com /* Finally, remove entry from kcf.conf, if present */ 10507968Sopensolaris@drydog.com if (in_kcfconf && (pent != NULL)) { 10517968Sopensolaris@drydog.com rc = update_kcfconf(pent, DELETE_MODE); 10520Sstevel@tonic-gate } 10530Sstevel@tonic-gate 10547968Sopensolaris@drydog.com free_entry(pent); 10550Sstevel@tonic-gate return (rc); 10560Sstevel@tonic-gate } 10570Sstevel@tonic-gate 10580Sstevel@tonic-gate 10597968Sopensolaris@drydog.com /* 10607968Sopensolaris@drydog.com * Implement the "cryptoadm refresh" command for global zones. 10617968Sopensolaris@drydog.com * That is, send the current contents of kcf.conf to the kernel via ioctl(). 10627968Sopensolaris@drydog.com */ 10630Sstevel@tonic-gate int 10640Sstevel@tonic-gate refresh(void) 10650Sstevel@tonic-gate { 10660Sstevel@tonic-gate crypto_load_soft_config_t *pload_soft_conf = NULL; 10670Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 10680Sstevel@tonic-gate crypto_load_dev_disabled_t *pload_dev_dis = NULL; 10697968Sopensolaris@drydog.com entrylist_t *pdevlist = NULL; 10707968Sopensolaris@drydog.com entrylist_t *psoftlist = NULL; 1071*10500SHai-May.Chao@Sun.COM entrylist_t *pfipslist = NULL; 10727968Sopensolaris@drydog.com entrylist_t *ptr; 10737968Sopensolaris@drydog.com int fd = -1; 10747968Sopensolaris@drydog.com int rc = SUCCESS; 10757968Sopensolaris@drydog.com int err; 10760Sstevel@tonic-gate 1077*10500SHai-May.Chao@Sun.COM if (get_kcfconf_info(&pdevlist, &psoftlist, &pfipslist) == 1078*10500SHai-May.Chao@Sun.COM FAILURE) { 10790Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to retrieve the providers' " 10800Sstevel@tonic-gate "information from the configuration file - %s.", 10810Sstevel@tonic-gate _PATH_KCF_CONF); 10820Sstevel@tonic-gate return (FAILURE); 10830Sstevel@tonic-gate } 10840Sstevel@tonic-gate 10850Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 10860Sstevel@tonic-gate err = errno; 10870Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 10880Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(err)); 10890Sstevel@tonic-gate free(psoftlist); 10900Sstevel@tonic-gate free(pdevlist); 10910Sstevel@tonic-gate return (FAILURE); 10920Sstevel@tonic-gate } 10930Sstevel@tonic-gate 10940Sstevel@tonic-gate /* 10957968Sopensolaris@drydog.com * For each software provider module, pass two sets of information to 10967968Sopensolaris@drydog.com * the kernel: the supported list and the disabled list. 10970Sstevel@tonic-gate */ 10987968Sopensolaris@drydog.com for (ptr = psoftlist; ptr != NULL; ptr = ptr->next) { 10997968Sopensolaris@drydog.com entry_t *pent = ptr->pent; 11007968Sopensolaris@drydog.com 11010Sstevel@tonic-gate /* load the supported list */ 11027968Sopensolaris@drydog.com if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) { 11037968Sopensolaris@drydog.com cryptodebug("setup_soft_conf() failed"); 11040Sstevel@tonic-gate rc = FAILURE; 11050Sstevel@tonic-gate break; 11060Sstevel@tonic-gate } 11070Sstevel@tonic-gate 11087968Sopensolaris@drydog.com if (!pent->load) { /* unloaded--mark as loaded */ 11097968Sopensolaris@drydog.com pent->load = B_TRUE; 11107968Sopensolaris@drydog.com rc = update_kcfconf(pent, MODIFY_MODE); 11117968Sopensolaris@drydog.com if (rc != SUCCESS) { 11127968Sopensolaris@drydog.com free(pload_soft_conf); 11137968Sopensolaris@drydog.com break; 11147968Sopensolaris@drydog.com } 11157968Sopensolaris@drydog.com } 11167968Sopensolaris@drydog.com 11170Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) 11180Sstevel@tonic-gate == -1) { 11190Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 11200Sstevel@tonic-gate strerror(errno)); 11210Sstevel@tonic-gate free(pload_soft_conf); 11220Sstevel@tonic-gate rc = FAILURE; 11230Sstevel@tonic-gate break; 11240Sstevel@tonic-gate } 11250Sstevel@tonic-gate 11260Sstevel@tonic-gate if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 11270Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl " 11280Sstevel@tonic-gate "return_value = %d", 11290Sstevel@tonic-gate pload_soft_conf->sc_return_value); 11300Sstevel@tonic-gate free(pload_soft_conf); 11310Sstevel@tonic-gate rc = FAILURE; 11320Sstevel@tonic-gate break; 11330Sstevel@tonic-gate } 11340Sstevel@tonic-gate 11357968Sopensolaris@drydog.com free(pload_soft_conf); 11367968Sopensolaris@drydog.com 11370Sstevel@tonic-gate /* load the disabled list */ 11380Sstevel@tonic-gate if (ptr->pent->dis_count != 0) { 11390Sstevel@tonic-gate pload_soft_dis = setup_soft_dis(ptr->pent); 11400Sstevel@tonic-gate if (pload_soft_dis == NULL) { 11417968Sopensolaris@drydog.com cryptodebug("setup_soft_dis() failed"); 11427968Sopensolaris@drydog.com free(pload_soft_dis); 11430Sstevel@tonic-gate rc = FAILURE; 11440Sstevel@tonic-gate break; 11450Sstevel@tonic-gate } 11460Sstevel@tonic-gate 11470Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, 11480Sstevel@tonic-gate pload_soft_dis) == -1) { 11490Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 11500Sstevel@tonic-gate "failed: %s", strerror(errno)); 11510Sstevel@tonic-gate free(pload_soft_dis); 11520Sstevel@tonic-gate rc = FAILURE; 11530Sstevel@tonic-gate break; 11540Sstevel@tonic-gate } 11550Sstevel@tonic-gate 11560Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != 11570Sstevel@tonic-gate CRYPTO_SUCCESS) { 11580Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 11590Sstevel@tonic-gate "return_value = %d", 11600Sstevel@tonic-gate pload_soft_dis->sd_return_value); 11610Sstevel@tonic-gate free(pload_soft_dis); 11620Sstevel@tonic-gate rc = FAILURE; 11630Sstevel@tonic-gate break; 11640Sstevel@tonic-gate } 11650Sstevel@tonic-gate free(pload_soft_dis); 11660Sstevel@tonic-gate } 11670Sstevel@tonic-gate } 11680Sstevel@tonic-gate 11690Sstevel@tonic-gate if (rc != SUCCESS) { 11700Sstevel@tonic-gate (void) close(fd); 11710Sstevel@tonic-gate return (rc); 11720Sstevel@tonic-gate } 11730Sstevel@tonic-gate 11740Sstevel@tonic-gate 11757968Sopensolaris@drydog.com /* 11767968Sopensolaris@drydog.com * For each hardware provider module, pass the disabled list 11777968Sopensolaris@drydog.com * information to the kernel. 11787968Sopensolaris@drydog.com */ 11797968Sopensolaris@drydog.com for (ptr = pdevlist; ptr != NULL; ptr = ptr->next) { 11800Sstevel@tonic-gate /* load the disabled list */ 11810Sstevel@tonic-gate if (ptr->pent->dis_count != 0) { 11820Sstevel@tonic-gate pload_dev_dis = setup_dev_dis(ptr->pent); 11830Sstevel@tonic-gate if (pload_dev_dis == NULL) { 11840Sstevel@tonic-gate rc = FAILURE; 11850Sstevel@tonic-gate break; 11860Sstevel@tonic-gate } 11870Sstevel@tonic-gate 11880Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) 11890Sstevel@tonic-gate == -1) { 11900Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 11910Sstevel@tonic-gate "failed: %s", strerror(errno)); 11920Sstevel@tonic-gate free(pload_dev_dis); 11930Sstevel@tonic-gate rc = FAILURE; 11940Sstevel@tonic-gate break; 11950Sstevel@tonic-gate } 11960Sstevel@tonic-gate 11970Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 11980Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 11990Sstevel@tonic-gate "return_value = %d", 12000Sstevel@tonic-gate pload_dev_dis->dd_return_value); 12010Sstevel@tonic-gate free(pload_dev_dis); 12020Sstevel@tonic-gate rc = FAILURE; 12030Sstevel@tonic-gate break; 12040Sstevel@tonic-gate } 12050Sstevel@tonic-gate free(pload_dev_dis); 12060Sstevel@tonic-gate } 12070Sstevel@tonic-gate } 12080Sstevel@tonic-gate 1209*10500SHai-May.Chao@Sun.COM /* 1210*10500SHai-May.Chao@Sun.COM * handle fips_status=enabled|disabled 1211*10500SHai-May.Chao@Sun.COM */ 1212*10500SHai-May.Chao@Sun.COM ptr = pfipslist; 1213*10500SHai-May.Chao@Sun.COM if (ptr != NULL) { 1214*10500SHai-May.Chao@Sun.COM if (ptr->pent->flag_fips_enabled) { 1215*10500SHai-May.Chao@Sun.COM rc = do_fips_actions(FIPS140_ENABLE, REFRESH); 1216*10500SHai-May.Chao@Sun.COM } else { 1217*10500SHai-May.Chao@Sun.COM rc = do_fips_actions(FIPS140_DISABLE, REFRESH); 1218*10500SHai-May.Chao@Sun.COM } 1219*10500SHai-May.Chao@Sun.COM } 1220*10500SHai-May.Chao@Sun.COM 12210Sstevel@tonic-gate (void) close(fd); 12220Sstevel@tonic-gate return (rc); 12230Sstevel@tonic-gate } 12240Sstevel@tonic-gate 12250Sstevel@tonic-gate /* 12260Sstevel@tonic-gate * Unload the kernel software provider. Before calling this function, the 12277968Sopensolaris@drydog.com * caller should check to see if the provider is in the kernel. 12287968Sopensolaris@drydog.com * 12297968Sopensolaris@drydog.com * This routine makes 2 ioctl calls to remove it completely from the kernel: 12307968Sopensolaris@drydog.com * CRYPTO_UNLOAD_SOFT_MODULE - does a modunload of the KCF module 12317968Sopensolaris@drydog.com * CRYPTO_LOAD_SOFT_DISABLED - updates kernel disabled mechanism list 12327968Sopensolaris@drydog.com * 12337968Sopensolaris@drydog.com * This implements part of "cryptoadm unload" and "cryptoadm uninstall". 12340Sstevel@tonic-gate */ 12350Sstevel@tonic-gate int 12367968Sopensolaris@drydog.com unload_kef_soft(char *provname) 12370Sstevel@tonic-gate { 12387968Sopensolaris@drydog.com crypto_unload_soft_module_t *punload_soft = NULL; 12390Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 12407968Sopensolaris@drydog.com entry_t *pent = NULL; 12417968Sopensolaris@drydog.com int fd = -1; 12427968Sopensolaris@drydog.com int err; 12430Sstevel@tonic-gate 12440Sstevel@tonic-gate if (provname == NULL) { 12450Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 12460Sstevel@tonic-gate return (FAILURE); 12470Sstevel@tonic-gate } 12480Sstevel@tonic-gate 1249*10500SHai-May.Chao@Sun.COM pent = getent_kef(provname, NULL, NULL, NULL); 12507968Sopensolaris@drydog.com if (pent == NULL) { /* not in kcf.conf */ 12511971Skrishna /* Construct an entry using the provname */ 12527968Sopensolaris@drydog.com pent = create_entry(provname); 12531971Skrishna if (pent == NULL) { 12541971Skrishna cryptoerror(LOG_STDERR, gettext("out of memory.")); 12551971Skrishna return (FAILURE); 12561971Skrishna } 12570Sstevel@tonic-gate } 12580Sstevel@tonic-gate 12590Sstevel@tonic-gate /* Open the admin_ioctl_device */ 12600Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 12610Sstevel@tonic-gate err = errno; 12620Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 12630Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(err)); 12647968Sopensolaris@drydog.com free_entry(pent); 12650Sstevel@tonic-gate return (FAILURE); 12660Sstevel@tonic-gate } 12670Sstevel@tonic-gate 12680Sstevel@tonic-gate /* Inform kernel to unload this software module */ 12690Sstevel@tonic-gate if ((punload_soft = setup_unload_soft(pent)) == NULL) { 12707968Sopensolaris@drydog.com free_entry(pent); 12710Sstevel@tonic-gate (void) close(fd); 12720Sstevel@tonic-gate return (FAILURE); 12730Sstevel@tonic-gate } 12740Sstevel@tonic-gate 12750Sstevel@tonic-gate if (ioctl(fd, CRYPTO_UNLOAD_SOFT_MODULE, punload_soft) == -1) { 12760Sstevel@tonic-gate cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl failed: %s", 12770Sstevel@tonic-gate strerror(errno)); 12780Sstevel@tonic-gate free_entry(pent); 12790Sstevel@tonic-gate free(punload_soft); 12800Sstevel@tonic-gate (void) close(fd); 12810Sstevel@tonic-gate return (FAILURE); 12820Sstevel@tonic-gate } 12830Sstevel@tonic-gate 12840Sstevel@tonic-gate if (punload_soft->sm_return_value != CRYPTO_SUCCESS) { 12850Sstevel@tonic-gate cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl return_value = " 12860Sstevel@tonic-gate "%d", punload_soft->sm_return_value); 12870Sstevel@tonic-gate /* 12887334SDaniel.Anderson@Sun.COM * If the return value is CRYPTO_UNKNOWN_PROVIDER, it means 12890Sstevel@tonic-gate * that the provider is not registered yet. Should just 12900Sstevel@tonic-gate * continue. 12910Sstevel@tonic-gate */ 12920Sstevel@tonic-gate if (punload_soft->sm_return_value != CRYPTO_UNKNOWN_PROVIDER) { 12930Sstevel@tonic-gate free_entry(pent); 12940Sstevel@tonic-gate free(punload_soft); 12950Sstevel@tonic-gate (void) close(fd); 12960Sstevel@tonic-gate return (FAILURE); 12970Sstevel@tonic-gate } 12980Sstevel@tonic-gate } 12990Sstevel@tonic-gate 13000Sstevel@tonic-gate free(punload_soft); 13010Sstevel@tonic-gate 13020Sstevel@tonic-gate /* Inform kernel to remove the disabled entries if any */ 13030Sstevel@tonic-gate if (pent->dis_count == 0) { 13040Sstevel@tonic-gate free_entry(pent); 13050Sstevel@tonic-gate (void) close(fd); 13060Sstevel@tonic-gate return (SUCCESS); 13070Sstevel@tonic-gate } else { 13080Sstevel@tonic-gate free_mechlist(pent->dislist); 13090Sstevel@tonic-gate pent->dislist = NULL; 13100Sstevel@tonic-gate pent->dis_count = 0; 13110Sstevel@tonic-gate } 13120Sstevel@tonic-gate 13130Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 13140Sstevel@tonic-gate free_entry(pent); 13150Sstevel@tonic-gate (void) close(fd); 13160Sstevel@tonic-gate return (FAILURE); 13170Sstevel@tonic-gate } 13180Sstevel@tonic-gate 13190Sstevel@tonic-gate /* pent is no longer needed; free it */ 13200Sstevel@tonic-gate free_entry(pent); 13210Sstevel@tonic-gate 13220Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) { 13230Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s", 13240Sstevel@tonic-gate strerror(errno)); 13250Sstevel@tonic-gate free(pload_soft_dis); 13260Sstevel@tonic-gate (void) close(fd); 13270Sstevel@tonic-gate return (FAILURE); 13280Sstevel@tonic-gate } 13290Sstevel@tonic-gate 13300Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 13310Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = " 13320Sstevel@tonic-gate "%d", pload_soft_dis->sd_return_value); 13330Sstevel@tonic-gate free(pload_soft_dis); 13340Sstevel@tonic-gate (void) close(fd); 13350Sstevel@tonic-gate return (FAILURE); 13360Sstevel@tonic-gate } 13370Sstevel@tonic-gate 13380Sstevel@tonic-gate free(pload_soft_dis); 13390Sstevel@tonic-gate (void) close(fd); 13400Sstevel@tonic-gate return (SUCCESS); 13410Sstevel@tonic-gate } 13420Sstevel@tonic-gate 13430Sstevel@tonic-gate 13440Sstevel@tonic-gate /* 13450Sstevel@tonic-gate * Check if a hardware provider is valid. If it is valid, returns its device 13460Sstevel@tonic-gate * name, instance number and the number of mechanisms it supports. 13470Sstevel@tonic-gate */ 13480Sstevel@tonic-gate static int 13490Sstevel@tonic-gate check_hardware_provider(char *provname, char *pname, int *pnum, int *pcount) 13500Sstevel@tonic-gate { 13510Sstevel@tonic-gate crypto_get_dev_list_t *dev_list = NULL; 13520Sstevel@tonic-gate int i; 13530Sstevel@tonic-gate 13540Sstevel@tonic-gate if (provname == NULL) { 13550Sstevel@tonic-gate return (FAILURE); 13560Sstevel@tonic-gate } 13570Sstevel@tonic-gate 13580Sstevel@tonic-gate /* First, get the device name and the instance number from provname */ 13590Sstevel@tonic-gate if (split_hw_provname(provname, pname, pnum) == FAILURE) { 13600Sstevel@tonic-gate return (FAILURE); 13610Sstevel@tonic-gate } 13620Sstevel@tonic-gate 13630Sstevel@tonic-gate /* 13640Sstevel@tonic-gate * Get the complete device list from kernel and check if this provider 13650Sstevel@tonic-gate * is in the list. 13660Sstevel@tonic-gate */ 13670Sstevel@tonic-gate if (get_dev_list(&dev_list) == FAILURE) { 13680Sstevel@tonic-gate return (FAILURE); 13690Sstevel@tonic-gate } 13700Sstevel@tonic-gate 13710Sstevel@tonic-gate for (i = 0; i < dev_list->dl_dev_count; i++) { 13720Sstevel@tonic-gate if ((strcmp(dev_list->dl_devs[i].le_dev_name, pname) == 0) && 13730Sstevel@tonic-gate (dev_list->dl_devs[i].le_dev_instance == *pnum)) { 13740Sstevel@tonic-gate break; 13750Sstevel@tonic-gate } 13760Sstevel@tonic-gate } 13770Sstevel@tonic-gate 13780Sstevel@tonic-gate if (i == dev_list->dl_dev_count) { 13790Sstevel@tonic-gate /* didn't find this provider in the kernel device list */ 13800Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s does not exist."), 13810Sstevel@tonic-gate provname); 13820Sstevel@tonic-gate free(dev_list); 13830Sstevel@tonic-gate return (FAILURE); 13840Sstevel@tonic-gate } 13850Sstevel@tonic-gate 13860Sstevel@tonic-gate /* This provider is valid. Get its mechanism count */ 13870Sstevel@tonic-gate *pcount = dev_list->dl_devs[i].le_mechanism_count; 13880Sstevel@tonic-gate 13890Sstevel@tonic-gate free(dev_list); 13900Sstevel@tonic-gate return (SUCCESS); 13910Sstevel@tonic-gate } 1392*10500SHai-May.Chao@Sun.COM 1393*10500SHai-May.Chao@Sun.COM int 1394*10500SHai-May.Chao@Sun.COM fips_update_kcfconf(int action) 1395*10500SHai-May.Chao@Sun.COM { 1396*10500SHai-May.Chao@Sun.COM 1397*10500SHai-May.Chao@Sun.COM char *str; 1398*10500SHai-May.Chao@Sun.COM 1399*10500SHai-May.Chao@Sun.COM if (action == FIPS140_ENABLE) 1400*10500SHai-May.Chao@Sun.COM str = "fips-140:fips_status=enabled\n"; 1401*10500SHai-May.Chao@Sun.COM else 1402*10500SHai-May.Chao@Sun.COM str = "fips-140:fips_status=disabled\n"; 1403*10500SHai-May.Chao@Sun.COM 1404*10500SHai-May.Chao@Sun.COM if (update_conf(_PATH_KCF_CONF, str) != SUCCESS) 1405*10500SHai-May.Chao@Sun.COM return (FAILURE); 1406*10500SHai-May.Chao@Sun.COM 1407*10500SHai-May.Chao@Sun.COM return (SUCCESS); 1408*10500SHai-May.Chao@Sun.COM } 1409*10500SHai-May.Chao@Sun.COM 1410*10500SHai-May.Chao@Sun.COM void 1411*10500SHai-May.Chao@Sun.COM fips_status_kcfconf(int *status) 1412*10500SHai-May.Chao@Sun.COM { 1413*10500SHai-May.Chao@Sun.COM 1414*10500SHai-May.Chao@Sun.COM entry_t *pent = NULL; 1415*10500SHai-May.Chao@Sun.COM 1416*10500SHai-May.Chao@Sun.COM if ((pent = getent_kef(FIPS_KEYWORD, NULL, NULL, NULL)) == NULL) { 1417*10500SHai-May.Chao@Sun.COM /* 1418*10500SHai-May.Chao@Sun.COM * By default (no FIPS entry), we assume FIPS is disabled. 1419*10500SHai-May.Chao@Sun.COM */ 1420*10500SHai-May.Chao@Sun.COM *status = CRYPTO_FIPS_MODE_DISABLED; 1421*10500SHai-May.Chao@Sun.COM return; 1422*10500SHai-May.Chao@Sun.COM } 1423*10500SHai-May.Chao@Sun.COM 1424*10500SHai-May.Chao@Sun.COM if (pent->flag_fips_enabled) 1425*10500SHai-May.Chao@Sun.COM *status = CRYPTO_FIPS_MODE_ENABLED; 1426*10500SHai-May.Chao@Sun.COM else 1427*10500SHai-May.Chao@Sun.COM *status = CRYPTO_FIPS_MODE_DISABLED; 1428*10500SHai-May.Chao@Sun.COM 1429*10500SHai-May.Chao@Sun.COM return; 1430*10500SHai-May.Chao@Sun.COM 1431*10500SHai-May.Chao@Sun.COM } 1432