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 5*1971Skrishna * Common Development and Distribution License (the "License"). 6*1971Skrishna * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*1971Skrishna * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <fcntl.h> 290Sstevel@tonic-gate #include <stdio.h> 300Sstevel@tonic-gate #include <stdlib.h> 310Sstevel@tonic-gate #include <strings.h> 320Sstevel@tonic-gate #include <unistd.h> 330Sstevel@tonic-gate #include <locale.h> 340Sstevel@tonic-gate #include <libgen.h> 350Sstevel@tonic-gate #include <sys/types.h> 360Sstevel@tonic-gate #include <sys/stat.h> 370Sstevel@tonic-gate #include <sys/crypto/ioctladmin.h> 380Sstevel@tonic-gate #include <signal.h> 390Sstevel@tonic-gate #include <sys/crypto/elfsign.h> 400Sstevel@tonic-gate #include "cryptoadm.h" 410Sstevel@tonic-gate 420Sstevel@tonic-gate static int err; /* to store the value of errno in case being overwritten */ 430Sstevel@tonic-gate static int check_hardware_provider(char *, char *, int *, int *); 440Sstevel@tonic-gate 450Sstevel@tonic-gate /* 460Sstevel@tonic-gate * Display the mechanism list for a kernel software provider. 470Sstevel@tonic-gate */ 480Sstevel@tonic-gate int 490Sstevel@tonic-gate list_mechlist_for_soft(char *provname) 500Sstevel@tonic-gate { 510Sstevel@tonic-gate mechlist_t *pmechlist; 520Sstevel@tonic-gate int rc; 530Sstevel@tonic-gate 540Sstevel@tonic-gate if (provname == NULL) { 550Sstevel@tonic-gate return (FAILURE); 560Sstevel@tonic-gate } 570Sstevel@tonic-gate 580Sstevel@tonic-gate rc = get_soft_info(provname, &pmechlist); 590Sstevel@tonic-gate if (rc == SUCCESS) { 600Sstevel@tonic-gate (void) filter_mechlist(&pmechlist, RANDOM); 610Sstevel@tonic-gate print_mechlist(provname, pmechlist); 620Sstevel@tonic-gate free_mechlist(pmechlist); 630Sstevel@tonic-gate } else { 640Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 650Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 660Sstevel@tonic-gate provname); 670Sstevel@tonic-gate } 680Sstevel@tonic-gate 690Sstevel@tonic-gate return (rc); 700Sstevel@tonic-gate 710Sstevel@tonic-gate } 720Sstevel@tonic-gate 730Sstevel@tonic-gate /* 740Sstevel@tonic-gate * Display the mechanism list for a kernel hardware provider. 750Sstevel@tonic-gate */ 760Sstevel@tonic-gate int 770Sstevel@tonic-gate list_mechlist_for_hard(char *provname) 780Sstevel@tonic-gate { 790Sstevel@tonic-gate mechlist_t *pmechlist; 800Sstevel@tonic-gate char devname[MAXNAMELEN]; 810Sstevel@tonic-gate int inst_num; 820Sstevel@tonic-gate int count; 830Sstevel@tonic-gate int rc = SUCCESS; 840Sstevel@tonic-gate 850Sstevel@tonic-gate if (provname == NULL) { 860Sstevel@tonic-gate return (FAILURE); 870Sstevel@tonic-gate } 880Sstevel@tonic-gate 890Sstevel@tonic-gate /* 900Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 910Sstevel@tonic-gate * mechanisms also. 920Sstevel@tonic-gate */ 930Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) == 940Sstevel@tonic-gate FAILURE) { 950Sstevel@tonic-gate return (FAILURE); 960Sstevel@tonic-gate } 970Sstevel@tonic-gate 980Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 990Sstevel@tonic-gate if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) == 1000Sstevel@tonic-gate SUCCESS) { 1010Sstevel@tonic-gate (void) filter_mechlist(&pmechlist, RANDOM); 1020Sstevel@tonic-gate print_mechlist(provname, pmechlist); 1030Sstevel@tonic-gate free_mechlist(pmechlist); 1040Sstevel@tonic-gate } 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate return (rc); 1070Sstevel@tonic-gate } 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate /* 1110Sstevel@tonic-gate * Display the policy information for a kernel software provider. 1120Sstevel@tonic-gate */ 1130Sstevel@tonic-gate int 1140Sstevel@tonic-gate list_policy_for_soft(char *provname) 1150Sstevel@tonic-gate { 1160Sstevel@tonic-gate int rc; 1170Sstevel@tonic-gate entry_t *pent = NULL; 1180Sstevel@tonic-gate mechlist_t *pmechlist; 1190Sstevel@tonic-gate boolean_t has_random = B_FALSE; 1200Sstevel@tonic-gate boolean_t has_mechs = B_FALSE; 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate if (provname == NULL) { 1230Sstevel@tonic-gate return (FAILURE); 1240Sstevel@tonic-gate } 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate if ((pent = getent_kef(provname)) == NULL) { 1270Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s does not exist."), 1280Sstevel@tonic-gate provname); 1290Sstevel@tonic-gate return (FAILURE); 1300Sstevel@tonic-gate } 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate rc = get_soft_info(provname, &pmechlist); 1330Sstevel@tonic-gate if (rc == SUCCESS) { 1340Sstevel@tonic-gate has_random = filter_mechlist(&pmechlist, RANDOM); 1350Sstevel@tonic-gate if (pmechlist != NULL) { 1360Sstevel@tonic-gate has_mechs = B_TRUE; 1370Sstevel@tonic-gate free_mechlist(pmechlist); 1380Sstevel@tonic-gate } 1390Sstevel@tonic-gate } else { 1400Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 1410Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 1420Sstevel@tonic-gate provname); 1430Sstevel@tonic-gate return (rc); 1440Sstevel@tonic-gate } 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate print_kef_policy(pent, has_random, has_mechs); 1470Sstevel@tonic-gate free_entry(pent); 1480Sstevel@tonic-gate return (SUCCESS); 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate /* 1540Sstevel@tonic-gate * Display the policy information for a kernel hardware provider. 1550Sstevel@tonic-gate */ 1560Sstevel@tonic-gate int 1570Sstevel@tonic-gate list_policy_for_hard(char *provname) 1580Sstevel@tonic-gate { 1590Sstevel@tonic-gate entry_t *pent; 1600Sstevel@tonic-gate boolean_t is_active; 1610Sstevel@tonic-gate mechlist_t *pmechlist; 1620Sstevel@tonic-gate char devname[MAXNAMELEN]; 1630Sstevel@tonic-gate int inst_num; 1640Sstevel@tonic-gate int count; 1650Sstevel@tonic-gate int rc = SUCCESS; 1660Sstevel@tonic-gate boolean_t has_random = B_FALSE; 1670Sstevel@tonic-gate boolean_t has_mechs = B_FALSE; 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate if (provname == NULL) { 1700Sstevel@tonic-gate return (FAILURE); 1710Sstevel@tonic-gate } 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate /* 1740Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 1750Sstevel@tonic-gate * mechanisms also. 1760Sstevel@tonic-gate */ 1770Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) == 1780Sstevel@tonic-gate FAILURE) { 1790Sstevel@tonic-gate return (FAILURE); 1800Sstevel@tonic-gate } 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 1830Sstevel@tonic-gate if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) == 1840Sstevel@tonic-gate SUCCESS) { 1850Sstevel@tonic-gate has_random = filter_mechlist(&pmechlist, RANDOM); 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate if (pmechlist != NULL) { 1880Sstevel@tonic-gate has_mechs = B_TRUE; 1890Sstevel@tonic-gate free_mechlist(pmechlist); 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate } else { 1920Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 1930Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 1940Sstevel@tonic-gate devname); 1950Sstevel@tonic-gate return (rc); 1960Sstevel@tonic-gate } 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate /* 1990Sstevel@tonic-gate * If the hardware provider has an entry in the kcf.conf file, 2000Sstevel@tonic-gate * some of its mechanisms must have been disabled. Print out 2010Sstevel@tonic-gate * the disabled list from the config file entry. Otherwise, 2020Sstevel@tonic-gate * if it is active, then all the mechanisms for it are enabled. 2030Sstevel@tonic-gate */ 2040Sstevel@tonic-gate if ((pent = getent_kef(provname)) != NULL) { 2050Sstevel@tonic-gate print_kef_policy(pent, has_random, has_mechs); 2060Sstevel@tonic-gate free_entry(pent); 2070Sstevel@tonic-gate return (SUCCESS); 2080Sstevel@tonic-gate } else { 2090Sstevel@tonic-gate if (check_active_for_hard(provname, &is_active) == 2100Sstevel@tonic-gate FAILURE) { 2110Sstevel@tonic-gate return (FAILURE); 2120Sstevel@tonic-gate } else if (is_active == B_TRUE) { 2130Sstevel@tonic-gate (void) printf(gettext( 2140Sstevel@tonic-gate "%s: all mechanisms are enabled."), provname); 2150Sstevel@tonic-gate if (has_random) 2160Sstevel@tonic-gate /* 2170Sstevel@tonic-gate * TRANSLATION_NOTE: 2180Sstevel@tonic-gate * "random" is a keyword and not to be 2190Sstevel@tonic-gate * translated. 2200Sstevel@tonic-gate */ 2210Sstevel@tonic-gate (void) printf(gettext(" %s is enabled.\n"), 2220Sstevel@tonic-gate "random"); 2230Sstevel@tonic-gate else 2240Sstevel@tonic-gate (void) printf("\n"); 2250Sstevel@tonic-gate return (SUCCESS); 2260Sstevel@tonic-gate } else { 2270Sstevel@tonic-gate cryptoerror(LOG_STDERR, 2280Sstevel@tonic-gate gettext("%s does not exist."), provname); 2290Sstevel@tonic-gate return (FAILURE); 2300Sstevel@tonic-gate } 2310Sstevel@tonic-gate } 2320Sstevel@tonic-gate } 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate int 2370Sstevel@tonic-gate disable_kef_hardware(char *provname, boolean_t rndflag, boolean_t allflag, 2380Sstevel@tonic-gate mechlist_t *dislist) 2390Sstevel@tonic-gate { 2400Sstevel@tonic-gate crypto_load_dev_disabled_t *pload_dev_dis; 2410Sstevel@tonic-gate mechlist_t *infolist; 2420Sstevel@tonic-gate entry_t *pent; 2430Sstevel@tonic-gate boolean_t new_dev_entry = B_FALSE; 2440Sstevel@tonic-gate char devname[MAXNAMELEN]; 2450Sstevel@tonic-gate int inst_num; 2460Sstevel@tonic-gate int count; 2470Sstevel@tonic-gate int fd; 2480Sstevel@tonic-gate int rc = SUCCESS; 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate if (provname == NULL) { 2510Sstevel@tonic-gate return (FAILURE); 2520Sstevel@tonic-gate } 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate /* 2550Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 2560Sstevel@tonic-gate * mechanisms also. 2570Sstevel@tonic-gate */ 2580Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) 2590Sstevel@tonic-gate == FAILURE) { 2600Sstevel@tonic-gate return (FAILURE); 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 2640Sstevel@tonic-gate if (get_dev_info(devname, inst_num, count, &infolist) == FAILURE) { 2650Sstevel@tonic-gate return (FAILURE); 2660Sstevel@tonic-gate } 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate /* 2690Sstevel@tonic-gate * Get the entry of this hardware provider from the config file. 2700Sstevel@tonic-gate * If there is no entry yet, create one for it. 2710Sstevel@tonic-gate */ 2720Sstevel@tonic-gate if ((pent = getent_kef(provname)) == NULL) { 2730Sstevel@tonic-gate if ((pent = malloc(sizeof (entry_t))) == NULL) { 2740Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("out of memory.")); 2750Sstevel@tonic-gate free_mechlist(infolist); 2760Sstevel@tonic-gate return (FAILURE); 2770Sstevel@tonic-gate } 2780Sstevel@tonic-gate new_dev_entry = B_TRUE; 2790Sstevel@tonic-gate (void) strlcpy(pent->name, provname, MAXNAMELEN); 2800Sstevel@tonic-gate pent->suplist = NULL; 2810Sstevel@tonic-gate pent->sup_count = 0; 2820Sstevel@tonic-gate pent->dislist = NULL; 2830Sstevel@tonic-gate pent->dis_count = 0; 2840Sstevel@tonic-gate } 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate /* 2870Sstevel@tonic-gate * kCF treats random as an internal mechanism. So, we need to 2880Sstevel@tonic-gate * filter it from the mechanism list here, if we are NOT disabling 2890Sstevel@tonic-gate * or enabling the random feature. Note that we map random feature at 2900Sstevel@tonic-gate * cryptoadm(1M) level to the "random" mechanism in kCF. 2910Sstevel@tonic-gate */ 2920Sstevel@tonic-gate if (!rndflag) { 2930Sstevel@tonic-gate (void) filter_mechlist(&infolist, RANDOM); 2940Sstevel@tonic-gate } 2950Sstevel@tonic-gate 2960Sstevel@tonic-gate /* Calculate the new disabled list */ 2970Sstevel@tonic-gate if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) { 2980Sstevel@tonic-gate free_entry(pent); 2990Sstevel@tonic-gate return (FAILURE); 3000Sstevel@tonic-gate } 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate /* If no mechanisms are to be disabled, return */ 3030Sstevel@tonic-gate if (pent->dis_count == 0) { 3040Sstevel@tonic-gate free_entry(pent); 3050Sstevel@tonic-gate return (SUCCESS); 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate /* Update the config file with the new entry or the updated entry */ 3090Sstevel@tonic-gate if (new_dev_entry) { 3100Sstevel@tonic-gate rc = update_kcfconf(pent, ADD_MODE); 3110Sstevel@tonic-gate } else { 3120Sstevel@tonic-gate rc = update_kcfconf(pent, MODIFY_MODE); 3130Sstevel@tonic-gate } 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate if (rc == FAILURE) { 3160Sstevel@tonic-gate free_entry(pent); 3170Sstevel@tonic-gate return (FAILURE); 3180Sstevel@tonic-gate } 3190Sstevel@tonic-gate 3200Sstevel@tonic-gate /* Inform kernel about the new disabled mechanism list */ 3210Sstevel@tonic-gate if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) { 3220Sstevel@tonic-gate free_entry(pent); 3230Sstevel@tonic-gate return (FAILURE); 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate free_entry(pent); 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 3280Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 3290Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 3300Sstevel@tonic-gate free(pload_dev_dis); 3310Sstevel@tonic-gate return (FAILURE); 3320Sstevel@tonic-gate } 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) { 3350Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: %s", 3360Sstevel@tonic-gate strerror(errno)); 3370Sstevel@tonic-gate free(pload_dev_dis); 3380Sstevel@tonic-gate (void) close(fd); 3390Sstevel@tonic-gate return (FAILURE); 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 3430Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl return_value = " 3440Sstevel@tonic-gate "%d", pload_dev_dis->dd_return_value); 3450Sstevel@tonic-gate free(pload_dev_dis); 3460Sstevel@tonic-gate (void) close(fd); 3470Sstevel@tonic-gate return (FAILURE); 3480Sstevel@tonic-gate } 3490Sstevel@tonic-gate 3500Sstevel@tonic-gate free(pload_dev_dis); 3510Sstevel@tonic-gate (void) close(fd); 3520Sstevel@tonic-gate return (SUCCESS); 3530Sstevel@tonic-gate } 3540Sstevel@tonic-gate 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate int 3580Sstevel@tonic-gate disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag, 3590Sstevel@tonic-gate mechlist_t *dislist) 3600Sstevel@tonic-gate { 3610Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 3620Sstevel@tonic-gate mechlist_t *infolist; 3630Sstevel@tonic-gate entry_t *pent; 3640Sstevel@tonic-gate boolean_t is_active; 3650Sstevel@tonic-gate int fd; 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate if (provname == NULL) { 3680Sstevel@tonic-gate return (FAILURE); 3690Sstevel@tonic-gate } 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate /* Get the entry of this provider from the config file. */ 3720Sstevel@tonic-gate if ((pent = getent_kef(provname)) == NULL) { 3730Sstevel@tonic-gate cryptoerror(LOG_STDERR, 3740Sstevel@tonic-gate gettext("%s does not exist."), provname); 3750Sstevel@tonic-gate return (FAILURE); 3760Sstevel@tonic-gate } 3770Sstevel@tonic-gate 3780Sstevel@tonic-gate /* 3790Sstevel@tonic-gate * Check if the kernel software provider is currently unloaded. 3800Sstevel@tonic-gate * If it is unloaded, return FAILURE, because the disable subcommand 3810Sstevel@tonic-gate * can not perform on inactive (unloaded) providers. 3820Sstevel@tonic-gate */ 3830Sstevel@tonic-gate if (check_active_for_soft(provname, &is_active) == FAILURE) { 3840Sstevel@tonic-gate free_entry(pent); 3850Sstevel@tonic-gate return (FAILURE); 3860Sstevel@tonic-gate } else if (is_active == B_FALSE) { 3870Sstevel@tonic-gate /* 3880Sstevel@tonic-gate * TRANSLATION_NOTE: 3890Sstevel@tonic-gate * "disable" is a keyword and not to be translated. 3900Sstevel@tonic-gate */ 3910Sstevel@tonic-gate cryptoerror(LOG_STDERR, 3920Sstevel@tonic-gate gettext("can not do %1$s on an unloaded " 3930Sstevel@tonic-gate "kernel software provider -- %2$s."), "disable", provname); 3940Sstevel@tonic-gate free_entry(pent); 3950Sstevel@tonic-gate return (FAILURE); 3960Sstevel@tonic-gate } 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate /* Get the mechanism list for the software provider */ 3990Sstevel@tonic-gate if (get_soft_info(provname, &infolist) == FAILURE) { 4000Sstevel@tonic-gate free(pent); 4010Sstevel@tonic-gate return (FAILURE); 4020Sstevel@tonic-gate } 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate /* See comments in disable_kef_hardware() */ 4050Sstevel@tonic-gate if (!rndflag) { 4060Sstevel@tonic-gate (void) filter_mechlist(&infolist, RANDOM); 4070Sstevel@tonic-gate } 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate /* Calculate the new disabled list */ 4100Sstevel@tonic-gate if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) { 4110Sstevel@tonic-gate free_entry(pent); 4120Sstevel@tonic-gate free_mechlist(infolist); 4130Sstevel@tonic-gate return (FAILURE); 4140Sstevel@tonic-gate } 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate /* infolist is no longer needed; free it */ 4170Sstevel@tonic-gate free_mechlist(infolist); 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate /* Update the kcf.conf file with the updated entry */ 4200Sstevel@tonic-gate if (update_kcfconf(pent, MODIFY_MODE) == FAILURE) { 4210Sstevel@tonic-gate free_entry(pent); 4220Sstevel@tonic-gate return (FAILURE); 4230Sstevel@tonic-gate } 4240Sstevel@tonic-gate 4250Sstevel@tonic-gate /* Inform kernel about the new disabled list. */ 4260Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 4270Sstevel@tonic-gate free_entry(pent); 4280Sstevel@tonic-gate return (FAILURE); 4290Sstevel@tonic-gate } 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate /* pent is no longer needed; free it. */ 4320Sstevel@tonic-gate free_entry(pent); 4330Sstevel@tonic-gate 4340Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 4350Sstevel@tonic-gate cryptoerror(LOG_STDERR, 4360Sstevel@tonic-gate gettext("failed to open %s for RW: %s"), 4370Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 4380Sstevel@tonic-gate free(pload_soft_dis); 4390Sstevel@tonic-gate return (FAILURE); 4400Sstevel@tonic-gate } 4410Sstevel@tonic-gate 4420Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) { 4430Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s", 4440Sstevel@tonic-gate strerror(errno)); 4450Sstevel@tonic-gate free(pload_soft_dis); 4460Sstevel@tonic-gate (void) close(fd); 4470Sstevel@tonic-gate return (FAILURE); 4480Sstevel@tonic-gate } 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 4510Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = " 4520Sstevel@tonic-gate "%d", pload_soft_dis->sd_return_value); 4530Sstevel@tonic-gate free(pload_soft_dis); 4540Sstevel@tonic-gate (void) close(fd); 4550Sstevel@tonic-gate return (FAILURE); 4560Sstevel@tonic-gate } 4570Sstevel@tonic-gate 4580Sstevel@tonic-gate free(pload_soft_dis); 4590Sstevel@tonic-gate (void) close(fd); 4600Sstevel@tonic-gate return (SUCCESS); 4610Sstevel@tonic-gate } 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate 4640Sstevel@tonic-gate int 4650Sstevel@tonic-gate enable_kef(char *provname, boolean_t rndflag, boolean_t allflag, 4660Sstevel@tonic-gate mechlist_t *mlist) 4670Sstevel@tonic-gate { 4680Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 4690Sstevel@tonic-gate crypto_load_dev_disabled_t *pload_dev_dis = NULL; 4700Sstevel@tonic-gate entry_t *pent; 4710Sstevel@tonic-gate boolean_t redo_flag = B_FALSE; 4720Sstevel@tonic-gate int fd; 4730Sstevel@tonic-gate int rc = SUCCESS; 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate 4760Sstevel@tonic-gate /* Get the entry with the provider name from the kcf.conf file */ 4770Sstevel@tonic-gate pent = getent_kef(provname); 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate if (is_device(provname)) { 4800Sstevel@tonic-gate if (pent == NULL) { 4810Sstevel@tonic-gate /* 4820Sstevel@tonic-gate * This device doesn't have an entry in the config 4830Sstevel@tonic-gate * file, therefore nothing is disabled. 4840Sstevel@tonic-gate */ 4850Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 4860Sstevel@tonic-gate "all mechanisms are enabled already for %s."), 4870Sstevel@tonic-gate provname); 4880Sstevel@tonic-gate return (SUCCESS); 4890Sstevel@tonic-gate } 4900Sstevel@tonic-gate } else { /* a software module */ 4910Sstevel@tonic-gate if (pent == NULL) { 4920Sstevel@tonic-gate cryptoerror(LOG_STDERR, 4930Sstevel@tonic-gate gettext("%s does not exist."), provname); 4940Sstevel@tonic-gate return (FAILURE); 4950Sstevel@tonic-gate } else if (pent->dis_count == 0) { 4960Sstevel@tonic-gate /* nothing to be enabled. */ 4970Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 4980Sstevel@tonic-gate "all mechanisms are enabled already for %s."), 4990Sstevel@tonic-gate provname); 5000Sstevel@tonic-gate free_entry(pent); 5010Sstevel@tonic-gate return (SUCCESS); 5020Sstevel@tonic-gate } 5030Sstevel@tonic-gate } 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate if (!rndflag) { 5060Sstevel@tonic-gate /* See comments in disable_kef_hardware() */ 5070Sstevel@tonic-gate redo_flag = filter_mechlist(&pent->dislist, RANDOM); 5080Sstevel@tonic-gate if (redo_flag) 5090Sstevel@tonic-gate pent->dis_count--; 5100Sstevel@tonic-gate } 5110Sstevel@tonic-gate 5120Sstevel@tonic-gate /* Update the entry by enabling mechanisms for this provider */ 5130Sstevel@tonic-gate if ((rc = enable_mechs(&pent, allflag, mlist)) != SUCCESS) { 5140Sstevel@tonic-gate free_entry(pent); 5150Sstevel@tonic-gate return (rc); 5160Sstevel@tonic-gate } 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate if (redo_flag) { 5190Sstevel@tonic-gate mechlist_t *tmp; 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate if ((tmp = create_mech(RANDOM)) == NULL) { 5220Sstevel@tonic-gate free_entry(pent); 5230Sstevel@tonic-gate return (FAILURE); 5240Sstevel@tonic-gate } 5250Sstevel@tonic-gate tmp->next = pent->dislist; 5260Sstevel@tonic-gate pent->dislist = tmp; 5270Sstevel@tonic-gate pent->dis_count++; 5280Sstevel@tonic-gate } 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate /* 5310Sstevel@tonic-gate * Update the kcf.conf file with the updated entry. 5320Sstevel@tonic-gate * For a hardware provider, if there is no more disabled mechanism, 5330Sstevel@tonic-gate * the entire entry in the config file should be removed. 5340Sstevel@tonic-gate */ 5350Sstevel@tonic-gate if (is_device(pent->name) && (pent->dis_count == 0)) { 5360Sstevel@tonic-gate rc = update_kcfconf(pent, DELETE_MODE); 5370Sstevel@tonic-gate } else { 5380Sstevel@tonic-gate rc = update_kcfconf(pent, MODIFY_MODE); 5390Sstevel@tonic-gate } 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate if (rc == FAILURE) { 5420Sstevel@tonic-gate free_entry(pent); 5430Sstevel@tonic-gate return (FAILURE); 5440Sstevel@tonic-gate } 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate 5470Sstevel@tonic-gate /* Inform Kernel about the policy change */ 5480Sstevel@tonic-gate 5490Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 5500Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 5510Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 5520Sstevel@tonic-gate return (FAILURE); 5530Sstevel@tonic-gate } 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate if (is_device(provname)) { 5560Sstevel@tonic-gate /* LOAD_DEV_DISABLED */ 5570Sstevel@tonic-gate if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) { 5580Sstevel@tonic-gate return (FAILURE); 5590Sstevel@tonic-gate } 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) { 5620Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: " 5630Sstevel@tonic-gate "%s", strerror(errno)); 5640Sstevel@tonic-gate free(pload_dev_dis); 5650Sstevel@tonic-gate (void) close(fd); 5660Sstevel@tonic-gate return (FAILURE); 5670Sstevel@tonic-gate } 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 5700Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 5710Sstevel@tonic-gate "return_value = %d", 5720Sstevel@tonic-gate pload_dev_dis->dd_return_value); 5730Sstevel@tonic-gate free(pload_dev_dis); 5740Sstevel@tonic-gate (void) close(fd); 5750Sstevel@tonic-gate return (FAILURE); 5760Sstevel@tonic-gate } 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate } else { 5790Sstevel@tonic-gate /* LOAD_SOFT_DISABLED */ 5800Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 5810Sstevel@tonic-gate return (FAILURE); 5820Sstevel@tonic-gate } 5830Sstevel@tonic-gate 5840Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) 5850Sstevel@tonic-gate == -1) { 5860Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: " 5870Sstevel@tonic-gate "%s", strerror(errno)); 5880Sstevel@tonic-gate free(pload_soft_dis); 5890Sstevel@tonic-gate (void) close(fd); 5900Sstevel@tonic-gate return (FAILURE); 5910Sstevel@tonic-gate } 5920Sstevel@tonic-gate 5930Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 5940Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 5950Sstevel@tonic-gate "return_value = %d", 5960Sstevel@tonic-gate pload_soft_dis->sd_return_value); 5970Sstevel@tonic-gate free(pload_soft_dis); 5980Sstevel@tonic-gate (void) close(fd); 5990Sstevel@tonic-gate return (FAILURE); 6000Sstevel@tonic-gate } 6010Sstevel@tonic-gate } 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate (void) close(fd); 6040Sstevel@tonic-gate return (SUCCESS); 6050Sstevel@tonic-gate } 6060Sstevel@tonic-gate 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate /* 6090Sstevel@tonic-gate * Install a software module with the specified mechanism list into the system. 6100Sstevel@tonic-gate * This routine adds an entry into the config file for this software module 6110Sstevel@tonic-gate * first, then makes a CRYPTO_LOAD_SOFT_CONFIG ioctl call to inform kernel 6120Sstevel@tonic-gate * about the new addition. 6130Sstevel@tonic-gate */ 6140Sstevel@tonic-gate int 6150Sstevel@tonic-gate install_kef(char *provname, mechlist_t *mlist) 6160Sstevel@tonic-gate { 6170Sstevel@tonic-gate crypto_load_soft_config_t *pload_soft_conf = NULL; 6180Sstevel@tonic-gate boolean_t found; 6190Sstevel@tonic-gate entry_t *pent; 6200Sstevel@tonic-gate FILE *pfile; 6210Sstevel@tonic-gate FILE *pfile_tmp; 6220Sstevel@tonic-gate char tmpfile_name[MAXPATHLEN]; 6230Sstevel@tonic-gate char *ptr; 6240Sstevel@tonic-gate char *str; 6250Sstevel@tonic-gate char *name; 6260Sstevel@tonic-gate char buffer[BUFSIZ]; 6270Sstevel@tonic-gate char buffer2[BUFSIZ]; 6280Sstevel@tonic-gate int found_count; 6290Sstevel@tonic-gate int fd; 6300Sstevel@tonic-gate int rc = SUCCESS; 6310Sstevel@tonic-gate 6320Sstevel@tonic-gate if ((provname == NULL) || (mlist == NULL)) { 6330Sstevel@tonic-gate return (FAILURE); 6340Sstevel@tonic-gate } 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate /* Check if the provider already exists */ 6370Sstevel@tonic-gate if ((pent = getent_kef(provname)) != NULL) { 6380Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s exists already."), 6390Sstevel@tonic-gate provname); 6400Sstevel@tonic-gate free_entry(pent); 6410Sstevel@tonic-gate return (FAILURE); 6420Sstevel@tonic-gate } 6430Sstevel@tonic-gate 6440Sstevel@tonic-gate /* Create an entry with provname and mlist. */ 6450Sstevel@tonic-gate if ((pent = malloc(sizeof (entry_t))) == NULL) { 6460Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("out of memory.")); 6470Sstevel@tonic-gate return (FAILURE); 6480Sstevel@tonic-gate } 6490Sstevel@tonic-gate 6500Sstevel@tonic-gate (void) strlcpy(pent->name, provname, MAXNAMELEN); 6510Sstevel@tonic-gate pent->sup_count = get_mech_count(mlist); 6520Sstevel@tonic-gate pent->suplist = mlist; 6530Sstevel@tonic-gate pent->dis_count = 0; 6540Sstevel@tonic-gate pent->dislist = NULL; 6550Sstevel@tonic-gate 6560Sstevel@tonic-gate /* Append an entry for this software module to the kcf.conf file. */ 6570Sstevel@tonic-gate if ((str = ent2str(pent)) == NULL) { 6580Sstevel@tonic-gate free_entry(pent); 6590Sstevel@tonic-gate return (FAILURE); 6600Sstevel@tonic-gate } 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) { 6630Sstevel@tonic-gate err = errno; 6640Sstevel@tonic-gate cryptoerror(LOG_STDERR, 6650Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 6660Sstevel@tonic-gate strerror(err)); 6670Sstevel@tonic-gate cryptodebug("failed to open %s for write.", _PATH_KCF_CONF); 6680Sstevel@tonic-gate free_entry(pent); 6690Sstevel@tonic-gate return (FAILURE); 6700Sstevel@tonic-gate } 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 6730Sstevel@tonic-gate err = errno; 6740Sstevel@tonic-gate cryptoerror(LOG_STDERR, 6750Sstevel@tonic-gate gettext("failed to lock the configuration - %s"), 6760Sstevel@tonic-gate strerror(err)); 6770Sstevel@tonic-gate free_entry(pent); 6780Sstevel@tonic-gate (void) fclose(pfile); 6790Sstevel@tonic-gate return (FAILURE); 6800Sstevel@tonic-gate } 6810Sstevel@tonic-gate 6820Sstevel@tonic-gate /* 6830Sstevel@tonic-gate * Create a temporary file in the /etc/crypto directory. 6840Sstevel@tonic-gate */ 6850Sstevel@tonic-gate (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 6860Sstevel@tonic-gate if (mkstemp(tmpfile_name) == -1) { 6870Sstevel@tonic-gate err = errno; 6880Sstevel@tonic-gate cryptoerror(LOG_STDERR, 6890Sstevel@tonic-gate gettext("failed to create a temporary file - %s"), 6900Sstevel@tonic-gate strerror(err)); 6910Sstevel@tonic-gate free_entry(pent); 6920Sstevel@tonic-gate (void) fclose(pfile); 6930Sstevel@tonic-gate return (FAILURE); 6940Sstevel@tonic-gate } 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 6970Sstevel@tonic-gate err = errno; 6980Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 6990Sstevel@tonic-gate tmpfile_name, strerror(err)); 7000Sstevel@tonic-gate free_entry(pent); 7010Sstevel@tonic-gate (void) fclose(pfile); 7020Sstevel@tonic-gate return (FAILURE); 7030Sstevel@tonic-gate } 7040Sstevel@tonic-gate 7050Sstevel@tonic-gate 7060Sstevel@tonic-gate /* 7070Sstevel@tonic-gate * Loop thru the config file. If the provider was reserved within a 7080Sstevel@tonic-gate * package bracket, just uncomment it. Otherwise, append it at 7090Sstevel@tonic-gate * the end. The resulting file will be saved in the temp file first. 7100Sstevel@tonic-gate */ 7110Sstevel@tonic-gate found_count = 0; 7120Sstevel@tonic-gate rc = SUCCESS; 7130Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) { 7140Sstevel@tonic-gate found = B_FALSE; 7150Sstevel@tonic-gate if (buffer[0] == '#') { 7160Sstevel@tonic-gate (void) strlcpy(buffer2, buffer, BUFSIZ); 7170Sstevel@tonic-gate ptr = buffer2; 7180Sstevel@tonic-gate ptr++; 7190Sstevel@tonic-gate if ((name = strtok(ptr, SEP_COLON)) == NULL) { 7200Sstevel@tonic-gate rc = FAILURE; 7210Sstevel@tonic-gate break; 7220Sstevel@tonic-gate } else if (strcmp(provname, name) == 0) { 7230Sstevel@tonic-gate found = B_TRUE; 7240Sstevel@tonic-gate found_count++; 7250Sstevel@tonic-gate } 7260Sstevel@tonic-gate } 7270Sstevel@tonic-gate 7280Sstevel@tonic-gate if (found == B_FALSE) { 7290Sstevel@tonic-gate if (fputs(buffer, pfile_tmp) == EOF) { 7300Sstevel@tonic-gate rc = FAILURE; 7310Sstevel@tonic-gate } 7320Sstevel@tonic-gate } else { 7330Sstevel@tonic-gate if (found_count == 1) { 7340Sstevel@tonic-gate if (fputs(str, pfile_tmp) == EOF) { 7350Sstevel@tonic-gate rc = FAILURE; 7360Sstevel@tonic-gate } 7370Sstevel@tonic-gate } else { 7380Sstevel@tonic-gate /* 7390Sstevel@tonic-gate * Found a second entry with #libname. 7400Sstevel@tonic-gate * Should not happen. The kcf.conf ffile 7410Sstevel@tonic-gate * is corrupted. Give a warning and skip 7420Sstevel@tonic-gate * this entry. 7430Sstevel@tonic-gate */ 7440Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 7450Sstevel@tonic-gate "(Warning) Found an additional reserved " 7460Sstevel@tonic-gate "entry for %s."), provname); 7470Sstevel@tonic-gate } 7480Sstevel@tonic-gate } 7490Sstevel@tonic-gate 7500Sstevel@tonic-gate if (rc == FAILURE) { 7510Sstevel@tonic-gate break; 7520Sstevel@tonic-gate } 7530Sstevel@tonic-gate } 7540Sstevel@tonic-gate (void) fclose(pfile); 7550Sstevel@tonic-gate 7560Sstevel@tonic-gate if (rc == FAILURE) { 7570Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("write error.")); 7580Sstevel@tonic-gate (void) fclose(pfile_tmp); 7590Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 7600Sstevel@tonic-gate err = errno; 7610Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 7620Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), tmpfile_name, 7630Sstevel@tonic-gate strerror(err)); 7640Sstevel@tonic-gate } 7650Sstevel@tonic-gate free_entry(pent); 7660Sstevel@tonic-gate return (FAILURE); 7670Sstevel@tonic-gate } 7680Sstevel@tonic-gate 7690Sstevel@tonic-gate if (found_count == 0) { 7700Sstevel@tonic-gate /* 7710Sstevel@tonic-gate * This libname was not in package before, append it to the 7720Sstevel@tonic-gate * end of the temp file. 7730Sstevel@tonic-gate */ 7740Sstevel@tonic-gate if (fputs(str, pfile_tmp) == EOF) { 7750Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 7760Sstevel@tonic-gate "failed to write to %s: %s"), tmpfile_name, 7770Sstevel@tonic-gate strerror(errno)); 7780Sstevel@tonic-gate (void) fclose(pfile_tmp); 7790Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 7800Sstevel@tonic-gate err = errno; 7810Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 7820Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 7830Sstevel@tonic-gate tmpfile_name, strerror(err)); 7840Sstevel@tonic-gate } 7850Sstevel@tonic-gate free_entry(pent); 7860Sstevel@tonic-gate return (FAILURE); 7870Sstevel@tonic-gate } 7880Sstevel@tonic-gate } 7890Sstevel@tonic-gate 7900Sstevel@tonic-gate if (fclose(pfile_tmp) != 0) { 7910Sstevel@tonic-gate err = errno; 7920Sstevel@tonic-gate cryptoerror(LOG_STDERR, 7930Sstevel@tonic-gate gettext("failed to close %s: %s"), tmpfile_name, 7940Sstevel@tonic-gate strerror(err)); 7950Sstevel@tonic-gate return (FAILURE); 7960Sstevel@tonic-gate } 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) { 7990Sstevel@tonic-gate err = errno; 8000Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8010Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 8020Sstevel@tonic-gate strerror(err)); 8030Sstevel@tonic-gate cryptodebug("failed to rename %s to %s: %s", tmpfile_name, 8040Sstevel@tonic-gate _PATH_KCF_CONF, strerror(err)); 8050Sstevel@tonic-gate rc = FAILURE; 8060Sstevel@tonic-gate } else if (chmod(_PATH_KCF_CONF, 8070Sstevel@tonic-gate S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 8080Sstevel@tonic-gate err = errno; 8090Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8100Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 8110Sstevel@tonic-gate strerror(err)); 8120Sstevel@tonic-gate cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF, 8130Sstevel@tonic-gate strerror(err)); 8140Sstevel@tonic-gate rc = FAILURE; 8150Sstevel@tonic-gate } else { 8160Sstevel@tonic-gate rc = SUCCESS; 8170Sstevel@tonic-gate } 8180Sstevel@tonic-gate 8190Sstevel@tonic-gate if (rc == FAILURE) { 8200Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 8210Sstevel@tonic-gate err = errno; 8220Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8230Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 8240Sstevel@tonic-gate tmpfile_name, strerror(err)); 8250Sstevel@tonic-gate } 8260Sstevel@tonic-gate return (FAILURE); 8270Sstevel@tonic-gate } 8280Sstevel@tonic-gate 8290Sstevel@tonic-gate 8300Sstevel@tonic-gate /* Inform kernel of this new software module. */ 8310Sstevel@tonic-gate 8320Sstevel@tonic-gate if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) { 8330Sstevel@tonic-gate free_entry(pent); 8340Sstevel@tonic-gate return (FAILURE); 8350Sstevel@tonic-gate } 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 8380Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 8390Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 8400Sstevel@tonic-gate free_entry(pent); 8410Sstevel@tonic-gate free(pload_soft_conf); 8420Sstevel@tonic-gate return (FAILURE); 8430Sstevel@tonic-gate } 8440Sstevel@tonic-gate 8450Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) { 8460Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 8470Sstevel@tonic-gate strerror(errno)); 8480Sstevel@tonic-gate free_entry(pent); 8490Sstevel@tonic-gate free(pload_soft_conf); 8500Sstevel@tonic-gate (void) close(fd); 8510Sstevel@tonic-gate return (FAILURE); 8520Sstevel@tonic-gate } 8530Sstevel@tonic-gate 8540Sstevel@tonic-gate if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 8550Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed, " 8560Sstevel@tonic-gate "return_value = %d", pload_soft_conf->sc_return_value); 8570Sstevel@tonic-gate free_entry(pent); 8580Sstevel@tonic-gate free(pload_soft_conf); 8590Sstevel@tonic-gate (void) close(fd); 8600Sstevel@tonic-gate return (FAILURE); 8610Sstevel@tonic-gate } 8620Sstevel@tonic-gate 8630Sstevel@tonic-gate free_entry(pent); 8640Sstevel@tonic-gate free(pload_soft_conf); 8650Sstevel@tonic-gate (void) close(fd); 8660Sstevel@tonic-gate return (SUCCESS); 8670Sstevel@tonic-gate } 8680Sstevel@tonic-gate 8690Sstevel@tonic-gate /* 8700Sstevel@tonic-gate * Uninstall the software module. This routine first unloads the software 8710Sstevel@tonic-gate * module with 3 ioctl calls, then deletes its entry from the config file. 8720Sstevel@tonic-gate * Removing an entry from the config file needs to be done last to ensure 8730Sstevel@tonic-gate * that there is still an entry if the earlier unload failed for any reason. 8740Sstevel@tonic-gate */ 8750Sstevel@tonic-gate int 8760Sstevel@tonic-gate uninstall_kef(char *provname) 8770Sstevel@tonic-gate { 8780Sstevel@tonic-gate entry_t *pent; 8790Sstevel@tonic-gate boolean_t is_active; 8800Sstevel@tonic-gate boolean_t in_package; 8810Sstevel@tonic-gate boolean_t found; 8820Sstevel@tonic-gate FILE *pfile; 8830Sstevel@tonic-gate FILE *pfile_tmp; 8840Sstevel@tonic-gate char tmpfile_name[MAXPATHLEN]; 8850Sstevel@tonic-gate char *name; 8860Sstevel@tonic-gate char strbuf[BUFSIZ]; 8870Sstevel@tonic-gate char buffer[BUFSIZ]; 8880Sstevel@tonic-gate char buffer2[BUFSIZ]; 8890Sstevel@tonic-gate char *str; 8900Sstevel@tonic-gate int len; 8910Sstevel@tonic-gate int rc = SUCCESS; 8920Sstevel@tonic-gate 8930Sstevel@tonic-gate 8940Sstevel@tonic-gate /* Check if it is in the kcf.conf file first. */ 8950Sstevel@tonic-gate if ((pent = getent_kef(provname)) == NULL) { 8960Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8970Sstevel@tonic-gate gettext("%s does not exist."), provname); 8980Sstevel@tonic-gate return (FAILURE); 8990Sstevel@tonic-gate } 9000Sstevel@tonic-gate 9010Sstevel@tonic-gate 9020Sstevel@tonic-gate /* 9030Sstevel@tonic-gate * Get rid of the disabled list for the provider and get the converted 9040Sstevel@tonic-gate * string for the entry. This is to prepare the string for a provider 9050Sstevel@tonic-gate * that is in a package. 9060Sstevel@tonic-gate */ 9070Sstevel@tonic-gate free_mechlist(pent->dislist); 9080Sstevel@tonic-gate pent->dis_count = 0; 9090Sstevel@tonic-gate pent->dislist = NULL; 9100Sstevel@tonic-gate str = ent2str(pent); 9110Sstevel@tonic-gate free_entry(pent); 9120Sstevel@tonic-gate if (str == NULL) { 9130Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 9140Sstevel@tonic-gate return (FAILURE); 9150Sstevel@tonic-gate } 9160Sstevel@tonic-gate (void) snprintf(strbuf, sizeof (strbuf), "%s%s", "#", str); 9170Sstevel@tonic-gate free(str); 9180Sstevel@tonic-gate 9190Sstevel@tonic-gate /* If it is not loaded, unload it first */ 9200Sstevel@tonic-gate if (check_active_for_soft(provname, &is_active) == FAILURE) { 9210Sstevel@tonic-gate return (FAILURE); 9220Sstevel@tonic-gate } else if ((is_active == B_TRUE) && 923*1971Skrishna (unload_kef_soft(provname, B_TRUE) == FAILURE)) { 9240Sstevel@tonic-gate cryptoerror(LOG_STDERR, 9250Sstevel@tonic-gate gettext("failed to uninstall %s.\n"), provname); 9260Sstevel@tonic-gate return (FAILURE); 9270Sstevel@tonic-gate } 9280Sstevel@tonic-gate 9290Sstevel@tonic-gate /* 9300Sstevel@tonic-gate * Remove the entry from the config file. If the provider to be 9310Sstevel@tonic-gate * uninstalled is in a package, just comment it off. 9320Sstevel@tonic-gate */ 9330Sstevel@tonic-gate if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) { 9340Sstevel@tonic-gate err = errno; 9350Sstevel@tonic-gate cryptoerror(LOG_STDERR, 9360Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 9370Sstevel@tonic-gate strerror(err)); 9380Sstevel@tonic-gate cryptodebug("failed to open %s for write.", _PATH_KCF_CONF); 9390Sstevel@tonic-gate return (FAILURE); 9400Sstevel@tonic-gate } 9410Sstevel@tonic-gate 9420Sstevel@tonic-gate if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 9430Sstevel@tonic-gate err = errno; 9440Sstevel@tonic-gate cryptoerror(LOG_STDERR, 9450Sstevel@tonic-gate gettext("failed to lock the configuration - %s"), 9460Sstevel@tonic-gate strerror(err)); 9470Sstevel@tonic-gate (void) fclose(pfile); 9480Sstevel@tonic-gate return (FAILURE); 9490Sstevel@tonic-gate } 9500Sstevel@tonic-gate 9510Sstevel@tonic-gate /* 9520Sstevel@tonic-gate * Create a temporary file in the /etc/crypto directory to save 9530Sstevel@tonic-gate * the new configuration file first. 9540Sstevel@tonic-gate */ 9550Sstevel@tonic-gate (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 9560Sstevel@tonic-gate if (mkstemp(tmpfile_name) == -1) { 9570Sstevel@tonic-gate err = errno; 9580Sstevel@tonic-gate cryptoerror(LOG_STDERR, 9590Sstevel@tonic-gate gettext("failed to create a temporary file - %s"), 9600Sstevel@tonic-gate strerror(err)); 9610Sstevel@tonic-gate (void) fclose(pfile); 9620Sstevel@tonic-gate return (FAILURE); 9630Sstevel@tonic-gate } 9640Sstevel@tonic-gate 9650Sstevel@tonic-gate if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 9660Sstevel@tonic-gate err = errno; 9670Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 9680Sstevel@tonic-gate tmpfile_name, strerror(err)); 9690Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 9700Sstevel@tonic-gate err = errno; 9710Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 9720Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), tmpfile_name, 9730Sstevel@tonic-gate strerror(err)); 9740Sstevel@tonic-gate } 9750Sstevel@tonic-gate (void) fclose(pfile); 9760Sstevel@tonic-gate return (FAILURE); 9770Sstevel@tonic-gate } 9780Sstevel@tonic-gate 9790Sstevel@tonic-gate /* 9800Sstevel@tonic-gate * Loop thru the config file. If the kernel software provider 9810Sstevel@tonic-gate * to be uninstalled is in a package, just comment it off. 9820Sstevel@tonic-gate */ 9830Sstevel@tonic-gate in_package = B_FALSE; 9840Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) { 9850Sstevel@tonic-gate found = B_FALSE; 9860Sstevel@tonic-gate if (!(buffer[0] == ' ' || buffer[0] == '\n' || 9870Sstevel@tonic-gate buffer[0] == '\t')) { 9880Sstevel@tonic-gate if (strstr(buffer, " Start ") != NULL) { 9890Sstevel@tonic-gate in_package = B_TRUE; 9900Sstevel@tonic-gate } else if (strstr(buffer, " End ") != NULL) { 9910Sstevel@tonic-gate in_package = B_FALSE; 9920Sstevel@tonic-gate } else if (buffer[0] != '#') { 9930Sstevel@tonic-gate (void) strlcpy(buffer2, buffer, BUFSIZ); 9940Sstevel@tonic-gate 9950Sstevel@tonic-gate /* get rid of trailing '\n' */ 9960Sstevel@tonic-gate len = strlen(buffer2); 9970Sstevel@tonic-gate if (buffer2[len-1] == '\n') { 9980Sstevel@tonic-gate len--; 9990Sstevel@tonic-gate } 10000Sstevel@tonic-gate buffer2[len] = '\0'; 10010Sstevel@tonic-gate 10020Sstevel@tonic-gate if ((name = strtok(buffer2, SEP_COLON)) 10030Sstevel@tonic-gate == NULL) { 10040Sstevel@tonic-gate rc = FAILURE; 10050Sstevel@tonic-gate break; 10060Sstevel@tonic-gate } else if (strcmp(provname, name) == 0) { 10070Sstevel@tonic-gate found = B_TRUE; 10080Sstevel@tonic-gate } 10090Sstevel@tonic-gate } 10100Sstevel@tonic-gate } 10110Sstevel@tonic-gate 10120Sstevel@tonic-gate if (found) { 10130Sstevel@tonic-gate if (in_package) { 10140Sstevel@tonic-gate if (fputs(strbuf, pfile_tmp) == EOF) { 10150Sstevel@tonic-gate rc = FAILURE; 10160Sstevel@tonic-gate } 10170Sstevel@tonic-gate } 10180Sstevel@tonic-gate } else { 10190Sstevel@tonic-gate if (fputs(buffer, pfile_tmp) == EOF) { 10200Sstevel@tonic-gate rc = FAILURE; 10210Sstevel@tonic-gate } 10220Sstevel@tonic-gate } 10230Sstevel@tonic-gate 10240Sstevel@tonic-gate if (rc == FAILURE) { 10250Sstevel@tonic-gate break; 10260Sstevel@tonic-gate } 10270Sstevel@tonic-gate } 10280Sstevel@tonic-gate 10290Sstevel@tonic-gate if (rc == FAILURE) { 10300Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("write error.")); 10310Sstevel@tonic-gate (void) fclose(pfile); 10320Sstevel@tonic-gate (void) fclose(pfile_tmp); 10330Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 10340Sstevel@tonic-gate err = errno; 10350Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 10360Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), tmpfile_name, 10370Sstevel@tonic-gate strerror(err)); 10380Sstevel@tonic-gate } 10390Sstevel@tonic-gate return (FAILURE); 10400Sstevel@tonic-gate } 10410Sstevel@tonic-gate 10420Sstevel@tonic-gate (void) fclose(pfile); 10430Sstevel@tonic-gate if (fclose(pfile_tmp) != 0) { 10440Sstevel@tonic-gate err = errno; 10450Sstevel@tonic-gate cryptoerror(LOG_STDERR, 10460Sstevel@tonic-gate gettext("failed to close %s: %s"), tmpfile_name, 10470Sstevel@tonic-gate strerror(err)); 10480Sstevel@tonic-gate return (FAILURE); 10490Sstevel@tonic-gate } 10500Sstevel@tonic-gate 10510Sstevel@tonic-gate /* Now update the real config file */ 10520Sstevel@tonic-gate if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) { 10530Sstevel@tonic-gate err = errno; 10540Sstevel@tonic-gate cryptoerror(LOG_STDERR, 10550Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 10560Sstevel@tonic-gate strerror(err)); 10570Sstevel@tonic-gate cryptodebug("failed to rename %1$s to %2$s: %3$s", tmpfile, 10580Sstevel@tonic-gate _PATH_KCF_CONF, strerror(err)); 10590Sstevel@tonic-gate rc = FAILURE; 10600Sstevel@tonic-gate } else if (chmod(_PATH_KCF_CONF, 10610Sstevel@tonic-gate S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 10620Sstevel@tonic-gate err = errno; 10630Sstevel@tonic-gate cryptoerror(LOG_STDERR, 10640Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 10650Sstevel@tonic-gate strerror(err)); 10660Sstevel@tonic-gate cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF, 10670Sstevel@tonic-gate strerror(err)); 10680Sstevel@tonic-gate rc = FAILURE; 10690Sstevel@tonic-gate } else { 10700Sstevel@tonic-gate rc = SUCCESS; 10710Sstevel@tonic-gate } 10720Sstevel@tonic-gate 10730Sstevel@tonic-gate if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) { 10740Sstevel@tonic-gate err = errno; 10750Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 10760Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), tmpfile_name, 10770Sstevel@tonic-gate strerror(err)); 10780Sstevel@tonic-gate } 10790Sstevel@tonic-gate 10800Sstevel@tonic-gate return (rc); 10810Sstevel@tonic-gate 10820Sstevel@tonic-gate } 10830Sstevel@tonic-gate 10840Sstevel@tonic-gate 10850Sstevel@tonic-gate int 10860Sstevel@tonic-gate refresh(void) 10870Sstevel@tonic-gate { 10880Sstevel@tonic-gate crypto_get_soft_list_t *psoftlist_kernel = NULL; 10890Sstevel@tonic-gate crypto_load_soft_config_t *pload_soft_conf = NULL; 10900Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 10910Sstevel@tonic-gate crypto_load_dev_disabled_t *pload_dev_dis = NULL; 10920Sstevel@tonic-gate entrylist_t *pdevlist = NULL; 10930Sstevel@tonic-gate entrylist_t *psoftlist = NULL; 10940Sstevel@tonic-gate entrylist_t *ptr; 10950Sstevel@tonic-gate boolean_t found; 10960Sstevel@tonic-gate char *psoftname; 10970Sstevel@tonic-gate int fd; 10980Sstevel@tonic-gate int rc = SUCCESS; 10990Sstevel@tonic-gate int i; 11000Sstevel@tonic-gate 11010Sstevel@tonic-gate if (get_soft_list(&psoftlist_kernel) == FAILURE) { 11020Sstevel@tonic-gate cryptoerror(LOG_ERR, gettext("Failed to retrieve the " 11030Sstevel@tonic-gate "software provider list from kernel.")); 11040Sstevel@tonic-gate return (FAILURE); 11050Sstevel@tonic-gate } 11060Sstevel@tonic-gate 11070Sstevel@tonic-gate if (get_kcfconf_info(&pdevlist, &psoftlist) == FAILURE) { 11080Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to retrieve the providers' " 11090Sstevel@tonic-gate "information from the configuration file - %s.", 11100Sstevel@tonic-gate _PATH_KCF_CONF); 11110Sstevel@tonic-gate return (FAILURE); 11120Sstevel@tonic-gate } 11130Sstevel@tonic-gate 11140Sstevel@tonic-gate /* 11150Sstevel@tonic-gate * If a kernel software provider is in kernel, but it is not in the 11160Sstevel@tonic-gate * kcf.conf file, it must have been pkgrm'ed and needs to be unloaded 11170Sstevel@tonic-gate * now. 11180Sstevel@tonic-gate */ 11190Sstevel@tonic-gate if (psoftlist_kernel->sl_soft_count > 0) { 11200Sstevel@tonic-gate psoftname = psoftlist_kernel->sl_soft_names; 11210Sstevel@tonic-gate for (i = 0; i < psoftlist_kernel->sl_soft_count; i++) { 11220Sstevel@tonic-gate ptr = psoftlist; 11230Sstevel@tonic-gate found = B_FALSE; 11240Sstevel@tonic-gate while (ptr != NULL) { 11250Sstevel@tonic-gate if (strcmp(psoftname, ptr->pent->name) == 0) { 11260Sstevel@tonic-gate found = B_TRUE; 11270Sstevel@tonic-gate break; 11280Sstevel@tonic-gate } 11290Sstevel@tonic-gate ptr = ptr->next; 11300Sstevel@tonic-gate } 11310Sstevel@tonic-gate 11320Sstevel@tonic-gate if (!found) { 1133*1971Skrishna rc = unload_kef_soft(psoftname, B_FALSE); 11340Sstevel@tonic-gate if (rc == FAILURE) { 11350Sstevel@tonic-gate cryptoerror(LOG_ERR, gettext( 11360Sstevel@tonic-gate "WARNING - the provider %s is " 11370Sstevel@tonic-gate "still in kernel."), psoftname); 11380Sstevel@tonic-gate } 11390Sstevel@tonic-gate } 11400Sstevel@tonic-gate psoftname = psoftname + strlen(psoftname) + 1; 11410Sstevel@tonic-gate } 11420Sstevel@tonic-gate } 11430Sstevel@tonic-gate free(psoftlist_kernel); 11440Sstevel@tonic-gate 11450Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 11460Sstevel@tonic-gate err = errno; 11470Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 11480Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(err)); 11490Sstevel@tonic-gate free(psoftlist); 11500Sstevel@tonic-gate free(pdevlist); 11510Sstevel@tonic-gate return (FAILURE); 11520Sstevel@tonic-gate } 11530Sstevel@tonic-gate 11540Sstevel@tonic-gate /* 11550Sstevel@tonic-gate * For each software module, pass two sets of information to kernel 11560Sstevel@tonic-gate * - the supported list and the disabled list 11570Sstevel@tonic-gate */ 11580Sstevel@tonic-gate ptr = psoftlist; 11590Sstevel@tonic-gate while (ptr != NULL) { 11600Sstevel@tonic-gate /* load the supported list */ 11610Sstevel@tonic-gate if ((pload_soft_conf = setup_soft_conf(ptr->pent)) == NULL) { 11620Sstevel@tonic-gate rc = FAILURE; 11630Sstevel@tonic-gate break; 11640Sstevel@tonic-gate } 11650Sstevel@tonic-gate 11660Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) 11670Sstevel@tonic-gate == -1) { 11680Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 11690Sstevel@tonic-gate strerror(errno)); 11700Sstevel@tonic-gate free(pload_soft_conf); 11710Sstevel@tonic-gate rc = FAILURE; 11720Sstevel@tonic-gate break; 11730Sstevel@tonic-gate } 11740Sstevel@tonic-gate 11750Sstevel@tonic-gate if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 11760Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl " 11770Sstevel@tonic-gate "return_value = %d", 11780Sstevel@tonic-gate pload_soft_conf->sc_return_value); 11790Sstevel@tonic-gate free(pload_soft_conf); 11800Sstevel@tonic-gate rc = FAILURE; 11810Sstevel@tonic-gate break; 11820Sstevel@tonic-gate } 11830Sstevel@tonic-gate 11840Sstevel@tonic-gate /* load the disabled list */ 11850Sstevel@tonic-gate if (ptr->pent->dis_count != 0) { 11860Sstevel@tonic-gate pload_soft_dis = setup_soft_dis(ptr->pent); 11870Sstevel@tonic-gate if (pload_soft_dis == NULL) { 11880Sstevel@tonic-gate rc = FAILURE; 11890Sstevel@tonic-gate break; 11900Sstevel@tonic-gate } 11910Sstevel@tonic-gate 11920Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, 11930Sstevel@tonic-gate pload_soft_dis) == -1) { 11940Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 11950Sstevel@tonic-gate "failed: %s", strerror(errno)); 11960Sstevel@tonic-gate free(pload_soft_dis); 11970Sstevel@tonic-gate rc = FAILURE; 11980Sstevel@tonic-gate break; 11990Sstevel@tonic-gate } 12000Sstevel@tonic-gate 12010Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != 12020Sstevel@tonic-gate CRYPTO_SUCCESS) { 12030Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 12040Sstevel@tonic-gate "return_value = %d", 12050Sstevel@tonic-gate pload_soft_dis->sd_return_value); 12060Sstevel@tonic-gate free(pload_soft_dis); 12070Sstevel@tonic-gate rc = FAILURE; 12080Sstevel@tonic-gate break; 12090Sstevel@tonic-gate } 12100Sstevel@tonic-gate free(pload_soft_dis); 12110Sstevel@tonic-gate } 12120Sstevel@tonic-gate 12130Sstevel@tonic-gate free(pload_soft_conf); 12140Sstevel@tonic-gate ptr = ptr->next; 12150Sstevel@tonic-gate } 12160Sstevel@tonic-gate 12170Sstevel@tonic-gate if (rc != SUCCESS) { 12180Sstevel@tonic-gate (void) close(fd); 12190Sstevel@tonic-gate return (rc); 12200Sstevel@tonic-gate } 12210Sstevel@tonic-gate 12220Sstevel@tonic-gate 12230Sstevel@tonic-gate /* Pass the disabledlist information for Device to kernel */ 12240Sstevel@tonic-gate ptr = pdevlist; 12250Sstevel@tonic-gate while (ptr != NULL) { 12260Sstevel@tonic-gate /* load the disabled list */ 12270Sstevel@tonic-gate if (ptr->pent->dis_count != 0) { 12280Sstevel@tonic-gate pload_dev_dis = setup_dev_dis(ptr->pent); 12290Sstevel@tonic-gate if (pload_dev_dis == NULL) { 12300Sstevel@tonic-gate rc = FAILURE; 12310Sstevel@tonic-gate break; 12320Sstevel@tonic-gate } 12330Sstevel@tonic-gate 12340Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) 12350Sstevel@tonic-gate == -1) { 12360Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 12370Sstevel@tonic-gate "failed: %s", strerror(errno)); 12380Sstevel@tonic-gate free(pload_dev_dis); 12390Sstevel@tonic-gate rc = FAILURE; 12400Sstevel@tonic-gate break; 12410Sstevel@tonic-gate } 12420Sstevel@tonic-gate 12430Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 12440Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 12450Sstevel@tonic-gate "return_value = %d", 12460Sstevel@tonic-gate pload_dev_dis->dd_return_value); 12470Sstevel@tonic-gate free(pload_dev_dis); 12480Sstevel@tonic-gate rc = FAILURE; 12490Sstevel@tonic-gate break; 12500Sstevel@tonic-gate } 12510Sstevel@tonic-gate free(pload_dev_dis); 12520Sstevel@tonic-gate } 12530Sstevel@tonic-gate 12540Sstevel@tonic-gate ptr = ptr->next; 12550Sstevel@tonic-gate } 12560Sstevel@tonic-gate 12570Sstevel@tonic-gate (void) close(fd); 12580Sstevel@tonic-gate return (rc); 12590Sstevel@tonic-gate } 12600Sstevel@tonic-gate 12610Sstevel@tonic-gate /* 12620Sstevel@tonic-gate * Unload the kernel software provider. Before calling this function, the 12630Sstevel@tonic-gate * caller should check if the provider is in the config file and if it 1264*1971Skrishna * is kernel. This routine makes 3 ioctl calls to remove it from kernel 1265*1971Skrishna * completely. The argument do_check set to B_FALSE means that the 1266*1971Skrishna * caller knows the provider is not the config file and hence the check 1267*1971Skrishna * is skipped. 12680Sstevel@tonic-gate */ 12690Sstevel@tonic-gate int 1270*1971Skrishna unload_kef_soft(char *provname, boolean_t do_check) 12710Sstevel@tonic-gate { 12720Sstevel@tonic-gate crypto_unload_soft_module_t *punload_soft = NULL; 12730Sstevel@tonic-gate crypto_load_soft_config_t *pload_soft_conf = NULL; 12740Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 12750Sstevel@tonic-gate entry_t *pent = NULL; 12760Sstevel@tonic-gate int fd; 12770Sstevel@tonic-gate 12780Sstevel@tonic-gate if (provname == NULL) { 12790Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 12800Sstevel@tonic-gate return (FAILURE); 12810Sstevel@tonic-gate } 12820Sstevel@tonic-gate 1283*1971Skrishna if (!do_check) { 1284*1971Skrishna /* Construct an entry using the provname */ 1285*1971Skrishna pent = calloc(1, sizeof (entry_t)); 1286*1971Skrishna if (pent == NULL) { 1287*1971Skrishna cryptoerror(LOG_STDERR, gettext("out of memory.")); 1288*1971Skrishna return (FAILURE); 1289*1971Skrishna } 1290*1971Skrishna (void) strlcpy(pent->name, provname, MAXNAMELEN); 1291*1971Skrishna } else if ((pent = getent_kef(provname)) == NULL) { 12920Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s does not exist."), 12930Sstevel@tonic-gate provname); 12940Sstevel@tonic-gate return (FAILURE); 12950Sstevel@tonic-gate } 12960Sstevel@tonic-gate 12970Sstevel@tonic-gate /* Open the admin_ioctl_device */ 12980Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 12990Sstevel@tonic-gate err = errno; 13000Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 13010Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(err)); 13020Sstevel@tonic-gate return (FAILURE); 13030Sstevel@tonic-gate } 13040Sstevel@tonic-gate 13050Sstevel@tonic-gate /* Inform kernel to unload this software module */ 13060Sstevel@tonic-gate if ((punload_soft = setup_unload_soft(pent)) == NULL) { 13070Sstevel@tonic-gate (void) close(fd); 13080Sstevel@tonic-gate return (FAILURE); 13090Sstevel@tonic-gate } 13100Sstevel@tonic-gate 13110Sstevel@tonic-gate if (ioctl(fd, CRYPTO_UNLOAD_SOFT_MODULE, punload_soft) == -1) { 13120Sstevel@tonic-gate cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl failed: %s", 13130Sstevel@tonic-gate strerror(errno)); 13140Sstevel@tonic-gate free_entry(pent); 13150Sstevel@tonic-gate free(punload_soft); 13160Sstevel@tonic-gate (void) close(fd); 13170Sstevel@tonic-gate return (FAILURE); 13180Sstevel@tonic-gate } 13190Sstevel@tonic-gate 13200Sstevel@tonic-gate if (punload_soft->sm_return_value != CRYPTO_SUCCESS) { 13210Sstevel@tonic-gate cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl return_value = " 13220Sstevel@tonic-gate "%d", punload_soft->sm_return_value); 13230Sstevel@tonic-gate /* 13240Sstevel@tonic-gate * If the return value is CRYPTO_UNKNOWN_PRIVDER, it means 13250Sstevel@tonic-gate * that the provider is not registered yet. Should just 13260Sstevel@tonic-gate * continue. 13270Sstevel@tonic-gate */ 13280Sstevel@tonic-gate if (punload_soft->sm_return_value != CRYPTO_UNKNOWN_PROVIDER) { 13290Sstevel@tonic-gate free_entry(pent); 13300Sstevel@tonic-gate free(punload_soft); 13310Sstevel@tonic-gate (void) close(fd); 13320Sstevel@tonic-gate return (FAILURE); 13330Sstevel@tonic-gate } 13340Sstevel@tonic-gate } 13350Sstevel@tonic-gate 13360Sstevel@tonic-gate free(punload_soft); 13370Sstevel@tonic-gate 13380Sstevel@tonic-gate /* 13390Sstevel@tonic-gate * Inform kernel to remove the configuration of this software 13400Sstevel@tonic-gate * module. 13410Sstevel@tonic-gate */ 13420Sstevel@tonic-gate free_mechlist(pent->suplist); 13430Sstevel@tonic-gate pent->suplist = NULL; 13440Sstevel@tonic-gate pent->sup_count = 0; 13450Sstevel@tonic-gate if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) { 13460Sstevel@tonic-gate free_entry(pent); 13470Sstevel@tonic-gate (void) close(fd); 13480Sstevel@tonic-gate return (FAILURE); 13490Sstevel@tonic-gate } 13500Sstevel@tonic-gate 13510Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) { 13520Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 13530Sstevel@tonic-gate strerror(errno)); 13540Sstevel@tonic-gate free_entry(pent); 13550Sstevel@tonic-gate free(pload_soft_conf); 13560Sstevel@tonic-gate (void) close(fd); 13570Sstevel@tonic-gate return (FAILURE); 13580Sstevel@tonic-gate } 13590Sstevel@tonic-gate 13600Sstevel@tonic-gate if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 13610Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl return_value = " 13620Sstevel@tonic-gate "%d", pload_soft_conf->sc_return_value); 13630Sstevel@tonic-gate free_entry(pent); 13640Sstevel@tonic-gate free(pload_soft_conf); 13650Sstevel@tonic-gate (void) close(fd); 13660Sstevel@tonic-gate return (FAILURE); 13670Sstevel@tonic-gate } 13680Sstevel@tonic-gate 13690Sstevel@tonic-gate free(pload_soft_conf); 13700Sstevel@tonic-gate 13710Sstevel@tonic-gate /* Inform kernel to remove the disabled entries if any */ 13720Sstevel@tonic-gate if (pent->dis_count == 0) { 13730Sstevel@tonic-gate free_entry(pent); 13740Sstevel@tonic-gate (void) close(fd); 13750Sstevel@tonic-gate return (SUCCESS); 13760Sstevel@tonic-gate } else { 13770Sstevel@tonic-gate free_mechlist(pent->dislist); 13780Sstevel@tonic-gate pent->dislist = NULL; 13790Sstevel@tonic-gate pent->dis_count = 0; 13800Sstevel@tonic-gate } 13810Sstevel@tonic-gate 13820Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 13830Sstevel@tonic-gate free_entry(pent); 13840Sstevel@tonic-gate (void) close(fd); 13850Sstevel@tonic-gate return (FAILURE); 13860Sstevel@tonic-gate } 13870Sstevel@tonic-gate 13880Sstevel@tonic-gate /* pent is no longer needed; free it */ 13890Sstevel@tonic-gate free_entry(pent); 13900Sstevel@tonic-gate 13910Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) { 13920Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s", 13930Sstevel@tonic-gate strerror(errno)); 13940Sstevel@tonic-gate free(pload_soft_dis); 13950Sstevel@tonic-gate (void) close(fd); 13960Sstevel@tonic-gate return (FAILURE); 13970Sstevel@tonic-gate } 13980Sstevel@tonic-gate 13990Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 14000Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = " 14010Sstevel@tonic-gate "%d", pload_soft_dis->sd_return_value); 14020Sstevel@tonic-gate free(pload_soft_dis); 14030Sstevel@tonic-gate (void) close(fd); 14040Sstevel@tonic-gate return (FAILURE); 14050Sstevel@tonic-gate } 14060Sstevel@tonic-gate 14070Sstevel@tonic-gate free(pload_soft_dis); 14080Sstevel@tonic-gate (void) close(fd); 14090Sstevel@tonic-gate return (SUCCESS); 14100Sstevel@tonic-gate } 14110Sstevel@tonic-gate 14120Sstevel@tonic-gate 14130Sstevel@tonic-gate /* 14140Sstevel@tonic-gate * Check if a hardware provider is valid. If it is valid, returns its device 14150Sstevel@tonic-gate * name, instance number and the number of mechanisms it supports. 14160Sstevel@tonic-gate */ 14170Sstevel@tonic-gate static int 14180Sstevel@tonic-gate check_hardware_provider(char *provname, char *pname, int *pnum, int *pcount) 14190Sstevel@tonic-gate { 14200Sstevel@tonic-gate crypto_get_dev_list_t *dev_list = NULL; 14210Sstevel@tonic-gate int i; 14220Sstevel@tonic-gate 14230Sstevel@tonic-gate if (provname == NULL) { 14240Sstevel@tonic-gate return (FAILURE); 14250Sstevel@tonic-gate } 14260Sstevel@tonic-gate 14270Sstevel@tonic-gate /* First, get the device name and the instance number from provname */ 14280Sstevel@tonic-gate if (split_hw_provname(provname, pname, pnum) == FAILURE) { 14290Sstevel@tonic-gate return (FAILURE); 14300Sstevel@tonic-gate } 14310Sstevel@tonic-gate 14320Sstevel@tonic-gate /* 14330Sstevel@tonic-gate * Get the complete device list from kernel and check if this provider 14340Sstevel@tonic-gate * is in the list. 14350Sstevel@tonic-gate */ 14360Sstevel@tonic-gate if (get_dev_list(&dev_list) == FAILURE) { 14370Sstevel@tonic-gate return (FAILURE); 14380Sstevel@tonic-gate } 14390Sstevel@tonic-gate 14400Sstevel@tonic-gate for (i = 0; i < dev_list->dl_dev_count; i++) { 14410Sstevel@tonic-gate if ((strcmp(dev_list->dl_devs[i].le_dev_name, pname) == 0) && 14420Sstevel@tonic-gate (dev_list->dl_devs[i].le_dev_instance == *pnum)) { 14430Sstevel@tonic-gate break; 14440Sstevel@tonic-gate } 14450Sstevel@tonic-gate } 14460Sstevel@tonic-gate 14470Sstevel@tonic-gate if (i == dev_list->dl_dev_count) { 14480Sstevel@tonic-gate /* didn't find this provider in the kernel device list */ 14490Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s does not exist."), 14500Sstevel@tonic-gate provname); 14510Sstevel@tonic-gate free(dev_list); 14520Sstevel@tonic-gate return (FAILURE); 14530Sstevel@tonic-gate } 14540Sstevel@tonic-gate 14550Sstevel@tonic-gate /* This provider is valid. Get its mechanism count */ 14560Sstevel@tonic-gate *pcount = dev_list->dl_devs[i].le_mechanism_count; 14570Sstevel@tonic-gate 14580Sstevel@tonic-gate free(dev_list); 14590Sstevel@tonic-gate return (SUCCESS); 14600Sstevel@tonic-gate } 1461