1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <fcntl.h> 30*0Sstevel@tonic-gate #include <stdio.h> 31*0Sstevel@tonic-gate #include <stdlib.h> 32*0Sstevel@tonic-gate #include <strings.h> 33*0Sstevel@tonic-gate #include <unistd.h> 34*0Sstevel@tonic-gate #include <locale.h> 35*0Sstevel@tonic-gate #include <libgen.h> 36*0Sstevel@tonic-gate #include <sys/types.h> 37*0Sstevel@tonic-gate #include <sys/stat.h> 38*0Sstevel@tonic-gate #include <sys/crypto/ioctladmin.h> 39*0Sstevel@tonic-gate #include <signal.h> 40*0Sstevel@tonic-gate #include <sys/crypto/elfsign.h> 41*0Sstevel@tonic-gate #include "cryptoadm.h" 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate static int err; /* to store the value of errno in case being overwritten */ 44*0Sstevel@tonic-gate static int check_hardware_provider(char *, char *, int *, int *); 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate /* 47*0Sstevel@tonic-gate * Display the mechanism list for a kernel software provider. 48*0Sstevel@tonic-gate */ 49*0Sstevel@tonic-gate int 50*0Sstevel@tonic-gate list_mechlist_for_soft(char *provname) 51*0Sstevel@tonic-gate { 52*0Sstevel@tonic-gate mechlist_t *pmechlist; 53*0Sstevel@tonic-gate int rc; 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate if (provname == NULL) { 56*0Sstevel@tonic-gate return (FAILURE); 57*0Sstevel@tonic-gate } 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate rc = get_soft_info(provname, &pmechlist); 60*0Sstevel@tonic-gate if (rc == SUCCESS) { 61*0Sstevel@tonic-gate (void) filter_mechlist(&pmechlist, RANDOM); 62*0Sstevel@tonic-gate print_mechlist(provname, pmechlist); 63*0Sstevel@tonic-gate free_mechlist(pmechlist); 64*0Sstevel@tonic-gate } else { 65*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 66*0Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 67*0Sstevel@tonic-gate provname); 68*0Sstevel@tonic-gate } 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate return (rc); 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate } 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate /* 75*0Sstevel@tonic-gate * Display the mechanism list for a kernel hardware provider. 76*0Sstevel@tonic-gate */ 77*0Sstevel@tonic-gate int 78*0Sstevel@tonic-gate list_mechlist_for_hard(char *provname) 79*0Sstevel@tonic-gate { 80*0Sstevel@tonic-gate mechlist_t *pmechlist; 81*0Sstevel@tonic-gate char devname[MAXNAMELEN]; 82*0Sstevel@tonic-gate int inst_num; 83*0Sstevel@tonic-gate int count; 84*0Sstevel@tonic-gate int rc = SUCCESS; 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate if (provname == NULL) { 87*0Sstevel@tonic-gate return (FAILURE); 88*0Sstevel@tonic-gate } 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate /* 91*0Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 92*0Sstevel@tonic-gate * mechanisms also. 93*0Sstevel@tonic-gate */ 94*0Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) == 95*0Sstevel@tonic-gate FAILURE) { 96*0Sstevel@tonic-gate return (FAILURE); 97*0Sstevel@tonic-gate } 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 100*0Sstevel@tonic-gate if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) == 101*0Sstevel@tonic-gate SUCCESS) { 102*0Sstevel@tonic-gate (void) filter_mechlist(&pmechlist, RANDOM); 103*0Sstevel@tonic-gate print_mechlist(provname, pmechlist); 104*0Sstevel@tonic-gate free_mechlist(pmechlist); 105*0Sstevel@tonic-gate } 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate return (rc); 108*0Sstevel@tonic-gate } 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate /* 112*0Sstevel@tonic-gate * Display the policy information for a kernel software provider. 113*0Sstevel@tonic-gate */ 114*0Sstevel@tonic-gate int 115*0Sstevel@tonic-gate list_policy_for_soft(char *provname) 116*0Sstevel@tonic-gate { 117*0Sstevel@tonic-gate int rc; 118*0Sstevel@tonic-gate entry_t *pent = NULL; 119*0Sstevel@tonic-gate mechlist_t *pmechlist; 120*0Sstevel@tonic-gate boolean_t has_random = B_FALSE; 121*0Sstevel@tonic-gate boolean_t has_mechs = B_FALSE; 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate if (provname == NULL) { 124*0Sstevel@tonic-gate return (FAILURE); 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate if ((pent = getent_kef(provname)) == NULL) { 128*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s does not exist."), 129*0Sstevel@tonic-gate provname); 130*0Sstevel@tonic-gate return (FAILURE); 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate rc = get_soft_info(provname, &pmechlist); 134*0Sstevel@tonic-gate if (rc == SUCCESS) { 135*0Sstevel@tonic-gate has_random = filter_mechlist(&pmechlist, RANDOM); 136*0Sstevel@tonic-gate if (pmechlist != NULL) { 137*0Sstevel@tonic-gate has_mechs = B_TRUE; 138*0Sstevel@tonic-gate free_mechlist(pmechlist); 139*0Sstevel@tonic-gate } 140*0Sstevel@tonic-gate } else { 141*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 142*0Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 143*0Sstevel@tonic-gate provname); 144*0Sstevel@tonic-gate return (rc); 145*0Sstevel@tonic-gate } 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate print_kef_policy(pent, has_random, has_mechs); 148*0Sstevel@tonic-gate free_entry(pent); 149*0Sstevel@tonic-gate return (SUCCESS); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate /* 155*0Sstevel@tonic-gate * Display the policy information for a kernel hardware provider. 156*0Sstevel@tonic-gate */ 157*0Sstevel@tonic-gate int 158*0Sstevel@tonic-gate list_policy_for_hard(char *provname) 159*0Sstevel@tonic-gate { 160*0Sstevel@tonic-gate entry_t *pent; 161*0Sstevel@tonic-gate boolean_t is_active; 162*0Sstevel@tonic-gate mechlist_t *pmechlist; 163*0Sstevel@tonic-gate char devname[MAXNAMELEN]; 164*0Sstevel@tonic-gate int inst_num; 165*0Sstevel@tonic-gate int count; 166*0Sstevel@tonic-gate int rc = SUCCESS; 167*0Sstevel@tonic-gate boolean_t has_random = B_FALSE; 168*0Sstevel@tonic-gate boolean_t has_mechs = B_FALSE; 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate if (provname == NULL) { 171*0Sstevel@tonic-gate return (FAILURE); 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate /* 175*0Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 176*0Sstevel@tonic-gate * mechanisms also. 177*0Sstevel@tonic-gate */ 178*0Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) == 179*0Sstevel@tonic-gate FAILURE) { 180*0Sstevel@tonic-gate return (FAILURE); 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 184*0Sstevel@tonic-gate if ((rc = get_dev_info(devname, inst_num, count, &pmechlist)) == 185*0Sstevel@tonic-gate SUCCESS) { 186*0Sstevel@tonic-gate has_random = filter_mechlist(&pmechlist, RANDOM); 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate if (pmechlist != NULL) { 189*0Sstevel@tonic-gate has_mechs = B_TRUE; 190*0Sstevel@tonic-gate free_mechlist(pmechlist); 191*0Sstevel@tonic-gate } 192*0Sstevel@tonic-gate } else { 193*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 194*0Sstevel@tonic-gate "failed to retrieve the mechanism list for %s."), 195*0Sstevel@tonic-gate devname); 196*0Sstevel@tonic-gate return (rc); 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate /* 200*0Sstevel@tonic-gate * If the hardware provider has an entry in the kcf.conf file, 201*0Sstevel@tonic-gate * some of its mechanisms must have been disabled. Print out 202*0Sstevel@tonic-gate * the disabled list from the config file entry. Otherwise, 203*0Sstevel@tonic-gate * if it is active, then all the mechanisms for it are enabled. 204*0Sstevel@tonic-gate */ 205*0Sstevel@tonic-gate if ((pent = getent_kef(provname)) != NULL) { 206*0Sstevel@tonic-gate print_kef_policy(pent, has_random, has_mechs); 207*0Sstevel@tonic-gate free_entry(pent); 208*0Sstevel@tonic-gate return (SUCCESS); 209*0Sstevel@tonic-gate } else { 210*0Sstevel@tonic-gate if (check_active_for_hard(provname, &is_active) == 211*0Sstevel@tonic-gate FAILURE) { 212*0Sstevel@tonic-gate return (FAILURE); 213*0Sstevel@tonic-gate } else if (is_active == B_TRUE) { 214*0Sstevel@tonic-gate (void) printf(gettext( 215*0Sstevel@tonic-gate "%s: all mechanisms are enabled."), provname); 216*0Sstevel@tonic-gate if (has_random) 217*0Sstevel@tonic-gate /* 218*0Sstevel@tonic-gate * TRANSLATION_NOTE: 219*0Sstevel@tonic-gate * "random" is a keyword and not to be 220*0Sstevel@tonic-gate * translated. 221*0Sstevel@tonic-gate */ 222*0Sstevel@tonic-gate (void) printf(gettext(" %s is enabled.\n"), 223*0Sstevel@tonic-gate "random"); 224*0Sstevel@tonic-gate else 225*0Sstevel@tonic-gate (void) printf("\n"); 226*0Sstevel@tonic-gate return (SUCCESS); 227*0Sstevel@tonic-gate } else { 228*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 229*0Sstevel@tonic-gate gettext("%s does not exist."), provname); 230*0Sstevel@tonic-gate return (FAILURE); 231*0Sstevel@tonic-gate } 232*0Sstevel@tonic-gate } 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate int 238*0Sstevel@tonic-gate disable_kef_hardware(char *provname, boolean_t rndflag, boolean_t allflag, 239*0Sstevel@tonic-gate mechlist_t *dislist) 240*0Sstevel@tonic-gate { 241*0Sstevel@tonic-gate crypto_load_dev_disabled_t *pload_dev_dis; 242*0Sstevel@tonic-gate mechlist_t *infolist; 243*0Sstevel@tonic-gate entry_t *pent; 244*0Sstevel@tonic-gate boolean_t new_dev_entry = B_FALSE; 245*0Sstevel@tonic-gate char devname[MAXNAMELEN]; 246*0Sstevel@tonic-gate int inst_num; 247*0Sstevel@tonic-gate int count; 248*0Sstevel@tonic-gate int fd; 249*0Sstevel@tonic-gate int rc = SUCCESS; 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate if (provname == NULL) { 252*0Sstevel@tonic-gate return (FAILURE); 253*0Sstevel@tonic-gate } 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate /* 256*0Sstevel@tonic-gate * Check if the provider is valid. If it is valid, get the number of 257*0Sstevel@tonic-gate * mechanisms also. 258*0Sstevel@tonic-gate */ 259*0Sstevel@tonic-gate if (check_hardware_provider(provname, devname, &inst_num, &count) 260*0Sstevel@tonic-gate == FAILURE) { 261*0Sstevel@tonic-gate return (FAILURE); 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate /* Get the mechanism list for the kernel hardware provider */ 265*0Sstevel@tonic-gate if (get_dev_info(devname, inst_num, count, &infolist) == FAILURE) { 266*0Sstevel@tonic-gate return (FAILURE); 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate /* 270*0Sstevel@tonic-gate * Get the entry of this hardware provider from the config file. 271*0Sstevel@tonic-gate * If there is no entry yet, create one for it. 272*0Sstevel@tonic-gate */ 273*0Sstevel@tonic-gate if ((pent = getent_kef(provname)) == NULL) { 274*0Sstevel@tonic-gate if ((pent = malloc(sizeof (entry_t))) == NULL) { 275*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("out of memory.")); 276*0Sstevel@tonic-gate free_mechlist(infolist); 277*0Sstevel@tonic-gate return (FAILURE); 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate new_dev_entry = B_TRUE; 280*0Sstevel@tonic-gate (void) strlcpy(pent->name, provname, MAXNAMELEN); 281*0Sstevel@tonic-gate pent->suplist = NULL; 282*0Sstevel@tonic-gate pent->sup_count = 0; 283*0Sstevel@tonic-gate pent->dislist = NULL; 284*0Sstevel@tonic-gate pent->dis_count = 0; 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate /* 288*0Sstevel@tonic-gate * kCF treats random as an internal mechanism. So, we need to 289*0Sstevel@tonic-gate * filter it from the mechanism list here, if we are NOT disabling 290*0Sstevel@tonic-gate * or enabling the random feature. Note that we map random feature at 291*0Sstevel@tonic-gate * cryptoadm(1M) level to the "random" mechanism in kCF. 292*0Sstevel@tonic-gate */ 293*0Sstevel@tonic-gate if (!rndflag) { 294*0Sstevel@tonic-gate (void) filter_mechlist(&infolist, RANDOM); 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate /* Calculate the new disabled list */ 298*0Sstevel@tonic-gate if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) { 299*0Sstevel@tonic-gate free_entry(pent); 300*0Sstevel@tonic-gate return (FAILURE); 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate /* If no mechanisms are to be disabled, return */ 304*0Sstevel@tonic-gate if (pent->dis_count == 0) { 305*0Sstevel@tonic-gate free_entry(pent); 306*0Sstevel@tonic-gate return (SUCCESS); 307*0Sstevel@tonic-gate } 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate /* Update the config file with the new entry or the updated entry */ 310*0Sstevel@tonic-gate if (new_dev_entry) { 311*0Sstevel@tonic-gate rc = update_kcfconf(pent, ADD_MODE); 312*0Sstevel@tonic-gate } else { 313*0Sstevel@tonic-gate rc = update_kcfconf(pent, MODIFY_MODE); 314*0Sstevel@tonic-gate } 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate if (rc == FAILURE) { 317*0Sstevel@tonic-gate free_entry(pent); 318*0Sstevel@tonic-gate return (FAILURE); 319*0Sstevel@tonic-gate } 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate /* Inform kernel about the new disabled mechanism list */ 322*0Sstevel@tonic-gate if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) { 323*0Sstevel@tonic-gate free_entry(pent); 324*0Sstevel@tonic-gate return (FAILURE); 325*0Sstevel@tonic-gate } 326*0Sstevel@tonic-gate free_entry(pent); 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 329*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 330*0Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 331*0Sstevel@tonic-gate free(pload_dev_dis); 332*0Sstevel@tonic-gate return (FAILURE); 333*0Sstevel@tonic-gate } 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) { 336*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: %s", 337*0Sstevel@tonic-gate strerror(errno)); 338*0Sstevel@tonic-gate free(pload_dev_dis); 339*0Sstevel@tonic-gate (void) close(fd); 340*0Sstevel@tonic-gate return (FAILURE); 341*0Sstevel@tonic-gate } 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 344*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl return_value = " 345*0Sstevel@tonic-gate "%d", pload_dev_dis->dd_return_value); 346*0Sstevel@tonic-gate free(pload_dev_dis); 347*0Sstevel@tonic-gate (void) close(fd); 348*0Sstevel@tonic-gate return (FAILURE); 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate free(pload_dev_dis); 352*0Sstevel@tonic-gate (void) close(fd); 353*0Sstevel@tonic-gate return (SUCCESS); 354*0Sstevel@tonic-gate } 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate int 359*0Sstevel@tonic-gate disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag, 360*0Sstevel@tonic-gate mechlist_t *dislist) 361*0Sstevel@tonic-gate { 362*0Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 363*0Sstevel@tonic-gate mechlist_t *infolist; 364*0Sstevel@tonic-gate entry_t *pent; 365*0Sstevel@tonic-gate boolean_t is_active; 366*0Sstevel@tonic-gate int fd; 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate if (provname == NULL) { 369*0Sstevel@tonic-gate return (FAILURE); 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate /* Get the entry of this provider from the config file. */ 373*0Sstevel@tonic-gate if ((pent = getent_kef(provname)) == NULL) { 374*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 375*0Sstevel@tonic-gate gettext("%s does not exist."), provname); 376*0Sstevel@tonic-gate return (FAILURE); 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate /* 380*0Sstevel@tonic-gate * Check if the kernel software provider is currently unloaded. 381*0Sstevel@tonic-gate * If it is unloaded, return FAILURE, because the disable subcommand 382*0Sstevel@tonic-gate * can not perform on inactive (unloaded) providers. 383*0Sstevel@tonic-gate */ 384*0Sstevel@tonic-gate if (check_active_for_soft(provname, &is_active) == FAILURE) { 385*0Sstevel@tonic-gate free_entry(pent); 386*0Sstevel@tonic-gate return (FAILURE); 387*0Sstevel@tonic-gate } else if (is_active == B_FALSE) { 388*0Sstevel@tonic-gate /* 389*0Sstevel@tonic-gate * TRANSLATION_NOTE: 390*0Sstevel@tonic-gate * "disable" is a keyword and not to be translated. 391*0Sstevel@tonic-gate */ 392*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 393*0Sstevel@tonic-gate gettext("can not do %1$s on an unloaded " 394*0Sstevel@tonic-gate "kernel software provider -- %2$s."), "disable", provname); 395*0Sstevel@tonic-gate free_entry(pent); 396*0Sstevel@tonic-gate return (FAILURE); 397*0Sstevel@tonic-gate } 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate /* Get the mechanism list for the software provider */ 400*0Sstevel@tonic-gate if (get_soft_info(provname, &infolist) == FAILURE) { 401*0Sstevel@tonic-gate free(pent); 402*0Sstevel@tonic-gate return (FAILURE); 403*0Sstevel@tonic-gate } 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate /* See comments in disable_kef_hardware() */ 406*0Sstevel@tonic-gate if (!rndflag) { 407*0Sstevel@tonic-gate (void) filter_mechlist(&infolist, RANDOM); 408*0Sstevel@tonic-gate } 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate /* Calculate the new disabled list */ 411*0Sstevel@tonic-gate if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) { 412*0Sstevel@tonic-gate free_entry(pent); 413*0Sstevel@tonic-gate free_mechlist(infolist); 414*0Sstevel@tonic-gate return (FAILURE); 415*0Sstevel@tonic-gate } 416*0Sstevel@tonic-gate 417*0Sstevel@tonic-gate /* infolist is no longer needed; free it */ 418*0Sstevel@tonic-gate free_mechlist(infolist); 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate /* Update the kcf.conf file with the updated entry */ 421*0Sstevel@tonic-gate if (update_kcfconf(pent, MODIFY_MODE) == FAILURE) { 422*0Sstevel@tonic-gate free_entry(pent); 423*0Sstevel@tonic-gate return (FAILURE); 424*0Sstevel@tonic-gate } 425*0Sstevel@tonic-gate 426*0Sstevel@tonic-gate /* Inform kernel about the new disabled list. */ 427*0Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 428*0Sstevel@tonic-gate free_entry(pent); 429*0Sstevel@tonic-gate return (FAILURE); 430*0Sstevel@tonic-gate } 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate /* pent is no longer needed; free it. */ 433*0Sstevel@tonic-gate free_entry(pent); 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 436*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 437*0Sstevel@tonic-gate gettext("failed to open %s for RW: %s"), 438*0Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 439*0Sstevel@tonic-gate free(pload_soft_dis); 440*0Sstevel@tonic-gate return (FAILURE); 441*0Sstevel@tonic-gate } 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) { 444*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s", 445*0Sstevel@tonic-gate strerror(errno)); 446*0Sstevel@tonic-gate free(pload_soft_dis); 447*0Sstevel@tonic-gate (void) close(fd); 448*0Sstevel@tonic-gate return (FAILURE); 449*0Sstevel@tonic-gate } 450*0Sstevel@tonic-gate 451*0Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 452*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = " 453*0Sstevel@tonic-gate "%d", pload_soft_dis->sd_return_value); 454*0Sstevel@tonic-gate free(pload_soft_dis); 455*0Sstevel@tonic-gate (void) close(fd); 456*0Sstevel@tonic-gate return (FAILURE); 457*0Sstevel@tonic-gate } 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate free(pload_soft_dis); 460*0Sstevel@tonic-gate (void) close(fd); 461*0Sstevel@tonic-gate return (SUCCESS); 462*0Sstevel@tonic-gate } 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate int 466*0Sstevel@tonic-gate enable_kef(char *provname, boolean_t rndflag, boolean_t allflag, 467*0Sstevel@tonic-gate mechlist_t *mlist) 468*0Sstevel@tonic-gate { 469*0Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 470*0Sstevel@tonic-gate crypto_load_dev_disabled_t *pload_dev_dis = NULL; 471*0Sstevel@tonic-gate entry_t *pent; 472*0Sstevel@tonic-gate boolean_t redo_flag = B_FALSE; 473*0Sstevel@tonic-gate int fd; 474*0Sstevel@tonic-gate int rc = SUCCESS; 475*0Sstevel@tonic-gate 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate /* Get the entry with the provider name from the kcf.conf file */ 478*0Sstevel@tonic-gate pent = getent_kef(provname); 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate if (is_device(provname)) { 481*0Sstevel@tonic-gate if (pent == NULL) { 482*0Sstevel@tonic-gate /* 483*0Sstevel@tonic-gate * This device doesn't have an entry in the config 484*0Sstevel@tonic-gate * file, therefore nothing is disabled. 485*0Sstevel@tonic-gate */ 486*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 487*0Sstevel@tonic-gate "all mechanisms are enabled already for %s."), 488*0Sstevel@tonic-gate provname); 489*0Sstevel@tonic-gate return (SUCCESS); 490*0Sstevel@tonic-gate } 491*0Sstevel@tonic-gate } else { /* a software module */ 492*0Sstevel@tonic-gate if (pent == NULL) { 493*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 494*0Sstevel@tonic-gate gettext("%s does not exist."), provname); 495*0Sstevel@tonic-gate return (FAILURE); 496*0Sstevel@tonic-gate } else if (pent->dis_count == 0) { 497*0Sstevel@tonic-gate /* nothing to be enabled. */ 498*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 499*0Sstevel@tonic-gate "all mechanisms are enabled already for %s."), 500*0Sstevel@tonic-gate provname); 501*0Sstevel@tonic-gate free_entry(pent); 502*0Sstevel@tonic-gate return (SUCCESS); 503*0Sstevel@tonic-gate } 504*0Sstevel@tonic-gate } 505*0Sstevel@tonic-gate 506*0Sstevel@tonic-gate if (!rndflag) { 507*0Sstevel@tonic-gate /* See comments in disable_kef_hardware() */ 508*0Sstevel@tonic-gate redo_flag = filter_mechlist(&pent->dislist, RANDOM); 509*0Sstevel@tonic-gate if (redo_flag) 510*0Sstevel@tonic-gate pent->dis_count--; 511*0Sstevel@tonic-gate } 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate /* Update the entry by enabling mechanisms for this provider */ 514*0Sstevel@tonic-gate if ((rc = enable_mechs(&pent, allflag, mlist)) != SUCCESS) { 515*0Sstevel@tonic-gate free_entry(pent); 516*0Sstevel@tonic-gate return (rc); 517*0Sstevel@tonic-gate } 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate if (redo_flag) { 520*0Sstevel@tonic-gate mechlist_t *tmp; 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate if ((tmp = create_mech(RANDOM)) == NULL) { 523*0Sstevel@tonic-gate free_entry(pent); 524*0Sstevel@tonic-gate return (FAILURE); 525*0Sstevel@tonic-gate } 526*0Sstevel@tonic-gate tmp->next = pent->dislist; 527*0Sstevel@tonic-gate pent->dislist = tmp; 528*0Sstevel@tonic-gate pent->dis_count++; 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate /* 532*0Sstevel@tonic-gate * Update the kcf.conf file with the updated entry. 533*0Sstevel@tonic-gate * For a hardware provider, if there is no more disabled mechanism, 534*0Sstevel@tonic-gate * the entire entry in the config file should be removed. 535*0Sstevel@tonic-gate */ 536*0Sstevel@tonic-gate if (is_device(pent->name) && (pent->dis_count == 0)) { 537*0Sstevel@tonic-gate rc = update_kcfconf(pent, DELETE_MODE); 538*0Sstevel@tonic-gate } else { 539*0Sstevel@tonic-gate rc = update_kcfconf(pent, MODIFY_MODE); 540*0Sstevel@tonic-gate } 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate if (rc == FAILURE) { 543*0Sstevel@tonic-gate free_entry(pent); 544*0Sstevel@tonic-gate return (FAILURE); 545*0Sstevel@tonic-gate } 546*0Sstevel@tonic-gate 547*0Sstevel@tonic-gate 548*0Sstevel@tonic-gate /* Inform Kernel about the policy change */ 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 551*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 552*0Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 553*0Sstevel@tonic-gate return (FAILURE); 554*0Sstevel@tonic-gate } 555*0Sstevel@tonic-gate 556*0Sstevel@tonic-gate if (is_device(provname)) { 557*0Sstevel@tonic-gate /* LOAD_DEV_DISABLED */ 558*0Sstevel@tonic-gate if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) { 559*0Sstevel@tonic-gate return (FAILURE); 560*0Sstevel@tonic-gate } 561*0Sstevel@tonic-gate 562*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) { 563*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: " 564*0Sstevel@tonic-gate "%s", strerror(errno)); 565*0Sstevel@tonic-gate free(pload_dev_dis); 566*0Sstevel@tonic-gate (void) close(fd); 567*0Sstevel@tonic-gate return (FAILURE); 568*0Sstevel@tonic-gate } 569*0Sstevel@tonic-gate 570*0Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 571*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 572*0Sstevel@tonic-gate "return_value = %d", 573*0Sstevel@tonic-gate pload_dev_dis->dd_return_value); 574*0Sstevel@tonic-gate free(pload_dev_dis); 575*0Sstevel@tonic-gate (void) close(fd); 576*0Sstevel@tonic-gate return (FAILURE); 577*0Sstevel@tonic-gate } 578*0Sstevel@tonic-gate 579*0Sstevel@tonic-gate } else { 580*0Sstevel@tonic-gate /* LOAD_SOFT_DISABLED */ 581*0Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 582*0Sstevel@tonic-gate return (FAILURE); 583*0Sstevel@tonic-gate } 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) 586*0Sstevel@tonic-gate == -1) { 587*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: " 588*0Sstevel@tonic-gate "%s", strerror(errno)); 589*0Sstevel@tonic-gate free(pload_soft_dis); 590*0Sstevel@tonic-gate (void) close(fd); 591*0Sstevel@tonic-gate return (FAILURE); 592*0Sstevel@tonic-gate } 593*0Sstevel@tonic-gate 594*0Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 595*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 596*0Sstevel@tonic-gate "return_value = %d", 597*0Sstevel@tonic-gate pload_soft_dis->sd_return_value); 598*0Sstevel@tonic-gate free(pload_soft_dis); 599*0Sstevel@tonic-gate (void) close(fd); 600*0Sstevel@tonic-gate return (FAILURE); 601*0Sstevel@tonic-gate } 602*0Sstevel@tonic-gate } 603*0Sstevel@tonic-gate 604*0Sstevel@tonic-gate (void) close(fd); 605*0Sstevel@tonic-gate return (SUCCESS); 606*0Sstevel@tonic-gate } 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gate 609*0Sstevel@tonic-gate /* 610*0Sstevel@tonic-gate * Install a software module with the specified mechanism list into the system. 611*0Sstevel@tonic-gate * This routine adds an entry into the config file for this software module 612*0Sstevel@tonic-gate * first, then makes a CRYPTO_LOAD_SOFT_CONFIG ioctl call to inform kernel 613*0Sstevel@tonic-gate * about the new addition. 614*0Sstevel@tonic-gate */ 615*0Sstevel@tonic-gate int 616*0Sstevel@tonic-gate install_kef(char *provname, mechlist_t *mlist) 617*0Sstevel@tonic-gate { 618*0Sstevel@tonic-gate crypto_load_soft_config_t *pload_soft_conf = NULL; 619*0Sstevel@tonic-gate boolean_t found; 620*0Sstevel@tonic-gate entry_t *pent; 621*0Sstevel@tonic-gate FILE *pfile; 622*0Sstevel@tonic-gate FILE *pfile_tmp; 623*0Sstevel@tonic-gate char tmpfile_name[MAXPATHLEN]; 624*0Sstevel@tonic-gate char *ptr; 625*0Sstevel@tonic-gate char *str; 626*0Sstevel@tonic-gate char *name; 627*0Sstevel@tonic-gate char buffer[BUFSIZ]; 628*0Sstevel@tonic-gate char buffer2[BUFSIZ]; 629*0Sstevel@tonic-gate int found_count; 630*0Sstevel@tonic-gate int fd; 631*0Sstevel@tonic-gate int rc = SUCCESS; 632*0Sstevel@tonic-gate 633*0Sstevel@tonic-gate if ((provname == NULL) || (mlist == NULL)) { 634*0Sstevel@tonic-gate return (FAILURE); 635*0Sstevel@tonic-gate } 636*0Sstevel@tonic-gate 637*0Sstevel@tonic-gate /* Check if the provider already exists */ 638*0Sstevel@tonic-gate if ((pent = getent_kef(provname)) != NULL) { 639*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s exists already."), 640*0Sstevel@tonic-gate provname); 641*0Sstevel@tonic-gate free_entry(pent); 642*0Sstevel@tonic-gate return (FAILURE); 643*0Sstevel@tonic-gate } 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate /* Create an entry with provname and mlist. */ 646*0Sstevel@tonic-gate if ((pent = malloc(sizeof (entry_t))) == NULL) { 647*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("out of memory.")); 648*0Sstevel@tonic-gate return (FAILURE); 649*0Sstevel@tonic-gate } 650*0Sstevel@tonic-gate 651*0Sstevel@tonic-gate (void) strlcpy(pent->name, provname, MAXNAMELEN); 652*0Sstevel@tonic-gate pent->sup_count = get_mech_count(mlist); 653*0Sstevel@tonic-gate pent->suplist = mlist; 654*0Sstevel@tonic-gate pent->dis_count = 0; 655*0Sstevel@tonic-gate pent->dislist = NULL; 656*0Sstevel@tonic-gate 657*0Sstevel@tonic-gate /* Append an entry for this software module to the kcf.conf file. */ 658*0Sstevel@tonic-gate if ((str = ent2str(pent)) == NULL) { 659*0Sstevel@tonic-gate free_entry(pent); 660*0Sstevel@tonic-gate return (FAILURE); 661*0Sstevel@tonic-gate } 662*0Sstevel@tonic-gate 663*0Sstevel@tonic-gate if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) { 664*0Sstevel@tonic-gate err = errno; 665*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 666*0Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 667*0Sstevel@tonic-gate strerror(err)); 668*0Sstevel@tonic-gate cryptodebug("failed to open %s for write.", _PATH_KCF_CONF); 669*0Sstevel@tonic-gate free_entry(pent); 670*0Sstevel@tonic-gate return (FAILURE); 671*0Sstevel@tonic-gate } 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 674*0Sstevel@tonic-gate err = errno; 675*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 676*0Sstevel@tonic-gate gettext("failed to lock the configuration - %s"), 677*0Sstevel@tonic-gate strerror(err)); 678*0Sstevel@tonic-gate free_entry(pent); 679*0Sstevel@tonic-gate (void) fclose(pfile); 680*0Sstevel@tonic-gate return (FAILURE); 681*0Sstevel@tonic-gate } 682*0Sstevel@tonic-gate 683*0Sstevel@tonic-gate /* 684*0Sstevel@tonic-gate * Create a temporary file in the /etc/crypto directory. 685*0Sstevel@tonic-gate */ 686*0Sstevel@tonic-gate (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 687*0Sstevel@tonic-gate if (mkstemp(tmpfile_name) == -1) { 688*0Sstevel@tonic-gate err = errno; 689*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 690*0Sstevel@tonic-gate gettext("failed to create a temporary file - %s"), 691*0Sstevel@tonic-gate strerror(err)); 692*0Sstevel@tonic-gate free_entry(pent); 693*0Sstevel@tonic-gate (void) fclose(pfile); 694*0Sstevel@tonic-gate return (FAILURE); 695*0Sstevel@tonic-gate } 696*0Sstevel@tonic-gate 697*0Sstevel@tonic-gate if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 698*0Sstevel@tonic-gate err = errno; 699*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 700*0Sstevel@tonic-gate tmpfile_name, strerror(err)); 701*0Sstevel@tonic-gate free_entry(pent); 702*0Sstevel@tonic-gate (void) fclose(pfile); 703*0Sstevel@tonic-gate return (FAILURE); 704*0Sstevel@tonic-gate } 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate 707*0Sstevel@tonic-gate /* 708*0Sstevel@tonic-gate * Loop thru the config file. If the provider was reserved within a 709*0Sstevel@tonic-gate * package bracket, just uncomment it. Otherwise, append it at 710*0Sstevel@tonic-gate * the end. The resulting file will be saved in the temp file first. 711*0Sstevel@tonic-gate */ 712*0Sstevel@tonic-gate found_count = 0; 713*0Sstevel@tonic-gate rc = SUCCESS; 714*0Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) { 715*0Sstevel@tonic-gate found = B_FALSE; 716*0Sstevel@tonic-gate if (buffer[0] == '#') { 717*0Sstevel@tonic-gate (void) strlcpy(buffer2, buffer, BUFSIZ); 718*0Sstevel@tonic-gate ptr = buffer2; 719*0Sstevel@tonic-gate ptr++; 720*0Sstevel@tonic-gate if ((name = strtok(ptr, SEP_COLON)) == NULL) { 721*0Sstevel@tonic-gate rc = FAILURE; 722*0Sstevel@tonic-gate break; 723*0Sstevel@tonic-gate } else if (strcmp(provname, name) == 0) { 724*0Sstevel@tonic-gate found = B_TRUE; 725*0Sstevel@tonic-gate found_count++; 726*0Sstevel@tonic-gate } 727*0Sstevel@tonic-gate } 728*0Sstevel@tonic-gate 729*0Sstevel@tonic-gate if (found == B_FALSE) { 730*0Sstevel@tonic-gate if (fputs(buffer, pfile_tmp) == EOF) { 731*0Sstevel@tonic-gate rc = FAILURE; 732*0Sstevel@tonic-gate } 733*0Sstevel@tonic-gate } else { 734*0Sstevel@tonic-gate if (found_count == 1) { 735*0Sstevel@tonic-gate if (fputs(str, pfile_tmp) == EOF) { 736*0Sstevel@tonic-gate rc = FAILURE; 737*0Sstevel@tonic-gate } 738*0Sstevel@tonic-gate } else { 739*0Sstevel@tonic-gate /* 740*0Sstevel@tonic-gate * Found a second entry with #libname. 741*0Sstevel@tonic-gate * Should not happen. The kcf.conf ffile 742*0Sstevel@tonic-gate * is corrupted. Give a warning and skip 743*0Sstevel@tonic-gate * this entry. 744*0Sstevel@tonic-gate */ 745*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 746*0Sstevel@tonic-gate "(Warning) Found an additional reserved " 747*0Sstevel@tonic-gate "entry for %s."), provname); 748*0Sstevel@tonic-gate } 749*0Sstevel@tonic-gate } 750*0Sstevel@tonic-gate 751*0Sstevel@tonic-gate if (rc == FAILURE) { 752*0Sstevel@tonic-gate break; 753*0Sstevel@tonic-gate } 754*0Sstevel@tonic-gate } 755*0Sstevel@tonic-gate (void) fclose(pfile); 756*0Sstevel@tonic-gate 757*0Sstevel@tonic-gate if (rc == FAILURE) { 758*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("write error.")); 759*0Sstevel@tonic-gate (void) fclose(pfile_tmp); 760*0Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 761*0Sstevel@tonic-gate err = errno; 762*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 763*0Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), tmpfile_name, 764*0Sstevel@tonic-gate strerror(err)); 765*0Sstevel@tonic-gate } 766*0Sstevel@tonic-gate free_entry(pent); 767*0Sstevel@tonic-gate return (FAILURE); 768*0Sstevel@tonic-gate } 769*0Sstevel@tonic-gate 770*0Sstevel@tonic-gate if (found_count == 0) { 771*0Sstevel@tonic-gate /* 772*0Sstevel@tonic-gate * This libname was not in package before, append it to the 773*0Sstevel@tonic-gate * end of the temp file. 774*0Sstevel@tonic-gate */ 775*0Sstevel@tonic-gate if (fputs(str, pfile_tmp) == EOF) { 776*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 777*0Sstevel@tonic-gate "failed to write to %s: %s"), tmpfile_name, 778*0Sstevel@tonic-gate strerror(errno)); 779*0Sstevel@tonic-gate (void) fclose(pfile_tmp); 780*0Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 781*0Sstevel@tonic-gate err = errno; 782*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 783*0Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 784*0Sstevel@tonic-gate tmpfile_name, strerror(err)); 785*0Sstevel@tonic-gate } 786*0Sstevel@tonic-gate free_entry(pent); 787*0Sstevel@tonic-gate return (FAILURE); 788*0Sstevel@tonic-gate } 789*0Sstevel@tonic-gate } 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate if (fclose(pfile_tmp) != 0) { 792*0Sstevel@tonic-gate err = errno; 793*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 794*0Sstevel@tonic-gate gettext("failed to close %s: %s"), tmpfile_name, 795*0Sstevel@tonic-gate strerror(err)); 796*0Sstevel@tonic-gate return (FAILURE); 797*0Sstevel@tonic-gate } 798*0Sstevel@tonic-gate 799*0Sstevel@tonic-gate if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) { 800*0Sstevel@tonic-gate err = errno; 801*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 802*0Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 803*0Sstevel@tonic-gate strerror(err)); 804*0Sstevel@tonic-gate cryptodebug("failed to rename %s to %s: %s", tmpfile_name, 805*0Sstevel@tonic-gate _PATH_KCF_CONF, strerror(err)); 806*0Sstevel@tonic-gate rc = FAILURE; 807*0Sstevel@tonic-gate } else if (chmod(_PATH_KCF_CONF, 808*0Sstevel@tonic-gate S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 809*0Sstevel@tonic-gate err = errno; 810*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 811*0Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 812*0Sstevel@tonic-gate strerror(err)); 813*0Sstevel@tonic-gate cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF, 814*0Sstevel@tonic-gate strerror(err)); 815*0Sstevel@tonic-gate rc = FAILURE; 816*0Sstevel@tonic-gate } else { 817*0Sstevel@tonic-gate rc = SUCCESS; 818*0Sstevel@tonic-gate } 819*0Sstevel@tonic-gate 820*0Sstevel@tonic-gate if (rc == FAILURE) { 821*0Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 822*0Sstevel@tonic-gate err = errno; 823*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 824*0Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 825*0Sstevel@tonic-gate tmpfile_name, strerror(err)); 826*0Sstevel@tonic-gate } 827*0Sstevel@tonic-gate return (FAILURE); 828*0Sstevel@tonic-gate } 829*0Sstevel@tonic-gate 830*0Sstevel@tonic-gate 831*0Sstevel@tonic-gate /* Inform kernel of this new software module. */ 832*0Sstevel@tonic-gate 833*0Sstevel@tonic-gate if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) { 834*0Sstevel@tonic-gate free_entry(pent); 835*0Sstevel@tonic-gate return (FAILURE); 836*0Sstevel@tonic-gate } 837*0Sstevel@tonic-gate 838*0Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 839*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 840*0Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 841*0Sstevel@tonic-gate free_entry(pent); 842*0Sstevel@tonic-gate free(pload_soft_conf); 843*0Sstevel@tonic-gate return (FAILURE); 844*0Sstevel@tonic-gate } 845*0Sstevel@tonic-gate 846*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) { 847*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 848*0Sstevel@tonic-gate strerror(errno)); 849*0Sstevel@tonic-gate free_entry(pent); 850*0Sstevel@tonic-gate free(pload_soft_conf); 851*0Sstevel@tonic-gate (void) close(fd); 852*0Sstevel@tonic-gate return (FAILURE); 853*0Sstevel@tonic-gate } 854*0Sstevel@tonic-gate 855*0Sstevel@tonic-gate if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 856*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed, " 857*0Sstevel@tonic-gate "return_value = %d", pload_soft_conf->sc_return_value); 858*0Sstevel@tonic-gate free_entry(pent); 859*0Sstevel@tonic-gate free(pload_soft_conf); 860*0Sstevel@tonic-gate (void) close(fd); 861*0Sstevel@tonic-gate return (FAILURE); 862*0Sstevel@tonic-gate } 863*0Sstevel@tonic-gate 864*0Sstevel@tonic-gate free_entry(pent); 865*0Sstevel@tonic-gate free(pload_soft_conf); 866*0Sstevel@tonic-gate (void) close(fd); 867*0Sstevel@tonic-gate return (SUCCESS); 868*0Sstevel@tonic-gate } 869*0Sstevel@tonic-gate 870*0Sstevel@tonic-gate /* 871*0Sstevel@tonic-gate * Uninstall the software module. This routine first unloads the software 872*0Sstevel@tonic-gate * module with 3 ioctl calls, then deletes its entry from the config file. 873*0Sstevel@tonic-gate * Removing an entry from the config file needs to be done last to ensure 874*0Sstevel@tonic-gate * that there is still an entry if the earlier unload failed for any reason. 875*0Sstevel@tonic-gate */ 876*0Sstevel@tonic-gate int 877*0Sstevel@tonic-gate uninstall_kef(char *provname) 878*0Sstevel@tonic-gate { 879*0Sstevel@tonic-gate entry_t *pent; 880*0Sstevel@tonic-gate boolean_t is_active; 881*0Sstevel@tonic-gate boolean_t in_package; 882*0Sstevel@tonic-gate boolean_t found; 883*0Sstevel@tonic-gate FILE *pfile; 884*0Sstevel@tonic-gate FILE *pfile_tmp; 885*0Sstevel@tonic-gate char tmpfile_name[MAXPATHLEN]; 886*0Sstevel@tonic-gate char *name; 887*0Sstevel@tonic-gate char strbuf[BUFSIZ]; 888*0Sstevel@tonic-gate char buffer[BUFSIZ]; 889*0Sstevel@tonic-gate char buffer2[BUFSIZ]; 890*0Sstevel@tonic-gate char *str; 891*0Sstevel@tonic-gate int len; 892*0Sstevel@tonic-gate int rc = SUCCESS; 893*0Sstevel@tonic-gate 894*0Sstevel@tonic-gate 895*0Sstevel@tonic-gate /* Check if it is in the kcf.conf file first. */ 896*0Sstevel@tonic-gate if ((pent = getent_kef(provname)) == NULL) { 897*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 898*0Sstevel@tonic-gate gettext("%s does not exist."), provname); 899*0Sstevel@tonic-gate return (FAILURE); 900*0Sstevel@tonic-gate } 901*0Sstevel@tonic-gate 902*0Sstevel@tonic-gate 903*0Sstevel@tonic-gate /* 904*0Sstevel@tonic-gate * Get rid of the disabled list for the provider and get the converted 905*0Sstevel@tonic-gate * string for the entry. This is to prepare the string for a provider 906*0Sstevel@tonic-gate * that is in a package. 907*0Sstevel@tonic-gate */ 908*0Sstevel@tonic-gate free_mechlist(pent->dislist); 909*0Sstevel@tonic-gate pent->dis_count = 0; 910*0Sstevel@tonic-gate pent->dislist = NULL; 911*0Sstevel@tonic-gate str = ent2str(pent); 912*0Sstevel@tonic-gate free_entry(pent); 913*0Sstevel@tonic-gate if (str == NULL) { 914*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 915*0Sstevel@tonic-gate return (FAILURE); 916*0Sstevel@tonic-gate } 917*0Sstevel@tonic-gate (void) snprintf(strbuf, sizeof (strbuf), "%s%s", "#", str); 918*0Sstevel@tonic-gate free(str); 919*0Sstevel@tonic-gate 920*0Sstevel@tonic-gate /* If it is not loaded, unload it first */ 921*0Sstevel@tonic-gate if (check_active_for_soft(provname, &is_active) == FAILURE) { 922*0Sstevel@tonic-gate return (FAILURE); 923*0Sstevel@tonic-gate } else if ((is_active == B_TRUE) && 924*0Sstevel@tonic-gate (unload_kef_soft(provname) == FAILURE)) { 925*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 926*0Sstevel@tonic-gate gettext("failed to uninstall %s.\n"), provname); 927*0Sstevel@tonic-gate return (FAILURE); 928*0Sstevel@tonic-gate } 929*0Sstevel@tonic-gate 930*0Sstevel@tonic-gate /* 931*0Sstevel@tonic-gate * Remove the entry from the config file. If the provider to be 932*0Sstevel@tonic-gate * uninstalled is in a package, just comment it off. 933*0Sstevel@tonic-gate */ 934*0Sstevel@tonic-gate if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) { 935*0Sstevel@tonic-gate err = errno; 936*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 937*0Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 938*0Sstevel@tonic-gate strerror(err)); 939*0Sstevel@tonic-gate cryptodebug("failed to open %s for write.", _PATH_KCF_CONF); 940*0Sstevel@tonic-gate return (FAILURE); 941*0Sstevel@tonic-gate } 942*0Sstevel@tonic-gate 943*0Sstevel@tonic-gate if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 944*0Sstevel@tonic-gate err = errno; 945*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 946*0Sstevel@tonic-gate gettext("failed to lock the configuration - %s"), 947*0Sstevel@tonic-gate strerror(err)); 948*0Sstevel@tonic-gate (void) fclose(pfile); 949*0Sstevel@tonic-gate return (FAILURE); 950*0Sstevel@tonic-gate } 951*0Sstevel@tonic-gate 952*0Sstevel@tonic-gate /* 953*0Sstevel@tonic-gate * Create a temporary file in the /etc/crypto directory to save 954*0Sstevel@tonic-gate * the new configuration file first. 955*0Sstevel@tonic-gate */ 956*0Sstevel@tonic-gate (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 957*0Sstevel@tonic-gate if (mkstemp(tmpfile_name) == -1) { 958*0Sstevel@tonic-gate err = errno; 959*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 960*0Sstevel@tonic-gate gettext("failed to create a temporary file - %s"), 961*0Sstevel@tonic-gate strerror(err)); 962*0Sstevel@tonic-gate (void) fclose(pfile); 963*0Sstevel@tonic-gate return (FAILURE); 964*0Sstevel@tonic-gate } 965*0Sstevel@tonic-gate 966*0Sstevel@tonic-gate if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 967*0Sstevel@tonic-gate err = errno; 968*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 969*0Sstevel@tonic-gate tmpfile_name, strerror(err)); 970*0Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 971*0Sstevel@tonic-gate err = errno; 972*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 973*0Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), tmpfile_name, 974*0Sstevel@tonic-gate strerror(err)); 975*0Sstevel@tonic-gate } 976*0Sstevel@tonic-gate (void) fclose(pfile); 977*0Sstevel@tonic-gate return (FAILURE); 978*0Sstevel@tonic-gate } 979*0Sstevel@tonic-gate 980*0Sstevel@tonic-gate /* 981*0Sstevel@tonic-gate * Loop thru the config file. If the kernel software provider 982*0Sstevel@tonic-gate * to be uninstalled is in a package, just comment it off. 983*0Sstevel@tonic-gate */ 984*0Sstevel@tonic-gate in_package = B_FALSE; 985*0Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) { 986*0Sstevel@tonic-gate found = B_FALSE; 987*0Sstevel@tonic-gate if (!(buffer[0] == ' ' || buffer[0] == '\n' || 988*0Sstevel@tonic-gate buffer[0] == '\t')) { 989*0Sstevel@tonic-gate if (strstr(buffer, " Start ") != NULL) { 990*0Sstevel@tonic-gate in_package = B_TRUE; 991*0Sstevel@tonic-gate } else if (strstr(buffer, " End ") != NULL) { 992*0Sstevel@tonic-gate in_package = B_FALSE; 993*0Sstevel@tonic-gate } else if (buffer[0] != '#') { 994*0Sstevel@tonic-gate (void) strlcpy(buffer2, buffer, BUFSIZ); 995*0Sstevel@tonic-gate 996*0Sstevel@tonic-gate /* get rid of trailing '\n' */ 997*0Sstevel@tonic-gate len = strlen(buffer2); 998*0Sstevel@tonic-gate if (buffer2[len-1] == '\n') { 999*0Sstevel@tonic-gate len--; 1000*0Sstevel@tonic-gate } 1001*0Sstevel@tonic-gate buffer2[len] = '\0'; 1002*0Sstevel@tonic-gate 1003*0Sstevel@tonic-gate if ((name = strtok(buffer2, SEP_COLON)) 1004*0Sstevel@tonic-gate == NULL) { 1005*0Sstevel@tonic-gate rc = FAILURE; 1006*0Sstevel@tonic-gate break; 1007*0Sstevel@tonic-gate } else if (strcmp(provname, name) == 0) { 1008*0Sstevel@tonic-gate found = B_TRUE; 1009*0Sstevel@tonic-gate } 1010*0Sstevel@tonic-gate } 1011*0Sstevel@tonic-gate } 1012*0Sstevel@tonic-gate 1013*0Sstevel@tonic-gate if (found) { 1014*0Sstevel@tonic-gate if (in_package) { 1015*0Sstevel@tonic-gate if (fputs(strbuf, pfile_tmp) == EOF) { 1016*0Sstevel@tonic-gate rc = FAILURE; 1017*0Sstevel@tonic-gate } 1018*0Sstevel@tonic-gate } 1019*0Sstevel@tonic-gate } else { 1020*0Sstevel@tonic-gate if (fputs(buffer, pfile_tmp) == EOF) { 1021*0Sstevel@tonic-gate rc = FAILURE; 1022*0Sstevel@tonic-gate } 1023*0Sstevel@tonic-gate } 1024*0Sstevel@tonic-gate 1025*0Sstevel@tonic-gate if (rc == FAILURE) { 1026*0Sstevel@tonic-gate break; 1027*0Sstevel@tonic-gate } 1028*0Sstevel@tonic-gate } 1029*0Sstevel@tonic-gate 1030*0Sstevel@tonic-gate if (rc == FAILURE) { 1031*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("write error.")); 1032*0Sstevel@tonic-gate (void) fclose(pfile); 1033*0Sstevel@tonic-gate (void) fclose(pfile_tmp); 1034*0Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 1035*0Sstevel@tonic-gate err = errno; 1036*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 1037*0Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), tmpfile_name, 1038*0Sstevel@tonic-gate strerror(err)); 1039*0Sstevel@tonic-gate } 1040*0Sstevel@tonic-gate return (FAILURE); 1041*0Sstevel@tonic-gate } 1042*0Sstevel@tonic-gate 1043*0Sstevel@tonic-gate (void) fclose(pfile); 1044*0Sstevel@tonic-gate if (fclose(pfile_tmp) != 0) { 1045*0Sstevel@tonic-gate err = errno; 1046*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 1047*0Sstevel@tonic-gate gettext("failed to close %s: %s"), tmpfile_name, 1048*0Sstevel@tonic-gate strerror(err)); 1049*0Sstevel@tonic-gate return (FAILURE); 1050*0Sstevel@tonic-gate } 1051*0Sstevel@tonic-gate 1052*0Sstevel@tonic-gate /* Now update the real config file */ 1053*0Sstevel@tonic-gate if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) { 1054*0Sstevel@tonic-gate err = errno; 1055*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 1056*0Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 1057*0Sstevel@tonic-gate strerror(err)); 1058*0Sstevel@tonic-gate cryptodebug("failed to rename %1$s to %2$s: %3$s", tmpfile, 1059*0Sstevel@tonic-gate _PATH_KCF_CONF, strerror(err)); 1060*0Sstevel@tonic-gate rc = FAILURE; 1061*0Sstevel@tonic-gate } else if (chmod(_PATH_KCF_CONF, 1062*0Sstevel@tonic-gate S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 1063*0Sstevel@tonic-gate err = errno; 1064*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, 1065*0Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 1066*0Sstevel@tonic-gate strerror(err)); 1067*0Sstevel@tonic-gate cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF, 1068*0Sstevel@tonic-gate strerror(err)); 1069*0Sstevel@tonic-gate rc = FAILURE; 1070*0Sstevel@tonic-gate } else { 1071*0Sstevel@tonic-gate rc = SUCCESS; 1072*0Sstevel@tonic-gate } 1073*0Sstevel@tonic-gate 1074*0Sstevel@tonic-gate if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) { 1075*0Sstevel@tonic-gate err = errno; 1076*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 1077*0Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), tmpfile_name, 1078*0Sstevel@tonic-gate strerror(err)); 1079*0Sstevel@tonic-gate } 1080*0Sstevel@tonic-gate 1081*0Sstevel@tonic-gate return (rc); 1082*0Sstevel@tonic-gate 1083*0Sstevel@tonic-gate } 1084*0Sstevel@tonic-gate 1085*0Sstevel@tonic-gate 1086*0Sstevel@tonic-gate int 1087*0Sstevel@tonic-gate refresh(void) 1088*0Sstevel@tonic-gate { 1089*0Sstevel@tonic-gate crypto_get_soft_list_t *psoftlist_kernel = NULL; 1090*0Sstevel@tonic-gate crypto_load_soft_config_t *pload_soft_conf = NULL; 1091*0Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 1092*0Sstevel@tonic-gate crypto_load_dev_disabled_t *pload_dev_dis = NULL; 1093*0Sstevel@tonic-gate entrylist_t *pdevlist = NULL; 1094*0Sstevel@tonic-gate entrylist_t *psoftlist = NULL; 1095*0Sstevel@tonic-gate entrylist_t *ptr; 1096*0Sstevel@tonic-gate boolean_t found; 1097*0Sstevel@tonic-gate char *psoftname; 1098*0Sstevel@tonic-gate int fd; 1099*0Sstevel@tonic-gate int rc = SUCCESS; 1100*0Sstevel@tonic-gate int i; 1101*0Sstevel@tonic-gate 1102*0Sstevel@tonic-gate if (get_soft_list(&psoftlist_kernel) == FAILURE) { 1103*0Sstevel@tonic-gate cryptoerror(LOG_ERR, gettext("Failed to retrieve the " 1104*0Sstevel@tonic-gate "software provider list from kernel.")); 1105*0Sstevel@tonic-gate return (FAILURE); 1106*0Sstevel@tonic-gate } 1107*0Sstevel@tonic-gate 1108*0Sstevel@tonic-gate if (get_kcfconf_info(&pdevlist, &psoftlist) == FAILURE) { 1109*0Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to retrieve the providers' " 1110*0Sstevel@tonic-gate "information from the configuration file - %s.", 1111*0Sstevel@tonic-gate _PATH_KCF_CONF); 1112*0Sstevel@tonic-gate return (FAILURE); 1113*0Sstevel@tonic-gate } 1114*0Sstevel@tonic-gate 1115*0Sstevel@tonic-gate /* 1116*0Sstevel@tonic-gate * If a kernel software provider is in kernel, but it is not in the 1117*0Sstevel@tonic-gate * kcf.conf file, it must have been pkgrm'ed and needs to be unloaded 1118*0Sstevel@tonic-gate * now. 1119*0Sstevel@tonic-gate */ 1120*0Sstevel@tonic-gate if (psoftlist_kernel->sl_soft_count > 0) { 1121*0Sstevel@tonic-gate psoftname = psoftlist_kernel->sl_soft_names; 1122*0Sstevel@tonic-gate for (i = 0; i < psoftlist_kernel->sl_soft_count; i++) { 1123*0Sstevel@tonic-gate ptr = psoftlist; 1124*0Sstevel@tonic-gate found = B_FALSE; 1125*0Sstevel@tonic-gate while (ptr != NULL) { 1126*0Sstevel@tonic-gate if (strcmp(psoftname, ptr->pent->name) == 0) { 1127*0Sstevel@tonic-gate found = B_TRUE; 1128*0Sstevel@tonic-gate break; 1129*0Sstevel@tonic-gate } 1130*0Sstevel@tonic-gate ptr = ptr->next; 1131*0Sstevel@tonic-gate } 1132*0Sstevel@tonic-gate 1133*0Sstevel@tonic-gate if (!found) { 1134*0Sstevel@tonic-gate rc = unload_kef_soft(psoftname); 1135*0Sstevel@tonic-gate if (rc == FAILURE) { 1136*0Sstevel@tonic-gate cryptoerror(LOG_ERR, gettext( 1137*0Sstevel@tonic-gate "WARNING - the provider %s is " 1138*0Sstevel@tonic-gate "still in kernel."), psoftname); 1139*0Sstevel@tonic-gate } 1140*0Sstevel@tonic-gate } 1141*0Sstevel@tonic-gate psoftname = psoftname + strlen(psoftname) + 1; 1142*0Sstevel@tonic-gate } 1143*0Sstevel@tonic-gate } 1144*0Sstevel@tonic-gate free(psoftlist_kernel); 1145*0Sstevel@tonic-gate 1146*0Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 1147*0Sstevel@tonic-gate err = errno; 1148*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 1149*0Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(err)); 1150*0Sstevel@tonic-gate free(psoftlist); 1151*0Sstevel@tonic-gate free(pdevlist); 1152*0Sstevel@tonic-gate return (FAILURE); 1153*0Sstevel@tonic-gate } 1154*0Sstevel@tonic-gate 1155*0Sstevel@tonic-gate /* 1156*0Sstevel@tonic-gate * For each software module, pass two sets of information to kernel 1157*0Sstevel@tonic-gate * - the supported list and the disabled list 1158*0Sstevel@tonic-gate */ 1159*0Sstevel@tonic-gate ptr = psoftlist; 1160*0Sstevel@tonic-gate while (ptr != NULL) { 1161*0Sstevel@tonic-gate /* load the supported list */ 1162*0Sstevel@tonic-gate if ((pload_soft_conf = setup_soft_conf(ptr->pent)) == NULL) { 1163*0Sstevel@tonic-gate rc = FAILURE; 1164*0Sstevel@tonic-gate break; 1165*0Sstevel@tonic-gate } 1166*0Sstevel@tonic-gate 1167*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) 1168*0Sstevel@tonic-gate == -1) { 1169*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 1170*0Sstevel@tonic-gate strerror(errno)); 1171*0Sstevel@tonic-gate free(pload_soft_conf); 1172*0Sstevel@tonic-gate rc = FAILURE; 1173*0Sstevel@tonic-gate break; 1174*0Sstevel@tonic-gate } 1175*0Sstevel@tonic-gate 1176*0Sstevel@tonic-gate if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 1177*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl " 1178*0Sstevel@tonic-gate "return_value = %d", 1179*0Sstevel@tonic-gate pload_soft_conf->sc_return_value); 1180*0Sstevel@tonic-gate free(pload_soft_conf); 1181*0Sstevel@tonic-gate rc = FAILURE; 1182*0Sstevel@tonic-gate break; 1183*0Sstevel@tonic-gate } 1184*0Sstevel@tonic-gate 1185*0Sstevel@tonic-gate /* load the disabled list */ 1186*0Sstevel@tonic-gate if (ptr->pent->dis_count != 0) { 1187*0Sstevel@tonic-gate pload_soft_dis = setup_soft_dis(ptr->pent); 1188*0Sstevel@tonic-gate if (pload_soft_dis == NULL) { 1189*0Sstevel@tonic-gate rc = FAILURE; 1190*0Sstevel@tonic-gate break; 1191*0Sstevel@tonic-gate } 1192*0Sstevel@tonic-gate 1193*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, 1194*0Sstevel@tonic-gate pload_soft_dis) == -1) { 1195*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 1196*0Sstevel@tonic-gate "failed: %s", strerror(errno)); 1197*0Sstevel@tonic-gate free(pload_soft_dis); 1198*0Sstevel@tonic-gate rc = FAILURE; 1199*0Sstevel@tonic-gate break; 1200*0Sstevel@tonic-gate } 1201*0Sstevel@tonic-gate 1202*0Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != 1203*0Sstevel@tonic-gate CRYPTO_SUCCESS) { 1204*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl " 1205*0Sstevel@tonic-gate "return_value = %d", 1206*0Sstevel@tonic-gate pload_soft_dis->sd_return_value); 1207*0Sstevel@tonic-gate free(pload_soft_dis); 1208*0Sstevel@tonic-gate rc = FAILURE; 1209*0Sstevel@tonic-gate break; 1210*0Sstevel@tonic-gate } 1211*0Sstevel@tonic-gate free(pload_soft_dis); 1212*0Sstevel@tonic-gate } 1213*0Sstevel@tonic-gate 1214*0Sstevel@tonic-gate free(pload_soft_conf); 1215*0Sstevel@tonic-gate ptr = ptr->next; 1216*0Sstevel@tonic-gate } 1217*0Sstevel@tonic-gate 1218*0Sstevel@tonic-gate if (rc != SUCCESS) { 1219*0Sstevel@tonic-gate (void) close(fd); 1220*0Sstevel@tonic-gate return (rc); 1221*0Sstevel@tonic-gate } 1222*0Sstevel@tonic-gate 1223*0Sstevel@tonic-gate 1224*0Sstevel@tonic-gate /* Pass the disabledlist information for Device to kernel */ 1225*0Sstevel@tonic-gate ptr = pdevlist; 1226*0Sstevel@tonic-gate while (ptr != NULL) { 1227*0Sstevel@tonic-gate /* load the disabled list */ 1228*0Sstevel@tonic-gate if (ptr->pent->dis_count != 0) { 1229*0Sstevel@tonic-gate pload_dev_dis = setup_dev_dis(ptr->pent); 1230*0Sstevel@tonic-gate if (pload_dev_dis == NULL) { 1231*0Sstevel@tonic-gate rc = FAILURE; 1232*0Sstevel@tonic-gate break; 1233*0Sstevel@tonic-gate } 1234*0Sstevel@tonic-gate 1235*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) 1236*0Sstevel@tonic-gate == -1) { 1237*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 1238*0Sstevel@tonic-gate "failed: %s", strerror(errno)); 1239*0Sstevel@tonic-gate free(pload_dev_dis); 1240*0Sstevel@tonic-gate rc = FAILURE; 1241*0Sstevel@tonic-gate break; 1242*0Sstevel@tonic-gate } 1243*0Sstevel@tonic-gate 1244*0Sstevel@tonic-gate if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) { 1245*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl " 1246*0Sstevel@tonic-gate "return_value = %d", 1247*0Sstevel@tonic-gate pload_dev_dis->dd_return_value); 1248*0Sstevel@tonic-gate free(pload_dev_dis); 1249*0Sstevel@tonic-gate rc = FAILURE; 1250*0Sstevel@tonic-gate break; 1251*0Sstevel@tonic-gate } 1252*0Sstevel@tonic-gate free(pload_dev_dis); 1253*0Sstevel@tonic-gate } 1254*0Sstevel@tonic-gate 1255*0Sstevel@tonic-gate ptr = ptr->next; 1256*0Sstevel@tonic-gate } 1257*0Sstevel@tonic-gate 1258*0Sstevel@tonic-gate (void) close(fd); 1259*0Sstevel@tonic-gate return (rc); 1260*0Sstevel@tonic-gate } 1261*0Sstevel@tonic-gate 1262*0Sstevel@tonic-gate /* 1263*0Sstevel@tonic-gate * Unload the kernel software provider. Before calling this function, the 1264*0Sstevel@tonic-gate * caller should check if the provider is in the config file and if it 1265*0Sstevel@tonic-gate * is kernel. This routine makes 3 ioctl calls to remove it from kernel 1266*0Sstevel@tonic-gate * completely. 1267*0Sstevel@tonic-gate */ 1268*0Sstevel@tonic-gate int 1269*0Sstevel@tonic-gate unload_kef_soft(char *provname) 1270*0Sstevel@tonic-gate { 1271*0Sstevel@tonic-gate crypto_unload_soft_module_t *punload_soft = NULL; 1272*0Sstevel@tonic-gate crypto_load_soft_config_t *pload_soft_conf = NULL; 1273*0Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis = NULL; 1274*0Sstevel@tonic-gate entry_t *pent = NULL; 1275*0Sstevel@tonic-gate int fd; 1276*0Sstevel@tonic-gate 1277*0Sstevel@tonic-gate if (provname == NULL) { 1278*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 1279*0Sstevel@tonic-gate return (FAILURE); 1280*0Sstevel@tonic-gate } 1281*0Sstevel@tonic-gate 1282*0Sstevel@tonic-gate if ((pent = getent_kef(provname)) == NULL) { 1283*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s does not exist."), 1284*0Sstevel@tonic-gate provname); 1285*0Sstevel@tonic-gate return (FAILURE); 1286*0Sstevel@tonic-gate } 1287*0Sstevel@tonic-gate 1288*0Sstevel@tonic-gate /* Open the admin_ioctl_device */ 1289*0Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { 1290*0Sstevel@tonic-gate err = errno; 1291*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 1292*0Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(err)); 1293*0Sstevel@tonic-gate return (FAILURE); 1294*0Sstevel@tonic-gate } 1295*0Sstevel@tonic-gate 1296*0Sstevel@tonic-gate /* Inform kernel to unload this software module */ 1297*0Sstevel@tonic-gate if ((punload_soft = setup_unload_soft(pent)) == NULL) { 1298*0Sstevel@tonic-gate (void) close(fd); 1299*0Sstevel@tonic-gate return (FAILURE); 1300*0Sstevel@tonic-gate } 1301*0Sstevel@tonic-gate 1302*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_UNLOAD_SOFT_MODULE, punload_soft) == -1) { 1303*0Sstevel@tonic-gate cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl failed: %s", 1304*0Sstevel@tonic-gate strerror(errno)); 1305*0Sstevel@tonic-gate free_entry(pent); 1306*0Sstevel@tonic-gate free(punload_soft); 1307*0Sstevel@tonic-gate (void) close(fd); 1308*0Sstevel@tonic-gate return (FAILURE); 1309*0Sstevel@tonic-gate } 1310*0Sstevel@tonic-gate 1311*0Sstevel@tonic-gate if (punload_soft->sm_return_value != CRYPTO_SUCCESS) { 1312*0Sstevel@tonic-gate cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl return_value = " 1313*0Sstevel@tonic-gate "%d", punload_soft->sm_return_value); 1314*0Sstevel@tonic-gate /* 1315*0Sstevel@tonic-gate * If the return value is CRYPTO_UNKNOWN_PRIVDER, it means 1316*0Sstevel@tonic-gate * that the provider is not registered yet. Should just 1317*0Sstevel@tonic-gate * continue. 1318*0Sstevel@tonic-gate */ 1319*0Sstevel@tonic-gate if (punload_soft->sm_return_value != CRYPTO_UNKNOWN_PROVIDER) { 1320*0Sstevel@tonic-gate free_entry(pent); 1321*0Sstevel@tonic-gate free(punload_soft); 1322*0Sstevel@tonic-gate (void) close(fd); 1323*0Sstevel@tonic-gate return (FAILURE); 1324*0Sstevel@tonic-gate } 1325*0Sstevel@tonic-gate } 1326*0Sstevel@tonic-gate 1327*0Sstevel@tonic-gate free(punload_soft); 1328*0Sstevel@tonic-gate 1329*0Sstevel@tonic-gate /* 1330*0Sstevel@tonic-gate * Inform kernel to remove the configuration of this software 1331*0Sstevel@tonic-gate * module. 1332*0Sstevel@tonic-gate */ 1333*0Sstevel@tonic-gate free_mechlist(pent->suplist); 1334*0Sstevel@tonic-gate pent->suplist = NULL; 1335*0Sstevel@tonic-gate pent->sup_count = 0; 1336*0Sstevel@tonic-gate if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) { 1337*0Sstevel@tonic-gate free_entry(pent); 1338*0Sstevel@tonic-gate (void) close(fd); 1339*0Sstevel@tonic-gate return (FAILURE); 1340*0Sstevel@tonic-gate } 1341*0Sstevel@tonic-gate 1342*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) { 1343*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s", 1344*0Sstevel@tonic-gate strerror(errno)); 1345*0Sstevel@tonic-gate free_entry(pent); 1346*0Sstevel@tonic-gate free(pload_soft_conf); 1347*0Sstevel@tonic-gate (void) close(fd); 1348*0Sstevel@tonic-gate return (FAILURE); 1349*0Sstevel@tonic-gate } 1350*0Sstevel@tonic-gate 1351*0Sstevel@tonic-gate if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) { 1352*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl return_value = " 1353*0Sstevel@tonic-gate "%d", pload_soft_conf->sc_return_value); 1354*0Sstevel@tonic-gate free_entry(pent); 1355*0Sstevel@tonic-gate free(pload_soft_conf); 1356*0Sstevel@tonic-gate (void) close(fd); 1357*0Sstevel@tonic-gate return (FAILURE); 1358*0Sstevel@tonic-gate } 1359*0Sstevel@tonic-gate 1360*0Sstevel@tonic-gate free(pload_soft_conf); 1361*0Sstevel@tonic-gate 1362*0Sstevel@tonic-gate /* Inform kernel to remove the disabled entries if any */ 1363*0Sstevel@tonic-gate if (pent->dis_count == 0) { 1364*0Sstevel@tonic-gate free_entry(pent); 1365*0Sstevel@tonic-gate (void) close(fd); 1366*0Sstevel@tonic-gate return (SUCCESS); 1367*0Sstevel@tonic-gate } else { 1368*0Sstevel@tonic-gate free_mechlist(pent->dislist); 1369*0Sstevel@tonic-gate pent->dislist = NULL; 1370*0Sstevel@tonic-gate pent->dis_count = 0; 1371*0Sstevel@tonic-gate } 1372*0Sstevel@tonic-gate 1373*0Sstevel@tonic-gate if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { 1374*0Sstevel@tonic-gate free_entry(pent); 1375*0Sstevel@tonic-gate (void) close(fd); 1376*0Sstevel@tonic-gate return (FAILURE); 1377*0Sstevel@tonic-gate } 1378*0Sstevel@tonic-gate 1379*0Sstevel@tonic-gate /* pent is no longer needed; free it */ 1380*0Sstevel@tonic-gate free_entry(pent); 1381*0Sstevel@tonic-gate 1382*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) { 1383*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s", 1384*0Sstevel@tonic-gate strerror(errno)); 1385*0Sstevel@tonic-gate free(pload_soft_dis); 1386*0Sstevel@tonic-gate (void) close(fd); 1387*0Sstevel@tonic-gate return (FAILURE); 1388*0Sstevel@tonic-gate } 1389*0Sstevel@tonic-gate 1390*0Sstevel@tonic-gate if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { 1391*0Sstevel@tonic-gate cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = " 1392*0Sstevel@tonic-gate "%d", pload_soft_dis->sd_return_value); 1393*0Sstevel@tonic-gate free(pload_soft_dis); 1394*0Sstevel@tonic-gate (void) close(fd); 1395*0Sstevel@tonic-gate return (FAILURE); 1396*0Sstevel@tonic-gate } 1397*0Sstevel@tonic-gate 1398*0Sstevel@tonic-gate free(pload_soft_dis); 1399*0Sstevel@tonic-gate (void) close(fd); 1400*0Sstevel@tonic-gate return (SUCCESS); 1401*0Sstevel@tonic-gate } 1402*0Sstevel@tonic-gate 1403*0Sstevel@tonic-gate 1404*0Sstevel@tonic-gate /* 1405*0Sstevel@tonic-gate * Check if a hardware provider is valid. If it is valid, returns its device 1406*0Sstevel@tonic-gate * name, instance number and the number of mechanisms it supports. 1407*0Sstevel@tonic-gate */ 1408*0Sstevel@tonic-gate static int 1409*0Sstevel@tonic-gate check_hardware_provider(char *provname, char *pname, int *pnum, int *pcount) 1410*0Sstevel@tonic-gate { 1411*0Sstevel@tonic-gate crypto_get_dev_list_t *dev_list = NULL; 1412*0Sstevel@tonic-gate int i; 1413*0Sstevel@tonic-gate 1414*0Sstevel@tonic-gate if (provname == NULL) { 1415*0Sstevel@tonic-gate return (FAILURE); 1416*0Sstevel@tonic-gate } 1417*0Sstevel@tonic-gate 1418*0Sstevel@tonic-gate /* First, get the device name and the instance number from provname */ 1419*0Sstevel@tonic-gate if (split_hw_provname(provname, pname, pnum) == FAILURE) { 1420*0Sstevel@tonic-gate return (FAILURE); 1421*0Sstevel@tonic-gate } 1422*0Sstevel@tonic-gate 1423*0Sstevel@tonic-gate /* 1424*0Sstevel@tonic-gate * Get the complete device list from kernel and check if this provider 1425*0Sstevel@tonic-gate * is in the list. 1426*0Sstevel@tonic-gate */ 1427*0Sstevel@tonic-gate if (get_dev_list(&dev_list) == FAILURE) { 1428*0Sstevel@tonic-gate return (FAILURE); 1429*0Sstevel@tonic-gate } 1430*0Sstevel@tonic-gate 1431*0Sstevel@tonic-gate for (i = 0; i < dev_list->dl_dev_count; i++) { 1432*0Sstevel@tonic-gate if ((strcmp(dev_list->dl_devs[i].le_dev_name, pname) == 0) && 1433*0Sstevel@tonic-gate (dev_list->dl_devs[i].le_dev_instance == *pnum)) { 1434*0Sstevel@tonic-gate break; 1435*0Sstevel@tonic-gate } 1436*0Sstevel@tonic-gate } 1437*0Sstevel@tonic-gate 1438*0Sstevel@tonic-gate if (i == dev_list->dl_dev_count) { 1439*0Sstevel@tonic-gate /* didn't find this provider in the kernel device list */ 1440*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s does not exist."), 1441*0Sstevel@tonic-gate provname); 1442*0Sstevel@tonic-gate free(dev_list); 1443*0Sstevel@tonic-gate return (FAILURE); 1444*0Sstevel@tonic-gate } 1445*0Sstevel@tonic-gate 1446*0Sstevel@tonic-gate /* This provider is valid. Get its mechanism count */ 1447*0Sstevel@tonic-gate *pcount = dev_list->dl_devs[i].le_mechanism_count; 1448*0Sstevel@tonic-gate 1449*0Sstevel@tonic-gate free(dev_list); 1450*0Sstevel@tonic-gate return (SUCCESS); 1451*0Sstevel@tonic-gate } 1452