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