10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53089Swyllys  * Common Development and Distribution License (the "License").
63089Swyllys  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
227011Sda73024  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <cryptoutil.h>
270Sstevel@tonic-gate #include <fcntl.h>
280Sstevel@tonic-gate #include <libintl.h>
290Sstevel@tonic-gate #include <stdio.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <strings.h>
320Sstevel@tonic-gate #include <unistd.h>
330Sstevel@tonic-gate #include <errno.h>
340Sstevel@tonic-gate #include <dlfcn.h>
350Sstevel@tonic-gate #include <link.h>
360Sstevel@tonic-gate #include <sys/types.h>
370Sstevel@tonic-gate #include <sys/stat.h>
380Sstevel@tonic-gate #include <security/cryptoki.h>
390Sstevel@tonic-gate #include "cryptoadm.h"
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #define	HDR1 "                                     P\n"
420Sstevel@tonic-gate #define	HDR2 "                         S     V  K  a     U  D\n"
430Sstevel@tonic-gate #define	HDR3 "                         i     e  e  i     n  e\n"
440Sstevel@tonic-gate #define	HDR4 "                      S  g  V  r  y  r  W  w  r\n"
450Sstevel@tonic-gate #define	HDR5 "             E  D  D  i  n  e  i  G  G  r  r  i\n"
460Sstevel@tonic-gate #define	HDR6 "          H  n  e  i  g  +  r  +  e  e  a  a  v  E\n"
470Sstevel@tonic-gate #define	HDR7 "min  max  W  c  c  g  n  R  i  R  n  n  p  p  e  C\n"
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 
500Sstevel@tonic-gate static int err; /* To store errno which may be overwritten by gettext() */
510Sstevel@tonic-gate static boolean_t is_in_policylist(midstr_t, umechlist_t *);
520Sstevel@tonic-gate static char *uent2str(uentry_t *);
530Sstevel@tonic-gate static boolean_t check_random(CK_SLOT_ID, CK_FUNCTION_LIST_PTR);
540Sstevel@tonic-gate 
550Sstevel@tonic-gate static void display_slot_flags(CK_FLAGS flags)
560Sstevel@tonic-gate {
570Sstevel@tonic-gate 	(void) printf(gettext("Slot Flags: "));
580Sstevel@tonic-gate 	if (flags & CKF_TOKEN_PRESENT)
590Sstevel@tonic-gate 		(void) printf("CKF_TOKEN_PRESENT ");
600Sstevel@tonic-gate 	if (flags & CKF_REMOVABLE_DEVICE)
610Sstevel@tonic-gate 		(void) printf("CKF_REMOVABLE_DEVICE ");
620Sstevel@tonic-gate 	if (flags & CKF_HW_SLOT)
630Sstevel@tonic-gate 		(void) printf("CKF_HW_SLOT ");
640Sstevel@tonic-gate 	(void) printf("\n");
650Sstevel@tonic-gate }
660Sstevel@tonic-gate 
670Sstevel@tonic-gate void
680Sstevel@tonic-gate display_token_flags(CK_FLAGS flags)
690Sstevel@tonic-gate {
700Sstevel@tonic-gate 	(void) printf(gettext("Flags: "));
710Sstevel@tonic-gate 	if (flags & CKF_RNG)
720Sstevel@tonic-gate 		(void) printf("CKF_RNG ");
730Sstevel@tonic-gate 	if (flags & CKF_WRITE_PROTECTED)
740Sstevel@tonic-gate 		(void) printf("CKF_WRITE_PROTECTED ");
750Sstevel@tonic-gate 	if (flags & CKF_LOGIN_REQUIRED)
760Sstevel@tonic-gate 		(void) printf("CKF_LOGIN_REQUIRED ");
770Sstevel@tonic-gate 	if (flags & CKF_USER_PIN_INITIALIZED)
780Sstevel@tonic-gate 		(void) printf("CKF_USER_PIN_INITIALIZED ");
790Sstevel@tonic-gate 	if (flags & CKF_RESTORE_KEY_NOT_NEEDED)
800Sstevel@tonic-gate 		(void) printf("CKF_RESTORE_KEY_NOT_NEEDED ");
810Sstevel@tonic-gate 	if (flags & CKF_CLOCK_ON_TOKEN)
820Sstevel@tonic-gate 		(void) printf("CKF_CLOCK_ON_TOKEN ");
830Sstevel@tonic-gate 	if (flags & CKF_PROTECTED_AUTHENTICATION_PATH)
840Sstevel@tonic-gate 		(void) printf("CKF_PROTECTED_AUTHENTICATION_PATH ");
850Sstevel@tonic-gate 	if (flags & CKF_DUAL_CRYPTO_OPERATIONS)
860Sstevel@tonic-gate 		(void) printf("CKF_DUAL_CRYPTO_OPERATIONS ");
870Sstevel@tonic-gate 	if (flags & CKF_TOKEN_INITIALIZED)
880Sstevel@tonic-gate 		(void) printf("CKF_TOKEN_INITIALIZED ");
890Sstevel@tonic-gate 	if (flags & CKF_SECONDARY_AUTHENTICATION)
900Sstevel@tonic-gate 		(void) printf("CKF_SECONDARY_AUTHENTICATION ");
910Sstevel@tonic-gate 	if (flags & CKF_USER_PIN_COUNT_LOW)
920Sstevel@tonic-gate 		(void) printf("CKF_USER_PIN_COUNT_LOW ");
930Sstevel@tonic-gate 	if (flags & CKF_USER_PIN_FINAL_TRY)
940Sstevel@tonic-gate 		(void) printf("CKF_USER_PIN_FINAL_TRY ");
950Sstevel@tonic-gate 	if (flags & CKF_USER_PIN_LOCKED)
960Sstevel@tonic-gate 		(void) printf("CKF_USER_PIN_LOCKED ");
970Sstevel@tonic-gate 	if (flags & CKF_USER_PIN_TO_BE_CHANGED)
980Sstevel@tonic-gate 		(void) printf("CKF_USER_PIN_TO_BE_CHANGED ");
990Sstevel@tonic-gate 	if (flags & CKF_SO_PIN_COUNT_LOW)
1000Sstevel@tonic-gate 		(void) printf("CKF_SO_PIN_COUNT_LOW ");
1010Sstevel@tonic-gate 	if (flags & CKF_SO_PIN_FINAL_TRY)
1020Sstevel@tonic-gate 		(void) printf("CKF_SO_PIN_FINAL_TRY ");
1030Sstevel@tonic-gate 	if (flags & CKF_SO_PIN_LOCKED)
1040Sstevel@tonic-gate 		(void) printf("CKF_SO_PIN_LOCKED ");
1050Sstevel@tonic-gate 	if (flags & CKF_SO_PIN_TO_BE_CHANGED)
1060Sstevel@tonic-gate 		(void) printf("CKF_SO_PIN_TO_BE_CHANGED ");
1070Sstevel@tonic-gate 	if (flags & CKF_SO_PIN_TO_BE_CHANGED)
1080Sstevel@tonic-gate 		(void) printf("CKF_SO_PIN_TO_BE_CHANGED ");
1090Sstevel@tonic-gate 	(void) printf("\n");
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate void
1130Sstevel@tonic-gate display_mech_info(CK_MECHANISM_INFO *mechInfo)
1140Sstevel@tonic-gate {
1150Sstevel@tonic-gate 	CK_FLAGS ec_flags = CKF_EC_F_P | CKF_EC_F_2M | CKF_EC_ECPARAMETERS |
1167011Sda73024 	    CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS | CKF_EC_COMPRESS;
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 	(void) printf("%-4ld %-4ld ", mechInfo->ulMinKeySize,
1197011Sda73024 	    mechInfo->ulMaxKeySize);
1200Sstevel@tonic-gate 	(void) printf("%s  %s  %s  %s  %s  %s  %s  %s  %s  %s  %s  %s  "
1217011Sda73024 	    "%s  %s",
1227011Sda73024 	    (mechInfo->flags & CKF_HW) ? "X" : ".",
1237011Sda73024 	    (mechInfo->flags & CKF_ENCRYPT) ? "X" : ".",
1247011Sda73024 	    (mechInfo->flags & CKF_DECRYPT) ? "X" : ".",
1257011Sda73024 	    (mechInfo->flags & CKF_DIGEST) ? "X" : ".",
1267011Sda73024 	    (mechInfo->flags & CKF_SIGN) ? "X" : ".",
1277011Sda73024 	    (mechInfo->flags & CKF_SIGN_RECOVER) ? "X" : ".",
1287011Sda73024 	    (mechInfo->flags & CKF_VERIFY) ? "X" : ".",
1297011Sda73024 	    (mechInfo->flags & CKF_VERIFY_RECOVER) ? "X" : ".",
1307011Sda73024 	    (mechInfo->flags & CKF_GENERATE) ? "X" : ".",
1317011Sda73024 	    (mechInfo->flags & CKF_GENERATE_KEY_PAIR) ? "X" : ".",
1327011Sda73024 	    (mechInfo->flags & CKF_WRAP) ? "X" : ".",
1337011Sda73024 	    (mechInfo->flags & CKF_UNWRAP) ? "X" : ".",
1347011Sda73024 	    (mechInfo->flags & CKF_DERIVE) ? "X" : ".",
1357011Sda73024 	    (mechInfo->flags & ec_flags) ? "X" : ".");
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate /*
1390Sstevel@tonic-gate  * Converts the provided list of mechanism names in their string format to
1407011Sda73024  * their corresponding PKCS#11 mechanism IDs.
1410Sstevel@tonic-gate  *
1420Sstevel@tonic-gate  * The list of mechanism names to be converted is provided in the
1430Sstevel@tonic-gate  * "mlist" argument.  The list of converted mechanism IDs is returned
1440Sstevel@tonic-gate  * in the "pmech_list" argument.
1450Sstevel@tonic-gate  *
1460Sstevel@tonic-gate  * This function is called by list_metaslot_info() and
1470Sstevel@tonic-gate  * list_mechlist_for_lib() functions.
1480Sstevel@tonic-gate  */
1490Sstevel@tonic-gate int
1500Sstevel@tonic-gate convert_mechlist(CK_MECHANISM_TYPE **pmech_list, CK_ULONG *mech_count,
1510Sstevel@tonic-gate     mechlist_t *mlist)
1520Sstevel@tonic-gate {
1530Sstevel@tonic-gate 	int i, n = 0;
1540Sstevel@tonic-gate 	mechlist_t *p = mlist;
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	while (p != NULL) {
1570Sstevel@tonic-gate 		p = p->next;
1580Sstevel@tonic-gate 		n++;
1590Sstevel@tonic-gate 	}
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	*pmech_list = malloc(n * sizeof (CK_MECHANISM_TYPE));
1620Sstevel@tonic-gate 	if (pmech_list == NULL) {
1630Sstevel@tonic-gate 		cryptodebug("out of memory");
1640Sstevel@tonic-gate 		return (FAILURE);
1650Sstevel@tonic-gate 	}
1660Sstevel@tonic-gate 	p = mlist;
1670Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
1680Sstevel@tonic-gate 		if (pkcs11_str2mech(p->name, &(*pmech_list[i])) != CKR_OK) {
1690Sstevel@tonic-gate 			free(*pmech_list);
1700Sstevel@tonic-gate 			return (FAILURE);
1710Sstevel@tonic-gate 		}
1720Sstevel@tonic-gate 		p = p->next;
1730Sstevel@tonic-gate 	}
1740Sstevel@tonic-gate 	*mech_count = n;
1750Sstevel@tonic-gate 	return (SUCCESS);
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate /*
1790Sstevel@tonic-gate  * Display the mechanism list for a user-level library
1800Sstevel@tonic-gate  */
1810Sstevel@tonic-gate int
1820Sstevel@tonic-gate list_mechlist_for_lib(char *libname, mechlist_t *mlist,
1830Sstevel@tonic-gate 		flag_val_t *rng_flag, boolean_t no_warn,
1840Sstevel@tonic-gate 		boolean_t verbose, boolean_t show_mechs)
1850Sstevel@tonic-gate {
1860Sstevel@tonic-gate 	CK_RV	rv = CKR_OK;
1870Sstevel@tonic-gate 	CK_RV	(*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR);
1880Sstevel@tonic-gate 	CK_FUNCTION_LIST_PTR	prov_funcs; /* Provider's function list */
1890Sstevel@tonic-gate 	CK_SLOT_ID_PTR		prov_slots = NULL; /* Provider's slot list */
1900Sstevel@tonic-gate 	CK_MECHANISM_TYPE_PTR	pmech_list; /* mechanism list for a slot */
1910Sstevel@tonic-gate 	CK_SLOT_INFO	slotinfo;
1920Sstevel@tonic-gate 	CK_ULONG	slot_count;
1930Sstevel@tonic-gate 	CK_ULONG	mech_count;
1940Sstevel@tonic-gate 	uentry_t	*puent = NULL;
1957011Sda73024 	boolean_t	lib_initialized = B_FALSE;
1967011Sda73024 	void		*dldesc = NULL;
1977011Sda73024 	char		*dl_error;
1987011Sda73024 	const char 	*mech_name;
1997011Sda73024 	char		*isa;
2007011Sda73024 	char		libpath[MAXPATHLEN];
2017011Sda73024 	char		buf[MAXPATHLEN];
2027011Sda73024 	int		i, j;
2037011Sda73024 	int		rc = SUCCESS;
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	if (libname == NULL) {
2060Sstevel@tonic-gate 		/* should not happen */
2070Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
2080Sstevel@tonic-gate 		cryptodebug("list_mechlist_for_lib() - libname is NULL.");
2090Sstevel@tonic-gate 		return (FAILURE);
2100Sstevel@tonic-gate 	}
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 	/* Check if the library is in the pkcs11.conf file */
2130Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) == NULL) {
2140Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
2150Sstevel@tonic-gate 		    gettext("%s does not exist."), libname);
2160Sstevel@tonic-gate 		return (FAILURE);
2170Sstevel@tonic-gate 	}
2180Sstevel@tonic-gate 	free_uentry(puent);
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	/* Remove $ISA from the library name */
2210Sstevel@tonic-gate 	if (strlcpy(buf, libname, sizeof (buf)) >= sizeof (buf)) {
2220Sstevel@tonic-gate 		(void) printf(gettext("%s: the provider name is too long."),
2230Sstevel@tonic-gate 		    libname);
2240Sstevel@tonic-gate 		return (FAILURE);
2250Sstevel@tonic-gate 	}
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	if ((isa = strstr(buf, PKCS11_ISA)) != NULL) {
2280Sstevel@tonic-gate 		*isa = '\000';
2290Sstevel@tonic-gate 		isa += strlen(PKCS11_ISA);
2300Sstevel@tonic-gate 		(void) snprintf(libpath, MAXPATHLEN, "%s%s%s", buf, "/", isa);
2310Sstevel@tonic-gate 	} else {
2320Sstevel@tonic-gate 		(void) strlcpy(libpath, libname, sizeof (libpath));
2330Sstevel@tonic-gate 	}
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	/* Open the provider */
2360Sstevel@tonic-gate 	dldesc = dlopen(libpath, RTLD_NOW);
2370Sstevel@tonic-gate 	if (dldesc == NULL) {
2380Sstevel@tonic-gate 		dl_error = dlerror();
2390Sstevel@tonic-gate 		cryptodebug("Cannot load PKCS#11 library %s.  dlerror: %s",
2400Sstevel@tonic-gate 		    libname, dl_error != NULL ? dl_error : "Unknown");
2410Sstevel@tonic-gate 		rc = FAILURE;
2420Sstevel@tonic-gate 		goto clean_exit;
2430Sstevel@tonic-gate 	}
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	/* Get the pointer to provider's C_GetFunctionList() */
2460Sstevel@tonic-gate 	Tmp_C_GetFunctionList = (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList");
2470Sstevel@tonic-gate 	if (Tmp_C_GetFunctionList == NULL) {
2480Sstevel@tonic-gate 		cryptodebug("Cannot get the address of the C_GetFunctionList "
2490Sstevel@tonic-gate 		    "from %s", libname);
2500Sstevel@tonic-gate 		rc = FAILURE;
2510Sstevel@tonic-gate 		goto clean_exit;
2520Sstevel@tonic-gate 	}
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	/* Get the provider's function list */
2550Sstevel@tonic-gate 	rv = Tmp_C_GetFunctionList(&prov_funcs);
2560Sstevel@tonic-gate 	if (rv != CKR_OK) {
2570Sstevel@tonic-gate 		cryptodebug("failed to call C_GetFunctionList from %s",
2580Sstevel@tonic-gate 		    libname);
2590Sstevel@tonic-gate 		rc = FAILURE;
2600Sstevel@tonic-gate 		goto clean_exit;
2610Sstevel@tonic-gate 	}
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	/* Initialize this provider */
2640Sstevel@tonic-gate 	rv = prov_funcs->C_Initialize(NULL_PTR);
2650Sstevel@tonic-gate 	if (rv != CKR_OK) {
2660Sstevel@tonic-gate 		cryptodebug("failed to call C_Initialize from %s, "
2670Sstevel@tonic-gate 		    "return code = %d", libname, rv);
2680Sstevel@tonic-gate 		rc = FAILURE;
2690Sstevel@tonic-gate 		goto clean_exit;
2700Sstevel@tonic-gate 	} else {
2710Sstevel@tonic-gate 		lib_initialized = B_TRUE;
2720Sstevel@tonic-gate 	}
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	/*
2750Sstevel@tonic-gate 	 * Find out how many slots this provider has, call with tokenPresent
2760Sstevel@tonic-gate 	 * set to FALSE so all potential slots are returned.
2770Sstevel@tonic-gate 	 */
2780Sstevel@tonic-gate 	rv = prov_funcs->C_GetSlotList(FALSE, NULL_PTR, &slot_count);
2790Sstevel@tonic-gate 	if (rv != CKR_OK) {
2800Sstevel@tonic-gate 		cryptodebug("failed to get the slotlist from %s.", libname);
2810Sstevel@tonic-gate 		rc = FAILURE;
2820Sstevel@tonic-gate 		goto clean_exit;
2830Sstevel@tonic-gate 	} else if (slot_count == 0) {
2840Sstevel@tonic-gate 		if (!no_warn)
2850Sstevel@tonic-gate 			(void) printf(gettext("%s: no slots presented.\n"),
2867011Sda73024 			    libname);
2870Sstevel@tonic-gate 		rc = SUCCESS;
2880Sstevel@tonic-gate 		goto clean_exit;
2890Sstevel@tonic-gate 	}
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	/* Allocate memory for the slot list */
2920Sstevel@tonic-gate 	prov_slots = malloc(slot_count * sizeof (CK_SLOT_ID));
2930Sstevel@tonic-gate 	if (prov_slots == NULL) {
2940Sstevel@tonic-gate 		cryptodebug("out of memory.");
2950Sstevel@tonic-gate 		rc = FAILURE;
2960Sstevel@tonic-gate 		goto clean_exit;
2970Sstevel@tonic-gate 	}
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	/* Get the slot list from provider */
3000Sstevel@tonic-gate 	rv = prov_funcs->C_GetSlotList(FALSE, prov_slots, &slot_count);
3010Sstevel@tonic-gate 	if (rv != CKR_OK) {
3020Sstevel@tonic-gate 		cryptodebug("failed to call C_GetSlotList() from %s.",
3030Sstevel@tonic-gate 		    libname);
3040Sstevel@tonic-gate 		rc = FAILURE;
3050Sstevel@tonic-gate 		goto clean_exit;
3060Sstevel@tonic-gate 	}
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	if (verbose) {
3090Sstevel@tonic-gate 		(void) printf(gettext("Number of slots: %d\n"), slot_count);
3100Sstevel@tonic-gate 	}
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	/* Get the mechanism list for each slot */
3130Sstevel@tonic-gate 	for (i = 0; i < slot_count; i++) {
3140Sstevel@tonic-gate 		if (verbose)
3150Sstevel@tonic-gate 			/*
3160Sstevel@tonic-gate 			 * TRANSLATION_NOTE:
3170Sstevel@tonic-gate 			 * In some languages, the # symbol should be
3180Sstevel@tonic-gate 			 * converted to "no", an "n" followed by a
3190Sstevel@tonic-gate 			 * superscript "o"..
3200Sstevel@tonic-gate 			 */
3210Sstevel@tonic-gate 			(void) printf(gettext("\nSlot #%d\n"), i+1);
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 		if ((rng_flag != NULL) && (*rng_flag == NO_RNG)) {
3240Sstevel@tonic-gate 			if (check_random(prov_slots[i], prov_funcs)) {
3250Sstevel@tonic-gate 				*rng_flag = HAS_RNG;
3260Sstevel@tonic-gate 				rc = SUCCESS;
3270Sstevel@tonic-gate 				goto clean_exit;
3280Sstevel@tonic-gate 			} else
3290Sstevel@tonic-gate 				continue;
3300Sstevel@tonic-gate 		}
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 		rv = prov_funcs->C_GetSlotInfo(prov_slots[i], &slotinfo);
3330Sstevel@tonic-gate 		if (rv != CKR_OK) {
3340Sstevel@tonic-gate 			cryptodebug("failed to get slotinfo from %s", libname);
3350Sstevel@tonic-gate 			rc = FAILURE;
3360Sstevel@tonic-gate 			break;
3370Sstevel@tonic-gate 		}
3380Sstevel@tonic-gate 		if (verbose) {
3390Sstevel@tonic-gate 			CK_TOKEN_INFO tokeninfo;
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 			(void) printf(gettext("Description: %.64s\n"
3427011Sda73024 			    "Manufacturer: %.32s\n"
3437011Sda73024 			    "PKCS#11 Version: %d.%d\n"),
3447011Sda73024 			    slotinfo.slotDescription,
3457011Sda73024 			    slotinfo.manufacturerID,
3467011Sda73024 			    prov_funcs->version.major,
3477011Sda73024 			    prov_funcs->version.minor);
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 			(void) printf(gettext("Hardware Version: %d.%d\n"
3507011Sda73024 			    "Firmware Version: %d.%d\n"),
3517011Sda73024 			    slotinfo.hardwareVersion.major,
3527011Sda73024 			    slotinfo.hardwareVersion.minor,
3537011Sda73024 			    slotinfo.firmwareVersion.major,
3547011Sda73024 			    slotinfo.firmwareVersion.minor);
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 			(void) printf(gettext("Token Present: %s\n"),
3577011Sda73024 			    (slotinfo.flags & CKF_TOKEN_PRESENT ?
3587011Sda73024 			    gettext("True") : gettext("False")));
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 			display_slot_flags(slotinfo.flags);
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 			rv = prov_funcs->C_GetTokenInfo(prov_slots[i],
3637011Sda73024 			    &tokeninfo);
3640Sstevel@tonic-gate 			if (rv != CKR_OK) {
3650Sstevel@tonic-gate 				cryptodebug("Failed to get "
3667011Sda73024 				    "token info from %s", libname);
3670Sstevel@tonic-gate 				rc = FAILURE;
3680Sstevel@tonic-gate 				break;
3690Sstevel@tonic-gate 			}
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 			(void) printf(gettext("Token Label: %.32s\n"
3727011Sda73024 			    "Manufacturer ID: %.32s\n"
3737011Sda73024 			    "Model: %.16s\n"
3747011Sda73024 			    "Serial Number: %.16s\n"
3757011Sda73024 			    "Hardware Version: %d.%d\n"
3767011Sda73024 			    "Firmware Version: %d.%d\n"
3777011Sda73024 			    "UTC Time: %.16s\n"
378*7304SDarren.Moffat@Sun.COM 			    "PIN Min Length: %d\n"
379*7304SDarren.Moffat@Sun.COM 			    "PIN Max Length: %d\n"),
3807011Sda73024 			    tokeninfo.label,
3817011Sda73024 			    tokeninfo.manufacturerID,
3827011Sda73024 			    tokeninfo.model,
3837011Sda73024 			    tokeninfo.serialNumber,
3847011Sda73024 			    tokeninfo.hardwareVersion.major,
3857011Sda73024 			    tokeninfo.hardwareVersion.minor,
3867011Sda73024 			    tokeninfo.firmwareVersion.major,
3877011Sda73024 			    tokeninfo.firmwareVersion.minor,
3887011Sda73024 			    tokeninfo.utcTime,
3897011Sda73024 			    tokeninfo.ulMinPinLen,
3907011Sda73024 			    tokeninfo.ulMaxPinLen);
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 			display_token_flags(tokeninfo.flags);
3930Sstevel@tonic-gate 		}
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 		if (mlist == NULL) {
3960Sstevel@tonic-gate 			rv = prov_funcs->C_GetMechanismList(prov_slots[i],
3977011Sda73024 			    NULL_PTR, &mech_count);
3980Sstevel@tonic-gate 			if (rv != CKR_OK) {
3990Sstevel@tonic-gate 				cryptodebug(
4007011Sda73024 				    "failed to call C_GetMechanismList() "
4017011Sda73024 				    "from %s.", libname);
4020Sstevel@tonic-gate 				rc = FAILURE;
4030Sstevel@tonic-gate 				break;
4040Sstevel@tonic-gate 			}
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 			if (mech_count == 0) {
4070Sstevel@tonic-gate 				/* no mechanisms in this slot */
4080Sstevel@tonic-gate 				continue;
4090Sstevel@tonic-gate 			}
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 			pmech_list = malloc(mech_count *
4127011Sda73024 			    sizeof (CK_MECHANISM_TYPE));
4130Sstevel@tonic-gate 			if (pmech_list == NULL) {
4140Sstevel@tonic-gate 				cryptodebug("out of memory");
4150Sstevel@tonic-gate 				rc = FAILURE;
4160Sstevel@tonic-gate 				break;
4170Sstevel@tonic-gate 			}
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 			/* Get the actual mechanism list */
4200Sstevel@tonic-gate 			rv = prov_funcs->C_GetMechanismList(prov_slots[i],
4217011Sda73024 			    pmech_list, &mech_count);
4220Sstevel@tonic-gate 			if (rv != CKR_OK) {
4230Sstevel@tonic-gate 				cryptodebug(
4247011Sda73024 				    "failed to call C_GetMechanismList() "
4257011Sda73024 				    "from %s.", libname);
4260Sstevel@tonic-gate 				(void) free(pmech_list);
4270Sstevel@tonic-gate 				rc = FAILURE;
4280Sstevel@tonic-gate 				break;
4290Sstevel@tonic-gate 			}
4300Sstevel@tonic-gate 		} else  {
4310Sstevel@tonic-gate 			/* use the mechanism list passed in */
4320Sstevel@tonic-gate 			rc = convert_mechlist(&pmech_list, &mech_count, mlist);
4330Sstevel@tonic-gate 			if (rc != SUCCESS) {
4340Sstevel@tonic-gate 				goto clean_exit;
4350Sstevel@tonic-gate 			}
4360Sstevel@tonic-gate 		}
4370Sstevel@tonic-gate 		if (show_mechs)
4380Sstevel@tonic-gate 			(void) printf(gettext("Mechanisms:\n"));
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 		if (verbose && show_mechs) {
4410Sstevel@tonic-gate 			display_verbose_mech_header();
4420Sstevel@tonic-gate 		}
4430Sstevel@tonic-gate 		/*
4440Sstevel@tonic-gate 		 * Merge the current mechanism list into the returning
4450Sstevel@tonic-gate 		 * mechanism list.
4460Sstevel@tonic-gate 		 */
4470Sstevel@tonic-gate 		for (j = 0; show_mechs && j < mech_count; j++) {
4487011Sda73024 			CK_MECHANISM_TYPE	mech = pmech_list[j];
4497011Sda73024 
4507106Sda73024 			if (mech >= CKM_VENDOR_DEFINED) {
4517011Sda73024 				(void) printf("%#lx", mech);
4527011Sda73024 			} else {
4537011Sda73024 				mech_name = pkcs11_mech2str(mech);
4547011Sda73024 				(void) printf("%-29s", mech_name);
4557011Sda73024 			}
4567011Sda73024 
4570Sstevel@tonic-gate 			if (verbose) {
4580Sstevel@tonic-gate 				CK_MECHANISM_INFO mech_info;
4590Sstevel@tonic-gate 				rv = prov_funcs->C_GetMechanismInfo(
4607011Sda73024 				    prov_slots[i], mech, &mech_info);
4610Sstevel@tonic-gate 				if (rv != CKR_OK) {
4620Sstevel@tonic-gate 					cryptodebug(
4630Sstevel@tonic-gate 					    "failed to call "
4640Sstevel@tonic-gate 					    "C_GetMechanismInfo() from %s.",
4650Sstevel@tonic-gate 					    libname);
4660Sstevel@tonic-gate 					(void) free(pmech_list);
4670Sstevel@tonic-gate 					rc = FAILURE;
4680Sstevel@tonic-gate 					break;
4690Sstevel@tonic-gate 				}
4700Sstevel@tonic-gate 				display_mech_info(&mech_info);
4710Sstevel@tonic-gate 			}
4720Sstevel@tonic-gate 			(void) printf("\n");
4730Sstevel@tonic-gate 		}
4740Sstevel@tonic-gate 		(void) free(pmech_list);
4750Sstevel@tonic-gate 		if (rc == FAILURE) {
4760Sstevel@tonic-gate 			break;
4770Sstevel@tonic-gate 		}
4780Sstevel@tonic-gate 	}
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 	if (rng_flag != NULL || rc == FAILURE) {
4810Sstevel@tonic-gate 		goto clean_exit;
4820Sstevel@tonic-gate 	}
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate clean_exit:
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 	if (rc == FAILURE) {
4870Sstevel@tonic-gate 		(void) printf(gettext(
4880Sstevel@tonic-gate 		    "%s: failed to retrieve the mechanism list.\n"), libname);
4890Sstevel@tonic-gate 	}
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	if (lib_initialized) {
4920Sstevel@tonic-gate 		(void) prov_funcs->C_Finalize(NULL_PTR);
4930Sstevel@tonic-gate 	}
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 	if (dldesc != NULL) {
4960Sstevel@tonic-gate 		(void) dlclose(dldesc);
4970Sstevel@tonic-gate 	}
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 	if (prov_slots != NULL) {
5000Sstevel@tonic-gate 		(void) free(prov_slots);
5010Sstevel@tonic-gate 	}
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 	return (rc);
5040Sstevel@tonic-gate }
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate /*
5080Sstevel@tonic-gate  * Display the mechanism policy for a user-level library
5090Sstevel@tonic-gate  */
5100Sstevel@tonic-gate int
5110Sstevel@tonic-gate list_policy_for_lib(char *libname)
5120Sstevel@tonic-gate {
5130Sstevel@tonic-gate 	uentry_t *puent = NULL;
5140Sstevel@tonic-gate 	int rc;
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 	if (libname == NULL) {
5170Sstevel@tonic-gate 		/* should not happen */
5180Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
5190Sstevel@tonic-gate 		cryptodebug("list_policy_for_lib() - libname is NULL.");
5200Sstevel@tonic-gate 		return (FAILURE);
5210Sstevel@tonic-gate 	}
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 	/* Get the library entry from the pkcs11.conf file */
5240Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) == NULL) {
5250Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
5260Sstevel@tonic-gate 		    gettext("%s does not exist."), libname);
5270Sstevel@tonic-gate 		return (FAILURE);
5280Sstevel@tonic-gate 	}
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 	/* Print the policy for this library */
5310Sstevel@tonic-gate 	rc = print_uef_policy(puent);
5320Sstevel@tonic-gate 	free_uentry(puent);
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	return (rc);
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate /*
5390Sstevel@tonic-gate  * Disable mechanisms for a user-level library
5400Sstevel@tonic-gate  */
5410Sstevel@tonic-gate int
5420Sstevel@tonic-gate disable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag,
5430Sstevel@tonic-gate     mechlist_t *marglist)
5440Sstevel@tonic-gate {
5450Sstevel@tonic-gate 	uentry_t	*puent;
5460Sstevel@tonic-gate 	int	rc;
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate 	if (libname == NULL) {
5490Sstevel@tonic-gate 		/* should not happen */
5500Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
5510Sstevel@tonic-gate 		cryptodebug("disable_uef_lib() - libname is NULL.");
5520Sstevel@tonic-gate 		return (FAILURE);
5530Sstevel@tonic-gate 	}
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 	/* Get the provider entry from the pkcs11.conf file */
5560Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) == NULL) {
5570Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
5580Sstevel@tonic-gate 		    gettext("%s does not exist."), libname);
5590Sstevel@tonic-gate 		return (FAILURE);
5600Sstevel@tonic-gate 	}
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate 	/*
5630Sstevel@tonic-gate 	 * Update the mechanism policy of this library entry, based on
5640Sstevel@tonic-gate 	 * the current policy mode of the library and the mechanisms specified
5650Sstevel@tonic-gate 	 * in CLI.
5660Sstevel@tonic-gate 	 */
5670Sstevel@tonic-gate 	if (allflag) {
5680Sstevel@tonic-gate 		/*
5690Sstevel@tonic-gate 		 * If disabling all, just need to clean up the policylist and
5700Sstevel@tonic-gate 		 * set the flag_enabledlist flag to be B_TRUE.
5710Sstevel@tonic-gate 		 */
5720Sstevel@tonic-gate 		free_umechlist(puent->policylist);
5730Sstevel@tonic-gate 		puent->policylist = NULL;
5740Sstevel@tonic-gate 		puent->count = 0;
5750Sstevel@tonic-gate 		puent->flag_enabledlist = B_TRUE;
5760Sstevel@tonic-gate 		rc = SUCCESS;
5770Sstevel@tonic-gate 	} else if (marglist != NULL) {
5780Sstevel@tonic-gate 		if (puent->flag_enabledlist == B_TRUE) {
5790Sstevel@tonic-gate 			/*
5800Sstevel@tonic-gate 			 * The current default policy mode of this library
5810Sstevel@tonic-gate 			 * is "all are disabled, except ...", so if a
5820Sstevel@tonic-gate 			 * specified mechanism is in the exception list
5830Sstevel@tonic-gate 			 * (the policylist), delete it from the policylist.
5840Sstevel@tonic-gate 			 */
5850Sstevel@tonic-gate 			rc = update_policylist(puent, marglist, DELETE_MODE);
5860Sstevel@tonic-gate 		} else {
5870Sstevel@tonic-gate 			/*
5880Sstevel@tonic-gate 			 * The current default policy mode of this library
5890Sstevel@tonic-gate 			 * is "all are enabled", so if a specified mechanism
5900Sstevel@tonic-gate 			 * is not in the exception list (policylist), add
5910Sstevel@tonic-gate 			 * it into the policylist.
5920Sstevel@tonic-gate 			 */
5930Sstevel@tonic-gate 			rc = update_policylist(puent, marglist, ADD_MODE);
5940Sstevel@tonic-gate 		}
5950Sstevel@tonic-gate 	} else if (!rndflag) {
5960Sstevel@tonic-gate 		/* should not happen */
5970Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
5980Sstevel@tonic-gate 		cryptodebug("disable_uef_lib() - wrong arguments.");
5990Sstevel@tonic-gate 		return (FAILURE);
6000Sstevel@tonic-gate 	}
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 	if (rndflag)
6030Sstevel@tonic-gate 		puent->flag_norandom = B_TRUE;
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate 	if (rc == FAILURE) {
6060Sstevel@tonic-gate 		free_uentry(puent);
6070Sstevel@tonic-gate 		return (FAILURE);
6080Sstevel@tonic-gate 	}
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 	/* Update the pkcs11.conf file with the updated entry */
6110Sstevel@tonic-gate 	rc = update_pkcs11conf(puent);
6120Sstevel@tonic-gate 	free_uentry(puent);
6130Sstevel@tonic-gate 	return (rc);
6140Sstevel@tonic-gate }
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate /*
6180Sstevel@tonic-gate  * Enable disabled mechanisms for a user-level library.
6190Sstevel@tonic-gate  */
6200Sstevel@tonic-gate int
6210Sstevel@tonic-gate enable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag,
6220Sstevel@tonic-gate     mechlist_t *marglist)
6230Sstevel@tonic-gate {
6240Sstevel@tonic-gate 	uentry_t	*puent;
6250Sstevel@tonic-gate 	int	rc = SUCCESS;
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 	if (libname == NULL) {
6280Sstevel@tonic-gate 		/* should not happen */
6290Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
6300Sstevel@tonic-gate 		cryptodebug("enable_uef_lib() - libname is NULL.");
6310Sstevel@tonic-gate 		return (FAILURE);
6320Sstevel@tonic-gate 	}
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate 	/* Get the provider entry from the pkcs11.conf file */
6350Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) == NULL) {
6360Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
6370Sstevel@tonic-gate 		    gettext("%s does not exist."), libname);
6380Sstevel@tonic-gate 		return (FAILURE);
6390Sstevel@tonic-gate 	}
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 	/*
6420Sstevel@tonic-gate 	 * Update the mechanism policy of this library entry, based on
6430Sstevel@tonic-gate 	 * the current policy mode of the library and the mechanisms
6440Sstevel@tonic-gate 	 * specified in CLI.
6450Sstevel@tonic-gate 	 */
6460Sstevel@tonic-gate 	if (allflag) {
6470Sstevel@tonic-gate 		/*
6480Sstevel@tonic-gate 		 * If enabling all, what needs to be done are cleaning up the
6490Sstevel@tonic-gate 		 * policylist and setting the "flag_enabledlist" flag to
6500Sstevel@tonic-gate 		 * B_FALSE.
6510Sstevel@tonic-gate 		 */
6520Sstevel@tonic-gate 		free_umechlist(puent->policylist);
6530Sstevel@tonic-gate 		puent->policylist = NULL;
6540Sstevel@tonic-gate 		puent->count = 0;
6550Sstevel@tonic-gate 		puent->flag_enabledlist = B_FALSE;
6560Sstevel@tonic-gate 		rc = SUCCESS;
6570Sstevel@tonic-gate 	} else if (marglist != NULL) {
6580Sstevel@tonic-gate 		if (puent->flag_enabledlist == B_TRUE) {
6590Sstevel@tonic-gate 			/*
6600Sstevel@tonic-gate 			 * The current default policy mode of this library
6610Sstevel@tonic-gate 			 * is "all are disabled, except ...", so if a
6620Sstevel@tonic-gate 			 * specified mechanism is not in the exception list
6630Sstevel@tonic-gate 			 * (policylist), add it.
6640Sstevel@tonic-gate 			 */
6650Sstevel@tonic-gate 			rc = update_policylist(puent, marglist, ADD_MODE);
6660Sstevel@tonic-gate 		} else {
6670Sstevel@tonic-gate 			/*
6680Sstevel@tonic-gate 			 * The current default policy mode of this library
6690Sstevel@tonic-gate 			 * is "all are enabled, except", so if a specified
6700Sstevel@tonic-gate 			 * mechanism is in the exception list (policylist),
6710Sstevel@tonic-gate 			 * delete it.
6720Sstevel@tonic-gate 			 */
6730Sstevel@tonic-gate 			rc = update_policylist(puent, marglist, DELETE_MODE);
6740Sstevel@tonic-gate 		}
6750Sstevel@tonic-gate 	} else if (!rndflag) {
6760Sstevel@tonic-gate 		/* should not come here */
6770Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
6780Sstevel@tonic-gate 		cryptodebug("enable_uef_lib() - wrong arguments.");
6790Sstevel@tonic-gate 		return (FAILURE);
6800Sstevel@tonic-gate 	}
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 	if (rndflag)
6830Sstevel@tonic-gate 		puent->flag_norandom = B_FALSE;
6840Sstevel@tonic-gate 
6850Sstevel@tonic-gate 	if (rc == FAILURE) {
6860Sstevel@tonic-gate 		free_uentry(puent);
6870Sstevel@tonic-gate 		return (FAILURE);
6880Sstevel@tonic-gate 	}
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate 	/* Update the pkcs11.conf file with the updated entry */
6910Sstevel@tonic-gate 	rc = update_pkcs11conf(puent);
6920Sstevel@tonic-gate 	free_uentry(puent);
6930Sstevel@tonic-gate 	return (rc);
6940Sstevel@tonic-gate }
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate /*
6980Sstevel@tonic-gate  * Install a user-level library.
6990Sstevel@tonic-gate  */
7000Sstevel@tonic-gate int
7010Sstevel@tonic-gate install_uef_lib(char *libname)
7020Sstevel@tonic-gate {
7030Sstevel@tonic-gate 	uentry_t	*puent;
7040Sstevel@tonic-gate 	struct stat 	statbuf;
7050Sstevel@tonic-gate 	boolean_t	found;
7060Sstevel@tonic-gate 	FILE	*pfile;
7070Sstevel@tonic-gate 	FILE	*pfile_tmp;
7080Sstevel@tonic-gate 	char	tmpfile_name[MAXPATHLEN];
7090Sstevel@tonic-gate 	char	libpath[MAXPATHLEN];
7100Sstevel@tonic-gate 	char	libbuf[MAXPATHLEN];
7110Sstevel@tonic-gate 	char	*isa;
7120Sstevel@tonic-gate 	char 	buffer[BUFSIZ];
7130Sstevel@tonic-gate 	char 	*ptr;
7140Sstevel@tonic-gate 	int	found_count;
7150Sstevel@tonic-gate 	int	rc = SUCCESS;
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 
7180Sstevel@tonic-gate 	if (libname == NULL) {
7190Sstevel@tonic-gate 		/* should not happen */
7200Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
7210Sstevel@tonic-gate 		cryptodebug("install_uef_lib() - libname is NULL.");
7220Sstevel@tonic-gate 		return (FAILURE);
7230Sstevel@tonic-gate 	}
7240Sstevel@tonic-gate 
7250Sstevel@tonic-gate 	/* Check if the provider already exists in the framework */
7260Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) != NULL) {
7270Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s exists already."),
7280Sstevel@tonic-gate 		    libname);
7290Sstevel@tonic-gate 		free_uentry(puent);
7300Sstevel@tonic-gate 		return (FAILURE);
7310Sstevel@tonic-gate 	}
7320Sstevel@tonic-gate 
7330Sstevel@tonic-gate 	/*
7340Sstevel@tonic-gate 	 * Check if the library exists in the system. if $ISA is in the
7350Sstevel@tonic-gate 	 * path, only check the 32bit version.
7360Sstevel@tonic-gate 	 */
7370Sstevel@tonic-gate 	if (strlcpy(libbuf, libname, MAXPATHLEN) >= MAXPATHLEN) {
7380Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
7390Sstevel@tonic-gate 		    gettext("the provider name is too long - %s"), libname);
7400Sstevel@tonic-gate 		return (FAILURE);
7410Sstevel@tonic-gate 	}
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 	if ((isa = strstr(libbuf, PKCS11_ISA)) != NULL) {
7440Sstevel@tonic-gate 		*isa = '\000';
7450Sstevel@tonic-gate 		isa += strlen(PKCS11_ISA);
7460Sstevel@tonic-gate 		(void) snprintf(libpath, sizeof (libpath), "%s%s%s", libbuf,
7470Sstevel@tonic-gate 		    "/", isa);
7480Sstevel@tonic-gate 	} else {
7490Sstevel@tonic-gate 		(void) strlcpy(libpath, libname, sizeof (libpath));
7500Sstevel@tonic-gate 	}
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 	/* Check if it is same as the framework library */
7530Sstevel@tonic-gate 	if (strcmp(libpath, UEF_FRAME_LIB) == 0) {
7540Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
7550Sstevel@tonic-gate 		    "The framework library %s can not be installed."),
7560Sstevel@tonic-gate 		    libname);
7570Sstevel@tonic-gate 		return (FAILURE);
7580Sstevel@tonic-gate 	}
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 	if (stat(libpath, &statbuf) != 0) {
7610Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s not found"), libname);
7620Sstevel@tonic-gate 		return (FAILURE);
7630Sstevel@tonic-gate 	}
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 	/* Need to add "\n" to libname for adding into the config file */
7660Sstevel@tonic-gate 	if (strlcat(libname, "\n", MAXPATHLEN) >= MAXPATHLEN) {
7670Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
7680Sstevel@tonic-gate 		    "can not install %s; the name is too long."), libname);
7690Sstevel@tonic-gate 		return (FAILURE);
7700Sstevel@tonic-gate 	}
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
7730Sstevel@tonic-gate 		err = errno;
7740Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
7750Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
7760Sstevel@tonic-gate 		    strerror(err));
7770Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
7780Sstevel@tonic-gate 		return (FAILURE);
7790Sstevel@tonic-gate 	}
7800Sstevel@tonic-gate 
7810Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
7820Sstevel@tonic-gate 		err = errno;
7830Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
7840Sstevel@tonic-gate 		    gettext("failed to lock the configuration - %s"),
7850Sstevel@tonic-gate 		    strerror(err));
7860Sstevel@tonic-gate 		(void) fclose(pfile);
7870Sstevel@tonic-gate 		return (FAILURE);
7880Sstevel@tonic-gate 	}
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 	/*
7910Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory.
7920Sstevel@tonic-gate 	 */
7930Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
7940Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
7950Sstevel@tonic-gate 		err = errno;
7960Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
7970Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
7980Sstevel@tonic-gate 		    strerror(err));
7990Sstevel@tonic-gate 		(void) fclose(pfile);
8000Sstevel@tonic-gate 		return (FAILURE);
8010Sstevel@tonic-gate 	}
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
8040Sstevel@tonic-gate 		err = errno;
8050Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
8060Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
8070Sstevel@tonic-gate 		(void) fclose(pfile);
8080Sstevel@tonic-gate 		return (FAILURE);
8090Sstevel@tonic-gate 	}
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 	/*
8120Sstevel@tonic-gate 	 * Loop thru the config file. If the file was reserved within a
8130Sstevel@tonic-gate 	 * package bracket, just uncomment it.  Other wise, append it at
8140Sstevel@tonic-gate 	 * the end.  The resulting file will be saved in the temp file first.
8150Sstevel@tonic-gate 	 */
8160Sstevel@tonic-gate 	found_count = 0;
8170Sstevel@tonic-gate 	rc = SUCCESS;
8180Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
8190Sstevel@tonic-gate 		found = B_FALSE;
8200Sstevel@tonic-gate 		if (buffer[0] == '#') {
8210Sstevel@tonic-gate 			ptr = buffer;
8220Sstevel@tonic-gate 			ptr++;
8230Sstevel@tonic-gate 			if (strcmp(libname, ptr) == 0) {
8240Sstevel@tonic-gate 				found = B_TRUE;
8250Sstevel@tonic-gate 				found_count++;
8260Sstevel@tonic-gate 			}
8270Sstevel@tonic-gate 		}
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate 		if (found == B_FALSE) {
8300Sstevel@tonic-gate 			if (fputs(buffer, pfile_tmp) == EOF) {
8310Sstevel@tonic-gate 				rc = FAILURE;
8320Sstevel@tonic-gate 			}
8330Sstevel@tonic-gate 		} else {
8340Sstevel@tonic-gate 			if (found_count == 1) {
8350Sstevel@tonic-gate 				if (fputs(ptr, pfile_tmp) == EOF) {
8360Sstevel@tonic-gate 					rc = FAILURE;
8370Sstevel@tonic-gate 				}
8380Sstevel@tonic-gate 			} else {
8390Sstevel@tonic-gate 				/*
8400Sstevel@tonic-gate 				 * Found a second entry with #libname.
8410Sstevel@tonic-gate 				 * Should not happen. The pkcs11.conf file
8420Sstevel@tonic-gate 				 * is corrupted. Give a warning and skip
8430Sstevel@tonic-gate 				 * this entry.
8440Sstevel@tonic-gate 				 */
8450Sstevel@tonic-gate 				cryptoerror(LOG_STDERR, gettext(
8460Sstevel@tonic-gate 				    "(Warning) Found an additional reserved "
8470Sstevel@tonic-gate 				    "entry for %s."), libname);
8480Sstevel@tonic-gate 			}
8490Sstevel@tonic-gate 		}
8500Sstevel@tonic-gate 
8510Sstevel@tonic-gate 		if (rc == FAILURE) {
8520Sstevel@tonic-gate 			break;
8530Sstevel@tonic-gate 		}
8540Sstevel@tonic-gate 	}
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 	if (rc == FAILURE) {
8570Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("write error."));
8580Sstevel@tonic-gate 		(void) fclose(pfile);
8590Sstevel@tonic-gate 		(void) fclose(pfile_tmp);
8600Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
8610Sstevel@tonic-gate 			err = errno;
8620Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
8630Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"), tmpfile_name,
8640Sstevel@tonic-gate 			    strerror(err));
8650Sstevel@tonic-gate 		}
8660Sstevel@tonic-gate 		return (FAILURE);
8670Sstevel@tonic-gate 	}
8680Sstevel@tonic-gate 
8690Sstevel@tonic-gate 	if (found_count == 0) {
8700Sstevel@tonic-gate 		/*
8710Sstevel@tonic-gate 		 * This libname was not in package before, append it to the
8720Sstevel@tonic-gate 		 * end of the temp file.
8730Sstevel@tonic-gate 		 */
8740Sstevel@tonic-gate 		if (fputs(libname, pfile_tmp) == EOF) {
8750Sstevel@tonic-gate 			err = errno;
8760Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
8770Sstevel@tonic-gate 			    "failed to write to %s: %s"), tmpfile_name,
8780Sstevel@tonic-gate 			    strerror(err));
8790Sstevel@tonic-gate 			(void) fclose(pfile);
8800Sstevel@tonic-gate 			(void) fclose(pfile_tmp);
8810Sstevel@tonic-gate 			if (unlink(tmpfile_name) != 0) {
8820Sstevel@tonic-gate 				err = errno;
8830Sstevel@tonic-gate 				cryptoerror(LOG_STDERR, gettext(
8840Sstevel@tonic-gate 				    "(Warning) failed to remove %s: %s"),
8850Sstevel@tonic-gate 				    tmpfile_name, strerror(err));
8860Sstevel@tonic-gate 			}
8870Sstevel@tonic-gate 			return (FAILURE);
8880Sstevel@tonic-gate 		}
8890Sstevel@tonic-gate 	}
8900Sstevel@tonic-gate 
8910Sstevel@tonic-gate 	(void) fclose(pfile);
8920Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
8930Sstevel@tonic-gate 		err = errno;
8940Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8950Sstevel@tonic-gate 		    gettext("failed to close %s: %s"), tmpfile_name,
8960Sstevel@tonic-gate 		    strerror(err));
8970Sstevel@tonic-gate 		return (FAILURE);
8980Sstevel@tonic-gate 	}
8990Sstevel@tonic-gate 
9000Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
9010Sstevel@tonic-gate 		err = errno;
9020Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9030Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
9040Sstevel@tonic-gate 		    strerror(err));
9050Sstevel@tonic-gate 		cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
9060Sstevel@tonic-gate 		    _PATH_PKCS11_CONF, strerror(err));
9070Sstevel@tonic-gate 		rc = FAILURE;
9080Sstevel@tonic-gate 	} else if (chmod(_PATH_PKCS11_CONF,
9090Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
9100Sstevel@tonic-gate 		err = errno;
9110Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9120Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
9130Sstevel@tonic-gate 		    strerror(err));
9140Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
9150Sstevel@tonic-gate 		    strerror(err));
9160Sstevel@tonic-gate 		rc = FAILURE;
9170Sstevel@tonic-gate 	} else {
9180Sstevel@tonic-gate 		rc = SUCCESS;
9190Sstevel@tonic-gate 	}
9200Sstevel@tonic-gate 
9210Sstevel@tonic-gate 	if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
9220Sstevel@tonic-gate 		err = errno;
9230Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
9240Sstevel@tonic-gate 		    "(Warning) failed to remove %s: %s"), tmpfile_name,
9250Sstevel@tonic-gate 		    strerror(err));
9260Sstevel@tonic-gate 	}
9270Sstevel@tonic-gate 
9280Sstevel@tonic-gate 	return (rc);
9290Sstevel@tonic-gate }
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate 
9320Sstevel@tonic-gate /*
9330Sstevel@tonic-gate  * Uninstall a user-level library.
9340Sstevel@tonic-gate  */
9350Sstevel@tonic-gate int
9360Sstevel@tonic-gate uninstall_uef_lib(char *libname)
9370Sstevel@tonic-gate {
9380Sstevel@tonic-gate 	uentry_t	*puent;
9390Sstevel@tonic-gate 	FILE	*pfile;
9400Sstevel@tonic-gate 	FILE	*pfile_tmp;
9410Sstevel@tonic-gate 	char 	buffer[BUFSIZ];
9420Sstevel@tonic-gate 	char 	buffer2[BUFSIZ];
9430Sstevel@tonic-gate 	char	tmpfile_name[MAXPATHLEN];
9440Sstevel@tonic-gate 	char 	*name;
9450Sstevel@tonic-gate 	boolean_t	found;
9460Sstevel@tonic-gate 	boolean_t	in_package;
9470Sstevel@tonic-gate 	int	len;
9480Sstevel@tonic-gate 	int	rc = SUCCESS;
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 	if (libname == NULL) {
9510Sstevel@tonic-gate 		/* should not happen */
9520Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
9530Sstevel@tonic-gate 		cryptodebug("uninstall_uef_lib() - libname is NULL.");
9540Sstevel@tonic-gate 		return (FAILURE);
9550Sstevel@tonic-gate 	}
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate 	/* Check if the provider exists */
9580Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) == NULL) {
9590Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9600Sstevel@tonic-gate 		    gettext("%s does not exist."), libname);
9610Sstevel@tonic-gate 		return (FAILURE);
9620Sstevel@tonic-gate 	}
9630Sstevel@tonic-gate 	free_uentry(puent);
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate 	/*  Open the pkcs11.conf file and lock it */
9660Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
9670Sstevel@tonic-gate 		err = errno;
9680Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9690Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
9700Sstevel@tonic-gate 		    strerror(err));
9710Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
9720Sstevel@tonic-gate 		return (FAILURE);
9730Sstevel@tonic-gate 	}
9740Sstevel@tonic-gate 
9750Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
9760Sstevel@tonic-gate 		err = errno;
9770Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9780Sstevel@tonic-gate 		    gettext("failed to lock the configuration - %s"),
9790Sstevel@tonic-gate 		    strerror(err));
9800Sstevel@tonic-gate 		(void) fclose(pfile);
9810Sstevel@tonic-gate 		return (FAILURE);
9820Sstevel@tonic-gate 	}
9830Sstevel@tonic-gate 
9840Sstevel@tonic-gate 	/*
9850Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory to save
9860Sstevel@tonic-gate 	 * the new configuration file first.
9870Sstevel@tonic-gate 	 */
9880Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
9890Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
9900Sstevel@tonic-gate 		err = errno;
9910Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9920Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
9930Sstevel@tonic-gate 		    strerror(err));
9940Sstevel@tonic-gate 		(void) fclose(pfile);
9950Sstevel@tonic-gate 		return (FAILURE);
9960Sstevel@tonic-gate 	}
9970Sstevel@tonic-gate 
9980Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
9990Sstevel@tonic-gate 		err = errno;
10000Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
10010Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
10020Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
10030Sstevel@tonic-gate 			err = errno;
10040Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
10050Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
10060Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
10070Sstevel@tonic-gate 		}
10080Sstevel@tonic-gate 		(void) fclose(pfile);
10090Sstevel@tonic-gate 		return (FAILURE);
10100Sstevel@tonic-gate 	}
10110Sstevel@tonic-gate 
10120Sstevel@tonic-gate 
10130Sstevel@tonic-gate 	/*
10140Sstevel@tonic-gate 	 * Loop thru the config file.  If the library to be uninstalled
10150Sstevel@tonic-gate 	 * is in a package, just comment it off.
10160Sstevel@tonic-gate 	 */
10170Sstevel@tonic-gate 	in_package = B_FALSE;
10180Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
10190Sstevel@tonic-gate 		found = B_FALSE;
10200Sstevel@tonic-gate 		if (!(buffer[0] == ' ' || buffer[0] == '\n' ||
10210Sstevel@tonic-gate 		    buffer[0] == '\t')) {
10220Sstevel@tonic-gate 			if (strstr(buffer, " Start ") != NULL) {
10230Sstevel@tonic-gate 				in_package = B_TRUE;
10240Sstevel@tonic-gate 			} else if (strstr(buffer, " End ") != NULL) {
10250Sstevel@tonic-gate 				in_package = B_FALSE;
10260Sstevel@tonic-gate 			} else if (buffer[0] != '#') {
10270Sstevel@tonic-gate 				(void) strlcpy(buffer2, buffer, BUFSIZ);
10280Sstevel@tonic-gate 
10290Sstevel@tonic-gate 				/* get rid of trailing '\n' */
10300Sstevel@tonic-gate 				len = strlen(buffer2);
10310Sstevel@tonic-gate 				if (buffer2[len-1] == '\n') {
10320Sstevel@tonic-gate 					len--;
10330Sstevel@tonic-gate 				}
10340Sstevel@tonic-gate 				buffer2[len] = '\0';
10350Sstevel@tonic-gate 
10360Sstevel@tonic-gate 				if ((name = strtok(buffer2, SEP_COLON))
10370Sstevel@tonic-gate 				    == NULL) {
10380Sstevel@tonic-gate 					rc = FAILURE;
10390Sstevel@tonic-gate 					break;
10400Sstevel@tonic-gate 				} else if (strcmp(libname, name) == 0) {
10410Sstevel@tonic-gate 					found = B_TRUE;
10420Sstevel@tonic-gate 				}
10430Sstevel@tonic-gate 			}
10440Sstevel@tonic-gate 		}
10450Sstevel@tonic-gate 
10460Sstevel@tonic-gate 		if (found) {
10470Sstevel@tonic-gate 			if (in_package) {
10480Sstevel@tonic-gate 				(void) snprintf(buffer2, sizeof (buffer2),
10490Sstevel@tonic-gate 				    "%s%s%s", "#", libname, "\n");
10500Sstevel@tonic-gate 				if (fputs(buffer2, pfile_tmp) == EOF) {
10510Sstevel@tonic-gate 					rc = FAILURE;
10520Sstevel@tonic-gate 				}
10530Sstevel@tonic-gate 			}
10540Sstevel@tonic-gate 		} else {
10550Sstevel@tonic-gate 			if (fputs(buffer, pfile_tmp) == EOF) {
10560Sstevel@tonic-gate 				rc = FAILURE;
10570Sstevel@tonic-gate 			}
10580Sstevel@tonic-gate 		}
10590Sstevel@tonic-gate 
10600Sstevel@tonic-gate 		if (rc == FAILURE) {
10610Sstevel@tonic-gate 			break;
10620Sstevel@tonic-gate 		}
10630Sstevel@tonic-gate 	}
10640Sstevel@tonic-gate 
10650Sstevel@tonic-gate 	if (rc == FAILURE) {
10660Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("write error."));
10670Sstevel@tonic-gate 		(void) fclose(pfile);
10680Sstevel@tonic-gate 		(void) fclose(pfile_tmp);
10690Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
10700Sstevel@tonic-gate 			err = errno;
10710Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
10720Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
10730Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
10740Sstevel@tonic-gate 		}
10750Sstevel@tonic-gate 		return (FAILURE);
10760Sstevel@tonic-gate 	}
10770Sstevel@tonic-gate 
10780Sstevel@tonic-gate 	(void) fclose(pfile);
10790Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
10800Sstevel@tonic-gate 		err = errno;
10810Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
10820Sstevel@tonic-gate 		    gettext("failed to close a temporary file - %s"),
10830Sstevel@tonic-gate 		    strerror(err));
10840Sstevel@tonic-gate 		return (FAILURE);
10850Sstevel@tonic-gate 	}
10860Sstevel@tonic-gate 
10870Sstevel@tonic-gate 	/* Now update the real config file */
10880Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
10890Sstevel@tonic-gate 		err = errno;
10900Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
10910Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
10920Sstevel@tonic-gate 		    strerror(err));
10930Sstevel@tonic-gate 		cryptodebug("failed to rename %s to %s: %s", tmpfile,
10940Sstevel@tonic-gate 		    _PATH_PKCS11_CONF, strerror(err));
10950Sstevel@tonic-gate 		rc = FAILURE;
10960Sstevel@tonic-gate 	} else if (chmod(_PATH_PKCS11_CONF,
10970Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
10980Sstevel@tonic-gate 		err = errno;
10990Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
11000Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
11010Sstevel@tonic-gate 		    strerror(err));
11020Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
11030Sstevel@tonic-gate 		    strerror(err));
11040Sstevel@tonic-gate 		rc = FAILURE;
11050Sstevel@tonic-gate 	} else {
11060Sstevel@tonic-gate 		rc = SUCCESS;
11070Sstevel@tonic-gate 	}
11080Sstevel@tonic-gate 
11090Sstevel@tonic-gate 	if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
11100Sstevel@tonic-gate 		err = errno;
11110Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
11120Sstevel@tonic-gate 		    "(Warning) failed to remove %s: %s"),
11130Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
11140Sstevel@tonic-gate 	}
11150Sstevel@tonic-gate 
11160Sstevel@tonic-gate 	return (rc);
11170Sstevel@tonic-gate }
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate 
11200Sstevel@tonic-gate int
11210Sstevel@tonic-gate display_policy(uentry_t *puent)
11220Sstevel@tonic-gate {
11237011Sda73024 	CK_MECHANISM_TYPE	mech_id;
11247011Sda73024 	const char		*mech_name;
11257011Sda73024 	umechlist_t		*ptr;
11260Sstevel@tonic-gate 
11270Sstevel@tonic-gate 	if (puent == NULL) {
11280Sstevel@tonic-gate 		return (SUCCESS);
11290Sstevel@tonic-gate 	}
11300Sstevel@tonic-gate 
11310Sstevel@tonic-gate 	if (puent->flag_enabledlist == B_FALSE) {
11320Sstevel@tonic-gate 		(void) printf(gettext("%s: all mechanisms are enabled"),
11330Sstevel@tonic-gate 		    puent->name);
11340Sstevel@tonic-gate 		ptr = puent->policylist;
11350Sstevel@tonic-gate 		if (ptr == NULL) {
11360Sstevel@tonic-gate 			(void) printf(".");
11370Sstevel@tonic-gate 		} else {
11380Sstevel@tonic-gate 			(void) printf(gettext(", except "));
11390Sstevel@tonic-gate 			while (ptr != NULL) {
11400Sstevel@tonic-gate 				mech_id = strtoul(ptr->name, NULL, 0);
11410Sstevel@tonic-gate 				if (mech_id & CKO_VENDOR_DEFINED) {
11420Sstevel@tonic-gate 					/* vendor defined mechanism */
11430Sstevel@tonic-gate 					(void) printf("%s", ptr->name);
11440Sstevel@tonic-gate 				} else {
11457106Sda73024 					if (mech_id >= CKM_VENDOR_DEFINED) {
11467011Sda73024 						(void) printf("%#lx", mech_id);
11477011Sda73024 					} else {
11487011Sda73024 						mech_name = pkcs11_mech2str(
11497011Sda73024 						    mech_id);
11507011Sda73024 						if (mech_name == NULL) {
11517011Sda73024 							return (FAILURE);
11527011Sda73024 						}
11537011Sda73024 						(void) printf("%s", mech_name);
11540Sstevel@tonic-gate 					}
11550Sstevel@tonic-gate 				}
11560Sstevel@tonic-gate 
11570Sstevel@tonic-gate 				ptr = ptr->next;
11580Sstevel@tonic-gate 				if (ptr == NULL) {
11590Sstevel@tonic-gate 					(void) printf(".");
11600Sstevel@tonic-gate 				} else {
11610Sstevel@tonic-gate 					(void) printf(",");
11620Sstevel@tonic-gate 				}
11630Sstevel@tonic-gate 			}
11640Sstevel@tonic-gate 		}
11650Sstevel@tonic-gate 	} else { /* puent->flag_enabledlist == B_TRUE */
11660Sstevel@tonic-gate 		(void) printf(gettext("%s: all mechanisms are disabled"),
11670Sstevel@tonic-gate 		    puent->name);
11680Sstevel@tonic-gate 		ptr = puent->policylist;
11690Sstevel@tonic-gate 		if (ptr == NULL) {
11700Sstevel@tonic-gate 			(void) printf(".");
11710Sstevel@tonic-gate 		} else {
11720Sstevel@tonic-gate 			(void) printf(gettext(", except "));
11730Sstevel@tonic-gate 			while (ptr != NULL) {
11740Sstevel@tonic-gate 				mech_id = strtoul(ptr->name, NULL, 0);
11750Sstevel@tonic-gate 				if (mech_id & CKO_VENDOR_DEFINED) {
11760Sstevel@tonic-gate 					/* vendor defined mechanism */
11770Sstevel@tonic-gate 					(void) printf("%s", ptr->name);
11780Sstevel@tonic-gate 				} else {
11790Sstevel@tonic-gate 					mech_name = pkcs11_mech2str(mech_id);
11800Sstevel@tonic-gate 					if (mech_name == NULL) {
11810Sstevel@tonic-gate 						return (FAILURE);
11820Sstevel@tonic-gate 					}
11830Sstevel@tonic-gate 					(void) printf("%s", mech_name);
11840Sstevel@tonic-gate 				}
11850Sstevel@tonic-gate 				ptr = ptr->next;
11860Sstevel@tonic-gate 				if (ptr == NULL) {
11870Sstevel@tonic-gate 					(void) printf(".");
11880Sstevel@tonic-gate 				} else {
11890Sstevel@tonic-gate 					(void) printf(",");
11900Sstevel@tonic-gate 				}
11910Sstevel@tonic-gate 			}
11920Sstevel@tonic-gate 		}
11930Sstevel@tonic-gate 	}
11940Sstevel@tonic-gate 	return (SUCCESS);
11950Sstevel@tonic-gate }
11960Sstevel@tonic-gate 
11970Sstevel@tonic-gate 
11980Sstevel@tonic-gate 
11990Sstevel@tonic-gate /*
12000Sstevel@tonic-gate  * Print out the mechanism policy for a user-level provider pointed by puent.
12010Sstevel@tonic-gate  */
12020Sstevel@tonic-gate int
12030Sstevel@tonic-gate print_uef_policy(uentry_t *puent)
12040Sstevel@tonic-gate {
12050Sstevel@tonic-gate 	flag_val_t rng_flag;
12060Sstevel@tonic-gate 
12070Sstevel@tonic-gate 	if (puent == NULL) {
12080Sstevel@tonic-gate 		return (FAILURE);
12090Sstevel@tonic-gate 	}
12100Sstevel@tonic-gate 
12110Sstevel@tonic-gate 	rng_flag = NO_RNG;
12120Sstevel@tonic-gate 	if (list_mechlist_for_lib(puent->name, NULL, &rng_flag, B_TRUE,
12137011Sda73024 	    B_FALSE, B_FALSE) != SUCCESS) {
12140Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
12150Sstevel@tonic-gate 		    gettext("%s internal error."), puent->name);
12160Sstevel@tonic-gate 		return (FAILURE);
12170Sstevel@tonic-gate 	}
12180Sstevel@tonic-gate 
12190Sstevel@tonic-gate 	if (display_policy(puent) != SUCCESS) {
12200Sstevel@tonic-gate 		goto failed_exit;
12210Sstevel@tonic-gate 	}
12220Sstevel@tonic-gate 
12230Sstevel@tonic-gate 
12240Sstevel@tonic-gate 	if (puent->flag_norandom == B_TRUE)
12250Sstevel@tonic-gate 		/*
12260Sstevel@tonic-gate 		 * TRANSLATION_NOTE:
12270Sstevel@tonic-gate 		 * "random" is a keyword and not to be translated.
12280Sstevel@tonic-gate 		 */
12290Sstevel@tonic-gate 		(void) printf(gettext(" %s is disabled."), "random");
12300Sstevel@tonic-gate 	else {
12310Sstevel@tonic-gate 		if (rng_flag == HAS_RNG)
12320Sstevel@tonic-gate 			/*
12330Sstevel@tonic-gate 			 * TRANSLATION_NOTE:
12340Sstevel@tonic-gate 			 * "random" is a keyword and not to be translated.
12350Sstevel@tonic-gate 			 */
12360Sstevel@tonic-gate 			(void) printf(gettext(" %s is enabled."), "random");
12370Sstevel@tonic-gate 	}
12380Sstevel@tonic-gate 	(void) printf("\n");
12390Sstevel@tonic-gate 
12400Sstevel@tonic-gate 	return (SUCCESS);
12410Sstevel@tonic-gate 
12420Sstevel@tonic-gate failed_exit:
12430Sstevel@tonic-gate 
12440Sstevel@tonic-gate 	(void) printf(gettext("\nout of memory.\n"));
12450Sstevel@tonic-gate 	return (FAILURE);
12460Sstevel@tonic-gate }
12470Sstevel@tonic-gate 
12480Sstevel@tonic-gate 
12490Sstevel@tonic-gate /*
12500Sstevel@tonic-gate  * Check if the mechanism is in the mechanism list.
12510Sstevel@tonic-gate  */
12520Sstevel@tonic-gate static boolean_t
12530Sstevel@tonic-gate is_in_policylist(midstr_t mechname, umechlist_t *plist)
12540Sstevel@tonic-gate {
12550Sstevel@tonic-gate 	boolean_t found = B_FALSE;
12560Sstevel@tonic-gate 
12570Sstevel@tonic-gate 	if (mechname == NULL) {
12580Sstevel@tonic-gate 		return (B_FALSE);
12590Sstevel@tonic-gate 	}
12600Sstevel@tonic-gate 
12610Sstevel@tonic-gate 	while (plist != NULL) {
12620Sstevel@tonic-gate 		if (strcmp(plist->name, mechname) == 0) {
12630Sstevel@tonic-gate 			found = B_TRUE;
12640Sstevel@tonic-gate 			break;
12650Sstevel@tonic-gate 		}
12660Sstevel@tonic-gate 		plist = plist->next;
12670Sstevel@tonic-gate 	}
12680Sstevel@tonic-gate 
12690Sstevel@tonic-gate 	return (found);
12700Sstevel@tonic-gate }
12710Sstevel@tonic-gate 
12720Sstevel@tonic-gate 
12730Sstevel@tonic-gate /*
12740Sstevel@tonic-gate  * Update the pkcs11.conf file with the updated entry.
12750Sstevel@tonic-gate  */
12760Sstevel@tonic-gate int
12770Sstevel@tonic-gate update_pkcs11conf(uentry_t *puent)
12780Sstevel@tonic-gate {
12790Sstevel@tonic-gate 	FILE	*pfile;
12800Sstevel@tonic-gate 	FILE	*pfile_tmp;
12810Sstevel@tonic-gate 	char buffer[BUFSIZ];
12820Sstevel@tonic-gate 	char buffer2[BUFSIZ];
12830Sstevel@tonic-gate 	char tmpfile_name[MAXPATHLEN];
12840Sstevel@tonic-gate 	char *name;
12850Sstevel@tonic-gate 	char *str;
12860Sstevel@tonic-gate 	int len;
12870Sstevel@tonic-gate 	int rc = SUCCESS;
12880Sstevel@tonic-gate 	boolean_t found;
12890Sstevel@tonic-gate 
12900Sstevel@tonic-gate 	if (puent == NULL) {
12910Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
12920Sstevel@tonic-gate 		return (FAILURE);
12930Sstevel@tonic-gate 	}
12940Sstevel@tonic-gate 
12950Sstevel@tonic-gate 	/* Open the pkcs11.conf file */
12960Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
12970Sstevel@tonic-gate 		err = errno;
12980Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
12990Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
13000Sstevel@tonic-gate 		    strerror(err));
13010Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
13020Sstevel@tonic-gate 		return (FAILURE);
13030Sstevel@tonic-gate 	}
13040Sstevel@tonic-gate 
13050Sstevel@tonic-gate 	/* Lock the pkcs11.conf file */
13060Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
13070Sstevel@tonic-gate 		err = errno;
13080Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
13090Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
13107011Sda73024 		    strerror(err));
13110Sstevel@tonic-gate 		(void) fclose(pfile);
13120Sstevel@tonic-gate 		return (FAILURE);
13130Sstevel@tonic-gate 	}
13140Sstevel@tonic-gate 
13150Sstevel@tonic-gate 	/*
13160Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory to save
13170Sstevel@tonic-gate 	 * updated configuration file first.
13180Sstevel@tonic-gate 	 */
13190Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
13200Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
13210Sstevel@tonic-gate 		err = errno;
13220Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
13230Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
13240Sstevel@tonic-gate 		    strerror(err));
13250Sstevel@tonic-gate 		(void) fclose(pfile);
13260Sstevel@tonic-gate 		return (FAILURE);
13270Sstevel@tonic-gate 	}
13280Sstevel@tonic-gate 
13290Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
13300Sstevel@tonic-gate 		err = errno;
13310Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
13320Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
13330Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
13340Sstevel@tonic-gate 			err = errno;
13350Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
13360Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
13370Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
13380Sstevel@tonic-gate 		}
13390Sstevel@tonic-gate 		(void) fclose(pfile);
13400Sstevel@tonic-gate 		return (FAILURE);
13410Sstevel@tonic-gate 	}
13420Sstevel@tonic-gate 
13430Sstevel@tonic-gate 
13440Sstevel@tonic-gate 	/*
13450Sstevel@tonic-gate 	 * Loop thru entire pkcs11.conf file, update the entry to be
13460Sstevel@tonic-gate 	 * updated and save the updated file to the temporary file first.
13470Sstevel@tonic-gate 	 */
13480Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
13490Sstevel@tonic-gate 		found = B_FALSE;
13500Sstevel@tonic-gate 		if (!(buffer[0] == '#' || buffer[0] == ' ' ||
13510Sstevel@tonic-gate 		    buffer[0] == '\n'|| buffer[0] == '\t')) {
13520Sstevel@tonic-gate 			/*
13530Sstevel@tonic-gate 			 * Get the provider name from this line and check if
13540Sstevel@tonic-gate 			 * this is the entry to be updated. Note: can not use
13550Sstevel@tonic-gate 			 * "buffer" directly because strtok will change its
13560Sstevel@tonic-gate 			 * value.
13570Sstevel@tonic-gate 			 */
13580Sstevel@tonic-gate 			(void) strlcpy(buffer2, buffer, BUFSIZ);
13590Sstevel@tonic-gate 
13600Sstevel@tonic-gate 			/* get rid of trailing '\n' */
13610Sstevel@tonic-gate 			len = strlen(buffer2);
13620Sstevel@tonic-gate 			if (buffer2[len-1] == '\n') {
13630Sstevel@tonic-gate 				len--;
13640Sstevel@tonic-gate 			}
13650Sstevel@tonic-gate 			buffer2[len] = '\0';
13660Sstevel@tonic-gate 
13670Sstevel@tonic-gate 			if ((name = strtok(buffer2, SEP_COLON)) == NULL) {
13680Sstevel@tonic-gate 				rc = FAILURE;
13690Sstevel@tonic-gate 				break;
13700Sstevel@tonic-gate 			} else if (strcmp(puent->name, name) == 0) {
13710Sstevel@tonic-gate 				found = B_TRUE;
13720Sstevel@tonic-gate 			}
13730Sstevel@tonic-gate 		}
13740Sstevel@tonic-gate 
13750Sstevel@tonic-gate 		if (found) {
13760Sstevel@tonic-gate 			/*
13770Sstevel@tonic-gate 			 * This is the entry to be modified, get the updated
13780Sstevel@tonic-gate 			 * string.
13790Sstevel@tonic-gate 			 */
13800Sstevel@tonic-gate 			if ((str = uent2str(puent)) == NULL) {
13810Sstevel@tonic-gate 				rc = FAILURE;
13820Sstevel@tonic-gate 				break;
13830Sstevel@tonic-gate 			} else {
13840Sstevel@tonic-gate 				(void) strlcpy(buffer, str, BUFSIZ);
13850Sstevel@tonic-gate 				free(str);
13860Sstevel@tonic-gate 			}
13870Sstevel@tonic-gate 		}
13880Sstevel@tonic-gate 
13890Sstevel@tonic-gate 		if (fputs(buffer, pfile_tmp) == EOF) {
13900Sstevel@tonic-gate 			err = errno;
13910Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
13920Sstevel@tonic-gate 			    "failed to write to a temp file: %s."),
13930Sstevel@tonic-gate 			    strerror(err));
13940Sstevel@tonic-gate 			rc = FAILURE;
13950Sstevel@tonic-gate 			break;
13960Sstevel@tonic-gate 		}
13970Sstevel@tonic-gate 	}
13980Sstevel@tonic-gate 
13990Sstevel@tonic-gate 	if (rc == FAILURE) {
14000Sstevel@tonic-gate 		(void) fclose(pfile);
14010Sstevel@tonic-gate 		(void) fclose(pfile_tmp);
14020Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
14030Sstevel@tonic-gate 			err = errno;
14040Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
14050Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
14060Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
14070Sstevel@tonic-gate 		}
14080Sstevel@tonic-gate 		return (FAILURE);
14090Sstevel@tonic-gate 	}
14100Sstevel@tonic-gate 
14110Sstevel@tonic-gate 	(void) fclose(pfile);
14120Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
14130Sstevel@tonic-gate 		err = errno;
14140Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
14150Sstevel@tonic-gate 		    gettext("failed to close %s: %s"), tmpfile_name,
14160Sstevel@tonic-gate 		    strerror(err));
14170Sstevel@tonic-gate 		return (FAILURE);
14180Sstevel@tonic-gate 	}
14190Sstevel@tonic-gate 
14200Sstevel@tonic-gate 	/* Copy the temporary file to the pkcs11.conf file */
14210Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
14220Sstevel@tonic-gate 		err = errno;
14230Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
14240Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
14250Sstevel@tonic-gate 		    strerror(err));
14260Sstevel@tonic-gate 		cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
14270Sstevel@tonic-gate 		    _PATH_PKCS11_CONF, strerror(err));
14280Sstevel@tonic-gate 		rc = FAILURE;
14290Sstevel@tonic-gate 	} else if (chmod(_PATH_PKCS11_CONF,
14300Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
14310Sstevel@tonic-gate 		err = errno;
14320Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
14330Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
14340Sstevel@tonic-gate 		    strerror(err));
14350Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
14360Sstevel@tonic-gate 		    strerror(err));
14370Sstevel@tonic-gate 		rc = FAILURE;
14380Sstevel@tonic-gate 	} else {
14390Sstevel@tonic-gate 		rc = SUCCESS;
14400Sstevel@tonic-gate 	}
14410Sstevel@tonic-gate 
14420Sstevel@tonic-gate 	if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
14430Sstevel@tonic-gate 		err = errno;
14440Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
14450Sstevel@tonic-gate 		    "(Warning) failed to remove %s: %s"),
14460Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
14470Sstevel@tonic-gate 	}
14480Sstevel@tonic-gate 
14490Sstevel@tonic-gate 	return (rc);
14500Sstevel@tonic-gate }
14510Sstevel@tonic-gate 
14520Sstevel@tonic-gate 
14530Sstevel@tonic-gate /*
14540Sstevel@tonic-gate  * Convert an uentry to a character string
14550Sstevel@tonic-gate  */
14560Sstevel@tonic-gate static char *
14570Sstevel@tonic-gate uent2str(uentry_t *puent)
14580Sstevel@tonic-gate {
14590Sstevel@tonic-gate 	umechlist_t	*phead;
14600Sstevel@tonic-gate 	boolean_t tok1_present = B_FALSE;
14610Sstevel@tonic-gate 	char *buf;
14620Sstevel@tonic-gate 	char blank_buf[128];
14630Sstevel@tonic-gate 
14640Sstevel@tonic-gate 	if (puent == NULL) {
14650Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
14660Sstevel@tonic-gate 		return (NULL);
14670Sstevel@tonic-gate 	}
14680Sstevel@tonic-gate 
14690Sstevel@tonic-gate 	buf = malloc(BUFSIZ);
14700Sstevel@tonic-gate 	if (buf == NULL) {
14710Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("out of memory."));
14720Sstevel@tonic-gate 		return (NULL);
14730Sstevel@tonic-gate 	}
14740Sstevel@tonic-gate 
14750Sstevel@tonic-gate 	/* convert the library name */
14760Sstevel@tonic-gate 	if (strlcpy(buf, puent->name, BUFSIZ) >= BUFSIZ) {
14770Sstevel@tonic-gate 		free(buf);
14780Sstevel@tonic-gate 		return (NULL);
14790Sstevel@tonic-gate 	}
14800Sstevel@tonic-gate 
14810Sstevel@tonic-gate 
14820Sstevel@tonic-gate 	/* convert the enabledlist or the disabledlist */
14830Sstevel@tonic-gate 	if (puent->flag_enabledlist == B_TRUE) {
14840Sstevel@tonic-gate 		if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
14850Sstevel@tonic-gate 			free(buf);
14860Sstevel@tonic-gate 			return (NULL);
14870Sstevel@tonic-gate 		}
14880Sstevel@tonic-gate 
14890Sstevel@tonic-gate 		if (strlcat(buf, EF_ENABLED, BUFSIZ) >= BUFSIZ) {
14900Sstevel@tonic-gate 			free(buf);
14910Sstevel@tonic-gate 			return (NULL);
14920Sstevel@tonic-gate 		}
14930Sstevel@tonic-gate 
14940Sstevel@tonic-gate 		phead = puent->policylist;
14950Sstevel@tonic-gate 		while (phead != NULL) {
14960Sstevel@tonic-gate 			if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
14970Sstevel@tonic-gate 				free(buf);
14980Sstevel@tonic-gate 				return (NULL);
14990Sstevel@tonic-gate 			}
15000Sstevel@tonic-gate 
15010Sstevel@tonic-gate 			phead = phead->next;
15020Sstevel@tonic-gate 			if (phead != NULL) {
15030Sstevel@tonic-gate 				if (strlcat(buf, SEP_COMMA, BUFSIZ)
15040Sstevel@tonic-gate 				    >= BUFSIZ) {
15050Sstevel@tonic-gate 					free(buf);
15060Sstevel@tonic-gate 					return (NULL);
15070Sstevel@tonic-gate 				}
15080Sstevel@tonic-gate 			}
15090Sstevel@tonic-gate 		}
15100Sstevel@tonic-gate 		tok1_present = B_TRUE;
15110Sstevel@tonic-gate 	} else if (puent->policylist != NULL) {
15120Sstevel@tonic-gate 		if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
15130Sstevel@tonic-gate 			free(buf);
15140Sstevel@tonic-gate 			return (NULL);
15150Sstevel@tonic-gate 		}
15160Sstevel@tonic-gate 
15170Sstevel@tonic-gate 		if (strlcat(buf, EF_DISABLED, BUFSIZ) >= BUFSIZ) {
15180Sstevel@tonic-gate 			free(buf);
15190Sstevel@tonic-gate 			return (NULL);
15200Sstevel@tonic-gate 		}
15210Sstevel@tonic-gate 		phead = puent->policylist;
15220Sstevel@tonic-gate 		while (phead != NULL) {
15230Sstevel@tonic-gate 			if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
15240Sstevel@tonic-gate 				free(buf);
15250Sstevel@tonic-gate 				return (NULL);
15260Sstevel@tonic-gate 			}
15270Sstevel@tonic-gate 
15280Sstevel@tonic-gate 			phead = phead->next;
15290Sstevel@tonic-gate 			if (phead != NULL) {
15300Sstevel@tonic-gate 				if (strlcat(buf, SEP_COMMA, BUFSIZ)
15310Sstevel@tonic-gate 				    >= BUFSIZ) {
15320Sstevel@tonic-gate 					free(buf);
15330Sstevel@tonic-gate 					return (NULL);
15340Sstevel@tonic-gate 				}
15350Sstevel@tonic-gate 			}
15360Sstevel@tonic-gate 		}
15370Sstevel@tonic-gate 		tok1_present = B_TRUE;
15380Sstevel@tonic-gate 	}
15390Sstevel@tonic-gate 
15400Sstevel@tonic-gate 	if (puent->flag_norandom == B_TRUE) {
15410Sstevel@tonic-gate 		if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON),
15420Sstevel@tonic-gate 		    BUFSIZ) >= BUFSIZ) {
15430Sstevel@tonic-gate 			free(buf);
15440Sstevel@tonic-gate 			return (NULL);
15450Sstevel@tonic-gate 		}
15460Sstevel@tonic-gate 
15470Sstevel@tonic-gate 		if (strlcat(buf, EF_NORANDOM, BUFSIZ) >= BUFSIZ) {
15480Sstevel@tonic-gate 			free(buf);
15490Sstevel@tonic-gate 			return (NULL);
15500Sstevel@tonic-gate 		}
15510Sstevel@tonic-gate 	}
15520Sstevel@tonic-gate 
15530Sstevel@tonic-gate 	if (strcmp(puent->name, METASLOT_KEYWORD) == 0) {
15540Sstevel@tonic-gate 
15550Sstevel@tonic-gate 		/* write the metaslot_status= value */
15560Sstevel@tonic-gate 		if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON),
15570Sstevel@tonic-gate 		    BUFSIZ) >= BUFSIZ) {
15580Sstevel@tonic-gate 			free(buf);
15590Sstevel@tonic-gate 			return (NULL);
15600Sstevel@tonic-gate 		}
15610Sstevel@tonic-gate 
15620Sstevel@tonic-gate 		if (strlcat(buf, METASLOT_STATUS, BUFSIZ) >= BUFSIZ) {
15630Sstevel@tonic-gate 			free(buf);
15640Sstevel@tonic-gate 			return (NULL);
15650Sstevel@tonic-gate 		}
15660Sstevel@tonic-gate 
15670Sstevel@tonic-gate 		if (puent->flag_metaslot_enabled) {
15680Sstevel@tonic-gate 			if (strlcat(buf, METASLOT_ENABLED, BUFSIZ) >= BUFSIZ) {
15690Sstevel@tonic-gate 				free(buf);
15700Sstevel@tonic-gate 				return (NULL);
15710Sstevel@tonic-gate 			}
15720Sstevel@tonic-gate 		} else {
15730Sstevel@tonic-gate 			if (strlcat(buf, METASLOT_DISABLED, BUFSIZ)
15740Sstevel@tonic-gate 			    >= BUFSIZ) {
15750Sstevel@tonic-gate 				free(buf);
15760Sstevel@tonic-gate 				return (NULL);
15770Sstevel@tonic-gate 			}
15780Sstevel@tonic-gate 		}
15790Sstevel@tonic-gate 
15800Sstevel@tonic-gate 		if (!tok1_present) {
15810Sstevel@tonic-gate 			tok1_present = B_TRUE;
15820Sstevel@tonic-gate 		}
15830Sstevel@tonic-gate 
15840Sstevel@tonic-gate 		if (strlcat(buf, SEP_SEMICOLON, BUFSIZ) >= BUFSIZ) {
15850Sstevel@tonic-gate 			free(buf);
15860Sstevel@tonic-gate 			return (NULL);
15870Sstevel@tonic-gate 		}
15880Sstevel@tonic-gate 
15890Sstevel@tonic-gate 		if (strlcat(buf, METASLOT_AUTO_KEY_MIGRATE, BUFSIZ) >= BUFSIZ) {
15900Sstevel@tonic-gate 			free(buf);
15910Sstevel@tonic-gate 			return (NULL);
15920Sstevel@tonic-gate 		}
15930Sstevel@tonic-gate 
15940Sstevel@tonic-gate 		if (puent->flag_metaslot_auto_key_migrate) {
15950Sstevel@tonic-gate 			if (strlcat(buf, METASLOT_ENABLED, BUFSIZ) >= BUFSIZ) {
15960Sstevel@tonic-gate 				free(buf);
15970Sstevel@tonic-gate 				return (NULL);
15980Sstevel@tonic-gate 			}
15990Sstevel@tonic-gate 		} else {
16000Sstevel@tonic-gate 			if (strlcat(buf, METASLOT_DISABLED, BUFSIZ) >= BUFSIZ) {
16010Sstevel@tonic-gate 				free(buf);
16020Sstevel@tonic-gate 				return (NULL);
16030Sstevel@tonic-gate 			}
16040Sstevel@tonic-gate 		}
16050Sstevel@tonic-gate 
16060Sstevel@tonic-gate 		bzero(blank_buf, sizeof (blank_buf));
16070Sstevel@tonic-gate 
16080Sstevel@tonic-gate 		/* write metaslot_token= if specified */
16090Sstevel@tonic-gate 		if (memcmp(puent->metaslot_ks_token, blank_buf,
16100Sstevel@tonic-gate 		    TOKEN_LABEL_SIZE) != 0) {
16110Sstevel@tonic-gate 			/* write the metaslot_status= value */
16120Sstevel@tonic-gate 			if (strlcat(buf, (tok1_present ?
16130Sstevel@tonic-gate 			    SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) {
16140Sstevel@tonic-gate 				free(buf);
16150Sstevel@tonic-gate 				return (NULL);
16160Sstevel@tonic-gate 			}
16170Sstevel@tonic-gate 
16180Sstevel@tonic-gate 			if (strlcat(buf, METASLOT_TOKEN, BUFSIZ) >= BUFSIZ) {
16190Sstevel@tonic-gate 				free(buf);
16200Sstevel@tonic-gate 				return (NULL);
16210Sstevel@tonic-gate 			}
16220Sstevel@tonic-gate 
16230Sstevel@tonic-gate 			if (strlcat(buf,
16240Sstevel@tonic-gate 			    (const char *)puent->metaslot_ks_token, BUFSIZ)
16250Sstevel@tonic-gate 			    >= BUFSIZ) {
16260Sstevel@tonic-gate 				free(buf);
16270Sstevel@tonic-gate 				return (NULL);
16280Sstevel@tonic-gate 			}
16290Sstevel@tonic-gate 		}
16300Sstevel@tonic-gate 
16310Sstevel@tonic-gate 		/* write metaslot_slot= if specified */
16320Sstevel@tonic-gate 		if (memcmp(puent->metaslot_ks_slot, blank_buf,
16330Sstevel@tonic-gate 		    SLOT_DESCRIPTION_SIZE) != 0) {
16340Sstevel@tonic-gate 			/* write the metaslot_status= value */
16350Sstevel@tonic-gate 			if (strlcat(buf, (tok1_present ?
16360Sstevel@tonic-gate 			    SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) {
16370Sstevel@tonic-gate 				free(buf);
16380Sstevel@tonic-gate 				return (NULL);
16390Sstevel@tonic-gate 			}
16400Sstevel@tonic-gate 
16410Sstevel@tonic-gate 			if (strlcat(buf, METASLOT_SLOT, BUFSIZ) >= BUFSIZ) {
16420Sstevel@tonic-gate 				free(buf);
16430Sstevel@tonic-gate 				return (NULL);
16440Sstevel@tonic-gate 			}
16450Sstevel@tonic-gate 
16460Sstevel@tonic-gate 			if (strlcat(buf,
16470Sstevel@tonic-gate 			    (const char *)puent->metaslot_ks_slot, BUFSIZ)
16480Sstevel@tonic-gate 			    >= BUFSIZ) {
16490Sstevel@tonic-gate 				free(buf);
16500Sstevel@tonic-gate 				return (NULL);
16510Sstevel@tonic-gate 			}
16520Sstevel@tonic-gate 		}
16530Sstevel@tonic-gate 	}
16540Sstevel@tonic-gate 
16550Sstevel@tonic-gate 	if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) {
16560Sstevel@tonic-gate 		free(buf);
16570Sstevel@tonic-gate 		return (NULL);
16580Sstevel@tonic-gate 	}
16590Sstevel@tonic-gate 
16600Sstevel@tonic-gate 	return (buf);
16610Sstevel@tonic-gate }
16620Sstevel@tonic-gate 
16630Sstevel@tonic-gate 
16640Sstevel@tonic-gate /*
16650Sstevel@tonic-gate  * This function updates the default policy mode and the policy exception list
16660Sstevel@tonic-gate  * for a user-level provider based on the mechanism specified in the disable
16670Sstevel@tonic-gate  * or enable subcommand and the update mode.   This function is called by the
16680Sstevel@tonic-gate  * enable_uef_lib() or disable_uef_lib().
16690Sstevel@tonic-gate  */
16700Sstevel@tonic-gate int
16710Sstevel@tonic-gate update_policylist(uentry_t *puent, mechlist_t *marglist, int update_mode)
16720Sstevel@tonic-gate {
16730Sstevel@tonic-gate 	CK_MECHANISM_TYPE mech_type;
16740Sstevel@tonic-gate 	midstr_t	midname;
16750Sstevel@tonic-gate 	umechlist_t	*phead;
16760Sstevel@tonic-gate 	umechlist_t	*pcur;
16770Sstevel@tonic-gate 	umechlist_t	*pumech;
16780Sstevel@tonic-gate 	boolean_t	found;
16790Sstevel@tonic-gate 	int	rc = SUCCESS;
16800Sstevel@tonic-gate 
16810Sstevel@tonic-gate 	if ((puent == NULL) || (marglist == NULL)) {
16820Sstevel@tonic-gate 		/* should not happen */
16830Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
16840Sstevel@tonic-gate 		cryptodebug("update_policylist()- puent or marglist is NULL.");
16850Sstevel@tonic-gate 		return (FAILURE);
16860Sstevel@tonic-gate 	}
16870Sstevel@tonic-gate 
16880Sstevel@tonic-gate 	if ((update_mode != ADD_MODE) && (update_mode != DELETE_MODE)) {
16890Sstevel@tonic-gate 		/* should not happen */
16900Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
16910Sstevel@tonic-gate 		cryptodebug("update_policylist() - update_mode is incorrect.");
16920Sstevel@tonic-gate 		return (FAILURE);
16930Sstevel@tonic-gate 	}
16940Sstevel@tonic-gate 
16950Sstevel@tonic-gate 	/*
16960Sstevel@tonic-gate 	 * For each mechanism operand, get its mechanism type first.
16970Sstevel@tonic-gate 	 * If fails to get the mechanism type, the mechanism operand must be
16980Sstevel@tonic-gate 	 * invalid, gives an warning and ignore it. Otherwise,
16990Sstevel@tonic-gate 	 * - convert the mechanism type to the internal representation (hex)
17000Sstevel@tonic-gate 	 *   in the pkcs11.conf file
17010Sstevel@tonic-gate 	 * - If update_mode == DELETE_MODE,
17020Sstevel@tonic-gate 	 *	If the mechanism is in the policy list, delete it.
17030Sstevel@tonic-gate 	 *	If the mechanism is not in the policy list, do nothing.
17040Sstevel@tonic-gate 	 * - If update_mode == ADD_MODE,
17050Sstevel@tonic-gate 	 *	If the mechanism is not in the policy list, add it.
17060Sstevel@tonic-gate 	 *	If the mechanism is in the policy list already, do nothing.
17070Sstevel@tonic-gate 	 */
17080Sstevel@tonic-gate 	while (marglist) {
17090Sstevel@tonic-gate 		if (pkcs11_str2mech(marglist->name, &mech_type) != CKR_OK) {
17100Sstevel@tonic-gate 			/*
17110Sstevel@tonic-gate 			 * This mechanism is not a valid PKCS11 mechanism,
17120Sstevel@tonic-gate 			 * give warning and ignore it.
17130Sstevel@tonic-gate 			 */
17140Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
17150Sstevel@tonic-gate 			    "(Warning) %s is not a valid PKCS#11 mechanism."),
17160Sstevel@tonic-gate 			    marglist->name);
17170Sstevel@tonic-gate 			rc = FAILURE;
17180Sstevel@tonic-gate 		} else {
17190Sstevel@tonic-gate 			(void) snprintf(midname, sizeof (midname), "%#010x",
17200Sstevel@tonic-gate 			    (int)mech_type);
17210Sstevel@tonic-gate 			if (update_mode == DELETE_MODE) {
17220Sstevel@tonic-gate 				found = B_FALSE;
17230Sstevel@tonic-gate 				phead = pcur = puent->policylist;
17240Sstevel@tonic-gate 				while (!found && pcur) {
17250Sstevel@tonic-gate 					if (strcmp(pcur->name, midname) == 0) {
17260Sstevel@tonic-gate 						found = B_TRUE;
17270Sstevel@tonic-gate 					} else {
17280Sstevel@tonic-gate 						phead = pcur;
17290Sstevel@tonic-gate 						pcur = pcur->next;
17300Sstevel@tonic-gate 					}
17310Sstevel@tonic-gate 				}
17320Sstevel@tonic-gate 
17330Sstevel@tonic-gate 				if (found) {
17340Sstevel@tonic-gate 					if (phead == pcur) {
17350Sstevel@tonic-gate 						puent->policylist =
17360Sstevel@tonic-gate 						    puent->policylist->next;
17370Sstevel@tonic-gate 						free(pcur);
17380Sstevel@tonic-gate 					} else {
17390Sstevel@tonic-gate 						phead->next = pcur->next;
17400Sstevel@tonic-gate 						free(pcur);
17410Sstevel@tonic-gate 					}
17420Sstevel@tonic-gate 					puent->count--;
17430Sstevel@tonic-gate 					if (puent->count == 0) {
17440Sstevel@tonic-gate 						puent->policylist = NULL;
17450Sstevel@tonic-gate 					}
17460Sstevel@tonic-gate 				}
17470Sstevel@tonic-gate 			} else if (update_mode == ADD_MODE) {
17480Sstevel@tonic-gate 				if (!is_in_policylist(midname,
17490Sstevel@tonic-gate 				    puent->policylist)) {
17500Sstevel@tonic-gate 					pumech = create_umech(midname);
17510Sstevel@tonic-gate 					if (pumech == NULL) {
17520Sstevel@tonic-gate 						rc = FAILURE;
17530Sstevel@tonic-gate 						break;
17540Sstevel@tonic-gate 					}
17550Sstevel@tonic-gate 					phead = puent->policylist;
17560Sstevel@tonic-gate 					puent->policylist = pumech;
17570Sstevel@tonic-gate 					pumech->next = phead;
17580Sstevel@tonic-gate 					puent->count++;
17590Sstevel@tonic-gate 				}
17600Sstevel@tonic-gate 			}
17610Sstevel@tonic-gate 		}
17620Sstevel@tonic-gate 		marglist = marglist->next;
17630Sstevel@tonic-gate 	}
17640Sstevel@tonic-gate 
17650Sstevel@tonic-gate 	return (rc);
17660Sstevel@tonic-gate }
17670Sstevel@tonic-gate 
17680Sstevel@tonic-gate /*
17690Sstevel@tonic-gate  * Open a session to the given slot and check if we can do
17700Sstevel@tonic-gate  * random numbers by asking for one byte.
17710Sstevel@tonic-gate  */
17720Sstevel@tonic-gate static boolean_t
17730Sstevel@tonic-gate check_random(CK_SLOT_ID slot_id, CK_FUNCTION_LIST_PTR prov_funcs)
17740Sstevel@tonic-gate {
17750Sstevel@tonic-gate 	CK_RV rv;
17760Sstevel@tonic-gate 	CK_SESSION_HANDLE hSession;
17770Sstevel@tonic-gate 	CK_BYTE test_byte;
17780Sstevel@tonic-gate 	CK_BYTE_PTR test_byte_ptr = &test_byte;
17790Sstevel@tonic-gate 
17800Sstevel@tonic-gate 	rv = prov_funcs->C_OpenSession(slot_id, CKF_SERIAL_SESSION,
17810Sstevel@tonic-gate 	    NULL_PTR, NULL, &hSession);
17820Sstevel@tonic-gate 	if (rv != CKR_OK)
17830Sstevel@tonic-gate 		return (B_FALSE);
17840Sstevel@tonic-gate 
17850Sstevel@tonic-gate 	/* We care only about the return value */
17860Sstevel@tonic-gate 	rv = prov_funcs->C_GenerateRandom(hSession, test_byte_ptr,
17870Sstevel@tonic-gate 	    sizeof (test_byte));
17880Sstevel@tonic-gate 	(void) prov_funcs->C_CloseSession(hSession);
17890Sstevel@tonic-gate 
17900Sstevel@tonic-gate 	/*
17910Sstevel@tonic-gate 	 * These checks are purely to determine whether the slot can do
17920Sstevel@tonic-gate 	 * random numbers. So, we don't check whether the routine
17930Sstevel@tonic-gate 	 * succeeds. The reason we check for CKR_RANDOM_NO_RNG also is that
17940Sstevel@tonic-gate 	 * this error effectively means CKR_FUNCTION_NOT_SUPPORTED.
17950Sstevel@tonic-gate 	 */
17960Sstevel@tonic-gate 	if (rv != CKR_FUNCTION_NOT_SUPPORTED && rv != CKR_RANDOM_NO_RNG)
17970Sstevel@tonic-gate 		return (B_TRUE);
17980Sstevel@tonic-gate 	else
17990Sstevel@tonic-gate 		return (B_FALSE);
18000Sstevel@tonic-gate }
18010Sstevel@tonic-gate 
18020Sstevel@tonic-gate void
18030Sstevel@tonic-gate display_verbose_mech_header()
18040Sstevel@tonic-gate {
18050Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR1);
18060Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR2);
18070Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR3);
18080Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR4);
18090Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR5);
18100Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR6);
18110Sstevel@tonic-gate 	(void) printf("%-28.28s %s", gettext("mechanism name"), HDR7);
18120Sstevel@tonic-gate 	/*
18130Sstevel@tonic-gate 	 * TRANSLATION_NOTE:
18140Sstevel@tonic-gate 	 * Strictly for appearance's sake, the first header line should be
18150Sstevel@tonic-gate 	 * as long as the length of the translated text above.  The format
18160Sstevel@tonic-gate 	 * lengths should all match too.
18170Sstevel@tonic-gate 	 */
18180Sstevel@tonic-gate 	(void) printf("%28s ---- ---- "
18190Sstevel@tonic-gate 	    "-  -  -  -  -  -  -  -  -  -  -  -  -  -\n",
18200Sstevel@tonic-gate 	    gettext("----------------------------"));
18210Sstevel@tonic-gate }
1822