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 /* 2210500SHai-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*10979SHai-May.Chao@Sun.COM * Parameters phardlist and psoftlist are supplied by 4710500SHai-May.Chao@Sun.COM * get_soft_info(). 4810500SHai-May.Chao@Sun.COM * If NULL, this function obtains it by calling getent_kef() and 4910500SHai-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*10979SHai-May.Chao@Sun.COM entrylist_t *phardlist, entrylist_t *psoftlist) 540Sstevel@tonic-gate { 557968Sopensolaris@drydog.com mechlist_t *pmechlist = NULL; 567968Sopensolaris@drydog.com int rc; 570Sstevel@tonic-gate 580Sstevel@tonic-gate if (provname == NULL) { 590Sstevel@tonic-gate return (FAILURE); 600Sstevel@tonic-gate } 610Sstevel@tonic-gate 62*10979SHai-May.Chao@Sun.COM rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist); 630Sstevel@tonic-gate if (rc == SUCCESS) { 640Sstevel@tonic-gate (void) filter_mechlist(&pmechlist, RANDOM); 650Sstevel@tonic-gate print_mechlist(provname, pmechlist); 660Sstevel@tonic-gate free_mechlist(pmechlist); 670Sstevel@tonic-gate } else { 680Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 690Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 700Sstevel@tonic-gate provname); 710Sstevel@tonic-gate } 720Sstevel@tonic-gate 730Sstevel@tonic-gate return (rc); 740Sstevel@tonic-gate } 750Sstevel@tonic-gate 760Sstevel@tonic-gate /* 770Sstevel@tonic-gate * Display the mechanism list for a kernel hardware provider. 787968Sopensolaris@drydog.com * This implements part of the "cryptoadm list -m" command. 790Sstevel@tonic-gate */ 800Sstevel@tonic-gate int 810Sstevel@tonic-gate list_mechlist_for_hard(char *provname) 820Sstevel@tonic-gate { 837968Sopensolaris@drydog.com mechlist_t *pmechlist = NULL; 847968Sopensolaris@drydog.com char devname[MAXNAMELEN]; 857968Sopensolaris@drydog.com int inst_num; 867968Sopensolaris@drydog.com int count; 877968Sopensolaris@drydog.com int rc = SUCCESS; 880Sstevel@tonic-gate 890Sstevel@tonic-gate if (provname == NULL) { 900Sstevel@tonic-gate return (FAILURE); 910Sstevel@tonic-gate } 920Sstevel@tonic-gate 930Sstevel@tonic-gate /* 940Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 950Sstevel@tonic-gate * mechanisms also. 960Sstevel@tonic-gate */ 970Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) == 980Sstevel@tonic-gate FAILURE) { 990Sstevel@tonic-gate return (FAILURE); 1000Sstevel@tonic-gate } 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 1030Sstevel@tonic-gate if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) == 1040Sstevel@tonic-gate SUCCESS) { 1050Sstevel@tonic-gate (void) filter_mechlist(&pmechlist, RANDOM); 1060Sstevel@tonic-gate print_mechlist(provname, pmechlist); 1070Sstevel@tonic-gate free_mechlist(pmechlist); 1080Sstevel@tonic-gate } 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate return (rc); 1110Sstevel@tonic-gate } 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate /* 1150Sstevel@tonic-gate * Display the policy information for a kernel software provider. 1167968Sopensolaris@drydog.com * This implements part of the "cryptoadm list -p" command. 1177968Sopensolaris@drydog.com * 118*10979SHai-May.Chao@Sun.COM * Parameters phardlist and psoftlist are supplied by 11910500SHai-May.Chao@Sun.COM * getent_kef(). 12010500SHai-May.Chao@Sun.COM * If NULL, this function obtains it by calling get_kcfconf_info() 12110500SHai-May.Chao@Sun.COM * via getent_kef() internally. 1220Sstevel@tonic-gate */ 1230Sstevel@tonic-gate int 1247968Sopensolaris@drydog.com list_policy_for_soft(char *provname, 125*10979SHai-May.Chao@Sun.COM entrylist_t *phardlist, entrylist_t *psoftlist) 1260Sstevel@tonic-gate { 1277968Sopensolaris@drydog.com int rc; 1287968Sopensolaris@drydog.com entry_t *pent = NULL; 1297968Sopensolaris@drydog.com mechlist_t *pmechlist = NULL; 1307968Sopensolaris@drydog.com boolean_t has_random = B_FALSE; 1317968Sopensolaris@drydog.com boolean_t has_mechs = B_FALSE; 1327968Sopensolaris@drydog.com boolean_t in_kernel = B_FALSE; 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate if (provname == NULL) { 1350Sstevel@tonic-gate return (FAILURE); 1360Sstevel@tonic-gate } 1370Sstevel@tonic-gate 1387968Sopensolaris@drydog.com if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) { 1397968Sopensolaris@drydog.com return (FAILURE); 1407968Sopensolaris@drydog.com } else if (in_kernel == B_FALSE) { 1410Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s does not exist."), 1420Sstevel@tonic-gate provname); 1430Sstevel@tonic-gate return (FAILURE); 1440Sstevel@tonic-gate } 145*10979SHai-May.Chao@Sun.COM pent = getent_kef(provname, phardlist, psoftlist); 1460Sstevel@tonic-gate 147*10979SHai-May.Chao@Sun.COM rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist); 1480Sstevel@tonic-gate if (rc == SUCCESS) { 1490Sstevel@tonic-gate has_random = filter_mechlist(&pmechlist, RANDOM); 1500Sstevel@tonic-gate if (pmechlist != NULL) { 1510Sstevel@tonic-gate has_mechs = B_TRUE; 1520Sstevel@tonic-gate free_mechlist(pmechlist); 1530Sstevel@tonic-gate } 1540Sstevel@tonic-gate } else { 1550Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 1560Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 1570Sstevel@tonic-gate provname); 1580Sstevel@tonic-gate return (rc); 1590Sstevel@tonic-gate } 1600Sstevel@tonic-gate 1617968Sopensolaris@drydog.com print_kef_policy(provname, pent, has_random, has_mechs); 1620Sstevel@tonic-gate free_entry(pent); 1630Sstevel@tonic-gate return (SUCCESS); 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate /* 1690Sstevel@tonic-gate * Display the policy information for a kernel hardware provider. 1707968Sopensolaris@drydog.com * This implements part of the "cryptoadm list -p" command. 1717968Sopensolaris@drydog.com * 172*10979SHai-May.Chao@Sun.COM * Parameters phardlist and psoftlist are supplied by getent_kef(). 17310500SHai-May.Chao@Sun.COM * If NULL, this function obtains it by calling get_kcfconf_info() via 17410500SHai-May.Chao@Sun.COM * getent_kef() internally. 17510500SHai-May.Chao@Sun.COM * Parameter pdevlist is supplied by check_kernel_for_hard(). 17610500SHai-May.Chao@Sun.COM * If NULL, this function obtains it by calling get_dev_list() via 17710500SHai-May.Chao@Sun.COM * check_kernel_for_hard() internally. 1780Sstevel@tonic-gate */ 1790Sstevel@tonic-gate int 1807968Sopensolaris@drydog.com list_policy_for_hard(char *provname, 1817968Sopensolaris@drydog.com entrylist_t *phardlist, entrylist_t *psoftlist, 182*10979SHai-May.Chao@Sun.COM crypto_get_dev_list_t *pdevlist) 1830Sstevel@tonic-gate { 1847968Sopensolaris@drydog.com entry_t *pent = NULL; 1857968Sopensolaris@drydog.com boolean_t in_kernel; 1867968Sopensolaris@drydog.com mechlist_t *pmechlist = NULL; 1877968Sopensolaris@drydog.com char devname[MAXNAMELEN]; 1887968Sopensolaris@drydog.com int inst_num; 1897968Sopensolaris@drydog.com int count; 1907968Sopensolaris@drydog.com int rc = SUCCESS; 1917968Sopensolaris@drydog.com boolean_t has_random = B_FALSE; 1927968Sopensolaris@drydog.com boolean_t has_mechs = B_FALSE; 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate if (provname == NULL) { 1950Sstevel@tonic-gate return (FAILURE); 1960Sstevel@tonic-gate } 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate /* 1990Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 2000Sstevel@tonic-gate * mechanisms also. 2010Sstevel@tonic-gate */ 2020Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) == 2030Sstevel@tonic-gate FAILURE) { 2040Sstevel@tonic-gate return (FAILURE); 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 2080Sstevel@tonic-gate if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) == 2090Sstevel@tonic-gate SUCCESS) { 2100Sstevel@tonic-gate has_random = filter_mechlist(&pmechlist, RANDOM); 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate if (pmechlist != NULL) { 2130Sstevel@tonic-gate has_mechs = B_TRUE; 2140Sstevel@tonic-gate free_mechlist(pmechlist); 2150Sstevel@tonic-gate } 2160Sstevel@tonic-gate } else { 2170Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 2180Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 2190Sstevel@tonic-gate devname); 2200Sstevel@tonic-gate return (rc); 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate /* 2240Sstevel@tonic-gate * If the hardware provider has an entry in the kcf.conf file, 2250Sstevel@tonic-gate * some of its mechanisms must have been disabled. Print out 2260Sstevel@tonic-gate * the disabled list from the config file entry. Otherwise, 2270Sstevel@tonic-gate * if it is active, then all the mechanisms for it are enabled. 2280Sstevel@tonic-gate */ 229*10979SHai-May.Chao@Sun.COM if ((pent = getent_kef(provname, phardlist, psoftlist)) != NULL) { 2307968Sopensolaris@drydog.com print_kef_policy(provname, pent, has_random, has_mechs); 2310Sstevel@tonic-gate free_entry(pent); 2320Sstevel@tonic-gate return (SUCCESS); 2330Sstevel@tonic-gate } else { 2347968Sopensolaris@drydog.com if (check_kernel_for_hard(provname, pdevlist, 2357968Sopensolaris@drydog.com &in_kernel) == FAILURE) { 2360Sstevel@tonic-gate return (FAILURE); 2377968Sopensolaris@drydog.com } else if (in_kernel == B_TRUE) { 2380Sstevel@tonic-gate (void) printf(gettext( 2390Sstevel@tonic-gate "%s: all mechanisms are enabled."), provname); 2400Sstevel@tonic-gate if (has_random) 2410Sstevel@tonic-gate /* 2427334SDaniel.Anderson@Sun.COM * TRANSLATION_NOTE 2430Sstevel@tonic-gate * "random" is a keyword and not to be 2440Sstevel@tonic-gate * translated. 2450Sstevel@tonic-gate */ 2460Sstevel@tonic-gate (void) printf(gettext(" %s is enabled.\n"), 2470Sstevel@tonic-gate "random"); 2480Sstevel@tonic-gate else 2490Sstevel@tonic-gate (void) printf("\n"); 2500Sstevel@tonic-gate return (SUCCESS); 2510Sstevel@tonic-gate } else { 2520Sstevel@tonic-gate cryptoerror(LOG_STDERR, 2530Sstevel@tonic-gate gettext("%s does not exist."), provname); 2540Sstevel@tonic-gate return (FAILURE); 2550Sstevel@tonic-gate } 2560Sstevel@tonic-gate } 2570Sstevel@tonic-gate } 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate 2607968Sopensolaris@drydog.com /* 2617968Sopensolaris@drydog.com * Disable a kernel hardware provider. 2627968Sopensolaris@drydog.com * This implements the "cryptoadm disable" command for 2637968Sopensolaris@drydog.com * kernel hardware providers. 2647968Sopensolaris@drydog.com */ 2650Sstevel@tonic-gate int 2660Sstevel@tonic-gate disable_kef_hardware(char *provname, boolean_t rndflag, boolean_t allflag, 2670Sstevel@tonic-gate mechlist_t *dislist) 2680Sstevel@tonic-gate { 2697968Sopensolaris@drydog.com crypto_load_dev_disabled_t *pload_dev_dis = NULL; 2707968Sopensolaris@drydog.com mechlist_t *infolist = NULL; 2717968Sopensolaris@drydog.com entry_t *pent = NULL; 2727968Sopensolaris@drydog.com boolean_t new_dev_entry = B_FALSE; 2737968Sopensolaris@drydog.com char devname[MAXNAMELEN]; 2747968Sopensolaris@drydog.com int inst_num; 2757968Sopensolaris@drydog.com int count; 2767968Sopensolaris@drydog.com int fd = -1; 2777968Sopensolaris@drydog.com int rc = SUCCESS; 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate if (provname == NULL) { 2800Sstevel@tonic-gate return (FAILURE); 2810Sstevel@tonic-gate } 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate /* 2840Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 2850Sstevel@tonic-gate * mechanisms also. 2860Sstevel@tonic-gate */ 2870Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) 2880Sstevel@tonic-gate == FAILURE) { 2890Sstevel@tonic-gate return (FAILURE); 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 2930Sstevel@tonic-gate if (get_dev_info(devname, inst_num, count, &infolist) == FAILURE) { 2940Sstevel@tonic-gate return (FAILURE); 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate /* 2980Sstevel@tonic-gate * Get the entry of this hardware provider from the config file. 2990Sstevel@tonic-gate * If there is no entry yet, create one for it. 3000Sstevel@tonic-gate */ 301*10979SHai-May.Chao@Sun.COM if ((pent = getent_kef(provname, NULL, NULL)) == NULL) { 3027968Sopensolaris@drydog.com if ((pent = create_entry(provname)) == NULL) { 3030Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("out of memory.")); 3040Sstevel@tonic-gate free_mechlist(infolist); 3050Sstevel@tonic-gate return (FAILURE); 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate new_dev_entry = B_TRUE; 3080Sstevel@tonic-gate } 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate /* 3110Sstevel@tonic-gate * kCF treats random as an internal mechanism. So, we need to 3120Sstevel@tonic-gate * filter it from the mechanism list here, if we are NOT disabling 3130Sstevel@tonic-gate * or enabling the random feature. Note that we map random feature at 3140Sstevel@tonic-gate * cryptoadm(1M) level to the "random" mechanism in kCF. 3150Sstevel@tonic-gate */ 3160Sstevel@tonic-gate if (!rndflag) { 3172860Smcpowers (void) filter_mechlist(&dislist, RANDOM); 3180Sstevel@tonic-gate } 3190Sstevel@tonic-gate 3200Sstevel@tonic-gate /* Calculate the new disabled list */ 3210Sstevel@tonic-gate if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) { 3222860Smcpowers free_mechlist(infolist); 3230Sstevel@tonic-gate free_entry(pent); 3240Sstevel@tonic-gate return (FAILURE); 3250Sstevel@tonic-gate } 3262860Smcpowers free_mechlist(infolist); 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate /* If no mechanisms are to be disabled, return */ 3290Sstevel@tonic-gate if (pent->dis_count == 0) { 3300Sstevel@tonic-gate free_entry(pent); 3310Sstevel@tonic-gate return (SUCCESS); 3320Sstevel@tonic-gate } 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate /* Update the config file with the new entry or the updated entry */ 3350Sstevel@tonic-gate if (new_dev_entry) { 3360Sstevel@tonic-gate rc = update_kcfconf(pent, ADD_MODE); 3370Sstevel@tonic-gate } else { 3380Sstevel@tonic-gate rc = update_kcfconf(pent, MODIFY_MODE); 3390Sstevel@tonic-gate } 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate if (rc == FAILURE) { 3420Sstevel@tonic-gate free_entry(pent); 3430Sstevel@tonic-gate return (FAILURE); 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate /* Inform kernel about the new disabled mechanism list */ 3470Sstevel@tonic-gate if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) { 3480Sstevel@tonic-gate free_entry(pent); 3490Sstevel@tonic-gate return (FAILURE); 3500Sstevel@tonic-gate } 3510Sstevel@tonic-gate free_entry(pent); 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 3540Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 3550Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 3560Sstevel@tonic-gate free(pload_dev_dis); 3570Sstevel@tonic-gate return (FAILURE); 3580Sstevel@tonic-gate } 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) { 3610Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: %s", 3620Sstevel@tonic-gate strerror(errno)); 3630Sstevel@tonic-gate free(pload_dev_dis); 3640Sstevel@tonic-gate (void) close(fd); 3650Sstevel@tonic-gate return (FAILURE); 3660Sstevel@tonic-gate } 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 3690Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl return_value = " 3700Sstevel@tonic-gate "%d", pload_dev_dis->dd_return_value); 3710Sstevel@tonic-gate free(pload_dev_dis); 3720Sstevel@tonic-gate (void) close(fd); 3730Sstevel@tonic-gate return (FAILURE); 3740Sstevel@tonic-gate } 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate free(pload_dev_dis); 3770Sstevel@tonic-gate (void) close(fd); 3780Sstevel@tonic-gate return (SUCCESS); 3790Sstevel@tonic-gate } 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate 3827968Sopensolaris@drydog.com /* 3837968Sopensolaris@drydog.com * Disable a kernel software provider. 3847968Sopensolaris@drydog.com * This implements the "cryptoadm disable" command for 3857968Sopensolaris@drydog.com * kernel software providers. 3867968Sopensolaris@drydog.com */ 3870Sstevel@tonic-gate int 3880Sstevel@tonic-gate disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag, 3890Sstevel@tonic-gate mechlist_t *dislist) 3900Sstevel@tonic-gate { 3910Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 3927968Sopensolaris@drydog.com mechlist_t *infolist = NULL; 3937968Sopensolaris@drydog.com entry_t *pent = NULL; 3947968Sopensolaris@drydog.com entrylist_t *phardlist = NULL; 3957968Sopensolaris@drydog.com entrylist_t *psoftlist = NULL; 3967968Sopensolaris@drydog.com boolean_t in_kernel = B_FALSE; 3977968Sopensolaris@drydog.com int fd = -1; 3987968Sopensolaris@drydog.com int rc = SUCCESS; 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate if (provname == NULL) { 4010Sstevel@tonic-gate return (FAILURE); 4020Sstevel@tonic-gate } 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate /* 4050Sstevel@tonic-gate * Check if the kernel software provider is currently unloaded. 4060Sstevel@tonic-gate * If it is unloaded, return FAILURE, because the disable subcommand 4070Sstevel@tonic-gate * can not perform on inactive (unloaded) providers. 4080Sstevel@tonic-gate */ 409*10979SHai-May.Chao@Sun.COM if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) { 4107968Sopensolaris@drydog.com return (FAILURE); 4117968Sopensolaris@drydog.com } else if (in_kernel == B_FALSE) { 4127968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, 4137968Sopensolaris@drydog.com gettext("%s is not loaded or does not exist."), 4147968Sopensolaris@drydog.com provname); 4150Sstevel@tonic-gate return (FAILURE); 4167968Sopensolaris@drydog.com } 4177968Sopensolaris@drydog.com 418*10979SHai-May.Chao@Sun.COM if (get_kcfconf_info(&phardlist, &psoftlist) == FAILURE) { 4197968Sopensolaris@drydog.com cryptoerror(LOG_ERR, 4207968Sopensolaris@drydog.com "failed to retrieve the providers' " 4217968Sopensolaris@drydog.com "information from the configuration file - %s.", 4227968Sopensolaris@drydog.com _PATH_KCF_CONF); 4230Sstevel@tonic-gate return (FAILURE); 4240Sstevel@tonic-gate } 4250Sstevel@tonic-gate 4267968Sopensolaris@drydog.com /* 4277968Sopensolaris@drydog.com * Get the entry of this provider from the kcf.conf file, if any. 4287968Sopensolaris@drydog.com * Otherwise, create a new kcf.conf entry for writing back to the file. 4297968Sopensolaris@drydog.com */ 430*10979SHai-May.Chao@Sun.COM pent = getent_kef(provname, phardlist, psoftlist); 4317968Sopensolaris@drydog.com if (pent == NULL) { /* create a new entry */ 4327968Sopensolaris@drydog.com pent = create_entry(provname); 4337968Sopensolaris@drydog.com if (pent == NULL) { 4347968Sopensolaris@drydog.com cryptodebug("out of memory."); 4357968Sopensolaris@drydog.com rc = FAILURE; 4367968Sopensolaris@drydog.com goto out; 4377968Sopensolaris@drydog.com } 4380Sstevel@tonic-gate } 4390Sstevel@tonic-gate 4407968Sopensolaris@drydog.com /* Get the mechanism list for the software provider from the kernel */ 441*10979SHai-May.Chao@Sun.COM if (get_soft_info(provname, &infolist, phardlist, psoftlist) == 442*10979SHai-May.Chao@Sun.COM FAILURE) { 4437968Sopensolaris@drydog.com rc = FAILURE; 4447968Sopensolaris@drydog.com goto out; 4457968Sopensolaris@drydog.com } 4467968Sopensolaris@drydog.com 4477968Sopensolaris@drydog.com if ((infolist != NULL) && (infolist->name[0] != '\0')) { 4487968Sopensolaris@drydog.com /* 4497968Sopensolaris@drydog.com * Replace the supportedlist from kcf.conf with possibly 4507968Sopensolaris@drydog.com * more-up-to-date list from the kernel. This is the case 4517968Sopensolaris@drydog.com * for default software providers that had more mechanisms 4527968Sopensolaris@drydog.com * added in the current version of the kernel. 4537968Sopensolaris@drydog.com */ 4547968Sopensolaris@drydog.com free_mechlist(pent->suplist); 4557968Sopensolaris@drydog.com pent->suplist = infolist; 4567968Sopensolaris@drydog.com } 4577968Sopensolaris@drydog.com 4587968Sopensolaris@drydog.com /* 4597968Sopensolaris@drydog.com * kCF treats random as an internal mechanism. So, we need to 4607968Sopensolaris@drydog.com * filter it from the mechanism list here, if we are NOT disabling 4617968Sopensolaris@drydog.com * or enabling the random feature. Note that we map random feature at 4627968Sopensolaris@drydog.com * cryptoadm(1M) level to the "random" mechanism in kCF. 4637968Sopensolaris@drydog.com */ 4640Sstevel@tonic-gate if (!rndflag) { 4650Sstevel@tonic-gate (void) filter_mechlist(&infolist, RANDOM); 4660Sstevel@tonic-gate } 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate /* Calculate the new disabled list */ 4690Sstevel@tonic-gate if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) { 4707968Sopensolaris@drydog.com rc = FAILURE; 4717968Sopensolaris@drydog.com goto out; 4720Sstevel@tonic-gate } 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate /* Update the kcf.conf file with the updated entry */ 4750Sstevel@tonic-gate if (update_kcfconf(pent, MODIFY_MODE) == FAILURE) { 4767968Sopensolaris@drydog.com rc = FAILURE; 4777968Sopensolaris@drydog.com goto out; 4780Sstevel@tonic-gate } 4790Sstevel@tonic-gate 4807968Sopensolaris@drydog.com /* Setup argument to inform kernel about the new disabled list. */ 4810Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 4827968Sopensolaris@drydog.com rc = FAILURE; 4837968Sopensolaris@drydog.com goto out; 4840Sstevel@tonic-gate } 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 4870Sstevel@tonic-gate cryptoerror(LOG_STDERR, 4880Sstevel@tonic-gate gettext("failed to open %s for RW: %s"), 4890Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 4907968Sopensolaris@drydog.com rc = FAILURE; 4917968Sopensolaris@drydog.com goto out; 4920Sstevel@tonic-gate } 4930Sstevel@tonic-gate 4947968Sopensolaris@drydog.com /* Inform kernel about the new disabled list. */ 4950Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) { 4960Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s", 4970Sstevel@tonic-gate strerror(errno)); 4987968Sopensolaris@drydog.com rc = FAILURE; 4997968Sopensolaris@drydog.com goto out; 5000Sstevel@tonic-gate } 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 5030Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = " 5040Sstevel@tonic-gate "%d", pload_soft_dis->sd_return_value); 5057968Sopensolaris@drydog.com rc = FAILURE; 5067968Sopensolaris@drydog.com goto out; 5070Sstevel@tonic-gate } 5080Sstevel@tonic-gate 5097968Sopensolaris@drydog.com out: 5107968Sopensolaris@drydog.com free_entrylist(phardlist); 5117968Sopensolaris@drydog.com free_entrylist(psoftlist); 5127968Sopensolaris@drydog.com free_mechlist(infolist); 5137968Sopensolaris@drydog.com free_entry(pent); 5140Sstevel@tonic-gate free(pload_soft_dis); 5157968Sopensolaris@drydog.com if (fd != -1) 5167968Sopensolaris@drydog.com (void) close(fd); 5177968Sopensolaris@drydog.com return (rc); 5180Sstevel@tonic-gate } 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate 5217968Sopensolaris@drydog.com /* 5227968Sopensolaris@drydog.com * Enable a kernel software or hardware provider. 5237968Sopensolaris@drydog.com * This implements the "cryptoadm enable" command for kernel providers. 5247968Sopensolaris@drydog.com */ 5250Sstevel@tonic-gate int 5260Sstevel@tonic-gate enable_kef(char *provname, boolean_t rndflag, boolean_t allflag, 5270Sstevel@tonic-gate mechlist_t *mlist) 5280Sstevel@tonic-gate { 5290Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 5300Sstevel@tonic-gate crypto_load_dev_disabled_t *pload_dev_dis = NULL; 5317968Sopensolaris@drydog.com entry_t *pent = NULL; 5327968Sopensolaris@drydog.com boolean_t redo_flag = B_FALSE; 5337968Sopensolaris@drydog.com boolean_t in_kernel = B_FALSE; 5347968Sopensolaris@drydog.com int fd = -1; 5357968Sopensolaris@drydog.com int rc = SUCCESS; 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate 5387968Sopensolaris@drydog.com /* Get the entry of this provider from the kcf.conf file, if any. */ 539*10979SHai-May.Chao@Sun.COM pent = getent_kef(provname, NULL, NULL); 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate if (is_device(provname)) { 5420Sstevel@tonic-gate if (pent == NULL) { 5430Sstevel@tonic-gate /* 5440Sstevel@tonic-gate * This device doesn't have an entry in the config 5450Sstevel@tonic-gate * file, therefore nothing is disabled. 5460Sstevel@tonic-gate */ 5470Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 5480Sstevel@tonic-gate "all mechanisms are enabled already for %s."), 5490Sstevel@tonic-gate provname); 5507968Sopensolaris@drydog.com free_entry(pent); 5510Sstevel@tonic-gate return (SUCCESS); 5520Sstevel@tonic-gate } 5530Sstevel@tonic-gate } else { /* a software module */ 5547968Sopensolaris@drydog.com if (check_kernel_for_soft(provname, NULL, &in_kernel) == 5557968Sopensolaris@drydog.com FAILURE) { 5567968Sopensolaris@drydog.com free_entry(pent); 5570Sstevel@tonic-gate return (FAILURE); 5587968Sopensolaris@drydog.com } else if (in_kernel == B_FALSE) { 5597968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext("%s does not exist."), 5607968Sopensolaris@drydog.com provname); 5617968Sopensolaris@drydog.com free_entry(pent); 5627968Sopensolaris@drydog.com return (FAILURE); 5637968Sopensolaris@drydog.com } else if ((pent == NULL) || (pent->dis_count == 0)) { 5640Sstevel@tonic-gate /* nothing to be enabled. */ 5650Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 5660Sstevel@tonic-gate "all mechanisms are enabled already for %s."), 5670Sstevel@tonic-gate provname); 5680Sstevel@tonic-gate free_entry(pent); 5690Sstevel@tonic-gate return (SUCCESS); 5700Sstevel@tonic-gate } 5710Sstevel@tonic-gate } 5720Sstevel@tonic-gate 5737968Sopensolaris@drydog.com /* 5747968Sopensolaris@drydog.com * kCF treats random as an internal mechanism. So, we need to 5757968Sopensolaris@drydog.com * filter it from the mechanism list here, if we are NOT disabling 5767968Sopensolaris@drydog.com * or enabling the random feature. Note that we map random feature at 5777968Sopensolaris@drydog.com * cryptoadm(1M) level to the "random" mechanism in kCF. 5787968Sopensolaris@drydog.com */ 5790Sstevel@tonic-gate if (!rndflag) { 5800Sstevel@tonic-gate redo_flag = filter_mechlist(&pent->dislist, RANDOM); 5810Sstevel@tonic-gate if (redo_flag) 5820Sstevel@tonic-gate pent->dis_count--; 5830Sstevel@tonic-gate } 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate /* Update the entry by enabling mechanisms for this provider */ 5860Sstevel@tonic-gate if ((rc = enable_mechs(&pent, allflag, mlist)) != SUCCESS) { 5870Sstevel@tonic-gate free_entry(pent); 5880Sstevel@tonic-gate return (rc); 5890Sstevel@tonic-gate } 5900Sstevel@tonic-gate 5910Sstevel@tonic-gate if (redo_flag) { 5920Sstevel@tonic-gate mechlist_t *tmp; 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate if ((tmp = create_mech(RANDOM)) == NULL) { 5950Sstevel@tonic-gate free_entry(pent); 5960Sstevel@tonic-gate return (FAILURE); 5970Sstevel@tonic-gate } 5980Sstevel@tonic-gate tmp->next = pent->dislist; 5990Sstevel@tonic-gate pent->dislist = tmp; 6000Sstevel@tonic-gate pent->dis_count++; 6010Sstevel@tonic-gate } 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate /* 6047968Sopensolaris@drydog.com * Update the kcf.conf file with the updated entry. 6050Sstevel@tonic-gate * For a hardware provider, if there is no more disabled mechanism, 6067968Sopensolaris@drydog.com * remove the entire kcf.conf entry. 6070Sstevel@tonic-gate */ 6080Sstevel@tonic-gate if (is_device(pent->name) && (pent->dis_count == 0)) { 6090Sstevel@tonic-gate rc = update_kcfconf(pent, DELETE_MODE); 6100Sstevel@tonic-gate } else { 6110Sstevel@tonic-gate rc = update_kcfconf(pent, MODIFY_MODE); 6120Sstevel@tonic-gate } 6130Sstevel@tonic-gate 6140Sstevel@tonic-gate if (rc == FAILURE) { 6150Sstevel@tonic-gate free_entry(pent); 6160Sstevel@tonic-gate return (FAILURE); 6170Sstevel@tonic-gate } 6180Sstevel@tonic-gate 6190Sstevel@tonic-gate 6200Sstevel@tonic-gate /* Inform Kernel about the policy change */ 6210Sstevel@tonic-gate 6220Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 6230Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 6240Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 6257968Sopensolaris@drydog.com free_entry(pent); 6260Sstevel@tonic-gate return (FAILURE); 6270Sstevel@tonic-gate } 6280Sstevel@tonic-gate 6290Sstevel@tonic-gate if (is_device(provname)) { 6300Sstevel@tonic-gate /* LOAD_DEV_DISABLED */ 6310Sstevel@tonic-gate if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) { 6327968Sopensolaris@drydog.com free_entry(pent); 6330Sstevel@tonic-gate return (FAILURE); 6340Sstevel@tonic-gate } 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) { 6370Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: " 6380Sstevel@tonic-gate "%s", strerror(errno)); 6397968Sopensolaris@drydog.com free_entry(pent); 6400Sstevel@tonic-gate free(pload_dev_dis); 6410Sstevel@tonic-gate (void) close(fd); 6420Sstevel@tonic-gate return (FAILURE); 6430Sstevel@tonic-gate } 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 6460Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 6470Sstevel@tonic-gate "return_value = %d", 6480Sstevel@tonic-gate pload_dev_dis->dd_return_value); 6497968Sopensolaris@drydog.com free_entry(pent); 6500Sstevel@tonic-gate free(pload_dev_dis); 6510Sstevel@tonic-gate (void) close(fd); 6520Sstevel@tonic-gate return (FAILURE); 6530Sstevel@tonic-gate } 6540Sstevel@tonic-gate 6557968Sopensolaris@drydog.com } else { /* a software module */ 6560Sstevel@tonic-gate /* LOAD_SOFT_DISABLED */ 6570Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 6587968Sopensolaris@drydog.com free_entry(pent); 6590Sstevel@tonic-gate return (FAILURE); 6600Sstevel@tonic-gate } 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) 6630Sstevel@tonic-gate == -1) { 6640Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: " 6650Sstevel@tonic-gate "%s", strerror(errno)); 6667968Sopensolaris@drydog.com free_entry(pent); 6670Sstevel@tonic-gate free(pload_soft_dis); 6680Sstevel@tonic-gate (void) close(fd); 6690Sstevel@tonic-gate return (FAILURE); 6700Sstevel@tonic-gate } 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 6730Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 6740Sstevel@tonic-gate "return_value = %d", 6750Sstevel@tonic-gate pload_soft_dis->sd_return_value); 6767968Sopensolaris@drydog.com free_entry(pent); 6770Sstevel@tonic-gate free(pload_soft_dis); 6780Sstevel@tonic-gate (void) close(fd); 6790Sstevel@tonic-gate return (FAILURE); 6800Sstevel@tonic-gate } 6810Sstevel@tonic-gate } 6820Sstevel@tonic-gate 6837968Sopensolaris@drydog.com free_entry(pent); 6847968Sopensolaris@drydog.com free(pload_soft_dis); 6850Sstevel@tonic-gate (void) close(fd); 6860Sstevel@tonic-gate return (SUCCESS); 6870Sstevel@tonic-gate } 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate /* 6910Sstevel@tonic-gate * Install a software module with the specified mechanism list into the system. 6920Sstevel@tonic-gate * This routine adds an entry into the config file for this software module 6930Sstevel@tonic-gate * first, then makes a CRYPTO_LOAD_SOFT_CONFIG ioctl call to inform kernel 6940Sstevel@tonic-gate * about the new addition. 6950Sstevel@tonic-gate */ 6960Sstevel@tonic-gate int 6970Sstevel@tonic-gate install_kef(char *provname, mechlist_t *mlist) 6980Sstevel@tonic-gate { 6990Sstevel@tonic-gate crypto_load_soft_config_t *pload_soft_conf = NULL; 7007968Sopensolaris@drydog.com boolean_t found; 7017968Sopensolaris@drydog.com entry_t *pent = NULL; 7027968Sopensolaris@drydog.com FILE *pfile = NULL; 7037968Sopensolaris@drydog.com FILE *pfile_tmp = NULL; 7047968Sopensolaris@drydog.com char tmpfile_name[MAXPATHLEN]; 7057968Sopensolaris@drydog.com char *ptr; 7067968Sopensolaris@drydog.com char *str; 7077968Sopensolaris@drydog.com char *name; 7087968Sopensolaris@drydog.com char buffer[BUFSIZ]; 7097968Sopensolaris@drydog.com char buffer2[BUFSIZ]; 7107968Sopensolaris@drydog.com int found_count; 7117968Sopensolaris@drydog.com int fd = -1; 7127968Sopensolaris@drydog.com int rc = SUCCESS; 7137968Sopensolaris@drydog.com int err; 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate if ((provname == NULL) || (mlist == NULL)) { 7160Sstevel@tonic-gate return (FAILURE); 7170Sstevel@tonic-gate } 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate /* Check if the provider already exists */ 720*10979SHai-May.Chao@Sun.COM if ((pent = getent_kef(provname, NULL, NULL)) != NULL) { 7210Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s exists already."), 7220Sstevel@tonic-gate provname); 7230Sstevel@tonic-gate free_entry(pent); 7240Sstevel@tonic-gate return (FAILURE); 7250Sstevel@tonic-gate } 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate /* Create an entry with provname and mlist. */ 7287968Sopensolaris@drydog.com if ((pent = create_entry(provname)) == NULL) { 7290Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("out of memory.")); 7300Sstevel@tonic-gate return (FAILURE); 7310Sstevel@tonic-gate } 7320Sstevel@tonic-gate pent->sup_count = get_mech_count(mlist); 7330Sstevel@tonic-gate pent->suplist = mlist; 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate /* Append an entry for this software module to the kcf.conf file. */ 7360Sstevel@tonic-gate if ((str = ent2str(pent)) == NULL) { 7370Sstevel@tonic-gate free_entry(pent); 7380Sstevel@tonic-gate return (FAILURE); 7390Sstevel@tonic-gate } 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) { 7420Sstevel@tonic-gate err = errno; 7430Sstevel@tonic-gate cryptoerror(LOG_STDERR, 7440Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 7450Sstevel@tonic-gate strerror(err)); 7460Sstevel@tonic-gate cryptodebug("failed to open %s for write.", _PATH_KCF_CONF); 7470Sstevel@tonic-gate free_entry(pent); 7480Sstevel@tonic-gate return (FAILURE); 7490Sstevel@tonic-gate } 7500Sstevel@tonic-gate 7510Sstevel@tonic-gate if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 7520Sstevel@tonic-gate err = errno; 7530Sstevel@tonic-gate cryptoerror(LOG_STDERR, 7540Sstevel@tonic-gate gettext("failed to lock the configuration - %s"), 7550Sstevel@tonic-gate strerror(err)); 7560Sstevel@tonic-gate free_entry(pent); 7570Sstevel@tonic-gate (void) fclose(pfile); 7580Sstevel@tonic-gate return (FAILURE); 7590Sstevel@tonic-gate } 7600Sstevel@tonic-gate 7610Sstevel@tonic-gate /* 7620Sstevel@tonic-gate * Create a temporary file in the /etc/crypto directory. 7630Sstevel@tonic-gate */ 7640Sstevel@tonic-gate (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 7650Sstevel@tonic-gate if (mkstemp(tmpfile_name) == -1) { 7660Sstevel@tonic-gate err = errno; 7670Sstevel@tonic-gate cryptoerror(LOG_STDERR, 7680Sstevel@tonic-gate gettext("failed to create a temporary file - %s"), 7690Sstevel@tonic-gate strerror(err)); 7700Sstevel@tonic-gate free_entry(pent); 7710Sstevel@tonic-gate (void) fclose(pfile); 7720Sstevel@tonic-gate return (FAILURE); 7730Sstevel@tonic-gate } 7740Sstevel@tonic-gate 7750Sstevel@tonic-gate if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 7760Sstevel@tonic-gate err = errno; 7770Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 7780Sstevel@tonic-gate tmpfile_name, 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 7850Sstevel@tonic-gate /* 7860Sstevel@tonic-gate * Loop thru the config file. If the provider was reserved within a 7870Sstevel@tonic-gate * package bracket, just uncomment it. Otherwise, append it at 7880Sstevel@tonic-gate * the end. The resulting file will be saved in the temp file first. 7890Sstevel@tonic-gate */ 7900Sstevel@tonic-gate found_count = 0; 7910Sstevel@tonic-gate rc = SUCCESS; 7920Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) { 7930Sstevel@tonic-gate found = B_FALSE; 7940Sstevel@tonic-gate if (buffer[0] == '#') { 7950Sstevel@tonic-gate (void) strlcpy(buffer2, buffer, BUFSIZ); 7960Sstevel@tonic-gate ptr = buffer2; 7970Sstevel@tonic-gate ptr++; 7980Sstevel@tonic-gate if ((name = strtok(ptr, SEP_COLON)) == NULL) { 7990Sstevel@tonic-gate rc = FAILURE; 8000Sstevel@tonic-gate break; 8010Sstevel@tonic-gate } else if (strcmp(provname, name) == 0) { 8020Sstevel@tonic-gate found = B_TRUE; 8030Sstevel@tonic-gate found_count++; 8040Sstevel@tonic-gate } 8050Sstevel@tonic-gate } 8060Sstevel@tonic-gate 8070Sstevel@tonic-gate if (found == B_FALSE) { 8080Sstevel@tonic-gate if (fputs(buffer, pfile_tmp) == EOF) { 8090Sstevel@tonic-gate rc = FAILURE; 8100Sstevel@tonic-gate } 8110Sstevel@tonic-gate } else { 8120Sstevel@tonic-gate if (found_count == 1) { 8130Sstevel@tonic-gate if (fputs(str, pfile_tmp) == EOF) { 8140Sstevel@tonic-gate rc = FAILURE; 8150Sstevel@tonic-gate } 8160Sstevel@tonic-gate } else { 8170Sstevel@tonic-gate /* 8180Sstevel@tonic-gate * Found a second entry with #libname. 8197968Sopensolaris@drydog.com * Should not happen. The kcf.conf file 8200Sstevel@tonic-gate * is corrupted. Give a warning and skip 8210Sstevel@tonic-gate * this entry. 8220Sstevel@tonic-gate */ 8230Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8240Sstevel@tonic-gate "(Warning) Found an additional reserved " 8250Sstevel@tonic-gate "entry for %s."), provname); 8260Sstevel@tonic-gate } 8270Sstevel@tonic-gate } 8280Sstevel@tonic-gate 8290Sstevel@tonic-gate if (rc == FAILURE) { 8300Sstevel@tonic-gate break; 8310Sstevel@tonic-gate } 8320Sstevel@tonic-gate } 8330Sstevel@tonic-gate (void) fclose(pfile); 8340Sstevel@tonic-gate 8350Sstevel@tonic-gate if (rc == FAILURE) { 8360Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("write error.")); 8370Sstevel@tonic-gate (void) fclose(pfile_tmp); 8380Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 8390Sstevel@tonic-gate err = errno; 8400Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8410Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), tmpfile_name, 8420Sstevel@tonic-gate strerror(err)); 8430Sstevel@tonic-gate } 8440Sstevel@tonic-gate free_entry(pent); 8450Sstevel@tonic-gate return (FAILURE); 8460Sstevel@tonic-gate } 8470Sstevel@tonic-gate 8480Sstevel@tonic-gate if (found_count == 0) { 8490Sstevel@tonic-gate /* 8500Sstevel@tonic-gate * This libname was not in package before, append it to the 8510Sstevel@tonic-gate * end of the temp file. 8520Sstevel@tonic-gate */ 8530Sstevel@tonic-gate if (fputs(str, pfile_tmp) == EOF) { 8540Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8550Sstevel@tonic-gate "failed to write to %s: %s"), tmpfile_name, 8560Sstevel@tonic-gate strerror(errno)); 8570Sstevel@tonic-gate (void) fclose(pfile_tmp); 8580Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 8590Sstevel@tonic-gate err = errno; 8600Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8610Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 8620Sstevel@tonic-gate tmpfile_name, strerror(err)); 8630Sstevel@tonic-gate } 8640Sstevel@tonic-gate free_entry(pent); 8650Sstevel@tonic-gate return (FAILURE); 8660Sstevel@tonic-gate } 8670Sstevel@tonic-gate } 8680Sstevel@tonic-gate 8690Sstevel@tonic-gate if (fclose(pfile_tmp) != 0) { 8700Sstevel@tonic-gate err = errno; 8710Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8720Sstevel@tonic-gate gettext("failed to close %s: %s"), tmpfile_name, 8730Sstevel@tonic-gate strerror(err)); 8747968Sopensolaris@drydog.com free_entry(pent); 8750Sstevel@tonic-gate return (FAILURE); 8760Sstevel@tonic-gate } 8770Sstevel@tonic-gate 8780Sstevel@tonic-gate if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) { 8790Sstevel@tonic-gate err = errno; 8800Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8810Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 8827968Sopensolaris@drydog.com strerror(err)); 8830Sstevel@tonic-gate cryptodebug("failed to rename %s to %s: %s", tmpfile_name, 8840Sstevel@tonic-gate _PATH_KCF_CONF, strerror(err)); 8850Sstevel@tonic-gate rc = FAILURE; 8860Sstevel@tonic-gate } else if (chmod(_PATH_KCF_CONF, 8870Sstevel@tonic-gate S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 8880Sstevel@tonic-gate err = errno; 8890Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8900Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 8910Sstevel@tonic-gate strerror(err)); 8920Sstevel@tonic-gate cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF, 8930Sstevel@tonic-gate strerror(err)); 8940Sstevel@tonic-gate rc = FAILURE; 8950Sstevel@tonic-gate } else { 8960Sstevel@tonic-gate rc = SUCCESS; 8970Sstevel@tonic-gate } 8980Sstevel@tonic-gate 8990Sstevel@tonic-gate if (rc == FAILURE) { 9000Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 9010Sstevel@tonic-gate err = errno; 9020Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 9030Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 9040Sstevel@tonic-gate tmpfile_name, strerror(err)); 9050Sstevel@tonic-gate } 9067968Sopensolaris@drydog.com free_entry(pent); 9070Sstevel@tonic-gate return (FAILURE); 9080Sstevel@tonic-gate } 9090Sstevel@tonic-gate 9100Sstevel@tonic-gate 9110Sstevel@tonic-gate /* Inform kernel of this new software module. */ 9120Sstevel@tonic-gate 9130Sstevel@tonic-gate if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) { 9140Sstevel@tonic-gate free_entry(pent); 9150Sstevel@tonic-gate return (FAILURE); 9160Sstevel@tonic-gate } 9170Sstevel@tonic-gate 9180Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 9190Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 9200Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 9210Sstevel@tonic-gate free_entry(pent); 9220Sstevel@tonic-gate free(pload_soft_conf); 9230Sstevel@tonic-gate return (FAILURE); 9240Sstevel@tonic-gate } 9250Sstevel@tonic-gate 9260Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) { 9270Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 9280Sstevel@tonic-gate strerror(errno)); 9290Sstevel@tonic-gate free_entry(pent); 9300Sstevel@tonic-gate free(pload_soft_conf); 9310Sstevel@tonic-gate (void) close(fd); 9320Sstevel@tonic-gate return (FAILURE); 9330Sstevel@tonic-gate } 9340Sstevel@tonic-gate 9350Sstevel@tonic-gate if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 9360Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed, " 9370Sstevel@tonic-gate "return_value = %d", pload_soft_conf->sc_return_value); 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 free_entry(pent); 9450Sstevel@tonic-gate free(pload_soft_conf); 9460Sstevel@tonic-gate (void) close(fd); 9470Sstevel@tonic-gate return (SUCCESS); 9480Sstevel@tonic-gate } 9490Sstevel@tonic-gate 9500Sstevel@tonic-gate /* 9510Sstevel@tonic-gate * Uninstall the software module. This routine first unloads the software 9520Sstevel@tonic-gate * module with 3 ioctl calls, then deletes its entry from the config file. 9530Sstevel@tonic-gate * Removing an entry from the config file needs to be done last to ensure 9540Sstevel@tonic-gate * that there is still an entry if the earlier unload failed for any reason. 9550Sstevel@tonic-gate */ 9560Sstevel@tonic-gate int 9570Sstevel@tonic-gate uninstall_kef(char *provname) 9580Sstevel@tonic-gate { 9597968Sopensolaris@drydog.com entry_t *pent = NULL; 9607968Sopensolaris@drydog.com int rc = SUCCESS; 9617968Sopensolaris@drydog.com boolean_t in_kernel = B_FALSE; 9627968Sopensolaris@drydog.com boolean_t in_kcfconf = B_FALSE; 9637968Sopensolaris@drydog.com int fd = -1; 9647968Sopensolaris@drydog.com crypto_load_soft_config_t *pload_soft_conf = NULL; 9650Sstevel@tonic-gate 9667968Sopensolaris@drydog.com /* Check to see if the provider exists first. */ 9677968Sopensolaris@drydog.com if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) { 9680Sstevel@tonic-gate return (FAILURE); 9697968Sopensolaris@drydog.com } else if (in_kernel == B_FALSE) { 9707968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext("%s does not exist."), 9717968Sopensolaris@drydog.com provname); 9720Sstevel@tonic-gate return (FAILURE); 9730Sstevel@tonic-gate } 9740Sstevel@tonic-gate 9750Sstevel@tonic-gate /* 9767968Sopensolaris@drydog.com * If it is loaded, unload it first. This does 2 ioctl calls: 9777968Sopensolaris@drydog.com * CRYPTO_UNLOAD_SOFT_MODULE and CRYPTO_LOAD_SOFT_DISABLED. 9780Sstevel@tonic-gate */ 9797968Sopensolaris@drydog.com if (unload_kef_soft(provname) == FAILURE) { 9800Sstevel@tonic-gate cryptoerror(LOG_STDERR, 9817968Sopensolaris@drydog.com gettext("failed to unload %s during uninstall.\n"), 9827968Sopensolaris@drydog.com provname); 9830Sstevel@tonic-gate return (FAILURE); 9840Sstevel@tonic-gate } 9850Sstevel@tonic-gate 9860Sstevel@tonic-gate /* 9877968Sopensolaris@drydog.com * Inform kernel to remove the configuration of this software module. 9880Sstevel@tonic-gate */ 9890Sstevel@tonic-gate 9907968Sopensolaris@drydog.com /* Setup ioctl() parameter */ 991*10979SHai-May.Chao@Sun.COM pent = getent_kef(provname, NULL, NULL); 9927968Sopensolaris@drydog.com if (pent != NULL) { /* in kcf.conf */ 9937968Sopensolaris@drydog.com in_kcfconf = B_TRUE; 9947968Sopensolaris@drydog.com free_mechlist(pent->suplist); 9957968Sopensolaris@drydog.com pent->suplist = NULL; 9967968Sopensolaris@drydog.com pent->sup_count = 0; 9977968Sopensolaris@drydog.com } else if ((pent = create_entry(provname)) == NULL) { 9987968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext("out of memory.")); 9997968Sopensolaris@drydog.com return (FAILURE); 10007968Sopensolaris@drydog.com } 10017968Sopensolaris@drydog.com if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) { 10027968Sopensolaris@drydog.com free_entry(pent); 10037968Sopensolaris@drydog.com return (FAILURE); 10040Sstevel@tonic-gate } 10050Sstevel@tonic-gate 10067968Sopensolaris@drydog.com /* Open the /dev/cryptoadm device */ 10077968Sopensolaris@drydog.com if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 10087968Sopensolaris@drydog.com int err = errno; 10097968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 10107968Sopensolaris@drydog.com ADMIN_IOCTL_DEVICE, strerror(err)); 10117968Sopensolaris@drydog.com free_entry(pent); 10127968Sopensolaris@drydog.com free(pload_soft_conf); 10137968Sopensolaris@drydog.com return (FAILURE); 10147968Sopensolaris@drydog.com } 10157968Sopensolaris@drydog.com 10167968Sopensolaris@drydog.com if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, 10177968Sopensolaris@drydog.com pload_soft_conf) == -1) { 10187968Sopensolaris@drydog.com cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 10197968Sopensolaris@drydog.com strerror(errno)); 10207968Sopensolaris@drydog.com free_entry(pent); 10217968Sopensolaris@drydog.com free(pload_soft_conf); 10227968Sopensolaris@drydog.com (void) close(fd); 10230Sstevel@tonic-gate return (FAILURE); 10240Sstevel@tonic-gate } 10250Sstevel@tonic-gate 10267968Sopensolaris@drydog.com if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 10277968Sopensolaris@drydog.com cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl = return_value = %d", 10287968Sopensolaris@drydog.com pload_soft_conf->sc_return_value); 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 /* ioctl cleanup */ 10367968Sopensolaris@drydog.com free(pload_soft_conf); 10377968Sopensolaris@drydog.com (void) close(fd); 10387968Sopensolaris@drydog.com 10397968Sopensolaris@drydog.com 10407968Sopensolaris@drydog.com /* Finally, remove entry from kcf.conf, if present */ 10417968Sopensolaris@drydog.com if (in_kcfconf && (pent != NULL)) { 10427968Sopensolaris@drydog.com rc = update_kcfconf(pent, DELETE_MODE); 10430Sstevel@tonic-gate } 10440Sstevel@tonic-gate 10457968Sopensolaris@drydog.com free_entry(pent); 10460Sstevel@tonic-gate return (rc); 10470Sstevel@tonic-gate } 10480Sstevel@tonic-gate 10490Sstevel@tonic-gate 10507968Sopensolaris@drydog.com /* 10517968Sopensolaris@drydog.com * Implement the "cryptoadm refresh" command for global zones. 10527968Sopensolaris@drydog.com * That is, send the current contents of kcf.conf to the kernel via ioctl(). 10537968Sopensolaris@drydog.com */ 10540Sstevel@tonic-gate int 10550Sstevel@tonic-gate refresh(void) 10560Sstevel@tonic-gate { 10570Sstevel@tonic-gate crypto_load_soft_config_t *pload_soft_conf = NULL; 10580Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 10590Sstevel@tonic-gate crypto_load_dev_disabled_t *pload_dev_dis = NULL; 10607968Sopensolaris@drydog.com entrylist_t *pdevlist = NULL; 10617968Sopensolaris@drydog.com entrylist_t *psoftlist = NULL; 10627968Sopensolaris@drydog.com entrylist_t *ptr; 10637968Sopensolaris@drydog.com int fd = -1; 10647968Sopensolaris@drydog.com int rc = SUCCESS; 10657968Sopensolaris@drydog.com int err; 10660Sstevel@tonic-gate 1067*10979SHai-May.Chao@Sun.COM if (get_kcfconf_info(&pdevlist, &psoftlist) == FAILURE) { 10680Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to retrieve the providers' " 10690Sstevel@tonic-gate "information from the configuration file - %s.", 10700Sstevel@tonic-gate _PATH_KCF_CONF); 10710Sstevel@tonic-gate return (FAILURE); 10720Sstevel@tonic-gate } 10730Sstevel@tonic-gate 10740Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 10750Sstevel@tonic-gate err = errno; 10760Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 10770Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(err)); 10780Sstevel@tonic-gate free(psoftlist); 10790Sstevel@tonic-gate free(pdevlist); 10800Sstevel@tonic-gate return (FAILURE); 10810Sstevel@tonic-gate } 10820Sstevel@tonic-gate 10830Sstevel@tonic-gate /* 10847968Sopensolaris@drydog.com * For each software provider module, pass two sets of information to 10857968Sopensolaris@drydog.com * the kernel: the supported list and the disabled list. 10860Sstevel@tonic-gate */ 10877968Sopensolaris@drydog.com for (ptr = psoftlist; ptr != NULL; ptr = ptr->next) { 10887968Sopensolaris@drydog.com entry_t *pent = ptr->pent; 10897968Sopensolaris@drydog.com 10900Sstevel@tonic-gate /* load the supported list */ 10917968Sopensolaris@drydog.com if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) { 10927968Sopensolaris@drydog.com cryptodebug("setup_soft_conf() failed"); 10930Sstevel@tonic-gate rc = FAILURE; 10940Sstevel@tonic-gate break; 10950Sstevel@tonic-gate } 10960Sstevel@tonic-gate 10977968Sopensolaris@drydog.com if (!pent->load) { /* unloaded--mark as loaded */ 10987968Sopensolaris@drydog.com pent->load = B_TRUE; 10997968Sopensolaris@drydog.com rc = update_kcfconf(pent, MODIFY_MODE); 11007968Sopensolaris@drydog.com if (rc != SUCCESS) { 11017968Sopensolaris@drydog.com free(pload_soft_conf); 11027968Sopensolaris@drydog.com break; 11037968Sopensolaris@drydog.com } 11047968Sopensolaris@drydog.com } 11057968Sopensolaris@drydog.com 11060Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) 11070Sstevel@tonic-gate == -1) { 11080Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 11090Sstevel@tonic-gate strerror(errno)); 11100Sstevel@tonic-gate free(pload_soft_conf); 11110Sstevel@tonic-gate rc = FAILURE; 11120Sstevel@tonic-gate break; 11130Sstevel@tonic-gate } 11140Sstevel@tonic-gate 11150Sstevel@tonic-gate if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 11160Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl " 11170Sstevel@tonic-gate "return_value = %d", 11180Sstevel@tonic-gate pload_soft_conf->sc_return_value); 11190Sstevel@tonic-gate free(pload_soft_conf); 11200Sstevel@tonic-gate rc = FAILURE; 11210Sstevel@tonic-gate break; 11220Sstevel@tonic-gate } 11230Sstevel@tonic-gate 11247968Sopensolaris@drydog.com free(pload_soft_conf); 11257968Sopensolaris@drydog.com 11260Sstevel@tonic-gate /* load the disabled list */ 11270Sstevel@tonic-gate if (ptr->pent->dis_count != 0) { 11280Sstevel@tonic-gate pload_soft_dis = setup_soft_dis(ptr->pent); 11290Sstevel@tonic-gate if (pload_soft_dis == NULL) { 11307968Sopensolaris@drydog.com cryptodebug("setup_soft_dis() failed"); 11317968Sopensolaris@drydog.com free(pload_soft_dis); 11320Sstevel@tonic-gate rc = FAILURE; 11330Sstevel@tonic-gate break; 11340Sstevel@tonic-gate } 11350Sstevel@tonic-gate 11360Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, 11370Sstevel@tonic-gate pload_soft_dis) == -1) { 11380Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 11390Sstevel@tonic-gate "failed: %s", strerror(errno)); 11400Sstevel@tonic-gate free(pload_soft_dis); 11410Sstevel@tonic-gate rc = FAILURE; 11420Sstevel@tonic-gate break; 11430Sstevel@tonic-gate } 11440Sstevel@tonic-gate 11450Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != 11460Sstevel@tonic-gate CRYPTO_SUCCESS) { 11470Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 11480Sstevel@tonic-gate "return_value = %d", 11490Sstevel@tonic-gate pload_soft_dis->sd_return_value); 11500Sstevel@tonic-gate free(pload_soft_dis); 11510Sstevel@tonic-gate rc = FAILURE; 11520Sstevel@tonic-gate break; 11530Sstevel@tonic-gate } 11540Sstevel@tonic-gate free(pload_soft_dis); 11550Sstevel@tonic-gate } 11560Sstevel@tonic-gate } 11570Sstevel@tonic-gate 11580Sstevel@tonic-gate if (rc != SUCCESS) { 11590Sstevel@tonic-gate (void) close(fd); 11600Sstevel@tonic-gate return (rc); 11610Sstevel@tonic-gate } 11620Sstevel@tonic-gate 11630Sstevel@tonic-gate 11647968Sopensolaris@drydog.com /* 11657968Sopensolaris@drydog.com * For each hardware provider module, pass the disabled list 11667968Sopensolaris@drydog.com * information to the kernel. 11677968Sopensolaris@drydog.com */ 11687968Sopensolaris@drydog.com for (ptr = pdevlist; ptr != NULL; ptr = ptr->next) { 11690Sstevel@tonic-gate /* load the disabled list */ 11700Sstevel@tonic-gate if (ptr->pent->dis_count != 0) { 11710Sstevel@tonic-gate pload_dev_dis = setup_dev_dis(ptr->pent); 11720Sstevel@tonic-gate if (pload_dev_dis == NULL) { 11730Sstevel@tonic-gate rc = FAILURE; 11740Sstevel@tonic-gate break; 11750Sstevel@tonic-gate } 11760Sstevel@tonic-gate 11770Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) 11780Sstevel@tonic-gate == -1) { 11790Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 11800Sstevel@tonic-gate "failed: %s", strerror(errno)); 11810Sstevel@tonic-gate free(pload_dev_dis); 11820Sstevel@tonic-gate rc = FAILURE; 11830Sstevel@tonic-gate break; 11840Sstevel@tonic-gate } 11850Sstevel@tonic-gate 11860Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 11870Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 11880Sstevel@tonic-gate "return_value = %d", 11890Sstevel@tonic-gate pload_dev_dis->dd_return_value); 11900Sstevel@tonic-gate free(pload_dev_dis); 11910Sstevel@tonic-gate rc = FAILURE; 11920Sstevel@tonic-gate break; 11930Sstevel@tonic-gate } 11940Sstevel@tonic-gate free(pload_dev_dis); 11950Sstevel@tonic-gate } 11960Sstevel@tonic-gate } 11970Sstevel@tonic-gate 119810500SHai-May.Chao@Sun.COM /* 119910500SHai-May.Chao@Sun.COM * handle fips_status=enabled|disabled 120010500SHai-May.Chao@Sun.COM */ 1201*10979SHai-May.Chao@Sun.COM { 1202*10979SHai-May.Chao@Sun.COM int pkcs11_fips_mode = 0; 1203*10979SHai-May.Chao@Sun.COM 1204*10979SHai-May.Chao@Sun.COM /* Get FIPS-140 status from pkcs11.conf */ 1205*10979SHai-May.Chao@Sun.COM fips_status_pkcs11conf(&pkcs11_fips_mode); 1206*10979SHai-May.Chao@Sun.COM if (pkcs11_fips_mode == CRYPTO_FIPS_MODE_ENABLED) { 1207*10979SHai-May.Chao@Sun.COM rc = do_fips_actions(FIPS140_ENABLE, REFRESH); 1208*10979SHai-May.Chao@Sun.COM } else { 1209*10979SHai-May.Chao@Sun.COM rc = do_fips_actions(FIPS140_DISABLE, REFRESH); 1210*10979SHai-May.Chao@Sun.COM } 121110500SHai-May.Chao@Sun.COM } 121210500SHai-May.Chao@Sun.COM 12130Sstevel@tonic-gate (void) close(fd); 12140Sstevel@tonic-gate return (rc); 12150Sstevel@tonic-gate } 12160Sstevel@tonic-gate 12170Sstevel@tonic-gate /* 12180Sstevel@tonic-gate * Unload the kernel software provider. Before calling this function, the 12197968Sopensolaris@drydog.com * caller should check to see if the provider is in the kernel. 12207968Sopensolaris@drydog.com * 12217968Sopensolaris@drydog.com * This routine makes 2 ioctl calls to remove it completely from the kernel: 12227968Sopensolaris@drydog.com * CRYPTO_UNLOAD_SOFT_MODULE - does a modunload of the KCF module 12237968Sopensolaris@drydog.com * CRYPTO_LOAD_SOFT_DISABLED - updates kernel disabled mechanism list 12247968Sopensolaris@drydog.com * 12257968Sopensolaris@drydog.com * This implements part of "cryptoadm unload" and "cryptoadm uninstall". 12260Sstevel@tonic-gate */ 12270Sstevel@tonic-gate int 12287968Sopensolaris@drydog.com unload_kef_soft(char *provname) 12290Sstevel@tonic-gate { 12307968Sopensolaris@drydog.com crypto_unload_soft_module_t *punload_soft = NULL; 12310Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 12327968Sopensolaris@drydog.com entry_t *pent = NULL; 12337968Sopensolaris@drydog.com int fd = -1; 12347968Sopensolaris@drydog.com int err; 12350Sstevel@tonic-gate 12360Sstevel@tonic-gate if (provname == NULL) { 12370Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 12380Sstevel@tonic-gate return (FAILURE); 12390Sstevel@tonic-gate } 12400Sstevel@tonic-gate 1241*10979SHai-May.Chao@Sun.COM pent = getent_kef(provname, NULL, NULL); 12427968Sopensolaris@drydog.com if (pent == NULL) { /* not in kcf.conf */ 12431971Skrishna /* Construct an entry using the provname */ 12447968Sopensolaris@drydog.com pent = create_entry(provname); 12451971Skrishna if (pent == NULL) { 12461971Skrishna cryptoerror(LOG_STDERR, gettext("out of memory.")); 12471971Skrishna return (FAILURE); 12481971Skrishna } 12490Sstevel@tonic-gate } 12500Sstevel@tonic-gate 12510Sstevel@tonic-gate /* Open the admin_ioctl_device */ 12520Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 12530Sstevel@tonic-gate err = errno; 12540Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 12550Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(err)); 12567968Sopensolaris@drydog.com free_entry(pent); 12570Sstevel@tonic-gate return (FAILURE); 12580Sstevel@tonic-gate } 12590Sstevel@tonic-gate 12600Sstevel@tonic-gate /* Inform kernel to unload this software module */ 12610Sstevel@tonic-gate if ((punload_soft = setup_unload_soft(pent)) == NULL) { 12627968Sopensolaris@drydog.com free_entry(pent); 12630Sstevel@tonic-gate (void) close(fd); 12640Sstevel@tonic-gate return (FAILURE); 12650Sstevel@tonic-gate } 12660Sstevel@tonic-gate 12670Sstevel@tonic-gate if (ioctl(fd, CRYPTO_UNLOAD_SOFT_MODULE, punload_soft) == -1) { 12680Sstevel@tonic-gate cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl failed: %s", 12690Sstevel@tonic-gate strerror(errno)); 12700Sstevel@tonic-gate free_entry(pent); 12710Sstevel@tonic-gate free(punload_soft); 12720Sstevel@tonic-gate (void) close(fd); 12730Sstevel@tonic-gate return (FAILURE); 12740Sstevel@tonic-gate } 12750Sstevel@tonic-gate 12760Sstevel@tonic-gate if (punload_soft->sm_return_value != CRYPTO_SUCCESS) { 12770Sstevel@tonic-gate cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl return_value = " 12780Sstevel@tonic-gate "%d", punload_soft->sm_return_value); 12790Sstevel@tonic-gate /* 12807334SDaniel.Anderson@Sun.COM * If the return value is CRYPTO_UNKNOWN_PROVIDER, it means 12810Sstevel@tonic-gate * that the provider is not registered yet. Should just 12820Sstevel@tonic-gate * continue. 12830Sstevel@tonic-gate */ 12840Sstevel@tonic-gate if (punload_soft->sm_return_value != CRYPTO_UNKNOWN_PROVIDER) { 12850Sstevel@tonic-gate free_entry(pent); 12860Sstevel@tonic-gate free(punload_soft); 12870Sstevel@tonic-gate (void) close(fd); 12880Sstevel@tonic-gate return (FAILURE); 12890Sstevel@tonic-gate } 12900Sstevel@tonic-gate } 12910Sstevel@tonic-gate 12920Sstevel@tonic-gate free(punload_soft); 12930Sstevel@tonic-gate 12940Sstevel@tonic-gate /* Inform kernel to remove the disabled entries if any */ 12950Sstevel@tonic-gate if (pent->dis_count == 0) { 12960Sstevel@tonic-gate free_entry(pent); 12970Sstevel@tonic-gate (void) close(fd); 12980Sstevel@tonic-gate return (SUCCESS); 12990Sstevel@tonic-gate } else { 13000Sstevel@tonic-gate free_mechlist(pent->dislist); 13010Sstevel@tonic-gate pent->dislist = NULL; 13020Sstevel@tonic-gate pent->dis_count = 0; 13030Sstevel@tonic-gate } 13040Sstevel@tonic-gate 13050Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 13060Sstevel@tonic-gate free_entry(pent); 13070Sstevel@tonic-gate (void) close(fd); 13080Sstevel@tonic-gate return (FAILURE); 13090Sstevel@tonic-gate } 13100Sstevel@tonic-gate 13110Sstevel@tonic-gate /* pent is no longer needed; free it */ 13120Sstevel@tonic-gate free_entry(pent); 13130Sstevel@tonic-gate 13140Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) { 13150Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s", 13160Sstevel@tonic-gate strerror(errno)); 13170Sstevel@tonic-gate free(pload_soft_dis); 13180Sstevel@tonic-gate (void) close(fd); 13190Sstevel@tonic-gate return (FAILURE); 13200Sstevel@tonic-gate } 13210Sstevel@tonic-gate 13220Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 13230Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = " 13240Sstevel@tonic-gate "%d", pload_soft_dis->sd_return_value); 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 free(pload_soft_dis); 13310Sstevel@tonic-gate (void) close(fd); 13320Sstevel@tonic-gate return (SUCCESS); 13330Sstevel@tonic-gate } 13340Sstevel@tonic-gate 13350Sstevel@tonic-gate 13360Sstevel@tonic-gate /* 13370Sstevel@tonic-gate * Check if a hardware provider is valid. If it is valid, returns its device 13380Sstevel@tonic-gate * name, instance number and the number of mechanisms it supports. 13390Sstevel@tonic-gate */ 13400Sstevel@tonic-gate static int 13410Sstevel@tonic-gate check_hardware_provider(char *provname, char *pname, int *pnum, int *pcount) 13420Sstevel@tonic-gate { 13430Sstevel@tonic-gate crypto_get_dev_list_t *dev_list = NULL; 13440Sstevel@tonic-gate int i; 13450Sstevel@tonic-gate 13460Sstevel@tonic-gate if (provname == NULL) { 13470Sstevel@tonic-gate return (FAILURE); 13480Sstevel@tonic-gate } 13490Sstevel@tonic-gate 13500Sstevel@tonic-gate /* First, get the device name and the instance number from provname */ 13510Sstevel@tonic-gate if (split_hw_provname(provname, pname, pnum) == FAILURE) { 13520Sstevel@tonic-gate return (FAILURE); 13530Sstevel@tonic-gate } 13540Sstevel@tonic-gate 13550Sstevel@tonic-gate /* 13560Sstevel@tonic-gate * Get the complete device list from kernel and check if this provider 13570Sstevel@tonic-gate * is in the list. 13580Sstevel@tonic-gate */ 13590Sstevel@tonic-gate if (get_dev_list(&dev_list) == FAILURE) { 13600Sstevel@tonic-gate return (FAILURE); 13610Sstevel@tonic-gate } 13620Sstevel@tonic-gate 13630Sstevel@tonic-gate for (i = 0; i < dev_list->dl_dev_count; i++) { 13640Sstevel@tonic-gate if ((strcmp(dev_list->dl_devs[i].le_dev_name, pname) == 0) && 13650Sstevel@tonic-gate (dev_list->dl_devs[i].le_dev_instance == *pnum)) { 13660Sstevel@tonic-gate break; 13670Sstevel@tonic-gate } 13680Sstevel@tonic-gate } 13690Sstevel@tonic-gate 13700Sstevel@tonic-gate if (i == dev_list->dl_dev_count) { 13710Sstevel@tonic-gate /* didn't find this provider in the kernel device list */ 13720Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s does not exist."), 13730Sstevel@tonic-gate provname); 13740Sstevel@tonic-gate free(dev_list); 13750Sstevel@tonic-gate return (FAILURE); 13760Sstevel@tonic-gate } 13770Sstevel@tonic-gate 13780Sstevel@tonic-gate /* This provider is valid. Get its mechanism count */ 13790Sstevel@tonic-gate *pcount = dev_list->dl_devs[i].le_mechanism_count; 13800Sstevel@tonic-gate 13810Sstevel@tonic-gate free(dev_list); 13820Sstevel@tonic-gate return (SUCCESS); 13830Sstevel@tonic-gate } 1384