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 2004 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 <zone.h> 38*0Sstevel@tonic-gate #include <sys/crypto/ioctladmin.h> 39*0Sstevel@tonic-gate #include "cryptoadm.h" 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate #define DEFAULT_DEV_NUM 5 42*0Sstevel@tonic-gate #define DEFAULT_SOFT_NUM 10 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate static crypto_get_soft_info_t *setup_get_soft_info(char *, int); 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate /* 47*0Sstevel@tonic-gate * Prepare the argument for the LOAD_SOFT_CONFIG ioctl call for the 48*0Sstevel@tonic-gate * provider pointed by pent. Return NULL if out of memory. 49*0Sstevel@tonic-gate */ 50*0Sstevel@tonic-gate crypto_load_soft_config_t * 51*0Sstevel@tonic-gate setup_soft_conf(entry_t *pent) 52*0Sstevel@tonic-gate { 53*0Sstevel@tonic-gate crypto_load_soft_config_t *pload_soft_conf; 54*0Sstevel@tonic-gate mechlist_t *plist; 55*0Sstevel@tonic-gate uint_t sup_count; 56*0Sstevel@tonic-gate size_t extra_mech_size = 0; 57*0Sstevel@tonic-gate int i; 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate if (pent == NULL) { 60*0Sstevel@tonic-gate return (NULL); 61*0Sstevel@tonic-gate } 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate sup_count = pent->sup_count; 64*0Sstevel@tonic-gate if (sup_count > 1) { 65*0Sstevel@tonic-gate extra_mech_size = sizeof (crypto_mech_name_t) * 66*0Sstevel@tonic-gate (sup_count - 1); 67*0Sstevel@tonic-gate } 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate pload_soft_conf = malloc(sizeof (crypto_load_soft_config_t) + 70*0Sstevel@tonic-gate extra_mech_size); 71*0Sstevel@tonic-gate if (pload_soft_conf == NULL) { 72*0Sstevel@tonic-gate cryptodebug("out of memory."); 73*0Sstevel@tonic-gate return (NULL); 74*0Sstevel@tonic-gate } 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate (void) strlcpy(pload_soft_conf->sc_name, pent->name, MAXNAMELEN); 77*0Sstevel@tonic-gate pload_soft_conf->sc_count = sup_count; 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate i = 0; 80*0Sstevel@tonic-gate plist = pent->suplist; 81*0Sstevel@tonic-gate while (i < sup_count) { 82*0Sstevel@tonic-gate (void) strlcpy(pload_soft_conf->sc_list[i++], 83*0Sstevel@tonic-gate plist->name, CRYPTO_MAX_MECH_NAME); 84*0Sstevel@tonic-gate plist = plist->next; 85*0Sstevel@tonic-gate } 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate return (pload_soft_conf); 88*0Sstevel@tonic-gate } 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate /* 92*0Sstevel@tonic-gate * Prepare the argument for the LOAD_SOFT_DISABLED ioctl call for the 93*0Sstevel@tonic-gate * provider pointed by pent. Return NULL if out of memory. 94*0Sstevel@tonic-gate */ 95*0Sstevel@tonic-gate crypto_load_soft_disabled_t * 96*0Sstevel@tonic-gate setup_soft_dis(entry_t *pent) 97*0Sstevel@tonic-gate { 98*0Sstevel@tonic-gate crypto_load_soft_disabled_t *pload_soft_dis; 99*0Sstevel@tonic-gate mechlist_t *plist; 100*0Sstevel@tonic-gate size_t extra_mech_size = 0; 101*0Sstevel@tonic-gate uint_t dis_count; 102*0Sstevel@tonic-gate int i; 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate if (pent == NULL) { 105*0Sstevel@tonic-gate return (NULL); 106*0Sstevel@tonic-gate } 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate dis_count = pent->dis_count; 109*0Sstevel@tonic-gate if (dis_count > 1) { 110*0Sstevel@tonic-gate extra_mech_size = sizeof (crypto_mech_name_t) * 111*0Sstevel@tonic-gate (dis_count - 1); 112*0Sstevel@tonic-gate } 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate pload_soft_dis = malloc(sizeof (crypto_load_soft_disabled_t) + 115*0Sstevel@tonic-gate extra_mech_size); 116*0Sstevel@tonic-gate if (pload_soft_dis == NULL) { 117*0Sstevel@tonic-gate cryptodebug("out of memory."); 118*0Sstevel@tonic-gate return (NULL); 119*0Sstevel@tonic-gate } 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate (void) strlcpy(pload_soft_dis->sd_name, pent->name, MAXNAMELEN); 122*0Sstevel@tonic-gate pload_soft_dis->sd_count = dis_count; 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate i = 0; 125*0Sstevel@tonic-gate plist = pent->dislist; 126*0Sstevel@tonic-gate while (i < dis_count) { 127*0Sstevel@tonic-gate (void) strlcpy(pload_soft_dis->sd_list[i++], 128*0Sstevel@tonic-gate plist->name, CRYPTO_MAX_MECH_NAME); 129*0Sstevel@tonic-gate plist = plist->next; 130*0Sstevel@tonic-gate } 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate return (pload_soft_dis); 133*0Sstevel@tonic-gate } 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate /* 137*0Sstevel@tonic-gate * Prepare the argument for the LOAD_DEV_DISABLED ioctl call for the 138*0Sstevel@tonic-gate * provider pointed by pent. Return NULL if out of memory. 139*0Sstevel@tonic-gate */ 140*0Sstevel@tonic-gate crypto_load_dev_disabled_t * 141*0Sstevel@tonic-gate setup_dev_dis(entry_t *pent) 142*0Sstevel@tonic-gate { 143*0Sstevel@tonic-gate crypto_load_dev_disabled_t *pload_dev_dis; 144*0Sstevel@tonic-gate mechlist_t *plist; 145*0Sstevel@tonic-gate size_t extra_mech_size = 0; 146*0Sstevel@tonic-gate uint_t dis_count; 147*0Sstevel@tonic-gate int i; 148*0Sstevel@tonic-gate char pname[MAXNAMELEN]; 149*0Sstevel@tonic-gate int inst_num; 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate if (pent == NULL) { 152*0Sstevel@tonic-gate return (NULL); 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate /* get the device name and the instance number */ 156*0Sstevel@tonic-gate if (split_hw_provname(pent->name, pname, &inst_num) == FAILURE) { 157*0Sstevel@tonic-gate return (NULL); 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* allocate space for pload_dev_des */ 161*0Sstevel@tonic-gate dis_count = pent->dis_count; 162*0Sstevel@tonic-gate if (dis_count > 1) { 163*0Sstevel@tonic-gate extra_mech_size = sizeof (crypto_mech_name_t) * 164*0Sstevel@tonic-gate (dis_count - 1); 165*0Sstevel@tonic-gate } 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate pload_dev_dis = malloc(sizeof (crypto_load_dev_disabled_t) + 168*0Sstevel@tonic-gate extra_mech_size); 169*0Sstevel@tonic-gate if (pload_dev_dis == NULL) { 170*0Sstevel@tonic-gate cryptodebug("out of memory."); 171*0Sstevel@tonic-gate return (NULL); 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate /* set the values for pload_dev_dis */ 175*0Sstevel@tonic-gate (void) strlcpy(pload_dev_dis->dd_dev_name, pname, MAXNAMELEN); 176*0Sstevel@tonic-gate pload_dev_dis->dd_dev_instance = inst_num; 177*0Sstevel@tonic-gate pload_dev_dis->dd_count = dis_count; 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate i = 0; 180*0Sstevel@tonic-gate plist = pent->dislist; 181*0Sstevel@tonic-gate while (i < dis_count) { 182*0Sstevel@tonic-gate (void) strlcpy(pload_dev_dis->dd_list[i++], 183*0Sstevel@tonic-gate plist->name, CRYPTO_MAX_MECH_NAME); 184*0Sstevel@tonic-gate plist = plist->next; 185*0Sstevel@tonic-gate } 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate return (pload_dev_dis); 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate /* 192*0Sstevel@tonic-gate * Prepare the calling argument of the UNLOAD_SOFT_MODULE ioctl call for the 193*0Sstevel@tonic-gate * provider pointed by pent. Return NULL if out of memory. 194*0Sstevel@tonic-gate */ 195*0Sstevel@tonic-gate crypto_unload_soft_module_t * 196*0Sstevel@tonic-gate setup_unload_soft(entry_t *pent) 197*0Sstevel@tonic-gate { 198*0Sstevel@tonic-gate crypto_unload_soft_module_t *punload_soft; 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate if (pent == NULL) { 201*0Sstevel@tonic-gate return (NULL); 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate punload_soft = malloc(sizeof (crypto_unload_soft_module_t)); 205*0Sstevel@tonic-gate if (punload_soft == NULL) { 206*0Sstevel@tonic-gate cryptodebug("out of memory."); 207*0Sstevel@tonic-gate return (NULL); 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate (void) strlcpy(punload_soft->sm_name, pent->name, MAXNAMELEN); 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate return (punload_soft); 213*0Sstevel@tonic-gate } 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate /* 217*0Sstevel@tonic-gate * Prepare the calling argument for the GET_SOFT_INFO call for the provider 218*0Sstevel@tonic-gate * with the number of mechanisms specified in the second argument. 219*0Sstevel@tonic-gate */ 220*0Sstevel@tonic-gate static crypto_get_soft_info_t * 221*0Sstevel@tonic-gate setup_get_soft_info(char *provname, int count) 222*0Sstevel@tonic-gate { 223*0Sstevel@tonic-gate crypto_get_soft_info_t *psoft_info; 224*0Sstevel@tonic-gate size_t extra_mech_size = 0; 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate if (provname == NULL) { 227*0Sstevel@tonic-gate return (NULL); 228*0Sstevel@tonic-gate } 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate if (count > 1) { 231*0Sstevel@tonic-gate extra_mech_size = sizeof (crypto_mech_name_t) * (count - 1); 232*0Sstevel@tonic-gate } 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate psoft_info = malloc(sizeof (crypto_get_soft_info_t) + extra_mech_size); 235*0Sstevel@tonic-gate if (psoft_info == NULL) { 236*0Sstevel@tonic-gate cryptodebug("out of memory."); 237*0Sstevel@tonic-gate return (NULL); 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate (void) strlcpy(psoft_info->si_name, provname, MAXNAMELEN); 241*0Sstevel@tonic-gate psoft_info->si_count = count; 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate return (psoft_info); 244*0Sstevel@tonic-gate } 245*0Sstevel@tonic-gate 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate /* 248*0Sstevel@tonic-gate * Get the device list from kernel. 249*0Sstevel@tonic-gate */ 250*0Sstevel@tonic-gate int 251*0Sstevel@tonic-gate get_dev_list(crypto_get_dev_list_t **ppdevlist) 252*0Sstevel@tonic-gate { 253*0Sstevel@tonic-gate crypto_get_dev_list_t *pdevlist; 254*0Sstevel@tonic-gate int fd; 255*0Sstevel@tonic-gate int count = DEFAULT_DEV_NUM; 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate pdevlist = malloc(sizeof (crypto_get_dev_list_t) + 258*0Sstevel@tonic-gate sizeof (crypto_dev_list_entry_t) * (count - 1)); 259*0Sstevel@tonic-gate if (pdevlist == NULL) { 260*0Sstevel@tonic-gate cryptodebug("out of memory."); 261*0Sstevel@tonic-gate return (FAILURE); 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) { 265*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 266*0Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 267*0Sstevel@tonic-gate return (FAILURE); 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate pdevlist->dl_dev_count = count; 271*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_GET_DEV_LIST, pdevlist) == -1) { 272*0Sstevel@tonic-gate cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s", 273*0Sstevel@tonic-gate strerror(errno)); 274*0Sstevel@tonic-gate free(pdevlist); 275*0Sstevel@tonic-gate (void) close(fd); 276*0Sstevel@tonic-gate return (FAILURE); 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate /* BUFFER is too small, get the number of devices and retry it. */ 280*0Sstevel@tonic-gate if (pdevlist->dl_return_value == CRYPTO_BUFFER_TOO_SMALL) { 281*0Sstevel@tonic-gate count = pdevlist->dl_dev_count; 282*0Sstevel@tonic-gate free(pdevlist); 283*0Sstevel@tonic-gate pdevlist = malloc(sizeof (crypto_get_dev_list_t) + 284*0Sstevel@tonic-gate sizeof (crypto_dev_list_entry_t) * (count - 1)); 285*0Sstevel@tonic-gate if (pdevlist == NULL) { 286*0Sstevel@tonic-gate cryptodebug("out of memory."); 287*0Sstevel@tonic-gate (void) close(fd); 288*0Sstevel@tonic-gate return (FAILURE); 289*0Sstevel@tonic-gate } 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_GET_DEV_LIST, pdevlist) == -1) { 292*0Sstevel@tonic-gate cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s", 293*0Sstevel@tonic-gate strerror(errno)); 294*0Sstevel@tonic-gate free(pdevlist); 295*0Sstevel@tonic-gate (void) close(fd); 296*0Sstevel@tonic-gate return (FAILURE); 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate } 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate if (pdevlist->dl_return_value != CRYPTO_SUCCESS) { 301*0Sstevel@tonic-gate cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed, " 302*0Sstevel@tonic-gate "return_value = %d", pdevlist->dl_return_value); 303*0Sstevel@tonic-gate free(pdevlist); 304*0Sstevel@tonic-gate (void) close(fd); 305*0Sstevel@tonic-gate return (FAILURE); 306*0Sstevel@tonic-gate } 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate *ppdevlist = pdevlist; 309*0Sstevel@tonic-gate (void) close(fd); 310*0Sstevel@tonic-gate return (SUCCESS); 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate /* 315*0Sstevel@tonic-gate * Get all the mechanisms supported by the hardware provider. 316*0Sstevel@tonic-gate * The result will be stored in the second argument. 317*0Sstevel@tonic-gate */ 318*0Sstevel@tonic-gate int 319*0Sstevel@tonic-gate get_dev_info(char *devname, int inst_num, int count, mechlist_t **ppmechlist) 320*0Sstevel@tonic-gate { 321*0Sstevel@tonic-gate crypto_get_dev_info_t *dev_info; 322*0Sstevel@tonic-gate mechlist_t *phead; 323*0Sstevel@tonic-gate mechlist_t *pcur; 324*0Sstevel@tonic-gate mechlist_t *pmech; 325*0Sstevel@tonic-gate int fd; 326*0Sstevel@tonic-gate int i; 327*0Sstevel@tonic-gate int rc; 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate if (devname == NULL || count < 1) { 330*0Sstevel@tonic-gate cryptodebug("get_dev_info(): devname is NULL or bogus count"); 331*0Sstevel@tonic-gate return (FAILURE); 332*0Sstevel@tonic-gate } 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate /* Set up the argument for the CRYPTO_GET_DEV_INFO ioctl call */ 335*0Sstevel@tonic-gate dev_info = malloc(sizeof (crypto_get_dev_info_t) + 336*0Sstevel@tonic-gate sizeof (crypto_mech_name_t) * (count - 1)); 337*0Sstevel@tonic-gate if (dev_info == NULL) { 338*0Sstevel@tonic-gate cryptodebug("out of memory."); 339*0Sstevel@tonic-gate return (FAILURE); 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate (void) strlcpy(dev_info->di_dev_name, devname, MAXNAMELEN); 342*0Sstevel@tonic-gate dev_info->di_dev_instance = inst_num; 343*0Sstevel@tonic-gate dev_info->di_count = count; 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate /* Open the ioctl device */ 346*0Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) { 347*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 348*0Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 349*0Sstevel@tonic-gate free(dev_info); 350*0Sstevel@tonic-gate return (FAILURE); 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_GET_DEV_INFO, dev_info) == -1) { 354*0Sstevel@tonic-gate cryptodebug("CRYPTO_GET_DEV_INFO ioctl failed: %s", 355*0Sstevel@tonic-gate strerror(errno)); 356*0Sstevel@tonic-gate free(dev_info); 357*0Sstevel@tonic-gate (void) close(fd); 358*0Sstevel@tonic-gate return (FAILURE); 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate if (dev_info->di_return_value != CRYPTO_SUCCESS) { 362*0Sstevel@tonic-gate cryptodebug("CRYPTO_GET_DEV_INFO ioctl failed, " 363*0Sstevel@tonic-gate "return_value = %d", dev_info->di_return_value); 364*0Sstevel@tonic-gate free(dev_info); 365*0Sstevel@tonic-gate (void) close(fd); 366*0Sstevel@tonic-gate return (FAILURE); 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate phead = pcur = NULL; 370*0Sstevel@tonic-gate rc = SUCCESS; 371*0Sstevel@tonic-gate for (i = 0; i < dev_info->di_count; i++) { 372*0Sstevel@tonic-gate pmech = create_mech(&dev_info->di_list[i][0]); 373*0Sstevel@tonic-gate if (pmech == NULL) { 374*0Sstevel@tonic-gate rc = FAILURE; 375*0Sstevel@tonic-gate break; 376*0Sstevel@tonic-gate } else { 377*0Sstevel@tonic-gate if (phead == NULL) { 378*0Sstevel@tonic-gate phead = pcur = pmech; 379*0Sstevel@tonic-gate } else { 380*0Sstevel@tonic-gate pcur->next = pmech; 381*0Sstevel@tonic-gate pcur = pmech; 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate } 384*0Sstevel@tonic-gate } 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gate if (rc == SUCCESS) { 387*0Sstevel@tonic-gate *ppmechlist = phead; 388*0Sstevel@tonic-gate } else { 389*0Sstevel@tonic-gate free_mechlist(phead); 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate free(dev_info); 393*0Sstevel@tonic-gate (void) close(fd); 394*0Sstevel@tonic-gate return (rc); 395*0Sstevel@tonic-gate } 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate /* 400*0Sstevel@tonic-gate * Get the supported mechanism list of the software provider from kernel. 401*0Sstevel@tonic-gate */ 402*0Sstevel@tonic-gate int 403*0Sstevel@tonic-gate get_soft_info(char *provname, mechlist_t **ppmechlist) 404*0Sstevel@tonic-gate { 405*0Sstevel@tonic-gate crypto_get_soft_info_t *psoft_info; 406*0Sstevel@tonic-gate mechlist_t *phead; 407*0Sstevel@tonic-gate mechlist_t *pmech; 408*0Sstevel@tonic-gate mechlist_t *pcur; 409*0Sstevel@tonic-gate entry_t *pent; 410*0Sstevel@tonic-gate int count; 411*0Sstevel@tonic-gate int fd; 412*0Sstevel@tonic-gate int rc; 413*0Sstevel@tonic-gate int i; 414*0Sstevel@tonic-gate 415*0Sstevel@tonic-gate if (provname == NULL) { 416*0Sstevel@tonic-gate return (FAILURE); 417*0Sstevel@tonic-gate } 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate if (getzoneid() == GLOBAL_ZONEID) { 420*0Sstevel@tonic-gate /* use kcf.conf for kernel software providers in global zone */ 421*0Sstevel@tonic-gate if ((pent = getent_kef(provname)) == NULL) { 422*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s does not exist."), 423*0Sstevel@tonic-gate provname); 424*0Sstevel@tonic-gate return (FAILURE); 425*0Sstevel@tonic-gate } 426*0Sstevel@tonic-gate count = pent->sup_count; 427*0Sstevel@tonic-gate free_entry(pent); 428*0Sstevel@tonic-gate } else { 429*0Sstevel@tonic-gate /* 430*0Sstevel@tonic-gate * kcf.conf not there in non-global zone, set mech count to 1; 431*0Sstevel@tonic-gate * it will be reset to the correct value later if the setup 432*0Sstevel@tonic-gate * buffer is too small 433*0Sstevel@tonic-gate */ 434*0Sstevel@tonic-gate count = 1; 435*0Sstevel@tonic-gate } 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate if ((psoft_info = setup_get_soft_info(provname, count)) == NULL) { 438*0Sstevel@tonic-gate return (FAILURE); 439*0Sstevel@tonic-gate } 440*0Sstevel@tonic-gate 441*0Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) { 442*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 443*0Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 444*0Sstevel@tonic-gate free(psoft_info); 445*0Sstevel@tonic-gate return (FAILURE); 446*0Sstevel@tonic-gate } 447*0Sstevel@tonic-gate 448*0Sstevel@tonic-gate /* make GET_SOFT_INFO ioctl call */ 449*0Sstevel@tonic-gate if ((rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info)) == -1) { 450*0Sstevel@tonic-gate cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed: %s", 451*0Sstevel@tonic-gate strerror(errno)); 452*0Sstevel@tonic-gate (void) close(fd); 453*0Sstevel@tonic-gate free(psoft_info); 454*0Sstevel@tonic-gate return (FAILURE); 455*0Sstevel@tonic-gate } 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gate /* BUFFER is too small, get the number of mechanisms and retry it. */ 458*0Sstevel@tonic-gate if (psoft_info->si_return_value == CRYPTO_BUFFER_TOO_SMALL) { 459*0Sstevel@tonic-gate count = psoft_info->si_count; 460*0Sstevel@tonic-gate free(psoft_info); 461*0Sstevel@tonic-gate if ((psoft_info = setup_get_soft_info(provname, count)) 462*0Sstevel@tonic-gate == NULL) { 463*0Sstevel@tonic-gate (void) close(fd); 464*0Sstevel@tonic-gate return (FAILURE); 465*0Sstevel@tonic-gate } else { 466*0Sstevel@tonic-gate rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info); 467*0Sstevel@tonic-gate if (rc == -1) { 468*0Sstevel@tonic-gate cryptodebug("CRYPTO_GET_SOFT_INFO ioctl " 469*0Sstevel@tonic-gate "failed: %s", strerror(errno)); 470*0Sstevel@tonic-gate (void) close(fd); 471*0Sstevel@tonic-gate free(psoft_info); 472*0Sstevel@tonic-gate return (FAILURE); 473*0Sstevel@tonic-gate } 474*0Sstevel@tonic-gate } 475*0Sstevel@tonic-gate } 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate (void) close(fd); 478*0Sstevel@tonic-gate if (psoft_info->si_return_value != CRYPTO_SUCCESS) { 479*0Sstevel@tonic-gate cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed, " 480*0Sstevel@tonic-gate "return_value = %d", psoft_info->si_return_value); 481*0Sstevel@tonic-gate free(psoft_info); 482*0Sstevel@tonic-gate return (FAILURE); 483*0Sstevel@tonic-gate } 484*0Sstevel@tonic-gate 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate /* Get the mechanism list and return it */ 487*0Sstevel@tonic-gate rc = SUCCESS; 488*0Sstevel@tonic-gate phead = pcur = NULL; 489*0Sstevel@tonic-gate for (i = 0; i < psoft_info->si_count; i++) { 490*0Sstevel@tonic-gate pmech = create_mech(&psoft_info->si_list[i][0]); 491*0Sstevel@tonic-gate if (pmech == NULL) { 492*0Sstevel@tonic-gate rc = FAILURE; 493*0Sstevel@tonic-gate break; 494*0Sstevel@tonic-gate } else { 495*0Sstevel@tonic-gate if (phead == NULL) { 496*0Sstevel@tonic-gate phead = pcur = pmech; 497*0Sstevel@tonic-gate } else { 498*0Sstevel@tonic-gate pcur->next = pmech; 499*0Sstevel@tonic-gate pcur = pmech; 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate } 502*0Sstevel@tonic-gate } 503*0Sstevel@tonic-gate 504*0Sstevel@tonic-gate if (rc == FAILURE) { 505*0Sstevel@tonic-gate free_mechlist(phead); 506*0Sstevel@tonic-gate } else { 507*0Sstevel@tonic-gate *ppmechlist = phead; 508*0Sstevel@tonic-gate } 509*0Sstevel@tonic-gate 510*0Sstevel@tonic-gate free(psoft_info); 511*0Sstevel@tonic-gate return (rc); 512*0Sstevel@tonic-gate } 513*0Sstevel@tonic-gate 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate /* 516*0Sstevel@tonic-gate * Get the kernel software provider list from kernel. 517*0Sstevel@tonic-gate */ 518*0Sstevel@tonic-gate int 519*0Sstevel@tonic-gate get_soft_list(crypto_get_soft_list_t **ppsoftlist) 520*0Sstevel@tonic-gate { 521*0Sstevel@tonic-gate crypto_get_soft_list_t *psoftlist = NULL; 522*0Sstevel@tonic-gate int count = DEFAULT_SOFT_NUM; 523*0Sstevel@tonic-gate int len; 524*0Sstevel@tonic-gate int fd; 525*0Sstevel@tonic-gate 526*0Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) { 527*0Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 528*0Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 529*0Sstevel@tonic-gate return (FAILURE); 530*0Sstevel@tonic-gate } 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gate len = MAXNAMELEN * count; 533*0Sstevel@tonic-gate psoftlist = malloc(sizeof (crypto_get_soft_list_t) + len); 534*0Sstevel@tonic-gate if (psoftlist == NULL) { 535*0Sstevel@tonic-gate cryptodebug("out of memory."); 536*0Sstevel@tonic-gate (void) close(fd); 537*0Sstevel@tonic-gate return (FAILURE); 538*0Sstevel@tonic-gate } 539*0Sstevel@tonic-gate psoftlist->sl_soft_names = (caddr_t)(psoftlist + 1); 540*0Sstevel@tonic-gate psoftlist->sl_soft_count = count; 541*0Sstevel@tonic-gate psoftlist->sl_soft_len = len; 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_GET_SOFT_LIST, psoftlist) == -1) { 544*0Sstevel@tonic-gate cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed: %s", 545*0Sstevel@tonic-gate strerror(errno)); 546*0Sstevel@tonic-gate free(psoftlist); 547*0Sstevel@tonic-gate (void) close(fd); 548*0Sstevel@tonic-gate return (FAILURE); 549*0Sstevel@tonic-gate } 550*0Sstevel@tonic-gate 551*0Sstevel@tonic-gate /* 552*0Sstevel@tonic-gate * if BUFFER is too small, get the number of software providers and 553*0Sstevel@tonic-gate * the minimum length needed for names and length and retry it. 554*0Sstevel@tonic-gate */ 555*0Sstevel@tonic-gate if (psoftlist->sl_return_value == CRYPTO_BUFFER_TOO_SMALL) { 556*0Sstevel@tonic-gate count = psoftlist->sl_soft_count; 557*0Sstevel@tonic-gate len = psoftlist->sl_soft_len; 558*0Sstevel@tonic-gate free(psoftlist); 559*0Sstevel@tonic-gate psoftlist = malloc(sizeof (crypto_get_soft_list_t) + len); 560*0Sstevel@tonic-gate if (psoftlist == NULL) { 561*0Sstevel@tonic-gate cryptodebug("out of memory."); 562*0Sstevel@tonic-gate (void) close(fd); 563*0Sstevel@tonic-gate return (FAILURE); 564*0Sstevel@tonic-gate } 565*0Sstevel@tonic-gate psoftlist->sl_soft_names = (caddr_t)(psoftlist + 1); 566*0Sstevel@tonic-gate psoftlist->sl_soft_count = count; 567*0Sstevel@tonic-gate psoftlist->sl_soft_len = len; 568*0Sstevel@tonic-gate 569*0Sstevel@tonic-gate if (ioctl(fd, CRYPTO_GET_SOFT_LIST, psoftlist) == -1) { 570*0Sstevel@tonic-gate cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed:" 571*0Sstevel@tonic-gate "%s", strerror(errno)); 572*0Sstevel@tonic-gate free(psoftlist); 573*0Sstevel@tonic-gate (void) close(fd); 574*0Sstevel@tonic-gate return (FAILURE); 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate } 577*0Sstevel@tonic-gate 578*0Sstevel@tonic-gate if (psoftlist->sl_return_value != CRYPTO_SUCCESS) { 579*0Sstevel@tonic-gate cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed, " 580*0Sstevel@tonic-gate "return_value = %d", psoftlist->sl_return_value); 581*0Sstevel@tonic-gate free(psoftlist); 582*0Sstevel@tonic-gate (void) close(fd); 583*0Sstevel@tonic-gate return (FAILURE); 584*0Sstevel@tonic-gate } 585*0Sstevel@tonic-gate 586*0Sstevel@tonic-gate *ppsoftlist = psoftlist; 587*0Sstevel@tonic-gate (void) close(fd); 588*0Sstevel@tonic-gate return (SUCCESS); 589*0Sstevel@tonic-gate } 590