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