xref: /onnv-gate/usr/src/cmd/cmd-crypto/cryptoadm/adm_uef.c (revision 13048:dbb29763d43d)
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 /*
2212888SDarren.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 
display_slot_flags(CK_FLAGS flags)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
display_token_flags(CK_FLAGS flags)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
display_mech_info(CK_MECHANISM_INFO * mechInfo)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
convert_mechlist(CK_MECHANISM_TYPE ** pmech_list,CK_ULONG * mech_count,mechlist_t * mlist)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
list_mechlist_for_lib(char * libname,mechlist_t * mlist,flag_val_t * rng_flag,boolean_t no_warn,boolean_t verbose,boolean_t show_mechs)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 */
18912888SDarren.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 
234*13048SValerie.Fenwick@Oracle.COM 	/*
235*13048SValerie.Fenwick@Oracle.COM 	 * Open the provider. Use RTLD_NOW here, as a way to
236*13048SValerie.Fenwick@Oracle.COM 	 * catch any providers with incomplete symbols that
237*13048SValerie.Fenwick@Oracle.COM 	 * might otherwise cause problems during libpkcs11's
238*13048SValerie.Fenwick@Oracle.COM 	 * execution.
239*13048SValerie.Fenwick@Oracle.COM 	 */
2400Sstevel@tonic-gate 	dldesc = dlopen(libpath, RTLD_NOW);
2410Sstevel@tonic-gate 	if (dldesc == NULL) {
2420Sstevel@tonic-gate 		dl_error = dlerror();
2430Sstevel@tonic-gate 		cryptodebug("Cannot load PKCS#11 library %s.  dlerror: %s",
2440Sstevel@tonic-gate 		    libname, dl_error != NULL ? dl_error : "Unknown");
2450Sstevel@tonic-gate 		rc = FAILURE;
2460Sstevel@tonic-gate 		goto clean_exit;
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	/* Get the pointer to provider's C_GetFunctionList() */
2500Sstevel@tonic-gate 	Tmp_C_GetFunctionList = (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList");
2510Sstevel@tonic-gate 	if (Tmp_C_GetFunctionList == NULL) {
2520Sstevel@tonic-gate 		cryptodebug("Cannot get the address of the C_GetFunctionList "
2530Sstevel@tonic-gate 		    "from %s", libname);
2540Sstevel@tonic-gate 		rc = FAILURE;
2550Sstevel@tonic-gate 		goto clean_exit;
2560Sstevel@tonic-gate 	}
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	/* Get the provider's function list */
2590Sstevel@tonic-gate 	rv = Tmp_C_GetFunctionList(&prov_funcs);
2600Sstevel@tonic-gate 	if (rv != CKR_OK) {
2610Sstevel@tonic-gate 		cryptodebug("failed to call C_GetFunctionList from %s",
2620Sstevel@tonic-gate 		    libname);
2630Sstevel@tonic-gate 		rc = FAILURE;
2640Sstevel@tonic-gate 		goto clean_exit;
2650Sstevel@tonic-gate 	}
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	/* Initialize this provider */
2680Sstevel@tonic-gate 	rv = prov_funcs->C_Initialize(NULL_PTR);
2690Sstevel@tonic-gate 	if (rv != CKR_OK) {
2700Sstevel@tonic-gate 		cryptodebug("failed to call C_Initialize from %s, "
2710Sstevel@tonic-gate 		    "return code = %d", libname, rv);
2720Sstevel@tonic-gate 		rc = FAILURE;
2730Sstevel@tonic-gate 		goto clean_exit;
2740Sstevel@tonic-gate 	} else {
2750Sstevel@tonic-gate 		lib_initialized = B_TRUE;
2760Sstevel@tonic-gate 	}
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	/*
2790Sstevel@tonic-gate 	 * Find out how many slots this provider has, call with tokenPresent
2800Sstevel@tonic-gate 	 * set to FALSE so all potential slots are returned.
2810Sstevel@tonic-gate 	 */
2820Sstevel@tonic-gate 	rv = prov_funcs->C_GetSlotList(FALSE, NULL_PTR, &slot_count);
2830Sstevel@tonic-gate 	if (rv != CKR_OK) {
2840Sstevel@tonic-gate 		cryptodebug("failed to get the slotlist from %s.", libname);
2850Sstevel@tonic-gate 		rc = FAILURE;
2860Sstevel@tonic-gate 		goto clean_exit;
2870Sstevel@tonic-gate 	} else if (slot_count == 0) {
2880Sstevel@tonic-gate 		if (!no_warn)
2890Sstevel@tonic-gate 			(void) printf(gettext("%s: no slots presented.\n"),
2907011Sda73024 			    libname);
2910Sstevel@tonic-gate 		rc = SUCCESS;
2920Sstevel@tonic-gate 		goto clean_exit;
2930Sstevel@tonic-gate 	}
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	/* Allocate memory for the slot list */
2960Sstevel@tonic-gate 	prov_slots = malloc(slot_count * sizeof (CK_SLOT_ID));
2970Sstevel@tonic-gate 	if (prov_slots == NULL) {
2980Sstevel@tonic-gate 		cryptodebug("out of memory.");
2990Sstevel@tonic-gate 		rc = FAILURE;
3000Sstevel@tonic-gate 		goto clean_exit;
3010Sstevel@tonic-gate 	}
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	/* Get the slot list from provider */
3040Sstevel@tonic-gate 	rv = prov_funcs->C_GetSlotList(FALSE, prov_slots, &slot_count);
3050Sstevel@tonic-gate 	if (rv != CKR_OK) {
3060Sstevel@tonic-gate 		cryptodebug("failed to call C_GetSlotList() from %s.",
3070Sstevel@tonic-gate 		    libname);
3080Sstevel@tonic-gate 		rc = FAILURE;
3090Sstevel@tonic-gate 		goto clean_exit;
3100Sstevel@tonic-gate 	}
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	if (verbose) {
3130Sstevel@tonic-gate 		(void) printf(gettext("Number of slots: %d\n"), slot_count);
3140Sstevel@tonic-gate 	}
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 	/* Get the mechanism list for each slot */
3170Sstevel@tonic-gate 	for (i = 0; i < slot_count; i++) {
3180Sstevel@tonic-gate 		if (verbose)
3190Sstevel@tonic-gate 			/*
3207334SDaniel.Anderson@Sun.COM 			 * TRANSLATION_NOTE
3210Sstevel@tonic-gate 			 * In some languages, the # symbol should be
3220Sstevel@tonic-gate 			 * converted to "no", an "n" followed by a
3230Sstevel@tonic-gate 			 * superscript "o"..
3240Sstevel@tonic-gate 			 */
3250Sstevel@tonic-gate 			(void) printf(gettext("\nSlot #%d\n"), i+1);
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 		if ((rng_flag != NULL) && (*rng_flag == NO_RNG)) {
3280Sstevel@tonic-gate 			if (check_random(prov_slots[i], prov_funcs)) {
3290Sstevel@tonic-gate 				*rng_flag = HAS_RNG;
3300Sstevel@tonic-gate 				rc = SUCCESS;
3310Sstevel@tonic-gate 				goto clean_exit;
3320Sstevel@tonic-gate 			} else
3330Sstevel@tonic-gate 				continue;
3340Sstevel@tonic-gate 		}
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 		rv = prov_funcs->C_GetSlotInfo(prov_slots[i], &slotinfo);
3370Sstevel@tonic-gate 		if (rv != CKR_OK) {
3380Sstevel@tonic-gate 			cryptodebug("failed to get slotinfo from %s", libname);
3390Sstevel@tonic-gate 			rc = FAILURE;
3400Sstevel@tonic-gate 			break;
3410Sstevel@tonic-gate 		}
3420Sstevel@tonic-gate 		if (verbose) {
3430Sstevel@tonic-gate 			CK_TOKEN_INFO tokeninfo;
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 			(void) printf(gettext("Description: %.64s\n"
3467011Sda73024 			    "Manufacturer: %.32s\n"
3477011Sda73024 			    "PKCS#11 Version: %d.%d\n"),
3487011Sda73024 			    slotinfo.slotDescription,
3497011Sda73024 			    slotinfo.manufacturerID,
3507011Sda73024 			    prov_funcs->version.major,
3517011Sda73024 			    prov_funcs->version.minor);
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 			(void) printf(gettext("Hardware Version: %d.%d\n"
3547011Sda73024 			    "Firmware Version: %d.%d\n"),
3557011Sda73024 			    slotinfo.hardwareVersion.major,
3567011Sda73024 			    slotinfo.hardwareVersion.minor,
3577011Sda73024 			    slotinfo.firmwareVersion.major,
3587011Sda73024 			    slotinfo.firmwareVersion.minor);
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 			(void) printf(gettext("Token Present: %s\n"),
3617011Sda73024 			    (slotinfo.flags & CKF_TOKEN_PRESENT ?
3627011Sda73024 			    gettext("True") : gettext("False")));
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 			display_slot_flags(slotinfo.flags);
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 			rv = prov_funcs->C_GetTokenInfo(prov_slots[i],
3677011Sda73024 			    &tokeninfo);
3680Sstevel@tonic-gate 			if (rv != CKR_OK) {
3690Sstevel@tonic-gate 				cryptodebug("Failed to get "
3707011Sda73024 				    "token info from %s", libname);
3710Sstevel@tonic-gate 				rc = FAILURE;
3720Sstevel@tonic-gate 				break;
3730Sstevel@tonic-gate 			}
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 			(void) printf(gettext("Token Label: %.32s\n"
3767011Sda73024 			    "Manufacturer ID: %.32s\n"
3777011Sda73024 			    "Model: %.16s\n"
3787011Sda73024 			    "Serial Number: %.16s\n"
3797011Sda73024 			    "Hardware Version: %d.%d\n"
3807011Sda73024 			    "Firmware Version: %d.%d\n"
3817011Sda73024 			    "UTC Time: %.16s\n"
3827304SDarren.Moffat@Sun.COM 			    "PIN Min Length: %d\n"
3837304SDarren.Moffat@Sun.COM 			    "PIN Max Length: %d\n"),
3847011Sda73024 			    tokeninfo.label,
3857011Sda73024 			    tokeninfo.manufacturerID,
3867011Sda73024 			    tokeninfo.model,
3877011Sda73024 			    tokeninfo.serialNumber,
3887011Sda73024 			    tokeninfo.hardwareVersion.major,
3897011Sda73024 			    tokeninfo.hardwareVersion.minor,
3907011Sda73024 			    tokeninfo.firmwareVersion.major,
3917011Sda73024 			    tokeninfo.firmwareVersion.minor,
3927011Sda73024 			    tokeninfo.utcTime,
3937011Sda73024 			    tokeninfo.ulMinPinLen,
3947011Sda73024 			    tokeninfo.ulMaxPinLen);
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 			display_token_flags(tokeninfo.flags);
3970Sstevel@tonic-gate 		}
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 		if (mlist == NULL) {
4000Sstevel@tonic-gate 			rv = prov_funcs->C_GetMechanismList(prov_slots[i],
4017011Sda73024 			    NULL_PTR, &mech_count);
4020Sstevel@tonic-gate 			if (rv != CKR_OK) {
4030Sstevel@tonic-gate 				cryptodebug(
4047011Sda73024 				    "failed to call C_GetMechanismList() "
4057011Sda73024 				    "from %s.", libname);
4060Sstevel@tonic-gate 				rc = FAILURE;
4070Sstevel@tonic-gate 				break;
4080Sstevel@tonic-gate 			}
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 			if (mech_count == 0) {
4110Sstevel@tonic-gate 				/* no mechanisms in this slot */
4120Sstevel@tonic-gate 				continue;
4130Sstevel@tonic-gate 			}
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 			pmech_list = malloc(mech_count *
4167011Sda73024 			    sizeof (CK_MECHANISM_TYPE));
4170Sstevel@tonic-gate 			if (pmech_list == NULL) {
4180Sstevel@tonic-gate 				cryptodebug("out of memory");
4190Sstevel@tonic-gate 				rc = FAILURE;
4200Sstevel@tonic-gate 				break;
4210Sstevel@tonic-gate 			}
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 			/* Get the actual mechanism list */
4240Sstevel@tonic-gate 			rv = prov_funcs->C_GetMechanismList(prov_slots[i],
4257011Sda73024 			    pmech_list, &mech_count);
4260Sstevel@tonic-gate 			if (rv != CKR_OK) {
4270Sstevel@tonic-gate 				cryptodebug(
4287011Sda73024 				    "failed to call C_GetMechanismList() "
4297011Sda73024 				    "from %s.", libname);
43012888SDarren.Moffat@oracle.com 				free(pmech_list);
4310Sstevel@tonic-gate 				rc = FAILURE;
4320Sstevel@tonic-gate 				break;
4330Sstevel@tonic-gate 			}
4340Sstevel@tonic-gate 		} else  {
4350Sstevel@tonic-gate 			/* use the mechanism list passed in */
4360Sstevel@tonic-gate 			rc = convert_mechlist(&pmech_list, &mech_count, mlist);
4370Sstevel@tonic-gate 			if (rc != SUCCESS) {
4380Sstevel@tonic-gate 				goto clean_exit;
4390Sstevel@tonic-gate 			}
4400Sstevel@tonic-gate 		}
4410Sstevel@tonic-gate 		if (show_mechs)
4420Sstevel@tonic-gate 			(void) printf(gettext("Mechanisms:\n"));
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 		if (verbose && show_mechs) {
4450Sstevel@tonic-gate 			display_verbose_mech_header();
4460Sstevel@tonic-gate 		}
4470Sstevel@tonic-gate 		/*
4480Sstevel@tonic-gate 		 * Merge the current mechanism list into the returning
4490Sstevel@tonic-gate 		 * mechanism list.
4500Sstevel@tonic-gate 		 */
4510Sstevel@tonic-gate 		for (j = 0; show_mechs && j < mech_count; j++) {
4527011Sda73024 			CK_MECHANISM_TYPE	mech = pmech_list[j];
45312888SDarren.Moffat@oracle.com 			CK_MECHANISM_INFO mech_info;
4547011Sda73024 
45512888SDarren.Moffat@oracle.com 			rv = prov_funcs->C_GetMechanismInfo(
45612888SDarren.Moffat@oracle.com 			    prov_slots[i], mech, &mech_info);
45712888SDarren.Moffat@oracle.com 			if (rv != CKR_OK) {
45812888SDarren.Moffat@oracle.com 				cryptodebug(
45912888SDarren.Moffat@oracle.com 				    "failed to call "
46012888SDarren.Moffat@oracle.com 				    "C_GetMechanismInfo() from %s.",
46112888SDarren.Moffat@oracle.com 				    libname);
46212888SDarren.Moffat@oracle.com 				free(pmech_list);
46312888SDarren.Moffat@oracle.com 				pmech_list = NULL;
46412888SDarren.Moffat@oracle.com 				rc = FAILURE;
46512888SDarren.Moffat@oracle.com 				break;
46612888SDarren.Moffat@oracle.com 			}
4677106Sda73024 			if (mech >= CKM_VENDOR_DEFINED) {
4687011Sda73024 				(void) printf("%#lx", mech);
4697011Sda73024 			} else {
4707011Sda73024 				mech_name = pkcs11_mech2str(mech);
4717011Sda73024 				(void) printf("%-29s", mech_name);
4727011Sda73024 			}
4737011Sda73024 
4740Sstevel@tonic-gate 			if (verbose) {
4750Sstevel@tonic-gate 				display_mech_info(&mech_info);
4760Sstevel@tonic-gate 			}
4770Sstevel@tonic-gate 			(void) printf("\n");
4780Sstevel@tonic-gate 		}
47912888SDarren.Moffat@oracle.com 		if (pmech_list)
48012888SDarren.Moffat@oracle.com 			free(pmech_list);
4810Sstevel@tonic-gate 		if (rc == FAILURE) {
4820Sstevel@tonic-gate 			break;
4830Sstevel@tonic-gate 		}
4840Sstevel@tonic-gate 	}
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 	if (rng_flag != NULL || rc == FAILURE) {
4870Sstevel@tonic-gate 		goto clean_exit;
4880Sstevel@tonic-gate 	}
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate clean_exit:
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	if (rc == FAILURE) {
4930Sstevel@tonic-gate 		(void) printf(gettext(
4940Sstevel@tonic-gate 		    "%s: failed to retrieve the mechanism list.\n"), libname);
4950Sstevel@tonic-gate 	}
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	if (lib_initialized) {
4980Sstevel@tonic-gate 		(void) prov_funcs->C_Finalize(NULL_PTR);
4990Sstevel@tonic-gate 	}
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 	if (dldesc != NULL) {
5020Sstevel@tonic-gate 		(void) dlclose(dldesc);
5030Sstevel@tonic-gate 	}
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate 	if (prov_slots != NULL) {
50612888SDarren.Moffat@oracle.com 		free(prov_slots);
5070Sstevel@tonic-gate 	}
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 	return (rc);
5100Sstevel@tonic-gate }
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate /*
5140Sstevel@tonic-gate  * Display the mechanism policy for a user-level library
5150Sstevel@tonic-gate  */
5160Sstevel@tonic-gate int
list_policy_for_lib(char * libname)5170Sstevel@tonic-gate list_policy_for_lib(char *libname)
5180Sstevel@tonic-gate {
5190Sstevel@tonic-gate 	uentry_t *puent = NULL;
5200Sstevel@tonic-gate 	int rc;
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	if (libname == NULL) {
5230Sstevel@tonic-gate 		/* should not happen */
5240Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
5250Sstevel@tonic-gate 		cryptodebug("list_policy_for_lib() - libname is NULL.");
5260Sstevel@tonic-gate 		return (FAILURE);
5270Sstevel@tonic-gate 	}
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 	/* Get the library entry from the pkcs11.conf file */
5300Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) == NULL) {
5310Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
5320Sstevel@tonic-gate 		    gettext("%s does not exist."), libname);
5330Sstevel@tonic-gate 		return (FAILURE);
5340Sstevel@tonic-gate 	}
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 	/* Print the policy for this library */
5370Sstevel@tonic-gate 	rc = print_uef_policy(puent);
5380Sstevel@tonic-gate 	free_uentry(puent);
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 	return (rc);
5410Sstevel@tonic-gate }
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate /*
5450Sstevel@tonic-gate  * Disable mechanisms for a user-level library
5460Sstevel@tonic-gate  */
5470Sstevel@tonic-gate int
disable_uef_lib(char * libname,boolean_t rndflag,boolean_t allflag,mechlist_t * marglist)5480Sstevel@tonic-gate disable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag,
5490Sstevel@tonic-gate     mechlist_t *marglist)
5500Sstevel@tonic-gate {
5510Sstevel@tonic-gate 	uentry_t	*puent;
5520Sstevel@tonic-gate 	int	rc;
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 	if (libname == NULL) {
5550Sstevel@tonic-gate 		/* should not happen */
5560Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
5570Sstevel@tonic-gate 		cryptodebug("disable_uef_lib() - libname is NULL.");
5580Sstevel@tonic-gate 		return (FAILURE);
5590Sstevel@tonic-gate 	}
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 	/* Get the provider entry from the pkcs11.conf file */
5620Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) == NULL) {
5630Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
5640Sstevel@tonic-gate 		    gettext("%s does not exist."), libname);
5650Sstevel@tonic-gate 		return (FAILURE);
5660Sstevel@tonic-gate 	}
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate 	/*
5690Sstevel@tonic-gate 	 * Update the mechanism policy of this library entry, based on
5700Sstevel@tonic-gate 	 * the current policy mode of the library and the mechanisms specified
5710Sstevel@tonic-gate 	 * in CLI.
5720Sstevel@tonic-gate 	 */
5730Sstevel@tonic-gate 	if (allflag) {
5740Sstevel@tonic-gate 		/*
5750Sstevel@tonic-gate 		 * If disabling all, just need to clean up the policylist and
5760Sstevel@tonic-gate 		 * set the flag_enabledlist flag to be B_TRUE.
5770Sstevel@tonic-gate 		 */
5780Sstevel@tonic-gate 		free_umechlist(puent->policylist);
5790Sstevel@tonic-gate 		puent->policylist = NULL;
5800Sstevel@tonic-gate 		puent->count = 0;
5810Sstevel@tonic-gate 		puent->flag_enabledlist = B_TRUE;
5820Sstevel@tonic-gate 		rc = SUCCESS;
5830Sstevel@tonic-gate 	} else if (marglist != NULL) {
5840Sstevel@tonic-gate 		if (puent->flag_enabledlist == B_TRUE) {
5850Sstevel@tonic-gate 			/*
5860Sstevel@tonic-gate 			 * The current default policy mode of this library
5870Sstevel@tonic-gate 			 * is "all are disabled, except ...", so if a
5880Sstevel@tonic-gate 			 * specified mechanism is in the exception list
5890Sstevel@tonic-gate 			 * (the policylist), delete it from the policylist.
5900Sstevel@tonic-gate 			 */
5910Sstevel@tonic-gate 			rc = update_policylist(puent, marglist, DELETE_MODE);
5920Sstevel@tonic-gate 		} else {
5930Sstevel@tonic-gate 			/*
5940Sstevel@tonic-gate 			 * The current default policy mode of this library
5950Sstevel@tonic-gate 			 * is "all are enabled", so if a specified mechanism
5960Sstevel@tonic-gate 			 * is not in the exception list (policylist), add
5970Sstevel@tonic-gate 			 * it into the policylist.
5980Sstevel@tonic-gate 			 */
5990Sstevel@tonic-gate 			rc = update_policylist(puent, marglist, ADD_MODE);
6000Sstevel@tonic-gate 		}
6010Sstevel@tonic-gate 	} else if (!rndflag) {
6020Sstevel@tonic-gate 		/* should not happen */
6030Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
6040Sstevel@tonic-gate 		cryptodebug("disable_uef_lib() - wrong arguments.");
6050Sstevel@tonic-gate 		return (FAILURE);
6060Sstevel@tonic-gate 	}
6070Sstevel@tonic-gate 
6080Sstevel@tonic-gate 	if (rndflag)
6090Sstevel@tonic-gate 		puent->flag_norandom = B_TRUE;
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate 	if (rc == FAILURE) {
6120Sstevel@tonic-gate 		free_uentry(puent);
6130Sstevel@tonic-gate 		return (FAILURE);
6140Sstevel@tonic-gate 	}
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 	/* Update the pkcs11.conf file with the updated entry */
6170Sstevel@tonic-gate 	rc = update_pkcs11conf(puent);
6180Sstevel@tonic-gate 	free_uentry(puent);
6190Sstevel@tonic-gate 	return (rc);
6200Sstevel@tonic-gate }
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate /*
6240Sstevel@tonic-gate  * Enable disabled mechanisms for a user-level library.
6250Sstevel@tonic-gate  */
6260Sstevel@tonic-gate int
enable_uef_lib(char * libname,boolean_t rndflag,boolean_t allflag,mechlist_t * marglist)6270Sstevel@tonic-gate enable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag,
6280Sstevel@tonic-gate     mechlist_t *marglist)
6290Sstevel@tonic-gate {
6300Sstevel@tonic-gate 	uentry_t	*puent;
6310Sstevel@tonic-gate 	int	rc = SUCCESS;
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 	if (libname == NULL) {
6340Sstevel@tonic-gate 		/* should not happen */
6350Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
6360Sstevel@tonic-gate 		cryptodebug("enable_uef_lib() - libname is NULL.");
6370Sstevel@tonic-gate 		return (FAILURE);
6380Sstevel@tonic-gate 	}
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 	/* Get the provider entry from the pkcs11.conf file */
6410Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) == NULL) {
6420Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
6430Sstevel@tonic-gate 		    gettext("%s does not exist."), libname);
6440Sstevel@tonic-gate 		return (FAILURE);
6450Sstevel@tonic-gate 	}
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 	/*
6480Sstevel@tonic-gate 	 * Update the mechanism policy of this library entry, based on
6490Sstevel@tonic-gate 	 * the current policy mode of the library and the mechanisms
6500Sstevel@tonic-gate 	 * specified in CLI.
6510Sstevel@tonic-gate 	 */
6520Sstevel@tonic-gate 	if (allflag) {
6530Sstevel@tonic-gate 		/*
6540Sstevel@tonic-gate 		 * If enabling all, what needs to be done are cleaning up the
6550Sstevel@tonic-gate 		 * policylist and setting the "flag_enabledlist" flag to
6560Sstevel@tonic-gate 		 * B_FALSE.
6570Sstevel@tonic-gate 		 */
6580Sstevel@tonic-gate 		free_umechlist(puent->policylist);
6590Sstevel@tonic-gate 		puent->policylist = NULL;
6600Sstevel@tonic-gate 		puent->count = 0;
6610Sstevel@tonic-gate 		puent->flag_enabledlist = B_FALSE;
6620Sstevel@tonic-gate 		rc = SUCCESS;
6630Sstevel@tonic-gate 	} else if (marglist != NULL) {
6640Sstevel@tonic-gate 		if (puent->flag_enabledlist == B_TRUE) {
6650Sstevel@tonic-gate 			/*
6660Sstevel@tonic-gate 			 * The current default policy mode of this library
6670Sstevel@tonic-gate 			 * is "all are disabled, except ...", so if a
6680Sstevel@tonic-gate 			 * specified mechanism is not in the exception list
6690Sstevel@tonic-gate 			 * (policylist), add it.
6700Sstevel@tonic-gate 			 */
6710Sstevel@tonic-gate 			rc = update_policylist(puent, marglist, ADD_MODE);
6720Sstevel@tonic-gate 		} else {
6730Sstevel@tonic-gate 			/*
6740Sstevel@tonic-gate 			 * The current default policy mode of this library
6750Sstevel@tonic-gate 			 * is "all are enabled, except", so if a specified
6760Sstevel@tonic-gate 			 * mechanism is in the exception list (policylist),
6770Sstevel@tonic-gate 			 * delete it.
6780Sstevel@tonic-gate 			 */
6790Sstevel@tonic-gate 			rc = update_policylist(puent, marglist, DELETE_MODE);
6800Sstevel@tonic-gate 		}
6810Sstevel@tonic-gate 	} else if (!rndflag) {
6820Sstevel@tonic-gate 		/* should not come here */
6830Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
6840Sstevel@tonic-gate 		cryptodebug("enable_uef_lib() - wrong arguments.");
6850Sstevel@tonic-gate 		return (FAILURE);
6860Sstevel@tonic-gate 	}
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate 	if (rndflag)
6890Sstevel@tonic-gate 		puent->flag_norandom = B_FALSE;
6900Sstevel@tonic-gate 
6910Sstevel@tonic-gate 	if (rc == FAILURE) {
6920Sstevel@tonic-gate 		free_uentry(puent);
6930Sstevel@tonic-gate 		return (FAILURE);
6940Sstevel@tonic-gate 	}
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	/* Update the pkcs11.conf file with the updated entry */
6970Sstevel@tonic-gate 	rc = update_pkcs11conf(puent);
6980Sstevel@tonic-gate 	free_uentry(puent);
6990Sstevel@tonic-gate 	return (rc);
7000Sstevel@tonic-gate }
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 
7030Sstevel@tonic-gate /*
7040Sstevel@tonic-gate  * Install a user-level library.
7050Sstevel@tonic-gate  */
7060Sstevel@tonic-gate int
install_uef_lib(char * libname)7070Sstevel@tonic-gate install_uef_lib(char *libname)
7080Sstevel@tonic-gate {
7090Sstevel@tonic-gate 	uentry_t	*puent;
7100Sstevel@tonic-gate 	struct stat 	statbuf;
7110Sstevel@tonic-gate 	char	libpath[MAXPATHLEN];
7120Sstevel@tonic-gate 	char	libbuf[MAXPATHLEN];
7130Sstevel@tonic-gate 	char	*isa;
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate 	if (libname == NULL) {
7160Sstevel@tonic-gate 		/* should not happen */
7170Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
7180Sstevel@tonic-gate 		cryptodebug("install_uef_lib() - libname is NULL.");
7190Sstevel@tonic-gate 		return (FAILURE);
7200Sstevel@tonic-gate 	}
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate 	/* Check if the provider already exists in the framework */
7230Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) != NULL) {
7240Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s exists already."),
7250Sstevel@tonic-gate 		    libname);
7260Sstevel@tonic-gate 		free_uentry(puent);
7270Sstevel@tonic-gate 		return (FAILURE);
7280Sstevel@tonic-gate 	}
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate 	/*
7310Sstevel@tonic-gate 	 * Check if the library exists in the system. if $ISA is in the
7320Sstevel@tonic-gate 	 * path, only check the 32bit version.
7330Sstevel@tonic-gate 	 */
7340Sstevel@tonic-gate 	if (strlcpy(libbuf, libname, MAXPATHLEN) >= MAXPATHLEN) {
7350Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
7360Sstevel@tonic-gate 		    gettext("the provider name is too long - %s"), libname);
7370Sstevel@tonic-gate 		return (FAILURE);
7380Sstevel@tonic-gate 	}
7390Sstevel@tonic-gate 
7400Sstevel@tonic-gate 	if ((isa = strstr(libbuf, PKCS11_ISA)) != NULL) {
7410Sstevel@tonic-gate 		*isa = '\000';
7420Sstevel@tonic-gate 		isa += strlen(PKCS11_ISA);
7430Sstevel@tonic-gate 		(void) snprintf(libpath, sizeof (libpath), "%s%s%s", libbuf,
7440Sstevel@tonic-gate 		    "/", isa);
7450Sstevel@tonic-gate 	} else {
7460Sstevel@tonic-gate 		(void) strlcpy(libpath, libname, sizeof (libpath));
7470Sstevel@tonic-gate 	}
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate 	/* Check if it is same as the framework library */
7500Sstevel@tonic-gate 	if (strcmp(libpath, UEF_FRAME_LIB) == 0) {
7510Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
7520Sstevel@tonic-gate 		    "The framework library %s can not be installed."),
7530Sstevel@tonic-gate 		    libname);
7540Sstevel@tonic-gate 		return (FAILURE);
7550Sstevel@tonic-gate 	}
7560Sstevel@tonic-gate 
7570Sstevel@tonic-gate 	if (stat(libpath, &statbuf) != 0) {
7580Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s not found"), libname);
7590Sstevel@tonic-gate 		return (FAILURE);
7600Sstevel@tonic-gate 	}
7610Sstevel@tonic-gate 
7620Sstevel@tonic-gate 	/* Need to add "\n" to libname for adding into the config file */
7630Sstevel@tonic-gate 	if (strlcat(libname, "\n", MAXPATHLEN) >= MAXPATHLEN) {
7640Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
7650Sstevel@tonic-gate 		    "can not install %s; the name is too long."), libname);
7660Sstevel@tonic-gate 		return (FAILURE);
7670Sstevel@tonic-gate 	}
7680Sstevel@tonic-gate 
76910500SHai-May.Chao@Sun.COM 	return (update_conf(_PATH_PKCS11_CONF, libname));
7700Sstevel@tonic-gate 
7710Sstevel@tonic-gate }
7720Sstevel@tonic-gate 
7730Sstevel@tonic-gate 
7740Sstevel@tonic-gate /*
7750Sstevel@tonic-gate  * Uninstall a user-level library.
7760Sstevel@tonic-gate  */
7770Sstevel@tonic-gate int
uninstall_uef_lib(char * libname)7780Sstevel@tonic-gate uninstall_uef_lib(char *libname)
7790Sstevel@tonic-gate {
7800Sstevel@tonic-gate 	uentry_t	*puent;
7810Sstevel@tonic-gate 	FILE	*pfile;
7820Sstevel@tonic-gate 	FILE	*pfile_tmp;
7830Sstevel@tonic-gate 	char 	buffer[BUFSIZ];
7840Sstevel@tonic-gate 	char 	buffer2[BUFSIZ];
7850Sstevel@tonic-gate 	char	tmpfile_name[MAXPATHLEN];
7860Sstevel@tonic-gate 	char 	*name;
7870Sstevel@tonic-gate 	boolean_t	found;
7880Sstevel@tonic-gate 	boolean_t	in_package;
7890Sstevel@tonic-gate 	int	len;
7900Sstevel@tonic-gate 	int	rc = SUCCESS;
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate 	if (libname == NULL) {
7930Sstevel@tonic-gate 		/* should not happen */
7940Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
7950Sstevel@tonic-gate 		cryptodebug("uninstall_uef_lib() - libname is NULL.");
7960Sstevel@tonic-gate 		return (FAILURE);
7970Sstevel@tonic-gate 	}
7980Sstevel@tonic-gate 
7990Sstevel@tonic-gate 	/* Check if the provider exists */
8000Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) == NULL) {
8010Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8020Sstevel@tonic-gate 		    gettext("%s does not exist."), libname);
8030Sstevel@tonic-gate 		return (FAILURE);
8040Sstevel@tonic-gate 	}
8050Sstevel@tonic-gate 	free_uentry(puent);
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 	/*  Open the pkcs11.conf file and lock it */
8080Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
8090Sstevel@tonic-gate 		err = errno;
8100Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8110Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
8120Sstevel@tonic-gate 		    strerror(err));
8130Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
8140Sstevel@tonic-gate 		return (FAILURE);
8150Sstevel@tonic-gate 	}
8160Sstevel@tonic-gate 
8170Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
8180Sstevel@tonic-gate 		err = errno;
8190Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8200Sstevel@tonic-gate 		    gettext("failed to lock the configuration - %s"),
8210Sstevel@tonic-gate 		    strerror(err));
8220Sstevel@tonic-gate 		(void) fclose(pfile);
8230Sstevel@tonic-gate 		return (FAILURE);
8240Sstevel@tonic-gate 	}
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate 	/*
8270Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory to save
8280Sstevel@tonic-gate 	 * the new configuration file first.
8290Sstevel@tonic-gate 	 */
8300Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
8310Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
8320Sstevel@tonic-gate 		err = errno;
8330Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8340Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
8350Sstevel@tonic-gate 		    strerror(err));
8360Sstevel@tonic-gate 		(void) fclose(pfile);
8370Sstevel@tonic-gate 		return (FAILURE);
8380Sstevel@tonic-gate 	}
8390Sstevel@tonic-gate 
8400Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
8410Sstevel@tonic-gate 		err = errno;
8420Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
8430Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
8440Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
8450Sstevel@tonic-gate 			err = errno;
8460Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
8470Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
8480Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
8490Sstevel@tonic-gate 		}
8500Sstevel@tonic-gate 		(void) fclose(pfile);
8510Sstevel@tonic-gate 		return (FAILURE);
8520Sstevel@tonic-gate 	}
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate 
8550Sstevel@tonic-gate 	/*
8560Sstevel@tonic-gate 	 * Loop thru the config file.  If the library to be uninstalled
8570Sstevel@tonic-gate 	 * is in a package, just comment it off.
8580Sstevel@tonic-gate 	 */
8590Sstevel@tonic-gate 	in_package = B_FALSE;
8600Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
8610Sstevel@tonic-gate 		found = B_FALSE;
8620Sstevel@tonic-gate 		if (!(buffer[0] == ' ' || buffer[0] == '\n' ||
8630Sstevel@tonic-gate 		    buffer[0] == '\t')) {
8640Sstevel@tonic-gate 			if (strstr(buffer, " Start ") != NULL) {
8650Sstevel@tonic-gate 				in_package = B_TRUE;
8660Sstevel@tonic-gate 			} else if (strstr(buffer, " End ") != NULL) {
8670Sstevel@tonic-gate 				in_package = B_FALSE;
8680Sstevel@tonic-gate 			} else if (buffer[0] != '#') {
8690Sstevel@tonic-gate 				(void) strlcpy(buffer2, buffer, BUFSIZ);
8700Sstevel@tonic-gate 
8710Sstevel@tonic-gate 				/* get rid of trailing '\n' */
8720Sstevel@tonic-gate 				len = strlen(buffer2);
8730Sstevel@tonic-gate 				if (buffer2[len-1] == '\n') {
8740Sstevel@tonic-gate 					len--;
8750Sstevel@tonic-gate 				}
8760Sstevel@tonic-gate 				buffer2[len] = '\0';
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate 				if ((name = strtok(buffer2, SEP_COLON))
8790Sstevel@tonic-gate 				    == NULL) {
8800Sstevel@tonic-gate 					rc = FAILURE;
8810Sstevel@tonic-gate 					break;
8820Sstevel@tonic-gate 				} else if (strcmp(libname, name) == 0) {
8830Sstevel@tonic-gate 					found = B_TRUE;
8840Sstevel@tonic-gate 				}
8850Sstevel@tonic-gate 			}
8860Sstevel@tonic-gate 		}
8870Sstevel@tonic-gate 
8880Sstevel@tonic-gate 		if (found) {
8890Sstevel@tonic-gate 			if (in_package) {
8900Sstevel@tonic-gate 				(void) snprintf(buffer2, sizeof (buffer2),
8910Sstevel@tonic-gate 				    "%s%s%s", "#", libname, "\n");
8920Sstevel@tonic-gate 				if (fputs(buffer2, pfile_tmp) == EOF) {
8930Sstevel@tonic-gate 					rc = FAILURE;
8940Sstevel@tonic-gate 				}
8950Sstevel@tonic-gate 			}
8960Sstevel@tonic-gate 		} else {
8970Sstevel@tonic-gate 			if (fputs(buffer, pfile_tmp) == EOF) {
8980Sstevel@tonic-gate 				rc = FAILURE;
8990Sstevel@tonic-gate 			}
9000Sstevel@tonic-gate 		}
9010Sstevel@tonic-gate 
9020Sstevel@tonic-gate 		if (rc == FAILURE) {
9030Sstevel@tonic-gate 			break;
9040Sstevel@tonic-gate 		}
9050Sstevel@tonic-gate 	}
9060Sstevel@tonic-gate 
9070Sstevel@tonic-gate 	if (rc == FAILURE) {
9080Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("write error."));
9090Sstevel@tonic-gate 		(void) fclose(pfile);
9100Sstevel@tonic-gate 		(void) fclose(pfile_tmp);
9110Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
9120Sstevel@tonic-gate 			err = errno;
9130Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
9140Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
9150Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
9160Sstevel@tonic-gate 		}
9170Sstevel@tonic-gate 		return (FAILURE);
9180Sstevel@tonic-gate 	}
9190Sstevel@tonic-gate 
9200Sstevel@tonic-gate 	(void) fclose(pfile);
9210Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
9220Sstevel@tonic-gate 		err = errno;
9230Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9240Sstevel@tonic-gate 		    gettext("failed to close a temporary file - %s"),
9250Sstevel@tonic-gate 		    strerror(err));
9260Sstevel@tonic-gate 		return (FAILURE);
9270Sstevel@tonic-gate 	}
9280Sstevel@tonic-gate 
9290Sstevel@tonic-gate 	/* Now update the real config file */
9300Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
9310Sstevel@tonic-gate 		err = errno;
9320Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9330Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
9340Sstevel@tonic-gate 		    strerror(err));
9350Sstevel@tonic-gate 		cryptodebug("failed to rename %s to %s: %s", tmpfile,
9360Sstevel@tonic-gate 		    _PATH_PKCS11_CONF, strerror(err));
9370Sstevel@tonic-gate 		rc = FAILURE;
9380Sstevel@tonic-gate 	} else if (chmod(_PATH_PKCS11_CONF,
9390Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
9400Sstevel@tonic-gate 		err = errno;
9410Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9420Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
9430Sstevel@tonic-gate 		    strerror(err));
9440Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
9450Sstevel@tonic-gate 		    strerror(err));
9460Sstevel@tonic-gate 		rc = FAILURE;
9470Sstevel@tonic-gate 	} else {
9480Sstevel@tonic-gate 		rc = SUCCESS;
9490Sstevel@tonic-gate 	}
9500Sstevel@tonic-gate 
9510Sstevel@tonic-gate 	if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
9520Sstevel@tonic-gate 		err = errno;
9530Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
9540Sstevel@tonic-gate 		    "(Warning) failed to remove %s: %s"),
9550Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
9560Sstevel@tonic-gate 	}
9570Sstevel@tonic-gate 
9580Sstevel@tonic-gate 	return (rc);
9590Sstevel@tonic-gate }
9600Sstevel@tonic-gate 
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate int
display_policy(uentry_t * puent)9630Sstevel@tonic-gate display_policy(uentry_t *puent)
9640Sstevel@tonic-gate {
9657011Sda73024 	CK_MECHANISM_TYPE	mech_id;
9667011Sda73024 	const char		*mech_name;
9677011Sda73024 	umechlist_t		*ptr;
9680Sstevel@tonic-gate 
9690Sstevel@tonic-gate 	if (puent == NULL) {
9700Sstevel@tonic-gate 		return (SUCCESS);
9710Sstevel@tonic-gate 	}
9720Sstevel@tonic-gate 
9730Sstevel@tonic-gate 	if (puent->flag_enabledlist == B_FALSE) {
9740Sstevel@tonic-gate 		(void) printf(gettext("%s: all mechanisms are enabled"),
9750Sstevel@tonic-gate 		    puent->name);
9760Sstevel@tonic-gate 		ptr = puent->policylist;
9770Sstevel@tonic-gate 		if (ptr == NULL) {
9780Sstevel@tonic-gate 			(void) printf(".");
9790Sstevel@tonic-gate 		} else {
9800Sstevel@tonic-gate 			(void) printf(gettext(", except "));
9810Sstevel@tonic-gate 			while (ptr != NULL) {
9820Sstevel@tonic-gate 				mech_id = strtoul(ptr->name, NULL, 0);
9830Sstevel@tonic-gate 				if (mech_id & CKO_VENDOR_DEFINED) {
9840Sstevel@tonic-gate 					/* vendor defined mechanism */
9850Sstevel@tonic-gate 					(void) printf("%s", ptr->name);
9860Sstevel@tonic-gate 				} else {
9877106Sda73024 					if (mech_id >= CKM_VENDOR_DEFINED) {
9887011Sda73024 						(void) printf("%#lx", mech_id);
9897011Sda73024 					} else {
9907011Sda73024 						mech_name = pkcs11_mech2str(
9917011Sda73024 						    mech_id);
9927011Sda73024 						if (mech_name == NULL) {
9937011Sda73024 							return (FAILURE);
9947011Sda73024 						}
9957011Sda73024 						(void) printf("%s", mech_name);
9960Sstevel@tonic-gate 					}
9970Sstevel@tonic-gate 				}
9980Sstevel@tonic-gate 
9990Sstevel@tonic-gate 				ptr = ptr->next;
10000Sstevel@tonic-gate 				if (ptr == NULL) {
10010Sstevel@tonic-gate 					(void) printf(".");
10020Sstevel@tonic-gate 				} else {
10030Sstevel@tonic-gate 					(void) printf(",");
10040Sstevel@tonic-gate 				}
10050Sstevel@tonic-gate 			}
10060Sstevel@tonic-gate 		}
10070Sstevel@tonic-gate 	} else { /* puent->flag_enabledlist == B_TRUE */
10080Sstevel@tonic-gate 		(void) printf(gettext("%s: all mechanisms are disabled"),
10090Sstevel@tonic-gate 		    puent->name);
10100Sstevel@tonic-gate 		ptr = puent->policylist;
10110Sstevel@tonic-gate 		if (ptr == NULL) {
10120Sstevel@tonic-gate 			(void) printf(".");
10130Sstevel@tonic-gate 		} else {
10140Sstevel@tonic-gate 			(void) printf(gettext(", except "));
10150Sstevel@tonic-gate 			while (ptr != NULL) {
10160Sstevel@tonic-gate 				mech_id = strtoul(ptr->name, NULL, 0);
10170Sstevel@tonic-gate 				if (mech_id & CKO_VENDOR_DEFINED) {
10180Sstevel@tonic-gate 					/* vendor defined mechanism */
10190Sstevel@tonic-gate 					(void) printf("%s", ptr->name);
10200Sstevel@tonic-gate 				} else {
10210Sstevel@tonic-gate 					mech_name = pkcs11_mech2str(mech_id);
10220Sstevel@tonic-gate 					if (mech_name == NULL) {
10230Sstevel@tonic-gate 						return (FAILURE);
10240Sstevel@tonic-gate 					}
10250Sstevel@tonic-gate 					(void) printf("%s", mech_name);
10260Sstevel@tonic-gate 				}
10270Sstevel@tonic-gate 				ptr = ptr->next;
10280Sstevel@tonic-gate 				if (ptr == NULL) {
10290Sstevel@tonic-gate 					(void) printf(".");
10300Sstevel@tonic-gate 				} else {
10310Sstevel@tonic-gate 					(void) printf(",");
10320Sstevel@tonic-gate 				}
10330Sstevel@tonic-gate 			}
10340Sstevel@tonic-gate 		}
10350Sstevel@tonic-gate 	}
10360Sstevel@tonic-gate 	return (SUCCESS);
10370Sstevel@tonic-gate }
10380Sstevel@tonic-gate 
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate 
10410Sstevel@tonic-gate /*
10420Sstevel@tonic-gate  * Print out the mechanism policy for a user-level provider pointed by puent.
10430Sstevel@tonic-gate  */
10440Sstevel@tonic-gate int
print_uef_policy(uentry_t * puent)10450Sstevel@tonic-gate print_uef_policy(uentry_t *puent)
10460Sstevel@tonic-gate {
10470Sstevel@tonic-gate 	flag_val_t rng_flag;
10480Sstevel@tonic-gate 
10490Sstevel@tonic-gate 	if (puent == NULL) {
10500Sstevel@tonic-gate 		return (FAILURE);
10510Sstevel@tonic-gate 	}
10520Sstevel@tonic-gate 
10530Sstevel@tonic-gate 	rng_flag = NO_RNG;
10540Sstevel@tonic-gate 	if (list_mechlist_for_lib(puent->name, NULL, &rng_flag, B_TRUE,
10557011Sda73024 	    B_FALSE, B_FALSE) != SUCCESS) {
10560Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
10570Sstevel@tonic-gate 		    gettext("%s internal error."), puent->name);
10580Sstevel@tonic-gate 		return (FAILURE);
10590Sstevel@tonic-gate 	}
10600Sstevel@tonic-gate 
10610Sstevel@tonic-gate 	if (display_policy(puent) != SUCCESS) {
10620Sstevel@tonic-gate 		goto failed_exit;
10630Sstevel@tonic-gate 	}
10640Sstevel@tonic-gate 
10650Sstevel@tonic-gate 
10660Sstevel@tonic-gate 	if (puent->flag_norandom == B_TRUE)
10670Sstevel@tonic-gate 		/*
10687334SDaniel.Anderson@Sun.COM 		 * TRANSLATION_NOTE
10690Sstevel@tonic-gate 		 * "random" is a keyword and not to be translated.
10700Sstevel@tonic-gate 		 */
10710Sstevel@tonic-gate 		(void) printf(gettext(" %s is disabled."), "random");
10720Sstevel@tonic-gate 	else {
10730Sstevel@tonic-gate 		if (rng_flag == HAS_RNG)
10740Sstevel@tonic-gate 			/*
10757334SDaniel.Anderson@Sun.COM 			 * TRANSLATION_NOTE
10760Sstevel@tonic-gate 			 * "random" is a keyword and not to be translated.
10770Sstevel@tonic-gate 			 */
10780Sstevel@tonic-gate 			(void) printf(gettext(" %s is enabled."), "random");
10790Sstevel@tonic-gate 	}
10800Sstevel@tonic-gate 	(void) printf("\n");
10810Sstevel@tonic-gate 
10820Sstevel@tonic-gate 	return (SUCCESS);
10830Sstevel@tonic-gate 
10840Sstevel@tonic-gate failed_exit:
10850Sstevel@tonic-gate 
10860Sstevel@tonic-gate 	(void) printf(gettext("\nout of memory.\n"));
10870Sstevel@tonic-gate 	return (FAILURE);
10880Sstevel@tonic-gate }
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate 
10910Sstevel@tonic-gate /*
10920Sstevel@tonic-gate  * Check if the mechanism is in the mechanism list.
10930Sstevel@tonic-gate  */
10940Sstevel@tonic-gate static boolean_t
is_in_policylist(midstr_t mechname,umechlist_t * plist)10950Sstevel@tonic-gate is_in_policylist(midstr_t mechname, umechlist_t *plist)
10960Sstevel@tonic-gate {
10970Sstevel@tonic-gate 	boolean_t found = B_FALSE;
10980Sstevel@tonic-gate 
10990Sstevel@tonic-gate 	if (mechname == NULL) {
11000Sstevel@tonic-gate 		return (B_FALSE);
11010Sstevel@tonic-gate 	}
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	while (plist != NULL) {
11040Sstevel@tonic-gate 		if (strcmp(plist->name, mechname) == 0) {
11050Sstevel@tonic-gate 			found = B_TRUE;
11060Sstevel@tonic-gate 			break;
11070Sstevel@tonic-gate 		}
11080Sstevel@tonic-gate 		plist = plist->next;
11090Sstevel@tonic-gate 	}
11100Sstevel@tonic-gate 
11110Sstevel@tonic-gate 	return (found);
11120Sstevel@tonic-gate }
11130Sstevel@tonic-gate 
11140Sstevel@tonic-gate 
11150Sstevel@tonic-gate /*
11160Sstevel@tonic-gate  * Update the pkcs11.conf file with the updated entry.
11170Sstevel@tonic-gate  */
11180Sstevel@tonic-gate int
update_pkcs11conf(uentry_t * puent)11190Sstevel@tonic-gate update_pkcs11conf(uentry_t *puent)
11200Sstevel@tonic-gate {
11210Sstevel@tonic-gate 	FILE	*pfile;
11220Sstevel@tonic-gate 	FILE	*pfile_tmp;
11230Sstevel@tonic-gate 	char buffer[BUFSIZ];
11240Sstevel@tonic-gate 	char buffer2[BUFSIZ];
11250Sstevel@tonic-gate 	char tmpfile_name[MAXPATHLEN];
11260Sstevel@tonic-gate 	char *name;
11270Sstevel@tonic-gate 	char *str;
11280Sstevel@tonic-gate 	int len;
11290Sstevel@tonic-gate 	int rc = SUCCESS;
11300Sstevel@tonic-gate 	boolean_t found;
11310Sstevel@tonic-gate 
11320Sstevel@tonic-gate 	if (puent == NULL) {
11330Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
11340Sstevel@tonic-gate 		return (FAILURE);
11350Sstevel@tonic-gate 	}
11360Sstevel@tonic-gate 
11370Sstevel@tonic-gate 	/* Open the pkcs11.conf file */
11380Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
11390Sstevel@tonic-gate 		err = errno;
11400Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
11410Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
11420Sstevel@tonic-gate 		    strerror(err));
11430Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
11440Sstevel@tonic-gate 		return (FAILURE);
11450Sstevel@tonic-gate 	}
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate 	/* Lock the pkcs11.conf file */
11480Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
11490Sstevel@tonic-gate 		err = errno;
11500Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
11510Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
11527011Sda73024 		    strerror(err));
11530Sstevel@tonic-gate 		(void) fclose(pfile);
11540Sstevel@tonic-gate 		return (FAILURE);
11550Sstevel@tonic-gate 	}
11560Sstevel@tonic-gate 
11570Sstevel@tonic-gate 	/*
11580Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory to save
11590Sstevel@tonic-gate 	 * updated configuration file first.
11600Sstevel@tonic-gate 	 */
11610Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
11620Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
11630Sstevel@tonic-gate 		err = errno;
11640Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
11650Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
11660Sstevel@tonic-gate 		    strerror(err));
11670Sstevel@tonic-gate 		(void) fclose(pfile);
11680Sstevel@tonic-gate 		return (FAILURE);
11690Sstevel@tonic-gate 	}
11700Sstevel@tonic-gate 
11710Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
11720Sstevel@tonic-gate 		err = errno;
11730Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
11740Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
11750Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
11760Sstevel@tonic-gate 			err = errno;
11770Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
11780Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
11790Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
11800Sstevel@tonic-gate 		}
11810Sstevel@tonic-gate 		(void) fclose(pfile);
11820Sstevel@tonic-gate 		return (FAILURE);
11830Sstevel@tonic-gate 	}
11840Sstevel@tonic-gate 
11850Sstevel@tonic-gate 
11860Sstevel@tonic-gate 	/*
11870Sstevel@tonic-gate 	 * Loop thru entire pkcs11.conf file, update the entry to be
11880Sstevel@tonic-gate 	 * updated and save the updated file to the temporary file first.
11890Sstevel@tonic-gate 	 */
11900Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
11910Sstevel@tonic-gate 		found = B_FALSE;
11920Sstevel@tonic-gate 		if (!(buffer[0] == '#' || buffer[0] == ' ' ||
11930Sstevel@tonic-gate 		    buffer[0] == '\n'|| buffer[0] == '\t')) {
11940Sstevel@tonic-gate 			/*
11950Sstevel@tonic-gate 			 * Get the provider name from this line and check if
11960Sstevel@tonic-gate 			 * this is the entry to be updated. Note: can not use
11970Sstevel@tonic-gate 			 * "buffer" directly because strtok will change its
11980Sstevel@tonic-gate 			 * value.
11990Sstevel@tonic-gate 			 */
12000Sstevel@tonic-gate 			(void) strlcpy(buffer2, buffer, BUFSIZ);
12010Sstevel@tonic-gate 
12020Sstevel@tonic-gate 			/* get rid of trailing '\n' */
12030Sstevel@tonic-gate 			len = strlen(buffer2);
12040Sstevel@tonic-gate 			if (buffer2[len-1] == '\n') {
12050Sstevel@tonic-gate 				len--;
12060Sstevel@tonic-gate 			}
12070Sstevel@tonic-gate 			buffer2[len] = '\0';
12080Sstevel@tonic-gate 
12090Sstevel@tonic-gate 			if ((name = strtok(buffer2, SEP_COLON)) == NULL) {
12100Sstevel@tonic-gate 				rc = FAILURE;
12110Sstevel@tonic-gate 				break;
12120Sstevel@tonic-gate 			} else if (strcmp(puent->name, name) == 0) {
12130Sstevel@tonic-gate 				found = B_TRUE;
12140Sstevel@tonic-gate 			}
12150Sstevel@tonic-gate 		}
12160Sstevel@tonic-gate 
12170Sstevel@tonic-gate 		if (found) {
12180Sstevel@tonic-gate 			/*
12190Sstevel@tonic-gate 			 * This is the entry to be modified, get the updated
12200Sstevel@tonic-gate 			 * string.
12210Sstevel@tonic-gate 			 */
12220Sstevel@tonic-gate 			if ((str = uent2str(puent)) == NULL) {
12230Sstevel@tonic-gate 				rc = FAILURE;
12240Sstevel@tonic-gate 				break;
12250Sstevel@tonic-gate 			} else {
12260Sstevel@tonic-gate 				(void) strlcpy(buffer, str, BUFSIZ);
12270Sstevel@tonic-gate 				free(str);
12280Sstevel@tonic-gate 			}
12290Sstevel@tonic-gate 		}
12300Sstevel@tonic-gate 
12310Sstevel@tonic-gate 		if (fputs(buffer, pfile_tmp) == EOF) {
12320Sstevel@tonic-gate 			err = errno;
12330Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
12340Sstevel@tonic-gate 			    "failed to write to a temp file: %s."),
12350Sstevel@tonic-gate 			    strerror(err));
12360Sstevel@tonic-gate 			rc = FAILURE;
12370Sstevel@tonic-gate 			break;
12380Sstevel@tonic-gate 		}
12390Sstevel@tonic-gate 	}
12400Sstevel@tonic-gate 
12410Sstevel@tonic-gate 	if (rc == FAILURE) {
12420Sstevel@tonic-gate 		(void) fclose(pfile);
12430Sstevel@tonic-gate 		(void) fclose(pfile_tmp);
12440Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
12450Sstevel@tonic-gate 			err = errno;
12460Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
12470Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
12480Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
12490Sstevel@tonic-gate 		}
12500Sstevel@tonic-gate 		return (FAILURE);
12510Sstevel@tonic-gate 	}
12520Sstevel@tonic-gate 
12530Sstevel@tonic-gate 	(void) fclose(pfile);
12540Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
12550Sstevel@tonic-gate 		err = errno;
12560Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
12570Sstevel@tonic-gate 		    gettext("failed to close %s: %s"), tmpfile_name,
12580Sstevel@tonic-gate 		    strerror(err));
12590Sstevel@tonic-gate 		return (FAILURE);
12600Sstevel@tonic-gate 	}
12610Sstevel@tonic-gate 
12620Sstevel@tonic-gate 	/* Copy the temporary file to the pkcs11.conf file */
12630Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
12640Sstevel@tonic-gate 		err = errno;
12650Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
12660Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
12670Sstevel@tonic-gate 		    strerror(err));
12680Sstevel@tonic-gate 		cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
12690Sstevel@tonic-gate 		    _PATH_PKCS11_CONF, strerror(err));
12700Sstevel@tonic-gate 		rc = FAILURE;
12710Sstevel@tonic-gate 	} else if (chmod(_PATH_PKCS11_CONF,
12720Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
12730Sstevel@tonic-gate 		err = errno;
12740Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
12750Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
12760Sstevel@tonic-gate 		    strerror(err));
12770Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
12780Sstevel@tonic-gate 		    strerror(err));
12790Sstevel@tonic-gate 		rc = FAILURE;
12800Sstevel@tonic-gate 	} else {
12810Sstevel@tonic-gate 		rc = SUCCESS;
12820Sstevel@tonic-gate 	}
12830Sstevel@tonic-gate 
12840Sstevel@tonic-gate 	if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
12850Sstevel@tonic-gate 		err = errno;
12860Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
12870Sstevel@tonic-gate 		    "(Warning) failed to remove %s: %s"),
12880Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
12890Sstevel@tonic-gate 	}
12900Sstevel@tonic-gate 
12910Sstevel@tonic-gate 	return (rc);
12920Sstevel@tonic-gate }
12930Sstevel@tonic-gate 
12940Sstevel@tonic-gate 
12950Sstevel@tonic-gate /*
12960Sstevel@tonic-gate  * Convert an uentry to a character string
12970Sstevel@tonic-gate  */
12980Sstevel@tonic-gate static char *
uent2str(uentry_t * puent)12990Sstevel@tonic-gate uent2str(uentry_t *puent)
13000Sstevel@tonic-gate {
13010Sstevel@tonic-gate 	umechlist_t	*phead;
13020Sstevel@tonic-gate 	boolean_t tok1_present = B_FALSE;
13030Sstevel@tonic-gate 	char *buf;
13040Sstevel@tonic-gate 	char blank_buf[128];
13050Sstevel@tonic-gate 
13060Sstevel@tonic-gate 	if (puent == NULL) {
13070Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
13080Sstevel@tonic-gate 		return (NULL);
13090Sstevel@tonic-gate 	}
13100Sstevel@tonic-gate 
13110Sstevel@tonic-gate 	buf = malloc(BUFSIZ);
13120Sstevel@tonic-gate 	if (buf == NULL) {
13130Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("out of memory."));
13140Sstevel@tonic-gate 		return (NULL);
13150Sstevel@tonic-gate 	}
13160Sstevel@tonic-gate 
13170Sstevel@tonic-gate 	/* convert the library name */
13180Sstevel@tonic-gate 	if (strlcpy(buf, puent->name, BUFSIZ) >= BUFSIZ) {
13190Sstevel@tonic-gate 		free(buf);
13200Sstevel@tonic-gate 		return (NULL);
13210Sstevel@tonic-gate 	}
13220Sstevel@tonic-gate 
13230Sstevel@tonic-gate 
13240Sstevel@tonic-gate 	/* convert the enabledlist or the disabledlist */
13250Sstevel@tonic-gate 	if (puent->flag_enabledlist == B_TRUE) {
13260Sstevel@tonic-gate 		if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
13270Sstevel@tonic-gate 			free(buf);
13280Sstevel@tonic-gate 			return (NULL);
13290Sstevel@tonic-gate 		}
13300Sstevel@tonic-gate 
13310Sstevel@tonic-gate 		if (strlcat(buf, EF_ENABLED, BUFSIZ) >= BUFSIZ) {
13320Sstevel@tonic-gate 			free(buf);
13330Sstevel@tonic-gate 			return (NULL);
13340Sstevel@tonic-gate 		}
13350Sstevel@tonic-gate 
13360Sstevel@tonic-gate 		phead = puent->policylist;
13370Sstevel@tonic-gate 		while (phead != NULL) {
13380Sstevel@tonic-gate 			if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
13390Sstevel@tonic-gate 				free(buf);
13400Sstevel@tonic-gate 				return (NULL);
13410Sstevel@tonic-gate 			}
13420Sstevel@tonic-gate 
13430Sstevel@tonic-gate 			phead = phead->next;
13440Sstevel@tonic-gate 			if (phead != NULL) {
13450Sstevel@tonic-gate 				if (strlcat(buf, SEP_COMMA, BUFSIZ)
13460Sstevel@tonic-gate 				    >= BUFSIZ) {
13470Sstevel@tonic-gate 					free(buf);
13480Sstevel@tonic-gate 					return (NULL);
13490Sstevel@tonic-gate 				}
13500Sstevel@tonic-gate 			}
13510Sstevel@tonic-gate 		}
13520Sstevel@tonic-gate 		tok1_present = B_TRUE;
13530Sstevel@tonic-gate 	} else if (puent->policylist != NULL) {
13540Sstevel@tonic-gate 		if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
13550Sstevel@tonic-gate 			free(buf);
13560Sstevel@tonic-gate 			return (NULL);
13570Sstevel@tonic-gate 		}
13580Sstevel@tonic-gate 
13590Sstevel@tonic-gate 		if (strlcat(buf, EF_DISABLED, BUFSIZ) >= BUFSIZ) {
13600Sstevel@tonic-gate 			free(buf);
13610Sstevel@tonic-gate 			return (NULL);
13620Sstevel@tonic-gate 		}
13630Sstevel@tonic-gate 		phead = puent->policylist;
13640Sstevel@tonic-gate 		while (phead != NULL) {
13650Sstevel@tonic-gate 			if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
13660Sstevel@tonic-gate 				free(buf);
13670Sstevel@tonic-gate 				return (NULL);
13680Sstevel@tonic-gate 			}
13690Sstevel@tonic-gate 
13700Sstevel@tonic-gate 			phead = phead->next;
13710Sstevel@tonic-gate 			if (phead != NULL) {
13720Sstevel@tonic-gate 				if (strlcat(buf, SEP_COMMA, BUFSIZ)
13730Sstevel@tonic-gate 				    >= BUFSIZ) {
13740Sstevel@tonic-gate 					free(buf);
13750Sstevel@tonic-gate 					return (NULL);
13760Sstevel@tonic-gate 				}
13770Sstevel@tonic-gate 			}
13780Sstevel@tonic-gate 		}
13790Sstevel@tonic-gate 		tok1_present = B_TRUE;
13800Sstevel@tonic-gate 	}
13810Sstevel@tonic-gate 
13820Sstevel@tonic-gate 	if (puent->flag_norandom == B_TRUE) {
13830Sstevel@tonic-gate 		if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON),
13840Sstevel@tonic-gate 		    BUFSIZ) >= BUFSIZ) {
13850Sstevel@tonic-gate 			free(buf);
13860Sstevel@tonic-gate 			return (NULL);
13870Sstevel@tonic-gate 		}
13880Sstevel@tonic-gate 
13890Sstevel@tonic-gate 		if (strlcat(buf, EF_NORANDOM, BUFSIZ) >= BUFSIZ) {
13900Sstevel@tonic-gate 			free(buf);
13910Sstevel@tonic-gate 			return (NULL);
13920Sstevel@tonic-gate 		}
13930Sstevel@tonic-gate 	}
13940Sstevel@tonic-gate 
13950Sstevel@tonic-gate 	if (strcmp(puent->name, METASLOT_KEYWORD) == 0) {
13960Sstevel@tonic-gate 
13970Sstevel@tonic-gate 		/* write the metaslot_status= value */
13980Sstevel@tonic-gate 		if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON),
13990Sstevel@tonic-gate 		    BUFSIZ) >= BUFSIZ) {
14000Sstevel@tonic-gate 			free(buf);
14010Sstevel@tonic-gate 			return (NULL);
14020Sstevel@tonic-gate 		}
14030Sstevel@tonic-gate 
14040Sstevel@tonic-gate 		if (strlcat(buf, METASLOT_STATUS, BUFSIZ) >= BUFSIZ) {
14050Sstevel@tonic-gate 			free(buf);
14060Sstevel@tonic-gate 			return (NULL);
14070Sstevel@tonic-gate 		}
14080Sstevel@tonic-gate 
14090Sstevel@tonic-gate 		if (puent->flag_metaslot_enabled) {
141010500SHai-May.Chao@Sun.COM 			if (strlcat(buf, ENABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
14110Sstevel@tonic-gate 				free(buf);
14120Sstevel@tonic-gate 				return (NULL);
14130Sstevel@tonic-gate 			}
14140Sstevel@tonic-gate 		} else {
141510500SHai-May.Chao@Sun.COM 			if (strlcat(buf, DISABLED_KEYWORD, BUFSIZ)
14160Sstevel@tonic-gate 			    >= BUFSIZ) {
14170Sstevel@tonic-gate 				free(buf);
14180Sstevel@tonic-gate 				return (NULL);
14190Sstevel@tonic-gate 			}
14200Sstevel@tonic-gate 		}
14210Sstevel@tonic-gate 
14220Sstevel@tonic-gate 		if (!tok1_present) {
14230Sstevel@tonic-gate 			tok1_present = B_TRUE;
14240Sstevel@tonic-gate 		}
14250Sstevel@tonic-gate 
14260Sstevel@tonic-gate 		if (strlcat(buf, SEP_SEMICOLON, BUFSIZ) >= BUFSIZ) {
14270Sstevel@tonic-gate 			free(buf);
14280Sstevel@tonic-gate 			return (NULL);
14290Sstevel@tonic-gate 		}
14300Sstevel@tonic-gate 
14310Sstevel@tonic-gate 		if (strlcat(buf, METASLOT_AUTO_KEY_MIGRATE, BUFSIZ) >= BUFSIZ) {
14320Sstevel@tonic-gate 			free(buf);
14330Sstevel@tonic-gate 			return (NULL);
14340Sstevel@tonic-gate 		}
14350Sstevel@tonic-gate 
14360Sstevel@tonic-gate 		if (puent->flag_metaslot_auto_key_migrate) {
143710500SHai-May.Chao@Sun.COM 			if (strlcat(buf, ENABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
14380Sstevel@tonic-gate 				free(buf);
14390Sstevel@tonic-gate 				return (NULL);
14400Sstevel@tonic-gate 			}
14410Sstevel@tonic-gate 		} else {
144210500SHai-May.Chao@Sun.COM 			if (strlcat(buf, DISABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
14430Sstevel@tonic-gate 				free(buf);
14440Sstevel@tonic-gate 				return (NULL);
14450Sstevel@tonic-gate 			}
14460Sstevel@tonic-gate 		}
14470Sstevel@tonic-gate 
14480Sstevel@tonic-gate 		bzero(blank_buf, sizeof (blank_buf));
14490Sstevel@tonic-gate 
14500Sstevel@tonic-gate 		/* write metaslot_token= if specified */
14510Sstevel@tonic-gate 		if (memcmp(puent->metaslot_ks_token, blank_buf,
14520Sstevel@tonic-gate 		    TOKEN_LABEL_SIZE) != 0) {
14530Sstevel@tonic-gate 			/* write the metaslot_status= value */
14540Sstevel@tonic-gate 			if (strlcat(buf, (tok1_present ?
14550Sstevel@tonic-gate 			    SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) {
14560Sstevel@tonic-gate 				free(buf);
14570Sstevel@tonic-gate 				return (NULL);
14580Sstevel@tonic-gate 			}
14590Sstevel@tonic-gate 
14600Sstevel@tonic-gate 			if (strlcat(buf, METASLOT_TOKEN, BUFSIZ) >= BUFSIZ) {
14610Sstevel@tonic-gate 				free(buf);
14620Sstevel@tonic-gate 				return (NULL);
14630Sstevel@tonic-gate 			}
14640Sstevel@tonic-gate 
14650Sstevel@tonic-gate 			if (strlcat(buf,
14660Sstevel@tonic-gate 			    (const char *)puent->metaslot_ks_token, BUFSIZ)
14670Sstevel@tonic-gate 			    >= BUFSIZ) {
14680Sstevel@tonic-gate 				free(buf);
14690Sstevel@tonic-gate 				return (NULL);
14700Sstevel@tonic-gate 			}
14710Sstevel@tonic-gate 		}
14720Sstevel@tonic-gate 
14730Sstevel@tonic-gate 		/* write metaslot_slot= if specified */
14740Sstevel@tonic-gate 		if (memcmp(puent->metaslot_ks_slot, blank_buf,
14750Sstevel@tonic-gate 		    SLOT_DESCRIPTION_SIZE) != 0) {
14760Sstevel@tonic-gate 			/* write the metaslot_status= value */
14770Sstevel@tonic-gate 			if (strlcat(buf, (tok1_present ?
14780Sstevel@tonic-gate 			    SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) {
14790Sstevel@tonic-gate 				free(buf);
14800Sstevel@tonic-gate 				return (NULL);
14810Sstevel@tonic-gate 			}
14820Sstevel@tonic-gate 
14830Sstevel@tonic-gate 			if (strlcat(buf, METASLOT_SLOT, BUFSIZ) >= BUFSIZ) {
14840Sstevel@tonic-gate 				free(buf);
14850Sstevel@tonic-gate 				return (NULL);
14860Sstevel@tonic-gate 			}
14870Sstevel@tonic-gate 
14880Sstevel@tonic-gate 			if (strlcat(buf,
14890Sstevel@tonic-gate 			    (const char *)puent->metaslot_ks_slot, BUFSIZ)
14900Sstevel@tonic-gate 			    >= BUFSIZ) {
14910Sstevel@tonic-gate 				free(buf);
14920Sstevel@tonic-gate 				return (NULL);
14930Sstevel@tonic-gate 			}
14940Sstevel@tonic-gate 		}
14950Sstevel@tonic-gate 	}
14960Sstevel@tonic-gate 
14970Sstevel@tonic-gate 	if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) {
14980Sstevel@tonic-gate 		free(buf);
14990Sstevel@tonic-gate 		return (NULL);
15000Sstevel@tonic-gate 	}
15010Sstevel@tonic-gate 
15020Sstevel@tonic-gate 	return (buf);
15030Sstevel@tonic-gate }
15040Sstevel@tonic-gate 
15050Sstevel@tonic-gate 
15060Sstevel@tonic-gate /*
15070Sstevel@tonic-gate  * This function updates the default policy mode and the policy exception list
15080Sstevel@tonic-gate  * for a user-level provider based on the mechanism specified in the disable
15090Sstevel@tonic-gate  * or enable subcommand and the update mode.   This function is called by the
15100Sstevel@tonic-gate  * enable_uef_lib() or disable_uef_lib().
15110Sstevel@tonic-gate  */
15120Sstevel@tonic-gate int
update_policylist(uentry_t * puent,mechlist_t * marglist,int update_mode)15130Sstevel@tonic-gate update_policylist(uentry_t *puent, mechlist_t *marglist, int update_mode)
15140Sstevel@tonic-gate {
15150Sstevel@tonic-gate 	CK_MECHANISM_TYPE mech_type;
15160Sstevel@tonic-gate 	midstr_t	midname;
15170Sstevel@tonic-gate 	umechlist_t	*phead;
15180Sstevel@tonic-gate 	umechlist_t	*pcur;
15190Sstevel@tonic-gate 	umechlist_t	*pumech;
15200Sstevel@tonic-gate 	boolean_t	found;
15210Sstevel@tonic-gate 	int	rc = SUCCESS;
15220Sstevel@tonic-gate 
15230Sstevel@tonic-gate 	if ((puent == NULL) || (marglist == NULL)) {
15240Sstevel@tonic-gate 		/* should not happen */
15250Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
15260Sstevel@tonic-gate 		cryptodebug("update_policylist()- puent or marglist is NULL.");
15270Sstevel@tonic-gate 		return (FAILURE);
15280Sstevel@tonic-gate 	}
15290Sstevel@tonic-gate 
15300Sstevel@tonic-gate 	if ((update_mode != ADD_MODE) && (update_mode != DELETE_MODE)) {
15310Sstevel@tonic-gate 		/* should not happen */
15320Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
15330Sstevel@tonic-gate 		cryptodebug("update_policylist() - update_mode is incorrect.");
15340Sstevel@tonic-gate 		return (FAILURE);
15350Sstevel@tonic-gate 	}
15360Sstevel@tonic-gate 
15370Sstevel@tonic-gate 	/*
15380Sstevel@tonic-gate 	 * For each mechanism operand, get its mechanism type first.
15390Sstevel@tonic-gate 	 * If fails to get the mechanism type, the mechanism operand must be
15400Sstevel@tonic-gate 	 * invalid, gives an warning and ignore it. Otherwise,
15410Sstevel@tonic-gate 	 * - convert the mechanism type to the internal representation (hex)
15420Sstevel@tonic-gate 	 *   in the pkcs11.conf file
15430Sstevel@tonic-gate 	 * - If update_mode == DELETE_MODE,
15440Sstevel@tonic-gate 	 *	If the mechanism is in the policy list, delete it.
15450Sstevel@tonic-gate 	 *	If the mechanism is not in the policy list, do nothing.
15460Sstevel@tonic-gate 	 * - If update_mode == ADD_MODE,
15470Sstevel@tonic-gate 	 *	If the mechanism is not in the policy list, add it.
15480Sstevel@tonic-gate 	 *	If the mechanism is in the policy list already, do nothing.
15490Sstevel@tonic-gate 	 */
15500Sstevel@tonic-gate 	while (marglist) {
15510Sstevel@tonic-gate 		if (pkcs11_str2mech(marglist->name, &mech_type) != CKR_OK) {
15520Sstevel@tonic-gate 			/*
15530Sstevel@tonic-gate 			 * This mechanism is not a valid PKCS11 mechanism,
15540Sstevel@tonic-gate 			 * give warning and ignore it.
15550Sstevel@tonic-gate 			 */
15560Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
15570Sstevel@tonic-gate 			    "(Warning) %s is not a valid PKCS#11 mechanism."),
15580Sstevel@tonic-gate 			    marglist->name);
15590Sstevel@tonic-gate 			rc = FAILURE;
15600Sstevel@tonic-gate 		} else {
15610Sstevel@tonic-gate 			(void) snprintf(midname, sizeof (midname), "%#010x",
15620Sstevel@tonic-gate 			    (int)mech_type);
15630Sstevel@tonic-gate 			if (update_mode == DELETE_MODE) {
15640Sstevel@tonic-gate 				found = B_FALSE;
15650Sstevel@tonic-gate 				phead = pcur = puent->policylist;
15660Sstevel@tonic-gate 				while (!found && pcur) {
15670Sstevel@tonic-gate 					if (strcmp(pcur->name, midname) == 0) {
15680Sstevel@tonic-gate 						found = B_TRUE;
15690Sstevel@tonic-gate 					} else {
15700Sstevel@tonic-gate 						phead = pcur;
15710Sstevel@tonic-gate 						pcur = pcur->next;
15720Sstevel@tonic-gate 					}
15730Sstevel@tonic-gate 				}
15740Sstevel@tonic-gate 
15750Sstevel@tonic-gate 				if (found) {
15760Sstevel@tonic-gate 					if (phead == pcur) {
15770Sstevel@tonic-gate 						puent->policylist =
15780Sstevel@tonic-gate 						    puent->policylist->next;
15790Sstevel@tonic-gate 						free(pcur);
15800Sstevel@tonic-gate 					} else {
15810Sstevel@tonic-gate 						phead->next = pcur->next;
15820Sstevel@tonic-gate 						free(pcur);
15830Sstevel@tonic-gate 					}
15840Sstevel@tonic-gate 					puent->count--;
15850Sstevel@tonic-gate 					if (puent->count == 0) {
15860Sstevel@tonic-gate 						puent->policylist = NULL;
15870Sstevel@tonic-gate 					}
15880Sstevel@tonic-gate 				}
15890Sstevel@tonic-gate 			} else if (update_mode == ADD_MODE) {
15900Sstevel@tonic-gate 				if (!is_in_policylist(midname,
15910Sstevel@tonic-gate 				    puent->policylist)) {
15920Sstevel@tonic-gate 					pumech = create_umech(midname);
15930Sstevel@tonic-gate 					if (pumech == NULL) {
15940Sstevel@tonic-gate 						rc = FAILURE;
15950Sstevel@tonic-gate 						break;
15960Sstevel@tonic-gate 					}
15970Sstevel@tonic-gate 					phead = puent->policylist;
15980Sstevel@tonic-gate 					puent->policylist = pumech;
15990Sstevel@tonic-gate 					pumech->next = phead;
16000Sstevel@tonic-gate 					puent->count++;
16010Sstevel@tonic-gate 				}
16020Sstevel@tonic-gate 			}
16030Sstevel@tonic-gate 		}
16040Sstevel@tonic-gate 		marglist = marglist->next;
16050Sstevel@tonic-gate 	}
16060Sstevel@tonic-gate 
16070Sstevel@tonic-gate 	return (rc);
16080Sstevel@tonic-gate }
16090Sstevel@tonic-gate 
16100Sstevel@tonic-gate /*
16110Sstevel@tonic-gate  * Open a session to the given slot and check if we can do
16120Sstevel@tonic-gate  * random numbers by asking for one byte.
16130Sstevel@tonic-gate  */
16140Sstevel@tonic-gate static boolean_t
check_random(CK_SLOT_ID slot_id,CK_FUNCTION_LIST_PTR prov_funcs)16150Sstevel@tonic-gate check_random(CK_SLOT_ID slot_id, CK_FUNCTION_LIST_PTR prov_funcs)
16160Sstevel@tonic-gate {
16170Sstevel@tonic-gate 	CK_RV rv;
16180Sstevel@tonic-gate 	CK_SESSION_HANDLE hSession;
16190Sstevel@tonic-gate 	CK_BYTE test_byte;
16200Sstevel@tonic-gate 	CK_BYTE_PTR test_byte_ptr = &test_byte;
16210Sstevel@tonic-gate 
16220Sstevel@tonic-gate 	rv = prov_funcs->C_OpenSession(slot_id, CKF_SERIAL_SESSION,
16230Sstevel@tonic-gate 	    NULL_PTR, NULL, &hSession);
16240Sstevel@tonic-gate 	if (rv != CKR_OK)
16250Sstevel@tonic-gate 		return (B_FALSE);
16260Sstevel@tonic-gate 
16270Sstevel@tonic-gate 	/* We care only about the return value */
16280Sstevel@tonic-gate 	rv = prov_funcs->C_GenerateRandom(hSession, test_byte_ptr,
16290Sstevel@tonic-gate 	    sizeof (test_byte));
16300Sstevel@tonic-gate 	(void) prov_funcs->C_CloseSession(hSession);
16310Sstevel@tonic-gate 
16320Sstevel@tonic-gate 	/*
16330Sstevel@tonic-gate 	 * These checks are purely to determine whether the slot can do
16340Sstevel@tonic-gate 	 * random numbers. So, we don't check whether the routine
16350Sstevel@tonic-gate 	 * succeeds. The reason we check for CKR_RANDOM_NO_RNG also is that
16360Sstevel@tonic-gate 	 * this error effectively means CKR_FUNCTION_NOT_SUPPORTED.
16370Sstevel@tonic-gate 	 */
16380Sstevel@tonic-gate 	if (rv != CKR_FUNCTION_NOT_SUPPORTED && rv != CKR_RANDOM_NO_RNG)
16390Sstevel@tonic-gate 		return (B_TRUE);
16400Sstevel@tonic-gate 	else
16410Sstevel@tonic-gate 		return (B_FALSE);
16420Sstevel@tonic-gate }
16430Sstevel@tonic-gate 
16440Sstevel@tonic-gate void
display_verbose_mech_header()16450Sstevel@tonic-gate display_verbose_mech_header()
16460Sstevel@tonic-gate {
16470Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR1);
16480Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR2);
16490Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR3);
16500Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR4);
16510Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR5);
16520Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR6);
16530Sstevel@tonic-gate 	(void) printf("%-28.28s %s", gettext("mechanism name"), HDR7);
16540Sstevel@tonic-gate 	/*
16557334SDaniel.Anderson@Sun.COM 	 * TRANSLATION_NOTE
16560Sstevel@tonic-gate 	 * Strictly for appearance's sake, the first header line should be
16570Sstevel@tonic-gate 	 * as long as the length of the translated text above.  The format
16580Sstevel@tonic-gate 	 * lengths should all match too.
16590Sstevel@tonic-gate 	 */
16600Sstevel@tonic-gate 	(void) printf("%28s ---- ---- "
16610Sstevel@tonic-gate 	    "-  -  -  -  -  -  -  -  -  -  -  -  -  -\n",
16620Sstevel@tonic-gate 	    gettext("----------------------------"));
16630Sstevel@tonic-gate }
166410979SHai-May.Chao@Sun.COM 
166510979SHai-May.Chao@Sun.COM int
fips_update_pkcs11conf(int action)166610979SHai-May.Chao@Sun.COM fips_update_pkcs11conf(int action)
166710979SHai-May.Chao@Sun.COM {
166810979SHai-May.Chao@Sun.COM 
166910979SHai-May.Chao@Sun.COM 	char	*str;
167010979SHai-May.Chao@Sun.COM 
167110979SHai-May.Chao@Sun.COM 	if (action == FIPS140_ENABLE)
167210979SHai-May.Chao@Sun.COM 		str = "fips-140:fips_status=enabled\n";
167310979SHai-May.Chao@Sun.COM 	else
167410979SHai-May.Chao@Sun.COM 		str = "fips-140:fips_status=disabled\n";
167510979SHai-May.Chao@Sun.COM 
167610979SHai-May.Chao@Sun.COM 	if (update_conf(_PATH_PKCS11_CONF, str) != SUCCESS)
167710979SHai-May.Chao@Sun.COM 		return (FAILURE);
167810979SHai-May.Chao@Sun.COM 
167910979SHai-May.Chao@Sun.COM 	return (SUCCESS);
168010979SHai-May.Chao@Sun.COM }
168110979SHai-May.Chao@Sun.COM 
168210979SHai-May.Chao@Sun.COM void
fips_status_pkcs11conf(int * status)168310979SHai-May.Chao@Sun.COM fips_status_pkcs11conf(int *status)
168410979SHai-May.Chao@Sun.COM {
168510979SHai-May.Chao@Sun.COM 
168610979SHai-May.Chao@Sun.COM 	uentry_t *puent = NULL;
168710979SHai-May.Chao@Sun.COM 
168810979SHai-May.Chao@Sun.COM 	if ((puent = getent_uef(FIPS_KEYWORD)) == NULL) {
168910979SHai-May.Chao@Sun.COM 		/*
169010979SHai-May.Chao@Sun.COM 		 * By default (no fips-140 entry), we assume fips-140
169110979SHai-May.Chao@Sun.COM 		 * mode is disabled.
169210979SHai-May.Chao@Sun.COM 		 */
169310979SHai-May.Chao@Sun.COM 		*status = CRYPTO_FIPS_MODE_DISABLED;
169410979SHai-May.Chao@Sun.COM 		return;
169510979SHai-May.Chao@Sun.COM 	}
169610979SHai-May.Chao@Sun.COM 
169710979SHai-May.Chao@Sun.COM 	if (puent->flag_fips_enabled)
169810979SHai-May.Chao@Sun.COM 		*status = CRYPTO_FIPS_MODE_ENABLED;
169910979SHai-May.Chao@Sun.COM 	else
170010979SHai-May.Chao@Sun.COM 		*status = CRYPTO_FIPS_MODE_DISABLED;
170110979SHai-May.Chao@Sun.COM 
170210979SHai-May.Chao@Sun.COM 	return;
170310979SHai-May.Chao@Sun.COM 
170410979SHai-May.Chao@Sun.COM }
1705