17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51b22764fSDaniel OpenSolaris Anderson * Common Development and Distribution License (the "License"). 61b22764fSDaniel OpenSolaris Anderson * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 2232e0ab73SMisaki Miyashita * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 24*6ea3c060SGarrett D'Amore /* 25*6ea3c060SGarrett D'Amore * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 26*6ea3c060SGarrett D'Amore */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <fcntl.h> 297c478bd9Sstevel@tonic-gate #include <stdio.h> 307c478bd9Sstevel@tonic-gate #include <stdlib.h> 317c478bd9Sstevel@tonic-gate #include <strings.h> 327c478bd9Sstevel@tonic-gate #include <unistd.h> 337c478bd9Sstevel@tonic-gate #include <locale.h> 347c478bd9Sstevel@tonic-gate #include <libgen.h> 357c478bd9Sstevel@tonic-gate #include <sys/types.h> 3632e0ab73SMisaki Miyashita #include <sys/varargs.h> 377c478bd9Sstevel@tonic-gate #include <zone.h> 387c478bd9Sstevel@tonic-gate #include <sys/crypto/ioctladmin.h> 397c478bd9Sstevel@tonic-gate #include "cryptoadm.h" 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #define DEFAULT_DEV_NUM 5 427c478bd9Sstevel@tonic-gate #define DEFAULT_SOFT_NUM 10 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate static crypto_get_soft_info_t *setup_get_soft_info(char *, int); 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate /* 477c478bd9Sstevel@tonic-gate * Prepare the argument for the LOAD_SOFT_CONFIG ioctl call for the 487c478bd9Sstevel@tonic-gate * provider pointed by pent. Return NULL if out of memory. 497c478bd9Sstevel@tonic-gate */ 507c478bd9Sstevel@tonic-gate crypto_load_soft_config_t * 517c478bd9Sstevel@tonic-gate setup_soft_conf(entry_t *pent) 527c478bd9Sstevel@tonic-gate { 537c478bd9Sstevel@tonic-gate crypto_load_soft_config_t *pload_soft_conf; 547c478bd9Sstevel@tonic-gate mechlist_t *plist; 557c478bd9Sstevel@tonic-gate uint_t sup_count; 567c478bd9Sstevel@tonic-gate size_t extra_mech_size = 0; 577c478bd9Sstevel@tonic-gate int i; 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate if (pent == NULL) { 607c478bd9Sstevel@tonic-gate return (NULL); 617c478bd9Sstevel@tonic-gate } 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate sup_count = pent->sup_count; 647c478bd9Sstevel@tonic-gate if (sup_count > 1) { 657c478bd9Sstevel@tonic-gate extra_mech_size = sizeof (crypto_mech_name_t) * 667c478bd9Sstevel@tonic-gate (sup_count - 1); 677c478bd9Sstevel@tonic-gate } 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate pload_soft_conf = malloc(sizeof (crypto_load_soft_config_t) + 707c478bd9Sstevel@tonic-gate extra_mech_size); 717c478bd9Sstevel@tonic-gate if (pload_soft_conf == NULL) { 727c478bd9Sstevel@tonic-gate cryptodebug("out of memory."); 737c478bd9Sstevel@tonic-gate return (NULL); 747c478bd9Sstevel@tonic-gate } 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate (void) strlcpy(pload_soft_conf->sc_name, pent->name, MAXNAMELEN); 777c478bd9Sstevel@tonic-gate pload_soft_conf->sc_count = sup_count; 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate i = 0; 807c478bd9Sstevel@tonic-gate plist = pent->suplist; 817c478bd9Sstevel@tonic-gate while (i < sup_count) { 827c478bd9Sstevel@tonic-gate (void) strlcpy(pload_soft_conf->sc_list[i++], 837c478bd9Sstevel@tonic-gate plist->name, CRYPTO_MAX_MECH_NAME); 847c478bd9Sstevel@tonic-gate plist = plist->next; 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate return (pload_soft_conf); 887c478bd9Sstevel@tonic-gate } 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate /* 927c478bd9Sstevel@tonic-gate * Prepare the argument for the LOAD_SOFT_DISABLED ioctl call for the 937c478bd9Sstevel@tonic-gate * provider pointed by pent. Return NULL if out of memory. 947c478bd9Sstevel@tonic-gate */ 957c478bd9Sstevel@tonic-gate crypto_load_soft_disabled_t * 967c478bd9Sstevel@tonic-gate setup_soft_dis(entry_t *pent) 977c478bd9Sstevel@tonic-gate { 981b22764fSDaniel OpenSolaris Anderson crypto_load_soft_disabled_t *pload_soft_dis = NULL; 991b22764fSDaniel OpenSolaris Anderson mechlist_t *plist = NULL; 1007c478bd9Sstevel@tonic-gate size_t extra_mech_size = 0; 1017c478bd9Sstevel@tonic-gate uint_t dis_count; 1027c478bd9Sstevel@tonic-gate int i; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate if (pent == NULL) { 1057c478bd9Sstevel@tonic-gate return (NULL); 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate dis_count = pent->dis_count; 1097c478bd9Sstevel@tonic-gate if (dis_count > 1) { 1107c478bd9Sstevel@tonic-gate extra_mech_size = sizeof (crypto_mech_name_t) * 1117c478bd9Sstevel@tonic-gate (dis_count - 1); 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate pload_soft_dis = malloc(sizeof (crypto_load_soft_disabled_t) + 1157c478bd9Sstevel@tonic-gate extra_mech_size); 1167c478bd9Sstevel@tonic-gate if (pload_soft_dis == NULL) { 1177c478bd9Sstevel@tonic-gate cryptodebug("out of memory."); 1187c478bd9Sstevel@tonic-gate return (NULL); 1197c478bd9Sstevel@tonic-gate } 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate (void) strlcpy(pload_soft_dis->sd_name, pent->name, MAXNAMELEN); 1227c478bd9Sstevel@tonic-gate pload_soft_dis->sd_count = dis_count; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate i = 0; 1257c478bd9Sstevel@tonic-gate plist = pent->dislist; 1267c478bd9Sstevel@tonic-gate while (i < dis_count) { 1277c478bd9Sstevel@tonic-gate (void) strlcpy(pload_soft_dis->sd_list[i++], 1287c478bd9Sstevel@tonic-gate plist->name, CRYPTO_MAX_MECH_NAME); 1297c478bd9Sstevel@tonic-gate plist = plist->next; 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate return (pload_soft_dis); 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate /* 1377c478bd9Sstevel@tonic-gate * Prepare the argument for the LOAD_DEV_DISABLED ioctl call for the 1387c478bd9Sstevel@tonic-gate * provider pointed by pent. Return NULL if out of memory. 1397c478bd9Sstevel@tonic-gate */ 1407c478bd9Sstevel@tonic-gate crypto_load_dev_disabled_t * 1417c478bd9Sstevel@tonic-gate setup_dev_dis(entry_t *pent) 1427c478bd9Sstevel@tonic-gate { 1431b22764fSDaniel OpenSolaris Anderson crypto_load_dev_disabled_t *pload_dev_dis = NULL; 1441b22764fSDaniel OpenSolaris Anderson mechlist_t *plist = NULL; 1457c478bd9Sstevel@tonic-gate size_t extra_mech_size = 0; 1467c478bd9Sstevel@tonic-gate uint_t dis_count; 1477c478bd9Sstevel@tonic-gate int i; 1487c478bd9Sstevel@tonic-gate char pname[MAXNAMELEN]; 1497c478bd9Sstevel@tonic-gate int inst_num; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate if (pent == NULL) { 1527c478bd9Sstevel@tonic-gate return (NULL); 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate /* get the device name and the instance number */ 1567c478bd9Sstevel@tonic-gate if (split_hw_provname(pent->name, pname, &inst_num) == FAILURE) { 1577c478bd9Sstevel@tonic-gate return (NULL); 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate /* allocate space for pload_dev_des */ 1617c478bd9Sstevel@tonic-gate dis_count = pent->dis_count; 1627c478bd9Sstevel@tonic-gate if (dis_count > 1) { 1637c478bd9Sstevel@tonic-gate extra_mech_size = sizeof (crypto_mech_name_t) * 1647c478bd9Sstevel@tonic-gate (dis_count - 1); 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate pload_dev_dis = malloc(sizeof (crypto_load_dev_disabled_t) + 1687c478bd9Sstevel@tonic-gate extra_mech_size); 1697c478bd9Sstevel@tonic-gate if (pload_dev_dis == NULL) { 1707c478bd9Sstevel@tonic-gate cryptodebug("out of memory."); 1717c478bd9Sstevel@tonic-gate return (NULL); 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate /* set the values for pload_dev_dis */ 1757c478bd9Sstevel@tonic-gate (void) strlcpy(pload_dev_dis->dd_dev_name, pname, MAXNAMELEN); 1767c478bd9Sstevel@tonic-gate pload_dev_dis->dd_dev_instance = inst_num; 1777c478bd9Sstevel@tonic-gate pload_dev_dis->dd_count = dis_count; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate i = 0; 1807c478bd9Sstevel@tonic-gate plist = pent->dislist; 1817c478bd9Sstevel@tonic-gate while (i < dis_count) { 1827c478bd9Sstevel@tonic-gate (void) strlcpy(pload_dev_dis->dd_list[i++], 1837c478bd9Sstevel@tonic-gate plist->name, CRYPTO_MAX_MECH_NAME); 1847c478bd9Sstevel@tonic-gate plist = plist->next; 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate return (pload_dev_dis); 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * Prepare the calling argument of the UNLOAD_SOFT_MODULE ioctl call for the 1937c478bd9Sstevel@tonic-gate * provider pointed by pent. Return NULL if out of memory. 1947c478bd9Sstevel@tonic-gate */ 1957c478bd9Sstevel@tonic-gate crypto_unload_soft_module_t * 1967c478bd9Sstevel@tonic-gate setup_unload_soft(entry_t *pent) 1977c478bd9Sstevel@tonic-gate { 1987c478bd9Sstevel@tonic-gate crypto_unload_soft_module_t *punload_soft; 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate if (pent == NULL) { 2017c478bd9Sstevel@tonic-gate return (NULL); 2027c478bd9Sstevel@tonic-gate } 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate punload_soft = malloc(sizeof (crypto_unload_soft_module_t)); 2057c478bd9Sstevel@tonic-gate if (punload_soft == NULL) { 2067c478bd9Sstevel@tonic-gate cryptodebug("out of memory."); 2077c478bd9Sstevel@tonic-gate return (NULL); 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate (void) strlcpy(punload_soft->sm_name, pent->name, MAXNAMELEN); 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate return (punload_soft); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate /* 2177c478bd9Sstevel@tonic-gate * Prepare the calling argument for the GET_SOFT_INFO call for the provider 2187c478bd9Sstevel@tonic-gate * with the number of mechanisms specified in the second argument. 2191b22764fSDaniel OpenSolaris Anderson * 2201b22764fSDaniel OpenSolaris Anderson * Called by get_soft_info(). 2217c478bd9Sstevel@tonic-gate */ 2227c478bd9Sstevel@tonic-gate static crypto_get_soft_info_t * 2237c478bd9Sstevel@tonic-gate setup_get_soft_info(char *provname, int count) 2247c478bd9Sstevel@tonic-gate { 2257c478bd9Sstevel@tonic-gate crypto_get_soft_info_t *psoft_info; 2267c478bd9Sstevel@tonic-gate size_t extra_mech_size = 0; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate if (provname == NULL) { 2297c478bd9Sstevel@tonic-gate return (NULL); 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate if (count > 1) { 2337c478bd9Sstevel@tonic-gate extra_mech_size = sizeof (crypto_mech_name_t) * (count - 1); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate psoft_info = malloc(sizeof (crypto_get_soft_info_t) + extra_mech_size); 2377c478bd9Sstevel@tonic-gate if (psoft_info == NULL) { 2387c478bd9Sstevel@tonic-gate cryptodebug("out of memory."); 2397c478bd9Sstevel@tonic-gate return (NULL); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate (void) strlcpy(psoft_info->si_name, provname, MAXNAMELEN); 2437c478bd9Sstevel@tonic-gate psoft_info->si_count = count; 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate return (psoft_info); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate /* 2507c478bd9Sstevel@tonic-gate * Get the device list from kernel. 2517c478bd9Sstevel@tonic-gate */ 2527c478bd9Sstevel@tonic-gate int 2537c478bd9Sstevel@tonic-gate get_dev_list(crypto_get_dev_list_t **ppdevlist) 2547c478bd9Sstevel@tonic-gate { 2557c478bd9Sstevel@tonic-gate crypto_get_dev_list_t *pdevlist; 2561b22764fSDaniel OpenSolaris Anderson int fd = -1; 2577c478bd9Sstevel@tonic-gate int count = DEFAULT_DEV_NUM; 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate pdevlist = malloc(sizeof (crypto_get_dev_list_t) + 2607c478bd9Sstevel@tonic-gate sizeof (crypto_dev_list_entry_t) * (count - 1)); 2617c478bd9Sstevel@tonic-gate if (pdevlist == NULL) { 2627c478bd9Sstevel@tonic-gate cryptodebug("out of memory."); 2637c478bd9Sstevel@tonic-gate return (FAILURE); 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) { 2677c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 2687c478bd9Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 2697c478bd9Sstevel@tonic-gate return (FAILURE); 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate pdevlist->dl_dev_count = count; 2737c478bd9Sstevel@tonic-gate if (ioctl(fd, CRYPTO_GET_DEV_LIST, pdevlist) == -1) { 2747c478bd9Sstevel@tonic-gate cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s", 2757c478bd9Sstevel@tonic-gate strerror(errno)); 2767c478bd9Sstevel@tonic-gate free(pdevlist); 2777c478bd9Sstevel@tonic-gate (void) close(fd); 2787c478bd9Sstevel@tonic-gate return (FAILURE); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* BUFFER is too small, get the number of devices and retry it. */ 2827c478bd9Sstevel@tonic-gate if (pdevlist->dl_return_value == CRYPTO_BUFFER_TOO_SMALL) { 2837c478bd9Sstevel@tonic-gate count = pdevlist->dl_dev_count; 2847c478bd9Sstevel@tonic-gate free(pdevlist); 2857c478bd9Sstevel@tonic-gate pdevlist = malloc(sizeof (crypto_get_dev_list_t) + 2867c478bd9Sstevel@tonic-gate sizeof (crypto_dev_list_entry_t) * (count - 1)); 2877c478bd9Sstevel@tonic-gate if (pdevlist == NULL) { 2887c478bd9Sstevel@tonic-gate cryptodebug("out of memory."); 2897c478bd9Sstevel@tonic-gate (void) close(fd); 2907c478bd9Sstevel@tonic-gate return (FAILURE); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate if (ioctl(fd, CRYPTO_GET_DEV_LIST, pdevlist) == -1) { 2947c478bd9Sstevel@tonic-gate cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed: %s", 2957c478bd9Sstevel@tonic-gate strerror(errno)); 2967c478bd9Sstevel@tonic-gate free(pdevlist); 2977c478bd9Sstevel@tonic-gate (void) close(fd); 2987c478bd9Sstevel@tonic-gate return (FAILURE); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate if (pdevlist->dl_return_value != CRYPTO_SUCCESS) { 3037c478bd9Sstevel@tonic-gate cryptodebug("CRYPTO_GET_DEV_LIST ioctl failed, " 3047c478bd9Sstevel@tonic-gate "return_value = %d", pdevlist->dl_return_value); 3057c478bd9Sstevel@tonic-gate free(pdevlist); 3067c478bd9Sstevel@tonic-gate (void) close(fd); 3077c478bd9Sstevel@tonic-gate return (FAILURE); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate *ppdevlist = pdevlist; 3117c478bd9Sstevel@tonic-gate (void) close(fd); 3127c478bd9Sstevel@tonic-gate return (SUCCESS); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* 3177c478bd9Sstevel@tonic-gate * Get all the mechanisms supported by the hardware provider. 3187c478bd9Sstevel@tonic-gate * The result will be stored in the second argument. 3197c478bd9Sstevel@tonic-gate */ 3207c478bd9Sstevel@tonic-gate int 3217c478bd9Sstevel@tonic-gate get_dev_info(char *devname, int inst_num, int count, mechlist_t **ppmechlist) 3227c478bd9Sstevel@tonic-gate { 3237c478bd9Sstevel@tonic-gate crypto_get_dev_info_t *dev_info; 3247c478bd9Sstevel@tonic-gate mechlist_t *phead; 3257c478bd9Sstevel@tonic-gate mechlist_t *pcur; 3267c478bd9Sstevel@tonic-gate mechlist_t *pmech; 3271b22764fSDaniel OpenSolaris Anderson int fd = -1; 3287c478bd9Sstevel@tonic-gate int i; 3297c478bd9Sstevel@tonic-gate int rc; 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate if (devname == NULL || count < 1) { 3327c478bd9Sstevel@tonic-gate cryptodebug("get_dev_info(): devname is NULL or bogus count"); 3337c478bd9Sstevel@tonic-gate return (FAILURE); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate /* Set up the argument for the CRYPTO_GET_DEV_INFO ioctl call */ 3377c478bd9Sstevel@tonic-gate dev_info = malloc(sizeof (crypto_get_dev_info_t) + 3387c478bd9Sstevel@tonic-gate sizeof (crypto_mech_name_t) * (count - 1)); 3397c478bd9Sstevel@tonic-gate if (dev_info == NULL) { 3407c478bd9Sstevel@tonic-gate cryptodebug("out of memory."); 3417c478bd9Sstevel@tonic-gate return (FAILURE); 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate (void) strlcpy(dev_info->di_dev_name, devname, MAXNAMELEN); 3447c478bd9Sstevel@tonic-gate dev_info->di_dev_instance = inst_num; 3457c478bd9Sstevel@tonic-gate dev_info->di_count = count; 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate /* Open the ioctl device */ 3487c478bd9Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) { 3497c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 3507c478bd9Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 3517c478bd9Sstevel@tonic-gate free(dev_info); 3527c478bd9Sstevel@tonic-gate return (FAILURE); 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate if (ioctl(fd, CRYPTO_GET_DEV_INFO, dev_info) == -1) { 3567c478bd9Sstevel@tonic-gate cryptodebug("CRYPTO_GET_DEV_INFO ioctl failed: %s", 3577c478bd9Sstevel@tonic-gate strerror(errno)); 3587c478bd9Sstevel@tonic-gate free(dev_info); 3597c478bd9Sstevel@tonic-gate (void) close(fd); 3607c478bd9Sstevel@tonic-gate return (FAILURE); 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate if (dev_info->di_return_value != CRYPTO_SUCCESS) { 3647c478bd9Sstevel@tonic-gate cryptodebug("CRYPTO_GET_DEV_INFO ioctl failed, " 3657c478bd9Sstevel@tonic-gate "return_value = %d", dev_info->di_return_value); 3667c478bd9Sstevel@tonic-gate free(dev_info); 3677c478bd9Sstevel@tonic-gate (void) close(fd); 3687c478bd9Sstevel@tonic-gate return (FAILURE); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate phead = pcur = NULL; 3727c478bd9Sstevel@tonic-gate rc = SUCCESS; 3737c478bd9Sstevel@tonic-gate for (i = 0; i < dev_info->di_count; i++) { 3747c478bd9Sstevel@tonic-gate pmech = create_mech(&dev_info->di_list[i][0]); 3757c478bd9Sstevel@tonic-gate if (pmech == NULL) { 3767c478bd9Sstevel@tonic-gate rc = FAILURE; 3777c478bd9Sstevel@tonic-gate break; 3787c478bd9Sstevel@tonic-gate } else { 3797c478bd9Sstevel@tonic-gate if (phead == NULL) { 3807c478bd9Sstevel@tonic-gate phead = pcur = pmech; 3817c478bd9Sstevel@tonic-gate } else { 3827c478bd9Sstevel@tonic-gate pcur->next = pmech; 3837c478bd9Sstevel@tonic-gate pcur = pmech; 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate if (rc == SUCCESS) { 3897c478bd9Sstevel@tonic-gate *ppmechlist = phead; 3907c478bd9Sstevel@tonic-gate } else { 3917c478bd9Sstevel@tonic-gate free_mechlist(phead); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate free(dev_info); 3957c478bd9Sstevel@tonic-gate (void) close(fd); 3967c478bd9Sstevel@tonic-gate return (rc); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate /* 4017c478bd9Sstevel@tonic-gate * Get the supported mechanism list of the software provider from kernel. 4021b22764fSDaniel OpenSolaris Anderson * 4031b22764fSDaniel OpenSolaris Anderson * Parameters phardlist and psoftlist are supplied by get_kcfconf_info(). 4041b22764fSDaniel OpenSolaris Anderson * If NULL, this function calls get_kcfconf_info() internally. 4057c478bd9Sstevel@tonic-gate */ 4067c478bd9Sstevel@tonic-gate int 4071b22764fSDaniel OpenSolaris Anderson get_soft_info(char *provname, mechlist_t **ppmechlist, 408d616ad8eSHai-May Chao entrylist_t *phardlist, entrylist_t *psoftlist) 4097c478bd9Sstevel@tonic-gate { 4101b22764fSDaniel OpenSolaris Anderson boolean_t in_kernel = B_FALSE; 4117c478bd9Sstevel@tonic-gate crypto_get_soft_info_t *psoft_info; 4127c478bd9Sstevel@tonic-gate mechlist_t *phead; 4137c478bd9Sstevel@tonic-gate mechlist_t *pmech; 4147c478bd9Sstevel@tonic-gate mechlist_t *pcur; 4151b22764fSDaniel OpenSolaris Anderson entry_t *pent = NULL; 4167c478bd9Sstevel@tonic-gate int count; 4171b22764fSDaniel OpenSolaris Anderson int fd = -1; 4187c478bd9Sstevel@tonic-gate int rc; 4197c478bd9Sstevel@tonic-gate int i; 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate if (provname == NULL) { 4227c478bd9Sstevel@tonic-gate return (FAILURE); 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate if (getzoneid() == GLOBAL_ZONEID) { 4267c478bd9Sstevel@tonic-gate /* use kcf.conf for kernel software providers in global zone */ 427d616ad8eSHai-May Chao if ((pent = getent_kef(provname, phardlist, psoftlist)) == 428d616ad8eSHai-May Chao NULL) { 4291b22764fSDaniel OpenSolaris Anderson 4301b22764fSDaniel OpenSolaris Anderson /* No kcf.conf entry for this provider */ 4311b22764fSDaniel OpenSolaris Anderson if (check_kernel_for_soft(provname, NULL, &in_kernel) 4321b22764fSDaniel OpenSolaris Anderson == FAILURE) { 4331b22764fSDaniel OpenSolaris Anderson return (FAILURE); 4341b22764fSDaniel OpenSolaris Anderson } else if (in_kernel == B_FALSE) { 4351b22764fSDaniel OpenSolaris Anderson cryptoerror(LOG_STDERR, 4361b22764fSDaniel OpenSolaris Anderson gettext("%s does not exist."), provname); 4377c478bd9Sstevel@tonic-gate return (FAILURE); 4387c478bd9Sstevel@tonic-gate } 4391b22764fSDaniel OpenSolaris Anderson 4401b22764fSDaniel OpenSolaris Anderson /* 4411b22764fSDaniel OpenSolaris Anderson * Set mech count to 1. It will be reset to the 4421b22764fSDaniel OpenSolaris Anderson * correct value later if the setup buffer is too small. 4431b22764fSDaniel OpenSolaris Anderson */ 4441b22764fSDaniel OpenSolaris Anderson count = 1; 4451b22764fSDaniel OpenSolaris Anderson } else { 4467c478bd9Sstevel@tonic-gate count = pent->sup_count; 4477c478bd9Sstevel@tonic-gate free_entry(pent); 4481b22764fSDaniel OpenSolaris Anderson } 4497c478bd9Sstevel@tonic-gate } else { 4507c478bd9Sstevel@tonic-gate /* 4511b22764fSDaniel OpenSolaris Anderson * kcf.conf not there in non-global zone: set mech count to 1. 4521b22764fSDaniel OpenSolaris Anderson * It will be reset to the correct value later if the setup 4531b22764fSDaniel OpenSolaris Anderson * buffer is too small. 4547c478bd9Sstevel@tonic-gate */ 4557c478bd9Sstevel@tonic-gate count = 1; 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate if ((psoft_info = setup_get_soft_info(provname, count)) == NULL) { 4597c478bd9Sstevel@tonic-gate return (FAILURE); 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) { 4637c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 4647c478bd9Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 4657c478bd9Sstevel@tonic-gate free(psoft_info); 4667c478bd9Sstevel@tonic-gate return (FAILURE); 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate /* make GET_SOFT_INFO ioctl call */ 4707c478bd9Sstevel@tonic-gate if ((rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info)) == -1) { 4717c478bd9Sstevel@tonic-gate cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed: %s", 4727c478bd9Sstevel@tonic-gate strerror(errno)); 4737c478bd9Sstevel@tonic-gate (void) close(fd); 4747c478bd9Sstevel@tonic-gate free(psoft_info); 4757c478bd9Sstevel@tonic-gate return (FAILURE); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate /* BUFFER is too small, get the number of mechanisms and retry it. */ 4797c478bd9Sstevel@tonic-gate if (psoft_info->si_return_value == CRYPTO_BUFFER_TOO_SMALL) { 4807c478bd9Sstevel@tonic-gate count = psoft_info->si_count; 4817c478bd9Sstevel@tonic-gate free(psoft_info); 4827c478bd9Sstevel@tonic-gate if ((psoft_info = setup_get_soft_info(provname, count)) 4837c478bd9Sstevel@tonic-gate == NULL) { 4847c478bd9Sstevel@tonic-gate (void) close(fd); 4857c478bd9Sstevel@tonic-gate return (FAILURE); 4867c478bd9Sstevel@tonic-gate } else { 4877c478bd9Sstevel@tonic-gate rc = ioctl(fd, CRYPTO_GET_SOFT_INFO, psoft_info); 4887c478bd9Sstevel@tonic-gate if (rc == -1) { 4897c478bd9Sstevel@tonic-gate cryptodebug("CRYPTO_GET_SOFT_INFO ioctl " 4907c478bd9Sstevel@tonic-gate "failed: %s", strerror(errno)); 4917c478bd9Sstevel@tonic-gate (void) close(fd); 4927c478bd9Sstevel@tonic-gate free(psoft_info); 4937c478bd9Sstevel@tonic-gate return (FAILURE); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate (void) close(fd); 4997c478bd9Sstevel@tonic-gate if (psoft_info->si_return_value != CRYPTO_SUCCESS) { 5007c478bd9Sstevel@tonic-gate cryptodebug("CRYPTO_GET_SOFT_INFO ioctl failed, " 5017c478bd9Sstevel@tonic-gate "return_value = %d", psoft_info->si_return_value); 5027c478bd9Sstevel@tonic-gate free(psoft_info); 5037c478bd9Sstevel@tonic-gate return (FAILURE); 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate 5071b22764fSDaniel OpenSolaris Anderson /* Build the mechanism linked list and return it */ 5087c478bd9Sstevel@tonic-gate rc = SUCCESS; 5097c478bd9Sstevel@tonic-gate phead = pcur = NULL; 5107c478bd9Sstevel@tonic-gate for (i = 0; i < psoft_info->si_count; i++) { 5117c478bd9Sstevel@tonic-gate pmech = create_mech(&psoft_info->si_list[i][0]); 5127c478bd9Sstevel@tonic-gate if (pmech == NULL) { 5137c478bd9Sstevel@tonic-gate rc = FAILURE; 5147c478bd9Sstevel@tonic-gate break; 5157c478bd9Sstevel@tonic-gate } else { 5167c478bd9Sstevel@tonic-gate if (phead == NULL) { 5177c478bd9Sstevel@tonic-gate phead = pcur = pmech; 5187c478bd9Sstevel@tonic-gate } else { 5197c478bd9Sstevel@tonic-gate pcur->next = pmech; 5207c478bd9Sstevel@tonic-gate pcur = pmech; 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate if (rc == FAILURE) { 5267c478bd9Sstevel@tonic-gate free_mechlist(phead); 5277c478bd9Sstevel@tonic-gate } else { 5287c478bd9Sstevel@tonic-gate *ppmechlist = phead; 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate free(psoft_info); 5327c478bd9Sstevel@tonic-gate return (rc); 5337c478bd9Sstevel@tonic-gate } 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate /* 5377c478bd9Sstevel@tonic-gate * Get the kernel software provider list from kernel. 5387c478bd9Sstevel@tonic-gate */ 5397c478bd9Sstevel@tonic-gate int 5407c478bd9Sstevel@tonic-gate get_soft_list(crypto_get_soft_list_t **ppsoftlist) 5417c478bd9Sstevel@tonic-gate { 5427c478bd9Sstevel@tonic-gate crypto_get_soft_list_t *psoftlist = NULL; 5437c478bd9Sstevel@tonic-gate int count = DEFAULT_SOFT_NUM; 5447c478bd9Sstevel@tonic-gate int len; 5451b22764fSDaniel OpenSolaris Anderson int fd = -1; 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDONLY)) == -1) { 5487c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"), 5497c478bd9Sstevel@tonic-gate ADMIN_IOCTL_DEVICE, strerror(errno)); 5507c478bd9Sstevel@tonic-gate return (FAILURE); 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate len = MAXNAMELEN * count; 5547c478bd9Sstevel@tonic-gate psoftlist = malloc(sizeof (crypto_get_soft_list_t) + len); 5557c478bd9Sstevel@tonic-gate if (psoftlist == NULL) { 5567c478bd9Sstevel@tonic-gate cryptodebug("out of memory."); 5577c478bd9Sstevel@tonic-gate (void) close(fd); 5587c478bd9Sstevel@tonic-gate return (FAILURE); 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate psoftlist->sl_soft_names = (caddr_t)(psoftlist + 1); 5617c478bd9Sstevel@tonic-gate psoftlist->sl_soft_count = count; 5627c478bd9Sstevel@tonic-gate psoftlist->sl_soft_len = len; 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate if (ioctl(fd, CRYPTO_GET_SOFT_LIST, psoftlist) == -1) { 5657c478bd9Sstevel@tonic-gate cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed: %s", 5667c478bd9Sstevel@tonic-gate strerror(errno)); 5677c478bd9Sstevel@tonic-gate free(psoftlist); 5687c478bd9Sstevel@tonic-gate (void) close(fd); 5697c478bd9Sstevel@tonic-gate return (FAILURE); 5707c478bd9Sstevel@tonic-gate } 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate /* 5737c478bd9Sstevel@tonic-gate * if BUFFER is too small, get the number of software providers and 5747c478bd9Sstevel@tonic-gate * the minimum length needed for names and length and retry it. 5757c478bd9Sstevel@tonic-gate */ 5767c478bd9Sstevel@tonic-gate if (psoftlist->sl_return_value == CRYPTO_BUFFER_TOO_SMALL) { 5777c478bd9Sstevel@tonic-gate count = psoftlist->sl_soft_count; 5787c478bd9Sstevel@tonic-gate len = psoftlist->sl_soft_len; 5797c478bd9Sstevel@tonic-gate free(psoftlist); 5807c478bd9Sstevel@tonic-gate psoftlist = malloc(sizeof (crypto_get_soft_list_t) + len); 5817c478bd9Sstevel@tonic-gate if (psoftlist == NULL) { 5827c478bd9Sstevel@tonic-gate cryptodebug("out of memory."); 5837c478bd9Sstevel@tonic-gate (void) close(fd); 5847c478bd9Sstevel@tonic-gate return (FAILURE); 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate psoftlist->sl_soft_names = (caddr_t)(psoftlist + 1); 5877c478bd9Sstevel@tonic-gate psoftlist->sl_soft_count = count; 5887c478bd9Sstevel@tonic-gate psoftlist->sl_soft_len = len; 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate if (ioctl(fd, CRYPTO_GET_SOFT_LIST, psoftlist) == -1) { 5917c478bd9Sstevel@tonic-gate cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed:" 5927c478bd9Sstevel@tonic-gate "%s", strerror(errno)); 5937c478bd9Sstevel@tonic-gate free(psoftlist); 5947c478bd9Sstevel@tonic-gate (void) close(fd); 5957c478bd9Sstevel@tonic-gate return (FAILURE); 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate if (psoftlist->sl_return_value != CRYPTO_SUCCESS) { 6007c478bd9Sstevel@tonic-gate cryptodebug("CRYPTO_GET_SOFT_LIST ioctl failed, " 6017c478bd9Sstevel@tonic-gate "return_value = %d", psoftlist->sl_return_value); 6027c478bd9Sstevel@tonic-gate free(psoftlist); 6037c478bd9Sstevel@tonic-gate (void) close(fd); 6047c478bd9Sstevel@tonic-gate return (FAILURE); 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate *ppsoftlist = psoftlist; 6087c478bd9Sstevel@tonic-gate (void) close(fd); 6097c478bd9Sstevel@tonic-gate return (SUCCESS); 6107c478bd9Sstevel@tonic-gate } 611