Print this page
6414175 kcf.conf's supportedlist not providing much usefulness
   1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 #include <fcntl.h>
  30 #include <stdio.h>
  31 #include <stdlib.h>
  32 #include <strings.h>
  33 #include <unistd.h>
  34 #include <locale.h>
  35 #include <libgen.h>
  36 #include <sys/types.h>
  37 #include <zone.h>
  38 #include <sys/crypto/ioctladmin.h>
  39 #include "cryptoadm.h"
  40 
  41 #define DEFAULT_DEV_NUM 5
  42 #define DEFAULT_SOFT_NUM 10
  43 
  44 static crypto_get_soft_info_t *setup_get_soft_info(char *, int);
  45 
  46 /*
  47  * Prepare the argument for the LOAD_SOFT_CONFIG ioctl call for the
  48  * provider pointed by pent.  Return NULL if out of memory.


  78 
  79         i = 0;
  80         plist =  pent->suplist;
  81         while (i < sup_count) {
  82                 (void) strlcpy(pload_soft_conf->sc_list[i++],
  83                     plist->name, CRYPTO_MAX_MECH_NAME);
  84                 plist = plist->next;
  85         }
  86 
  87         return (pload_soft_conf);
  88 }
  89 
  90 
  91 /*
  92  * Prepare the argument for the LOAD_SOFT_DISABLED ioctl call for the
  93  * provider pointed by pent.  Return NULL if out of memory.
  94  */
  95 crypto_load_soft_disabled_t *
  96 setup_soft_dis(entry_t *pent)
  97 {
  98         crypto_load_soft_disabled_t     *pload_soft_dis;
  99         mechlist_t      *plist;
 100         size_t  extra_mech_size = 0;
 101         uint_t  dis_count;
 102         int     i;
 103 
 104         if (pent == NULL) {
 105                 return (NULL);
 106         }
 107 
 108         dis_count = pent->dis_count;
 109         if (dis_count > 1) {
 110                 extra_mech_size = sizeof (crypto_mech_name_t) *
 111                     (dis_count - 1);
 112         }
 113 
 114         pload_soft_dis = malloc(sizeof (crypto_load_soft_disabled_t) +
 115             extra_mech_size);
 116         if (pload_soft_dis == NULL) {
 117                 cryptodebug("out of memory.");
 118                 return (NULL);
 119         }


 123 
 124         i = 0;
 125         plist =  pent->dislist;
 126         while (i < dis_count) {
 127                 (void) strlcpy(pload_soft_dis->sd_list[i++],
 128                     plist->name, CRYPTO_MAX_MECH_NAME);
 129                 plist = plist->next;
 130         }
 131 
 132         return (pload_soft_dis);
 133 }
 134 
 135 
 136 /*
 137  * Prepare the argument for the LOAD_DEV_DISABLED ioctl call for the
 138  * provider pointed by pent.  Return NULL if out of memory.
 139  */
 140 crypto_load_dev_disabled_t *
 141 setup_dev_dis(entry_t *pent)
 142 {
 143         crypto_load_dev_disabled_t      *pload_dev_dis;
 144         mechlist_t      *plist;
 145         size_t  extra_mech_size = 0;
 146         uint_t  dis_count;
 147         int     i;
 148         char    pname[MAXNAMELEN];
 149         int     inst_num;
 150 
 151         if (pent == NULL) {
 152                 return (NULL);
 153         }
 154 
 155         /* get the device name and the instance number */
 156         if (split_hw_provname(pent->name, pname, &inst_num) == FAILURE) {
 157                 return (NULL);
 158         }
 159 
 160         /* allocate space for pload_dev_des */
 161         dis_count = pent->dis_count;
 162         if (dis_count > 1) {
 163                 extra_mech_size = sizeof (crypto_mech_name_t) *
 164                     (dis_count - 1);


 199 
 200         if (pent == NULL) {
 201                 return (NULL);
 202         }
 203 
 204         punload_soft = malloc(sizeof (crypto_unload_soft_module_t));
 205         if (punload_soft == NULL) {
 206                 cryptodebug("out of memory.");
 207                 return (NULL);
 208         }
 209 
 210         (void) strlcpy(punload_soft->sm_name, pent->name, MAXNAMELEN);
 211 
 212         return (punload_soft);
 213 }
 214 
 215 
 216 /*
 217  * Prepare the calling argument for the GET_SOFT_INFO call for the provider
 218  * with the number of mechanisms specified in the second argument.


 219  */
 220 static crypto_get_soft_info_t *
 221 setup_get_soft_info(char *provname, int count)
 222 {
 223         crypto_get_soft_info_t *psoft_info;
 224         size_t extra_mech_size = 0;
 225 
 226         if (provname == NULL) {
 227                 return (NULL);
 228         }
 229 
 230         if (count > 1) {
 231                 extra_mech_size = sizeof (crypto_mech_name_t) * (count - 1);
 232         }
 233 
 234         psoft_info = malloc(sizeof (crypto_get_soft_info_t) + extra_mech_size);
 235         if (psoft_info == NULL) {
 236                 cryptodebug("out of memory.");
 237                 return (NULL);
 238         }
 239 
 240         (void) strlcpy(psoft_info->si_name, provname, MAXNAMELEN);
 241         psoft_info->si_count = count;
 242 
 243         return (psoft_info);
 244 }
 245 
 246 
 247 /*
 248  * Get the device list from kernel.
 249  */
 250 int
 251 get_dev_list(crypto_get_dev_list_t **ppdevlist)
 252 {
 253         crypto_get_dev_list_t *pdevlist;
 254         int fd;
 255         int count = DEFAULT_DEV_NUM;
 256 
 257         pdevlist = malloc(sizeof (crypto_get_dev_list_t) +
 258             sizeof (crypto_dev_list_entry_t) * (count - 1));
 259         if (pdevlist == NULL) {
 260                 cryptodebug("out of memory.");
 261                 return (FAILURE);
 262         }
 263 
 264         if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
 265                 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
 266                     ADMIN_IOCTL_DEVICE, strerror(errno));
 267                 return (FAILURE);
 268         }
 269 
 270         pdevlist->dl_dev_count = count;
 271         if (ioctl(fd, CRYPTO_GET_DEV_LIST, pdevlist) == -1) {
 272                 cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s",
 273                     strerror(errno));
 274                 free(pdevlist);


 305                 return (FAILURE);
 306         }
 307 
 308         *ppdevlist = pdevlist;
 309         (void) close(fd);
 310         return (SUCCESS);
 311 }
 312 
 313 
 314 /*
 315  * Get all the mechanisms supported by the hardware provider.
 316  * The result will be stored in the second argument.
 317  */
 318 int
 319 get_dev_info(char *devname, int inst_num, int count, mechlist_t **ppmechlist)
 320 {
 321         crypto_get_dev_info_t *dev_info;
 322         mechlist_t *phead;
 323         mechlist_t *pcur;
 324         mechlist_t *pmech;
 325         int fd;
 326         int i;
 327         int rc;
 328 
 329         if (devname == NULL || count < 1) {
 330                 cryptodebug("get_dev_info(): devname is NULL or bogus count");
 331                 return (FAILURE);
 332         }
 333 
 334         /* Set up the argument for the CRYPTO_GET_DEV_INFO ioctl call */
 335         dev_info = malloc(sizeof (crypto_get_dev_info_t) +
 336             sizeof (crypto_mech_name_t) * (count - 1));
 337         if (dev_info == NULL) {
 338                 cryptodebug("out of memory.");
 339                 return (FAILURE);
 340         }
 341         (void) strlcpy(dev_info->di_dev_name, devname, MAXNAMELEN);
 342         dev_info->di_dev_instance = inst_num;
 343         dev_info->di_count = count;
 344 
 345         /* Open the ioctl device */


 378                                 phead = pcur = pmech;
 379                         } else {
 380                                 pcur->next = pmech;
 381                                 pcur = pmech;
 382                         }
 383                 }
 384         }
 385 
 386         if (rc == SUCCESS) {
 387                 *ppmechlist = phead;
 388         } else {
 389                 free_mechlist(phead);
 390         }
 391 
 392         free(dev_info);
 393         (void) close(fd);
 394         return (rc);
 395 }
 396 
 397 
 398 
 399 /*
 400  * Get the supported mechanism list of the software provider from kernel.



 401  */
 402 int
 403 get_soft_info(char *provname, mechlist_t **ppmechlist)

 404 {

 405         crypto_get_soft_info_t  *psoft_info;
 406         mechlist_t      *phead;
 407         mechlist_t      *pmech;
 408         mechlist_t      *pcur;
 409         entry_t *pent;
 410         int     count;
 411         int     fd;
 412         int     rc;
 413         int     i;
 414 
 415         if (provname == NULL) {
 416                 return (FAILURE);
 417         }
 418 
 419         if (getzoneid() == GLOBAL_ZONEID) {
 420                 /* use kcf.conf for kernel software providers in global zone */
 421                 if ((pent = getent_kef(provname)) == NULL) {
 422                         cryptoerror(LOG_STDERR, gettext("%s does not exist."),
 423                             provname);



 424                         return (FAILURE);




 425                 }







 426                 count = pent->sup_count;
 427                 free_entry(pent);

 428         } else {
 429                 /*
 430                  * kcf.conf not there in non-global zone, set mech count to 1;
 431                  * it will be reset to the correct value later if the setup
 432                  * buffer is too small
 433                  */
 434                 count = 1;
 435         }
 436 
 437         if ((psoft_info = setup_get_soft_info(provname, count)) == NULL) {
 438                 return (FAILURE);
 439         }
 440 
 441         if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
 442                 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
 443                     ADMIN_IOCTL_DEVICE, strerror(errno));
 444                 free(psoft_info);
 445                 return (FAILURE);
 446         }
 447 
 448         /* make GET_SOFT_INFO ioctl call */
 449         if ((rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info)) == -1) {
 450                 cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed: %s",
 451                     strerror(errno));
 452                 (void) close(fd);


 466                         rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info);
 467                         if (rc == -1) {
 468                                 cryptodebug("CRYPTO_GET_SOFT_INFO ioctl "
 469                                     "failed: %s", strerror(errno));
 470                                 (void) close(fd);
 471                                 free(psoft_info);
 472                                 return (FAILURE);
 473                         }
 474                 }
 475         }
 476 
 477         (void) close(fd);
 478         if (psoft_info->si_return_value != CRYPTO_SUCCESS) {
 479                 cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed, "
 480                     "return_value = %d", psoft_info->si_return_value);
 481                 free(psoft_info);
 482                 return (FAILURE);
 483         }
 484 
 485 
 486         /* Get the mechanism list and return it */
 487         rc = SUCCESS;
 488         phead = pcur = NULL;
 489         for (i = 0; i < psoft_info->si_count; i++) {
 490                 pmech = create_mech(&psoft_info->si_list[i][0]);
 491                 if (pmech == NULL) {
 492                         rc = FAILURE;
 493                         break;
 494                 } else {
 495                         if (phead == NULL) {
 496                                 phead = pcur = pmech;
 497                         } else {
 498                                 pcur->next = pmech;
 499                                 pcur = pmech;
 500                         }
 501                 }
 502         }
 503 
 504         if (rc == FAILURE) {
 505                 free_mechlist(phead);
 506         } else {
 507                 *ppmechlist = phead;
 508         }
 509 
 510         free(psoft_info);
 511         return (rc);
 512 }
 513 
 514 
 515 /*
 516  * Get the kernel software provider list from kernel.
 517  */
 518 int
 519 get_soft_list(crypto_get_soft_list_t **ppsoftlist)
 520 {
 521         crypto_get_soft_list_t *psoftlist = NULL;
 522         int count = DEFAULT_SOFT_NUM;
 523         int len;
 524         int fd;
 525 
 526         if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
 527                 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
 528                     ADMIN_IOCTL_DEVICE, strerror(errno));
 529                 return (FAILURE);
 530         }
 531 
 532         len = MAXNAMELEN * count;
 533         psoftlist = malloc(sizeof (crypto_get_soft_list_t) + len);
 534         if (psoftlist == NULL) {
 535                 cryptodebug("out of memory.");
 536                 (void) close(fd);
 537                 return (FAILURE);
 538         }
 539         psoftlist->sl_soft_names = (caddr_t)(psoftlist + 1);
 540         psoftlist->sl_soft_count = count;
 541         psoftlist->sl_soft_len = len;
 542 
 543         if (ioctl(fd, CRYPTO_GET_SOFT_LIST, psoftlist) == -1) {
 544                 cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed: %s",


   1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.

   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 


  26 #include <fcntl.h>
  27 #include <stdio.h>
  28 #include <stdlib.h>
  29 #include <strings.h>
  30 #include <unistd.h>
  31 #include <locale.h>
  32 #include <libgen.h>
  33 #include <sys/types.h>
  34 #include <zone.h>
  35 #include <sys/crypto/ioctladmin.h>
  36 #include "cryptoadm.h"
  37 
  38 #define DEFAULT_DEV_NUM 5
  39 #define DEFAULT_SOFT_NUM 10
  40 
  41 static crypto_get_soft_info_t *setup_get_soft_info(char *, int);
  42 
  43 /*
  44  * Prepare the argument for the LOAD_SOFT_CONFIG ioctl call for the
  45  * provider pointed by pent.  Return NULL if out of memory.


  75 
  76         i = 0;
  77         plist =  pent->suplist;
  78         while (i < sup_count) {
  79                 (void) strlcpy(pload_soft_conf->sc_list[i++],
  80                     plist->name, CRYPTO_MAX_MECH_NAME);
  81                 plist = plist->next;
  82         }
  83 
  84         return (pload_soft_conf);
  85 }
  86 
  87 
  88 /*
  89  * Prepare the argument for the LOAD_SOFT_DISABLED ioctl call for the
  90  * provider pointed by pent.  Return NULL if out of memory.
  91  */
  92 crypto_load_soft_disabled_t *
  93 setup_soft_dis(entry_t *pent)
  94 {
  95         crypto_load_soft_disabled_t     *pload_soft_dis = NULL;
  96         mechlist_t      *plist = NULL;
  97         size_t          extra_mech_size = 0;
  98         uint_t          dis_count;
  99         int             i;
 100 
 101         if (pent == NULL) {
 102                 return (NULL);
 103         }
 104 
 105         dis_count = pent->dis_count;
 106         if (dis_count > 1) {
 107                 extra_mech_size = sizeof (crypto_mech_name_t) *
 108                     (dis_count - 1);
 109         }
 110 
 111         pload_soft_dis = malloc(sizeof (crypto_load_soft_disabled_t) +
 112             extra_mech_size);
 113         if (pload_soft_dis == NULL) {
 114                 cryptodebug("out of memory.");
 115                 return (NULL);
 116         }


 120 
 121         i = 0;
 122         plist =  pent->dislist;
 123         while (i < dis_count) {
 124                 (void) strlcpy(pload_soft_dis->sd_list[i++],
 125                     plist->name, CRYPTO_MAX_MECH_NAME);
 126                 plist = plist->next;
 127         }
 128 
 129         return (pload_soft_dis);
 130 }
 131 
 132 
 133 /*
 134  * Prepare the argument for the LOAD_DEV_DISABLED ioctl call for the
 135  * provider pointed by pent.  Return NULL if out of memory.
 136  */
 137 crypto_load_dev_disabled_t *
 138 setup_dev_dis(entry_t *pent)
 139 {
 140         crypto_load_dev_disabled_t      *pload_dev_dis = NULL;
 141         mechlist_t      *plist = NULL;
 142         size_t          extra_mech_size = 0;
 143         uint_t          dis_count;
 144         int             i;
 145         char            pname[MAXNAMELEN];
 146         int             inst_num;
 147 
 148         if (pent == NULL) {
 149                 return (NULL);
 150         }
 151 
 152         /* get the device name and the instance number */
 153         if (split_hw_provname(pent->name, pname, &inst_num) == FAILURE) {
 154                 return (NULL);
 155         }
 156 
 157         /* allocate space for pload_dev_des */
 158         dis_count = pent->dis_count;
 159         if (dis_count > 1) {
 160                 extra_mech_size = sizeof (crypto_mech_name_t) *
 161                     (dis_count - 1);


 196 
 197         if (pent == NULL) {
 198                 return (NULL);
 199         }
 200 
 201         punload_soft = malloc(sizeof (crypto_unload_soft_module_t));
 202         if (punload_soft == NULL) {
 203                 cryptodebug("out of memory.");
 204                 return (NULL);
 205         }
 206 
 207         (void) strlcpy(punload_soft->sm_name, pent->name, MAXNAMELEN);
 208 
 209         return (punload_soft);
 210 }
 211 
 212 
 213 /*
 214  * Prepare the calling argument for the GET_SOFT_INFO call for the provider
 215  * with the number of mechanisms specified in the second argument.
 216  *
 217  * Called by get_soft_info().
 218  */
 219 static crypto_get_soft_info_t *
 220 setup_get_soft_info(char *provname, int count)
 221 {
 222         crypto_get_soft_info_t  *psoft_info;
 223         size_t                  extra_mech_size = 0;
 224 
 225         if (provname == NULL) {
 226                 return (NULL);
 227         }
 228 
 229         if (count > 1) {
 230                 extra_mech_size = sizeof (crypto_mech_name_t) * (count - 1);
 231         }
 232 
 233         psoft_info = malloc(sizeof (crypto_get_soft_info_t) + extra_mech_size);
 234         if (psoft_info == NULL) {
 235                 cryptodebug("out of memory.");
 236                 return (NULL);
 237         }
 238 
 239         (void) strlcpy(psoft_info->si_name, provname, MAXNAMELEN);
 240         psoft_info->si_count = count;
 241 
 242         return (psoft_info);
 243 }
 244 
 245 
 246 /*
 247  * Get the device list from kernel.
 248  */
 249 int
 250 get_dev_list(crypto_get_dev_list_t **ppdevlist)
 251 {
 252         crypto_get_dev_list_t   *pdevlist;
 253         int                     fd = -1;
 254         int                     count = DEFAULT_DEV_NUM;
 255 
 256         pdevlist = malloc(sizeof (crypto_get_dev_list_t) +
 257             sizeof (crypto_dev_list_entry_t) * (count - 1));
 258         if (pdevlist == NULL) {
 259                 cryptodebug("out of memory.");
 260                 return (FAILURE);
 261         }
 262 
 263         if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
 264                 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
 265                     ADMIN_IOCTL_DEVICE, strerror(errno));
 266                 return (FAILURE);
 267         }
 268 
 269         pdevlist->dl_dev_count = count;
 270         if (ioctl(fd, CRYPTO_GET_DEV_LIST, pdevlist) == -1) {
 271                 cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s",
 272                     strerror(errno));
 273                 free(pdevlist);


 304                 return (FAILURE);
 305         }
 306 
 307         *ppdevlist = pdevlist;
 308         (void) close(fd);
 309         return (SUCCESS);
 310 }
 311 
 312 
 313 /*
 314  * Get all the mechanisms supported by the hardware provider.
 315  * The result will be stored in the second argument.
 316  */
 317 int
 318 get_dev_info(char *devname, int inst_num, int count, mechlist_t **ppmechlist)
 319 {
 320         crypto_get_dev_info_t   *dev_info;
 321         mechlist_t      *phead;
 322         mechlist_t      *pcur;
 323         mechlist_t      *pmech;
 324         int             fd = -1;
 325         int             i;
 326         int             rc;
 327 
 328         if (devname == NULL || count < 1) {
 329                 cryptodebug("get_dev_info(): devname is NULL or bogus count");
 330                 return (FAILURE);
 331         }
 332 
 333         /* Set up the argument for the CRYPTO_GET_DEV_INFO ioctl call */
 334         dev_info = malloc(sizeof (crypto_get_dev_info_t) +
 335             sizeof (crypto_mech_name_t) * (count - 1));
 336         if (dev_info == NULL) {
 337                 cryptodebug("out of memory.");
 338                 return (FAILURE);
 339         }
 340         (void) strlcpy(dev_info->di_dev_name, devname, MAXNAMELEN);
 341         dev_info->di_dev_instance = inst_num;
 342         dev_info->di_count = count;
 343 
 344         /* Open the ioctl device */


 377                                 phead = pcur = pmech;
 378                         } else {
 379                                 pcur->next = pmech;
 380                                 pcur = pmech;
 381                         }
 382                 }
 383         }
 384 
 385         if (rc == SUCCESS) {
 386                 *ppmechlist = phead;
 387         } else {
 388                 free_mechlist(phead);
 389         }
 390 
 391         free(dev_info);
 392         (void) close(fd);
 393         return (rc);
 394 }
 395 
 396 

 397 /*
 398  * Get the supported mechanism list of the software provider from kernel.
 399  *
 400  * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
 401  * If NULL, this function calls get_kcfconf_info() internally.
 402  */
 403 int
 404 get_soft_info(char *provname, mechlist_t **ppmechlist,
 405         entrylist_t *phardlist, entrylist_t *psoftlist)
 406 {
 407         boolean_t               in_kernel = B_FALSE;
 408         crypto_get_soft_info_t  *psoft_info;
 409         mechlist_t              *phead;
 410         mechlist_t              *pmech;
 411         mechlist_t              *pcur;
 412         entry_t                 *pent = NULL;
 413         int                     count;
 414         int                     fd = -1;
 415         int                     rc;
 416         int                     i;
 417 
 418         if (provname == NULL) {
 419                 return (FAILURE);
 420         }
 421 
 422         if (getzoneid() == GLOBAL_ZONEID) {
 423                 /* use kcf.conf for kernel software providers in global zone */
 424                 if ((pent = getent_kef(provname, phardlist, psoftlist)) ==
 425                     NULL) {
 426 
 427                         /* No kcf.conf entry for this provider */
 428                         if (check_kernel_for_soft(provname, NULL, &in_kernel)
 429                             == FAILURE) {
 430                                 return (FAILURE);
 431                         } else if (in_kernel == B_FALSE) {
 432                                 cryptoerror(LOG_STDERR,
 433                                     gettext("%s does not exist."), provname);
 434                                 return (FAILURE);
 435                         }
 436 
 437                         /*
 438                          * Set mech count to 1.  It will be reset to the
 439                          * correct value later if the setup buffer is too small.
 440                          */
 441                         count = 1;
 442                 } else {
 443                         count = pent->sup_count;
 444                         free_entry(pent);
 445                 }
 446         } else {
 447                 /*
 448                  * kcf.conf not there in non-global zone: set mech count to 1.
 449                  * It will be reset to the correct value later if the setup
 450                  * buffer is too small.
 451                  */
 452                 count = 1;
 453         }
 454 
 455         if ((psoft_info = setup_get_soft_info(provname, count)) == NULL) {
 456                 return (FAILURE);
 457         }
 458 
 459         if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
 460                 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
 461                     ADMIN_IOCTL_DEVICE, strerror(errno));
 462                 free(psoft_info);
 463                 return (FAILURE);
 464         }
 465 
 466         /* make GET_SOFT_INFO ioctl call */
 467         if ((rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info)) == -1) {
 468                 cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed: %s",
 469                     strerror(errno));
 470                 (void) close(fd);


 484                         rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info);
 485                         if (rc == -1) {
 486                                 cryptodebug("CRYPTO_GET_SOFT_INFO ioctl "
 487                                     "failed: %s", strerror(errno));
 488                                 (void) close(fd);
 489                                 free(psoft_info);
 490                                 return (FAILURE);
 491                         }
 492                 }
 493         }
 494 
 495         (void) close(fd);
 496         if (psoft_info->si_return_value != CRYPTO_SUCCESS) {
 497                 cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed, "
 498                     "return_value = %d", psoft_info->si_return_value);
 499                 free(psoft_info);
 500                 return (FAILURE);
 501         }
 502 
 503 
 504         /* Build the mechanism linked list and return it */
 505         rc = SUCCESS;
 506         phead = pcur = NULL;
 507         for (i = 0; i < psoft_info->si_count; i++) {
 508                 pmech = create_mech(&psoft_info->si_list[i][0]);
 509                 if (pmech == NULL) {
 510                         rc = FAILURE;
 511                         break;
 512                 } else {
 513                         if (phead == NULL) {
 514                                 phead = pcur = pmech;
 515                         } else {
 516                                 pcur->next = pmech;
 517                                 pcur = pmech;
 518                         }
 519                 }
 520         }
 521 
 522         if (rc == FAILURE) {
 523                 free_mechlist(phead);
 524         } else {
 525                 *ppmechlist = phead;
 526         }
 527 
 528         free(psoft_info);
 529         return (rc);
 530 }
 531 
 532 
 533 /*
 534  * Get the kernel software provider list from kernel.
 535  */
 536 int
 537 get_soft_list(crypto_get_soft_list_t **ppsoftlist)
 538 {
 539         crypto_get_soft_list_t *psoftlist = NULL;
 540         int     count = DEFAULT_SOFT_NUM;
 541         int     len;
 542         int     fd = -1;
 543 
 544         if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) {
 545                 cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
 546                     ADMIN_IOCTL_DEVICE, strerror(errno));
 547                 return (FAILURE);
 548         }
 549 
 550         len = MAXNAMELEN * count;
 551         psoftlist = malloc(sizeof (crypto_get_soft_list_t) + len);
 552         if (psoftlist == NULL) {
 553                 cryptodebug("out of memory.");
 554                 (void) close(fd);
 555                 return (FAILURE);
 556         }
 557         psoftlist->sl_soft_names = (caddr_t)(psoftlist + 1);
 558         psoftlist->sl_soft_count = count;
 559         psoftlist->sl_soft_len = len;
 560 
 561         if (ioctl(fd, CRYPTO_GET_SOFT_LIST, psoftlist) == -1) {
 562                 cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed: %s",