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 /* 227334SDaniel.Anderson@Sun.COM * Copyright 2008 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. 44*7968Sopensolaris@drydog.com * This implements part of the "cryptoadm list -m" command. 45*7968Sopensolaris@drydog.com * 46*7968Sopensolaris@drydog.com * Parameters phardlist and psoftlist are supplied by get_kcfconf_info(). 47*7968Sopensolaris@drydog.com * If NULL, this function obtains it by calling get_kcfconf_info() internally. 480Sstevel@tonic-gate */ 490Sstevel@tonic-gate int 50*7968Sopensolaris@drydog.com list_mechlist_for_soft(char *provname, 51*7968Sopensolaris@drydog.com entrylist_t *phardlist, entrylist_t *psoftlist) 520Sstevel@tonic-gate { 53*7968Sopensolaris@drydog.com mechlist_t *pmechlist = NULL; 54*7968Sopensolaris@drydog.com int rc; 550Sstevel@tonic-gate 560Sstevel@tonic-gate if (provname == NULL) { 570Sstevel@tonic-gate return (FAILURE); 580Sstevel@tonic-gate } 590Sstevel@tonic-gate 60*7968Sopensolaris@drydog.com rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist); 610Sstevel@tonic-gate if (rc == SUCCESS) { 620Sstevel@tonic-gate (void) filter_mechlist(&pmechlist, RANDOM); 630Sstevel@tonic-gate print_mechlist(provname, pmechlist); 640Sstevel@tonic-gate free_mechlist(pmechlist); 650Sstevel@tonic-gate } else { 660Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 670Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 680Sstevel@tonic-gate provname); 690Sstevel@tonic-gate } 700Sstevel@tonic-gate 710Sstevel@tonic-gate return (rc); 720Sstevel@tonic-gate } 730Sstevel@tonic-gate 740Sstevel@tonic-gate /* 750Sstevel@tonic-gate * Display the mechanism list for a kernel hardware provider. 76*7968Sopensolaris@drydog.com * This implements part of the "cryptoadm list -m" command. 770Sstevel@tonic-gate */ 780Sstevel@tonic-gate int 790Sstevel@tonic-gate list_mechlist_for_hard(char *provname) 800Sstevel@tonic-gate { 81*7968Sopensolaris@drydog.com mechlist_t *pmechlist = NULL; 82*7968Sopensolaris@drydog.com char devname[MAXNAMELEN]; 83*7968Sopensolaris@drydog.com int inst_num; 84*7968Sopensolaris@drydog.com int count; 85*7968Sopensolaris@drydog.com int rc = SUCCESS; 860Sstevel@tonic-gate 870Sstevel@tonic-gate if (provname == NULL) { 880Sstevel@tonic-gate return (FAILURE); 890Sstevel@tonic-gate } 900Sstevel@tonic-gate 910Sstevel@tonic-gate /* 920Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 930Sstevel@tonic-gate * mechanisms also. 940Sstevel@tonic-gate */ 950Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) == 960Sstevel@tonic-gate FAILURE) { 970Sstevel@tonic-gate return (FAILURE); 980Sstevel@tonic-gate } 990Sstevel@tonic-gate 1000Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 1010Sstevel@tonic-gate if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) == 1020Sstevel@tonic-gate SUCCESS) { 1030Sstevel@tonic-gate (void) filter_mechlist(&pmechlist, RANDOM); 1040Sstevel@tonic-gate print_mechlist(provname, pmechlist); 1050Sstevel@tonic-gate free_mechlist(pmechlist); 1060Sstevel@tonic-gate } 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate return (rc); 1090Sstevel@tonic-gate } 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate /* 1130Sstevel@tonic-gate * Display the policy information for a kernel software provider. 114*7968Sopensolaris@drydog.com * This implements part of the "cryptoadm list -p" command. 115*7968Sopensolaris@drydog.com * 116*7968Sopensolaris@drydog.com * Parameters phardlist and psoftlist are supplied by get_kcfconf_info(). 117*7968Sopensolaris@drydog.com * If NULL, this function obtains it by calling get_kcfconf_info() internally. 1180Sstevel@tonic-gate */ 1190Sstevel@tonic-gate int 120*7968Sopensolaris@drydog.com list_policy_for_soft(char *provname, 121*7968Sopensolaris@drydog.com entrylist_t *phardlist, entrylist_t *psoftlist) 1220Sstevel@tonic-gate { 123*7968Sopensolaris@drydog.com int rc; 124*7968Sopensolaris@drydog.com entry_t *pent = NULL; 125*7968Sopensolaris@drydog.com mechlist_t *pmechlist = NULL; 126*7968Sopensolaris@drydog.com boolean_t has_random = B_FALSE; 127*7968Sopensolaris@drydog.com boolean_t has_mechs = B_FALSE; 128*7968Sopensolaris@drydog.com boolean_t in_kernel = B_FALSE; 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate if (provname == NULL) { 1310Sstevel@tonic-gate return (FAILURE); 1320Sstevel@tonic-gate } 1330Sstevel@tonic-gate 134*7968Sopensolaris@drydog.com if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) { 135*7968Sopensolaris@drydog.com return (FAILURE); 136*7968Sopensolaris@drydog.com } else if (in_kernel == B_FALSE) { 1370Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s does not exist."), 1380Sstevel@tonic-gate provname); 1390Sstevel@tonic-gate return (FAILURE); 1400Sstevel@tonic-gate } 141*7968Sopensolaris@drydog.com pent = getent_kef(provname, phardlist, psoftlist); 1420Sstevel@tonic-gate 143*7968Sopensolaris@drydog.com rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist); 1440Sstevel@tonic-gate if (rc == SUCCESS) { 1450Sstevel@tonic-gate has_random = filter_mechlist(&pmechlist, RANDOM); 1460Sstevel@tonic-gate if (pmechlist != NULL) { 1470Sstevel@tonic-gate has_mechs = B_TRUE; 1480Sstevel@tonic-gate free_mechlist(pmechlist); 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate } else { 1510Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 1520Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 1530Sstevel@tonic-gate provname); 1540Sstevel@tonic-gate return (rc); 1550Sstevel@tonic-gate } 1560Sstevel@tonic-gate 157*7968Sopensolaris@drydog.com print_kef_policy(provname, pent, has_random, has_mechs); 1580Sstevel@tonic-gate free_entry(pent); 1590Sstevel@tonic-gate return (SUCCESS); 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate /* 1650Sstevel@tonic-gate * Display the policy information for a kernel hardware provider. 166*7968Sopensolaris@drydog.com * This implements part of the "cryptoadm list -p" command. 167*7968Sopensolaris@drydog.com * 168*7968Sopensolaris@drydog.com * Parameters phardlist and psoftlist are supplied by get_kcfconf_info(). 169*7968Sopensolaris@drydog.com * If NULL, this function obtains it by calling get_kcfconf_info() internally. 170*7968Sopensolaris@drydog.com * Parameter pdevlist is supplied by get_dev_list(). 171*7968Sopensolaris@drydog.com * If NULL, this function obtains it by calling get_dev_list() internally. 1720Sstevel@tonic-gate */ 1730Sstevel@tonic-gate int 174*7968Sopensolaris@drydog.com list_policy_for_hard(char *provname, 175*7968Sopensolaris@drydog.com entrylist_t *phardlist, entrylist_t *psoftlist, 176*7968Sopensolaris@drydog.com crypto_get_dev_list_t *pdevlist) 1770Sstevel@tonic-gate { 178*7968Sopensolaris@drydog.com entry_t *pent = NULL; 179*7968Sopensolaris@drydog.com boolean_t in_kernel; 180*7968Sopensolaris@drydog.com mechlist_t *pmechlist = NULL; 181*7968Sopensolaris@drydog.com char devname[MAXNAMELEN]; 182*7968Sopensolaris@drydog.com int inst_num; 183*7968Sopensolaris@drydog.com int count; 184*7968Sopensolaris@drydog.com int rc = SUCCESS; 185*7968Sopensolaris@drydog.com boolean_t has_random = B_FALSE; 186*7968Sopensolaris@drydog.com boolean_t has_mechs = B_FALSE; 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate if (provname == NULL) { 1890Sstevel@tonic-gate return (FAILURE); 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate /* 1930Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 1940Sstevel@tonic-gate * mechanisms also. 1950Sstevel@tonic-gate */ 1960Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) == 1970Sstevel@tonic-gate FAILURE) { 1980Sstevel@tonic-gate return (FAILURE); 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 2020Sstevel@tonic-gate if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) == 2030Sstevel@tonic-gate SUCCESS) { 2040Sstevel@tonic-gate has_random = filter_mechlist(&pmechlist, RANDOM); 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate if (pmechlist != NULL) { 2070Sstevel@tonic-gate has_mechs = B_TRUE; 2080Sstevel@tonic-gate free_mechlist(pmechlist); 2090Sstevel@tonic-gate } 2100Sstevel@tonic-gate } else { 2110Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 2120Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 2130Sstevel@tonic-gate devname); 2140Sstevel@tonic-gate return (rc); 2150Sstevel@tonic-gate } 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate /* 2180Sstevel@tonic-gate * If the hardware provider has an entry in the kcf.conf file, 2190Sstevel@tonic-gate * some of its mechanisms must have been disabled. Print out 2200Sstevel@tonic-gate * the disabled list from the config file entry. Otherwise, 2210Sstevel@tonic-gate * if it is active, then all the mechanisms for it are enabled. 2220Sstevel@tonic-gate */ 223*7968Sopensolaris@drydog.com if ((pent = getent_kef(provname, phardlist, psoftlist)) != NULL) { 224*7968Sopensolaris@drydog.com print_kef_policy(provname, pent, has_random, has_mechs); 2250Sstevel@tonic-gate free_entry(pent); 2260Sstevel@tonic-gate return (SUCCESS); 2270Sstevel@tonic-gate } else { 228*7968Sopensolaris@drydog.com if (check_kernel_for_hard(provname, pdevlist, 229*7968Sopensolaris@drydog.com &in_kernel) == FAILURE) { 2300Sstevel@tonic-gate return (FAILURE); 231*7968Sopensolaris@drydog.com } else if (in_kernel == B_TRUE) { 2320Sstevel@tonic-gate (void) printf(gettext( 2330Sstevel@tonic-gate "%s: all mechanisms are enabled."), provname); 2340Sstevel@tonic-gate if (has_random) 2350Sstevel@tonic-gate /* 2367334SDaniel.Anderson@Sun.COM * TRANSLATION_NOTE 2370Sstevel@tonic-gate * "random" is a keyword and not to be 2380Sstevel@tonic-gate * translated. 2390Sstevel@tonic-gate */ 2400Sstevel@tonic-gate (void) printf(gettext(" %s is enabled.\n"), 2410Sstevel@tonic-gate "random"); 2420Sstevel@tonic-gate else 2430Sstevel@tonic-gate (void) printf("\n"); 2440Sstevel@tonic-gate return (SUCCESS); 2450Sstevel@tonic-gate } else { 2460Sstevel@tonic-gate cryptoerror(LOG_STDERR, 2470Sstevel@tonic-gate gettext("%s does not exist."), provname); 2480Sstevel@tonic-gate return (FAILURE); 2490Sstevel@tonic-gate } 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate } 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate 254*7968Sopensolaris@drydog.com /* 255*7968Sopensolaris@drydog.com * Disable a kernel hardware provider. 256*7968Sopensolaris@drydog.com * This implements the "cryptoadm disable" command for 257*7968Sopensolaris@drydog.com * kernel hardware providers. 258*7968Sopensolaris@drydog.com */ 2590Sstevel@tonic-gate int 2600Sstevel@tonic-gate disable_kef_hardware(char *provname, boolean_t rndflag, boolean_t allflag, 2610Sstevel@tonic-gate mechlist_t *dislist) 2620Sstevel@tonic-gate { 263*7968Sopensolaris@drydog.com crypto_load_dev_disabled_t *pload_dev_dis = NULL; 264*7968Sopensolaris@drydog.com mechlist_t *infolist = NULL; 265*7968Sopensolaris@drydog.com entry_t *pent = NULL; 266*7968Sopensolaris@drydog.com boolean_t new_dev_entry = B_FALSE; 267*7968Sopensolaris@drydog.com char devname[MAXNAMELEN]; 268*7968Sopensolaris@drydog.com int inst_num; 269*7968Sopensolaris@drydog.com int count; 270*7968Sopensolaris@drydog.com int fd = -1; 271*7968Sopensolaris@drydog.com int rc = SUCCESS; 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate if (provname == NULL) { 2740Sstevel@tonic-gate return (FAILURE); 2750Sstevel@tonic-gate } 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate /* 2780Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 2790Sstevel@tonic-gate * mechanisms also. 2800Sstevel@tonic-gate */ 2810Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) 2820Sstevel@tonic-gate == FAILURE) { 2830Sstevel@tonic-gate return (FAILURE); 2840Sstevel@tonic-gate } 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 2870Sstevel@tonic-gate if (get_dev_info(devname, inst_num, count, &infolist) == FAILURE) { 2880Sstevel@tonic-gate return (FAILURE); 2890Sstevel@tonic-gate } 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate /* 2920Sstevel@tonic-gate * Get the entry of this hardware provider from the config file. 2930Sstevel@tonic-gate * If there is no entry yet, create one for it. 2940Sstevel@tonic-gate */ 295*7968Sopensolaris@drydog.com if ((pent = getent_kef(provname, NULL, NULL)) == NULL) { 296*7968Sopensolaris@drydog.com if ((pent = create_entry(provname)) == NULL) { 2970Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("out of memory.")); 2980Sstevel@tonic-gate free_mechlist(infolist); 2990Sstevel@tonic-gate return (FAILURE); 3000Sstevel@tonic-gate } 3010Sstevel@tonic-gate new_dev_entry = B_TRUE; 3020Sstevel@tonic-gate } 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate /* 3050Sstevel@tonic-gate * kCF treats random as an internal mechanism. So, we need to 3060Sstevel@tonic-gate * filter it from the mechanism list here, if we are NOT disabling 3070Sstevel@tonic-gate * or enabling the random feature. Note that we map random feature at 3080Sstevel@tonic-gate * cryptoadm(1M) level to the "random" mechanism in kCF. 3090Sstevel@tonic-gate */ 3100Sstevel@tonic-gate if (!rndflag) { 3112860Smcpowers (void) filter_mechlist(&dislist, RANDOM); 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate /* Calculate the new disabled list */ 3150Sstevel@tonic-gate if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) { 3162860Smcpowers free_mechlist(infolist); 3170Sstevel@tonic-gate free_entry(pent); 3180Sstevel@tonic-gate return (FAILURE); 3190Sstevel@tonic-gate } 3202860Smcpowers free_mechlist(infolist); 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate /* If no mechanisms are to be disabled, return */ 3230Sstevel@tonic-gate if (pent->dis_count == 0) { 3240Sstevel@tonic-gate free_entry(pent); 3250Sstevel@tonic-gate return (SUCCESS); 3260Sstevel@tonic-gate } 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate /* Update the config file with the new entry or the updated entry */ 3290Sstevel@tonic-gate if (new_dev_entry) { 3300Sstevel@tonic-gate rc = update_kcfconf(pent, ADD_MODE); 3310Sstevel@tonic-gate } else { 3320Sstevel@tonic-gate rc = update_kcfconf(pent, MODIFY_MODE); 3330Sstevel@tonic-gate } 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate if (rc == FAILURE) { 3360Sstevel@tonic-gate free_entry(pent); 3370Sstevel@tonic-gate return (FAILURE); 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate /* Inform kernel about the new disabled mechanism list */ 3410Sstevel@tonic-gate if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) { 3420Sstevel@tonic-gate free_entry(pent); 3430Sstevel@tonic-gate return (FAILURE); 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate free_entry(pent); 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 3480Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 3490Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 3500Sstevel@tonic-gate free(pload_dev_dis); 3510Sstevel@tonic-gate return (FAILURE); 3520Sstevel@tonic-gate } 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) { 3550Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: %s", 3560Sstevel@tonic-gate strerror(errno)); 3570Sstevel@tonic-gate free(pload_dev_dis); 3580Sstevel@tonic-gate (void) close(fd); 3590Sstevel@tonic-gate return (FAILURE); 3600Sstevel@tonic-gate } 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 3630Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl return_value = " 3640Sstevel@tonic-gate "%d", pload_dev_dis->dd_return_value); 3650Sstevel@tonic-gate free(pload_dev_dis); 3660Sstevel@tonic-gate (void) close(fd); 3670Sstevel@tonic-gate return (FAILURE); 3680Sstevel@tonic-gate } 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate free(pload_dev_dis); 3710Sstevel@tonic-gate (void) close(fd); 3720Sstevel@tonic-gate return (SUCCESS); 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate 376*7968Sopensolaris@drydog.com /* 377*7968Sopensolaris@drydog.com * Disable a kernel software provider. 378*7968Sopensolaris@drydog.com * This implements the "cryptoadm disable" command for 379*7968Sopensolaris@drydog.com * kernel software providers. 380*7968Sopensolaris@drydog.com */ 3810Sstevel@tonic-gate int 3820Sstevel@tonic-gate disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag, 3830Sstevel@tonic-gate mechlist_t *dislist) 3840Sstevel@tonic-gate { 3850Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 386*7968Sopensolaris@drydog.com mechlist_t *infolist = NULL; 387*7968Sopensolaris@drydog.com entry_t *pent = NULL; 388*7968Sopensolaris@drydog.com entrylist_t *phardlist = NULL; 389*7968Sopensolaris@drydog.com entrylist_t *psoftlist = NULL; 390*7968Sopensolaris@drydog.com boolean_t in_kernel = B_FALSE; 391*7968Sopensolaris@drydog.com int fd = -1; 392*7968Sopensolaris@drydog.com int rc = SUCCESS; 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate if (provname == NULL) { 3950Sstevel@tonic-gate return (FAILURE); 3960Sstevel@tonic-gate } 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate /* 3990Sstevel@tonic-gate * Check if the kernel software provider is currently unloaded. 4000Sstevel@tonic-gate * If it is unloaded, return FAILURE, because the disable subcommand 4010Sstevel@tonic-gate * can not perform on inactive (unloaded) providers. 4020Sstevel@tonic-gate */ 403*7968Sopensolaris@drydog.com if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) { 404*7968Sopensolaris@drydog.com return (FAILURE); 405*7968Sopensolaris@drydog.com } else if (in_kernel == B_FALSE) { 406*7968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, 407*7968Sopensolaris@drydog.com gettext("%s is not loaded or does not exist."), 408*7968Sopensolaris@drydog.com provname); 4090Sstevel@tonic-gate return (FAILURE); 410*7968Sopensolaris@drydog.com } 411*7968Sopensolaris@drydog.com 412*7968Sopensolaris@drydog.com if (get_kcfconf_info(&phardlist, &psoftlist) == FAILURE) { 413*7968Sopensolaris@drydog.com cryptoerror(LOG_ERR, 414*7968Sopensolaris@drydog.com "failed to retrieve the providers' " 415*7968Sopensolaris@drydog.com "information from the configuration file - %s.", 416*7968Sopensolaris@drydog.com _PATH_KCF_CONF); 4170Sstevel@tonic-gate return (FAILURE); 4180Sstevel@tonic-gate } 4190Sstevel@tonic-gate 420*7968Sopensolaris@drydog.com /* 421*7968Sopensolaris@drydog.com * Get the entry of this provider from the kcf.conf file, if any. 422*7968Sopensolaris@drydog.com * Otherwise, create a new kcf.conf entry for writing back to the file. 423*7968Sopensolaris@drydog.com */ 424*7968Sopensolaris@drydog.com pent = getent_kef(provname, phardlist, psoftlist); 425*7968Sopensolaris@drydog.com if (pent == NULL) { /* create a new entry */ 426*7968Sopensolaris@drydog.com pent = create_entry(provname); 427*7968Sopensolaris@drydog.com if (pent == NULL) { 428*7968Sopensolaris@drydog.com cryptodebug("out of memory."); 429*7968Sopensolaris@drydog.com rc = FAILURE; 430*7968Sopensolaris@drydog.com goto out; 431*7968Sopensolaris@drydog.com } 4320Sstevel@tonic-gate } 4330Sstevel@tonic-gate 434*7968Sopensolaris@drydog.com /* Get the mechanism list for the software provider from the kernel */ 435*7968Sopensolaris@drydog.com if (get_soft_info(provname, &infolist, phardlist, psoftlist) == 436*7968Sopensolaris@drydog.com FAILURE) { 437*7968Sopensolaris@drydog.com rc = FAILURE; 438*7968Sopensolaris@drydog.com goto out; 439*7968Sopensolaris@drydog.com } 440*7968Sopensolaris@drydog.com 441*7968Sopensolaris@drydog.com if ((infolist != NULL) && (infolist->name[0] != '\0')) { 442*7968Sopensolaris@drydog.com /* 443*7968Sopensolaris@drydog.com * Replace the supportedlist from kcf.conf with possibly 444*7968Sopensolaris@drydog.com * more-up-to-date list from the kernel. This is the case 445*7968Sopensolaris@drydog.com * for default software providers that had more mechanisms 446*7968Sopensolaris@drydog.com * added in the current version of the kernel. 447*7968Sopensolaris@drydog.com */ 448*7968Sopensolaris@drydog.com free_mechlist(pent->suplist); 449*7968Sopensolaris@drydog.com pent->suplist = infolist; 450*7968Sopensolaris@drydog.com } 451*7968Sopensolaris@drydog.com 452*7968Sopensolaris@drydog.com /* 453*7968Sopensolaris@drydog.com * kCF treats random as an internal mechanism. So, we need to 454*7968Sopensolaris@drydog.com * filter it from the mechanism list here, if we are NOT disabling 455*7968Sopensolaris@drydog.com * or enabling the random feature. Note that we map random feature at 456*7968Sopensolaris@drydog.com * cryptoadm(1M) level to the "random" mechanism in kCF. 457*7968Sopensolaris@drydog.com */ 4580Sstevel@tonic-gate if (!rndflag) { 4590Sstevel@tonic-gate (void) filter_mechlist(&infolist, RANDOM); 4600Sstevel@tonic-gate } 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate /* Calculate the new disabled list */ 4630Sstevel@tonic-gate if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) { 464*7968Sopensolaris@drydog.com rc = FAILURE; 465*7968Sopensolaris@drydog.com goto out; 4660Sstevel@tonic-gate } 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate /* Update the kcf.conf file with the updated entry */ 4690Sstevel@tonic-gate if (update_kcfconf(pent, MODIFY_MODE) == FAILURE) { 470*7968Sopensolaris@drydog.com rc = FAILURE; 471*7968Sopensolaris@drydog.com goto out; 4720Sstevel@tonic-gate } 4730Sstevel@tonic-gate 474*7968Sopensolaris@drydog.com /* Setup argument to inform kernel about the new disabled list. */ 4750Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 476*7968Sopensolaris@drydog.com rc = FAILURE; 477*7968Sopensolaris@drydog.com goto out; 4780Sstevel@tonic-gate } 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 4810Sstevel@tonic-gate cryptoerror(LOG_STDERR, 4820Sstevel@tonic-gate gettext("failed to open %s for RW: %s"), 4830Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 484*7968Sopensolaris@drydog.com rc = FAILURE; 485*7968Sopensolaris@drydog.com goto out; 4860Sstevel@tonic-gate } 4870Sstevel@tonic-gate 488*7968Sopensolaris@drydog.com /* Inform kernel about the new disabled list. */ 4890Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) { 4900Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s", 4910Sstevel@tonic-gate strerror(errno)); 492*7968Sopensolaris@drydog.com rc = FAILURE; 493*7968Sopensolaris@drydog.com goto out; 4940Sstevel@tonic-gate } 4950Sstevel@tonic-gate 4960Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 4970Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = " 4980Sstevel@tonic-gate "%d", pload_soft_dis->sd_return_value); 499*7968Sopensolaris@drydog.com rc = FAILURE; 500*7968Sopensolaris@drydog.com goto out; 5010Sstevel@tonic-gate } 5020Sstevel@tonic-gate 503*7968Sopensolaris@drydog.com out: 504*7968Sopensolaris@drydog.com free_entrylist(phardlist); 505*7968Sopensolaris@drydog.com free_entrylist(psoftlist); 506*7968Sopensolaris@drydog.com free_mechlist(infolist); 507*7968Sopensolaris@drydog.com free_entry(pent); 5080Sstevel@tonic-gate free(pload_soft_dis); 509*7968Sopensolaris@drydog.com if (fd != -1) 510*7968Sopensolaris@drydog.com (void) close(fd); 511*7968Sopensolaris@drydog.com return (rc); 5120Sstevel@tonic-gate } 5130Sstevel@tonic-gate 5140Sstevel@tonic-gate 515*7968Sopensolaris@drydog.com /* 516*7968Sopensolaris@drydog.com * Enable a kernel software or hardware provider. 517*7968Sopensolaris@drydog.com * This implements the "cryptoadm enable" command for kernel providers. 518*7968Sopensolaris@drydog.com */ 5190Sstevel@tonic-gate int 5200Sstevel@tonic-gate enable_kef(char *provname, boolean_t rndflag, boolean_t allflag, 5210Sstevel@tonic-gate mechlist_t *mlist) 5220Sstevel@tonic-gate { 5230Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 5240Sstevel@tonic-gate crypto_load_dev_disabled_t *pload_dev_dis = NULL; 525*7968Sopensolaris@drydog.com entry_t *pent = NULL; 526*7968Sopensolaris@drydog.com boolean_t redo_flag = B_FALSE; 527*7968Sopensolaris@drydog.com boolean_t in_kernel = B_FALSE; 528*7968Sopensolaris@drydog.com int fd = -1; 529*7968Sopensolaris@drydog.com int rc = SUCCESS; 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate 532*7968Sopensolaris@drydog.com /* Get the entry of this provider from the kcf.conf file, if any. */ 533*7968Sopensolaris@drydog.com pent = getent_kef(provname, NULL, NULL); 5340Sstevel@tonic-gate 5350Sstevel@tonic-gate if (is_device(provname)) { 5360Sstevel@tonic-gate if (pent == NULL) { 5370Sstevel@tonic-gate /* 5380Sstevel@tonic-gate * This device doesn't have an entry in the config 5390Sstevel@tonic-gate * file, therefore nothing is disabled. 5400Sstevel@tonic-gate */ 5410Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 5420Sstevel@tonic-gate "all mechanisms are enabled already for %s."), 5430Sstevel@tonic-gate provname); 544*7968Sopensolaris@drydog.com free_entry(pent); 5450Sstevel@tonic-gate return (SUCCESS); 5460Sstevel@tonic-gate } 5470Sstevel@tonic-gate } else { /* a software module */ 548*7968Sopensolaris@drydog.com if (check_kernel_for_soft(provname, NULL, &in_kernel) == 549*7968Sopensolaris@drydog.com FAILURE) { 550*7968Sopensolaris@drydog.com free_entry(pent); 5510Sstevel@tonic-gate return (FAILURE); 552*7968Sopensolaris@drydog.com } else if (in_kernel == B_FALSE) { 553*7968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext("%s does not exist."), 554*7968Sopensolaris@drydog.com provname); 555*7968Sopensolaris@drydog.com free_entry(pent); 556*7968Sopensolaris@drydog.com return (FAILURE); 557*7968Sopensolaris@drydog.com } else if ((pent == NULL) || (pent->dis_count == 0)) { 5580Sstevel@tonic-gate /* nothing to be enabled. */ 5590Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 5600Sstevel@tonic-gate "all mechanisms are enabled already for %s."), 5610Sstevel@tonic-gate provname); 5620Sstevel@tonic-gate free_entry(pent); 5630Sstevel@tonic-gate return (SUCCESS); 5640Sstevel@tonic-gate } 5650Sstevel@tonic-gate } 5660Sstevel@tonic-gate 567*7968Sopensolaris@drydog.com /* 568*7968Sopensolaris@drydog.com * kCF treats random as an internal mechanism. So, we need to 569*7968Sopensolaris@drydog.com * filter it from the mechanism list here, if we are NOT disabling 570*7968Sopensolaris@drydog.com * or enabling the random feature. Note that we map random feature at 571*7968Sopensolaris@drydog.com * cryptoadm(1M) level to the "random" mechanism in kCF. 572*7968Sopensolaris@drydog.com */ 5730Sstevel@tonic-gate if (!rndflag) { 5740Sstevel@tonic-gate redo_flag = filter_mechlist(&pent->dislist, RANDOM); 5750Sstevel@tonic-gate if (redo_flag) 5760Sstevel@tonic-gate pent->dis_count--; 5770Sstevel@tonic-gate } 5780Sstevel@tonic-gate 5790Sstevel@tonic-gate /* Update the entry by enabling mechanisms for this provider */ 5800Sstevel@tonic-gate if ((rc = enable_mechs(&pent, allflag, mlist)) != SUCCESS) { 5810Sstevel@tonic-gate free_entry(pent); 5820Sstevel@tonic-gate return (rc); 5830Sstevel@tonic-gate } 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate if (redo_flag) { 5860Sstevel@tonic-gate mechlist_t *tmp; 5870Sstevel@tonic-gate 5880Sstevel@tonic-gate if ((tmp = create_mech(RANDOM)) == NULL) { 5890Sstevel@tonic-gate free_entry(pent); 5900Sstevel@tonic-gate return (FAILURE); 5910Sstevel@tonic-gate } 5920Sstevel@tonic-gate tmp->next = pent->dislist; 5930Sstevel@tonic-gate pent->dislist = tmp; 5940Sstevel@tonic-gate pent->dis_count++; 5950Sstevel@tonic-gate } 5960Sstevel@tonic-gate 5970Sstevel@tonic-gate /* 598*7968Sopensolaris@drydog.com * Update the kcf.conf file with the updated entry. 5990Sstevel@tonic-gate * For a hardware provider, if there is no more disabled mechanism, 600*7968Sopensolaris@drydog.com * remove the entire kcf.conf entry. 6010Sstevel@tonic-gate */ 6020Sstevel@tonic-gate if (is_device(pent->name) && (pent->dis_count == 0)) { 6030Sstevel@tonic-gate rc = update_kcfconf(pent, DELETE_MODE); 6040Sstevel@tonic-gate } else { 6050Sstevel@tonic-gate rc = update_kcfconf(pent, MODIFY_MODE); 6060Sstevel@tonic-gate } 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate if (rc == FAILURE) { 6090Sstevel@tonic-gate free_entry(pent); 6100Sstevel@tonic-gate return (FAILURE); 6110Sstevel@tonic-gate } 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate 6140Sstevel@tonic-gate /* Inform Kernel about the policy change */ 6150Sstevel@tonic-gate 6160Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 6170Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 6180Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 619*7968Sopensolaris@drydog.com free_entry(pent); 6200Sstevel@tonic-gate return (FAILURE); 6210Sstevel@tonic-gate } 6220Sstevel@tonic-gate 6230Sstevel@tonic-gate if (is_device(provname)) { 6240Sstevel@tonic-gate /* LOAD_DEV_DISABLED */ 6250Sstevel@tonic-gate if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) { 626*7968Sopensolaris@drydog.com free_entry(pent); 6270Sstevel@tonic-gate return (FAILURE); 6280Sstevel@tonic-gate } 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) { 6310Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: " 6320Sstevel@tonic-gate "%s", strerror(errno)); 633*7968Sopensolaris@drydog.com free_entry(pent); 6340Sstevel@tonic-gate free(pload_dev_dis); 6350Sstevel@tonic-gate (void) close(fd); 6360Sstevel@tonic-gate return (FAILURE); 6370Sstevel@tonic-gate } 6380Sstevel@tonic-gate 6390Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 6400Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 6410Sstevel@tonic-gate "return_value = %d", 6420Sstevel@tonic-gate pload_dev_dis->dd_return_value); 643*7968Sopensolaris@drydog.com free_entry(pent); 6440Sstevel@tonic-gate free(pload_dev_dis); 6450Sstevel@tonic-gate (void) close(fd); 6460Sstevel@tonic-gate return (FAILURE); 6470Sstevel@tonic-gate } 6480Sstevel@tonic-gate 649*7968Sopensolaris@drydog.com } else { /* a software module */ 6500Sstevel@tonic-gate /* LOAD_SOFT_DISABLED */ 6510Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 652*7968Sopensolaris@drydog.com free_entry(pent); 6530Sstevel@tonic-gate return (FAILURE); 6540Sstevel@tonic-gate } 6550Sstevel@tonic-gate 6560Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) 6570Sstevel@tonic-gate == -1) { 6580Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: " 6590Sstevel@tonic-gate "%s", strerror(errno)); 660*7968Sopensolaris@drydog.com free_entry(pent); 6610Sstevel@tonic-gate free(pload_soft_dis); 6620Sstevel@tonic-gate (void) close(fd); 6630Sstevel@tonic-gate return (FAILURE); 6640Sstevel@tonic-gate } 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 6670Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 6680Sstevel@tonic-gate "return_value = %d", 6690Sstevel@tonic-gate pload_soft_dis->sd_return_value); 670*7968Sopensolaris@drydog.com free_entry(pent); 6710Sstevel@tonic-gate free(pload_soft_dis); 6720Sstevel@tonic-gate (void) close(fd); 6730Sstevel@tonic-gate return (FAILURE); 6740Sstevel@tonic-gate } 6750Sstevel@tonic-gate } 6760Sstevel@tonic-gate 677*7968Sopensolaris@drydog.com free_entry(pent); 678*7968Sopensolaris@drydog.com free(pload_soft_dis); 6790Sstevel@tonic-gate (void) close(fd); 6800Sstevel@tonic-gate return (SUCCESS); 6810Sstevel@tonic-gate } 6820Sstevel@tonic-gate 6830Sstevel@tonic-gate 6840Sstevel@tonic-gate /* 6850Sstevel@tonic-gate * Install a software module with the specified mechanism list into the system. 6860Sstevel@tonic-gate * This routine adds an entry into the config file for this software module 6870Sstevel@tonic-gate * first, then makes a CRYPTO_LOAD_SOFT_CONFIG ioctl call to inform kernel 6880Sstevel@tonic-gate * about the new addition. 6890Sstevel@tonic-gate */ 6900Sstevel@tonic-gate int 6910Sstevel@tonic-gate install_kef(char *provname, mechlist_t *mlist) 6920Sstevel@tonic-gate { 6930Sstevel@tonic-gate crypto_load_soft_config_t *pload_soft_conf = NULL; 694*7968Sopensolaris@drydog.com boolean_t found; 695*7968Sopensolaris@drydog.com entry_t *pent = NULL; 696*7968Sopensolaris@drydog.com FILE *pfile = NULL; 697*7968Sopensolaris@drydog.com FILE *pfile_tmp = NULL; 698*7968Sopensolaris@drydog.com char tmpfile_name[MAXPATHLEN]; 699*7968Sopensolaris@drydog.com char *ptr; 700*7968Sopensolaris@drydog.com char *str; 701*7968Sopensolaris@drydog.com char *name; 702*7968Sopensolaris@drydog.com char buffer[BUFSIZ]; 703*7968Sopensolaris@drydog.com char buffer2[BUFSIZ]; 704*7968Sopensolaris@drydog.com int found_count; 705*7968Sopensolaris@drydog.com int fd = -1; 706*7968Sopensolaris@drydog.com int rc = SUCCESS; 707*7968Sopensolaris@drydog.com int err; 7080Sstevel@tonic-gate 7090Sstevel@tonic-gate if ((provname == NULL) || (mlist == NULL)) { 7100Sstevel@tonic-gate return (FAILURE); 7110Sstevel@tonic-gate } 7120Sstevel@tonic-gate 7130Sstevel@tonic-gate /* Check if the provider already exists */ 714*7968Sopensolaris@drydog.com if ((pent = getent_kef(provname, NULL, NULL)) != NULL) { 7150Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s exists already."), 7160Sstevel@tonic-gate provname); 7170Sstevel@tonic-gate free_entry(pent); 7180Sstevel@tonic-gate return (FAILURE); 7190Sstevel@tonic-gate } 7200Sstevel@tonic-gate 7210Sstevel@tonic-gate /* Create an entry with provname and mlist. */ 722*7968Sopensolaris@drydog.com if ((pent = create_entry(provname)) == NULL) { 7230Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("out of memory.")); 7240Sstevel@tonic-gate return (FAILURE); 7250Sstevel@tonic-gate } 7260Sstevel@tonic-gate pent->sup_count = get_mech_count(mlist); 7270Sstevel@tonic-gate pent->suplist = mlist; 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate /* Append an entry for this software module to the kcf.conf file. */ 7300Sstevel@tonic-gate if ((str = ent2str(pent)) == NULL) { 7310Sstevel@tonic-gate free_entry(pent); 7320Sstevel@tonic-gate return (FAILURE); 7330Sstevel@tonic-gate } 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) { 7360Sstevel@tonic-gate err = errno; 7370Sstevel@tonic-gate cryptoerror(LOG_STDERR, 7380Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 7390Sstevel@tonic-gate strerror(err)); 7400Sstevel@tonic-gate cryptodebug("failed to open %s for write.", _PATH_KCF_CONF); 7410Sstevel@tonic-gate free_entry(pent); 7420Sstevel@tonic-gate return (FAILURE); 7430Sstevel@tonic-gate } 7440Sstevel@tonic-gate 7450Sstevel@tonic-gate if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 7460Sstevel@tonic-gate err = errno; 7470Sstevel@tonic-gate cryptoerror(LOG_STDERR, 7480Sstevel@tonic-gate gettext("failed to lock the configuration - %s"), 7490Sstevel@tonic-gate strerror(err)); 7500Sstevel@tonic-gate free_entry(pent); 7510Sstevel@tonic-gate (void) fclose(pfile); 7520Sstevel@tonic-gate return (FAILURE); 7530Sstevel@tonic-gate } 7540Sstevel@tonic-gate 7550Sstevel@tonic-gate /* 7560Sstevel@tonic-gate * Create a temporary file in the /etc/crypto directory. 7570Sstevel@tonic-gate */ 7580Sstevel@tonic-gate (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 7590Sstevel@tonic-gate if (mkstemp(tmpfile_name) == -1) { 7600Sstevel@tonic-gate err = errno; 7610Sstevel@tonic-gate cryptoerror(LOG_STDERR, 7620Sstevel@tonic-gate gettext("failed to create a temporary file - %s"), 7630Sstevel@tonic-gate strerror(err)); 7640Sstevel@tonic-gate free_entry(pent); 7650Sstevel@tonic-gate (void) fclose(pfile); 7660Sstevel@tonic-gate return (FAILURE); 7670Sstevel@tonic-gate } 7680Sstevel@tonic-gate 7690Sstevel@tonic-gate if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 7700Sstevel@tonic-gate err = errno; 7710Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 7720Sstevel@tonic-gate tmpfile_name, strerror(err)); 7730Sstevel@tonic-gate free_entry(pent); 7740Sstevel@tonic-gate (void) fclose(pfile); 7750Sstevel@tonic-gate return (FAILURE); 7760Sstevel@tonic-gate } 7770Sstevel@tonic-gate 7780Sstevel@tonic-gate 7790Sstevel@tonic-gate /* 7800Sstevel@tonic-gate * Loop thru the config file. If the provider was reserved within a 7810Sstevel@tonic-gate * package bracket, just uncomment it. Otherwise, append it at 7820Sstevel@tonic-gate * the end. The resulting file will be saved in the temp file first. 7830Sstevel@tonic-gate */ 7840Sstevel@tonic-gate found_count = 0; 7850Sstevel@tonic-gate rc = SUCCESS; 7860Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) { 7870Sstevel@tonic-gate found = B_FALSE; 7880Sstevel@tonic-gate if (buffer[0] == '#') { 7890Sstevel@tonic-gate (void) strlcpy(buffer2, buffer, BUFSIZ); 7900Sstevel@tonic-gate ptr = buffer2; 7910Sstevel@tonic-gate ptr++; 7920Sstevel@tonic-gate if ((name = strtok(ptr, SEP_COLON)) == NULL) { 7930Sstevel@tonic-gate rc = FAILURE; 7940Sstevel@tonic-gate break; 7950Sstevel@tonic-gate } else if (strcmp(provname, name) == 0) { 7960Sstevel@tonic-gate found = B_TRUE; 7970Sstevel@tonic-gate found_count++; 7980Sstevel@tonic-gate } 7990Sstevel@tonic-gate } 8000Sstevel@tonic-gate 8010Sstevel@tonic-gate if (found == B_FALSE) { 8020Sstevel@tonic-gate if (fputs(buffer, pfile_tmp) == EOF) { 8030Sstevel@tonic-gate rc = FAILURE; 8040Sstevel@tonic-gate } 8050Sstevel@tonic-gate } else { 8060Sstevel@tonic-gate if (found_count == 1) { 8070Sstevel@tonic-gate if (fputs(str, pfile_tmp) == EOF) { 8080Sstevel@tonic-gate rc = FAILURE; 8090Sstevel@tonic-gate } 8100Sstevel@tonic-gate } else { 8110Sstevel@tonic-gate /* 8120Sstevel@tonic-gate * Found a second entry with #libname. 813*7968Sopensolaris@drydog.com * Should not happen. The kcf.conf file 8140Sstevel@tonic-gate * is corrupted. Give a warning and skip 8150Sstevel@tonic-gate * this entry. 8160Sstevel@tonic-gate */ 8170Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8180Sstevel@tonic-gate "(Warning) Found an additional reserved " 8190Sstevel@tonic-gate "entry for %s."), provname); 8200Sstevel@tonic-gate } 8210Sstevel@tonic-gate } 8220Sstevel@tonic-gate 8230Sstevel@tonic-gate if (rc == FAILURE) { 8240Sstevel@tonic-gate break; 8250Sstevel@tonic-gate } 8260Sstevel@tonic-gate } 8270Sstevel@tonic-gate (void) fclose(pfile); 8280Sstevel@tonic-gate 8290Sstevel@tonic-gate if (rc == FAILURE) { 8300Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("write error.")); 8310Sstevel@tonic-gate (void) fclose(pfile_tmp); 8320Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 8330Sstevel@tonic-gate err = errno; 8340Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8350Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), tmpfile_name, 8360Sstevel@tonic-gate strerror(err)); 8370Sstevel@tonic-gate } 8380Sstevel@tonic-gate free_entry(pent); 8390Sstevel@tonic-gate return (FAILURE); 8400Sstevel@tonic-gate } 8410Sstevel@tonic-gate 8420Sstevel@tonic-gate if (found_count == 0) { 8430Sstevel@tonic-gate /* 8440Sstevel@tonic-gate * This libname was not in package before, append it to the 8450Sstevel@tonic-gate * end of the temp file. 8460Sstevel@tonic-gate */ 8470Sstevel@tonic-gate if (fputs(str, pfile_tmp) == EOF) { 8480Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8490Sstevel@tonic-gate "failed to write to %s: %s"), tmpfile_name, 8500Sstevel@tonic-gate strerror(errno)); 8510Sstevel@tonic-gate (void) fclose(pfile_tmp); 8520Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 8530Sstevel@tonic-gate err = errno; 8540Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8550Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 8560Sstevel@tonic-gate tmpfile_name, strerror(err)); 8570Sstevel@tonic-gate } 8580Sstevel@tonic-gate free_entry(pent); 8590Sstevel@tonic-gate return (FAILURE); 8600Sstevel@tonic-gate } 8610Sstevel@tonic-gate } 8620Sstevel@tonic-gate 8630Sstevel@tonic-gate if (fclose(pfile_tmp) != 0) { 8640Sstevel@tonic-gate err = errno; 8650Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8660Sstevel@tonic-gate gettext("failed to close %s: %s"), tmpfile_name, 8670Sstevel@tonic-gate strerror(err)); 868*7968Sopensolaris@drydog.com free_entry(pent); 8690Sstevel@tonic-gate return (FAILURE); 8700Sstevel@tonic-gate } 8710Sstevel@tonic-gate 8720Sstevel@tonic-gate if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) { 8730Sstevel@tonic-gate err = errno; 8740Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8750Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 876*7968Sopensolaris@drydog.com strerror(err)); 8770Sstevel@tonic-gate cryptodebug("failed to rename %s to %s: %s", tmpfile_name, 8780Sstevel@tonic-gate _PATH_KCF_CONF, strerror(err)); 8790Sstevel@tonic-gate rc = FAILURE; 8800Sstevel@tonic-gate } else if (chmod(_PATH_KCF_CONF, 8810Sstevel@tonic-gate S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 8820Sstevel@tonic-gate err = errno; 8830Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8840Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 8850Sstevel@tonic-gate strerror(err)); 8860Sstevel@tonic-gate cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF, 8870Sstevel@tonic-gate strerror(err)); 8880Sstevel@tonic-gate rc = FAILURE; 8890Sstevel@tonic-gate } else { 8900Sstevel@tonic-gate rc = SUCCESS; 8910Sstevel@tonic-gate } 8920Sstevel@tonic-gate 8930Sstevel@tonic-gate if (rc == FAILURE) { 8940Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 8950Sstevel@tonic-gate err = errno; 8960Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8970Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 8980Sstevel@tonic-gate tmpfile_name, strerror(err)); 8990Sstevel@tonic-gate } 900*7968Sopensolaris@drydog.com free_entry(pent); 9010Sstevel@tonic-gate return (FAILURE); 9020Sstevel@tonic-gate } 9030Sstevel@tonic-gate 9040Sstevel@tonic-gate 9050Sstevel@tonic-gate /* Inform kernel of this new software module. */ 9060Sstevel@tonic-gate 9070Sstevel@tonic-gate if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) { 9080Sstevel@tonic-gate free_entry(pent); 9090Sstevel@tonic-gate return (FAILURE); 9100Sstevel@tonic-gate } 9110Sstevel@tonic-gate 9120Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 9130Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 9140Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 9150Sstevel@tonic-gate free_entry(pent); 9160Sstevel@tonic-gate free(pload_soft_conf); 9170Sstevel@tonic-gate return (FAILURE); 9180Sstevel@tonic-gate } 9190Sstevel@tonic-gate 9200Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) { 9210Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 9220Sstevel@tonic-gate strerror(errno)); 9230Sstevel@tonic-gate free_entry(pent); 9240Sstevel@tonic-gate free(pload_soft_conf); 9250Sstevel@tonic-gate (void) close(fd); 9260Sstevel@tonic-gate return (FAILURE); 9270Sstevel@tonic-gate } 9280Sstevel@tonic-gate 9290Sstevel@tonic-gate if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 9300Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed, " 9310Sstevel@tonic-gate "return_value = %d", pload_soft_conf->sc_return_value); 9320Sstevel@tonic-gate free_entry(pent); 9330Sstevel@tonic-gate free(pload_soft_conf); 9340Sstevel@tonic-gate (void) close(fd); 9350Sstevel@tonic-gate return (FAILURE); 9360Sstevel@tonic-gate } 9370Sstevel@tonic-gate 9380Sstevel@tonic-gate free_entry(pent); 9390Sstevel@tonic-gate free(pload_soft_conf); 9400Sstevel@tonic-gate (void) close(fd); 9410Sstevel@tonic-gate return (SUCCESS); 9420Sstevel@tonic-gate } 9430Sstevel@tonic-gate 9440Sstevel@tonic-gate /* 9450Sstevel@tonic-gate * Uninstall the software module. This routine first unloads the software 9460Sstevel@tonic-gate * module with 3 ioctl calls, then deletes its entry from the config file. 9470Sstevel@tonic-gate * Removing an entry from the config file needs to be done last to ensure 9480Sstevel@tonic-gate * that there is still an entry if the earlier unload failed for any reason. 9490Sstevel@tonic-gate */ 9500Sstevel@tonic-gate int 9510Sstevel@tonic-gate uninstall_kef(char *provname) 9520Sstevel@tonic-gate { 953*7968Sopensolaris@drydog.com entry_t *pent = NULL; 954*7968Sopensolaris@drydog.com int rc = SUCCESS; 955*7968Sopensolaris@drydog.com boolean_t in_kernel = B_FALSE; 956*7968Sopensolaris@drydog.com boolean_t in_kcfconf = B_FALSE; 957*7968Sopensolaris@drydog.com int fd = -1; 958*7968Sopensolaris@drydog.com crypto_load_soft_config_t *pload_soft_conf = NULL; 9590Sstevel@tonic-gate 960*7968Sopensolaris@drydog.com /* Check to see if the provider exists first. */ 961*7968Sopensolaris@drydog.com if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) { 9620Sstevel@tonic-gate return (FAILURE); 963*7968Sopensolaris@drydog.com } else if (in_kernel == B_FALSE) { 964*7968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext("%s does not exist."), 965*7968Sopensolaris@drydog.com provname); 9660Sstevel@tonic-gate return (FAILURE); 9670Sstevel@tonic-gate } 9680Sstevel@tonic-gate 9690Sstevel@tonic-gate /* 970*7968Sopensolaris@drydog.com * If it is loaded, unload it first. This does 2 ioctl calls: 971*7968Sopensolaris@drydog.com * CRYPTO_UNLOAD_SOFT_MODULE and CRYPTO_LOAD_SOFT_DISABLED. 9720Sstevel@tonic-gate */ 973*7968Sopensolaris@drydog.com if (unload_kef_soft(provname) == FAILURE) { 9740Sstevel@tonic-gate cryptoerror(LOG_STDERR, 975*7968Sopensolaris@drydog.com gettext("failed to unload %s during uninstall.\n"), 976*7968Sopensolaris@drydog.com provname); 9770Sstevel@tonic-gate return (FAILURE); 9780Sstevel@tonic-gate } 9790Sstevel@tonic-gate 9800Sstevel@tonic-gate /* 981*7968Sopensolaris@drydog.com * Inform kernel to remove the configuration of this software module. 9820Sstevel@tonic-gate */ 9830Sstevel@tonic-gate 984*7968Sopensolaris@drydog.com /* Setup ioctl() parameter */ 985*7968Sopensolaris@drydog.com pent = getent_kef(provname, NULL, NULL); 986*7968Sopensolaris@drydog.com if (pent != NULL) { /* in kcf.conf */ 987*7968Sopensolaris@drydog.com in_kcfconf = B_TRUE; 988*7968Sopensolaris@drydog.com free_mechlist(pent->suplist); 989*7968Sopensolaris@drydog.com pent->suplist = NULL; 990*7968Sopensolaris@drydog.com pent->sup_count = 0; 991*7968Sopensolaris@drydog.com } else if ((pent = create_entry(provname)) == NULL) { 992*7968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext("out of memory.")); 993*7968Sopensolaris@drydog.com return (FAILURE); 994*7968Sopensolaris@drydog.com } 995*7968Sopensolaris@drydog.com if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) { 996*7968Sopensolaris@drydog.com free_entry(pent); 997*7968Sopensolaris@drydog.com return (FAILURE); 9980Sstevel@tonic-gate } 9990Sstevel@tonic-gate 1000*7968Sopensolaris@drydog.com /* Open the /dev/cryptoadm device */ 1001*7968Sopensolaris@drydog.com if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 1002*7968Sopensolaris@drydog.com int err = errno; 1003*7968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 1004*7968Sopensolaris@drydog.com ADMIN_IOCTL_DEVICE, strerror(err)); 1005*7968Sopensolaris@drydog.com free_entry(pent); 1006*7968Sopensolaris@drydog.com free(pload_soft_conf); 1007*7968Sopensolaris@drydog.com return (FAILURE); 1008*7968Sopensolaris@drydog.com } 1009*7968Sopensolaris@drydog.com 1010*7968Sopensolaris@drydog.com if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, 1011*7968Sopensolaris@drydog.com pload_soft_conf) == -1) { 1012*7968Sopensolaris@drydog.com cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 1013*7968Sopensolaris@drydog.com strerror(errno)); 1014*7968Sopensolaris@drydog.com free_entry(pent); 1015*7968Sopensolaris@drydog.com free(pload_soft_conf); 1016*7968Sopensolaris@drydog.com (void) close(fd); 10170Sstevel@tonic-gate return (FAILURE); 10180Sstevel@tonic-gate } 10190Sstevel@tonic-gate 1020*7968Sopensolaris@drydog.com if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 1021*7968Sopensolaris@drydog.com cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl = return_value = %d", 1022*7968Sopensolaris@drydog.com pload_soft_conf->sc_return_value); 1023*7968Sopensolaris@drydog.com free_entry(pent); 1024*7968Sopensolaris@drydog.com free(pload_soft_conf); 1025*7968Sopensolaris@drydog.com (void) close(fd); 10260Sstevel@tonic-gate return (FAILURE); 10270Sstevel@tonic-gate } 10280Sstevel@tonic-gate 1029*7968Sopensolaris@drydog.com /* ioctl cleanup */ 1030*7968Sopensolaris@drydog.com free(pload_soft_conf); 1031*7968Sopensolaris@drydog.com (void) close(fd); 1032*7968Sopensolaris@drydog.com 1033*7968Sopensolaris@drydog.com 1034*7968Sopensolaris@drydog.com /* Finally, remove entry from kcf.conf, if present */ 1035*7968Sopensolaris@drydog.com if (in_kcfconf && (pent != NULL)) { 1036*7968Sopensolaris@drydog.com rc = update_kcfconf(pent, DELETE_MODE); 10370Sstevel@tonic-gate } 10380Sstevel@tonic-gate 1039*7968Sopensolaris@drydog.com free_entry(pent); 10400Sstevel@tonic-gate return (rc); 10410Sstevel@tonic-gate } 10420Sstevel@tonic-gate 10430Sstevel@tonic-gate 1044*7968Sopensolaris@drydog.com /* 1045*7968Sopensolaris@drydog.com * Implement the "cryptoadm refresh" command for global zones. 1046*7968Sopensolaris@drydog.com * That is, send the current contents of kcf.conf to the kernel via ioctl(). 1047*7968Sopensolaris@drydog.com */ 10480Sstevel@tonic-gate int 10490Sstevel@tonic-gate refresh(void) 10500Sstevel@tonic-gate { 10510Sstevel@tonic-gate crypto_load_soft_config_t *pload_soft_conf = NULL; 10520Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 10530Sstevel@tonic-gate crypto_load_dev_disabled_t *pload_dev_dis = NULL; 1054*7968Sopensolaris@drydog.com entrylist_t *pdevlist = NULL; 1055*7968Sopensolaris@drydog.com entrylist_t *psoftlist = NULL; 1056*7968Sopensolaris@drydog.com entrylist_t *ptr; 1057*7968Sopensolaris@drydog.com int fd = -1; 1058*7968Sopensolaris@drydog.com int rc = SUCCESS; 1059*7968Sopensolaris@drydog.com int err; 10600Sstevel@tonic-gate 10610Sstevel@tonic-gate if (get_kcfconf_info(&pdevlist, &psoftlist) == FAILURE) { 10620Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to retrieve the providers' " 10630Sstevel@tonic-gate "information from the configuration file - %s.", 10640Sstevel@tonic-gate _PATH_KCF_CONF); 10650Sstevel@tonic-gate return (FAILURE); 10660Sstevel@tonic-gate } 10670Sstevel@tonic-gate 10680Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 10690Sstevel@tonic-gate err = errno; 10700Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 10710Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(err)); 10720Sstevel@tonic-gate free(psoftlist); 10730Sstevel@tonic-gate free(pdevlist); 10740Sstevel@tonic-gate return (FAILURE); 10750Sstevel@tonic-gate } 10760Sstevel@tonic-gate 10770Sstevel@tonic-gate /* 1078*7968Sopensolaris@drydog.com * For each software provider module, pass two sets of information to 1079*7968Sopensolaris@drydog.com * the kernel: the supported list and the disabled list. 10800Sstevel@tonic-gate */ 1081*7968Sopensolaris@drydog.com for (ptr = psoftlist; ptr != NULL; ptr = ptr->next) { 1082*7968Sopensolaris@drydog.com entry_t *pent = ptr->pent; 1083*7968Sopensolaris@drydog.com 10840Sstevel@tonic-gate /* load the supported list */ 1085*7968Sopensolaris@drydog.com if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) { 1086*7968Sopensolaris@drydog.com cryptodebug("setup_soft_conf() failed"); 10870Sstevel@tonic-gate rc = FAILURE; 10880Sstevel@tonic-gate break; 10890Sstevel@tonic-gate } 10900Sstevel@tonic-gate 1091*7968Sopensolaris@drydog.com if (!pent->load) { /* unloaded--mark as loaded */ 1092*7968Sopensolaris@drydog.com pent->load = B_TRUE; 1093*7968Sopensolaris@drydog.com rc = update_kcfconf(pent, MODIFY_MODE); 1094*7968Sopensolaris@drydog.com if (rc != SUCCESS) { 1095*7968Sopensolaris@drydog.com free(pload_soft_conf); 1096*7968Sopensolaris@drydog.com break; 1097*7968Sopensolaris@drydog.com } 1098*7968Sopensolaris@drydog.com } 1099*7968Sopensolaris@drydog.com 11000Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) 11010Sstevel@tonic-gate == -1) { 11020Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 11030Sstevel@tonic-gate strerror(errno)); 11040Sstevel@tonic-gate free(pload_soft_conf); 11050Sstevel@tonic-gate rc = FAILURE; 11060Sstevel@tonic-gate break; 11070Sstevel@tonic-gate } 11080Sstevel@tonic-gate 11090Sstevel@tonic-gate if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 11100Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl " 11110Sstevel@tonic-gate "return_value = %d", 11120Sstevel@tonic-gate pload_soft_conf->sc_return_value); 11130Sstevel@tonic-gate free(pload_soft_conf); 11140Sstevel@tonic-gate rc = FAILURE; 11150Sstevel@tonic-gate break; 11160Sstevel@tonic-gate } 11170Sstevel@tonic-gate 1118*7968Sopensolaris@drydog.com free(pload_soft_conf); 1119*7968Sopensolaris@drydog.com 11200Sstevel@tonic-gate /* load the disabled list */ 11210Sstevel@tonic-gate if (ptr->pent->dis_count != 0) { 11220Sstevel@tonic-gate pload_soft_dis = setup_soft_dis(ptr->pent); 11230Sstevel@tonic-gate if (pload_soft_dis == NULL) { 1124*7968Sopensolaris@drydog.com cryptodebug("setup_soft_dis() failed"); 1125*7968Sopensolaris@drydog.com free(pload_soft_dis); 11260Sstevel@tonic-gate rc = FAILURE; 11270Sstevel@tonic-gate break; 11280Sstevel@tonic-gate } 11290Sstevel@tonic-gate 11300Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, 11310Sstevel@tonic-gate pload_soft_dis) == -1) { 11320Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 11330Sstevel@tonic-gate "failed: %s", strerror(errno)); 11340Sstevel@tonic-gate free(pload_soft_dis); 11350Sstevel@tonic-gate rc = FAILURE; 11360Sstevel@tonic-gate break; 11370Sstevel@tonic-gate } 11380Sstevel@tonic-gate 11390Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != 11400Sstevel@tonic-gate CRYPTO_SUCCESS) { 11410Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 11420Sstevel@tonic-gate "return_value = %d", 11430Sstevel@tonic-gate pload_soft_dis->sd_return_value); 11440Sstevel@tonic-gate free(pload_soft_dis); 11450Sstevel@tonic-gate rc = FAILURE; 11460Sstevel@tonic-gate break; 11470Sstevel@tonic-gate } 11480Sstevel@tonic-gate free(pload_soft_dis); 11490Sstevel@tonic-gate } 11500Sstevel@tonic-gate } 11510Sstevel@tonic-gate 11520Sstevel@tonic-gate if (rc != SUCCESS) { 11530Sstevel@tonic-gate (void) close(fd); 11540Sstevel@tonic-gate return (rc); 11550Sstevel@tonic-gate } 11560Sstevel@tonic-gate 11570Sstevel@tonic-gate 1158*7968Sopensolaris@drydog.com /* 1159*7968Sopensolaris@drydog.com * For each hardware provider module, pass the disabled list 1160*7968Sopensolaris@drydog.com * information to the kernel. 1161*7968Sopensolaris@drydog.com */ 1162*7968Sopensolaris@drydog.com for (ptr = pdevlist; ptr != NULL; ptr = ptr->next) { 11630Sstevel@tonic-gate /* load the disabled list */ 11640Sstevel@tonic-gate if (ptr->pent->dis_count != 0) { 11650Sstevel@tonic-gate pload_dev_dis = setup_dev_dis(ptr->pent); 11660Sstevel@tonic-gate if (pload_dev_dis == NULL) { 11670Sstevel@tonic-gate rc = FAILURE; 11680Sstevel@tonic-gate break; 11690Sstevel@tonic-gate } 11700Sstevel@tonic-gate 11710Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) 11720Sstevel@tonic-gate == -1) { 11730Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 11740Sstevel@tonic-gate "failed: %s", strerror(errno)); 11750Sstevel@tonic-gate free(pload_dev_dis); 11760Sstevel@tonic-gate rc = FAILURE; 11770Sstevel@tonic-gate break; 11780Sstevel@tonic-gate } 11790Sstevel@tonic-gate 11800Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 11810Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 11820Sstevel@tonic-gate "return_value = %d", 11830Sstevel@tonic-gate pload_dev_dis->dd_return_value); 11840Sstevel@tonic-gate free(pload_dev_dis); 11850Sstevel@tonic-gate rc = FAILURE; 11860Sstevel@tonic-gate break; 11870Sstevel@tonic-gate } 11880Sstevel@tonic-gate free(pload_dev_dis); 11890Sstevel@tonic-gate } 11900Sstevel@tonic-gate } 11910Sstevel@tonic-gate 11920Sstevel@tonic-gate (void) close(fd); 11930Sstevel@tonic-gate return (rc); 11940Sstevel@tonic-gate } 11950Sstevel@tonic-gate 11960Sstevel@tonic-gate /* 11970Sstevel@tonic-gate * Unload the kernel software provider. Before calling this function, the 1198*7968Sopensolaris@drydog.com * caller should check to see if the provider is in the kernel. 1199*7968Sopensolaris@drydog.com * 1200*7968Sopensolaris@drydog.com * This routine makes 2 ioctl calls to remove it completely from the kernel: 1201*7968Sopensolaris@drydog.com * CRYPTO_UNLOAD_SOFT_MODULE - does a modunload of the KCF module 1202*7968Sopensolaris@drydog.com * CRYPTO_LOAD_SOFT_DISABLED - updates kernel disabled mechanism list 1203*7968Sopensolaris@drydog.com * 1204*7968Sopensolaris@drydog.com * This implements part of "cryptoadm unload" and "cryptoadm uninstall". 12050Sstevel@tonic-gate */ 12060Sstevel@tonic-gate int 1207*7968Sopensolaris@drydog.com unload_kef_soft(char *provname) 12080Sstevel@tonic-gate { 1209*7968Sopensolaris@drydog.com crypto_unload_soft_module_t *punload_soft = NULL; 12100Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 1211*7968Sopensolaris@drydog.com entry_t *pent = NULL; 1212*7968Sopensolaris@drydog.com int fd = -1; 1213*7968Sopensolaris@drydog.com int err; 12140Sstevel@tonic-gate 12150Sstevel@tonic-gate if (provname == NULL) { 12160Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 12170Sstevel@tonic-gate return (FAILURE); 12180Sstevel@tonic-gate } 12190Sstevel@tonic-gate 1220*7968Sopensolaris@drydog.com pent = getent_kef(provname, NULL, NULL); 1221*7968Sopensolaris@drydog.com if (pent == NULL) { /* not in kcf.conf */ 12221971Skrishna /* Construct an entry using the provname */ 1223*7968Sopensolaris@drydog.com pent = create_entry(provname); 12241971Skrishna if (pent == NULL) { 12251971Skrishna cryptoerror(LOG_STDERR, gettext("out of memory.")); 12261971Skrishna return (FAILURE); 12271971Skrishna } 12280Sstevel@tonic-gate } 12290Sstevel@tonic-gate 12300Sstevel@tonic-gate /* Open the admin_ioctl_device */ 12310Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 12320Sstevel@tonic-gate err = errno; 12330Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 12340Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(err)); 1235*7968Sopensolaris@drydog.com free_entry(pent); 12360Sstevel@tonic-gate return (FAILURE); 12370Sstevel@tonic-gate } 12380Sstevel@tonic-gate 12390Sstevel@tonic-gate /* Inform kernel to unload this software module */ 12400Sstevel@tonic-gate if ((punload_soft = setup_unload_soft(pent)) == NULL) { 1241*7968Sopensolaris@drydog.com free_entry(pent); 12420Sstevel@tonic-gate (void) close(fd); 12430Sstevel@tonic-gate return (FAILURE); 12440Sstevel@tonic-gate } 12450Sstevel@tonic-gate 12460Sstevel@tonic-gate if (ioctl(fd, CRYPTO_UNLOAD_SOFT_MODULE, punload_soft) == -1) { 12470Sstevel@tonic-gate cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl failed: %s", 12480Sstevel@tonic-gate strerror(errno)); 12490Sstevel@tonic-gate free_entry(pent); 12500Sstevel@tonic-gate free(punload_soft); 12510Sstevel@tonic-gate (void) close(fd); 12520Sstevel@tonic-gate return (FAILURE); 12530Sstevel@tonic-gate } 12540Sstevel@tonic-gate 12550Sstevel@tonic-gate if (punload_soft->sm_return_value != CRYPTO_SUCCESS) { 12560Sstevel@tonic-gate cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl return_value = " 12570Sstevel@tonic-gate "%d", punload_soft->sm_return_value); 12580Sstevel@tonic-gate /* 12597334SDaniel.Anderson@Sun.COM * If the return value is CRYPTO_UNKNOWN_PROVIDER, it means 12600Sstevel@tonic-gate * that the provider is not registered yet. Should just 12610Sstevel@tonic-gate * continue. 12620Sstevel@tonic-gate */ 12630Sstevel@tonic-gate if (punload_soft->sm_return_value != CRYPTO_UNKNOWN_PROVIDER) { 12640Sstevel@tonic-gate free_entry(pent); 12650Sstevel@tonic-gate free(punload_soft); 12660Sstevel@tonic-gate (void) close(fd); 12670Sstevel@tonic-gate return (FAILURE); 12680Sstevel@tonic-gate } 12690Sstevel@tonic-gate } 12700Sstevel@tonic-gate 12710Sstevel@tonic-gate free(punload_soft); 12720Sstevel@tonic-gate 12730Sstevel@tonic-gate /* Inform kernel to remove the disabled entries if any */ 12740Sstevel@tonic-gate if (pent->dis_count == 0) { 12750Sstevel@tonic-gate free_entry(pent); 12760Sstevel@tonic-gate (void) close(fd); 12770Sstevel@tonic-gate return (SUCCESS); 12780Sstevel@tonic-gate } else { 12790Sstevel@tonic-gate free_mechlist(pent->dislist); 12800Sstevel@tonic-gate pent->dislist = NULL; 12810Sstevel@tonic-gate pent->dis_count = 0; 12820Sstevel@tonic-gate } 12830Sstevel@tonic-gate 12840Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 12850Sstevel@tonic-gate free_entry(pent); 12860Sstevel@tonic-gate (void) close(fd); 12870Sstevel@tonic-gate return (FAILURE); 12880Sstevel@tonic-gate } 12890Sstevel@tonic-gate 12900Sstevel@tonic-gate /* pent is no longer needed; free it */ 12910Sstevel@tonic-gate free_entry(pent); 12920Sstevel@tonic-gate 12930Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) { 12940Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s", 12950Sstevel@tonic-gate strerror(errno)); 12960Sstevel@tonic-gate free(pload_soft_dis); 12970Sstevel@tonic-gate (void) close(fd); 12980Sstevel@tonic-gate return (FAILURE); 12990Sstevel@tonic-gate } 13000Sstevel@tonic-gate 13010Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 13020Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = " 13030Sstevel@tonic-gate "%d", pload_soft_dis->sd_return_value); 13040Sstevel@tonic-gate free(pload_soft_dis); 13050Sstevel@tonic-gate (void) close(fd); 13060Sstevel@tonic-gate return (FAILURE); 13070Sstevel@tonic-gate } 13080Sstevel@tonic-gate 13090Sstevel@tonic-gate free(pload_soft_dis); 13100Sstevel@tonic-gate (void) close(fd); 13110Sstevel@tonic-gate return (SUCCESS); 13120Sstevel@tonic-gate } 13130Sstevel@tonic-gate 13140Sstevel@tonic-gate 13150Sstevel@tonic-gate /* 13160Sstevel@tonic-gate * Check if a hardware provider is valid. If it is valid, returns its device 13170Sstevel@tonic-gate * name, instance number and the number of mechanisms it supports. 13180Sstevel@tonic-gate */ 13190Sstevel@tonic-gate static int 13200Sstevel@tonic-gate check_hardware_provider(char *provname, char *pname, int *pnum, int *pcount) 13210Sstevel@tonic-gate { 13220Sstevel@tonic-gate crypto_get_dev_list_t *dev_list = NULL; 13230Sstevel@tonic-gate int i; 13240Sstevel@tonic-gate 13250Sstevel@tonic-gate if (provname == NULL) { 13260Sstevel@tonic-gate return (FAILURE); 13270Sstevel@tonic-gate } 13280Sstevel@tonic-gate 13290Sstevel@tonic-gate /* First, get the device name and the instance number from provname */ 13300Sstevel@tonic-gate if (split_hw_provname(provname, pname, pnum) == FAILURE) { 13310Sstevel@tonic-gate return (FAILURE); 13320Sstevel@tonic-gate } 13330Sstevel@tonic-gate 13340Sstevel@tonic-gate /* 13350Sstevel@tonic-gate * Get the complete device list from kernel and check if this provider 13360Sstevel@tonic-gate * is in the list. 13370Sstevel@tonic-gate */ 13380Sstevel@tonic-gate if (get_dev_list(&dev_list) == FAILURE) { 13390Sstevel@tonic-gate return (FAILURE); 13400Sstevel@tonic-gate } 13410Sstevel@tonic-gate 13420Sstevel@tonic-gate for (i = 0; i < dev_list->dl_dev_count; i++) { 13430Sstevel@tonic-gate if ((strcmp(dev_list->dl_devs[i].le_dev_name, pname) == 0) && 13440Sstevel@tonic-gate (dev_list->dl_devs[i].le_dev_instance == *pnum)) { 13450Sstevel@tonic-gate break; 13460Sstevel@tonic-gate } 13470Sstevel@tonic-gate } 13480Sstevel@tonic-gate 13490Sstevel@tonic-gate if (i == dev_list->dl_dev_count) { 13500Sstevel@tonic-gate /* didn't find this provider in the kernel device list */ 13510Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s does not exist."), 13520Sstevel@tonic-gate provname); 13530Sstevel@tonic-gate free(dev_list); 13540Sstevel@tonic-gate return (FAILURE); 13550Sstevel@tonic-gate } 13560Sstevel@tonic-gate 13570Sstevel@tonic-gate /* This provider is valid. Get its mechanism count */ 13580Sstevel@tonic-gate *pcount = dev_list->dl_devs[i].le_mechanism_count; 13590Sstevel@tonic-gate 13600Sstevel@tonic-gate free(dev_list); 13610Sstevel@tonic-gate return (SUCCESS); 13620Sstevel@tonic-gate } 1363