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